Browse Source

Merge pull request 'dev-wahyu' (#70) from dev-wahyu into staging

Reviewed-on: ordo/adw-frontend#70
pull/2/head
ibnu 1 year ago
parent
commit
7eb062f1a6
  1. 57
      cypress/e2e/addProject.cy.js
  2. 9
      cypress/e2e/tests/gantt-duration-edit.cy.js
  3. 81
      src/containers/DefaultLayout/DefaultLayout.js
  4. 148
      src/views/SimproV2/CreatedProyek/ImportActivity/index.js

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();
});
});

9
cypress/e2e/tests/gantt-duration-edit.cy.js

@ -1,9 +0,0 @@
describe("Test a page", () => {
beforeEach(() => {
cy.visit("http://localhost:3000/#/login");
});
it("should visit the authenticated page", () => {
// Continue with your assertions or other test steps
});
});

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>

148
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,27 +175,33 @@ 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;
}
}
extractedRow[prop] = columnData extractedRow[prop] = columnData
@ -232,13 +238,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 +274,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 +335,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 +344,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 +362,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 +403,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 +412,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 +429,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}

Loading…
Cancel
Save