Browse Source

Merge pull request 'staging' (#46) from staging into master

Reviewed-on: ibnu/generic-ospro-frontend#46
pull/2/head
farhantock 8 months ago
parent
commit
b8bea6f50c
  1. 23
      src/containers/DefaultLayout/DefaultLayout.js
  2. 263
      src/views/Dashboard/DashboardProject.js

23
src/containers/DefaultLayout/DefaultLayout.js

@ -269,9 +269,9 @@ class DefaultLayout extends Component {
return (
<div className="app">
<AppHeader fixed>
{/* <AppHeader fixed>
<DefaultHeader />
</AppHeader>
</AppHeader> */}
<div className="app-body">
{!window.location.href.includes("dashboard-project") || renderSidebar ? (
<AppSidebar minimized={this.state.minimized} fixed display="lg">
@ -339,16 +339,17 @@ class DefaultLayout extends Component {
</Suspense>
</AppAside>
</div>
{!this.isKominfo ?
(
<AppFooter>
<Suspense fallback={this.loading()}>
<DefaultFooter />
</Suspense>
</AppFooter>
) : null
{
!this.isKominfo ?
(
<AppFooter>
<Suspense fallback={this.loading()}>
<DefaultFooter />
</Suspense>
</AppFooter>
) : null
}
</div>
</div >
);
}
}

263
src/views/Dashboard/DashboardProject.js

@ -30,12 +30,8 @@ import {
} from "./Components";
import { Fab, Action } from "react-tiny-fab";
import "react-tiny-fab/dist/styles.css";
import { useHistory, useParams } from "react-router-dom";
import { Icon } from '@iconify/react';
import arrowLeft from '@iconify/icons-ion/ios-arrow-back';
import { useHistory, useLocation, useParams } from "react-router-dom";
const { TextArea } = Input;
const styles = {
cardContainer: {
backgroundColor: "#F8F8F8",
@ -59,12 +55,10 @@ const styles = {
cardTitle: { color: "#444444", fontSize: 16, fontWeight: "bold" },
cardSubtitle: { color: "#888888", fontSize: 12 },
};
const center = {
lat: -6.2,
lng: 106.816666,
};
const DashboardProject = (props) => {
let role_id = 0, user_id = 0, isLogin = false, token = '', company_id = 0, all_project = null, role_name = '', hierarchy = [], user_name = '';
if (props && props.role_id && props.user_id) {
@ -86,8 +80,8 @@ const DashboardProject = (props) => {
},
};
const { PROJECT_ID, GANTT_ID, SCURVE } = useParams();
const URL_GANTT = `https://project-gantt.ospro.id/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1&role_name=${role_name}&company_id=${company_id}`;
// const URL_GANTT = `http://localhost:8444/generic-ospro-gantt/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1&role_name=${role_name}&company_id=${company_id}`;
// const URL_GANTT = `https://project-gantt.ospro.id/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1&role_name=${role_name}&company_id=${company_id}`;
const URL_GANTT = `http://localhost:8444/generic-ospro-gantt/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1&role_name=${role_name}&company_id=${company_id}`;
const mapRef = useRef();
const [projectName, setProjectName] = useState("");
const [projectManagerName, setProjectManagerName] = useState("");
@ -140,10 +134,7 @@ const DashboardProject = (props) => {
const [isReadyGanttParents, setIsReadyGanttParents] = useState(false);
const [calculationStatus, setCalculationStatus] = useState(false);
const [isHierarchy, setIsHierarchy] = useState(null);
const [dataOverdue, setDataOverdue] = useState(null);
const [projectType, setProjectType] = useState(null);
let history = useHistory();
useEffect(() => {
getProjectDetail();
getOverdueActivities();
@ -152,28 +143,22 @@ const DashboardProject = (props) => {
getGantt();
getGanttParents();
return () => {
console.log("unmount RenderMap");
};
}, []);
useEffect(() => {
if (isHierarchy != null) {
getSCurve();
}
window.addEventListener("message", handleIframeMessage);
window.addEventListener('message', handleGetOverdue);
return () => {
window.removeEventListener("message", handleIframeMessage);
window.removeEventListener("message", handleGetOverdue);
};
}, [isHierarchy]);
useEffect(() => {
if (activeTabIdx === 1) {
initMap();
}
}, [activeTabIdx]);
useEffect(() => {
async function fetchData() {
await Promise.all([
@ -184,34 +169,24 @@ const DashboardProject = (props) => {
}
fetchData();
}, []);
useEffect(() => {
let deviation = 0;
// Convert plannedCost and totalCost to numbers
const plannedCostNumber = parseFloat(plannedCost);
const totalCostNumber = parseFloat(totalCost);
// Check if conversion is successful
if (!isNaN(plannedCostNumber) && !isNaN(totalCostNumber)) {
deviation = plannedCostNumber - totalCostNumber;
if (plannedCost && totalCost) {
deviation = plannedCost - totalCost;
}
setRemToComplete(deviation.toString());
}, [plannedCost, totalCost]);
const handleRedirect = () => {
history.push("/projects/" + GANTT_ID + "/" + PROJECT_ID + "/gantt");
};
const getManpower = async () => {
const url = `${BASE_OSPRO}/api/project/manpower/${PROJECT_ID}`;
try {
const response = await axios.get(url, HEADER);
setManPower(response.data.totalRecord);
} catch (error) {
console.error("Failed to get manpower:", error);
}
};
const getGantt = async () => {
setIsReadyGantt(false);
const url = `${BASE_OSPRO}/api/version-gantt/edit/${GANTT_ID}`;
@ -225,11 +200,9 @@ const DashboardProject = (props) => {
}
setIsReadyGantt(true);
} catch (error) {
console.error("Failed to get gantt data:", error);
setIsReadyGantt(true);
}
};
const getGanttParents = async () => {
setIsReadyGanttParents(false);
const url = `${BASE_OSPRO}/api/hierarchy-ftths/tree-gantt/${GANTT_ID}`;
@ -238,11 +211,9 @@ const DashboardProject = (props) => {
setDataGanttParents(response);
setIsReadyGanttParents(true);
} catch (error) {
console.error("Failed to get gantt data:", error);
setIsReadyGanttParents(true);
}
};
const getAssignedHR = async () => {
const url = `${BASE_OSPRO}/api/project/manpower/assigned/${GANTT_ID}`;
try {
@ -256,10 +227,8 @@ const DashboardProject = (props) => {
setAssignedHrCount(assignedList.length);
setAssignedHr(assignedList);
} catch (error) {
console.error("Failed to get assigned HR:", error);
}
};
const getActualHR = async () => {
const dateStart = moment().startOf("day").toDate();
const dateEnd = moment().endOf("day").toDate();
@ -299,7 +268,6 @@ const DashboardProject = (props) => {
console.error("Failed to get actual HR:", error);
}
};
const getProjectDetail = async () => {
setIsReadyProjectDetail(false);
let URL = `${BASE_OSPRO}/api/project/detail/${PROJECT_ID}`;
@ -313,13 +281,11 @@ const DashboardProject = (props) => {
.get(URL, HEADER)
.then((res) => res)
.catch((err) => err.response);
console.log("getProjectDetail", result);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
setIsReadyProjectDetail(true);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get project detail failed, ${result.data.message}`,
@ -328,8 +294,6 @@ const DashboardProject = (props) => {
setIsReadyProjectDetail(true);
return;
} else if (result.status == 200 && result.data.data) {
console.log(result.data.data);
// setComments(result.data.data);
setProjectName(result.data.data.nama ? result.data.data.nama : "-");
setProjectManagerName(
result.data.data.projectManager ? result.data.data.projectManager : "-"
@ -357,7 +321,6 @@ const DashboardProject = (props) => {
? result.data.data.header?.planned_end
: null
);
setProjectType(result.data.data.type_proyek_id);
setActualStart(
result.data.data.header?.start_date
? result.data.data.header.start_date
@ -377,7 +340,6 @@ const DashboardProject = (props) => {
? result.data.data.calculation_status
: false
);
if (
result.data.data.kode_sortname &&
result.data.data.kode_sortname !== ""
@ -390,14 +352,12 @@ const DashboardProject = (props) => {
}
}
};
const getSCurve = async () => {
setIsReadySCurve(false);
let URL = `${BASE_OSPRO}/api/project/get-s-curve`;
if (SCURVE && SCURVE == "1" && isHierarchy) {
URL = `${BASE_OSPRO}/api/project/calculate-s-curve`;
}
const payload = {
project_id: PROJECT_ID.toString(),
gantt_id: GANTT_ID.toString(),
@ -413,7 +373,6 @@ const DashboardProject = (props) => {
setIsReadySCurve(true);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get S Curve failed, ${result.data.message}`,
@ -425,7 +384,6 @@ const DashboardProject = (props) => {
let selisihProgress = 0;
let planningProgress = 0;
let actualProgress = 0;
console.log("test flow ", result.data.data);
let statusHealthBySchedule = "on-schedule";
if (
result.data.data.length > 0 &&
@ -449,13 +407,21 @@ const DashboardProject = (props) => {
result.data.data[0].data.budget_control.cost_deviation?.toString()
);
}
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
) {
planningProgress = result.data.data[0].data?.percentagePlan[result.data.data[0].data?.percentagePlan.length - 1];
setPlanningProgress(Math.ceil(planningProgress));
planningProgress = result.data.data[0].data?.percentagePlan[n];
setPlanningProgress(planningProgress);
}
if (
result.data.data.length > 0 &&
@ -468,19 +434,16 @@ const DashboardProject = (props) => {
];
setActualProgress(actualProgress);
}
selisihProgress = planningProgress - actualProgress;
if (selisihProgress > 0 && selisihProgress <= 5) {
statusHealthBySchedule = "warning";
} else if (selisihProgress > 5) {
statusHealthBySchedule = "danger";
}
setHealthBySchedule(statusHealthBySchedule);
setIsReadySCurve(true);
}
};
const getOverdueActivities = async () => {
setIsReadyOverdueActivities(false);
const URL = `${BASE_OSPRO}/api/project/get-overdue-activities`;
@ -494,13 +457,11 @@ const DashboardProject = (props) => {
.post(URL, payload, HEADER)
.then((res) => res)
.catch((err) => err.response);
console.log("getOverdueActivities", result);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
setIsReadyOverdueActivities(true);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get Overdue Activities failed, ${result.data.message}`,
@ -516,7 +477,6 @@ const DashboardProject = (props) => {
setIsReadyOverdueActivities(true);
}
};
const getIntegrationInvoice = async (kode_sortname, id, gantt_id = null) => {
setIsReadyIntegrationInvoice(false);
const URL = `${BASE_OSPRO}/api/project/get-integration-invoice`;
@ -531,13 +491,11 @@ const DashboardProject = (props) => {
.post(URL, payload, HEADER)
.then((res) => res)
.catch((err) => err.response);
console.log("getIntegrationInvoice", result);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
setIsReadyIntegrationInvoice(true);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get integration invoice failed, ${result.data.message}`,
@ -562,7 +520,6 @@ const DashboardProject = (props) => {
setIsReadyIntegrationInvoice(true);
}
};
const getReportDistribution = async () => {
setIsReadyReportDistribution(false);
const URL = `${BASE_OSPRO}/api/project/get-report-distribution`;
@ -578,13 +535,11 @@ const DashboardProject = (props) => {
.post(URL, payload, HEADER)
.then((res) => res)
.catch((err) => err.response);
console.log("getReportDistribution", result);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
setIsReadyReportDistribution(true);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get report distribution failed, ${result.data.message}`,
@ -597,7 +552,6 @@ const DashboardProject = (props) => {
setIsReadyReportDistribution(true);
}
};
const getComments = async () => {
setIsReadyComments(false);
const URL = `${BASE_OSPRO}/api/project-comment/search`;
@ -626,18 +580,15 @@ const DashboardProject = (props) => {
orders: { columns: ["created_at"], ascending: false },
paging: { start: 0, length: -1 },
};
const result = await axios
.post(URL, payload, HEADER)
.then((res) => res)
.catch((err) => err.response);
console.log("getComments", result);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
setIsReadyComments(true);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Get comments failed, ${result.data.message}`,
@ -650,9 +601,7 @@ const DashboardProject = (props) => {
setIsReadyComments(true);
}
};
const handleSendComment = async () => {
// console.log('handleSendComment', comment);
setIsSendingComment(true);
if (comment === "") {
NotificationManager.error(
@ -673,13 +622,11 @@ const DashboardProject = (props) => {
.post(URL, payload, HEADER)
.then((res) => res)
.catch((err) => err.response);
if (!result) {
NotificationManager.error(`Could not connect to internet.`, "Failed");
setIsSendingComment(false);
return;
}
if (result.status !== 200) {
NotificationManager.error(
`Post comment failed, ${result.data.message}`,
@ -693,29 +640,21 @@ const DashboardProject = (props) => {
getComments();
}
};
const resetInputComment = () => {
setComment("");
setIsSendingComment(false);
};
const handleBack = async () => {
window.parent.location.reload();
};
const initMap = () => {
let mymap = L.map("map-area", {
center: center,
zoom: 13,
});
setMymap(mymap);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(mymap);
};
useEffect(() => {
if (mymap) {
if (reportDistribution.length > 0) {
@ -727,21 +666,17 @@ const DashboardProject = (props) => {
}
}
}, [mymap, reportDistribution]);
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, isHierarchy: isHierarchy },
@ -749,13 +684,6 @@ const DashboardProject = (props) => {
);
}
};
const handleGetOverdue = (event) => {
if (event.data.type === 'dataOverdueUpdate') {
setDataOverdue(event.data.dataOverdue);
}
}
const RenderGantt = useMemo(
() => (
<iframe
@ -772,7 +700,6 @@ const DashboardProject = (props) => {
),
[activeTabIdx]
);
const RenderComments = useMemo(() => {
return (
<>
@ -827,108 +754,61 @@ const DashboardProject = (props) => {
</>
);
}, [comment, comments, isSendingComment, isReadyComments]);
const RenderBehindTasks = useMemo(() => {
return SCURVE ?
(
<div>
{!isReadyOverdueActivities && <ListLoader />}
{isReadyOverdueActivities &&
overdueActivities &&
overdueActivities.length < 1 && (
<div
style={{
flex: 1,
textAlign: "center",
color: "#E80053",
marginTop: 50,
marginBottom: 50,
}}
>
No overdue activity found.
</div>
)}
{isReadyOverdueActivities &&
overdueActivities &&
overdueActivities.length > 0 &&
overdueActivities.map((item, idx) => {
let end_date;
let planned_end;
let diffDays = 0;
let message = "";
if (item.end_date && item.end_date !== null) {
end_date = moment(item.end_date);
planned_end = moment(item.planned_end);
diffDays = end_date.diff(planned_end, "days");
if (isNaN(diffDays)) {
return null;
return (
<div>
{!isReadyOverdueActivities && <ListLoader />}
{isReadyOverdueActivities &&
overdueActivities &&
overdueActivities.length < 1 && (
<div
style={{
flex: 1,
textAlign: "center",
color: "#E80053",
marginTop: 50,
marginBottom: 50,
}}
>
No overdue activity found.
</div>
)}
{isReadyOverdueActivities &&
overdueActivities &&
overdueActivities.length > 0 &&
overdueActivities.map((item, idx) => {
let end_date;
let planned_end;
let diffDays = 0;
let message = "";
if (item.end_date && item.end_date !== null) {
end_date = moment(item.end_date);
planned_end = moment(item.planned_end);
diffDays = end_date.diff(planned_end, "days");
if (isNaN(diffDays)) {
return null;
} else {
if (diffDays > 0) {
message = `Overdue by ${diffDays + 1} days`;
} else {
if (diffDays > 0) {
message = `Overdue by ${diffDays + 1} days`;
} else {
return null;
}
return null;
}
}
return (
<BehindTaskItem key={idx} name={item.name + ' - ' + item.name_version} message={message} scurve={SCURVE} proyek_id={PROJECT_ID} gantt_id={item.version_gantt_id} />
);
})}
</div>
)
:
(
<div>
{!dataOverdue && <ListLoader />}
{dataOverdue &&
dataOverdue.length < 1 && (
<div
style={{
flex: 1,
textAlign: "center",
color: "#E80053",
marginTop: 50,
marginBottom: 50,
}}
>
No overdue activity found.
</div>
)}
{dataOverdue &&
dataOverdue.length > 0 &&
dataOverdue.map((item, idx) => {
let message = `Overdue by ${item.overdue} days`;
return (
<BehindTaskItem key={idx} name={item.text} message={message} />
);
})}
</div>
);
}, [dataOverdue, isReadyOverdueActivities, overdueActivities]);
}
return (
<BehindTaskItem key={idx} name={item.name} message={message} />
);
})}
</div>
);
}, [overdueActivities, isReadyOverdueActivities]);
return (
<div style={{ marginLeft: -25, marginRight: -25 }}>
<NotificationContainer />
<Row>
<Col span={18}>
<Row>
{
!SCURVE ?
<Col span={2}>
<Button
style={{
height: "100%",
width: "100%",
fontSize: "18px"
}}
onClick={handleBack}
type="primary"
>
<Icon icon={arrowLeft} style={{ fontSize: "20px" }} /> Back
</Button>
</Col> : null
}
<Col span={!SCURVE ? 6 : 8}>
<Col span={8}>
<div
style={{
border: "solid",
@ -1096,7 +976,7 @@ const DashboardProject = (props) => {
</Col>
</Row>
<Row>
<Col span={SCURVE ? 8 : projectType != 9 ? 8 : 10}>
<Col span={SCURVE ? 8 : 10}>
<div
style={{
border: "solid",
@ -1221,7 +1101,7 @@ const DashboardProject = (props) => {
</div>
</div>
</Col>
{SCURVE || projectType != 9 ? (
{SCURVE ? (
<Col span={16}>
<div
style={{
@ -1360,17 +1240,15 @@ const DashboardProject = (props) => {
BCWP (cost vs perform)
</Col>
<Col span={5} style={{ fontSize: 11 }}>
{isReadySCurve ?
(
planningProgress > 100 || actualProgress > 100
?
renderFormatRupiah(((parseInt(plannedCost) * parseFloat((actualProgress / planningProgress) * 100).toFixed(0)) / 100).toString(), "Rp.")
:
renderFormatRupiah(((parseInt(plannedCost) * parseInt(actualProgress)) / 100).toString(), "Rp.")
)
: (
{isReadySCurve ? (
bcwp ? (
renderFormatRupiah(bcwp, "Rp.")
) : (
"-"
)}
)
) : (
<SingleTextLoader width={100} height={10} />
)}
</Col>
<Col
span={7}
@ -1778,5 +1656,4 @@ const DashboardProject = (props) => {
</div>
);
};
export default DashboardProject;
Loading…
Cancel
Save