Browse Source

update endpoint

pull/2/head
wahyuun 1 year ago
parent
commit
2bf31bf161
  1. 9
      cypress.config.js
  2. 57
      cypress/e2e/addProject.cy.js
  3. 5
      cypress/fixtures/example.json
  4. 33
      cypress/support/commands.js
  5. 20
      cypress/support/e2e.js
  6. 1
      package.json
  7. 6
      src/appredux/modules/map/actions.js
  8. 2
      src/components/RoutingBarV2/index.js
  9. 81
      src/containers/DefaultLayout/DefaultLayout.js
  10. 1
      src/routes.js
  11. 51
      src/views/Dashboard/DashboardCustomer.js
  12. 19
      src/views/Dashboard/DashboardProject.js
  13. 4
      src/views/Master/MasterBroadcast/index.js
  14. 3
      src/views/Report/k3/index.js
  15. 8
      src/views/SimproV2/CreatedProyek/AsignHrProject.js
  16. 2
      src/views/SimproV2/CreatedProyek/DialogFormProyek.js
  17. 16
      src/views/SimproV2/CreatedProyek/DialogGantt.js
  18. 1
      src/views/SimproV2/CreatedProyek/DialogHierarchy.js
  19. 32
      src/views/SimproV2/CreatedProyek/FormAsignHr.js
  20. 157
      src/views/SimproV2/CreatedProyek/ImportActivity/index.js
  21. 219
      src/views/SimproV2/CreatedProyek/index.js
  22. 49
      src/views/SimproV2/Gantt/GanttFrame.js
  23. 25
      src/views/SimproV2/Gantt/index.js
  24. 2
      src/views/SimproV2/PanicButton/index.js
  25. 2
      src/views/SimproV2/Presence/index.js
  26. 2
      src/views/SimproV2/ResourceWorker/DialogForm.js

9
cypress.config.js

@ -0,0 +1,9 @@
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});

57
cypress/e2e/addProject.cy.js

@ -0,0 +1,57 @@
describe("Test a page", () => {
beforeEach(() => {
cy.login("admin", "1nt3gr4s14");
cy.url({ timeout: 20000 }).should("include", "/dashboard");
cy.visit("http://localhost:3000/#/projects");
});
it("Add project normal case", () => {
cy.intercept('GET', 'http://localhost/adw-backend/api/currency/list').as('getCurrency');
cy.intercept('GET', 'http://localhost/adw-backend/api/project-type/list').as('getType');
cy.intercept('GET', 'http://localhost/adw-backend/api/divisi/list').as('getDivisi');
cy.intercept('GET', 'http://localhost/adw-backend/api/project-phase/list').as('getPhase');
cy.intercept('GET', 'http://localhost/adw-backend/api/human-resource/list').as('getHr');
cy.get('[style="background: rgb(76, 175, 80); color: rgb(255, 255, 255);"]').click();
cy.get(':nth-child(2) > :nth-child(1) > .form-group > .form-control').type('Automated Test');
cy.get(':nth-child(2) > :nth-child(2) > .form-group > .form-control').type('AT');
cy.wait("@getType").then((xhr) => {
cy.get('#rc_select_1').type('template detail{enter}');
});
cy.wait("@getHr").then((xhr) => {
cy.get('#rc_select_2').type('admin adw{enter}');
});
cy.get(':nth-child(2) > .form-group > .ant-picker > .ant-picker-input > input').click();
cy.contains('td[title="2023-08-04"].ant-picker-cell', '4').click();
cy.get(':nth-child(5) > :nth-child(1) > .form-group > .form-control').type('Indramayu');
cy.get(':nth-child(5) > :nth-child(2) > .form-group > .form-control').type('Integrasia Utama');
cy.wait("@getCurrency").then((xhr) => {
cy.get('.col-md-4 > .ant-select > .ant-select-selector').click();
cy.get('[title="USD"] > .ant-select-item-option-content').click();
cy.get('.col-md-8 > .form-control').type(20000);
});
cy.get(':nth-child(6) > :nth-child(2) > .form-group > .form-control').type('Implement Automated Testing For Development');
cy.wait("@getDivisi").then((xhr) => {
cy.get('#rc_select_4').click();
cy.get('[title=" Construction"] > .ant-select-item-option-content').click();
});
cy.wait("@getPhase").then((xhr) => {
cy.get('#rc_select_5').click();
cy.get('.ant-select-item-option-content').contains('Inisiasi').click();
});
cy.get('#rc_select_6').click();
cy.get('.ant-select-item-option-content').contains('On budget').click();
cy.get('.btn-primary').click();
});
});

5
cypress/fixtures/example.json

@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

33
cypress/support/commands.js

@ -0,0 +1,33 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Cypress.Commands.add("login", (username, password) => {
// Implement your login logic here
// For example:
cy.visit("http://localhost:3000/#/login"); // Assuming your login page is at "/login"
cy.get("#exampleName").type(username);
cy.get("#examplePassword").type(password);
cy.get(".px-4").click();
});

20
cypress/support/e2e.js

@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

1
package.json

@ -101,6 +101,7 @@
"@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",
"react-scripts": "^3.0.1", "react-scripts": "^3.0.1",
"webpack-sources": "1.0.1" "webpack-sources": "1.0.1"
}, },

6
src/appredux/modules/map/actions.js

@ -122,9 +122,9 @@ export const getUserPoints = async () => {
feature.properties = { feature.properties = {
"user_id": n.user_id, "user_id": n.user_id,
"Name": n.name ? n.name : '-', "Name": n.name ? n.name : '-',
"Clock in time": n.clock_in ? moment(n.clock_in).format('YYYY-MM-DD HH:mm:ss') : '-', "Clock in time": n.clock_in ? moment(n.clock_in).format('DD-MM-YYYY HH:mm:ss') : '-',
"Clock in location": n.clock_in_loc ? n.clock_in_loc : '-', "Clock in location": n.clock_in_loc ? n.clock_in_loc : '-',
"Clock out time": n.clock_out ? moment(n.clock_out).format('YYYY-MM-DD HH:mm:ss') : '-', "Clock out time": n.clock_out ? moment(n.clock_out).format('DD-MM-YYYY HH:mm:ss') : '-',
"Clock out location": n.clock_out_loc ? n.clock_out_loc : '-', "Clock out location": n.clock_out_loc ? n.clock_out_loc : '-',
"image": n.image_selfie ? n.image_selfie : '', "image": n.image_selfie ? n.image_selfie : '',
"Projects": n.projects ? n.projects : null, "Projects": n.projects ? n.projects : null,
@ -133,7 +133,7 @@ export const getUserPoints = async () => {
feature.geometry = { feature.geometry = {
"type": "Point", "type": "Point",
"coordinates": [n.clock_in_lng, n.clock_in_lat] "coordinates": [n.wp_lon, n.wp_lat]
} }
featureCollection.features.push(feature); featureCollection.features.push(feature);

2
src/components/RoutingBarV2/index.js

@ -57,7 +57,7 @@ const RoutingBar = () => {
<div className="routingbar-range-picker"> <div className="routingbar-range-picker">
<RangePicker <RangePicker
showTime={{ format: 'HH:mm' }} showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm" format="DD-MM-YYYY HH:mm"
placeholder={['Start Time', 'End Time']} placeholder={['Start Time', 'End Time']}
onChange={onChange} onChange={onChange}
onOk={onOk} onOk={onOk}

81
src/containers/DefaultLayout/DefaultLayout.js

@ -17,6 +17,7 @@ import {
AppBreadcrumb2 as AppBreadcrumb, AppBreadcrumb2 as AppBreadcrumb,
AppSidebarNav2 as AppSidebarNav, AppSidebarNav2 as AppSidebarNav,
} from '@coreui/react'; } from '@coreui/react';
import LayoutHelper from '../../../node_modules/@coreui/react/lib/Shared/layout/layout';
import navigation from '../../_nav'; import navigation from '../../_nav';
import routes from '../../routes'; import routes from '../../routes';
import { emptyConstants } from '../../const/MapConst.js'; import { emptyConstants } from '../../const/MapConst.js';
@ -44,6 +45,7 @@ class DefaultLayout extends Component {
routes2: routes, routes2: routes,
finalRoutes: [], finalRoutes: [],
breadrCrumbReady: false, breadrCrumbReady: false,
minimized: true
} }
} }
@ -70,7 +72,10 @@ class DefaultLayout extends Component {
} }
} }
toggleMinimized = () => {
this.setState((prevState) => ({ minimized: !prevState.minimized }));
LayoutHelper.sidebarToggle(!this.state.minimized);
};
setFinalRoutes = () => { setFinalRoutes = () => {
const { routes2 } = this.state; const { routes2 } = this.state;
@ -229,52 +234,54 @@ class DefaultLayout extends Component {
} }
render() { render() {
const { location } = this.props; const { location } = this.props;
const { pathname } = location; const { pathname } = location;
let renderSidebar = false let renderSidebar = false
if (pathname.includes("/dashboard-project")) { if (pathname.includes("/dashboard-project")) {
// Remove the base URL and hash // Remove the base URL and hash
const path = pathname.replace("/dashboard-project/", ""); const path = pathname.replace("/dashboard-project/", "");
// Split the remaining path by "/" // Split the remaining path by "/"
const parts = path.split("/"); const parts = path.split("/");
if (parts[2] == "1") { if (parts[2] == "1") {
renderSidebar = true renderSidebar = true
} }
} }
return ( return (
<div className="app"> <div className="app">
<div className="app-body"> <div className="app-body">
{!window.location.href.includes("dashboard-project") || renderSidebar ? ( {!window.location.href.includes("dashboard-project") || renderSidebar ? (
<AppSidebar minimized={true} fixed display="lg"> <AppSidebar minimized={this.state.minimized} fixed display="lg">
{/* <div class="sidebar-header"> {/* <div class="sidebar-header">
<Suspense fallback={this.loading()}> <Suspense fallback={this.loading()}>
<DefaultHeader history={this.props.history} onLogout={e => this.signOut(e)} /> <DefaultHeader history={this.props.history} onLogout={e => this.signOut(e)} />
</Suspense> </Suspense>
</div> */} </div> */}
<hr /> <hr />
<AppSidebarHeader /> <AppSidebarHeader />
<AppSidebarForm /> <AppSidebarForm />
<Suspense> <Suspense>
{this.getMenu()} {this.getMenu()}
</Suspense> </Suspense>
<AppSidebarFooter /> <AppSidebarFooter />
<UncontrolledDropdown direction="down"> {this.state.minimized ? null :
<DropdownToggle nav> <UncontrolledDropdown direction="down">
<i className="nav-icon fa fa-user-circle"></i> {localStorage.getItem('user_name')} <DropdownToggle nav>
</DropdownToggle> <i className="nav-icon fa fa-user-circle"></i> {localStorage.getItem('user_name')}
<DropdownMenu right> </DropdownToggle>
<DropdownItem color="primary" size="sm" onClick={() => handleChangeLng("id")}>ID</DropdownItem> <DropdownMenu right>
<DropdownItem color="success" size="sm" onClick={() => handleChangeLng("en")}>EN</DropdownItem> <DropdownItem color="primary" size="sm" onClick={() => handleChangeLng("id")}>ID</DropdownItem>
<DropdownItem href="#/settings"><i className="fa fa-user"></i>Profile</DropdownItem> <DropdownItem color="success" size="sm" onClick={() => handleChangeLng("en")}>EN</DropdownItem>
<DropdownItem onClick={e => this.signOut(e)}><i className="fa fa-sign-out"></i> Logout</DropdownItem> <DropdownItem href="#/settings"><i className="fa fa-user"></i>Profile</DropdownItem>
</DropdownMenu> <DropdownItem onClick={e => this.signOut(e)}><i className="fa fa-sign-out"></i> Logout</DropdownItem>
</UncontrolledDropdown> </DropdownMenu>
<AppSidebarMinimizer /> </UncontrolledDropdown>}
</AppSidebar> <button className='sidebar-minimizer mt-auto' type='button' onClick={this.toggleMinimized}>
) : null } </button>
</AppSidebar>
) : null}
<main className="main"> <main className="main">
{this.state.breadrCrumbReady ? this.getAppBreadcrumb() : null} {this.state.breadrCrumbReady ? this.getAppBreadcrumb() : null}
<Container fluid> <Container fluid>

1
src/routes.js

@ -54,6 +54,7 @@ const routes = [
// { path: '/dashboard', name: 'Dashboard', component: Dashboard}, // { path: '/dashboard', name: 'Dashboard', component: Dashboard},
{ path: '/dashboard', name: 'DashboardBOD', component: DashboardBOD }, { path: '/dashboard', name: 'DashboardBOD', component: DashboardBOD },
{ path: '/dashboard-customer/:PROJECT_ID/:GANTT_ID', name: 'DashboardCustomer', component: DashboardCustomer }, { path: '/dashboard-customer/:PROJECT_ID/:GANTT_ID', name: 'DashboardCustomer', component: DashboardCustomer },
{ path: '/dashboard-customer/:PROJECT_ID/:GANTT_ID/:SCURVE', name: 'DashboardCustomer', component: DashboardCustomer },
{ path: '/dashboard-project/:PROJECT_ID/:GANTT_ID', exact: true, name: 'Dashboard Project', component: DashboardProject }, { path: '/dashboard-project/:PROJECT_ID/:GANTT_ID', exact: true, name: 'Dashboard Project', component: DashboardProject },
{ path: '/dashboard-project/:PROJECT_ID/:GANTT_ID/:SCURVE', exact: true, name: 'Dashboard Project', component: DashboardProject }, { path: '/dashboard-project/:PROJECT_ID/:GANTT_ID/:SCURVE', exact: true, name: 'Dashboard Project', component: DashboardProject },
{ path: '/projects', exact: true, name: 'Projects', component: CreatedProyek }, { path: '/projects', exact: true, name: 'Projects', component: CreatedProyek },

51
src/views/Dashboard/DashboardCustomer.js

@ -33,7 +33,7 @@ const DashboardCustomer = () => {
Authorization: `Bearer ${token}` Authorization: `Bearer ${token}`
} }
} }
const { PROJECT_ID, GANTT_ID } = useParams(); const { PROJECT_ID, GANTT_ID, SCURVE } = useParams();
const URL_GANTT = `https://adw-gantt.ospro.id/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`; const URL_GANTT = `https://adw-gantt.ospro.id/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`;
const mapRef = useRef() const mapRef = useRef()
const [projectName, setProjectName] = useState(""); const [projectName, setProjectName] = useState("");
@ -61,6 +61,7 @@ const DashboardCustomer = () => {
const [healthBySchedule, setHealthBySchedule] = useState('-'); const [healthBySchedule, setHealthBySchedule] = useState('-');
const [healthByBudget, setHealthByBudget] = useState('-'); const [healthByBudget, setHealthByBudget] = useState('-');
const [reportDistribution, setReportDistribution] = useState([]); const [reportDistribution, setReportDistribution] = useState([]);
const [calculationStatus, setCalculationStatus] = useState(false);
useEffect(() => { useEffect(() => {
getProjectDetail(); getProjectDetail();
@ -79,6 +80,25 @@ const DashboardCustomer = () => {
} }
}, [activeTabIdx]); }, [activeTabIdx]);
useEffect(() => {
// Add event listener for receiving messages from the iframe
window.addEventListener('message', handleIframeMessage);
// Clean up the event listener on component unmount
return () => {
window.removeEventListener('message', handleIframeMessage);
};
}, []);
const handleIframeMessage = (event) => {
if (event.data && event.data.action === 'getUrl') {
const childUrl = window.location.href;
// Send the URL back to the iframe
event.source.postMessage({ action: 'sendUrl', url: childUrl }, event.origin);
}
};
const getProjectDetail = async () => { const getProjectDetail = async () => {
setIsReadyProjectDetail(false); setIsReadyProjectDetail(false);
const URL = `${BASE_OSPRO}/api/project/detail/${PROJECT_ID}`; const URL = `${BASE_OSPRO}/api/project/detail/${PROJECT_ID}`;
@ -106,12 +126,13 @@ const DashboardCustomer = () => {
setActualStart(result.data.data.header?.start_date ? result.data.data.header.start_date : null) setActualStart(result.data.data.header?.start_date ? result.data.data.header.start_date : null)
setEstimatedFinish(result.data.data.header?.end_date ? result.data.data.header.end_date : null) setEstimatedFinish(result.data.data.header?.end_date ? result.data.data.header.end_date : null)
setIsReadyProjectDetail(true); setIsReadyProjectDetail(true);
setCalculationStatus(result.data.data.calculation_status ? result.data.data.calculation_status : false)
} }
} }
const getSCurve = async () => { const getSCurve = async () => {
setIsReadySCurve(false); setIsReadySCurve(false);
const URL = `${BASE_OSPRO}/api/project/get-s-curve`; URL = `${BASE_OSPRO}/api/project/calculate-s-curve`;
const payload = { const payload = {
"project_id": PROJECT_ID.toString(), "project_id": PROJECT_ID.toString(),
"period": "week", "period": "week",
@ -139,6 +160,20 @@ const DashboardCustomer = () => {
let planningProgress = result.data.data[0].data?.percentagePlan[result.data.data[0].data?.percentagePlan.length-1]; let planningProgress = result.data.data[0].data?.percentagePlan[result.data.data[0].data?.percentagePlan.length-1];
setPlanningProgress(planningProgress); setPlanningProgress(planningProgress);
} }
let now = new Date().toISOString().slice(0, 10);
let dates = result.data.data[0].data?.date;
let n = dates.findIndex(element => new Date(now) < new Date(element[0]));
if (n < 0) {
n = dates.length - 1;
}
if (result.data.data.length > 0 && result.data.data[0].data?.percentagePlan && result.data.data[0].data?.percentagePlan.length > 0) {
if(SCURVE && SCURVE == "1"){
planningProgress = result.data.data[0].data?.percentagePlan[result.data.data[0].data?.percentagePlan.length - 1];
} else {
planningProgress = result.data.data[0].data?.percentagePlan[n];
}
setPlanningProgress(planningProgress);
}
if (result.data.data.length > 0 && result.data.data[0].data?.percentageReal && result.data.data[0].data?.percentageReal.length > 0) { if (result.data.data.length > 0 && result.data.data[0].data?.percentageReal && result.data.data[0].data?.percentageReal.length > 0) {
let actualProgress = result.data.data[0].data?.percentageReal[result.data.data[0].data?.percentageReal.length-1]; let actualProgress = result.data.data[0].data?.percentageReal[result.data.data[0].data?.percentageReal.length-1];
setActualProgress(actualProgress); setActualProgress(actualProgress);
@ -396,7 +431,13 @@ const DashboardCustomer = () => {
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> <div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}>
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> <div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}>
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Project</div> <div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Project</div>
<div style={{fontSize: 14}}>{isReadyProjectDetail ? projectName : <SingleTextLoader />}</div> <div style={{fontSize: 14}}>{isReadyProjectDetail
? projectName
? calculationStatus
? projectName + " - S-Curve Ready"
: projectName + " - S-Curve Loading"
: null
: <SingleTextLoader />}</div>
</div> </div>
<div> <div>
<i className="fa fa-check-square" style={{fontSize: 28}}></i> <i className="fa fa-check-square" style={{fontSize: 28}}></i>
@ -492,13 +533,13 @@ const DashboardCustomer = () => {
<div style={{backgroundColor: '#222222', padding: 10, marginBottom: 5}}> <div style={{backgroundColor: '#222222', padding: 10, marginBottom: 5}}>
<div style={{color: '#FFFFFF', textAlign: 'center', marginBottom: 10, fontWeight: 'bold'}}>Progress</div> <div style={{color: '#FFFFFF', textAlign: 'center', marginBottom: 10, fontWeight: 'bold'}}>Progress</div>
{isReadySCurve ? {isReadySCurve ?
<ProgressPlanningBar progress={planningProgress} /> <ProgressPlanningBar progress={planningProgress > 100 ? 100 : planningProgress} />
: :
<SingleTextLoader width={"100%"} height={30} /> <SingleTextLoader width={"100%"} height={30} />
} }
<div style={{marginTop: 10, marginBottom: 10}}></div> <div style={{marginTop: 10, marginBottom: 10}}></div>
{isReadySCurve ? {isReadySCurve ?
<ProgressActualBar progress={actualProgress} /> <ProgressActualBar progress={planningProgress > 100 ? parseFloat(actualProgress / planningProgress * 100).toFixed(2) : actualProgress} />
: :
<SingleTextLoader width={"100%"} height={30} /> <SingleTextLoader width={"100%"} height={30} />
} }

19
src/views/Dashboard/DashboardProject.js

@ -73,7 +73,7 @@ const DashboardProject = () => {
}, },
}; };
const { PROJECT_ID, GANTT_ID, SCURVE } = useParams(); const { PROJECT_ID, GANTT_ID, SCURVE } = useParams();
const URL_GANTT = `http://localhost:8444/adw-gantt/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`; const URL_GANTT = `https://adw-gantt.ospro.id/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`;
const mapRef = useRef(); const mapRef = useRef();
const [projectName, setProjectName] = useState(""); const [projectName, setProjectName] = useState("");
const [projectManagerName, setProjectManagerName] = useState(""); const [projectManagerName, setProjectManagerName] = useState("");
@ -125,6 +125,7 @@ const DashboardProject = () => {
const [dataGanttParents, setDataGanttParents] = useState({}); const [dataGanttParents, setDataGanttParents] = useState({});
const [isReadyGanttParents, setIsReadyGanttParents] = useState(false); const [isReadyGanttParents, setIsReadyGanttParents] = useState(false);
const [calculationStatus, setCalculationStatus] = useState(false); const [calculationStatus, setCalculationStatus] = useState(false);
const [isHierarchy, setIsHierarchy] = useState(false);
let history = useHistory(); let history = useHistory();
useEffect(() => { useEffect(() => {
@ -185,6 +186,9 @@ const DashboardProject = () => {
try { try {
const response = await axios.get(url, HEADER); const response = await axios.get(url, HEADER);
setDataGantt(response); setDataGantt(response);
if (response.data.data.hierarchy_ftth_id) {
setIsHierarchy(true);
}
setIsReadyGantt(true); setIsReadyGantt(true);
} catch (error) { } catch (error) {
console.error("Failed to get gantt data:", error); console.error("Failed to get gantt data:", error);
@ -331,7 +335,7 @@ const DashboardProject = () => {
const getSCurve = async () => { const getSCurve = async () => {
setIsReadySCurve(false); setIsReadySCurve(false);
let URL = `${BASE_OSPRO}/api/project/get-s-curve`; let URL = `${BASE_OSPRO}/api/project/get-s-curve`;
if (SCURVE && SCURVE == "1") { if (SCURVE && SCURVE == "1" && isHierarchy) {
URL = `${BASE_OSPRO}/api/project/calculate-s-curve`; URL = `${BASE_OSPRO}/api/project/calculate-s-curve`;
} }
@ -373,9 +377,7 @@ const DashboardProject = () => {
setActualToDate( setActualToDate(
result.data.data[0].data.budget_control.acwp?.toString() result.data.data[0].data.budget_control.acwp?.toString()
); );
setBcwp( setBcwp(result.data.data[0].data.budget_control.bcwp?.toString());
result.data.data[0].data.budget_control.current_budget?.toString()
);
// setRemToComplete(result.data.data[0].data.budget_control.rem_to_complete?.toString()) // setRemToComplete(result.data.data[0].data.budget_control.rem_to_complete?.toString())
setAddCostToComplete( setAddCostToComplete(
result.data.data[0].data.budget_control.add_cost_to_complete?.toString() result.data.data[0].data.budget_control.add_cost_to_complete?.toString()
@ -389,8 +391,9 @@ const DashboardProject = () => {
} }
let now = new Date().toISOString().slice(0, 10); let now = new Date().toISOString().slice(0, 10);
let dates = result.data.data[0].data?.date; let dates = result.data.data[0].data?.date;
let n = let n = dates.findIndex(
dates.findIndex((element) => new Date(now) < new Date(element[0])) - 1; (element) => new Date(now) < new Date(element[0])
);
if (n < 0) { if (n < 0) {
n = dates.length - 1; n = dates.length - 1;
} }
@ -438,6 +441,8 @@ const DashboardProject = () => {
const URL = `${BASE_OSPRO}/api/project/get-overdue-activities`; const URL = `${BASE_OSPRO}/api/project/get-overdue-activities`;
const payload = { const payload = {
id: PROJECT_ID.toString(), id: PROJECT_ID.toString(),
gantt: GANTT_ID.toString(),
scurve: SCURVE ? SCURVE.toString() : null,
till_date: moment(new Date()).format("YYYY-MM-DD"), till_date: moment(new Date()).format("YYYY-MM-DD"),
}; };
const result = await axios const result = await axios

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

@ -444,7 +444,7 @@ class index extends Component {
<td>{n.message_notif !== "" ? n.message_notif : "-"}</td> <td>{n.message_notif !== "" ? n.message_notif : "-"}</td>
<td>{n.description !== "" ? n.description : "-"}</td> <td>{n.description !== "" ? n.description : "-"}</td>
<td>{n.status_send !== "" ? n.status_send : "-"}</td> <td>{n.status_send !== "" ? n.status_send : "-"}</td>
<td>{n.created_date !== "" ? moment.utc(n.created_date).format("YYYY-MM-DD HH:mm:ss") : "-"}</td> <td>{n.created_date !== "" ? moment.utc(n.created_date).format("DD-MM-YYYY HH:mm:ss") : "-"}</td>
</tr> </tr>
) )
}) : <tr> }) : <tr>
@ -569,7 +569,7 @@ class index extends Component {
</Input> </Input>
</div> </div>
<div style={{}}> <div style={{}}>
<RangePicker size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker} />{' '} <RangePicker format={"DD-MM-YYYY"} size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker} />{' '}
<Button color="primary" onClick={() => this.getDataPanicButton()}>{this.props.t('search')}</Button> <Button color="primary" onClick={() => this.getDataPanicButton()}>{this.props.t('search')}</Button>
</div> </div>
</div> </div>

3
src/views/Report/k3/index.js

@ -103,6 +103,7 @@ class index extends Component {
getAllProyek = async () => { getAllProyek = async () => {
const payload = { const payload = {
"select": ["id", "nama"],
"paging": { "start": 0, "length": -1 }, "paging": { "start": 0, "length": -1 },
"columns": [ "columns": [
{ "name": "nama", "logic_operator": "ilike", "value": "", "operator": "AND" } { "name": "nama", "logic_operator": "ilike", "value": "", "operator": "AND" }
@ -572,7 +573,7 @@ class index extends Component {
</Input> </Input>
</div> </div>
<div style={{ width: "50%", marginTop: "3px" }}> <div style={{ width: "50%", marginTop: "3px" }}>
<RangePicker size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker} />{' '} <RangePicker format={"DD-MM-YYYY"} size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker} />{' '}
<Button color="primary" onClick={() => this.getDataLaporanK3()}>{this.props.t('search')}</Button> <Button color="primary" onClick={() => this.getDataLaporanK3()}>{this.props.t('search')}</Button>
</div> </div>
</div> </div>

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

@ -34,9 +34,11 @@ const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, toolsR
}, [openDialog]); }, [openDialog]);
useEffect(() => { useEffect(() => {
getDataUser(); if (openDialog) {
getDataProjectRole(); getDataProjectRole();
}, []) getDataUser();
}
}, [dataUserToProject])
const getDataAssignHr = async () => { const getDataAssignHr = async () => {
const payload = { const payload = {

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

@ -511,6 +511,7 @@ const DialogFormProyek = ({
Start Date<span style={{ color: "red" }}>*</span> Start Date<span style={{ color: "red" }}>*</span>
</Label> </Label>
<DatePicker <DatePicker
format={"DD-MM-YYYY"}
style={{ width: "100%" }} style={{ width: "100%" }}
value={startDate} value={startDate}
onChange={handleDatePickerStart} onChange={handleDatePickerStart}
@ -530,6 +531,7 @@ const DialogFormProyek = ({
.format("YYYY-MM-DD"); .format("YYYY-MM-DD");
return current && currentDate < customDate; return current && currentDate < customDate;
}} }}
format={"DD-MM-YYYY"}
style={{ width: "100%" }} style={{ width: "100%" }}
value={endDate} value={endDate}
onChange={handleDatePickerEnd} onChange={handleDatePickerEnd}

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

@ -13,7 +13,7 @@ import DialogUserGantt from './DialogUserGantt';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName, hierarchyId, hierarchyName }) => { const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName, hierarchyId, hierarchyName, openDialogHierarchy }) => {
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
headers: { headers: {
@ -31,21 +31,13 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
const [humanResource, setHumanResource] = useState([]) const [humanResource, setHumanResource] = useState([])
useEffect(() => { useEffect(() => {
if (idTask > 0) { if (openDialog && hierarchyId > 0 || idTask > 0 && !openDialogHierarchy) {
getdataGantt(); getdataGantt();
} }
if (hierarchyId > 0) {
getdataGantt();
}
}, [hierarchyId, idTask, openDialog])
useEffect(() => {
if (!openDialog) { if (!openDialog) {
setDataGantt([]); setDataGantt([]);
} else {
} }
}, [openDialog]) }, [hierarchyId, idTask, openDialog])
const getDataHumanResource = async () => { const getDataHumanResource = async () => {
const result = await axios const result = await axios
@ -77,12 +69,14 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName
let payload; let payload;
if (hierarchyId) { if (hierarchyId) {
payload = { payload = {
"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" }
] ]
} }
} else { } else {
payload = { payload = {
"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" }
] ]

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

@ -311,6 +311,7 @@ const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyek
hierarchyId={parentId} hierarchyId={parentId}
hierarchyName={parentName} hierarchyName={parentName}
idTask={idTask} idTask={idTask}
openDialogHierarchy={openDialog}
/> />
<DialogFormGantt <DialogFormGantt
idTask={idTask} idTask={idTask}

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

@ -22,6 +22,7 @@ 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)
@ -29,6 +30,7 @@ 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("")
@ -67,6 +69,7 @@ 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()) : '')
@ -91,6 +94,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,
max_used:maxUsed.replaceAll(".", ""), max_used:maxUsed.replaceAll(".", ""),
standart_rate:standartRate.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""),
uom_standart_rate:uomStandartRate, uom_standart_rate:uomStandartRate,
@ -104,6 +108,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,
max_used:maxUsed.replaceAll(".", ""), max_used:maxUsed.replaceAll(".", ""),
standart_rate:standartRate.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""),
uom_standart_rate:uomStandartRate, uom_standart_rate:uomStandartRate,
@ -157,6 +162,33 @@ 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>

157
src/views/SimproV2/CreatedProyek/ImportActivity/index.js

@ -2,9 +2,9 @@ import React, { useState, useEffect, useMemo } from 'react';
import axios from "../../../../const/interceptorApi" import axios from "../../../../const/interceptorApi"
import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap'; import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap';
import { NotificationContainer, NotificationManager } from 'react-notifications'; import { NotificationContainer, NotificationManager } from 'react-notifications';
import { Button, Table, Form, Upload, Tooltip, Alert, Spin } from 'antd'; import { Button, Table, Form, Upload, Tooltip, Alert, Spin } from 'antd';
import { InboxOutlined, UploadOutlined } from '@ant-design/icons'; import { InboxOutlined, UploadOutlined } from '@ant-design/icons';
import {OutTable, ExcelRenderer} from 'react-excel-renderer'; import { OutTable, ExcelRenderer } from 'react-excel-renderer';
import './table.css'; import './table.css';
import { BASE_OSPRO, ASSIGN_HR_PROJECT_SEARCH } from '../../../../const/ApiConst'; import { BASE_OSPRO, ASSIGN_HR_PROJECT_SEARCH } from '../../../../const/ApiConst';
import { Prompt } from 'react-router-dom'; import { Prompt } from 'react-router-dom';
@ -89,60 +89,60 @@ const ImportActivity = ({ params }) => {
const pageName = params.name; const pageName = params.name;
const [dataTable, setDatatable] = useState([]) const [dataTable, setDatatable] = useState([])
const [dataUserToProject, setdataUserToProject] = useState([]) const [dataUserToProject, setdataUserToProject] = useState([])
// //
const [isMovePage, setIsMovePage] = useState(false); const [isMovePage, setIsMovePage] = useState(false);
const [isPreview, setIsPreview] = useState(false); const [isPreview, setIsPreview] = useState(false);
useEffect(() => { useEffect(() => {
getDataAssignHr(); getDataAssignHr();
}, []) }, [])
const getDataAssignHr = async () => { const getDataAssignHr = async () => {
let url = window.location.href; let url = window.location.href;
let urlSplitted = url.split('/') let urlSplitted = url.split('/')
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": urlSplitted[6] } { "name": "proyek_id", "logic_operator": "=", "value": urlSplitted[6] }
], ],
"joins": [ "joins": [
{ "name": "m_users", "column_join": "user_id", "column_results": ["name", "ktp_number"] }, { "name": "m_users", "column_join": "user_id", "column_results": ["name", "ktp_number"] },
{ "name": "m_role_proyek", "column_join": "project_role", "column_results": ["name"] }, { "name": "m_role_proyek", "column_join": "project_role", "column_results": ["name"] },
], ],
"orders": { "orders": {
"columns": [ "columns": [
"id" "id"
], ],
"ascending": false "ascending": false
} }
} }
const URL = ASSIGN_HR_PROJECT_SEARCH const URL = ASSIGN_HR_PROJECT_SEARCH
const result = await axios const result = await axios
.post(URL, payload, HEADER) .post(URL, payload, HEADER)
.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) {
let dataRes = result.data.data || [] let dataRes = result.data.data || []
setdataUserToProject(dataRes); setdataUserToProject(dataRes);
} else { } else {
NotificationManager.error('Gagal Mengambil Data!!', 'Failed'); NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
} }
} }
const fileHandler = (file) => { const fileHandler = (file) => {
setIsMovePage(true); setIsMovePage(true);
if(file.name.slice(file.name.lastIndexOf('.')+1) === "xlsx"){ if (file.name.slice(file.name.lastIndexOf('.') + 1) === "xlsx") {
// NotificationManager.info('Loading...',' '); // NotificationManager.info('Loading...',' ');
setTimeout(() => { setTimeout(() => {
previewHandler(file); previewHandler(file);
setIsMovePage(false); setIsMovePage(false);
}, 5000); }, 5000);
} else { } else {
NotificationManager.error('file harus dalam format .xlsx', 'Failed'); NotificationManager.error('file harus dalam format .xlsx', 'Failed');
} }
@ -156,7 +156,7 @@ const ImportActivity = ({ params }) => {
let dataMapped = [] let dataMapped = []
ExcelRenderer(fileObj, (err, resp) => { ExcelRenderer(fileObj, (err, resp) => {
if(err){ if (err) {
console.log(err) console.log(err)
errorHandler() errorHandler()
} else { } else {
@ -167,7 +167,7 @@ const ImportActivity = ({ params }) => {
return el.length > 0; return el.length > 0;
}); });
for(let i = 5; i < rows.length; i++){ for (let i = 5; i < rows.length; i++) {
let extractedRow = {} let extractedRow = {}
for (var prop in columnToIndexs) { for (var prop in columnToIndexs) {
@ -175,28 +175,45 @@ const ImportActivity = ({ params }) => {
let columnData = rows[i][columnToIndexs[prop]] let columnData = rows[i][columnToIndexs[prop]]
// remove leading whitespace // remove leading whitespace
if(typeof(columnData) == 'string') { if (typeof (columnData) == 'string') {
columnData = columnData.trim().replace(/&nbsp;/g, '').replace(/<[^\/>][^>]*><\/[^>]+>/g, "") columnData = columnData.trim().replace(/&nbsp;/g, '').replace(/<[^\/>][^>]*><\/[^>]+>/g, "")
} }
if(["nik"].includes(prop)){ if (["nik"].includes(prop)) {
if(columnData){ if (columnData) {
let index = dataUserToProject.findIndex((x) => columnData == x.join_first_ktp_number); let index = dataUserToProject.findIndex((x) => columnData == x.join_first_ktp_number);
if(index >= 0) { if (index >= 0) {
columnData = dataUserToProject[index].join_first_ktp_number; columnData = dataUserToProject[index].join_first_ktp_number;
} else { } else {
columnData = ''; columnData = '';
} }
} }
} }
if(prop == 'weight'){ if (prop == 'weight') {
if (columnData == null) { if (columnData == null) {
columnData = 0; columnData = 0;
} }
columnData = columnData * 100 columnData = columnData * 100
} }
if (prop == 'duration') {
if (columnData == null) {
columnData = 0;
}
}
if (prop == 'level') {
if (columnData == null) {
columnData = 1;
}
}
if (prop == 'name') {
if (columnData == null) {
columnData = "New Activity";
}
}
extractedRow[prop] = columnData extractedRow[prop] = columnData
} }
@ -232,13 +249,13 @@ const ImportActivity = ({ params }) => {
console.log(result) console.log(result)
if (result.data.code == 200) { if (result.data.code == 200) {
const timestamp = Date.now(); const timestamp = Date.now();
const newTimestamp = timestamp + 60000; const newTimestamp = timestamp + 60000;
window.location = urlSplitted[0] + '//' + urlSplitted[2] + `/#/projects/` + ganttId + '/' + result.data.projectId + '/' + newTimestamp + '/gantt' window.location = urlSplitted[0] + '//' + urlSplitted[2] + `/#/projects/` + ganttId + '/' + result.data.projectId + '/' + newTimestamp + '/gantt'
} }
setIsMovePage(true); setIsMovePage(true);
setIsPreview(true); setIsPreview(true);
} }
const columns = [ const columns = [
@ -268,7 +285,7 @@ const ImportActivity = ({ params }) => {
key: 'name', key: 'name',
render: (text, record) => { render: (text, record) => {
let prepend = "" let prepend = ""
for(let i = 1; i < record.level; i++) { for (let i = 1; i < record.level; i++) {
prepend = prepend + "--" prepend = prepend + "--"
} }
@ -329,7 +346,7 @@ const ImportActivity = ({ params }) => {
listType="text" listType="text"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
maxCount={1} maxCount={1}
beforeUpload={(file)=> fileHandler(file)} beforeUpload={(file) => fileHandler(file)}
showUploadList={false} showUploadList={false}
> >
<Button icon={<UploadOutlined />}>Import Excel</Button> <Button icon={<UploadOutlined />}>Import Excel</Button>
@ -338,11 +355,11 @@ const ImportActivity = ({ params }) => {
</Form.Item> </Form.Item>
</Form> </Form>
</Col> </Col>
<Col span={2} style={{display: 'flex', justifyContent: 'flex-end'}}> <Col span={2} style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button <Button
style={{ marginLeft: "5px", marginRight: "10px" }} style={{ marginLeft: "5px", marginRight: "10px" }}
disabled={dataTable.length > 0 ? false : true} disabled={dataTable.length > 0 ? false : true}
onClick={(e)=> saveHandler(e)} onClick={(e) => saveHandler(e)}
> >
<i className="fa fa-save" style={{ marginRight: "5px" }}></i> Save <i className="fa fa-save" style={{ marginRight: "5px" }}></i> Save
</Button> </Button>
@ -356,7 +373,7 @@ const ImportActivity = ({ params }) => {
<CardBody> <CardBody>
<Spin tip="Loading..."> <Spin tip="Loading...">
<Table <Table
rowClassName={(record, index) => index % 2 == 0 ? 'table-row-light' : 'table-row-dark'} rowClassName={(record, index) => index % 2 == 0 ? 'table-row-light' : 'table-row-dark'}
dataSource={dataTable} dataSource={dataTable}
columns={columns} columns={columns}
pagination={false} pagination={false}
@ -397,7 +414,7 @@ const ImportActivity = ({ params }) => {
listType="text" listType="text"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
maxCount={1} maxCount={1}
beforeUpload={(file)=> fileHandler(file)} beforeUpload={(file) => fileHandler(file)}
showUploadList={false} showUploadList={false}
> >
<Button icon={<UploadOutlined />}>Import Excel</Button> <Button icon={<UploadOutlined />}>Import Excel</Button>
@ -406,11 +423,11 @@ const ImportActivity = ({ params }) => {
</Form.Item> </Form.Item>
</Form> </Form>
</Col> </Col>
<Col span={2} style={{display: 'flex', justifyContent: 'flex-end'}}> <Col span={2} style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button <Button
style={{ marginLeft: "5px", marginRight: "10px" }} style={{ marginLeft: "5px", marginRight: "10px" }}
disabled={dataTable.length > 0 ? false : true} disabled={dataTable.length > 0 ? false : true}
onClick={(e)=> saveHandler(e)} onClick={(e) => saveHandler(e)}
> >
<i className="fa fa-save" style={{ marginRight: "5px" }}></i> Save <i className="fa fa-save" style={{ marginRight: "5px" }}></i> Save
</Button> </Button>
@ -423,7 +440,7 @@ const ImportActivity = ({ params }) => {
</CardHeader> </CardHeader>
<CardBody> <CardBody>
<Table <Table
rowClassName={(record, index) => index % 2 == 0 ? 'table-row-light' : 'table-row-dark'} rowClassName={(record, index) => index % 2 == 0 ? 'table-row-light' : 'table-row-dark'}
dataSource={dataTable} dataSource={dataTable}
columns={columns} columns={columns}
pagination={false} pagination={false}

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

@ -19,7 +19,7 @@ import {
Tooltip, Tooltip,
Popover, Popover,
Skeleton, Skeleton,
Divider, Spin,
} from "antd"; } from "antd";
import { import {
PROJECT_APPROVAL_ADD, PROJECT_APPROVAL_ADD,
@ -136,6 +136,7 @@ const CreatedProyek = ({ params, ...props }) => {
const [dataVersionGantt, setDataVersionGantt] = useState([]); const [dataVersionGantt, setDataVersionGantt] = useState([]);
const [dataHierarchy, setDataHierarchy] = useState([]); const [dataHierarchy, setDataHierarchy] = useState([]);
const [dataDetail, setDataDetail] = useState(null); const [dataDetail, setDataDetail] = useState(null);
const [loading, setLoading] = useState(true);
const pageName = params.name; const pageName = params.name;
@ -167,7 +168,7 @@ const CreatedProyek = ({ params, ...props }) => {
}, [openDialogProyek]); }, [openDialogProyek]);
useEffect(() => { useEffect(() => {
getDataProyek(); role_id !== "44" ? getDataProyek() : getDataProyekByCustomer();
}, [search, rowsPerPage, currentPage]); }, [search, rowsPerPage, currentPage]);
useEffect(() => { useEffect(() => {
@ -230,6 +231,30 @@ const CreatedProyek = ({ params, ...props }) => {
} }
}; };
const handleDashboard = async (text) => {
const URL = `${BASE_OSPRO}/api/project/detail/${text.id}`;
const result = await axios
.get(URL, HEADER)
.then((res) => res)
.catch((err) => err.response);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get project detail failed, ${result.data.message}`,
"Failed"
);
return;
} else if (result.status == 200 && result.data.data) {
history.push(
`dashboard-customer/${text.id}/${result.data.gantt.last_gantt_id}/1`
);
}
};
const getDataProyek = async () => { const getDataProyek = async () => {
let start = 0; let start = 0;
@ -246,6 +271,80 @@ const CreatedProyek = ({ params, ...props }) => {
operator: "AND", operator: "AND",
}, },
], ],
select: [
"id",
"nama",
"rencana_biaya",
"type_proyek_id",
"currency_symbol",
"mulai_proyek",
"akhir_proyek",
],
joins: [
{
name: "m_users",
column_join: "pm_id",
column_results: ["name", "username"],
},
{
name: "m_type_proyek",
column_join: "type_proyek_id",
column_results: ["name", "description"],
},
// { "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 },
paging: { start: start, length: rowsPerPage },
};
if (parseInt(role_id) !== 1) {
payload["columns"] = [
{ name: "id", logic_operator: "=", value: proyek_id, operator: "AND" },
];
}
const result = await axios
.post(PROYEK_SEARCH, payload, HEADER)
.then((res) => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
let dataRes = result.data.data || [];
setDatatable(dataRes);
setTotalPage(result.data.totalRecord);
setLoading(false);
} else {
setLoading(false);
NotificationManager.error("Gagal Mengambil Data!!", "Failed");
}
};
const getDataProyekByCustomer = async () => {
let start = 0;
if (currentPage !== 1 && currentPage > 1) {
start = currentPage * rowsPerPage - rowsPerPage;
}
const payload = {
columns: [
{
name: "nama",
logic_operator: "ilike",
value: search,
operator: "AND",
},
],
select: [
"id",
"nama",
"rencana_biaya",
"type_proyek_id",
"currency_symbol",
"mulai_proyek",
"akhir_proyek",
],
joins: [ joins: [
{ {
name: "m_users", name: "m_users",
@ -257,11 +356,10 @@ const CreatedProyek = ({ params, ...props }) => {
column_join: "proyek_id", column_join: "proyek_id",
column_results: ["type_proyek_id"], column_results: ["type_proyek_id"],
}, },
// { "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"] }
], ],
user_id: { user_id: user_id },
orders: { columns: ["id"], ascending: false }, orders: { columns: ["id"], ascending: false },
paging: { start: start, length: rowsPerPage }, paging: { start: start, length: rowsPerPage },
user_id: { user_id: user_id }
}; };
if (parseInt(role_id) !== 1) { if (parseInt(role_id) !== 1) {
@ -277,12 +375,12 @@ const CreatedProyek = ({ params, ...props }) => {
if (result && result.data && result.data.code == 200) { if (result && result.data && result.data.code == 200) {
let dataRes = result.data.data || []; let dataRes = result.data.data || [];
// const filteredData = dataRes.filter(
// (item) => item.join_first_role_id === parseInt(role_id)
// );
setDatatable(dataRes); setDatatable(dataRes);
setTotalPage(result.data.totalRecord); setTotalPage(result.data.totalRecord);
setLoading(false);
} else { } else {
setLoading(false);
NotificationManager.error("Gagal Mengambil Data!!", "Failed"); NotificationManager.error("Gagal Mengambil Data!!", "Failed");
} }
}; };
@ -304,6 +402,7 @@ const CreatedProyek = ({ params, ...props }) => {
const getdataGantt = async (idTask) => { const getdataGantt = async (idTask) => {
setLoadVersionGantt(true); setLoadVersionGantt(true);
const payload = { const payload = {
select: ["id", "name_version"],
columns: [ columns: [
{ {
name: "proyek_id", name: "proyek_id",
@ -591,7 +690,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) {
getDataProyek(); role_id !== "44" ? getDataProyek() : getDataProyekByCustomer();
setIdDelete(0); setIdDelete(0);
setAlertDelete(false); setAlertDelete(false);
NotificationManager.success(`Data proyek berhasil dihapus`, "Success!!"); NotificationManager.success(`Data proyek berhasil dihapus`, "Success!!");
@ -637,7 +737,7 @@ const CreatedProyek = ({ params, ...props }) => {
NotificationManager.success(`${result.data.message}`, "Success!!"); NotificationManager.success(`${result.data.message}`, "Success!!");
} }
getDataProyek(); role_id !== "44" ? getDataProyek() : getDataProyekByCustomer();
} else { } else {
NotificationManager.error(`${result.data.message}`, "Failed!!"); NotificationManager.error(`${result.data.message}`, "Failed!!");
} }
@ -718,7 +818,7 @@ const CreatedProyek = ({ params, ...props }) => {
const resultMilestone = await editMilestone(data.id, milestones); const resultMilestone = await editMilestone(data.id, milestones);
const resultApproval = await editApproval(data.id, approval); const resultApproval = await editApproval(data.id, approval);
if (result && result.status === 200) { if (result && result.status === 200) {
getDataProyek(); role_id !== "44" ? getDataProyek() : getDataProyekByCustomer();
NotificationManager.success(`Data proyek berhasil Ubah`, "Success!!"); NotificationManager.success(`Data proyek berhasil Ubah`, "Success!!");
} else { } else {
NotificationManager.error(`${result.data.message}`, "Failed!!"); NotificationManager.error(`${result.data.message}`, "Failed!!");
@ -898,7 +998,7 @@ const CreatedProyek = ({ params, ...props }) => {
const data = resData.map((elt) => [ const data = resData.map((elt) => [
elt.nama, elt.nama,
`Rp. ${formatThousand(elt.rencana_biaya)}`, `Rp. ${formatThousand(elt.rencana_biaya)}`,
elt.nama_type_proyek, elt.join_second_name,
elt.join_first_name, elt.join_first_name,
`${moment(elt.mulai_proyek).format(format)} - ${moment( `${moment(elt.mulai_proyek).format(format)} - ${moment(
elt.akhir_proyek elt.akhir_proyek
@ -1112,41 +1212,55 @@ const CreatedProyek = ({ params, ...props }) => {
title: "Action", title: "Action",
dataIndex: "", dataIndex: "",
key: "x", key: "x",
render: (text, record) => ( render: (text, record) =>
<> role_id == "44" ? (
<Popover <>
placement="rightTop" <Tooltip title="Dashboard Project">
title={text.nama}
content={popupMenu(text, record)}
trigger="click"
>
<Button size="small" type="link" style={{ color: "green" }}>
<i className="fa fa-ellipsis-v"></i>
</Button>
</Popover>
<Popover
placement="rightTop"
title={text.nama}
content={popupMenuGantt(text, record)}
trigger="click"
>
{text.type_proyek_id == 9 ? (
<Button size="small" type="link" style={{ color: "green" }}>
<i className="fa fa-bars"></i>
</Button>
) : (
<Button <Button
onClick={() => getdataGantt(text.id)}
size="small" size="small"
onClick={() => handleDashboard(text)}
type="link" type="link"
style={{ color: "green" }} style={{ color: "green" }}
> >
<i className="fa fa-bars"></i> <i className="fa fa-line-chart"></i>
</Button> </Button>
)} </Tooltip>
</Popover> </>
</> ) : (
), <>
<Popover
placement="rightTop"
title={text.nama}
content={popupMenu(text, record)}
trigger="click"
>
<Button size="small" type="link" style={{ color: "green" }}>
<i className="fa fa-ellipsis-v"></i>
</Button>
</Popover>
<Popover
placement="rightTop"
title={text.nama}
content={popupMenuGantt(text, record)}
trigger="click"
>
{text.type_proyek_id == 9 ? (
<Button size="small" type="link" style={{ color: "green" }}>
<i className="fa fa-bars"></i>
</Button>
) : (
<Button
onClick={() => getdataGantt(text.id)}
size="small"
type="link"
style={{ color: "green" }}
>
<i className="fa fa-bars"></i>
</Button>
)}
</Popover>
</>
),
}, },
{ title: "Project Name", dataIndex: "nama", key: "nama" }, { title: "Project Name", dataIndex: "nama", key: "nama" },
{ {
@ -1165,7 +1279,7 @@ const CreatedProyek = ({ params, ...props }) => {
dataIndex: "color_progress", dataIndex: "color_progress",
key: "color_progress", key: "color_progress",
render: (text, record) => ( render: (text, record) => (
<>{record.nama_type_proyek ? record.nama_type_proyek : "-"}</> <>{record.join_second_name ? record.join_second_name : "-"}</>
), ),
}, },
{ {
@ -1436,14 +1550,16 @@ const CreatedProyek = ({ params, ...props }) => {
/> />
</Col> </Col>
<Col> <Col>
<Tooltip title="Add Project"> {role_id == "44" ? null : ( // role kustomer
<Button <Tooltip title="Add Project">
style={{ background: "#4caf50", color: "#fff" }} <Button
onClick={() => handleOpenDialogProyek(0)} style={{ background: "#4caf50", color: "#fff" }}
> onClick={() => handleOpenDialogProyek(0)}
<i className="fa fa-plus"></i> >
</Button> <i className="fa fa-plus"></i>
</Tooltip> </Button>
</Tooltip>
)}
<Tooltip title="Export Excel"> <Tooltip title="Export Excel">
<Popover <Popover
// content={<a onClick={hide}>Close</a>} // content={<a onClick={hide}>Close</a>}
@ -1486,7 +1602,10 @@ const CreatedProyek = ({ params, ...props }) => {
</Row> </Row>
</CardHeader> </CardHeader>
<CardBody> <CardBody>
{RenderTable} <Spin tip="Loading..." spinning={loading}>
{RenderTable}
</Spin>
<Pagination <Pagination
style={{ marginTop: "25px" }} style={{ marginTop: "25px" }}
showSizeChanger showSizeChanger

49
src/views/SimproV2/Gantt/GanttFrame.js

@ -0,0 +1,49 @@
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { BASE_SIMPRO_LUMEN } from '../../../const/ApiConst';
const GanttFrame = React.memo((props) => {
const history = useHistory();
const { versionGanttId, idProject, token, ro, timestamp } = props;
const iframeSrc = `https://adw-gantt.ospro.id/edit-mode/index.html?base_url=${BASE_SIMPRO_LUMEN}&gantt_id=${versionGanttId}&proyek_id=${idProject}&token=${token}&ro=${ro}&timestamp=${timestamp}`;
const [batchEntityData, setBatchEntityData] = useState(null);
useEffect(() => {
const handleMessage = (event) => {
if (event.data && event.data.batchEntity) {
setBatchEntityData(event.data.batchEntity);
}
};
window.addEventListener('message', handleMessage);
}, []);
useEffect(()=>{
const handleNavigation = (event) => {
if (batchEntityData && batchEntityData !== '') {
const message = 'You have unsaved changes. Are you sure you want to leave this page?';
return message;
}
};
history.block(handleNavigation);
}, [batchEntityData])
return (
<iframe
id="frame-gantt"
src={iframeSrc}
style={{
width: '100%',
height: '95vh',
}}
scrolling="no"
frameBorder="0"
allow="fullscreen"
></iframe>
);
});
export default GanttFrame;

25
src/views/SimproV2/Gantt/index.js

@ -10,7 +10,7 @@ import axios from "../../../const/interceptorApi";
import { Fab, Action } from "react-tiny-fab"; import { Fab, Action } from "react-tiny-fab";
import "react-tiny-fab/dist/styles.css"; import "react-tiny-fab/dist/styles.css";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import GanttFrame from "./GanttFrame";
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
const userId = parseInt(localStorage.getItem("user_id")); const userId = parseInt(localStorage.getItem("user_id"));
const HEADER = { const HEADER = {
@ -93,24 +93,19 @@ const Gantt = (props) => {
} }
roCount = roCount + 1; roCount = roCount + 1;
}; };
const RenderGantt = () => (
<iframe
id="frame-gantt"
src={`http://localhost:8444/adw-gantt/edit-mode/index.html?base_url=${BASE_SIMPRO_LUMEN}&gantt_id=${versionGanttId}&proyek_id=${idProject}&token=${token}&ro=${ro}&timestamp=${timestamp}`}
style={{
width: "100%",
height: "95vh",
}}
scrolling="no"
frameBorder="0"
allow="fullscreen"
></iframe>
);
return ( return (
<> <>
<div style={{ margin: "-15px", marginBottom: "-30px" }}> <div style={{ margin: "-15px", marginBottom: "-30px" }}>
{ready && <RenderGantt />} {ready && (
<GanttFrame
versionGanttId={versionGanttId}
idProject={idProject}
token={token}
ro={ro}
timestamp={timestamp}
/>
)}
</div> </div>
</> </>
); );

2
src/views/SimproV2/PanicButton/index.js

@ -364,7 +364,7 @@ class index extends Component {
</Input> </Input>
</div> </div>
<div style={{ width: "50%" }}> <div style={{ width: "50%" }}>
<RangePicker size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker} />{' '} <RangePicker format={"DD-MM-YYYY"} size="default" allowClear={false} value={[this.state.startDate, this.state.endDate]} onChange={this.handleDatePicker} />{' '}
<Button color="primary" onClick={() => this.getDataPanicButton()}>{this.props.t('search')}</Button> <Button color="primary" onClick={() => this.getDataPanicButton()}>{this.props.t('search')}</Button>
</div> </div>
</div> </div>

2
src/views/SimproV2/Presence/index.js

@ -316,7 +316,7 @@ const Index = ({ params }) => {
</Input> </Input>
</div> </div>
<div style={{ width: "50%", marginTop: "3px" }}> <div style={{ width: "50%", marginTop: "3px" }}>
<RangePicker size="default" allowClear={false} value={[startDate, endDate]} onChange={handleDatePicker} />{' '} <RangePicker format="DD-MM-YYYY" size="default" allowClear={false} value={[startDate, endDate]} onChange={handleDatePicker} />{' '}
<Button color="primary" onClick={() => getDataPresence()}>{t('search')}</Button> <Button color="primary" onClick={() => getDataPresence()}>{t('search')}</Button>
</div> </div>
</div> </div>

2
src/views/SimproV2/ResourceWorker/DialogForm.js

@ -270,7 +270,7 @@ const DialogForm = ({ openDialog, closeDialog, toggleDialog, typeDialog, dataEdi
<Col md={6}> <Col md={6}>
<FormGroup> <FormGroup>
<Label className="capitalize">{t('birthDate')}</Label> <Label className="capitalize">{t('birthDate')}</Label>
<DatePicker style={{ width: "100%" }} value={birthDate} placeholder={t('inputBrithDate')} onChange={(date, dateString) => setBirthDate(date)} /> <DatePicker format={"DD-MM-YYYY"} style={{ width: "100%" }} value={birthDate} placeholder={t('inputBrithDate')} onChange={(date, dateString) => setBirthDate(date)} />
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>

Loading…
Cancel
Save