diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 0000000..97f47c4 --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,9 @@ +const { defineConfig } = require("cypress"); + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/cypress/e2e/addProject.cy.js b/cypress/e2e/addProject.cy.js new file mode 100644 index 0000000..9580b08 --- /dev/null +++ b/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(); + }); +}); diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 0000000..02e4254 --- /dev/null +++ b/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" +} diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000..2b0aa47 --- /dev/null +++ b/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(); +}); \ No newline at end of file diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js new file mode 100644 index 0000000..0e7290a --- /dev/null +++ b/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') \ No newline at end of file diff --git a/package.json b/package.json index 3e8583b..f6e19ba 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "@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" }, diff --git a/src/appredux/modules/map/actions.js b/src/appredux/modules/map/actions.js index 442deb3..db12266 100644 --- a/src/appredux/modules/map/actions.js +++ b/src/appredux/modules/map/actions.js @@ -122,9 +122,9 @@ export const getUserPoints = async () => { feature.properties = { "user_id": n.user_id, "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 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 : '-', "image": n.image_selfie ? n.image_selfie : '', "Projects": n.projects ? n.projects : null, @@ -133,7 +133,7 @@ export const getUserPoints = async () => { feature.geometry = { "type": "Point", - "coordinates": [n.clock_in_lng, n.clock_in_lat] + "coordinates": [n.wp_lon, n.wp_lat] } featureCollection.features.push(feature); @@ -209,4 +209,4 @@ export const getUserHistory = async (userId, dateString) => { toast.warn("Couldn't find user history at the selected time. Please select another range of time."); } store.dispatch(setIsSearchingRoute(false)); -} \ No newline at end of file +} diff --git a/src/components/RoutingBarV2/index.js b/src/components/RoutingBarV2/index.js index f9c9d46..017e523 100644 --- a/src/components/RoutingBarV2/index.js +++ b/src/components/RoutingBarV2/index.js @@ -57,7 +57,7 @@ const RoutingBar = () => {
{
) } -export default RoutingBar; \ No newline at end of file +export default RoutingBar; diff --git a/src/containers/DefaultLayout/DefaultLayout.js b/src/containers/DefaultLayout/DefaultLayout.js index 0ef378c..2d53f98 100644 --- a/src/containers/DefaultLayout/DefaultLayout.js +++ b/src/containers/DefaultLayout/DefaultLayout.js @@ -17,6 +17,7 @@ import { AppBreadcrumb2 as AppBreadcrumb, AppSidebarNav2 as AppSidebarNav, } from '@coreui/react'; +import LayoutHelper from '../../../node_modules/@coreui/react/lib/Shared/layout/layout'; import navigation from '../../_nav'; import routes from '../../routes'; import { emptyConstants } from '../../const/MapConst.js'; @@ -44,6 +45,7 @@ class DefaultLayout extends Component { routes2: routes, finalRoutes: [], 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 = () => { const { routes2 } = this.state; @@ -229,52 +234,54 @@ class DefaultLayout extends Component { } render() { - const { location } = this.props; - const { pathname } = location; - let renderSidebar = false + const { location } = this.props; + const { pathname } = location; + let renderSidebar = false - if (pathname.includes("/dashboard-project")) { - // Remove the base URL and hash - const path = pathname.replace("/dashboard-project/", ""); + if (pathname.includes("/dashboard-project")) { + // Remove the base URL and hash + const path = pathname.replace("/dashboard-project/", ""); - // Split the remaining path by "/" - const parts = path.split("/"); - if (parts[2] == "1") { - renderSidebar = true - } - } + // Split the remaining path by "/" + const parts = path.split("/"); + if (parts[2] == "1") { + renderSidebar = true + } + } return (
- {!window.location.href.includes("dashboard-project") || renderSidebar ? ( - - {/* @@ -606,4 +607,4 @@ class index extends Component { ) } } -export default withTranslation()(index); \ No newline at end of file +export default withTranslation()(index); diff --git a/src/views/SimproV2/CreatedProyek/AsignHrProject.js b/src/views/SimproV2/CreatedProyek/AsignHrProject.js index e2ca043..4abb8a7 100644 --- a/src/views/SimproV2/CreatedProyek/AsignHrProject.js +++ b/src/views/SimproV2/CreatedProyek/AsignHrProject.js @@ -34,9 +34,11 @@ const AssignHrProject = ({ openDialog, closeDialog, toggleDialog, idTask, toolsR }, [openDialog]); useEffect(() => { - getDataUser(); - getDataProjectRole(); - }, []) + if (openDialog) { + getDataProjectRole(); + getDataUser(); + } + }, [dataUserToProject]) const getDataAssignHr = async () => { const payload = { diff --git a/src/views/SimproV2/CreatedProyek/DialogFormProyek.js b/src/views/SimproV2/CreatedProyek/DialogFormProyek.js index 5bab0e6..75ec4c7 100644 --- a/src/views/SimproV2/CreatedProyek/DialogFormProyek.js +++ b/src/views/SimproV2/CreatedProyek/DialogFormProyek.js @@ -511,6 +511,7 @@ const DialogFormProyek = ({ Start Date* { +const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName, hierarchyId, hierarchyName, openDialogHierarchy }) => { const token = localStorage.getItem("token") const HEADER = { headers: { @@ -31,21 +31,13 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName const [humanResource, setHumanResource] = useState([]) useEffect(() => { - if (idTask > 0) { + if (openDialog && hierarchyId > 0 || idTask > 0 && !openDialogHierarchy) { getdataGantt(); } - if (hierarchyId > 0) { - getdataGantt(); - } - }, [hierarchyId, idTask, openDialog]) - - useEffect(() => { if (!openDialog) { setDataGantt([]); - } else { - } - }, [openDialog]) + }, [hierarchyId, idTask, openDialog]) const getDataHumanResource = async () => { const result = await axios @@ -77,12 +69,14 @@ const DialogGantt = ({ openDialog, closeDialog, toggleDialog, idTask, proyekName let payload; if (hierarchyId) { payload = { + "select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"], "columns": [ { "name": "hierarchy_ftth_id", "logic_operator": "=", "value": hierarchyId, "operator": "AND" } ] } } else { payload = { + "select": ["id", "name_version", "calculation_type", "description", "created_at", "progress"], "columns": [ { "name": "proyek_id", "logic_operator": "=", "value": idTask, "operator": "AND" } ] diff --git a/src/views/SimproV2/CreatedProyek/DialogHierarchy.js b/src/views/SimproV2/CreatedProyek/DialogHierarchy.js index d62ce53..7c1f99a 100644 --- a/src/views/SimproV2/CreatedProyek/DialogHierarchy.js +++ b/src/views/SimproV2/CreatedProyek/DialogHierarchy.js @@ -311,6 +311,7 @@ const DialogHierarchy = ({ openDialog, closeDialog, toggleDialog, idTask, proyek hierarchyId={parentId} hierarchyName={parentName} idTask={idTask} + openDialogHierarchy={openDialog} /> { setUser(null) @@ -29,6 +30,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, setProjectRole(null) setGroupR("") setMaxUsed("") + setIsCustomer(false) setStandartRate("") setUomStandartRate(null) setOverTimeRate("") @@ -67,6 +69,7 @@ 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()) : '') @@ -91,6 +94,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, proyek_id: idTask, user_id:user, project_role:projectRole, + is_customer: isCustomer, max_used:maxUsed.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""), uom_standart_rate:uomStandartRate, @@ -104,6 +108,7 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, proyek_id: idTask, user_id:user, project_role:projectRole, + is_customer: isCustomer, max_used:maxUsed.replaceAll(".", ""), standart_rate:standartRate.replaceAll(".", ""), uom_standart_rate:uomStandartRate, @@ -157,6 +162,33 @@ const FormAsignHr = ({ openDialog, closeDialog, toggleDialog, idTask, dataEdit, + + + + +
+