+ {/*
*/}
+ {/* OS PRO */}
+ {this.getLogoImage()}
+ {/* adw w= 100, kit w = 100, nawakara w= 40 */}
+ {/* PROJECT */}
+
+ )
+ }
+
+ dropDownMenu = () => {
+ const { dataAlert, totalAlert } = this.state
+ let dataAlertLength = dataAlert.length
+ let currentLoop = 0;
+ return (
+
+
+ Notifications
+
+ {dataAlert.map((n, index) => {
+ currentLoop++;
+ if (currentLoop < 6) {
+ return (
+
+ {n.keterangan ? n.keterangan : n.join.alert_keterangan ? n.join.alert_keterangan : "-"}
+
+ )
+ }
+ })}
+ {totalAlert > 5 ?
+ <>
+
+
+ Lihat Selengkapnya
+ > : null}
+ {totalAlert === 0 ?
+ Tidak ada notifikasi untuk saat ini!
+ : null}
+
+ )
+ }
+
+ gotoReportAlert = () => {
+ this.props.history.replace('/laporan-alert')
+ }
+
+ onReadNotif = (visible) => {
+ if (!visible) {
+ const { dataAlert } = this.state
+ let currentLoop = 0;
+ let listId = []
+ dataAlert.map((val, index) => {
+ currentLoop++;
+ if (currentLoop < 6) {
+ listId.push(val.id);
+ }
+ });
+
+ this.setState({ listReadNotif: listId });
+ }
+ }
+
+ markAsRead = async () => {
+ console.log("markAsRead")
+ let data = this.state.listReadNotif
+ const payload = {
+ "status_view": true
+ }
+ let promises = []
+ let result = []
+ if (data.length > 0) {
+ if (parseInt(localStorage.getItem('role_id')) === 1) {
+ data.map((val, index) => {
+ let url = ALERT_STATUSVIEW(val)
+ promises.push(axios.put(url, payload, config)
+ .then(res => result.push(res)));
+ });
+
+ } else {
+ data.map((val, index) => {
+ let url = ALERTUSER_STATUSVIEW(val)
+ promises.push(axios.put(url, payload, config)
+ .then(res => result.push(res)))
+ });
+ }
+ await Promise.all(promises);
+ }
+ this.setState({ listReadNotif: [] }, () => {
+ // this.getDataAlert()
+ });
+ }
+
+ getHeaderMenu = () => {
+ const { fullname, u_group } = this.state;
+ if (u_group == 'kominfo') {
+ /*return (
+
+
+ Dashboard
+
+
+ Map
+
+
+ )*/
+
+ // return (
+ //
+ //
Layanan Telekomunikasi Q2 2020 di Wilayah Indonesia
+ //
Coverage Operator Cellular dan Data Site Q2 2020
+ //
+ // )
+
+ return (
+
+
Layanan Telekomunikasi
+
+ )
+ }
+ else {
+ return (
+
+ {/*
+ Dashboard
+ */}
+ {/*
+ Dashboard B2B
+
+
+ Dashboard B2C
+ */}
+ {/*
+ Users
+ */}
+ {/*
+ Map
+ */}
+
+ )
+ }
+ }
+
+ render() {
+
+ // eslint-disable-next-line
+ const { children, ...attributes } = this.props;
+
+ return (
+
+
+ {/* */}
+ {this.getLogo()}
+ {/* */}
+
+
+ {this.getHeaderMenu()}
+
+
+
+ this.onReadNotif(visible)} overlay={this.dropDownMenu} trigger={['click']}>
+
+ 0 ? "danger" : "default"}>{this.state.totalAlert > 0 ? this.state.totalAlert : null}
+
+
+ {/*
+
+
+
+
+ */}
+
+
+
+
+
+ {/*Account */}
+ {/* Updates42
+ Messages42
+ Tasks42
+ Comments42
+ Settings */}
+ {/* Profile */}
+ {/* Settings
+ Payments42
+ Projects42
+
+ Lock Account */}
+ {localStorage.getItem('user_name')}
+ this.props.onLogout(e)}> Logout
+
+
+
+ {/* */}
+ {/* */}
+
+ );
+ }
+}
+
+DefaultHeader.propTypes = propTypes;
+DefaultHeader.defaultProps = defaultProps;
+
+export default DefaultHeader;
diff --git a/src/containers/DefaultLayout/DefaultLayout.js b/src/containers/DefaultLayout/DefaultLayout.js
new file mode 100644
index 0000000..b4d20cd
--- /dev/null
+++ b/src/containers/DefaultLayout/DefaultLayout.js
@@ -0,0 +1,470 @@
+import React, { Component, Suspense } from 'react';
+import { Redirect, Route, Switch } from 'react-router-dom';
+import * as router from 'react-router-dom';
+import { Container } from 'reactstrap';
+import axios from 'axios';
+import { ALERTUSER_SEARCH, ALERT_SEARCH, MENU_SEARCH, ROLEMENU_SEARCH, ALERTUSER_STATUSVIEW, ALERT_STATUSVIEW, MENU_MANAGEMENT, CONTROL_MONITORING_SEARCH } from '../../const/ApiConst';
+
+import {
+ // CIcon,
+ AppAside,
+ AppFooter,
+ AppHeader,
+ AppSidebar,
+ AppSidebarFooter,
+ AppSidebarForm,
+ AppSidebarHeader,
+ AppSidebarMinimizer,
+ AppBreadcrumb2 as AppBreadcrumb,
+ AppSidebarNav2 as AppSidebarNav,
+} from '@coreui/react';
+// sidebar nav config
+import navigation from '../../_nav';
+// import navigation_kominfo from '../../_nav_kominfo';
+// routes config
+import routes from '../../routes';
+import { emptyConstants } from '../../const/MapConst.js';
+const countErr = localStorage.getItem('countErr');
+const token = window.localStorage.getItem('token');
+const DefaultAside = React.lazy(() => import('./DefaultAside'));
+const DefaultFooter = React.lazy(() => import('./DefaultFooter'));
+const DefaultHeader = React.lazy(() => import('./DefaultHeader'));
+let errorCount = 0;
+const config = {
+ headers:
+ {
+ Authorization: `Bearer ${token}`,
+ "Content-type": `application/json`
+ }
+};
+class DefaultLayout extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ role_id: localStorage.getItem('role_id'),
+ token: localStorage.getItem('token'),
+ menu: { items: [] },
+ routes2: routes,
+ finalRoutes: [],
+ breadrCrumbReady: false,
+ }
+ }
+
+ async componentDidMount() {
+ const menu = localStorage.getItem("menu_login")
+ if (menu) this.setMenu(JSON.parse(menu))
+ // this.getMenu();
+
+ // this.getDataMenu();
+ console.log("componentdidmount defaultLayout");
+ this.getAppBreadcrumb();
+ if(!localStorage.getItem("token")){
+ console.log("token kosong");
+ this.signOut();
+ }
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ const menu = localStorage.getItem("menu_login")
+ console.log(" token ", localStorage.getItem("token"))
+ const { pathname } = this.props.location;
+ if (this.state.token !== prevState.token) {
+ // this.getDataMenu()
+
+ this.setMenu(JSON.parse(menu))
+ }
+ if (this.state.role_id !== prevState.role_id) {
+ // this.getDataMenu()
+ this.setMenu(JSON.parse(menu))
+ }
+ if (this.state.menu !== prevState.menu) {
+ this.setFinalRoutes()
+ }
+ }
+
+
+
+ setFinalRoutes = () => {
+ const { routes2 } = this.state;
+ if (routes2) {
+ const newRouter2 = routes2;
+ // console.log("cek newRouter 2", newRouter2)
+ this.state.routes2.map((val, index) => {
+ let indexRes = this.state.menu.items.findIndex(x => x.url === val.path);
+ if (indexRes >= 0) {
+
+ let obj = newRouter2[index]
+
+ obj['name'] = this.state.menu.items[indexRes].name
+
+ newRouter2[index] = obj
+
+ }
+ })
+ this.setState({ finalRoutes: newRouter2 }, () => {
+ this.setState({ breadrCrumbReady: true })
+ });
+ }
+ }
+
+ loading = () =>
Loading...
+
+ async signOut(e) {
+ if (e) {
+ e.preventDefault()
+ }
+ // localStorage.removeItem("u_group");
+ await localStorage.removeItem("role_id");
+ await window.localStorage.clear();
+ // emptyConstants();
+ this.props.history.replace('/login')
+ }
+
+ getDataMenu = async () => {
+ errorCount++;
+
+ let url = MENU_MANAGEMENT(this.state.role_id)
+ const result = await axios
+ .get(url, config)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ // console.log(result)
+
+ if (result && result.data && result.data.code == 200) {
+ window.localStorage.setItem('countErr', 0);
+ let resData = result.data.data
+ // resData.sort((a,b) => (a.join.m_menu_sequence > b.join.m_menu_sequence) ? 1 : ((b.join.m_menu_sequence > a.join.m_menu_sequence) ? -1 : 0))
+ // console.log(resData)
+ // resData.sort(function (a, b) {
+ // return a.join.m_menu_sequence - b.join.m_menu_sequence;
+ // });
+ this.setMenu(resData)
+ } else {
+ if (errorCount < 4) {
+ this.getDataMenu();
+ } else {
+ if (countErr) {
+ await window.localStorage.setItem('countErr', countErr + 1);
+ } else {
+ await window.localStorage.setItem('countErr', 1);
+ }
+ if (countErr) {
+ if (parseInt(countErr) > 2) {
+ this.signOut();
+ } else {
+ window.location.reload();
+ }
+ } else {
+ window.location.reload();
+ }
+ }
+ // NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
+ }
+ }
+
+ parseMenuChild = (data) => {
+ const menu = data.map(res => {
+ const obj = {
+ name: res.name,
+ url: res.url,
+ icon: res.icon
+ }
+ if (res.children.length > 0) {
+ obj.children = this.parseMenuChild(res.children)
+ } else {
+ delete obj.children
+ }
+
+ return obj
+ })
+
+ return menu
+ }
+
+ setMenu = data => {
+
+
+ const menu = data.map(res => {
+
+ const obj = {
+ name: res.name,
+ url: res.url,
+ icon: res.icon
+ }
+ if (res.children.length > 0) {
+ obj.children = this.parseMenuChild(res.children)
+ } else {
+ delete obj.children
+ }
+
+ return obj
+ })
+ // console.log(menu)
+ // console.log('setMenu', data)
+ // const menu = data || [];
+ // const listMenu = []
+ // menu.map((val, index)=>{
+ // let row = {
+ // name:val.join.m_menu_name,
+ // url:val.join.m_menu_url,
+ // icon:val.join.m_menu_icon
+ // }
+ // listMenu.push(row)
+ // });
+
+ // console.log("menu list",listMenu)
+ // const listMenu = [
+ // {
+ // name: 'Dashboard',
+ // url: '/dashboard',
+ // icon: 'icon-speedometer',
+ // },
+ // {
+ // name: 'Initiating',
+ // url: '/base',
+ // icon: 'cil-home',
+ // children: [
+ // {
+ // name: 'Project Charter',
+ // url: '/project-charter',
+ // icon: 'cil-description',
+ // },
+ // {
+ // name: 'Human Resource',
+ // url: '/human-resource',
+ // icon: 'cil-people',
+ // },
+ // {
+ // name: 'Material Resource',
+ // url: '/material-resource',
+ // icon: 'fa fa-cube',
+ // }
+ // ],
+ // },
+ // {
+ // name: 'Planning',
+ // url: '/base',
+ // icon: 'cil-calendar',
+ // children: [
+ // {
+ // name: 'Gantt',
+ // url: '/gantt',
+ // icon: 'fa fa-list-ul',
+ // }
+ // ],
+ // },
+ // {
+ // name: 'Executing',
+ // url: '/base',
+ // icon: 'fa fa-check',
+ // children: [
+ // {
+ // name: 'Planning Harian',
+ // url: '/planning-harian',
+ // icon: 'fa fa-calendar-check-o',
+ // }
+ // ],
+ // },
+ // {
+ // name: 'Control Monitoring',
+ // url: '/control-monitoring',
+ // icon: 'cil-clock',
+ // children: [
+ // {
+ // name: 'Control Monitoring',
+ // url: '/control-monitoring',
+ // icon: 'cil-clock',
+ // },
+ // {
+ // name: 'Presensi Resource',
+ // url: '/presensi-resource',
+ // icon: 'fa fa-calendar-check-o',
+ // },
+ // {
+ // name: 'Absensi Resource',
+ // url: '/absensi-resource',
+ // icon: 'fa fa-calendar-times-o',
+ // },
+ // {
+ // name: 'Laporan K3',
+ // url: '/laporan-k3',
+ // icon: 'fa fa-plus-circle',
+ // },
+ // {
+ // name: 'Broadcast',
+ // url: '/broadcast',
+ // icon: 'cil-bullhorn',
+ // }
+ // ]
+ // },
+ // {
+ // name: 'Closing',
+ // url: '/closing',
+ // icon: 'fa fa-calendar-times-o'
+ // },
+ // {
+ // name: 'Setting Platform',
+ // url: '/base',
+ // icon: 'fa fa-cog',
+ // children: [
+ // {
+ // name: 'Menu',
+ // url: '/menu',
+ // icon: 'fa fa-list',
+ // },
+ // {
+ // name: 'Role',
+ // url: '/roles',
+ // icon: 'cil-people',
+ // },
+ // {
+ // name: 'Project Role',
+ // url: '/project-role',
+ // icon: 'fa fa-tags',
+ // },
+ // // {
+ // // name: 'Admin',
+ // // url: '/user-admin',
+ // // icon: 'icon-user',
+ // // },
+ // {
+ // name: 'Project Type',
+ // url: '/project-type',
+ // icon: 'fa fa-bookmark-o',
+ // },
+ // {
+ // name: 'Alert Notifikasi',
+ // url: '/config-alert',
+ // icon: 'fa fa-bell',
+ // }
+ // ],
+ // }
+ // ]
+ console.log("menu", menu)
+ this.setState({ menu: { items: menu } }, () => {
+ // this.checkLocation();
+ })
+
+ }
+
+ checkLocation = () => {
+ const { pathname } = this.props.location;
+ let getIndex = this.getIndexMenu(pathname);
+ if (getIndex < 0) {
+ this.props.history.push("/403");
+ }
+ }
+
+ getIndexMenu = (url) => {
+ let index = this.state.menu.items.findIndex(obj => obj.url === url);
+ return index
+ }
+
+ getMenu = () => {
+ const { u_group } = this.state;
+ if (u_group == 'kominfo') {
+ // return
+ }
+ else {
+ return
+ }
+ }
+
+ getAppBreadcrumb = () => {
+ const { u_group } = this.state;
+ if (u_group == 'kominfo') {
+ routes.map((route, idx) => {
+ if (route.path == '/dashboard-kominfo') {
+ return
+ }
+ else {
+ return
+ }
+ });
+ }
+ else {
+ return
+ }
+ }
+
+ isKominfo = () => {
+ let u_group = localStorage.getItem('u_group');
+ if (u_group == 'kominfo') {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ render() {
+ // const u_group = localStorage.getItem('u_group')
+ // if(u_group === null){
+ // return(
+ //
+ // )
+ // }
+ return (
+
+
+
+ this.signOut(e)} />
+
+
+
+
+
+
+
+
+ {this.getMenu()}
+
+
+
+
+
+ {this.state.breadrCrumbReady ? this.getAppBreadcrumb() : null}
+ {/**/}
+
+
+
+ {routes.map((route, idx) => {
+ return route.component ? (
+ (
+
+ )} />
+ ) : (null);
+ })}
+
+
+
+
+
+
+
+
+
+
+
+ {!this.isKominfo ?
+ (
+
+
+
+
+
+ ) : null
+ }
+
+ );
+ }
+}
+
+export default DefaultLayout;
diff --git a/src/containers/DefaultLayout/__tests__/DefaultAside.test.js b/src/containers/DefaultLayout/__tests__/DefaultAside.test.js
new file mode 100644
index 0000000..b017646
--- /dev/null
+++ b/src/containers/DefaultLayout/__tests__/DefaultAside.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import DefaultAside from '../DefaultAside';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/containers/DefaultLayout/__tests__/DefaultFooter.test.js b/src/containers/DefaultLayout/__tests__/DefaultFooter.test.js
new file mode 100644
index 0000000..4bbb3e8
--- /dev/null
+++ b/src/containers/DefaultLayout/__tests__/DefaultFooter.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import DefaultFooter from '../DefaultFooter';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/containers/DefaultLayout/__tests__/DefaultHeader.test.js b/src/containers/DefaultLayout/__tests__/DefaultHeader.test.js
new file mode 100644
index 0000000..d83e72f
--- /dev/null
+++ b/src/containers/DefaultLayout/__tests__/DefaultHeader.test.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { MemoryRouter } from 'react-router-dom';
+import DefaultHeader from '../DefaultHeader';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/containers/DefaultLayout/__tests__/DefaultLayout.test.js b/src/containers/DefaultLayout/__tests__/DefaultLayout.test.js
new file mode 100644
index 0000000..a2d5145
--- /dev/null
+++ b/src/containers/DefaultLayout/__tests__/DefaultLayout.test.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import {MemoryRouter, Route} from 'react-router-dom';
+import DefaultLayout from '../DefaultLayout';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/containers/DefaultLayout/index.js b/src/containers/DefaultLayout/index.js
new file mode 100644
index 0000000..2719acd
--- /dev/null
+++ b/src/containers/DefaultLayout/index.js
@@ -0,0 +1,3 @@
+import DefaultLayout from './DefaultLayout';
+
+export default DefaultLayout;
diff --git a/src/containers/DefaultLayout/package.json b/src/containers/DefaultLayout/package.json
new file mode 100644
index 0000000..b8cc824
--- /dev/null
+++ b/src/containers/DefaultLayout/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "DefaultLayout",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./DefaultLayout.js"
+}
diff --git a/src/containers/index.js b/src/containers/index.js
new file mode 100644
index 0000000..35f9b9d
--- /dev/null
+++ b/src/containers/index.js
@@ -0,0 +1,3 @@
+import DefaultLayout from './DefaultLayout';
+
+export { DefaultLayout };
diff --git a/src/dummy_data/paxel.geojson b/src/dummy_data/paxel.geojson
new file mode 100644
index 0000000..9140641
--- /dev/null
+++ b/src/dummy_data/paxel.geojson
@@ -0,0 +1,101 @@
+{
+ "type": "FeatureCollection",
+ "totalFeatures": "unknown",
+ "features": [
+ {
+ "type": "Feature",
+ "id": "paxel_area_code_20210426.5083",
+ "geometry": {
+ "type": "MultiPolygon",
+ "coordinates": [
+ [
+ [
+ [
+ 106.522270001261,
+ -6.66321000044036
+ ],
+ [
+ 106.536260000699,
+ -6.66382999935416
+ ],
+ [
+ 106.556582195013,
+ -6.68497003983464
+ ],
+ [
+ 106.541310000657,
+ -6.71486999865072
+ ],
+ [
+ 106.542630000375,
+ -6.74058999942815
+ ],
+ [
+ 106.550740756582,
+ -6.7473471734325
+ ],
+ [
+ 106.533284161136,
+ -6.75148465469226
+ ],
+ [
+ 106.524773753407,
+ -6.76232523192311
+ ],
+ [
+ 106.498398062322,
+ -6.75218427058684
+ ],
+ [
+ 106.46682763259,
+ -6.75104031405846
+ ],
+ [
+ 106.459021692598,
+ -6.73381922767441
+ ],
+ [
+ 106.481760000125,
+ -6.72494999944212
+ ],
+ [
+ 106.504030000085,
+ -6.70412999979885
+ ],
+ [
+ 106.51431934866,
+ -6.65951255475977
+ ],
+ [
+ 106.522270001261,
+ -6.66321000044036
+ ]
+ ]
+ ]
+ ]
+ },
+ "geometry_name": "the_geom",
+ "properties": {
+ "fid": 37287,
+ "desa": "MALASARI",
+ "provinsi": "JAWA BARAT",
+ "kabkot": "BOGOR",
+ "kecamatan": "NANGGUNG",
+ "post_code": null,
+ "city_code": "",
+ "ph_code": "",
+ "locker_cod": "",
+ "area_code": "",
+ "id": 37287,
+ "cluster_area_code": "",
+ "service_ty": null
+ }
+ }
+ ],
+ "crs": {
+ "type": "name",
+ "properties": {
+ "name": "urn:ogc:def:crs:EPSG::4326"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/dummy_data/route.json b/src/dummy_data/route.json
new file mode 100644
index 0000000..9bb8756
--- /dev/null
+++ b/src/dummy_data/route.json
@@ -0,0 +1,7 @@
+{
+ "routes": [
+ {
+ "geometry": "hldhx@lnau`BCG_EaC??cFjAwDjF??uBlKMd@}@z@??aC^yk@z_@se@b[wFdE??wFfE}NfIoGxB_I\\gG}@eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^aMyBiHOkFNoI`CcVvM??gG^gF_@iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_EkUFmq@hBiOqBgTwS??iYse@gYq\\cp@ce@{vA}s@csJqaE}{@iRaqE{lBeRoIwd@_T{]_Ngn@{PmhEwaA{SeF_u@kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs@sPua@_OkXaMeT_Nwk@ob@gV}TiYs[uTwXoNmT{Uyb@wNg]{Nqa@oDgNeJu_@_G}YsFw]kDuZyDmm@i_@uyIJe~@jCg|@nGiv@zUi_BfNqaAvIow@dEed@dCcf@r@qz@Egs@{Acu@mCum@yIey@gGig@cK_m@aSku@qRil@we@{mAeTej@}Tkz@cLgr@aHko@qOmcEaJw~C{w@kai@qBchBq@kmBS{kDnBscBnFu_Dbc@_~QHeU`IuyDrC_}@bByp@fCyoA?qMbD}{AIkeAgBk_A_A{UsDke@gFej@qH{o@qGgb@qH{`@mMgm@uQus@kL{_@yOmd@ymBgwE}x@ouBwtA__DuhEgaKuWct@gp@cnBii@mlBa_@}|Asj@qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAwXyn@ywMyOyqD{_@cfIcDe}@y@aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrXitAhT}x@bE}Z_@qW_Kwv@qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi@xBycBeCauBoF}}@qJioAww@gjHaPopA_NurAyJku@uGmi@cDs[eRaiBkQstAsQkcByNmaCsK_uBcJgbEw@gkB_@ypEqDoqSm@eZcDwjBoGw`BoMegBaU_`Ce_@_uBqb@ytBwkFqiT_fAqfEwe@mfCka@_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o~CfIewG|YibQxBssB?es@qGciA}RorAoVajA_nAodD{[y`AgPqp@mKwr@ms@umEaW{dAmb@umAw|@ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux@}_Dui@_eB_u@guCuyAuiHukA_lKszAu|OmaA{wKm}@clHs_A_rEahCssKo\\sgBsSglAqk@yvDcS_wAyTwpBmPc|BwZknFoFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq@m~Hym@c`EuiBudIabB{hF{pWifx@snAw`GkFyVqf@y~BkoAi}Lel@wtc@}`@oaXi_C}pZsi@eqGsSuqJ|Lqeb@e]kgPcaAu}SkDwzGhn@gjYh\\qlNZovJieBqja@ed@siO{[ol\\kCmjMe\\isHorCmec@uLebB}EqiBaCg}@m@qwHrT_vFps@kkI`uAszIrpHuzYxx@e{Crw@kpDhN{wBtQarDy@knFgP_yCu\\wyCwyA{kHo~@omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm@_bAumFo}DgqA_uByi@swC~AkzDlhA}xEvcBa}Cxk@ql@`rAo|@~bBq{@``Bye@djDww@z_C_cAtn@ye@nfC_eC|gGahH~s@w}@``Fi~FpnAooC|u@wlEaEedRlYkrPvKerBfYs}Arg@m}AtrCkzElw@gjBbh@woBhR{gCwGkgCc[wtCuOapAcFoh@uBy[yBgr@c@iq@o@wvEv@sp@`FajBfCaq@fIipAdy@ewJlUc`ExGuaBdEmbBpBssArAuqBBg}@s@g{AkB{bBif@_bYmC}r@kDgm@sPq_BuJ_s@{X_{AsK_d@eM{d@wVgx@oWcu@??aDmOkNia@wFoSmDyMyCkPiBePwAob@XcQ|@oNdCoSfFwXhEmOnLi\\lbAulB`X_d@|k@au@bc@oc@bqC}{BhwDgcD`l@ed@??bL{G|a@eTje@oS~]cLr~Bgh@|b@}Jv}EieAlv@sPluD{z@nzA_]`|KchCtd@sPvb@wSb{@ko@f`RooQ~e[upZbuIolI|gFafFzu@iq@nMmJ|OeJn^{Qjh@yQhc@uJ~j@iGdd@kAp~BkBxO{@|QsAfYgEtYiGd]}Jpd@wRhVoNzNeK`j@ce@vgK}cJnSoSzQkVvUm^rSgc@`Uql@xIq\\vIgg@~kDyq[nIir@jNoq@xNwc@fYik@tk@su@neB}uBhqEesFjoGeyHtCoD|D}Ed|@ctAbIuOzqB_}D~NgY`\\um@v[gm@v{Cw`G`w@o{AdjAwzBh{C}`Gpp@ypAxn@}mAfz@{bBbNia@??jIab@`CuOlC}YnAcV`@_^m@aeB}@yk@YuTuBg^uCkZiGk\\yGeY}Lu_@oOsZiTe[uWi[sl@mo@soAauAsrBgzBqgAglAyd@ig@asAcyAklA}qAwHkGi{@s~@goAmsAyDeEirB_{B}IsJuEeFymAssAkdAmhAyTcVkFeEoKiH}l@kp@wg@sj@ku@ey@uh@kj@}EsFmG}Jk^_r@_f@m~@ym@yjA??a@cFd@kBrCgDbAUnAcBhAyAdk@et@??kF}D??OL"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/dummy_data/route2.json b/src/dummy_data/route2.json
new file mode 100644
index 0000000..7d09827
--- /dev/null
+++ b/src/dummy_data/route2.json
@@ -0,0 +1,257 @@
+{
+ "geocoded_waypoints": [
+ {
+ "geocoder_status": "OK",
+ "place_id": "ChIJT2zELKHxaS4RR5fpIKhtekA",
+ "types": [
+ "street_address"
+ ]
+ },
+ {
+ "geocoder_status": "OK",
+ "place_id": "ChIJdbdzpG7xaS4RUCaaEC6NIOo",
+ "types": [
+ "street_address"
+ ]
+ }
+ ],
+ "routes": [
+ {
+ "bounds": {
+ "northeast": {
+ "lat": -6.245234399999999,
+ "lng": 106.8006477
+ },
+ "southwest": {
+ "lat": -6.2623544,
+ "lng": 106.7885345
+ }
+ },
+ "copyrights": "Map data ©2021",
+ "legs": [
+ {
+ "distance": {
+ "text": "3.0 km",
+ "value": 2992
+ },
+ "duration": {
+ "text": "9 mins",
+ "value": 552
+ },
+ "end_address": "Jl. Melawai 5 No.172, RT.3/RW.1, Melawai, Kec. Kby. Baru, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12160, Indonesia",
+ "end_location": {
+ "lat": -6.245234399999999,
+ "lng": 106.8006477
+ },
+ "start_address": "Jl. Bri Radio Dalam No.34/4, RT.2/RW.15, Gandaria Utara, Kec. Kby. Baru, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12140, Indonesia",
+ "start_location": {
+ "lat": -6.2623544,
+ "lng": 106.7885345
+ },
+ "steps": [
+ {
+ "distance": {
+ "text": "1.5 km",
+ "value": 1495
+ },
+ "duration": {
+ "text": "4 mins",
+ "value": 221
+ },
+ "end_location": {
+ "lat": -6.2493628,
+ "lng": 106.7918222
+ },
+ "html_instructions": "Head
north on
Jl. Radio Dalam Raya toward
Jl. Dwijaya Raya Pass by Alfamart Radio Dalam 4 (on the right)
",
+ "polyline": {
+ "points": "tbfe@icxjSOEs@M}@K}C]m@KUKg@G[EKAQCaAO_@GGAoB[SEaCa@e@Ga@GuB]yA[{Ba@iAYkA[a@KqAi@w@WaA[KCgAYQCMAw@I}AKUCeAOQCoAUMCoAQyAQc@EcBKe@C}@IC?g@E_AG"
+ },
+ "start_location": {
+ "lat": -6.2623544,
+ "lng": 106.7885345
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "0.5 km",
+ "value": 532
+ },
+ "duration": {
+ "text": "2 mins",
+ "value": 99
+ },
+ "end_location": {
+ "lat": -6.2491213,
+ "lng": 106.7959681
+ },
+ "html_instructions": "Turn
right onto
Jl. Kramat Pela ",
+ "maneuver": "turn-right",
+ "polyline": {
+ "points": "nqce@{wxjSMA\\sBJm@JOBQFa@h@cC@EN_@Le@Hc@?QBQBIDQ@Q@O?UASCSAMCGEGU]QSWWQUq@q@MGQEGAKA"
+ },
+ "start_location": {
+ "lat": -6.2493628,
+ "lng": 106.7918222
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "25 m",
+ "value": 25
+ },
+ "duration": {
+ "text": "1 min",
+ "value": 4
+ },
+ "end_location": {
+ "lat": -6.249124,
+ "lng": 106.7961904
+ },
+ "html_instructions": "Turn
right toward
Jl. Barito II ",
+ "maneuver": "turn-right",
+ "polyline": {
+ "points": "~oce@yqyjSAK@_@"
+ },
+ "start_location": {
+ "lat": -6.2491213,
+ "lng": 106.7959681
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "0.2 km",
+ "value": 154
+ },
+ "duration": {
+ "text": "1 min",
+ "value": 36
+ },
+ "end_location": {
+ "lat": -6.249612600000001,
+ "lng": 106.7974484
+ },
+ "html_instructions": "Turn
right onto
Jl. Barito II ",
+ "maneuver": "turn-right",
+ "polyline": {
+ "points": "~oce@esyjS`@_@P[JSJ]DM@KH}@Bu@"
+ },
+ "start_location": {
+ "lat": -6.249124,
+ "lng": 106.7961904
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "0.4 km",
+ "value": 414
+ },
+ "duration": {
+ "text": "1 min",
+ "value": 77
+ },
+ "end_location": {
+ "lat": -6.2459198,
+ "lng": 106.7979545
+ },
+ "html_instructions": "Turn
left onto
Jl. Panglima Polim (signs for
Senayan /
Semanggi )
Pass by ATM Bank UOB (on the left)
",
+ "maneuver": "turn-left",
+ "polyline": {
+ "points": "`sce@a{yjSmBMgDUyBQGAyDW[CgAIk@E"
+ },
+ "start_location": {
+ "lat": -6.249612600000001,
+ "lng": 106.7974484
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "0.2 km",
+ "value": 220
+ },
+ "duration": {
+ "text": "1 min",
+ "value": 48
+ },
+ "end_location": {
+ "lat": -6.245905899999999,
+ "lng": 106.7999397
+ },
+ "html_instructions": "Turn
right onto
Jl. Melawai Raya Pass by MM Juice Melawai (on the right)
",
+ "maneuver": "turn-right",
+ "polyline": {
+ "points": "~{be@e~yjS?SAq@?S?A?]Cg@AKD_F"
+ },
+ "start_location": {
+ "lat": -6.2459198,
+ "lng": 106.7979545
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "74 m",
+ "value": 74
+ },
+ "duration": {
+ "text": "1 min",
+ "value": 33
+ },
+ "end_location": {
+ "lat": -6.2452361,
+ "lng": 106.7999455
+ },
+ "html_instructions": "Turn
left after HAZEL Brew Coffee (on the right)",
+ "maneuver": "turn-left",
+ "polyline": {
+ "points": "|{be@sjzjSO?C?_@?qAA"
+ },
+ "start_location": {
+ "lat": -6.245905899999999,
+ "lng": 106.7999397
+ },
+ "travel_mode": "DRIVING"
+ },
+ {
+ "distance": {
+ "text": "78 m",
+ "value": 78
+ },
+ "duration": {
+ "text": "1 min",
+ "value": 34
+ },
+ "end_location": {
+ "lat": -6.245234399999999,
+ "lng": 106.8006477
+ },
+ "html_instructions": "Turn
right onto
Jl. Melawai 9 Destination will be on the left
",
+ "maneuver": "turn-right",
+ "polyline": {
+ "points": "vwbe@ujzjSAkC"
+ },
+ "start_location": {
+ "lat": -6.2452361,
+ "lng": 106.7999455
+ },
+ "travel_mode": "DRIVING"
+ }
+ ],
+ "traffic_speed_entry": [],
+ "via_waypoint": []
+ }
+ ],
+ "overview_polyline": {
+ "points": "tbfe@icxjScAS{Ei@m@KUKcAM_C]mGeAgAOoEy@eE{@mBg@iCaAmA_@yA]eAKsBOwAS}AYiDc@kF_@yBOh@aDJOBQFa@h@cCPe@ViABc@H[Ba@Ai@Ea@IOg@q@i@m@q@q@MGYGKAAK@_@`@_@\\o@Pk@JiABu@mBMaHg@eHg@k@E?SAeAEsAD_FO?c@?qAAAkC"
+ },
+ "summary": "Jl. Radio Dalam Raya",
+ "warnings": [],
+ "waypoint_order": []
+ }
+ ],
+ "status": "OK"
+}
\ No newline at end of file
diff --git a/src/dummy_data/route3.geojson b/src/dummy_data/route3.geojson
new file mode 100644
index 0000000..9304824
--- /dev/null
+++ b/src/dummy_data/route3.geojson
@@ -0,0 +1,259 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "id": "sales.1",
+ "geometry_name": "the_geom",
+ "type": "Feature",
+ "properties": {
+ "id": "sales.1",
+ "name": "Sales 1"
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ 106.78853,
+ -6.26235
+ ],
+ [
+ 106.78863,
+ -6.26201
+ ],
+ [
+ 106.78884,
+ -6.26091
+ ],
+ [
+ 106.7889,
+ -6.26068
+ ],
+ [
+ 106.78896,
+ -6.26057
+ ],
+ [
+ 106.78903,
+ -6.26023
+ ],
+ [
+ 106.78918,
+ -6.25959
+ ],
+ [
+ 106.78953,
+ -6.25824
+ ],
+ [
+ 106.78961,
+ -6.25788
+ ],
+ [
+ 106.7899,
+ -6.25684
+ ],
+ [
+ 106.7902,
+ -6.25585
+ ],
+ [
+ 106.7904,
+ -6.2553
+ ],
+ [
+ 106.79073,
+ -6.25461
+ ],
+ [
+ 106.79089,
+ -6.25422
+ ],
+ [
+ 106.79104,
+ -6.25377
+ ],
+ [
+ 106.7911,
+ -6.25342
+ ],
+ [
+ 106.79118,
+ -6.25284
+ ],
+ [
+ 106.79128,
+ -6.2524
+ ],
+ [
+ 106.79141,
+ -6.25193
+ ],
+ [
+ 106.79159,
+ -6.25108
+ ],
+ [
+ 106.79175,
+ -6.2499
+ ],
+ [
+ 106.79183,
+ -6.24929
+ ],
+ [
+ 106.79264,
+ -6.2495
+ ],
+ [
+ 106.79272,
+ -6.24956
+ ],
+ [
+ 106.79281,
+ -6.24958
+ ],
+ [
+ 106.79298,
+ -6.24962
+ ],
+ [
+ 106.79364,
+ -6.24983
+ ],
+ [
+ 106.79383,
+ -6.24992
+ ],
+ [
+ 106.7942,
+ -6.25004
+ ],
+ [
+ 106.79438,
+ -6.25006
+ ],
+ [
+ 106.79452,
+ -6.25011
+ ],
+ [
+ 106.79469,
+ -6.25013
+ ],
+ [
+ 106.7949,
+ -6.25012
+ ],
+ [
+ 106.79507,
+ -6.25009
+ ],
+ [
+ 106.79515,
+ -6.25004
+ ],
+ [
+ 106.7954,
+ -6.24984
+ ],
+ [
+ 106.79563,
+ -6.24963
+ ],
+ [
+ 106.79588,
+ -6.24938
+ ],
+ [
+ 106.79592,
+ -6.24931
+ ],
+ [
+ 106.79596,
+ -6.24918
+ ],
+ [
+ 106.79597,
+ -6.24912
+ ],
+ [
+ 106.79603,
+ -6.24911
+ ],
+ [
+ 106.79619,
+ -6.24912
+ ],
+ [
+ 106.79635,
+ -6.24929
+ ],
+ [
+ 106.79659,
+ -6.24944
+ ],
+ [
+ 106.79681,
+ -6.24953
+ ],
+ [
+ 106.79718,
+ -6.24959
+ ],
+ [
+ 106.79745,
+ -6.24961
+ ],
+ [
+ 106.79752,
+ -6.24906
+ ],
+ [
+ 106.79772,
+ -6.24761
+ ],
+ [
+ 106.79792,
+ -6.24614
+ ],
+ [
+ 106.79795,
+ -6.24592
+ ],
+ [
+ 106.79805,
+ -6.24592
+ ],
+ [
+ 106.7984,
+ -6.24591
+ ],
+ [
+ 106.79882,
+ -6.24588
+ ],
+ [
+ 106.79994,
+ -6.24591
+ ],
+ [
+ 106.79994,
+ -6.24583
+ ],
+ [
+ 106.79994,
+ -6.24565
+ ],
+ [
+ 106.79995,
+ -6.24524
+ ],
+ [
+ 106.80065,
+ -6.24523
+ ]
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/dummy_data/sales.geojson b/src/dummy_data/sales.geojson
new file mode 100644
index 0000000..c9e0832
--- /dev/null
+++ b/src/dummy_data/sales.geojson
@@ -0,0 +1,85 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "id": "sales.1",
+ "geometry_name": "the_geom",
+ "type": "Feature",
+ "properties": {
+ "id": "sales.1",
+ "name": "Sales 1"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.79569244384766,
+ -6.2395378839383016
+ ]
+ }
+ },
+ {
+ "id": "sales.2",
+ "geometry_name": "the_geom",
+ "type": "Feature",
+ "properties": {
+ "id": "sales.2",
+ "name": "Sales 2"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.78788185119627,
+ -6.2620624718682665
+ ]
+ }
+ },
+ {
+ "id": "sales.3",
+ "geometry_name": "the_geom",
+ "type": "Feature",
+ "properties": {
+ "id": "sales.3",
+ "name": "Sales 3"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.81011199951172,
+ -6.249349850172153
+ ]
+ }
+ },
+ {
+ "id": "sales.4",
+ "geometry_name": "the_geom",
+ "type": "Feature",
+ "properties": {
+ "id": "sales.4",
+ "name": "Sales 4"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.81543350219727,
+ -6.215817763782759
+ ]
+ }
+ },
+ {
+ "id": "sales.5",
+ "geometry_name": "the_geom",
+ "type": "Feature",
+ "properties": {
+ "id": "sales.5",
+ "name": "Sales 5"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.80745124816895,
+ -6.2746041510497355
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 0000000..3abe104
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,24 @@
+.nowrap {
+ white-space: nowrap;
+}
+
+.withBtn .modal-title {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+}
+
+.shift-schedule .ant-table-thead>tr>th {
+ padding: 2px 0px !important;
+ /* margin: 0 !important; */
+}
+
+.shift-schedule .ant-table-tbody>tr>td {
+ padding: 2px 0px !important;
+ /* margin: 0 !important; */
+}
+
+.sidebar-minimized .sidebar .nav > .nav-dropdown > .nav-dropdown-items {
+ max-height: 300px !important;
+ overflow: auto;
+}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..9ac5b40
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,17 @@
+import 'react-app-polyfill/ie9'; // For IE 9-11 support
+import 'react-app-polyfill/stable';
+// import 'react-app-polyfill/ie11'; // For IE 11 support
+import './polyfill'
+import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import App from './App';
+import * as serviceWorker from './serviceWorker';
+import "antd/dist/antd.css";
+
+ReactDOM.render(
, document.getElementById('root'));
+
+// If you want your app to work offline and load faster, you can change
+// unregister() to register() below. Note this comes with some pitfalls.
+// Learn more about service workers: http://bit.ly/CRA-PWA
+serviceWorker.unregister();
diff --git a/src/polyfill.js b/src/polyfill.js
new file mode 100644
index 0000000..57f887d
--- /dev/null
+++ b/src/polyfill.js
@@ -0,0 +1,46 @@
+/*
+* required polyfills
+*/
+import "core-js";
+import 'core-js/features/set/map';
+
+/** IE9, IE10 and IE11 requires all of the following polyfills. **/
+// import 'core-js/es6/symbol'
+// import 'core-js/es6/object'
+// import 'core-js/es6/function'
+// import 'core-js/es6/parse-int'
+// import 'core-js/es6/parse-float'
+// import 'core-js/es6/number'
+// import 'core-js/es6/math'
+// import 'core-js/es6/string'
+// import 'core-js/es6/date'
+// import 'core-js/es6/array'
+// import 'core-js/es6/regexp'
+// import 'core-js/es6/map'
+// import 'core-js/es6/weak-map'
+// import 'core-js/es6/set'
+// import 'core-js/es7/object'
+
+/** IE10 and IE11 requires the following for the Reflect API. */
+// import 'core-js/es6/reflect'
+
+/** Evergreen browsers require these. **/
+// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
+// import 'core-js/es7/reflect'
+
+// CustomEvent() constructor functionality in IE9, IE10, IE11
+(function () {
+
+ if ( typeof window.CustomEvent === "function" ) return false
+
+ function CustomEvent ( event, params ) {
+ params = params || { bubbles: false, cancelable: false, detail: undefined }
+ var evt = document.createEvent( 'CustomEvent' )
+ evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail )
+ return evt
+ }
+
+ CustomEvent.prototype = window.Event.prototype
+
+ window.CustomEvent = CustomEvent
+})()
diff --git a/src/routes.js b/src/routes.js
new file mode 100644
index 0000000..5c8163c
--- /dev/null
+++ b/src/routes.js
@@ -0,0 +1,113 @@
+import React from 'react';
+
+const BaseLayers = React.lazy(() => import('./views/BaseLayers'));
+const Layers = React.lazy(() => import('./views/Layers/Layers'));
+const Layer = React.lazy(() => import('./views/Layers/Layer'));
+const MapConfig = React.lazy(() => import('./views/MapConfig'));
+// const DashboardKominfo = React.lazy(() => import('./views/DashboardKominfo'));
+// const Sales = React.lazy(() => import('./views/Master/MasterSales'));
+// const GroupSales = React.lazy(() => import('./views/Master/MasterGroupSales'));
+const OfficeHours = React.lazy(() => import('./views/Master/MasterOfficeHours'));
+// const Customer = React.lazy(() => import('./views/Master/MasterCustomer'));
+// const SettingSales = React.lazy(() => import('./views/Master/MasterSales/SettingSales'));
+// const SettingOffice = React.lazy(() => import('./views/Master/MasterOffice/SettingOffice'));
+// const SettingCustomer = React.lazy(() => import('./views/Master/MasterCustomer/SettingCustomer'));
+// new
+const DivisiKaryawan = React.lazy(() => import('./views/Master/MasterTipeKaryawan'));
+const UserAdmin = React.lazy(() => import('./views/Master/UserAdmin'));
+// const UserWaspang = React.lazy(() => import('./views/Master/UserWaspang'));
+const Presensi = React.lazy(() => import('./views/SimproV2/Presence'));
+const LaporanTugas = React.lazy(() => import('./views/Master/MasterTask'));
+const Izin = React.lazy(() => import('./views/Master/MasterCuti'));
+const Roles = React.lazy(() => import('./views/Master/MasterRoles'));
+const ProjectRole = React.lazy(() => import('./views/Master/RoleProject'));
+const Menu = React.lazy(() => import('./views/Master/MasterMenu'));
+const Broadcast = React.lazy(() => import('./views/Master/MasterBroadcast'));
+const PanicButton = React.lazy(() => import('./views/SimproV2/PanicButton'));
+const Absensi = React.lazy(() => import('./views/Master/MasterAbsensi'));
+const Lembur = React.lazy(() => import('./views/Master/MasterLembur'));
+const Organization = React.lazy(() => import('./views/Master/MasterOrganization'));
+const Proyek = React.lazy(() => import('./views/Master/Proyek'));
+// const SubProyek = React.lazy(() => import('./views/Master/SubProyek'));
+const DashboardSimpro = React.lazy(() => import('./views/DashboardSimpro'));
+const controlMonitoring = React.lazy(() => import('./views/Report/ControlMonitoring'));
+const K3 = React.lazy(() => import('./views/Report/k3'));
+const TestGantt = React.lazy(() => import('./views/testgantt'));
+const ConfigAlert = React.lazy(() => import('./views/Master/ConfigAlert'));
+// const NetworkDiagram = React.lazy(() => import('./views/Master/NetworkDiagram'));
+const LaporanAlert = React.lazy(() => import('./views/Report/alert'));
+const ControlMonitoringGantt = React.lazy(() => import('./views/ControlMonitoringGantt'));
+const CreatedProyek = React.lazy(() => import('./views/SimproV2/CreatedProyek'));
+const ResourceWorker = React.lazy(() => import('./views/SimproV2/ResourceWorker'));
+const ResourceMaterial = React.lazy(() => import('./views/SimproV2/ResourceMaterial'));
+const ResourceTools = React.lazy(() => import('./views/SimproV2/ResourceTools'));
+const PlanningHarian = React.lazy(() => import('./views/SimproV2/PlanningHarian'));
+const Closing = React.lazy(() => import('./views/SimproV2/Closing'));
+const ProjectType = React.lazy(() => import('./views/SimproV2/ProjectType'));
+const Divisi = React.lazy(() => import('./views/SimproV2/Divisi'));
+const Satuan = React.lazy(() => import('./views/SimproV2/Satuan'));
+const RateCost = React.lazy(() => import('./views/SimproV2/RateCost'));
+const Gantt = React.lazy(() => import('./views/SimproV2/Gantt'));
+const Shift = React.lazy(() => import('./views/SimproV2/Shift'));
+const UserShift = React.lazy(() => import('./views/SimproV2/UserShift'));
+const ScheduleShift = React.lazy(() => import('./views/SimproV2/ScheduleShift'));
+const ChecklistK3 = React.lazy(() => import('./views/SimproV2/ChecklistK3'));
+const DashboardPMO = React.lazy(() => import('./views/DashboardPMO'));
+const DashboardProject = React.lazy(() => import('./views/DashboardProject'));
+const DashboardSecurity = React.lazy(() => import('./views/DashboardSecurity'));
+// const PlanningVsRealisasi = React.lazy(() => import('./views/Master/PlanningVsRealisasi'));
+
+// https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config
+const routes = [
+ { path: '/', exact: true, name: 'Home' },
+ { path: '/dashboard', name: 'Dashboard', component: DashboardSimpro },
+ { path: '/map/config', exact: true, name: 'Config', component: MapConfig },
+ { path: '/map/baselayers', exact: true, name: 'Base Layers', component: BaseLayers },
+ { path: '/map/layers', exact: true, name: 'Layers', component: Layers },
+ { path: '/map/layers/:id', exact: true, name: 'Layer Details', component: Layer },
+ { path: '/office-hours', exact: true, name: 'Jam Kerja', component: OfficeHours },
+ { path: '/user-admin', exact: true, name: 'User Admin', component: UserAdmin },
+ // { path: '/user-waspang', exact: true, name: 'User Waspang', component: UserWaspang },
+ { path: '/divisi-karyawan', exact: true, name: 'Divisi Karyawan', component: DivisiKaryawan },
+ { path: '/presensi', exact: true, name: 'Presensi', component: Presensi },
+ { path: '/absensi', exact: true, name: 'Absensi', component: Absensi },
+ { path: '/laporan-tugas-karyawan', exact: true, name: 'Laporan Tugas Karyawan', component: LaporanTugas },
+ { path: '/izin', exact: true, name: 'Izin', component: Izin },
+ { path: '/broadcast', exact: true, name: 'Broadcast', component: Broadcast },
+ { path: '/panic-button', exact: true, name: 'Tombol Darurat', component: PanicButton },
+ { path: '/proyek', exact: true, name: 'Created Project', component: Proyek },
+ // { path: '/sub-proyek', exact: true, name: 'Subproyek', component: SubProyek },
+ { path: '/menu', exact: true, name: 'Menu', component: Menu },
+ { path: '/roles', exact: true, name: 'Roles', component: Roles },
+ { path: '/lembur', exact: true, name: 'Lembur', component: Lembur },
+ { path: '/organization', exact: true, name: 'Organisasi', component: Organization },
+ { path: '/control-monitoring', exact: true, name: 'Control Monitoring', component: controlMonitoring },
+ { path: '/laporan-k3', exact: true, name: 'Laporan K3', component: K3 },
+ { path: '/proyek-gantt', exact: true, name: 'Gantt Chart Proyek', component: TestGantt },
+ { path: '/config-alert', exact: true, name: 'Config Alert', component: ConfigAlert },
+ { path: '/laporan-alert', exact: true, name: 'Laporan Alert', component: LaporanAlert },
+ { path: '/control-monitoring-gantt', exact: true, name: 'Control Monitoring Gantt', component: ControlMonitoringGantt },
+ { path: '/projects', exact: true, name: 'Projects', component: CreatedProyek },
+ { path: '/human-resource', exact: true, name: 'Human Resource', component: ResourceWorker },
+ { path: '/material-resource', exact: true, name: 'Material Resource', component: ResourceMaterial },
+ { path: '/tools-resource', exact: true, name: 'Tools Resource', component: ResourceTools },
+ { path: '/projects/:id/:project/gantt', exact: true, name: 'Gantt', component: Gantt },
+ { path: '/planning-harian', exact: true, name: 'Planning Harian', component: PlanningHarian },
+ { path: '/presensi-resource', exact: true, name: 'Presensi Resource', component: Presensi },
+ { path: '/absensi-resource', exact: true, name: 'Absensi Resource', component: Absensi },
+ { path: '/closing', exact: true, name: 'Closing', component: Closing },
+ { path: '/project-type', exact: true, name: 'Project Type', component: ProjectType },
+ { path: '/divisi', exact: true, name: 'Divisi', component: Divisi },
+ { path: '/satuan', exact: true, name: 'Satuan', component: Satuan },
+ { path: '/rate-cost', exact: true, name: 'Rate Cost', component: RateCost },
+ { path: '/project-role', exact: true, name: 'Project Role', component: ProjectRole },
+ { path: '/working-hour', exact: true, name: 'Working Hour', component: Shift },
+ { path: '/user-shift', exact: true, name: 'Shift', component: UserShift },
+ { path: '/schedule-shift', exact: true, name: 'Schedule Shift', component: ScheduleShift },
+ { path: '/checklist-k3', exact: true, name: 'Checklist K3', component: ChecklistK3 },
+ { path: '/dashboard-pmo', exact: true, name: 'Dashboard PMO', component: DashboardPMO },
+ { path: '/dashboard-security', exact: true, name: 'Dashboard Security', component: DashboardSecurity },
+ { path: '/dashboard-project', exact: true, name: 'Dashboard Project', component: DashboardProject },
+];
+
+export default routes;
diff --git a/src/scss/_custom.scss b/src/scss/_custom.scss
new file mode 100644
index 0000000..cc6452e
--- /dev/null
+++ b/src/scss/_custom.scss
@@ -0,0 +1,135 @@
+// Here you can add other styles
+// @media (min-width: 992px)
+.sidebar-minimized .sidebar .nav-link {
+ min-width: 300px !important;
+}
+
+.sidebar-minimized .sidebar .nav-link:hover {
+ min-width: 300px !important;
+}
+
+.sidebar .nav-dropdown-items {
+ min-width: 250px !important;
+}
+
+.sidebar-minimized .sidebar .nav-dropdown-items .nav-item {
+ min-width: 250px !important;
+}
+
+
+.box-dashboard-pm {
+ margin-top: 10px;
+ width: 100%;
+ height: 90px;
+ padding: 10px;
+ border-radius: 2px;
+ box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5);
+ -webkit-box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5);
+ -moz-box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5);
+
+ .box-icon {
+ margin: 0;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ -ms-transform: translate(-50%, -50%);
+ transform: translate(-50%, -50%);
+ }
+
+ .box-content {
+ text-align: center;
+
+ .text-box {
+ color: #fff;
+ font-weight: 500
+ }
+
+ .text-box-secondary {
+ color: #e6e6e6;
+ font-weight: 500
+ }
+ }
+}
+
+.health-status {
+ height: 15px;
+ width: 15px;
+ border-radius: 50%;
+}
+
+.health-status-danger {
+ @extend .health-status;
+ background-color: #b30000;
+}
+
+.health-status-good {
+ @extend .health-status;
+ background-color: #047857;
+}
+
+.health-status-warning {
+ @extend .health-status;
+ background-color: #e68a00;
+}
+
+.health-status-default {
+ @extend .health-status;
+ background-color: #a8a29e;
+}
+
+.box-header-dashboard-project {
+ padding: 10px;
+ // background-color: #a8a29e;
+ border-radius: 3px;
+ box-shadow: 0px 0px 3px 0px rgba(97, 96, 96, 0.4);
+ -webkit-box-shadow: 0px 0px 3px 0px rgba(97, 96, 96, 0.4);
+ -moz-box-shadow: 0px 0px 3px 0px rgba(97, 96, 96, 0.4);
+}
+
+#map {
+ // position: absolute;
+ width: 100%;
+ height: 400px;
+}
+
+.chat {
+ overflow: auto;
+ height: 80vh;
+}
+
+.chat-content {
+ margin: 8px 0;
+ font-size: 0.8em;
+ border-bottom-right-radius: 10px;
+ border-bottom-left-radius: 10px;
+ border-top-right-radius: 10px;
+
+ box-shadow: 0px 0px 3px 0px rgba(97, 96, 96, 0.4) inset;
+ -webkit-box-shadow: 0px 0px 3px 0px rgba(97, 96, 96, 0.4) inset;
+ -moz-box-shadow: 0px 0px 3px 0px rgba(97, 96, 96, 0.4) inset;
+ // pointer-events: none;
+}
+
+.chat-header {
+ font-weight: bold;
+ color: rgb(53, 52, 52);
+}
+
+.chat-body-content {
+ padding-top: 4px;
+ font-weight: 500;
+ color: rgb(78, 78, 78)
+}
+
+.chat-footer {
+ padding-top: 5px;
+ font-weight: bold;
+ color: rgb(151, 151, 151);
+ font-size: 0.8em;
+ display: flex;
+ justify-content: flex-end;
+}
+
+.chat-body {
+ padding: 6px 10px
+}
\ No newline at end of file
diff --git a/src/scss/_ie-fix.scss b/src/scss/_ie-fix.scss
new file mode 100644
index 0000000..8cacff8
--- /dev/null
+++ b/src/scss/_ie-fix.scss
@@ -0,0 +1,11 @@
+html body .app.flex-row.align-items-center {
+ height: 100vh;
+}
+
+// ie11 floating footer temp fix, react only
+@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
+ #root {
+ display: flex;
+ flex-direction: column;
+ }
+}
diff --git a/src/scss/_variables.scss b/src/scss/_variables.scss
new file mode 100644
index 0000000..a47111f
--- /dev/null
+++ b/src/scss/_variables.scss
@@ -0,0 +1 @@
+// Variable overrides
diff --git a/src/scss/style.scss b/src/scss/style.scss
new file mode 100644
index 0000000..01a3be4
--- /dev/null
+++ b/src/scss/style.scss
@@ -0,0 +1,14 @@
+// If you want to override variables do it here
+@import "variables";
+
+// Import styles
+@import "~@coreui/coreui/scss/coreui.scss";
+
+// Temp fix for reactstrap
+@import '~@coreui/coreui/scss/_dropdown-menu-right.scss';
+
+// If you want to add something do it here
+@import "custom";
+
+// ie fixes
+@import "ie-fix";
diff --git a/src/scss/vendors/.gitkeep b/src/scss/vendors/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/src/scss/vendors/_variables.scss b/src/scss/vendors/_variables.scss
new file mode 100644
index 0000000..10e5ddb
--- /dev/null
+++ b/src/scss/vendors/_variables.scss
@@ -0,0 +1,4 @@
+// Override Boostrap variables
+@import "../variables";
+@import "~bootstrap/scss/mixins";
+@import "~@coreui/coreui/scss/variables";
diff --git a/src/serviceWorker.js b/src/serviceWorker.js
new file mode 100644
index 0000000..2c5d31f
--- /dev/null
+++ b/src/serviceWorker.js
@@ -0,0 +1,127 @@
+// In production, we register a service worker to serve assets from local cache.
+
+// This lets the app load faster on subsequent visits in production, and gives
+// it offline capabilities. However, it also means that developers (and users)
+// will only see deployed updates on the "N+1" visit to a page, since previously
+// cached resources are updated in the background.
+
+// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
+// This link also includes instructions on opting out of this behavior.
+
+const isLocalhost = Boolean(
+ window.location.hostname === 'localhost' ||
+ // [::1] is the IPv6 localhost address.
+ window.location.hostname === '[::1]' ||
+ // 127.0.0.1/8 is considered localhost for IPv4.
+ window.location.hostname.match(
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+ )
+);
+
+export function register(config) {
+ if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
+ // The URL constructor is available in all browsers that support SW.
+ const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
+ if (publicUrl.origin !== window.location.origin) {
+ // Our service worker won't work if PUBLIC_URL is on a different origin
+ // from what our page is served on. This might happen if a CDN is used to
+ // serve assets; see https://github.com/facebook/create-react-app/issues/2374
+ return;
+ }
+
+ window.addEventListener('load', () => {
+ const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+
+ if (isLocalhost) {
+ // This is running on localhost. Let's check if a service worker still exists or not.
+ checkValidServiceWorker(swUrl, config);
+
+ // Add some additional logging to localhost, pointing developers to the
+ // service worker/PWA documentation.
+ navigator.serviceWorker.ready.then(() => {
+ console.log(
+ 'This web app is being served cache-first by a service ' +
+ 'worker. To learn more, visit https://goo.gl/SC7cgQ'
+ );
+ });
+ } else {
+ // Is not local host. Just register service worker
+ registerValidSW(swUrl, config);
+ }
+ });
+ }
+}
+
+function registerValidSW(swUrl, config) {
+ navigator.serviceWorker
+ .register(swUrl)
+ .then(registration => {
+ registration.onupdatefound = () => {
+ const installingWorker = registration.installing;
+ installingWorker.onstatechange = () => {
+ if (installingWorker.state === 'installed') {
+ if (navigator.serviceWorker.controller) {
+ // At this point, the old content will have been purged and
+ // the fresh content will have been added to the cache.
+ // It's the perfect time to display a "New content is
+ // available; please refresh." message in your web app.
+ console.log('New content is available; please refresh.');
+
+ // Execute callback
+ if (config.onUpdate) {
+ config.onUpdate(registration);
+ }
+ } else {
+ // At this point, everything has been precached.
+ // It's the perfect time to display a
+ // "Content is cached for offline use." message.
+ console.log('Content is cached for offline use.');
+
+ // Execute callback
+ if (config.onSuccess) {
+ config.onSuccess(registration);
+ }
+ }
+ }
+ };
+ };
+ })
+ .catch(error => {
+ console.error('Error during service worker registration:', error);
+ });
+}
+
+function checkValidServiceWorker(swUrl, config) {
+ // Check if the service worker can be found. If it can't reload the page.
+ fetch(swUrl)
+ .then(response => {
+ // Ensure service worker exists, and that we really are getting a JS file.
+ if (
+ response.status === 404 ||
+ response.headers.get('content-type').indexOf('javascript') === -1
+ ) {
+ // No service worker found. Probably a different app. Reload the page.
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister().then(() => {
+ window.location.reload();
+ });
+ });
+ } else {
+ // Service worker found. Proceed as normal.
+ registerValidSW(swUrl, config);
+ }
+ })
+ .catch(() => {
+ console.log(
+ 'No internet connection found. App is running in offline mode.'
+ );
+ });
+}
+
+export function unregister() {
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister();
+ });
+ }
+}
diff --git a/src/setupTests.js b/src/setupTests.js
new file mode 100644
index 0000000..5b7289a
--- /dev/null
+++ b/src/setupTests.js
@@ -0,0 +1,15 @@
+import { configure } from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+
+configure({ adapter: new Adapter() });
+
+if (global.document) {
+ document.createRange = () => ( {
+ setStart: () => {},
+ setEnd: () => {},
+ commonAncestorContainer: {
+ nodeName: 'BODY',
+ ownerDocument: document,
+ },
+ });
+}
diff --git a/src/views/Base/Breadcrumbs/Breadcrumbs.js b/src/views/Base/Breadcrumbs/Breadcrumbs.js
new file mode 100644
index 0000000..fc5d1a1
--- /dev/null
+++ b/src/views/Base/Breadcrumbs/Breadcrumbs.js
@@ -0,0 +1,50 @@
+import React, { Component } from 'react';
+import { Breadcrumb, BreadcrumbItem, Card, CardBody, CardHeader, Col, Row } from 'reactstrap';
+
+class Breadcrumbs extends Component {
+ render() {
+ return (
+
+
+
+
+
+ Breadcrumbs
+
+
+
+
+ Home
+
+
+ {/*eslint-disable-next-line*/}
+ Home
+ Library
+
+
+ {/*eslint-disable-next-line*/}
+ Home
+ {/* eslint-disable-next-line*/}
+ Library
+ Data
+
+
+ Home
+ Library
+ Data
+ Bootstrap
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Breadcrumbs;
diff --git a/src/views/Base/Breadcrumbs/Breadcrumbs.test.js b/src/views/Base/Breadcrumbs/Breadcrumbs.test.js
new file mode 100644
index 0000000..a9ab3a7
--- /dev/null
+++ b/src/views/Base/Breadcrumbs/Breadcrumbs.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Breadcrumbs from './Breadcrumbs';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Breadcrumbs/package.json b/src/views/Base/Breadcrumbs/package.json
new file mode 100644
index 0000000..4b439ca
--- /dev/null
+++ b/src/views/Base/Breadcrumbs/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Breadcrumbs",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Breadcrumbs.js"
+}
diff --git a/src/views/Base/Cards/Cards.js b/src/views/Base/Cards/Cards.js
new file mode 100644
index 0000000..0393767
--- /dev/null
+++ b/src/views/Base/Cards/Cards.js
@@ -0,0 +1,416 @@
+import React, { Component } from 'react';
+import { Badge, Card, CardBody, CardFooter, CardHeader, Col, Row, Collapse, Fade } from 'reactstrap';
+import { AppSwitch } from '@coreui/react'
+
+class Cards extends Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.toggleFade = this.toggleFade.bind(this);
+ this.state = {
+ collapse: true,
+ fadeIn: true,
+ timeout: 300
+ };
+ }
+
+ toggle() {
+ this.setState({ collapse: !this.state.collapse });
+ }
+
+ toggleFade() {
+ this.setState((prevState) => { return { fadeIn: !prevState }});
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ Card title
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+ Card footer
+
+
+
+
+
+ Card with icon
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with switch
+
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with label
+
+ Success
+
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with label
+
+ 42
+
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+
+
+ Card outline primary
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card outline secondary
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card outline success
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card outline info
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card outline warning
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card outline danger
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+
+
+
+ Card with accent
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with accent
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with accent
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with accent
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with accent
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card with accent
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ Someone famous in Source Title
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ Someone famous in Source Title
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ Someone famous in Source Title
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ Someone famous in Source Title
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ Someone famous in Source Title
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ Someone famous in Source Title
+
+
+
+
+
+
+
+
+
+ Card title
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card title
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card title
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card title
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+ Card title
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+
+ Card actions
+
+ {/*eslint-disable-next-line*/}
+
+ {/*eslint-disable-next-line*/}
+
+ {/*eslint-disable-next-line*/}
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
+ laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation
+ ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Cards;
diff --git a/src/views/Base/Cards/Cards.test.js b/src/views/Base/Cards/Cards.test.js
new file mode 100644
index 0000000..b0f9c87
--- /dev/null
+++ b/src/views/Base/Cards/Cards.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Cards from './Cards';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Cards/package.json b/src/views/Base/Cards/package.json
new file mode 100644
index 0000000..ec9afb4
--- /dev/null
+++ b/src/views/Base/Cards/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Cards",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Cards.js"
+}
diff --git a/src/views/Base/Carousels/Carousels.js b/src/views/Base/Carousels/Carousels.js
new file mode 100644
index 0000000..3999e5a
--- /dev/null
+++ b/src/views/Base/Carousels/Carousels.js
@@ -0,0 +1,124 @@
+import React, { Component } from 'react';
+import { Card, CardBody, CardHeader, Carousel, CarouselCaption, CarouselControl, CarouselIndicators, CarouselItem, Col, Row } from 'reactstrap';
+
+const items = [
+ {
+ src: 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_1607923e7e2%20text%20%7B%20fill%3A%23555%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_1607923e7e2%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23777%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22285.9296875%22%20y%3D%22217.75625%22%3EFirst%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E',
+ altText: 'Slide 1',
+ caption: 'Slide 1',
+ },
+ {
+ src: 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_15ba800aa20%20text%20%7B%20fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_15ba800aa20%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23666%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22247.3203125%22%20y%3D%22218.3%22%3ESecond%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E',
+ altText: 'Slide 2',
+ caption: 'Slide 2',
+ },
+ {
+ src: 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22800%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20800%20400%22%20preserveAspectRatio%3D%22none%22%3E%3Cdefs%3E%3Cstyle%20type%3D%22text%2Fcss%22%3E%23holder_15ba800aa21%20text%20%7B%20fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C%20monospace%3Bfont-size%3A40pt%20%7D%20%3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg%20id%3D%22holder_15ba800aa21%22%3E%3Crect%20width%3D%22800%22%20height%3D%22400%22%20fill%3D%22%23555%22%3E%3C%2Frect%3E%3Cg%3E%3Ctext%20x%3D%22277%22%20y%3D%22218.3%22%3EThird%20slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E',
+ altText: 'Slide 3',
+ caption: 'Slide 3',
+ },
+];
+
+class Carousels extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = { activeIndex: 0 };
+ this.next = this.next.bind(this);
+ this.previous = this.previous.bind(this);
+ this.goToIndex = this.goToIndex.bind(this);
+ this.onExiting = this.onExiting.bind(this);
+ this.onExited = this.onExited.bind(this);
+ }
+
+ onExiting() {
+ this.animating = true;
+ }
+
+ onExited() {
+ this.animating = false;
+ }
+
+ next() {
+ if (this.animating) return;
+ const nextIndex = this.state.activeIndex === items.length - 1 ? 0 : this.state.activeIndex + 1;
+ this.setState({ activeIndex: nextIndex });
+ }
+
+ previous() {
+ if (this.animating) return;
+ const nextIndex = this.state.activeIndex === 0 ? items.length - 1 : this.state.activeIndex - 1;
+ this.setState({ activeIndex: nextIndex });
+ }
+
+ goToIndex(newIndex) {
+ if (this.animating) return;
+ this.setState({ activeIndex: newIndex });
+ }
+
+ render() {
+ const { activeIndex } = this.state;
+
+ const slides = items.map((item) => {
+ return (
+
+
+
+ );
+ });
+
+ const slides2 = items.map((item) => {
+ return (
+
+
+
+
+ );
+ });
+
+ return (
+
+
+
+
+
+ Carousel
+
+
+
+
+ {slides}
+
+
+
+
+
+
+
+ Carousel
+
+
+
+
+ {slides2}
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Carousels;
\ No newline at end of file
diff --git a/src/views/Base/Carousels/Carousels.test.js b/src/views/Base/Carousels/Carousels.test.js
new file mode 100644
index 0000000..efee537
--- /dev/null
+++ b/src/views/Base/Carousels/Carousels.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Carousels from './Carousels';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Carousels/package.json b/src/views/Base/Carousels/package.json
new file mode 100644
index 0000000..5c16947
--- /dev/null
+++ b/src/views/Base/Carousels/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Carousels",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Carousels.js"
+}
diff --git a/src/views/Base/Collapses/Collapses.js b/src/views/Base/Collapses/Collapses.js
new file mode 100644
index 0000000..1a93021
--- /dev/null
+++ b/src/views/Base/Collapses/Collapses.js
@@ -0,0 +1,233 @@
+import React, { Component } from 'react';
+import { Badge, Button, Card, CardBody, CardFooter, CardHeader, Col, Collapse, Fade, Row } from 'reactstrap';
+
+class Collapses extends Component {
+
+ constructor(props) {
+ super(props);
+ this.onEntering = this.onEntering.bind(this);
+ this.onEntered = this.onEntered.bind(this);
+ this.onExiting = this.onExiting.bind(this);
+ this.onExited = this.onExited.bind(this);
+ this.toggle = this.toggle.bind(this);
+ this.toggleAccordion = this.toggleAccordion.bind(this);
+ this.toggleCustom = this.toggleCustom.bind(this);
+ this.toggleFade = this.toggleFade.bind(this);
+ this.state = {
+ collapse: false,
+ accordion: [true, false, false],
+ custom: [true, false],
+ status: 'Closed',
+ fadeIn: true,
+ timeout: 300,
+ };
+ }
+
+ onEntering() {
+ this.setState({ status: 'Opening...' });
+ }
+
+ onEntered() {
+ this.setState({ status: 'Opened' });
+ }
+
+ onExiting() {
+ this.setState({ status: 'Closing...' });
+ }
+
+ onExited() {
+ this.setState({ status: 'Closed' });
+ }
+
+ toggle() {
+ this.setState({ collapse: !this.state.collapse });
+ }
+
+ toggleAccordion(tab) {
+
+ const prevState = this.state.accordion;
+ const state = prevState.map((x, index) => tab === index ? !x : false);
+
+ this.setState({
+ accordion: state,
+ });
+ }
+
+ toggleCustom(tab) {
+
+ const prevState = this.state.custom;
+ const state = prevState.map((x, index) => tab === index ? !x : false);
+
+ this.setState({
+ custom: state,
+ });
+ }
+
+ toggleFade() {
+ this.setState({ fadeIn: !this.state.fadeIn });
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ Collapse
+
+
+
+
+
+ Anim pariatur cliche reprehenderit,
+ enim eiusmod high life accusamus terry richardson ad squid. Nihil
+ anim keffiyeh helvetica, craft beer labore wes anderson cred
+ nesciunt sapiente ea proident.
+
+
+ Donec molestie odio id nisi malesuada, mattis tincidunt velit egestas. Sed non pulvinar risus. Aenean
+ elementum eleifend nunc, pellentesque dapibus arcu hendrerit fringilla. Aliquam in nibh massa. Cras
+ ultricies lorem non enim volutpat, a eleifend urna placerat. Fusce id luctus urna. In sed leo tellus.
+ Mauris tristique leo a nisl feugiat, eget vehicula leo venenatis. Quisque magna metus, luctus quis
+ sollicitudin vel, vehicula nec ipsum. Donec rutrum commodo lacus ut condimentum. Integer vel turpis
+ purus. Etiam vehicula, nulla non fringilla blandit, massa purus faucibus tellus, a luctus enim orci non
+ augue. Aenean ullamcorper nisl urna, non feugiat tortor volutpat in. Vivamus lobortis massa dolor, eget
+ faucibus ipsum varius eget. Pellentesque imperdiet, turpis sed sagittis lobortis, leo elit laoreet arcu,
+ vehicula sagittis elit leo id nisi.
+
+
+
+
+ Toggle
+
+ Current state: {this.state.status}
+
+
+
+
+ Fade
+
+
+
+
+ This content will fade in and out as the button is pressed...
+
+
+
+ Toggle Fade
+
+
+
+
+
+
+ Collapse accordion
+
+ NEW
+
+
+
+
+
+
+ this.toggleAccordion(0)} aria-expanded={this.state.accordion[0]} aria-controls="collapseOne">
+ Collapsible Group Item #1
+
+
+
+
+ 1. Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non
+ cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird
+ on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred
+ nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft
+ beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
+
+
+
+
+
+ this.toggleAccordion(1)} aria-expanded={this.state.accordion[1]} aria-controls="collapseTwo">
+ Collapsible Group Item #2
+
+
+
+
+ 2. Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non
+ cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird
+ on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred
+ nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft
+ beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
+
+
+
+
+
+ this.toggleAccordion(2)} aria-expanded={this.state.accordion[2]} aria-controls="collapseThree">
+ Collapsible Group Item #3
+
+
+
+
+ 3. Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non
+ cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird
+ on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred
+ nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft
+ beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
+
+
+
+
+
+
+
+
+ Collapse custom accordion
+
+ NEW
+
+
+
+
+
+
this.toggleCustom(0)} aria-expanded={this.state.custom[0]} aria-controls="exampleAccordion1">
+ Toggle item
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed pretium lorem non vestibulum scelerisque. Proin a vestibulum sem, eget
+ tristique massa. Aliquam lacinia rhoncus nibh quis ornare.
+
+
+
+
+
this.toggleCustom(1)} aria-expanded={this.state.custom[1]} aria-controls="exampleAccordion2">
+ Toggle item 2
+
+
+
+ Donec at ipsum dignissim, rutrum turpis scelerisque, tristique lectus. Pellentesque habitant morbi tristique senectus et netus et
+ malesuada fames ac turpis egestas. Vivamus nec dui turpis. Orci varius natoque penatibus et magnis dis parturient montes,
+ nascetur ridiculus mus.
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Collapses;
diff --git a/src/views/Base/Collapses/Collapses.test.js b/src/views/Base/Collapses/Collapses.test.js
new file mode 100644
index 0000000..ccd31e0
--- /dev/null
+++ b/src/views/Base/Collapses/Collapses.test.js
@@ -0,0 +1,73 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Collapses from './Collapses';
+import {mount} from 'enzyme/build';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+
+describe('toggle clicks', function() {
+ it('collapse without crashing', () => {
+ const wrapper = mount(
);
+ let collapse = wrapper.find('#toggleCollapse1').at(0);
+ collapse.simulate('click');
+ expect(wrapper.state().collapse).toEqual(true);
+ collapse.simulate('click');
+ expect(wrapper.state().collapse).toEqual(false);
+ collapse.simulate('click');
+ expect(wrapper.state().collapse).toEqual(true);
+ wrapper.unmount()
+ });
+ it('fade without crashing', () => {
+ const wrapper = mount(
);
+ let fade = wrapper.find('#toggleFade1').at(0);
+ fade.simulate('click');
+ expect(wrapper.state().fadeIn).toEqual(false);
+ fade.simulate('click');
+ expect(wrapper.state().fadeIn).toEqual(true);
+ wrapper.unmount()
+ });
+ it('accordion without crashing', () => {
+ const wrapper = mount(
);
+ let accordion = wrapper.find('[aria-controls="collapseOne"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().accordion[0]).toEqual(false);
+ expect(wrapper.state().accordion[1]).toEqual(false);
+ expect(wrapper.state().accordion[2]).toEqual(false);
+ accordion = wrapper.find('[aria-controls="collapseTwo"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().accordion[0]).toEqual(false);
+ expect(wrapper.state().accordion[1]).toEqual(true);
+ expect(wrapper.state().accordion[2]).toEqual(false);
+ accordion = wrapper.find('[aria-controls="collapseThree"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().accordion[0]).toEqual(false);
+ expect(wrapper.state().accordion[1]).toEqual(false);
+ expect(wrapper.state().accordion[2]).toEqual(true);
+ accordion = wrapper.find('[aria-controls="collapseOne"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().accordion[0]).toEqual(true);
+ expect(wrapper.state().accordion[1]).toEqual(false);
+ expect(wrapper.state().accordion[2]).toEqual(false);
+ wrapper.unmount()
+ });
+ it('custom without crashing', () => {
+ const wrapper = mount(
);
+ let accordion = wrapper.find('[aria-controls="exampleAccordion1"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().custom[0]).toEqual(false);
+ expect(wrapper.state().custom[1]).toEqual(false);
+ accordion = wrapper.find('[aria-controls="exampleAccordion1"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().custom[0]).toEqual(true);
+ expect(wrapper.state().custom[1]).toEqual(false);
+ accordion = wrapper.find('[aria-controls="exampleAccordion2"]').at(0);
+ accordion.simulate('click');
+ expect(wrapper.state().custom[0]).toEqual(false);
+ expect(wrapper.state().custom[1]).toEqual(true);
+ wrapper.unmount()
+ });
+});
diff --git a/src/views/Base/Collapses/package.json b/src/views/Base/Collapses/package.json
new file mode 100644
index 0000000..60c3569
--- /dev/null
+++ b/src/views/Base/Collapses/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Collapses",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Collapses.js"
+}
diff --git a/src/views/Base/Dropdowns/Dropdowns.js b/src/views/Base/Dropdowns/Dropdowns.js
new file mode 100644
index 0000000..ea1dac9
--- /dev/null
+++ b/src/views/Base/Dropdowns/Dropdowns.js
@@ -0,0 +1,168 @@
+import React, { Component } from 'react';
+import { Card, CardBody, CardHeader, Col, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Row, UncontrolledDropdown } from 'reactstrap';
+
+class Dropdowns extends Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ dropdownOpen: new Array(6).fill(false),
+ };
+ }
+
+ toggle(i) {
+ const newArray = this.state.dropdownOpen.map((element, index) => {
+ return (index === i ? !element : false);
+ });
+ this.setState({
+ dropdownOpen: newArray,
+ });
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ Dropdowns
+
+
+
+ {
+ this.toggle(0);
+ }}>
+
+ Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+
+
+
+
+ Dropdowns
+ alignment
+
+
+ {this.toggle(1);}}>
+
+ This dropdown's menu is right-aligned
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+
+
+
+
+ Dropdowns
+ sizing
+
+
+ {this.toggle(2);}} size="lg" className="mb-3">
+
+ Large Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+ {this.toggle(3);}} className="mb-3">
+
+ Normal Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+ {this.toggle(4);}} size="sm">
+
+ Small Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+
+
+
+
+ Custom Dropdowns
+
+
+ {this.toggle(5);}}>
+ {this.toggle(5);}}
+ data-toggle="dropdown"
+ aria-expanded={this.state.dropdownOpen[5]}
+ >
+ Custom Dropdown Content *
+
+
+ {this.toggle(5);}}>Custom dropdown item 1
+ {this.toggle(5);}}>Custom dropdown item 2
+ {this.toggle(5);}}>Custom dropdown text 3
+
+ {this.toggle(5);}}>Custom dropdown item 4
+
+
+
+
+
+
+ Uncontrolled Dropdown
+
+
+
+
+ Uncontrolled Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Dropdowns;
diff --git a/src/views/Base/Dropdowns/Dropdowns.test.js b/src/views/Base/Dropdowns/Dropdowns.test.js
new file mode 100644
index 0000000..5d9776c
--- /dev/null
+++ b/src/views/Base/Dropdowns/Dropdowns.test.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { mount } from 'enzyme'
+import Dropdowns from './Dropdowns';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+it('toggle click without crashing', () => {
+ const wrapper = mount(
);
+ for (let i=0; i<5; i++) {
+ let Dropdown = wrapper.find('button.dropdown-toggle').at(i);
+ Dropdown.simulate('click');
+ expect(wrapper.state().dropdownOpen[i]).toEqual(true);
+ }
+ for (let i=0; i<2; i++) {
+ let Dropdown = wrapper.find('[data-toggle="dropdown"]').at(0);
+ Dropdown.simulate('click');
+ expect(wrapper.state().dropdownOpen[5]).toEqual(true);
+ let DropdownItem = wrapper.find('div.dropdown-menu > .dropdown-item').at(i);
+ DropdownItem.simulate('click');
+ expect(wrapper.state().dropdownOpen[5]).toEqual(false);
+ }
+ wrapper.unmount()
+});
diff --git a/src/views/Base/Dropdowns/package.json b/src/views/Base/Dropdowns/package.json
new file mode 100644
index 0000000..cc28d86
--- /dev/null
+++ b/src/views/Base/Dropdowns/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Dropdowns",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Dropdowns.js"
+}
diff --git a/src/views/Base/Forms/Forms.js b/src/views/Base/Forms/Forms.js
new file mode 100644
index 0000000..f0e5ad6
--- /dev/null
+++ b/src/views/Base/Forms/Forms.js
@@ -0,0 +1,1161 @@
+import React, { Component } from 'react';
+import {
+ Badge,
+ Button,
+ Card,
+ CardBody,
+ CardFooter,
+ CardHeader,
+ Col,
+ Collapse,
+ DropdownItem,
+ DropdownMenu,
+ DropdownToggle,
+ Fade,
+ Form,
+ FormGroup,
+ FormText,
+ FormFeedback,
+ Input,
+ InputGroup,
+ InputGroupAddon,
+ InputGroupButtonDropdown,
+ InputGroupText,
+ Label,
+ Row,
+} from 'reactstrap';
+
+class Forms extends Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.toggleFade = this.toggleFade.bind(this);
+ this.state = {
+ collapse: true,
+ fadeIn: true,
+ timeout: 300
+ };
+ }
+
+ toggle() {
+ this.setState({ collapse: !this.state.collapse });
+ }
+
+ toggleFade() {
+ this.setState((prevState) => { return { fadeIn: !prevState }});
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default Forms;
diff --git a/src/views/Base/Forms/Forms.test.js b/src/views/Base/Forms/Forms.test.js
new file mode 100644
index 0000000..c77a535
--- /dev/null
+++ b/src/views/Base/Forms/Forms.test.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Forms from './Forms';
+import {mount} from 'enzyme/build';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+
+describe('toggle clicks', function() {
+ it('dropdowns without crashing', () => {
+ const wrapper = mount(
);
+ for (let i = 0; i < 4; i++) {
+ let count = i === 0 ? 'first' : i === 1 ? 'second' : i === 2 ? 'third' : 'fourth'
+ let Dropdown = wrapper.find('button.dropdown-toggle').at(i);
+ Dropdown.simulate('click');
+ expect(wrapper.state()[count]).toEqual(true);
+ }
+ wrapper.unmount()
+ });
+ it('collapse without crashing', () => {
+ const wrapper = mount(
);
+ let collapse = wrapper.find('button.btn-minimize').at(0);
+ collapse.simulate('click');
+ expect(wrapper.state().collapse).toEqual(false);
+ collapse.simulate('click');
+ expect(wrapper.state().collapse).toEqual(true);
+ wrapper.unmount()
+ });
+ it('fade without crashing', () => {
+ const wrapper = mount(
);
+ let fade = wrapper.find('button.btn-close').at(0);
+ fade.simulate('click');
+ expect(wrapper.state().fadeIn).toEqual(false);
+ wrapper.unmount()
+ });
+})
diff --git a/src/views/Base/Forms/package.json b/src/views/Base/Forms/package.json
new file mode 100644
index 0000000..6681319
--- /dev/null
+++ b/src/views/Base/Forms/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Forms",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Forms.js"
+}
diff --git a/src/views/Base/Jumbotrons/Jumbotrons.js b/src/views/Base/Jumbotrons/Jumbotrons.js
new file mode 100644
index 0000000..1941974
--- /dev/null
+++ b/src/views/Base/Jumbotrons/Jumbotrons.js
@@ -0,0 +1,56 @@
+import React, { Component } from 'react';
+import { Button, Card, CardBody, CardHeader, Col, Container, Jumbotron, Row } from 'reactstrap';
+
+class Jumbotrons extends Component {
+
+ render() {
+ return (
+
+
+
+
+
+ Jumbotron
+
+
+
+
+ Hello, world!
+ This is a simple hero unit, a simple Jumbotron-style component for calling extra
+ attention to featured content or information.
+
+ It uses utility classes for typgraphy and spacing to space content out within the larger container.
+
+ Learn More
+
+
+
+
+
+
+
+
+ Jumbotron
+ fluid
+
+
+
+
+ Fluid jumbotron
+ This is a modified jumbotron that occupies the entire horizontal space of its parent.
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Jumbotrons;
diff --git a/src/views/Base/Jumbotrons/Jumbotrons.test.js b/src/views/Base/Jumbotrons/Jumbotrons.test.js
new file mode 100644
index 0000000..8c00730
--- /dev/null
+++ b/src/views/Base/Jumbotrons/Jumbotrons.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Jumbotrons from './Jumbotrons';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Jumbotrons/package.json b/src/views/Base/Jumbotrons/package.json
new file mode 100644
index 0000000..ba7fb80
--- /dev/null
+++ b/src/views/Base/Jumbotrons/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Jumbotrons",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Jumbotrons.js"
+}
diff --git a/src/views/Base/ListGroups/ListGroups.js b/src/views/Base/ListGroups/ListGroups.js
new file mode 100644
index 0000000..c4fc57b
--- /dev/null
+++ b/src/views/Base/ListGroups/ListGroups.js
@@ -0,0 +1,229 @@
+import React, { Component } from 'react';
+import { Badge, Card, CardBody, CardHeader, Col, ListGroup, ListGroupItem, ListGroupItemHeading, ListGroupItemText, Row, TabContent, TabPane } from 'reactstrap';
+
+class ListGroups extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ activeTab: 1
+ };
+ }
+
+ toggle(tab) {
+ if (this.state.activeTab !== tab) {
+ this.setState({
+ activeTab: tab
+ });
+ }
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ List Group
+
+
+
+
+ Cras justo odio
+ Dapibus ac facilisis in
+ Morbi leo risus
+ Porta ac consectetur ac
+ Vestibulum at eros
+
+
+
+
+
+
+
+ List Group
+ tags
+
+
+
+ Cras justo odio 14
+ Dapibus ac facilisis in 2
+ Morbi leo risus 1
+
+
+
+
+
+
+
+
+
+ List Group
+ disabled items
+
+
+
+ Cras justo odio
+ Dapibus ac facilisis in
+ Morbi leo risus
+ Porta ac consectetur ac
+ Vestibulum at eros
+
+
+
+
+
+
+
+ List Group
+ contextual classes
+
+
+
+ Cras justo odio
+ Dapibus ac facilisis in
+ Morbi leo risus
+ Porta ac consectetur ac
+
+
+
+
+
+
+
+
+
+ List Group
+ anchors
+
+
+ Be sure to not use the standard .btn
classes here .
+
+ Cras justo odio
+ Dapibus ac facilisis in
+ Morbi leo risus
+ Porta ac consectetur ac
+ Vestibulum at eros
+
+
+
+
+
+
+
+
+ List Group
+ buttons
+
+
+
+ Cras justo odio
+ Dapibus ac facilisis in
+ Morbi leo risus
+ Porta ac consectetur ac
+ Vestibulum at eros
+
+
+
+
+
+
+
+
+
+ List Group
+ custom content
+
+
+
+
+ List group item heading
+
+ Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.
+
+
+
+ List group item heading
+
+ Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.
+
+
+
+ List group item heading
+
+ Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.
+
+
+
+
+
+
+
+
+
+
+
+ List Group with TabPanes
+
+ NEW
+
+
+
+
+
+
+ this.toggle(0)} action active={this.state.activeTab === 0} >Home
+ this.toggle(1)} action active={this.state.activeTab === 1} >Profile
+ this.toggle(2)} action active={this.state.activeTab === 2} >Messages
+ this.toggle(3)} action active={this.state.activeTab === 3} >Settings
+
+
+
+
+
+ Velit aute mollit ipsum ad dolor consectetur nulla officia culpa adipisicing exercitation fugiat tempor. Voluptate deserunt sit sunt
+ nisi aliqua fugiat proident ea ut. Mollit voluptate reprehenderit occaecat nisi ad non minim
+ tempor sunt voluptate consectetur exercitation id ut nulla. Ea et fugiat aliquip nostrud sunt incididunt consectetur culpa aliquip
+ eiusmod dolor. Anim ad Lorem aliqua in cupidatat nisi enim eu nostrud do aliquip veniam minim.
+
+
+ Cupidatat quis ad sint excepteur laborum in esse qui. Et excepteur consectetur ex nisi eu do cillum ad laborum. Mollit et eu officia
+ dolore sunt Lorem culpa qui commodo velit ex amet id ex. Officia anim incididunt laboris deserunt
+ anim aute dolor incididunt veniam aute dolore do exercitation. Dolor nisi culpa ex ad irure in elit eu dolore. Ad laboris ipsum
+ reprehenderit irure non commodo enim culpa commodo veniam incididunt veniam ad.
+
+
+ Ut ut do pariatur aliquip aliqua aliquip exercitation do nostrud commodo reprehenderit aute ipsum voluptate. Irure Lorem et laboris
+ nostrud amet cupidatat cupidatat anim do ut velit mollit consequat enim tempor. Consectetur
+ est minim nostrud nostrud consectetur irure labore voluptate irure. Ipsum id Lorem sit sint voluptate est pariatur eu ad cupidatat et
+ deserunt culpa sit eiusmod deserunt. Consectetur et fugiat anim do eiusmod aliquip nulla
+ laborum elit adipisicing pariatur cillum.
+
+
+ Irure enim occaecat labore sit qui aliquip reprehenderit amet velit. Deserunt ullamco ex elit nostrud ut dolore nisi officia magna
+ sit occaecat laboris sunt dolor. Nisi eu minim cillum occaecat aute est cupidatat aliqua labore
+ aute occaecat ea aliquip sunt amet. Aute mollit dolor ut exercitation irure commodo non amet consectetur quis amet culpa. Quis ullamco
+ nisi amet qui aute irure eu. Magna labore dolor quis ex labore id nostrud deserunt dolor
+ eiusmod eu pariatur culpa mollit in irure.
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ListGroups;
diff --git a/src/views/Base/ListGroups/ListGroups.test.js b/src/views/Base/ListGroups/ListGroups.test.js
new file mode 100644
index 0000000..139eccc
--- /dev/null
+++ b/src/views/Base/ListGroups/ListGroups.test.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import ListGroups from './ListGroups';
+import {mount} from 'enzyme/build';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+it('toggle click without crashing', () => {
+ const wrapper = mount(
);
+ for (let i=0; i<4; i++) {
+ let ListGroup = wrapper.find('#list-tab .list-group-item-action.list-group-item').at(i);
+ ListGroup.simulate('click');
+ expect(wrapper.state().activeTab).toEqual(i);
+ }
+ wrapper.unmount()
+});
diff --git a/src/views/Base/ListGroups/package.json b/src/views/Base/ListGroups/package.json
new file mode 100644
index 0000000..8c1e657
--- /dev/null
+++ b/src/views/Base/ListGroups/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "ListGroups",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./ListGroups.js"
+}
diff --git a/src/views/Base/Navbars/Navbars.js b/src/views/Base/Navbars/Navbars.js
new file mode 100644
index 0000000..5fc675b
--- /dev/null
+++ b/src/views/Base/Navbars/Navbars.js
@@ -0,0 +1,118 @@
+import React, { Component } from 'react';
+import {
+ Card,
+ CardBody,
+ CardHeader,
+ Collapse,
+ DropdownItem,
+ DropdownMenu,
+ DropdownToggle,
+ Nav,
+ Navbar,
+ NavbarBrand,
+ NavbarToggler,
+ NavItem,
+ NavLink,
+ UncontrolledDropdown,
+} from 'reactstrap';
+
+class Navbars extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.toggleNavbar = this.toggleNavbar.bind(this);
+ this.state = {
+ isOpen: false,
+ collapsed: true,
+ };
+ }
+
+ toggle() {
+ this.setState({
+ isOpen: !this.state.isOpen,
+ });
+ }
+
+ toggleNavbar() {
+ this.setState({
+ collapsed: !this.state.collapsed,
+ });
+ }
+
+ render() {
+ return (
+
+
+
+ Navbar
+
+
+
+
+ Bootstrap
+
+
+
+
+ Components
+
+
+ Github
+
+
+ {/*Warning: React does not recognize the `inNavbar` prop on a DOM element.*/}
+ {/*waiting for reactstrap@5.0.0-alpha.5*/}
+
+ Options
+
+
+
+ Option 1
+
+
+ Option 2
+
+
+
+ Reset
+
+
+
+
+
+
+
+
+
+
+ Navbar Toggler
+
+
+
+ Bootstrap
+
+
+
+
+ Components
+
+
+ Github
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Navbars;
\ No newline at end of file
diff --git a/src/views/Base/Navbars/Navbars.test.js b/src/views/Base/Navbars/Navbars.test.js
new file mode 100644
index 0000000..aa7aace
--- /dev/null
+++ b/src/views/Base/Navbars/Navbars.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Navbars from './Navbars';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Navbars/package.json b/src/views/Base/Navbars/package.json
new file mode 100644
index 0000000..06907ae
--- /dev/null
+++ b/src/views/Base/Navbars/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Navbars",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Navbars.js"
+}
diff --git a/src/views/Base/Navs/Navs.js b/src/views/Base/Navs/Navs.js
new file mode 100644
index 0000000..d132dbc
--- /dev/null
+++ b/src/views/Base/Navs/Navs.js
@@ -0,0 +1,159 @@
+import React, { Component } from 'react';
+import { Card, CardBody, CardHeader, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Nav, NavItem, NavLink } from 'reactstrap';
+
+class Navs extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ dropdownOpen: [false, false],
+ };
+ }
+
+ toggle(i) {
+ const newArray = this.state.dropdownOpen.map((element, index) => {
+ return (index === i ? !element : false);
+ });
+ this.setState({
+ dropdownOpen: newArray,
+ });
+ }
+
+ render() {
+ return (
+
+
+
+ Navs
+
+
+
+ List Based
+
+
+ Link
+
+
+ Link
+
+
+ Another Link
+
+
+ Disabled Link
+
+
+
+ Link Based
+
+ Link Link Another Link Disabled
+ Link
+
+
+
+
+
+ Navs Tabs
+
+
+
+
+ Link
+
+ {this.toggle(0);}}>
+
+ Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+
+ Link
+
+
+ Another Link
+
+
+ Disabled Link
+
+
+
+
+
+
+ Navs Pills
+
+
+
+
+ Link
+
+ {this.toggle(1);}}>
+
+ Dropdown
+
+
+ Header
+ Action
+ Another Action
+
+ Another Action
+
+
+
+ Link
+
+
+ Another Link
+
+
+ Disabled Link
+
+
+
+
+
+
+ Navs Vertical
+
+
+ List Based
+
+
+ Link
+
+
+ Link
+
+
+ Another Link
+
+
+ Disabled Link
+
+
+
+ Link based
+
+ Link Link Another Link Disabled
+ Link
+
+
+
+
+ );
+ }
+}
+
+export default Navs;
\ No newline at end of file
diff --git a/src/views/Base/Navs/Navs.test.js b/src/views/Base/Navs/Navs.test.js
new file mode 100644
index 0000000..380e873
--- /dev/null
+++ b/src/views/Base/Navs/Navs.test.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Navs from './Navs';
+import {mount} from 'enzyme/build';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+it('toggle click without crashing', () => {
+ const wrapper = mount(
);
+ for (let i=0; i<2; i++) {
+ let Nav = wrapper.find('a.dropdown-toggle').at(i);
+ Nav.simulate('click');
+ expect(wrapper.state().dropdownOpen[i]).toEqual(true);
+ }
+ wrapper.unmount()
+});
diff --git a/src/views/Base/Navs/package.json b/src/views/Base/Navs/package.json
new file mode 100644
index 0000000..5f7753d
--- /dev/null
+++ b/src/views/Base/Navs/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Navs",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Navs.js"
+}
diff --git a/src/views/Base/Paginations/Paginations.test.js b/src/views/Base/Paginations/Paginations.test.js
new file mode 100644
index 0000000..02048b6
--- /dev/null
+++ b/src/views/Base/Paginations/Paginations.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Paginations from './Pagnations';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Paginations/Pagnations.js b/src/views/Base/Paginations/Pagnations.js
new file mode 100644
index 0000000..2489c9e
--- /dev/null
+++ b/src/views/Base/Paginations/Pagnations.js
@@ -0,0 +1,177 @@
+import React, { Component } from 'react';
+import { Card, CardBody, CardHeader, Pagination, PaginationItem, PaginationLink } from 'reactstrap';
+
+class Paginations extends Component {
+
+ render() {
+ return (
+
+
+
+ Pagination
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+ Pagination
+ disabled and active states
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+ Pagination
+ sizing
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Paginations;
diff --git a/src/views/Base/Paginations/package.json b/src/views/Base/Paginations/package.json
new file mode 100644
index 0000000..1e89ea2
--- /dev/null
+++ b/src/views/Base/Paginations/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Pagnations",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Pagnations.js"
+}
diff --git a/src/views/Base/Popovers/Popovers.js b/src/views/Base/Popovers/Popovers.js
new file mode 100644
index 0000000..44748a2
--- /dev/null
+++ b/src/views/Base/Popovers/Popovers.js
@@ -0,0 +1,108 @@
+import React, { Component } from 'react';
+import { Button, Card, CardBody, CardHeader, Popover, PopoverBody, PopoverHeader } from 'reactstrap';
+
+class PopoverItem extends Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ popoverOpen: false,
+ };
+ }
+
+ toggle() {
+ this.setState({
+ popoverOpen: !this.state.popoverOpen,
+ });
+ }
+
+ render() {
+ return (
+
+
+ {this.props.item.text}
+
+
+ Popover Title
+ Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.
+
+
+ );
+ }
+}
+
+class Popovers extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ popoverOpen: false,
+ popovers: [
+ {
+ placement: 'top',
+ text: 'Top',
+ },
+ {
+ placement: 'bottom',
+ text: 'Bottom',
+ },
+ {
+ placement: 'left',
+ text: 'Left',
+ },
+ {
+ placement: 'right',
+ text: 'Right',
+ },
+ ],
+ };
+ }
+
+ toggle() {
+ this.setState({
+ popoverOpen: !this.state.popoverOpen,
+ });
+ }
+
+ render() {
+ return (
+
+
+
+ Popovers
+
+
+
+
+ Launch Popover
+
+
+ Popover Title
+ Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.
+
+
+
+
+
+ Popovers
+ list
+
+
+ {this.state.popovers.map((popover, i) => {
+ return ;
+ })}
+
+
+
+ );
+ }
+}
+
+export default Popovers;
diff --git a/src/views/Base/Popovers/Popovers.test.js b/src/views/Base/Popovers/Popovers.test.js
new file mode 100644
index 0000000..ec191a7
--- /dev/null
+++ b/src/views/Base/Popovers/Popovers.test.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Popovers from './Popovers';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ document.body.appendChild(div);
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Popovers/package.json b/src/views/Base/Popovers/package.json
new file mode 100644
index 0000000..37a3e47
--- /dev/null
+++ b/src/views/Base/Popovers/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Popovers",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Popovers.js"
+}
diff --git a/src/views/Base/ProgressBar/ProgressBar.js b/src/views/Base/ProgressBar/ProgressBar.js
new file mode 100644
index 0000000..a234b1d
--- /dev/null
+++ b/src/views/Base/ProgressBar/ProgressBar.js
@@ -0,0 +1,167 @@
+import React, { Component } from 'react';
+import { Card, CardBody, CardHeader, Progress } from 'reactstrap';
+
+class ProgressBar extends Component {
+
+ render() {
+ return (
+
+
+
+ Progress
+
+
+
+ 0%
+
+ 25%
+
+ 50%
+
+ 75%
+
+ 100%
+
+ Multiple bars
+
+
+
+
+
+
+
+
+
+
+
+ Progress
+ color variants
+
+
+
+
+
+
+
+
+
+
+
+ Progress
+ labels
+
+
+ 25%
+ 1/2
+ You're almost there!
+ You did it!
+
+ Meh
+ Wow!
+ Cool
+ 20%
+ !!
+
+
+
+
+
+ Progress
+ striped
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Progress
+ animated
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Progress
+ multiple bars / stacked
+
+
+ Plain
+
+
+
+
+
+
+
+ With Labels
+
+ Meh
+ Wow!
+ 25%
+ LOOK OUT!!
+
+ Stripes and Animations
+
+ Stripes
+ Animated Stripes
+ Plain
+
+
+
+
+
+ Progress
+ max value
+
+
+ 1 of 5
+
+ 50 of 135
+
+ 75 of 111
+
+ 463 of 500
+
+
+ Various (40) of 55
+
+ 5
+ 15
+ 10
+ 10
+
+
+
+
+ );
+ }
+}
+
+export default ProgressBar;
\ No newline at end of file
diff --git a/src/views/Base/ProgressBar/ProgressBar.test.js b/src/views/Base/ProgressBar/ProgressBar.test.js
new file mode 100644
index 0000000..1dffea7
--- /dev/null
+++ b/src/views/Base/ProgressBar/ProgressBar.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import ProgressBar from './ProgressBar';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/ProgressBar/package.json b/src/views/Base/ProgressBar/package.json
new file mode 100644
index 0000000..759527b
--- /dev/null
+++ b/src/views/Base/ProgressBar/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Progress Bar",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./ProgressBar.js"
+}
diff --git a/src/views/Base/Switches/Switches.js b/src/views/Base/Switches/Switches.js
new file mode 100644
index 0000000..730e94e
--- /dev/null
+++ b/src/views/Base/Switches/Switches.js
@@ -0,0 +1,494 @@
+import React, { Component } from 'react';
+import { Card, CardBody, CardHeader, Col, Row, Table } from 'reactstrap';
+import { AppSwitch } from '@coreui/react'
+
+class Switches extends Component {
+ render() {
+ return (
+
+
+
+
+
+
+ Switch default
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch pills
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3d Switch
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3d Switch disabled
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3d Switch outline="alt"
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3d Switch label
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3d Switch outline="alt" label
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3d Switch outline="alt" label
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch outline
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch outline pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch outline alternative
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch outline alternative - pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline alternative pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline alternative pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline alternative
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline alternative pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline alternative
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Switch with text outline alternative pills
+ {' '}CoreUI Pro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sizes
+
+
+
+
+
+ Size
+ Example
+ Props
+
+
+
+
+
+ Large
+
+
+
+
+
+ Add size={'lg'}
+
+
+
+
+ Normal
+
+
+
+
+
+ -
+
+
+
+
+ Small
+
+
+
+
+
+ Add size={'sm'}
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Switches;
diff --git a/src/views/Base/Switches/Switches.test.js b/src/views/Base/Switches/Switches.test.js
new file mode 100644
index 0000000..e48f76a
--- /dev/null
+++ b/src/views/Base/Switches/Switches.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Switches from './Switches';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Switches/package.json b/src/views/Base/Switches/package.json
new file mode 100644
index 0000000..fa1799a
--- /dev/null
+++ b/src/views/Base/Switches/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Switches",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Switches.js"
+}
diff --git a/src/views/Base/Tables/Tables.js b/src/views/Base/Tables/Tables.js
new file mode 100644
index 0000000..eae3ef1
--- /dev/null
+++ b/src/views/Base/Tables/Tables.js
@@ -0,0 +1,393 @@
+import React, { Component } from 'react';
+import { Badge, Card, CardBody, CardHeader, Col, Pagination, PaginationItem, PaginationLink, Row, Table } from 'reactstrap';
+
+class Tables extends Component {
+ render() {
+ return (
+
+
+
+
+
+ Simple Table
+
+
+
+
+
+ Username
+ Date registered
+ Role
+ Status
+
+
+
+
+ Samppa Nori
+ 2012/01/01
+ Member
+
+ Active
+
+
+
+ Estavan Lykos
+ 2012/02/01
+ Staff
+
+ Banned
+
+
+
+ Chetan Mohamed
+ 2012/02/01
+ Admin
+
+ Inactive
+
+
+
+ Derick Maximinus
+ 2012/03/01
+ Member
+
+ Pending
+
+
+
+ Friderik Dávid
+ 2012/01/21
+ Staff
+
+ Active
+
+
+
+
+
+
+
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+ Striped Table
+
+
+
+
+
+ Username
+ Date registered
+ Role
+ Status
+
+
+
+
+ Yiorgos Avraamu
+ 2012/01/01
+ Member
+
+ Active
+
+
+
+ Avram Tarasios
+ 2012/02/01
+ Staff
+
+ Banned
+
+
+
+ Quintin Ed
+ 2012/02/01
+ Admin
+
+ Inactive
+
+
+
+ Enéas Kwadwo
+ 2012/03/01
+ Member
+
+ Pending
+
+
+
+ Agapetus Tadeáš
+ 2012/01/21
+ Staff
+
+ Active
+
+
+
+
+
+ Prev
+
+ 1
+
+ 2
+ 3
+ 4
+ Next
+
+
+
+
+
+
+
+
+
+
+
+ Condensed Table
+
+
+
+
+
+ Username
+ Date registered
+ Role
+ Status
+
+
+
+
+ Carwyn Fachtna
+ 2012/01/01
+ Member
+
+ Active
+
+
+
+ Nehemiah Tatius
+ 2012/02/01
+ Staff
+
+ Banned
+
+
+
+ Ebbe Gemariah
+ 2012/02/01
+ Admin
+
+ Inactive
+
+
+
+ Eustorgios Amulius
+ 2012/03/01
+ Member
+
+ Pending
+
+
+
+ Leopold Gáspár
+ 2012/01/21
+ Staff
+
+ Active
+
+
+
+
+
+ Prev
+
+ 1
+
+ 2
+ 3
+ 4
+ Next
+
+
+
+
+
+
+
+
+ Bordered Table
+
+
+
+
+
+ Username
+ Date registered
+ Role
+ Status
+
+
+
+
+ Pompeius René
+ 2012/01/01
+ Member
+
+ Active
+
+
+
+ Paĉjo Jadon
+ 2012/02/01
+ Staff
+
+ Banned
+
+
+
+ Micheal Mercurius
+ 2012/02/01
+ Admin
+
+ Inactive
+
+
+
+ Ganesha Dubhghall
+ 2012/03/01
+ Member
+
+ Pending
+
+
+
+ Hiroto Šimun
+ 2012/01/21
+ Staff
+
+ Active
+
+
+
+
+
+ Prev
+
+ 1
+
+ 2
+ 3
+ 4
+ Next
+
+
+
+
+
+
+
+
+
+
+
+ Combined All Table
+
+
+
+
+
+ Username
+ Date registered
+ Role
+ Status
+
+
+
+
+ Vishnu Serghei
+ 2012/01/01
+ Member
+
+ Active
+
+
+
+ Zbyněk Phoibos
+ 2012/02/01
+ Staff
+
+ Banned
+
+
+
+ Einar Randall
+ 2012/02/01
+ Admin
+
+ Inactive
+
+
+
+ Félix Troels
+ 2012/03/01
+ Member
+
+ Pending
+
+
+
+ Aulus Agmundr
+ 2012/01/21
+ Staff
+
+ Active
+
+
+
+
+
+
+ Prev
+
+ 1
+
+ 2
+ 3
+ 4
+ Next
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Tables;
diff --git a/src/views/Base/Tables/Tables.test.js b/src/views/Base/Tables/Tables.test.js
new file mode 100644
index 0000000..602391b
--- /dev/null
+++ b/src/views/Base/Tables/Tables.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Tables from './Tables';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Tables/package.json b/src/views/Base/Tables/package.json
new file mode 100644
index 0000000..b6ff309
--- /dev/null
+++ b/src/views/Base/Tables/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Tables",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Tables.js"
+}
diff --git a/src/views/Base/Tabs/Tabs.js b/src/views/Base/Tabs/Tabs.js
new file mode 100644
index 0000000..d99806a
--- /dev/null
+++ b/src/views/Base/Tabs/Tabs.js
@@ -0,0 +1,183 @@
+import React, {Component} from 'react';
+import {Badge, Col, Nav, NavItem, NavLink, Row, TabContent, TabPane} from 'reactstrap';
+import classnames from 'classnames';
+
+class Tabs extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ activeTab: new Array(4).fill('1'),
+ };
+ }
+
+ lorem() {
+ return 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit.'
+ }
+
+ toggle(tabPane, tab) {
+ const newArray = this.state.activeTab.slice()
+ newArray[tabPane] = tab
+ this.setState({
+ activeTab: newArray,
+ });
+ }
+
+ tabPane() {
+ return (
+ <>
+
+ {`1. ${this.lorem()}`}
+
+
+ {`2. ${this.lorem()}`}
+
+
+ {`3. ${this.lorem()}`}
+
+ >
+ );
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ { this.toggle(0, '1'); }}
+ >
+ Home
+
+
+
+ { this.toggle(0, '2'); }}
+ >
+ Profile
+
+
+
+ { this.toggle(0, '3'); }}
+ >
+ Messages
+
+
+
+
+ {this.tabPane()}
+
+
+
+
+
+ { this.toggle(1, '1'); }}
+ >
+
+
+
+
+ { this.toggle(1, '2'); }}
+ >
+
+
+
+
+ { this.toggle(1, '3'); }}
+ >
+
+
+
+
+
+ {this.tabPane()}
+
+
+
+
+
+ { this.toggle(2, '1'); }}
+ >
+ Calculator
+
+
+
+ { this.toggle(2, '2'); }}
+ >
+ Shopping cart
+
+
+
+ { this.toggle(2,'3'); }}
+ >
+ Charts
+
+
+
+
+ {this.tabPane()}
+
+
+
+
+
+ { this.toggle(3, '1'); }}
+ >
+
+ Calc
+ {'\u00A0'}New
+
+
+
+ { this.toggle(3, '2'); }}
+ >
+
+ Cart
+ {'\u00A0'}29
+
+
+
+ { this.toggle(3, '3'); }} >
+
+ Charts
+
+
+
+
+ {this.tabPane()}
+
+
+
+
+ );
+ }
+}
+
+export default Tabs;
diff --git a/src/views/Base/Tabs/Tabs.test.js b/src/views/Base/Tabs/Tabs.test.js
new file mode 100644
index 0000000..1293edd
--- /dev/null
+++ b/src/views/Base/Tabs/Tabs.test.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Tabs from './Tabs';
+import {mount} from 'enzyme/build';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+it('toggle click without crashing', () => {
+ const wrapper = mount(
);
+ for (let pane=0; pane<4; pane++) {
+ for( let tabId=1; tabId<4; tabId++) {
+ let Tab = wrapper.find('.nav-tabs .nav-item .nav-link').at((3*pane)+tabId-1);
+ Tab.simulate('click');
+ expect(wrapper.state().activeTab[pane]).toEqual((tabId).toString());
+ }
+ }
+ wrapper.unmount()
+});
diff --git a/src/views/Base/Tabs/package.json b/src/views/Base/Tabs/package.json
new file mode 100644
index 0000000..162e63b
--- /dev/null
+++ b/src/views/Base/Tabs/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Tabs",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Tabs.js"
+}
diff --git a/src/views/Base/Tooltips/Tooltips.js b/src/views/Base/Tooltips/Tooltips.js
new file mode 100644
index 0000000..64be32c
--- /dev/null
+++ b/src/views/Base/Tooltips/Tooltips.js
@@ -0,0 +1,134 @@
+import React, { Component } from 'react';
+import { Button, Card, CardBody, CardHeader, Tooltip, UncontrolledTooltip } from 'reactstrap';
+
+class TooltipItem extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ tooltipOpen: false,
+ };
+ }
+
+ toggle() {
+ this.setState({
+ tooltipOpen: !this.state.tooltipOpen,
+ });
+ }
+
+ render() {
+ return (
+
+
+ {this.props.item.text}
+
+
+ Tooltip Content!
+
+
+ );
+ }
+}
+
+class Tooltips extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ tooltipOpen: [false, false],
+ tooltips: [
+ {
+ placement: 'top',
+ text: 'Top',
+ },
+ {
+ placement: 'bottom',
+ text: 'Bottom',
+ },
+ {
+ placement: 'left',
+ text: 'Left',
+ },
+ {
+ placement: 'right',
+ text: 'Right',
+ },
+ ],
+ };
+ }
+
+ toggle(i) {
+ const newArray = this.state.tooltipOpen.map((element, index) => {
+ return (index === i ? !element : false);
+ });
+ this.setState({
+ tooltipOpen: newArray,
+ });
+ }
+
+ render() {
+ return (
+
+
+
+ Tooltips
+
+
+
+ {/*eslint-disable-next-line*/}
+ Somewhere in here is a tooltip .
+ {this.toggle(0);}}>
+ Hello world!
+
+
+
+
+
+ Tooltip
+ disable autohide
+
+
+ {/*eslint-disable-next-line*/}
+ Sometimes you need to allow users to select text within a tooltip .
+ {this.toggle(1);}}>
+ Try to select this text!
+
+
+
+
+
+ Tooltip
+ list
+
+
+ {this.state.tooltips.map((tooltip, i) => {
+ return ;
+ })}
+
+
+
+
+ Tooltip
+ uncontrolled
+
+
+ {/*eslint-disable-next-line*/}
+ Somewhere in here is a tooltip .
+
+ Hello world!
+
+
+
+
+ );
+ }
+}
+
+export default Tooltips;
diff --git a/src/views/Base/Tooltips/Tooltips.test.js b/src/views/Base/Tooltips/Tooltips.test.js
new file mode 100644
index 0000000..cdbca71
--- /dev/null
+++ b/src/views/Base/Tooltips/Tooltips.test.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Tooltips from './Tooltips';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ document.body.appendChild(div);
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Base/Tooltips/package.json b/src/views/Base/Tooltips/package.json
new file mode 100644
index 0000000..61be3db
--- /dev/null
+++ b/src/views/Base/Tooltips/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Tooltips",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Tooltips.js"
+}
diff --git a/src/views/Base/index.js b/src/views/Base/index.js
new file mode 100644
index 0000000..a50ada9
--- /dev/null
+++ b/src/views/Base/index.js
@@ -0,0 +1,22 @@
+import Breadcrumbs from './Breadcrumbs';
+import Cards from './Cards';
+import Carousels from './Carousels';
+import Collapses from './Collapses';
+import Dropdowns from './Dropdowns';
+import Forms from './Forms';
+import Jumbotrons from './Jumbotrons';
+import ListGroups from './ListGroups';
+import Navbars from './Navbars';
+import Navs from './Navs';
+import Popovers from './Popovers';
+import Paginations from './Paginations';
+import ProgressBar from './ProgressBar';
+import Switches from './Switches';
+import Tables from './Tables';
+import Tabs from './Tabs';
+import Tooltips from './Tooltips';
+
+export {
+ Breadcrumbs, Cards, Carousels, Collapses, Dropdowns, Forms, Jumbotrons, ListGroups, Navbars, Navs, Popovers, ProgressBar, Switches, Tables, Tabs, Tooltips, Paginations
+};
+
diff --git a/src/views/BaseLayers/BaseLayers.css b/src/views/BaseLayers/BaseLayers.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/views/BaseLayers/BaseLayers.js b/src/views/BaseLayers/BaseLayers.js
new file mode 100644
index 0000000..4ded96c
--- /dev/null
+++ b/src/views/BaseLayers/BaseLayers.js
@@ -0,0 +1,40 @@
+import React, { Component } from 'react'
+// import './BaseLayers.css'
+import DataTable from '../../components/DataTable'
+
+const data = [
+ {
+ "id": 0,
+ "name": "Item name 0",
+ "price": 2100
+ },
+ {
+ "id": 1,
+ "name": "Item name 1",
+ "price": 2101
+ },
+ {
+ "id": 2,
+ "name": "Item name 2",
+ "price": 2102
+ },
+ {
+ "id": 3,
+ "name": "Item name 3",
+ "price": 2103
+ }];
+
+class BaseLayers extends Component {
+ render() {
+ return (
+
+
+
+ )
+ }
+}
+
+export default BaseLayers;
\ No newline at end of file
diff --git a/src/views/BaseLayers/package.json b/src/views/BaseLayers/package.json
new file mode 100644
index 0000000..3ba7d28
--- /dev/null
+++ b/src/views/BaseLayers/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "BaseLayers",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./BaseLayers.js"
+}
diff --git a/src/views/Buttons/BrandButtons/BrandButtons.js b/src/views/Buttons/BrandButtons/BrandButtons.js
new file mode 100644
index 0000000..c8f60c2
--- /dev/null
+++ b/src/views/Buttons/BrandButtons/BrandButtons.js
@@ -0,0 +1,324 @@
+import React, { Component } from 'react';
+import { Button, Card, CardBody, CardHeader, Col, Row } from 'reactstrap';
+
+class BrandButtons extends Component {
+ render() {
+ return (
+
+
+
+
+
+
+ Brand Button
+ Usage ex.
+
+ <Button className="btn-facebook btn-brand"><i className="fa fa-facebook"></i><span>Facebook</span></Button>
+
+
+
+ Size Small
+ Add this class .btn-sm
+
+
+ Facebook
+ Twitter
+ LinkedIn
+ Flickr
+ Tumblr
+ Xing
+ Github
+ HTML5
+ OpenID
+ StackOverflow
+ CSS3
+ YouTube
+ Dribbble
+ Google+
+ Instagram
+ Pinterest
+ VK
+ Yahoo
+ Behance
+ Dropbox
+ Reddit
+ Spotify
+ Vine
+ Forsquare
+ Vimeo
+
+ Size Normal
+
+ Facebook
+ Twitter
+ LinkedIn
+ Flickr
+ Tumblr
+ Xing
+ Github
+ HTML5
+ OpenID
+ StackOverflow
+ CSS3
+ YouTube
+ Dribbble
+ Google+
+ Instagram
+ Pinterest
+ VK
+ Yahoo
+ Behance
+ Dropbox
+ Reddit
+ Spotify
+ Vine
+ Forsquare
+ Vimeo
+
+ Size Large
+ Add this class .btn-lg
+
+
+ Facebook
+ Twitter
+ LinkedIn
+ Flickr
+ Tumblr
+ Xing
+ Github
+ HTML5
+ OpenID
+ StackOverflow
+ CSS3
+ YouTube
+ Dribbble
+ Google+
+ Instagram
+ Pinterest
+ VK
+ Yahoo
+ Behance
+ Dropbox
+ Reddit
+ Spotify
+ Vine
+ Forsquare
+ Vimeo
+
+
+
+
+
+
+
+
+
+ Brand Button
+ Icons only. Usage ex.
+
+ <Button className="btn-facebook btn-brand icon"><i className="fa fa-facebook"></i></Button>
+
+
+
+ Size Small
+ Add this class .btn-sm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Size Normal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Size Large
+ Add this class .btn-lg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Brand Button
+ Text only. Usage ex.
+
+ <Button className="btn-facebook btn-brand text"><span>Facebook</span></Button>
+
+
+
+ Size Small
+ Add this class .btn-sm
+
+
+ Facebook
+ Twitter
+ LinkedIn
+ Flickr
+ Tumblr
+ Xing
+ Github
+ HTML5
+ OpenID
+ StackOverflow
+ CSS3
+ YouTube
+ Dribbble
+ Google+
+ Instagram
+ Pinterest
+ VK
+ Yahoo
+ Behance
+ Dropbox
+ Reddit
+ Spotify
+ Vine
+ Forsquare
+ Vimeo
+
+ Size Normal
+
+ Facebook
+ Twitter
+ LinkedIn
+ Flickr
+ Tumblr
+ Xing
+ Github
+ HTML5
+ OpenID
+ StackOverflow
+ CSS3
+ YouTube
+ Dribbble
+ Google+
+ Instagram
+ Pinterest
+ VK
+ Yahoo
+ Behance
+ Dropbox
+ Reddit
+ Spotify
+ Vine
+ Forsquare
+ Vimeo
+
+ Size Large
+ Add this class .btn-lg
+
+
+ Facebook
+ Twitter
+ LinkedIn
+ Flickr
+ Tumblr
+ Xing
+ Github
+ HTML5
+ OpenID
+ StackOverflow
+ CSS3
+ YouTube
+ Dribbble
+ Google+
+ Instagram
+ Pinterest
+ VK
+ Yahoo
+ Behance
+ Dropbox
+ Reddit
+ Spotify
+ Vine
+ Forsquare
+ Vimeo
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default BrandButtons;
diff --git a/src/views/Buttons/BrandButtons/BrandButtons.test.js b/src/views/Buttons/BrandButtons/BrandButtons.test.js
new file mode 100644
index 0000000..24c7818
--- /dev/null
+++ b/src/views/Buttons/BrandButtons/BrandButtons.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import BrandButtons from './';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Buttons/BrandButtons/package.json b/src/views/Buttons/BrandButtons/package.json
new file mode 100644
index 0000000..cc1e6a0
--- /dev/null
+++ b/src/views/Buttons/BrandButtons/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "BrandButtons",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./BrandButtons.js"
+}
diff --git a/src/views/Buttons/ButtonDropdowns/ButtonDropdowns.js b/src/views/Buttons/ButtonDropdowns/ButtonDropdowns.js
new file mode 100644
index 0000000..4a00128
--- /dev/null
+++ b/src/views/Buttons/ButtonDropdowns/ButtonDropdowns.js
@@ -0,0 +1,290 @@
+import React, { Component } from 'react';
+import { Button, ButtonDropdown, Card, CardBody, CardHeader, Col, DropdownItem, DropdownMenu, DropdownToggle, Row } from 'reactstrap';
+
+class ButtonDropdowns extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ dropdownOpen: new Array(19).fill(false),
+ };
+ }
+
+ toggle(i) {
+ const newArray = this.state.dropdownOpen.map((element, index) => { return (index === i ? !element : false); });
+ this.setState({
+ dropdownOpen: newArray,
+ });
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ Button Dropdown
+
+
+
+ { this.toggle(0); }}>
+
+ Button Dropdown
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+
+
+
+
+ Single button dropdowns
+
+
+ { this.toggle(1); }}>
+
+ Primary
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(2); }}>
+
+ Secondary
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(3); }}>
+
+ Success
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(4); }}>
+
+ Info
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(5); }}>
+
+ Warning
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(6); }}>
+
+ Danger
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+
+
+
+
+ Split button dropdowns
+
+
+ { this.toggle(7); }}>
+ Primary
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(8); }}>
+ Secondary
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(9); }}>
+ Success
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(10); }}>
+ Info
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(11); }}>
+ Warning
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+ { this.toggle(12); }}>
+ Danger
+
+
+ Header
+ Action Disabled
+ Action
+
+ Another Action
+
+
+
+
+
+
+ Dropdown directions
+
+
+ { this.toggle(13); }}>
+
+ Direction Up
+
+
+ Header
+ Action Disabled
+ Action
+ Another Action
+
+
+ { this.toggle(14); }}>
+
+ Direction Left
+
+
+ Header
+ Action Disabled
+ Action
+ Another Action
+
+
+ { this.toggle(15); }}>
+
+ Direction Right
+
+
+ Header
+ Action Disabled
+ Action
+ Another Action
+
+
+ { this.toggle(16); }}>
+
+ Default Down
+
+
+ Header
+ Action Disabled
+ Action
+ Another Action
+
+
+
+
+
+
+ Button Dropdown sizing
+
+
+ { this.toggle(17); }}>
+
+ Large Button
+
+
+ Header
+ Action Disabled
+ Action
+ Another Action
+
+
+ { this.toggle(18); }}>
+
+ Small Button
+
+
+ Header
+ Action Disabled
+ Action
+ Another Action
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ButtonDropdowns;
diff --git a/src/views/Buttons/ButtonDropdowns/ButtonDropdowns.test.js b/src/views/Buttons/ButtonDropdowns/ButtonDropdowns.test.js
new file mode 100644
index 0000000..62f8f37
--- /dev/null
+++ b/src/views/Buttons/ButtonDropdowns/ButtonDropdowns.test.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { mount } from 'enzyme'
+import ButtonDropdowns from './ButtonDropdowns';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+it('toggle click without crashing', () => {
+ const wrapper = mount(
);
+ for (let i=0; i<19; i++) {
+ let ButtonDropdown = wrapper.find('button.dropdown-toggle').at(i);
+ ButtonDropdown.simulate('click');
+ expect(wrapper.state().dropdownOpen[i]).toEqual(true);
+ }
+ wrapper.unmount()
+});
+
diff --git a/src/views/Buttons/ButtonDropdowns/package.json b/src/views/Buttons/ButtonDropdowns/package.json
new file mode 100644
index 0000000..5bd5b4c
--- /dev/null
+++ b/src/views/Buttons/ButtonDropdowns/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "ButtonDropdowns",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./ButtonDropdowns.js"
+}
diff --git a/src/views/Buttons/ButtonGroups/ButtonGroups.js b/src/views/Buttons/ButtonGroups/ButtonGroups.js
new file mode 100644
index 0000000..8663a67
--- /dev/null
+++ b/src/views/Buttons/ButtonGroups/ButtonGroups.js
@@ -0,0 +1,192 @@
+import React, { Component } from 'react';
+import {
+ Button,
+ ButtonDropdown,
+ ButtonGroup,
+ ButtonToolbar,
+ Card,
+ CardBody,
+ CardHeader,
+ Col,
+ DropdownItem,
+ DropdownMenu,
+ DropdownToggle,
+ Input,
+ InputGroup,
+ InputGroupAddon,
+ InputGroupText,
+ Row,
+} from 'reactstrap';
+
+class ButtonGroups extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.toggle = this.toggle.bind(this);
+ this.state = {
+ dropdownOpen: new Array(2).fill(false),
+ };
+ }
+
+ toggle(i) {
+ const newArray = this.state.dropdownOpen.map((element, index) => { return (index === i ? !element : false); });
+ this.setState({
+ dropdownOpen: newArray,
+ });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default ButtonGroups;
diff --git a/src/views/Buttons/ButtonGroups/ButtonGroups.test.js b/src/views/Buttons/ButtonGroups/ButtonGroups.test.js
new file mode 100644
index 0000000..318de31
--- /dev/null
+++ b/src/views/Buttons/ButtonGroups/ButtonGroups.test.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import ButtonGroups from './ButtonGroups';
+import {mount} from 'enzyme/build';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
+it('toggle click without crashing', () => {
+ const wrapper = mount(
);
+ for (let i=0; i<2; i++) {
+ let ButtonGroup = wrapper.find('button.dropdown-toggle').at(i);
+ ButtonGroup.simulate('click');
+ expect(wrapper.state().dropdownOpen[i]).toEqual(true);
+ }
+ wrapper.unmount()
+});
diff --git a/src/views/Buttons/ButtonGroups/package.json b/src/views/Buttons/ButtonGroups/package.json
new file mode 100644
index 0000000..0a7eb82
--- /dev/null
+++ b/src/views/Buttons/ButtonGroups/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "ButtonGroups",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./ButtonGroups.js"
+}
diff --git a/src/views/Buttons/Buttons/Buttons.js b/src/views/Buttons/Buttons/Buttons.js
new file mode 100644
index 0000000..40eb012
--- /dev/null
+++ b/src/views/Buttons/Buttons/Buttons.js
@@ -0,0 +1,669 @@
+import React, { Component } from 'react';
+import { Button, Card, CardBody, CardHeader, Col, Row } from 'reactstrap';
+
+class Buttons extends Component {
+ render() {
+ return (
+
+
+
+ Standard Buttons
+
+
+
+
+ Normal
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+ Active State
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+ Disabled
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+
+
+ Outline Buttons
+
+
+
+ Use outline
prop
+
+
+
+ Normal
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+
+
+
+ Active State
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+
+
+
+ Disabled
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+
+
+
+
+
+ Ghost Buttons
+
+
+
+ Use
+ .btn-ghost-*
class for ghost buttons.
+
+
+
+ Normal
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+
+
+
+ Active State
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+
+
+
+ Disabled
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+
+
+
+
+
+ Square Buttons
+
+
+
+ Use
+ .btn-square
class for square buttons.
+
+
+
+ Normal
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+ Active State
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+ Disabled
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+
+
+ Pill Buttons
+
+
+
+ Use
+ .btn-pill
class for pill buttons.
+
+
+
+ Normal
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+ Active State
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+ Disabled
+
+
+ Primary
+
+
+ Secondary
+
+
+ Success
+
+
+ Warning
+
+
+ Danger
+
+
+ Info
+
+
+ Light
+
+
+ Dark
+
+
+ Link
+
+
+
+
+
+
+ Sizes
+
+
+ Fancy larger or smaller buttons? Add size="lg"
or size="sm"
for additional sizes.
+
+
+ Small
+
+
+ Standard Button
+
+
+ Outline Button
+
+
+ Ghost Button
+
+
+ Square Button
+
+
+ Pill Button
+
+
+
+
+ Normal
+
+
+ Standard Button
+
+
+ Outline Button
+
+
+ Ghost Button
+
+
+ Square Button
+
+
+ Pill Button
+
+
+
+
+ Large
+
+
+ Standard Button
+
+
+ Outline Button
+
+
+ Ghost Button
+
+
+ Square Button
+
+
+ Pill Button
+
+
+
+
+
+
+ With Icons
+
+
+
+
+
+ Standard Button
+
+
+
+
+ Outline Button
+
+
+
+
+ Ghost Button
+
+
+
+
+ Square Button
+
+
+
+
+ Pill Button
+
+
+
+
+
+
+
+
+
+ Block Level Buttons
+
+
+ Add prop block
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+
+
+
+
+
+
+ Block Level Buttons
+
+
+ Add prop block
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+ Block level button
+
+
+
+
+
+ );
+ }
+}
+
+export default Buttons;
diff --git a/src/views/Buttons/Buttons/Buttons.test.js b/src/views/Buttons/Buttons/Buttons.test.js
new file mode 100644
index 0000000..9c7a2e2
--- /dev/null
+++ b/src/views/Buttons/Buttons/Buttons.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Buttons from './Buttons';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/views/Buttons/Buttons/package.json b/src/views/Buttons/Buttons/package.json
new file mode 100644
index 0000000..f061146
--- /dev/null
+++ b/src/views/Buttons/Buttons/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Buttons",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Buttons.js"
+}
diff --git a/src/views/Buttons/index.js b/src/views/Buttons/index.js
new file mode 100644
index 0000000..7945b6f
--- /dev/null
+++ b/src/views/Buttons/index.js
@@ -0,0 +1,8 @@
+import ButtonDropdowns from './ButtonDropdowns';
+import ButtonGroups from './ButtonGroups';
+import Buttons from './Buttons';
+import BrandButtons from './BrandButtons';
+
+export {
+ ButtonDropdowns, ButtonGroups, Buttons, BrandButtons
+}
diff --git a/src/views/Charts/Charts.js b/src/views/Charts/Charts.js
new file mode 100644
index 0000000..765a44f
--- /dev/null
+++ b/src/views/Charts/Charts.js
@@ -0,0 +1,255 @@
+import React, { Component } from 'react';
+import { Bar, Doughnut, Line, Pie, Polar, Radar } from 'react-chartjs-2';
+import { Card, CardBody, CardColumns, CardHeader } from 'reactstrap';
+import { CustomTooltips } from '@coreui/coreui-plugin-chartjs-custom-tooltips';
+
+const line = {
+ labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
+ datasets: [
+ {
+ label: 'My First dataset',
+ fill: false,
+ lineTension: 0.1,
+ backgroundColor: 'rgba(75,192,192,0.4)',
+ borderColor: 'rgba(75,192,192,1)',
+ borderCapStyle: 'butt',
+ borderDash: [],
+ borderDashOffset: 0.0,
+ borderJoinStyle: 'miter',
+ pointBorderColor: 'rgba(75,192,192,1)',
+ pointBackgroundColor: '#fff',
+ pointBorderWidth: 1,
+ pointHoverRadius: 5,
+ pointHoverBackgroundColor: 'rgba(75,192,192,1)',
+ pointHoverBorderColor: 'rgba(220,220,220,1)',
+ pointHoverBorderWidth: 2,
+ pointRadius: 1,
+ pointHitRadius: 10,
+ data: [65, 59, 80, 81, 56, 55, 40],
+ },
+ ],
+};
+
+const bar = {
+ labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
+ datasets: [
+ {
+ label: 'My First dataset',
+ backgroundColor: 'rgba(255,99,132,0.2)',
+ borderColor: 'rgba(255,99,132,1)',
+ borderWidth: 1,
+ hoverBackgroundColor: 'rgba(255,99,132,0.4)',
+ hoverBorderColor: 'rgba(255,99,132,1)',
+ data: [65, 59, 80, 81, 56, 55, 40],
+ },
+ ],
+};
+
+const doughnut = {
+ labels: [
+ 'Red',
+ 'Green',
+ 'Yellow',
+ ],
+ datasets: [
+ {
+ data: [300, 50, 100],
+ backgroundColor: [
+ '#FF6384',
+ '#36A2EB',
+ '#FFCE56',
+ ],
+ hoverBackgroundColor: [
+ '#FF6384',
+ '#36A2EB',
+ '#FFCE56',
+ ],
+ }],
+};
+
+const radar = {
+ labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'],
+ datasets: [
+ {
+ label: 'My First dataset',
+ backgroundColor: 'rgba(179,181,198,0.2)',
+ borderColor: 'rgba(179,181,198,1)',
+ pointBackgroundColor: 'rgba(179,181,198,1)',
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: 'rgba(179,181,198,1)',
+ data: [65, 59, 90, 81, 56, 55, 40],
+ },
+ {
+ label: 'My Second dataset',
+ backgroundColor: 'rgba(255,99,132,0.2)',
+ borderColor: 'rgba(255,99,132,1)',
+ pointBackgroundColor: 'rgba(255,99,132,1)',
+ pointBorderColor: '#fff',
+ pointHoverBackgroundColor: '#fff',
+ pointHoverBorderColor: 'rgba(255,99,132,1)',
+ data: [28, 48, 40, 19, 96, 27, 100],
+ },
+ ],
+};
+
+const pie = {
+ labels: [
+ 'Red',
+ 'Green',
+ 'Yellow',
+ ],
+ datasets: [
+ {
+ data: [300, 50, 100],
+ backgroundColor: [
+ '#FF6384',
+ '#36A2EB',
+ '#FFCE56',
+ ],
+ hoverBackgroundColor: [
+ '#FF6384',
+ '#36A2EB',
+ '#FFCE56',
+ ],
+ }],
+};
+
+const polar = {
+ datasets: [
+ {
+ data: [
+ 11,
+ 16,
+ 7,
+ 3,
+ 14,
+ ],
+ backgroundColor: [
+ '#FF6384',
+ '#4BC0C0',
+ '#FFCE56',
+ '#E7E9ED',
+ '#36A2EB',
+ ],
+ label: 'My dataset' // for legend
+ }],
+ labels: [
+ 'Red',
+ 'Green',
+ 'Yellow',
+ 'Grey',
+ 'Blue',
+ ],
+};
+
+const options = {
+ tooltips: {
+ enabled: false,
+ custom: CustomTooltips
+ },
+ maintainAspectRatio: false
+}
+
+class Charts extends Component {
+ render() {
+ return (
+
+
+
+
+ Line Chart
+
+
+
+
+
+
+
+
+
+
+ Bar Chart
+
+
+
+
+
+
+
+
+
+
+ Doughnut Chart
+
+
+
+
+
+
+
+
+
+
+ Radar Chart
+
+
+
+
+
+
+
+
+
+
+ Pie Chart
+
+
+
+
+
+
+
+
+ Polar Area Chart
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default Charts;
diff --git a/src/views/Charts/Charts.test.js b/src/views/Charts/Charts.test.js
new file mode 100644
index 0000000..6f3cd70
--- /dev/null
+++ b/src/views/Charts/Charts.test.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Charts from './Charts';
+
+jest.mock('react-chartjs-2', () => ({
+ Line: () => null,
+ Polar: () => null,
+ Pie: () => null,
+ Radar: () => null,
+ Bar: () => null,
+ Doughnut: () => null,
+}));
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
, div);
+ ReactDOM.unmountComponentAtNode(div);
+});
\ No newline at end of file
diff --git a/src/views/Charts/package.json b/src/views/Charts/package.json
new file mode 100644
index 0000000..da44c70
--- /dev/null
+++ b/src/views/Charts/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "Charts",
+ "version": "0.0.0",
+ "private": true,
+ "main": "./Charts.js"
+}
diff --git a/src/views/ControlMonitoringGantt/Gantt.css b/src/views/ControlMonitoringGantt/Gantt.css
new file mode 100644
index 0000000..1d7f3bf
--- /dev/null
+++ b/src/views/ControlMonitoringGantt/Gantt.css
@@ -0,0 +1,3 @@
+.gantt_grid_scale .gantt_grid_head_cell{color:#000000;}
+.gantt_task .gantt_task_scale .gantt_scale_cell{color:#000000;}
+.gantt_grid_scale,.gantt_task_scale{color:#000000;}
\ No newline at end of file
diff --git a/src/views/ControlMonitoringGantt/GanttDhtmlx2.js b/src/views/ControlMonitoringGantt/GanttDhtmlx2.js
new file mode 100644
index 0000000..b7bc285
--- /dev/null
+++ b/src/views/ControlMonitoringGantt/GanttDhtmlx2.js
@@ -0,0 +1,270 @@
+/*global gantt*/
+import React, { Component } from 'react';
+import ReactDOM from 'react-dom';
+import moment from 'moment';
+import axios from 'axios';
+import { Pagination, Table, Button, Tooltip } from 'antd';
+import 'dhtmlx-gantt';
+import 'dhtmlx-gantt/codebase/dhtmlxgantt.css';
+import './Gantt.css';
+
+let startDate = "";
+let endDate = "";
+let dataGantt = { data: [], links: [] };
+let idLoop = 1
+
+export default class GanttFull extends Component {
+
+ componentDidMount() {
+
+ gantt.config.scale_unit = "day";
+ gantt.config.step = 1;
+ gantt.config.date_scale = "%j";
+
+ gantt.config.scale_height = 75;
+ gantt.config.min_column_width = 30;
+ gantt.config.subscales = [{ unit: "month", step: 1, date: "%F, %Y" }];
+ // gantt.config.start_date = new Date(this.props.config.startDate);
+ // gantt.config.end_date = new Date(this.props.config.endDate);
+ gantt.config.progress = false;
+ gantt.config.readonly = true;
+ gantt.config.drag_resize = true;
+ gantt.config.drag_links = false;
+ gantt.config.drag_progress = false;
+ gantt.config.select_task = false;
+ gantt.config.add_column = false;
+ gantt.config.grid_resize = true;
+ gantt.config.columns = [
+ { name: "text", label: "Proyek", tree: true, width: 200 },
+ // {
+ // name: "duration", align: "center", onrender: function (task, node) {
+ // node.setAttribute("title", task.text);
+ // }
+ // },
+ {
+ name: "staff", align: "center", label: "Duration", template: function (obj) {
+ // console.log(obj)
+ return `${obj.duration} day`
+ }
+ },
+ // {
+ // name: "external",
+ // label: "Add",
+ // align: "center",
+ // onrender: (task, node) => {
+ // return
+ // this.props.handleOpenDialogSub('Save', task)}>
+ //
+ // }
+ // }
+ ];
+
+ gantt.config.external_render = {
+ // checks the element is a React element
+ isElement: (element) => {
+ return React.isValidElement(element);
+ },
+ // renders the React element into the DOM
+ renderElement: (element, container) => {
+ ReactDOM.render(element, container);
+ }
+ };
+ // gantt.config.auto_scheduling = true;
+ // gantt.attachEvent("onTaskClick", function (id, e) {
+ // console.log({ id, e })
+
+ // return true;
+ // });
+
+ gantt.init(this.ganttContainer);
+ // dataGantt = {data: []};
+ // this.loadData();
+ idLoop = 1
+ dataGantt = { data: [], links: [] };
+ this.runData();
+ };
+
+ handleOpenDialog = (param) => {
+ console.log(param)
+ }
+
+ constructor(props, context) {
+ super(props, context);
+
+ // this.state = {
+ // dataGantt : {data: []}
+
+ // };
+ };
+
+
+
+ runData = () => {
+ const { startDate, endDate } = this.props
+ console.log({ startDate, endDate })
+ gantt.config.start_date = new Date(startDate);
+ gantt.config.end_date = new Date(endDate);
+
+ // startDate = this.props.startDate;
+ // endDate = this.props.endDate;
+ // companyId = this.props.config.companyId;
+ // action = this.props.config.action;
+ this.parseData()
+ gantt.clearAll();
+ // console.log('--------- format gantt --------')
+ // console.log(dataGantt)
+ gantt.parse(dataGantt);
+ }
+
+ parseDataPlanning = (param, idParent) => {
+
+ param.map(res => {
+ let obj = {
+ end_date: moment(res.target_planning).format("DD-MM-YYYY HH:mm"),
+ id: res.id,
+ parent: idParent,
+ progress: 1,
+ start_date: moment(res.created_at).format("DD-MM-YYYY HH:mm"),
+ text: res.nama,
+ color: '#ffff00'
+ }
+ dataGantt.data.push(obj)
+ let link = {
+ id: idLoop,
+ source: idParent.toString(),
+ target: res.id.toString(),
+ type: "1"
+ }
+ dataGantt.links.push(link)
+ idLoop++;
+ })
+ }
+
+ parseDataWaspang = (param, idparent) => {
+
+ param.map(res => {
+ const id = res.id + 100
+ let obj = {
+ // end_date: moment(res.target_planning).format("DD-MM-YYYY HH:mm"),
+ id: id,
+ parent: idparent,
+ progress: 1,
+ // start_date: moment(res.created_at).format("DD-MM-YYYY HH:mm"),
+ text: res.name,
+ color: '#217f91'
+ }
+ dataGantt.data.push(obj)
+ if (res.plannings) this.parseDataPlanning(res.plannings, id)
+ })
+ }
+
+ parseDataChild = param => {
+ param.map(res => {
+
+ if (res.subproyeks) {
+ const color = res.color_progress == "green" ? '#4caf50' : res.color_progress == "orange" ? '#ffc107' : '#f44336'
+ let obj = {
+ id: res.id,
+ open: true,
+ parent_id: res.parent_id,
+ proyek_id: res.proyek_id,
+ start_date: moment(res.mulai_proyek).format("DD-MM-YYYY HH:mm"),
+ end_date: moment(res.akhir_proyek).format("DD-MM-YYYY HH:mm"),
+ parent: res.parent_id || res.proyek_id,
+ text: res.nama,
+ // ...res.parent_id && { color: color }
+ }
+ dataGantt.data.push(obj)
+ this.parseDataChild(res.subproyeks)
+ } else {
+ const color = res.color_progress == "green" ? '#4caf50' : res.color_progress == "orange" ? '#ffc107' : '#f44336'
+ let obj = {
+ end_date: moment(res.akhir_proyek).format("DD-MM-YYYY HH:mm"),
+ id: res.id,
+ parent_id: res.parent_id,
+ proyek_id: res.proyek_id,
+ parent: res.parent_id || res.proyek_id,
+ progress: 1,
+ start_date: moment(res.mulai_proyek).format("DD-MM-YYYY HH:mm"),
+ text: res.nama,
+ // ...res.parent_id && { color: color }
+ }
+ dataGantt.data.push(obj)
+ if (res.user_waspangs) this.parseDataWaspang(res.user_waspangs, res.id)
+ }
+ })
+ }
+
+ parseData = () => {
+
+ this.props.data.map(res => {
+ if (res.subproyeks) {
+ let obj = {
+ id: res.id,
+ open: true,
+ text: res.nama,
+ start_date: moment(res.mulai_proyek).format("DD-MM-YYYY HH:mm"),
+ end_date: moment(res.akhir_proyek).format("DD-MM-YYYY HH:mm"),
+ parent_id: res.parent_id,
+ proyek_id: res.proyek_id ? res.proyek_id : res.id,
+ color: '#142952'
+ }
+ dataGantt.data.push(obj)
+ this.parseDataChild(res.subproyeks)
+ } else {
+ let obj = {
+ end_date: moment(res.akhir_proyek).format("DD-MM-YYYY HH:mm"),
+ id: res.id,
+ // parent: res.id,
+ parent_id: res.parent_id,
+ proyek_id: res.proyek_id ? res.proyek_id : res.id,
+ progress: 1,
+ start_date: moment(res.mulai_proyek).format("DD-MM-YYYY HH:mm"),
+ text: res.nama,
+ color: '#142952'
+ }
+ dataGantt.data.push(obj)
+ }
+ })
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if (prevProps.data !== this.props.data) {
+ dataGantt = { data: [], links: [] };
+ idLoop = 1
+ this.runData()
+ }
+ if (prevProps.startDate !== this.props.startDate) {
+ dataGantt = { data: [], links: [] };
+ idLoop = 1
+ this.runData()
+ }
+ if (prevProps.endDate !== this.props.endDate) {
+ dataGantt = { data: [], links: [] };
+ idLoop = 1
+ this.runData()
+ }
+ }
+
+
+
+ render() {
+
+
+ let height = window.innerHeight - 100;
+
+ return (
+
+
+
{ this.ganttContainer = input }}
+ style={{ width: '100%', height: '100%' }}
+ >
+
+
+
+
+ );
+ }
+}
+
diff --git a/src/views/ControlMonitoringGantt/index.js b/src/views/ControlMonitoringGantt/index.js
new file mode 100644
index 0000000..0dcfdb7
--- /dev/null
+++ b/src/views/ControlMonitoringGantt/index.js
@@ -0,0 +1,272 @@
+import React, { useEffect, useMemo, useState } from 'react';
+import Timeline from 'react-calendar-timeline'
+// make sure you include the timeline stylesheet or the timeline will not be styled
+import 'react-calendar-timeline/lib/Timeline.css'
+import moment from 'moment';
+import { BASE_SIMPRO, PROYEK_ADD, PROYEK_SEARCH_DETAIL, GANTT_CONTROL_MONITORING_SEARCH, PROYEK_EDIT, PROYEK_DELETE } from '../../const/ApiConst';
+import axios from 'axios';
+import { NotificationContainer, NotificationManager } from 'react-notifications';
+import { Button } from 'antd';
+import {
+ Container, Col, Row, UncontrolledTooltip,
+ Card,
+ CardBody,
+ CardHeader,
+ Table,
+ Modal, ModalHeader, ModalBody, ModalFooter
+} from 'reactstrap';
+// import GanttFull from './GanttDhtmlx';
+import GanttFull from './GanttDhtmlx2';
+import DialogForm from '../Master/Proyek/DialogForm';
+import DialogFormSub from '../Master/Proyek/DialogFormSub';
+import Iframe from "@nicholasadamou/react-iframe";
+
+const getUrlParameter = (sParam) => {
+ var sPageURL = window.location.search.substring(1),
+ sURLVariables = sPageURL.split('&'),
+ sParameterName,
+ i;
+
+ console.log("sPageURL", sPageURL);
+ for (i = 0; i < sURLVariables.length; i++) {
+ sParameterName = sURLVariables[i].split('=');
+
+ if (sParameterName[0] === sParam) {
+ return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
+ }
+ }
+ return false;
+};
+
+const GanttTimeLine = () => {
+ const token = localStorage.getItem("token")
+ const HEADER = {
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${token}`
+ }
+ }
+
+ const [proyekId, setProyekId] = useState(15);
+ const [dataGantt, setDataGantt] = useState([]);
+ const [prevProyekId, setPrevProyekId] = useState(0);
+ const [dataGroupGantt, setDataGroupGantt] = useState([]);
+ const [maxDateGantt, setMaxDateGantt] = useState(null);
+ const [minDateGantt, setMinDateGantt] = useState(null);
+ const [dataAllTimeLine, setDataAllTimeLine] = useState([]);
+ const [prevDataAllTimeLine, setPrevDataAllTimeLine] = useState(null);
+
+ const [idTask, setidTask] = useState(0);
+ const [dataTable, setDatatable] = useState([])
+ const [search, setSearch] = useState('')
+ const [currentPage, setCurrentPage] = useState(1)
+ const [totalPage, setTotalPage] = useState(0)
+ const [openDialog, setOpenDialog] = useState(false)
+ const [openDialogSub, setOpenDialogSub] = useState(false)
+ const [typeDialog, setTypeDialog] = useState('Save');
+ const [typeDialogSub, setTypeDialogSub] = useState('Save')
+ const [idDelete, setIdDelete] = useState(0)
+ const [alertDelete, setAlertDelete] = useState(false)
+ const [dataEdit, setDataEdit] = useState([])
+ const [dataEditSub, setDataEditSub] = useState([])
+ const [rowsPerPage, setRowsPerPage] = useState(10)
+ const [clickOpenModal, setClickOpenModal] = useState(false)
+ const [dataExport, setDataExport] = useState([])
+ const [allDataMenu, setAllDataMenu] = useState([])
+ const [idSubtask, setIdSubtask] = useState(0);
+
+ const handleMappingDataGantt = (data) => {
+ const minDates = data.map(res => moment(res.mulai_proyek)),
+ minDate = moment.min(minDates)
+ const maxDates = data.map(res => moment(res.akhir_proyek)),
+ maxDate = moment.max(maxDates)
+
+ console.log({ minDate, maxDate })
+ let groups = []
+ let items = []
+ data.map((res, idx) => {
+ let group = {
+ id: res.id,
+ title: res.nama,
+ stackItems: true,
+ height: 50
+ }
+ let item = {
+ id: res.id,
+ group: res.id,
+ title: res.pic,
+ start_time: moment(res.mulai_proyek),
+ end_time: moment(res.akhir_proyek),
+ // selectedBgColor: res.color_progress == "green" ? 'rgba(255, 99, 132)' : res.color_progress == "orange" ? 'rgba(255,146,3)' : 'rgba(164,7,120)',
+ // bgColor: res.color_progress == "green" ? 'rgba(255, 99, 132, 0.7)' : res.color_progress == "orange" ? 'rgba(255,146,3, 0.7)' : 'rgba(164,7,120, 0.7)',
+ // itemProps: {
+ // style: {
+ // background: res.color_progress == "green" ? 'rgba(255, 99, 132)' : res.color_progress == "orange" ? 'rgba(255,146,3)' : 'rgba(164,7,120)'
+ // }
+ // }
+ }
+ groups.push(group)
+ items.push(item)
+ })
+ // console.log({ items, groups })
+ setDataGantt(items)
+ setDataGroupGantt(groups)
+ setMaxDateGantt(maxDate)
+ setMinDateGantt(minDate)
+ }
+
+ const handleGetDataProyek = async () => {
+
+ const payload = {
+ "columns": [
+ { "name": "nama", "logic_operator": "like", "value": "", "operator": "AND" }
+ ],
+ "joins": [
+ { "name": "subproyeks.m_proyek", "column_join": "proyek_id", "column_results": ["nama", "biaya", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] },
+ { "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": true },
+ "paging": { "start": 0, "length": 25 }
+ }
+
+ const result = await axios
+ .post(GANTT_CONTROL_MONITORING_SEARCH, payload, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ console.log(result)
+
+ if (result && result.data && result.data.code == 200) {
+ const { data } = result.data
+ setDataAllTimeLine(data)
+ setPrevDataAllTimeLine(data)
+ handleMappingDataGantt(data)
+
+ } else {
+ NotificationManager.error('Gagal Export Data!!', 'Failed');
+ }
+ }
+
+ useEffect(() => {
+ let proyek_id = getUrlParameter('proyek_id');
+ console.log('proyek_id', proyek_id);
+ if (proyek_id) {
+ setProyekId(proyek_id);
+ }
+ handleGetDataProyek()
+ }, []);
+
+ const handleClickGroupGantt = param => {
+ const row = prevDataAllTimeLine.filter(res => res.id === param)
+ if (row.length > 0) {
+ const { subproyeks, proyek_id, parent_id } = row[0]
+ console.log(subproyeks)
+ // setDataAllTimeLine(row[0])
+ setPrevProyekId(parent_id || proyek_id)
+ handleMappingDataGantt(subproyeks)
+ setDataAllTimeLine(subproyeks)
+ }
+
+ }
+
+ const handleOpenDialog = (type) => {
+ setOpenDialog(true)
+ setTypeDialog(type)
+ }
+
+ const handleOpenDialogSub = (type, param) => {
+ console.log("sub proyek", param)
+ const { id, parent_id, proyek_id, parent } = param
+ const idParent = parent == 0 ? 0 : parent == proyek_id ? id : parent_id
+ // console.log({ proyek_id, idParent })
+ setidTask(proyek_id)
+ setIdSubtask(idParent)
+ setOpenDialogSub(true)
+ setTypeDialogSub(type)
+ }
+
+ const handleCloseDialog = (type, data) => {
+ if (type === "save") {
+ saveProyek(data);
+ }
+
+ setDataEdit([])
+ setOpenDialog(false)
+ }
+
+ const handleCloseDialogSub = (type, data) => {
+ // if (type === "save") {
+ // saveLocation(data);
+ // } else if (type === "edit") {
+ // editLocation(data);
+ // }
+ setDataEditSub([])
+ setOpenDialogSub(false)
+ if (type !== "cancel") {
+ handleGetDataProyek()
+ }
+
+ }
+
+ const toggleAddDialog = () => {
+ setOpenDialog(!openDialog)
+ }
+
+ const toggleAddDialogSub = () => {
+ setOpenDialogSub(!openDialogSub)
+ }
+
+ const saveProyek = async (data) => {
+ const formData = data
+
+ const result = await axios.post(PROYEK_ADD, formData, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ if (result && result.data && result.data.code === 200) {
+ handleGetDataProyek()
+ NotificationManager.success(`Data proyek berhasil ditambah`, 'Success!!');
+ } else {
+ NotificationManager.error(`${result.data.message}`, 'Failed!!');
+ }
+
+ }
+
+ const RenderGantt = useMemo(() => (
+
+ ), [dataAllTimeLine, maxDateGantt, minDateGantt])
+
+ return (
+
+ {/* {RenderGantt} */}
+ {/* */}
+
+
+ );
+}
+
+export default GanttTimeLine;
\ No newline at end of file
diff --git a/src/views/DashboardPMO/chartDashboard.js b/src/views/DashboardPMO/chartDashboard.js
new file mode 100644
index 0000000..ac73bd0
--- /dev/null
+++ b/src/views/DashboardPMO/chartDashboard.js
@@ -0,0 +1,106 @@
+import React from 'react';
+import { Doughnut, Bar } from 'react-chartjs-2';
+import faker from '@faker-js/faker';
+
+export const optionsDoughnut = {
+ title: {
+ display: true,
+ text: 'PROJECT BY TYPE'
+ },
+};
+
+export const data = {
+ labels: ['Manned guarding ', 'C&T', 'CMS ', 'ESS', 'RSO'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: [12, 19, 3, 5, 2],
+ backgroundColor: [
+ 'rgba(255, 99, 132, 0.2)',
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(75, 192, 192, 0.2)',
+ 'rgba(153, 102, 255, 0.2)',
+ // 'rgba(255, 159, 64, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(255, 99, 132, 1)',
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(75, 192, 192, 1)',
+ 'rgba(153, 102, 255, 1)',
+ // 'rgba(255, 159, 64, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+};
+
+export const DoughnutChart = () => {
+ return
;
+}
+
+
+export const options = {
+ title: {
+ display: true,
+ text: 'PROJECT BY GOVERNANCE PHASE'
+ },
+ legend: {
+ position: 'right',
+ },
+ responsive: true,
+ scales: {
+ yAxes: [{
+ display: true,
+
+ // position: 'right',
+ stacked: true,
+ }],
+ xAxes: [{
+ display: true,
+ // position: 'right',
+ stacked: true,
+ }],
+ },
+};
+
+const labels = [''];
+
+export const dataBar = {
+ labels,
+ datasets: [
+ {
+ indexAxis: 'y',
+ label: 'Initiation',
+ data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
+ backgroundColor: 'rgb(255, 99, 132)',
+ },
+ {
+ indexAxis: 'y',
+ label: 'Execution',
+ data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
+ backgroundColor: 'rgb(75, 192, 192)',
+ },
+ {
+ indexAxis: 'y',
+ label: 'Closing',
+ data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
+ backgroundColor: 'rgb(53, 162, 235)',
+ },
+ // {
+ // indexAxis: 'y',
+ // label: 'Excecution',
+ // data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
+ // backgroundColor: 'rgba(255, 159, 64, 1)',
+ // },
+ ],
+};
+
+export function BarChart() {
+ return
;
+}
+
+
+
+
diff --git a/src/views/DashboardPMO/index.js b/src/views/DashboardPMO/index.js
new file mode 100644
index 0000000..c3724f3
--- /dev/null
+++ b/src/views/DashboardPMO/index.js
@@ -0,0 +1,173 @@
+import React from 'react';
+import { Row, Col, Select } from 'antd';
+import TableDashboard from './tableDashboard';
+import { BarChart, DoughnutChart } from './chartDashboard';
+
+function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) {
+ return (
+
+
+
+
+ {icon}
+
+
+
+
+
{value}
+
{title.toUpperCase()}
+
{secondaryTitle && secondaryTitle.toUpperCase()}
+
+
+
+
+ )
+}
+
+const { Option } = Select;
+
+const DashbaoardPM = () => {
+ const onChange = (value) => {
+ console.log(`selected ${value}`);
+ }
+
+ const onSearch = (val) => {
+ console.log('search:', val);
+ }
+ return (
+
+
+ PORTOFOLIO DASHBOARD
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ Jack
+ Lucy
+ Tom
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ {['Manned guarding ', 'C&T', 'CMS ', 'ESS', 'RSO'].map(res => (
+ {res}
+ ))}
+ {/* Jack
+ Lucy
+ Tom */}
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ Jack
+ Lucy
+ Tom
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ {['Initiation ', 'Excecution', 'Closing '].map(res => (
+ {res}
+ ))}
+
+
+
+
+
+
+
+ }
+ value="100"
+ bgColor="teal"
+ title="Project Count" />
+ {/* }
+ value="19 M"
+ bgColor="#059669"
+ title="Project Cost"
+ secondaryTitle="(dollars)" /> */}
+ }
+ value="7.2 M"
+ bgColor="#047857"
+ title="Cost Variance"
+ secondaryTitle="(dollars)" />
+ }
+ value="2000"
+ bgColor="#0284c7"
+ title="Project Manpower"
+ />
+ }
+ value="540"
+ bgColor="#0369a1"
+ title="Manpower Variance"
+ />
+ }
+ value="80"
+ bgColor="#b30000"
+ title="Active Car" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default DashbaoardPM;
\ No newline at end of file
diff --git a/src/views/DashboardPMO/tableDashboard.js b/src/views/DashboardPMO/tableDashboard.js
new file mode 100644
index 0000000..efde38c
--- /dev/null
+++ b/src/views/DashboardPMO/tableDashboard.js
@@ -0,0 +1,130 @@
+import React from 'react';
+import { Table, Tag, Space } from 'antd';
+
+const columns = [
+ {
+ title: 'Project Name',
+ dataIndex: 'project',
+ key: 'project',
+ fixed: 'left',
+ width: 200,
+ // render: text =>
{text} ,
+ },
+ {
+ title: 'Project Owner',
+ dataIndex: 'owner',
+ key: 'owner',
+ },
+ {
+ title: 'Start Date',
+ dataIndex: 'startDate',
+ key: 'startDate',
+ },
+ {
+ title: 'End Date',
+ dataIndex: 'endDate',
+ key: 'endDate',
+ },
+ {
+ title: 'Cost',
+ dataIndex: 'cost',
+ key: 'cost',
+ render: text => `Rp. ${text.toLocaleString()}`,
+ align: 'right'
+ },
+ {
+ title: 'Cost Health',
+ dataIndex: 'costHealth',
+ key: 'costHealth',
+ render: text =>
+ text === 'good' ?
:
+ text === 'danger' ?
:
+ text === 'warning' ?
:
+ ,
+ align: 'center',
+ },
+ {
+ title: 'Work Health',
+ dataIndex: 'workHealth',
+ key: 'workHealth',
+ render: text =>
+ text === 'good' ?
:
+ text === 'danger' ?
:
+ text === 'warning' ?
:
,
+ align: 'center',
+ },
+ {
+ title: 'Schedule Health',
+ dataIndex: 'scheduleHealth',
+ key: 'scheduleHealth',
+ render: text =>
+ text === 'good' ?
:
+ text === 'danger' ?
:
+ text === 'warning' ?
:
,
+ align: 'center',
+ },
+ {
+ title: '% Complete',
+ dataIndex: 'complete',
+ key: 'complete',
+ render: text => `${text}%`,
+ align: 'right'
+ },
+ // {
+ // title: 'Action',
+ // key: 'action',
+ // render: (text, record) => (
+ //
+ // Invite {record.name}
+ // Delete
+ //
+ // ),
+ // },
+];
+
+const data = [
+ {
+ key: '1',
+ project: 'Bay Plaza',
+ owner: 'John Brown',
+ startDate: '1/22/2022',
+ endDate: '1/22/2023',
+ complete: 20,
+ cost: 40000000,
+ costHealth: 'good',
+ workHealth: 'default',
+ scheduleHealth: 'warning'
+ },
+ {
+ key: '2',
+ project: 'Jambi Bridge',
+ owner: 'Jim Green',
+ startDate: '4/22/2022',
+ endDate: '11/22/2023',
+ complete: 65,
+ cost: 20000000,
+ costHealth: 'good',
+ workHealth: 'default',
+ scheduleHealth: 'danger'
+ },
+ {
+ key: '3',
+ project: 'Banten International Airport',
+ owner: 'Joe Black',
+ startDate: '1/22/2022',
+ endDate: '1/22/2025',
+ complete: 50,
+ cost: 200000000,
+ costHealth: 'default',
+ workHealth: 'default',
+ scheduleHealth: 'default'
+ },
+];
+
+const TableDashboard = () => {
+ return (
+
+ );
+}
+
+export default TableDashboard;
\ No newline at end of file
diff --git a/src/views/DashboardProject/chatDashboard.js b/src/views/DashboardProject/chatDashboard.js
new file mode 100644
index 0000000..ee8b168
--- /dev/null
+++ b/src/views/DashboardProject/chatDashboard.js
@@ -0,0 +1,42 @@
+import React from 'react';
+
+const ChatDashboard = () => {
+ return (
+
+
+
+
+
+
+ Robert William
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+
+
+ 14/01/22 14:21
+
+
+
+
+
+
+ Jennifer lawrence
+
+
+ Curabitur lobortis tellus nibh, at tincidunt turpis viverra at. Integer aliquam in quam eu fringilla. Nullam eu mauris gravida
+
+
+ 14/01/22 10:20
+
+
+
+
+
+
+ );
+}
+
+export default ChatDashboard;
\ No newline at end of file
diff --git a/src/views/DashboardProject/ganttDashboard.js b/src/views/DashboardProject/ganttDashboard.js
new file mode 100644
index 0000000..7e4e8ca
--- /dev/null
+++ b/src/views/DashboardProject/ganttDashboard.js
@@ -0,0 +1,33 @@
+import React, { useEffect, useMemo, useState } from 'react';
+import Timeline from 'react-calendar-timeline'
+// make sure you include the timeline stylesheet or the timeline will not be styled
+import 'react-calendar-timeline/lib/Timeline.css'
+// import moment from 'moment';
+// import { USER_VERSION_GANTT_SEARCH, BASE_SIMPRO_LUMEN } from '../../../const/ApiConst';
+// import axios from "../../../const/interceptorApi"
+const token = localStorage.getItem("token")
+const url = `https://ospro-gantt.ospro.id/src/index.html?base_url=https://ospro-api.ospro.id/api&gantt_id=12&proyek_id=11&token=${token}&ro=0`
+
+const Gantt = (props) => {
+
+ const RenderGantt = () => (
+
+ )
+
+ return (
+
+
+
+ );
+}
+
+export default Gantt;
\ No newline at end of file
diff --git a/src/views/DashboardProject/index.js b/src/views/DashboardProject/index.js
new file mode 100644
index 0000000..652a9b6
--- /dev/null
+++ b/src/views/DashboardProject/index.js
@@ -0,0 +1,171 @@
+import React from 'react';
+import { Row, Col, Select, Divider } from 'antd';
+import moment from 'moment'
+import Gantt from './ganttDashboard';
+import TableDashboard from './tableDashboard';
+import ChatDashboard from './chatDashboard';
+
+function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) {
+ return (
+
+ )
+}
+
+const DashboardProject = () => {
+ return (
+
+
+
+
+
+
+
+
+
Project Manager
+
Mark Julius
+
+
+
+
+
+
+
+
+
Date
+
{moment().format("DD-MM-YYYY")}
+
+
+
+
+
+
+
+
SCHEDULE
+
+
+
+
+
+
Start Date
+
April 1, 2022
+
+
+
+
+
+
+
+
+
+
Baseline Finish Date
+
September 30, 2022
+
+
+
+
+
+
+
+
+
+
Estimated Finish Date
+
April 1, 2023
+
+
+
+
+
+
+
+
+
FINANCIALS
+
+
+
+
+
+
Budget To Date (BCWP)
+
Rp. 2.000.000.000
+
+
+
+
+
+
+
+
+
+
Actual To Date (ACWP)
+
Rp. 1.700.000.000
+
+
+
+
+
+
+
+
+
+
Variance
+
Rp. 300.000.000
+
+
+
+
+
+
+
+
+ }
+ value="3.200.000.000"
+ bgColor="#059669"
+ title="Budget" />
+
+
+
+
+
+
+
+
+ );
+}
+
+export default DashboardProject;
\ No newline at end of file
diff --git a/src/views/DashboardProject/tableDashboard.js b/src/views/DashboardProject/tableDashboard.js
new file mode 100644
index 0000000..85d00c6
--- /dev/null
+++ b/src/views/DashboardProject/tableDashboard.js
@@ -0,0 +1,77 @@
+import React from 'react';
+import { Table, Tag, Space } from 'antd';
+
+const columns = [
+ {
+ title: 'No',
+ dataIndex: 'carNo',
+ key: 'carNo',
+ fixed: 'left',
+ },
+ {
+ title: 'Description',
+ dataIndex: 'description',
+ key: 'description',
+ width: 350
+ },
+ {
+ title: 'Severity',
+ dataIndex: 'severity',
+ key: 'severity',
+ render: text => {
+ return text == 'low' ?
LOW
:
+ text == 'medium' ?
MEDIUM
:
+
HIGH
+ },
+ },
+ {
+ title: 'Status',
+ dataIndex: 'status',
+ key: 'status',
+ render: text => {
+ return text == 'open' ?
OPEN
:
+ text == 'on-progress' ?
ON PROGRESS
:
+
DONE
+ },
+ },
+ {
+ title: 'Assigned',
+ dataIndex: 'assigned',
+ key: 'assigned',
+
+ },
+ {
+ title: 'Due',
+ dataIndex: 'due',
+ key: 'due',
+ }
+];
+
+const data = [
+ {
+ key: '1',
+ carNo: 'RIS001',
+ description: 'Test Analyst on unplanned leave, risk to project if leave extends pas 5/20',
+ severity: 'medium',
+ status: 'on-progress',
+ due: '05/04/2022',
+ assigned: 'John Lennon'
+ },
+ {
+ key: '2',
+ carNo: 'RIS002',
+ description: 'Coffee machine broken, result in extra long breaks to find coffee',
+ severity: 'low',
+ status: 'open',
+ due: '14/011/2022',
+ assigned: 'Robert William'
+ },
+];
+
+const TableDashboard = () => {
+ return (
+
+ );
+}
+
+export default TableDashboard;
\ No newline at end of file
diff --git a/src/views/DashboardSecurity/index.js b/src/views/DashboardSecurity/index.js
new file mode 100644
index 0000000..0e587ac
--- /dev/null
+++ b/src/views/DashboardSecurity/index.js
@@ -0,0 +1,124 @@
+import React from 'react';
+import { Row, Col, Select, DatePicker } from 'antd';
+import TableDashboard from './tableDashboard';
+import MapDashboard from './mapDashboard';
+const { Option } = Select;
+
+const DashboardSecurity = () => {
+ const onChange = (value) => {
+ console.log(`selected ${value}`);
+ }
+
+ const onSearch = (val) => {
+ console.log('search:', val);
+ }
+
+ const onChangeDate = (date, dateString) => {
+ console.log(date, dateString);
+ }
+ return (
+
+
+
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ Jack
+ Lucy
+ Tom
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ {['Manned guarding ', 'C&T', 'CMS ', 'ESS', 'RSO'].map(res => (
+ {res}
+ ))}
+ {/* Jack
+ Lucy
+ Tom */}
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ Jawa Barat
+ DKI Jakarta
+ Jawa Tengah
+ Jawa Timur
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ {['Sindang ', 'Kebayoran Lama', 'Kebayoran baru '].map(res => (
+ {res}
+ ))}
+
+
+
+
+ option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }
+ >
+ {['Radio Dalam ', 'Cipete', 'Haji Nawi '].map(res => (
+ {res}
+ ))}
+
+
+
+
+
+
+ );
+}
+
+export default DashboardSecurity;
\ No newline at end of file
diff --git a/src/views/DashboardSecurity/mapDashboard.js b/src/views/DashboardSecurity/mapDashboard.js
new file mode 100644
index 0000000..1ebece3
--- /dev/null
+++ b/src/views/DashboardSecurity/mapDashboard.js
@@ -0,0 +1,51 @@
+import React, { useEffect } from 'react';
+import L from 'leaflet';
+
+
+let map = null
+
+const MapDashboard = () => {
+
+ useEffect(() => {
+
+ // INITIALIZE Dashboard
+ if (!map) {
+ map = L.map('map', { zoomControl: false }).setView([-2.721044, 116.62442], 5);
+ L.tileLayer(
+ 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+ maxZoom: 18,
+ attribution: '©
OpenStreetMap contributors'
+ }
+ ).addTo(map);
+ L.marker([-6.142719569327774, 106.55132520955486]).addTo(map)
+ .bindPopup(`
+ ICN 1
+
+ 8 Pencurian`)
+ .openPopup();
+
+ L.marker([-1.9277364358639633, 102.86230604426582]).addTo(map)
+ .bindPopup(`
+ ICN 2
+
+ 2 Demonstrasi`)
+ .openPopup();
+
+ L.marker([-1.4977487818768103, 114.87755236966134]).addTo(map)
+ .bindPopup(`
+ ICN 3
+
+ 1 Demonstrasi`)
+ .openPopup();
+ }
+ }, []);
+
+ return (
+ <>
+
+ >
+
+ );
+}
+
+export default MapDashboard;
\ No newline at end of file
diff --git a/src/views/DashboardSecurity/tableDashboard.js b/src/views/DashboardSecurity/tableDashboard.js
new file mode 100644
index 0000000..f14b01b
--- /dev/null
+++ b/src/views/DashboardSecurity/tableDashboard.js
@@ -0,0 +1,85 @@
+import React from 'react';
+import { Table, Tag, Space } from 'antd';
+
+const columns = [
+ {
+ title: 'No',
+ dataIndex: 'key',
+ key: 'key',
+ width: 50
+ },
+ {
+ title: 'ICN',
+ dataIndex: 'icn',
+ key: 'icn',
+ },
+ {
+ title: 'Project Name',
+ dataIndex: 'project',
+ key: 'project',
+ width: 300
+ },
+ {
+ title: 'Project Location',
+ dataIndex: 'location',
+ key: 'location',
+ },
+ {
+ title: 'Incident Date',
+ dataIndex: 'startDate',
+ key: 'startDate',
+ },
+ {
+ title: 'Incident',
+ dataIndex: 'incident',
+ key: 'incident',
+ },
+ {
+ title: 'Status',
+ dataIndex: 'status',
+ key: 'status',
+ render: text => {
+ return text == 'open' ?
OPEN
:
CLOSE
+ },
+ }
+];
+
+const data = [
+ {
+ key: '1',
+ icn: 'ICN 1',
+ project: 'Banten International Airport',
+ status: 'close',
+ location: 'Banten',
+ startDate: '17/01/2022',
+ incident: 'Pencurian',
+ },
+ {
+ key: '2',
+ icn: 'ICN 2',
+ project: 'Jambi Bridge',
+ location: 'Jambi',
+ status: 'open',
+ startDate: '04/2/2022',
+ incident: 'Demonstrasi',
+ },
+ {
+ key: '3',
+ icn: 'ICN 3',
+ project: 'Bay Plaza',
+ location: 'Kalimantan',
+ status: 'open',
+ startDate: '28/3/2022',
+ incident: 'Demonstrasi',
+ }
+
+
+];
+
+const TableDashboard = () => {
+ return (
+
+ );
+}
+
+export default TableDashboard;
\ No newline at end of file
diff --git a/src/views/DashboardSimpro/BarChart.js b/src/views/DashboardSimpro/BarChart.js
new file mode 100644
index 0000000..0695ba1
--- /dev/null
+++ b/src/views/DashboardSimpro/BarChart.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import { Bar } from 'react-chartjs-2';
+
+const data = {
+ labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: [12, 19, 3, 5, 2, 3],
+ backgroundColor: [
+ 'rgba(255, 99, 132, 0.2)',
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(75, 192, 192, 0.2)',
+ 'rgba(153, 102, 255, 0.2)',
+ 'rgba(255, 159, 64, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(255, 99, 132, 1)',
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(75, 192, 192, 1)',
+ 'rgba(153, 102, 255, 1)',
+ 'rgba(255, 159, 64, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+};
+
+const options = {
+ scales: {
+ yAxes: [
+ {
+ ticks: {
+ beginAtZero: true,
+ },
+ },
+ ],
+ },
+};
+
+const BarChart = () => (
+ <>
+ {/*
*/}
+
+ >
+);
+
+export default BarChart;
\ No newline at end of file
diff --git a/src/views/DashboardSimpro/Dashboard.css b/src/views/DashboardSimpro/Dashboard.css
new file mode 100644
index 0000000..f57e9a6
--- /dev/null
+++ b/src/views/DashboardSimpro/Dashboard.css
@@ -0,0 +1,128 @@
+.number-asset {
+ font-size: 50px;
+ font-weight: bold;
+ text-align: center;
+}
+
+.no-padding {
+
+}
+
+.text-bold {
+ font-weight: bold;
+}
+
+.view-rectangle {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ justify-content: space-between;
+}
+
+.view1 {
+ width: 220px;
+ height: 100px;
+ padding: 10px;
+ margin-bottom: -20px;
+
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background-color: #008B8B;
+}
+.view2 {
+ width: 220px;
+ height: 100px;
+ padding: 10px;
+
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background-color: #8B008B;
+}
+.view3 {
+ width: 220px;
+ height: 100px;
+ padding: 10px;
+
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background-color: #7CFC00;
+}
+.view4 {
+ width: 220px;
+ height: 100px;
+ padding: 10px;
+
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background-color: #FF0000;
+}
+.view5 {
+ width: 220px;
+ height: 100px;
+ padding: 10px;
+
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background-color: #4682B4;
+}
+
+.number-style {
+ font-size: 30px;
+ color: black;
+ font-weight: bold;
+ margin-bottom:15px;
+}
+
+.number-style1 {
+ font-size: 30px;
+ color: #FFFFFF;
+ font-weight: bold;
+ margin-bottom:15px;
+}
+
+.daily-info-card {
+ min-width: 130px;
+ width: 220px;
+ height: 100px;
+ padding: 10px;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ margin: 4px;
+ border-radius: 8px;
+}
+
+
+.dashboard-container {
+ overflow-x: auto;
+}
+
+.maptable-window-button-container {
+ float: right;
+ right: 0px;
+}
+
+.maptable-close, .maptable-maximize, .maptable-minimize {
+ cursor: pointer;
+ padding: 4px;
+}
+
+.maptable-header {
+ margin-bottom: -10px;
+}
+
+.maptable-title {
+ font-size: 24px;
+ font-weight: 700;
+ text-align: left;
+ margin-left: 20px;
+}
+
+.maptable-close:hover, .maptable-maximize:hover, .maptable-minimize:hover {
+ color: #20a8d8;
+}
diff --git a/src/views/DashboardSimpro/LineChart.js b/src/views/DashboardSimpro/LineChart.js
new file mode 100644
index 0000000..2696fef
--- /dev/null
+++ b/src/views/DashboardSimpro/LineChart.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { Line } from 'react-chartjs-2';
+
+const MultiAxisLine = ({ data, handleClickChart, optionsAdded }) => {
+ const options = { ...optionsAdded };
+
+ return (
+ <>
+ {/*
+
Multi Axis Line Chart
+
+
*/}
+
+ >
+ );
+}
+
+export default MultiAxisLine;
\ No newline at end of file
diff --git a/src/views/DashboardSimpro/PieChart.js b/src/views/DashboardSimpro/PieChart.js
new file mode 100644
index 0000000..614a48e
--- /dev/null
+++ b/src/views/DashboardSimpro/PieChart.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import { Pie } from 'react-chartjs-2';
+
+const options = {
+ responsive: true,
+ maintainAspectRatio: false,
+ title: {
+ display: true,
+ text: 'Status Proyek'
+ },
+ legend: {
+ display: true,
+ position: 'bottom'
+ // labels: {
+ // fontColor: 'rgb(255, 99, 132)'
+ // }
+ }
+}
+
+const PieChart = ({data}) => (
+ <>
+
+ >
+);
+
+export default PieChart;
\ No newline at end of file
diff --git a/src/views/DashboardSimpro/index 16.js b/src/views/DashboardSimpro/index 16.js
new file mode 100644
index 0000000..27e2cc4
--- /dev/null
+++ b/src/views/DashboardSimpro/index 16.js
@@ -0,0 +1,531 @@
+import { DatePicker } from 'antd';
+import Chart from 'chart.js';
+import ChartDataLabels from 'chartjs-plugin-datalabels';
+import moment from 'moment';
+import React, { useEffect, useState } from 'react';
+import {
+ Card, Modal, ModalHeader, ModalBody, ModalFooter, Button,
+ CardBody, CardHeader, Col, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Row
+} from 'reactstrap';
+import { Pagination, Tooltip, Tree, List, Checkbox } from 'antd';
+import '../../../node_modules/react-grid-layout/css/styles.css';
+import '../../../node_modules/react-resizable/css/styles.css';
+import {
+ DONE_COLOR, IZIN_COLOR, NOT_YET_COLOR,
+ PRESENT_COLOR, TOTAL_COLOR,
+ RED_COLOR,
+ ORANGE_COLOR,
+ GREEN_COLOR,
+ DARK_GREY_COLOR,
+ BLUE_COLOR,
+ PURPLE_COLOR
+} from '../../const/AppConst.js';
+import '../Map/CustomScroll.css';
+import './Dashboard.css';
+import { BASE_SIMPRO } from '../../const/ApiConst';
+import { NotificationContainer, NotificationManager } from 'react-notifications';
+import axios from 'axios'
+import numeral from 'numeral';
+import ContentLoader from "react-content-loader"
+import LineChart from './LineChart';
+import PieChart from './PieChart';
+import { projectTreeConst } from '../../const/LayerTreeConst.js';
+import { PLANNING_REALISASI_SEARCH, PLANNING_SEARCH, PROYEK_SEARCH_DETAIL, PROYEK_EDIT } from '../../const/ApiConst.js';
+import { getChildrenTree, formatRupiah, DATE_TIME_FORMAT } from '../../const/CustomFunc.js';
+
+const id_org = window.localStorage.getItem('id_org');
+const roleName = window.localStorage.getItem('role_name');
+
+Chart.plugins.register(ChartDataLabels);
+const { RangePicker } = DatePicker;
+
+let menu = [
+ // {
+ // "id": 1,
+ // "title": "PLANNING",
+ // "key": "total karyawan",
+ // // "total": this.state.sumEmployee,
+ // "color": TOTAL_COLOR
+ // },
+ // {
+ // "id": 2,
+ // "title": "REALISASI",
+ // "key": "presensi",
+ // // "total": this.state.sumPresensi,
+ // "color": PRESENT_COLOR
+ // },
+ {
+ "id": 3,
+ "title": "PANIC BUTTON",
+ "key": "absent",
+ // "total": this.state.sumAbsensi,
+ "color": IZIN_COLOR
+ },
+ {
+ "id": 4,
+ "title": "WASPANG ACTIVE",
+ "key": "karyawan telat",
+ // "total": this.state.sumTelat,
+ "color": GREEN_COLOR
+ },
+ {
+ "id": 5,
+ "title": "WASPANG ABSENT",
+ "key": "karyawan tanpa keterangan",
+ // "total": this.state.sumTanpaKet,
+ "color": ORANGE_COLOR
+ }
+ // {
+ // "id": 6,
+ // "title": "PANIK BUTTON",
+ // "key": "panic button",
+ // "total": this.state.sumPanicBtn,
+ // "color": ABSENT_COLOR
+ // }
+]
+
+const defaultPersentaseProyek = {
+ labels: [],
+ datasets: [
+ {
+ label: 'Progress',
+ data: [],
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+};
+
+const defaultCostProyek = {
+ labels: [],
+ datasets: [
+ {
+ label: 'Perencanaan',
+ data: [],
+ fill: false,
+ backgroundColor: 'rgb(255, 99, 132)',
+ borderColor: 'rgba(255, 99, 132, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ {
+ label: 'Realisasi',
+ data: [],
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+};
+
+const defaultStatusProyek = {
+ labels: ['Aman', 'Alert', 'Critical'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: [],
+ backgroundColor: [
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(255, 99, 132, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(255, 99, 132, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+};
+
+const DashboardSimpro = () => {
+ const token = localStorage.getItem("token")
+ const HEADER = {
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${token}`
+ }
+ }
+ const [openPlanRealisasi, setopenPlanRealisasi] = useState(false);
+ const [openCostPlanRealisasi, setopenCostPlanRealisasi] = useState(false);
+ const [dataChart, setDataChart] = useState([]);
+ const [projectTree, setProjectTree] = useState([]);
+ const [allProyek, setAllProyek] = useState(true);
+ const [dataStatusProyek, setDataStatusProyek] = useState(null);
+ const [dataPersentaseProyek, setDataPersentaseProyek] = useState(null);
+ const [dataCostProyek, setdataCostProyek] = useState(null);
+ const [projectTreeVisible, setProjectTreeVisible] = useState(false);
+ const [checkedKeysProjectTree, setCheckedKeysProjectTree] = useState([]);
+ const [openModalTable, setOpenModalTable] = useState(false);
+ const [dataDashboard, setDataDashboard] = useState(null);
+
+ const handleGetDataDashboard = async () => {
+ const URL = `${BASE_SIMPRO}/dashboard-proyek/search`
+ const payload = {
+ "columns": [
+ { "name": "created_at", "logic_operator": "range", "value": "2021-11-06 00:00:00", "value1": "2021-11-06 23:59:59", "operator": "AND" }
+ ],
+ "paging": { "start": 0, "length": -1 }
+ }
+ // console.log(payload)
+ const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response)
+ if (result.data.code === 200) {
+ setDataDashboard(result.data.data);
+ } else {
+ NotificationManager.error('Gaga Menambah Data!!', 'Failed');
+ }
+
+ }
+
+ const handleGetDataDashboardChart = async () => {
+ const URL = `${BASE_SIMPRO}/dashboard-status/search`
+ let str = ''
+ checkedKeysProjectTree.map((res, idx) => {
+ if (idx == 0) str += `${res}`
+ if (idx != 0) str += `,${res}`
+ })
+ console.log(str)
+ const payload = {
+ "columns": [
+ { "name": "id", "logic_operator": "in", "value": str ? str : "0", "operator": "AND" }
+ ],
+ "orders": { "columns": ["nama"], "ascending": true }
+ }
+ // console.log(payload)
+ const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response)
+ if (result.data.code === 200) {
+
+ const { persentase_progress, progress_cost_planning, progress_cost_realisasi, status_proyek } = result.data.data
+
+ const labelPersentaseProyek = persentase_progress ? persentase_progress.map(res => res.label) : []
+ const valuePersentaseProyek = persentase_progress ? persentase_progress.map(res => res.total) : []
+ const persentaseProyek = {
+ labels: labelPersentaseProyek,
+ datasets: [
+ {
+ label: 'Progress',
+ data: valuePersentaseProyek,
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+ };
+ setDataPersentaseProyek(persentaseProyek)
+ const labelCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.label) : []
+ const valueCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.total) : []
+ const valueCostRealisasi = progress_cost_realisasi ? progress_cost_realisasi.map(res => res.total) : []
+
+ const costProyek = {
+ labels: labelCostPlaning,
+ datasets: [
+ {
+ label: 'Perencanaan',
+ data: valueCostPlaning,
+ fill: false,
+ backgroundColor: 'rgb(255, 99, 132)',
+ borderColor: 'rgba(255, 99, 132, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ {
+ label: 'Realisasi',
+ data: valueCostRealisasi,
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+ };
+ setdataCostProyek(costProyek)
+
+ const valueStatusProyek = status_proyek ? status_proyek.map(res => res.total) : []
+
+ const statusProyek = {
+ labels: ['Aman', 'Alert', 'Critical'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: valueStatusProyek,
+ backgroundColor: [
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(255, 99, 132, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(255, 99, 132, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+ };
+
+ setDataStatusProyek(statusProyek)
+
+ } else {
+ NotificationManager.error('Gaga Menambah Data!!', 'Failed');
+ }
+
+ }
+
+ const getProyek = async () => {
+ const URL = `${BASE_SIMPRO}/proyek/list?start=0&length=-1&orderby=nama&asc=true`
+ const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
+ if (result.data.code === 200) {
+ setProjectTree(result.data.data);
+ const arr = result.data.data.map(res => res.id)
+ // console.log("checked all", data)
+ setCheckedKeysProjectTree(arr)
+ } else {
+ NotificationManager.error('Gaga Menambah Data!!', 'Failed');
+ }
+ }
+ useEffect(() => {
+ handleGetDataDashboardChart()
+ // console.log(checkedKeysProjectTree)
+ }, [checkedKeysProjectTree]);
+
+ useEffect(() => {
+ if (allProyek) {
+ const data = projectTree.map(res => res.id)
+ console.log("checked all", data)
+ setCheckedKeysProjectTree(data)
+ }
+ }, [allProyek]);
+
+ useEffect(() => {
+ handleGetDataDashboard()
+ getProyek()
+ // return () => {
+ // cleanup
+ // };
+ }, []);
+
+ const renderDailyInfo = () => {
+
+ return (
+ <>
+ {/*
+
{dataDashboard ? dataDashboard.planning : 0}
+
PLANNING
+
+
+
{dataDashboard ? dataDashboard.realisasi : 0}
+
REALISASI
+
*/}
+
+
{dataDashboard ? dataDashboard.panic_button : 0}
+
PANIC BUTTON
+
+
+
{dataDashboard ? dataDashboard.waspang_status.presensi : 0}
+
WASPANG ACTIVE
+
+
+
{dataDashboard ? dataDashboard.waspang_status.absensi : 0}
+
WASPANG ABSENT
+
+ >
+ )
+ }
+
+ const handleClickChart = param => {
+ if (!param.length) return;
+ console.log(param)
+ const { _datasetIndex, _index } = param[0];
+ const data = dataPersentaseProyek.datasets[_datasetIndex].label
+ console.log(data)
+ setOpenModalTable(true)
+ }
+
+ const handleClickProyek = id => {
+ const arr = [...checkedKeysProjectTree]
+ const idx = arr.indexOf(id)
+ if (idx == -1) {
+ arr.push(id)
+ } else {
+ arr.splice(idx, 1)
+ }
+ setCheckedKeysProjectTree(arr)
+ }
+
+ return (
+
+
setOpenModalTable(!openModalTable)}
+ >
+ setOpenModalTable(!openModalTable)}>
+ Modal title
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+
+ setOpenModalTable(!openModalTable)}
+ >
+ Do Something
+
+ {' '}
+ setOpenModalTable(!openModalTable)}>
+ Cancel
+
+
+
+
+
+
+
+
+
+
+ Proyek
+ {/*
+
+
+ setProjectTree(!projectTreeVisible)}>
+
+
+ */}
+
+
+
+
+ setAllProyek(!allProyek)}>Semua
+ Header
}
+ // footer={Footer
}
+ // bordered
+ dataSource={projectTree}
+ renderItem={item => (
+
+ handleClickProyek(item.id)}>{item.nama}
+
+ )}
+ />
+
+
+
+
+
+
+ {/*
+
+ Waspang Status
+
+ */}
+
+ {renderDailyInfo()}
+
+ {/*
+ */}
+
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+ {/*
*/}
+
+
+ {/* */}
+
+ {/*
*/}
+
+
+
+
+
+ );
+}
+
+export default DashboardSimpro;
\ No newline at end of file
diff --git a/src/views/DashboardSimpro/index.js b/src/views/DashboardSimpro/index.js
new file mode 100644
index 0000000..c9574a2
--- /dev/null
+++ b/src/views/DashboardSimpro/index.js
@@ -0,0 +1,366 @@
+import { DatePicker } from 'antd';
+import Chart from 'chart.js';
+import ChartDataLabels from 'chartjs-plugin-datalabels';
+import moment from 'moment';
+import React, { useEffect, useState } from 'react';
+import {
+ Card, Modal, ModalHeader, ModalBody, ModalFooter, Button,
+ CardBody, CardHeader, Col, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Row
+} from 'reactstrap';
+import { Pagination, Tooltip, Tree, List, Checkbox } from 'antd';
+import '../../../node_modules/react-grid-layout/css/styles.css';
+import '../../../node_modules/react-resizable/css/styles.css';
+import {
+ DONE_COLOR, IZIN_COLOR, NOT_YET_COLOR,
+ PRESENT_COLOR, TOTAL_COLOR,
+ RED_COLOR,
+ ORANGE_COLOR,
+ GREEN_COLOR,
+ DARK_GREY_COLOR,
+ BLUE_COLOR,
+ PURPLE_COLOR
+} from '../../const/AppConst.js';
+import '../Map/CustomScroll.css';
+import './Dashboard.css';
+import { BASE_SIMPRO } from '../../const/ApiConst';
+import { NotificationContainer, NotificationManager } from 'react-notifications';
+import axios from 'axios'
+import numeral from 'numeral';
+import ContentLoader from "react-content-loader"
+import LineChart from './LineChart';
+import PieChart from './PieChart';
+import { projectTreeConst } from '../../const/LayerTreeConst.js';
+import { PLANNING_REALISASI_SEARCH, PLANNING_SEARCH, PROYEK_SEARCH_DETAIL, PROYEK_EDIT } from '../../const/ApiConst.js';
+import { getChildrenTree, formatRupiah, DATE_TIME_FORMAT } from '../../const/CustomFunc.js';
+import SiopasMap from '../Map/Map_16.js';
+const id_org = window.localStorage.getItem('id_org');
+const roleName = window.localStorage.getItem('role_name');
+
+Chart.plugins.register(ChartDataLabels);
+const { RangePicker } = DatePicker;
+
+let menu = [
+ // {
+ // "id": 1,
+ // "title": "PLANNING",
+ // "key": "total karyawan",
+ // // "total": this.state.sumEmployee,
+ // "color": TOTAL_COLOR
+ // },
+ // {
+ // "id": 2,
+ // "title": "REALISASI",
+ // "key": "presensi",
+ // // "total": this.state.sumPresensi,
+ // "color": PRESENT_COLOR
+ // },
+ {
+ "id": 3,
+ "title": "PANIC BUTTON",
+ "key": "absent",
+ // "total": this.state.sumAbsensi,
+ "color": IZIN_COLOR
+ },
+ {
+ "id": 4,
+ "title": "WASPANG ACTIVE",
+ "key": "karyawan telat",
+ // "total": this.state.sumTelat,
+ "color": GREEN_COLOR
+ },
+ {
+ "id": 5,
+ "title": "WASPANG ABSENT",
+ "key": "karyawan tanpa keterangan",
+ // "total": this.state.sumTanpaKet,
+ "color": ORANGE_COLOR
+ }
+ // {
+ // "id": 6,
+ // "title": "PANIK BUTTON",
+ // "key": "panic button",
+ // "total": this.state.sumPanicBtn,
+ // "color": ABSENT_COLOR
+ // }
+]
+
+const defaultPersentaseProyek = {
+ labels: [],
+ datasets: [
+ {
+ label: 'Progress',
+ data: [],
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+};
+
+const defaultCostProyek = {
+ labels: [],
+ datasets: [
+ {
+ label: 'Perencanaan',
+ data: [],
+ fill: false,
+ backgroundColor: 'rgb(255, 99, 132)',
+ borderColor: 'rgba(255, 99, 132, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ {
+ label: 'Realisasi',
+ data: [],
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+};
+
+const defaultStatusProyek = {
+ labels: ['Aman', 'Alert', 'Critical'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: [],
+ backgroundColor: [
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(255, 99, 132, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(255, 99, 132, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+};
+
+const DashboardSimpro = () => {
+ const token = localStorage.getItem("token")
+ const HEADER = {
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Bearer ${token}`
+ }
+ }
+ const [openPlanRealisasi, setopenPlanRealisasi] = useState(false);
+ const [openCostPlanRealisasi, setopenCostPlanRealisasi] = useState(false);
+ const [dataChart, setDataChart] = useState([]);
+ const [projectTree, setProjectTree] = useState([]);
+ const [allProyek, setAllProyek] = useState(true);
+ const [dataStatusProyek, setDataStatusProyek] = useState(null);
+ const [dataPersentaseProyek, setDataPersentaseProyek] = useState(null);
+ const [dataCostProyek, setdataCostProyek] = useState(null);
+ const [projectTreeVisible, setProjectTreeVisible] = useState(false);
+ const [checkedKeysProjectTree, setCheckedKeysProjectTree] = useState([]);
+ const [openModalTable, setOpenModalTable] = useState(false);
+ const [dataDashboard, setDataDashboard] = useState(null);
+
+ const handleGetDataDashboard = async () => {
+ const URL = `${BASE_SIMPRO}/dashboard-proyek/search`
+ const payload = {
+ "columns": [
+ { "name": "created_at", "logic_operator": "range", "value": "2021-11-06 00:00:00", "value1": "2021-11-06 23:59:59", "operator": "AND" }
+ ],
+ "paging": { "start": 0, "length": -1 }
+ }
+ // console.log(payload)
+ const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response)
+ if (result.data.code === 200) {
+ setDataDashboard(result.data.data);
+ } else {
+ NotificationManager.error('Gaga Menambah Data!!', 'Failed');
+ }
+
+ }
+
+ const handleGetDataDashboardChart = async () => {
+ const URL = `${BASE_SIMPRO}/dashboard-status/search`
+ let str = ''
+ checkedKeysProjectTree.map((res, idx) => {
+ if (idx == 0) str += `${res}`
+ if (idx != 0) str += `,${res}`
+ })
+ console.log(str)
+ const payload = {
+ "columns": [
+ { "name": "id", "logic_operator": "in", "value": str ? str : "0", "operator": "AND" }
+ ],
+ "orders": { "columns": ["nama"], "ascending": true }
+ }
+ // console.log(payload)
+ const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response)
+ if (result.data.code === 200) {
+
+ const { persentase_progress, progress_cost_planning, progress_cost_realisasi, status_proyek } = result.data.data
+
+ const labelPersentaseProyek = persentase_progress ? persentase_progress.map(res => res.label) : []
+ const valuePersentaseProyek = persentase_progress ? persentase_progress.map(res => res.total) : []
+ const persentaseProyek = {
+ labels: labelPersentaseProyek,
+ datasets: [
+ {
+ label: 'Progress',
+ data: valuePersentaseProyek,
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+ };
+ setDataPersentaseProyek(persentaseProyek)
+ const labelCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.label) : []
+ const valueCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.total) : []
+ const valueCostRealisasi = progress_cost_realisasi ? progress_cost_realisasi.map(res => res.total) : []
+
+ const costProyek = {
+ labels: labelCostPlaning,
+ datasets: [
+ {
+ label: 'Perencanaan',
+ data: valueCostPlaning,
+ fill: false,
+ backgroundColor: 'rgb(255, 99, 132)',
+ borderColor: 'rgba(255, 99, 132, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ {
+ label: 'Realisasi',
+ data: valueCostRealisasi,
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+ };
+ setdataCostProyek(costProyek)
+
+ const valueStatusProyek = status_proyek ? status_proyek.map(res => res.total) : []
+
+ const statusProyek = {
+ labels: ['Aman', 'Alert', 'Critical'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: valueStatusProyek,
+ backgroundColor: [
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(255, 99, 132, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(255, 99, 132, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+ };
+
+ setDataStatusProyek(statusProyek)
+
+ } else {
+ NotificationManager.error('Gaga Menambah Data!!', 'Failed');
+ }
+
+ }
+
+ const getProyek = async () => {
+ const URL = `${BASE_SIMPRO}/proyek/list?start=0&length=-1&orderby=nama&asc=true`
+ const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
+ if (result.data.code === 200) {
+ setProjectTree(result.data.data);
+ const arr = result.data.data.map(res => res.id)
+ // console.log("checked all", data)
+ setCheckedKeysProjectTree(arr)
+ } else {
+ NotificationManager.error('Gaga Menambah Data!!', 'Failed');
+ }
+ }
+ // useEffect(() => {
+ // handleGetDataDashboardChart()
+ // // console.log(checkedKeysProjectTree)
+ // }, [checkedKeysProjectTree]);
+
+ // useEffect(() => {
+ // if (allProyek) {
+ // const data = projectTree.map(res => res.id)
+ // console.log("checked all", data)
+ // setCheckedKeysProjectTree(data)
+ // }
+ // }, [allProyek]);
+
+ // useEffect(() => {
+ // handleGetDataDashboard()
+ // getProyek()
+ // // return () => {
+ // // cleanup
+ // // };
+ // }, []);
+
+ const renderDailyInfo = () => {
+
+ return (
+ <>
+ {/* Loading...
+
+ toggleActiveTab = (tab) => {
+ const {activeTab} = this.state;
+ if (activeTab !== tab) {
+ this.setState({activeTab: tab});
+ }
+ }
+
+ /*getLayerList = async () => {
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_LIST, param).then(response => response.json()).then(res => res)
+ if (result.data){
+ if (result.data.length > 0) {
+ this.setState({layers: result.data}, () => {
+ console.log(this.state.layers);
+ });
+ }
+ } else {
+ }
+ } catch(err) {
+ console.log(err);
+ alert(err.message.toString());
+ }
+ }*/
+
+ getLayerDetails = async(layer_id) => {
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_DETAIL+layer_id, param).then(response => response.json()).then(res => res)
+ if (result.data){
+ if (result.data.length > 0) {
+ /*let layer_details_contents = {
+ "Layer Title (label on map)": result.data[0].title_en,
+ "Layer Name": result.data[0].name,
+ "Abstract": result.data[0].abstract_en,
+ "Workspace": result.data[0].workspace,
+ "Data Store": result.data[0].store
+ }*/
+ let layer_details_contents = [
+ {
+ "name": "layer_title",
+ "label": "Layer Title (label on Map)",
+ "value": result.data[0].title_en,
+ "type": "text",
+ "disabled": false
+ },
+ {
+ "name": "layer_name",
+ "label": "Layer Name",
+ "value": result.data[0].name,
+ "type": "text",
+ "disabled": true
+ },
+ {
+ "name": "abstract",
+ "label": "Abstract",
+ "value": result.data[0].abstract_en,
+ "type": "text",
+ "disabled": false
+ },
+ {
+ "name": "workspace",
+ "label": "Workspace",
+ "value": result.data[0].workspace,
+ "type": "text",
+ "disabled": true
+ },
+ {
+ "name": "datastore",
+ "label": "Data Store",
+ "value": result.data[0].store,
+ "type": "text",
+ "disabled": true
+ },
+ ]
+ this.setState({layer_details: result.data, layer_details_contents: layer_details_contents}, () => {
+ // console.log('layer_details', this.state.layer_details);
+ // console.log('layer_details_contents', this.state.layer_details_contents);
+ });
+ }
+ } else {
+ }
+ } catch(err) {
+ console.log(err);
+ alert(err.message.toString());
+ }
+ }
+
+ getLayerAttribute = async(layer_id) => {
+ // const { layer_id } = this.state;
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_ATTRIBUTE+layer_id, param).then(response => response.json()).then(res => res)
+ if (result.data){
+ if (result.data.length > 0) {
+
+ let columns = [];
+ /*attribute: "tgl_pembuk"
+ description: null
+ attribute_label: null
+ attribute_type: "xsd:string"
+ visible: "t"
+ display_order: "15"
+ */
+ let data = [];
+
+ /*for (let key in result.data[0]) {
+ columns.push({
+ dataField: key,
+ text: key,
+ sort: true
+ })
+ }*/
+ for (let i=0; i < result.data.length; i++) {
+ data.push({
+ "attribute": result.data[i].attribute,
+ "attribute_label": result.data[i].attribute_label,
+ "attribute_type": result.data[i].attribute_type,
+ "description": result.data[i].description,
+ "visible": result.data[i].visible,
+ // "display_order": result.data[i].display_order
+ });
+ }
+
+ console.log('result data getLayerAttribute', result.data);
+
+ this.setState({
+ // columns: result.data.length !== 0 ? columns:dataColumns,
+ dataAttribute: result.data
+ })
+
+ // this.setState({layerAttribute: result.data}, () => {
+ // console.log(this.state.layerAttribute);
+ // const { layerAttribute } = this.state;
+
+ // });
+ }
+ } else {
+
+ }
+ } catch(err) {
+ console.log(err);
+ alert(err.message.toString());
+ }
+ }
+
+ getLayerSearchLabel = async(layer_id) => {
+ const { selectedSearchLabelId } = this.state;
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_SEARCH_LABEL+layer_id, param).then(response => response.json()).then(res => res)
+ if (result.data){
+ if (result.data.length > 0) {
+ console.log('getLayerSearchLabel result', result);
+ this.setState({
+ selectedSearchLabelId: result.data[0].attribute_id,
+ searchLabelData: result.data
+ })
+ }
+ } else {
+
+ }
+ } catch(err) {
+ console.log(err);
+ alert(err.message.toString());
+ }
+ }
+
+ onSelectRowTable = () => {
+
+ }
+
+ onSelectAllRowTable = () => {
+
+ }
+
+ toggleEditCell = () => {
+ this.setState({
+ editCellMode: !this.state.editCellMode,
+ updateAttributeBtnVisible: !this.state.updateAttributeBtnVisible
+ });
+ /*let { editCellMode } = this.state;
+ console.log("editCellMode ", editCellMode)
+ // when editCellMode === true -> false (deactive)
+ editCellMode ?
+ this.setState({
+ editCellMode: false,
+ selectRow: {
+ mode: 'checkbox',
+ clickToSelect: true,
+ clickToEdit: false,
+ bgColor: '#e4e5e6',
+ onSelect: (row, isSelect, rowIndex, e) => this.onSelectRowTable({row, isSelect, e, rowIndex}),
+ onSelectAll: (isSelect, rows, e) => this.onSelectAllRowTable(isSelect, rows, e),
+ },
+ selectedRows: []
+ }) :
+ // when editCellMode === false -> true (activate)
+ this.setState({
+ editCellMode: true,
+ selectRow: {
+ mode: 'checkbox',
+ clickToSelect: false,
+ clickToEdit: true,
+ bgColor: '#e4e5e6',
+ onSelect: (row, isSelect, rowIndex, e) => this.onSelectRowTable({row, isSelect, e, rowIndex}),
+ onSelectAll: (isSelect, rows, e) => this.onSelectAllRowTable(isSelect, rows, e),
+ }
+ });*/
+ }
+
+ handleChangeInputLayerDetails = (idx, event) => {
+ let { layer_details_contents } = this.state;
+ let changedItem = findWhere(layer_details_contents, {name: idx});
+ let value = event.target.value;
+ changedItem.value = value;
+ console.log('changedItem', changedItem);
+ this.setState({layer_details_contents: layer_details_contents});
+ console.log('layer_details_contents', this.state.layer_details_contents);
+ }
+
+ handleChangeSelectSearchLabel = (event) => {
+ const { selectedSearchLabelId } = this.state;
+ let value = event.target.value;
+ this.setState({selectedSearchLabelId: value}, () => {
+ console.log(this.state.selectedSearchLabelId);
+ })
+ }
+
+ renderModalEditLayerDetails = () => {
+
+ const {layer_details_contents} = this.state
+ return (
+ Loading...
+
+ getLayerList = async () => {
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ let layers = [];
+
+ try {
+ const result = await fetch(API_LAYER_LIST, param).then(response => response.json()).then(res => res)
+ // console.log(result);
+ if (result.data){
+ if (result.data.length > 0) {
+ // for(let i=0; i < result.data.length; i++) {
+
+ // }
+ this.setState({layers: result.data}, () => {
+ // console.log(this.state.layers);
+ });
+ }
+ } else {
+ // this.setState({chartTypeGeometry: doughnut});
+ }
+ } catch(err) {
+ console.log(err);
+ alert(err.message.toString());
+ // this.setState({alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true})
+ }
+ }
+
+ handleChangeSearchLayer = (event) => {
+ event.preventDefault();
+ let value = event.target.value.toLowerCase();
+ this.setState({searchInput: value}, () => {
+ this.returnSearchData(this.state.searchInput);
+ });
+ }
+
+ returnSearchData = (value) => {
+ let filteredFeatures = [];
+ if (value === '') {
+ return this.state.layers;
+ }
+ else {
+ filteredFeatures = this.state.layers.filter((result) => {
+ /*if (result.id.toLowerCase().includes(this.state.searchInput)) {
+ return result.id.toLowerCase().includes(this.state.searchInput);
+ }
+ else {
+ for (let key in result.properties) {
+ if (result.properties[key] !== null ) {
+ if (result.properties[key].toString().toLowerCase().includes(this.state.searchInput)) {
+ return result.properties[key].toString().toLowerCase().includes(this.state.searchInput);
+ }
+ }
+ }
+ }*/
+ for (let key in result) {
+ if (result[key] !== null) {
+ if (result[key].toString().toLowerCase().includes(this.state.searchInput)) {
+ return result[key].toString().toLowerCase().includes(this.state.searchInput);
+ }
+ }
+ }
+ // console.log(result);
+ });
+ return filteredFeatures;
+ }
+ }
+
+ renderList = () => {
+ let searchData = this.returnSearchData(this.state.searchInput);
+ console.log('searchData', searchData);
+ if (searchData.length > 0) {
+ return searchData.map((item, index) => {
+ let layerDetailUrl = `layers/${item.resourcebase_ptr_id}`;
+ let layerThumbnailSrc = layerThumbnailUrl(item.name);
+ return (
+ Loading...
+
+ // ngerequest API buat ngepush ke this.waspangFeatures
+ getDataUserToProyek = async () => {
+ const { chosenProyekIds } = this.state;
+ let payload = {
+ "columns": [],
+ "joins": [
+ {
+ "name": "m_proyek",
+ "column_join": "proyek_id",
+ "column_results": [
+ "nama",
+ "biaya",
+ "color_progress",
+ "jumlah_pekerja",
+ "pic",
+ "mulai_proyek",
+ "akhir_proyek"
+ ]
+ },
+ {
+ "name": "m_subproyek",
+ "column_join": "subproyek_id",
+ "column_results": [
+ "nama",
+ "biaya",
+ "color_progress",
+ "jumlah_pekerja",
+ "pic",
+ "mulai_proyek",
+ "akhir_proyek"
+ ]
+ },
+ {
+ "name": "m_users",
+ "column_join": "user_id",
+ "column_results": [
+ "name",
+ "username",
+ "email",
+ "phone_number",
+ "gender"
+ ]
+ }
+ ],
+ "orders": {
+ "columns": [
+ "id"
+ ],
+ "ascending": true
+ },
+ "paging": {
+ "start": 0,
+ "length": 25
+ }
+ }
+
+ if (chosenProyekIds.length > 0) {
+ payload.columns.push({
+ "name": "proyek_id",
+ "logic_operator": "in",
+ "value": chosenProyekIds.join(),
+ "operator": "AND"
+ });
+ }
+
+ // if(parseInt(localStorage.getItem('role_id'))!==1){
+ // payload.columns.push(
+ // {
+ // "name": "id",
+ // "logic_operator": "=",
+ // "value": localStorage.getItem('proyek_id'),
+ // "operator": "AND"
+ // }
+ // )
+ // }
+
+ const config = {
+ method: 'POST', // *GET, POST, PUT, DELETE, etc.
+ // mode: 'cors', // no-cors, *cors, same-origin
+ // cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+ // credentials: 'same-origin', // include, *same-origin, omit
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer '+window.localStorage.getItem('token')
+ // 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ // redirect: 'follow', // manual, *follow, error
+ // referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
+ body: JSON.stringify(payload) // body data type must match "Content-Type" header
+ }
+
+ const result = await fetch(USERPROYEK_SEARCH, config).then(response => response.json()).then(res => res);
+ if (result && result.code == 200) {
+ // this.getWaspangFeatures(result.data);
+ this.setState({waspangData: result.data}, () => this.getWaspangFeatures());
+ } else {
+ toast.error('Gagal Mengambil Data!!');
+ }
+ }
+
+ // ngerequest API buat ngepush data chart
+ // (dataStatusProyek,
+ // dataPersentaseProyek,
+ // dataCostProyek,
+ // dataStatusWaspang)
+ getChartData = async () => {
+ const { chosenProyekIds } = this.state;
+ let payload = {
+ "columns": [],
+ "orders": {
+ "columns": [
+ "id"
+ ],
+ "ascending": true
+ }
+ }
+
+ if (chosenProyekIds.length > 0) {
+ payload.columns.push({
+ "name": "id",
+ "logic_operator": "in",
+ "value": chosenProyekIds.join(),
+ "operator": "AND"
+ });
+ }
+
+ // if(parseInt(localStorage.getItem('role_id'))!==1){
+ // payload.columns.push(
+ // {
+ // "name": "id",
+ // "logic_operator": "=",
+ // "value": localStorage.getItem('proyek_id'),
+ // "operator": "AND"
+ // }
+ // )
+ // }
+
+ const config = {
+ method: 'POST', // *GET, POST, PUT, DELETE, etc.
+ // mode: 'cors', // no-cors, *cors, same-origin
+ // cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+ // credentials: 'same-origin', // include, *same-origin, omit
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer '+window.localStorage.getItem('token')
+ // 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ // redirect: 'follow', // manual, *follow, error
+ // referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
+ body: JSON.stringify(payload) // body data type must match "Content-Type" header
+ }
+
+ const result = await fetch(DASHBOARD_STATUS_SEARCH, config).then(response => response.json()).then(res => res);
+ if (result && result.code == 200) {
+ const { persentase_progress_plan, persentase_progress_actual, progress_cost_planning, progress_cost_realisasi, status_proyek } = result.data
+
+ const labelPersentaseProyek = persentase_progress_plan ? persentase_progress_plan.map(res => res.label) : []
+ const valuePersentaseProyekPlan = persentase_progress_plan ? persentase_progress_plan.map(res => res.total) : []
+ const valuePersentaseProyekActual = persentase_progress_actual ? persentase_progress_actual.map(res => res.total) : []
+ const persentaseProyek = {
+ labels: labelPersentaseProyek,
+ datasets: [
+ {
+ label: 'Perencanaan',
+ data: valuePersentaseProyekPlan,
+ fill: false,
+ backgroundColor: 'rgb(255, 99, 132)',
+ borderColor: 'rgba(255, 99, 132, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ {
+ label: 'Realisasi',
+ data: valuePersentaseProyekActual,
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+ };
+ this.setState({dataPersentaseProyek: persentaseProyek});
+
+ const labelCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.label) : []
+ const valueCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.total) : []
+ const valueCostRealisasi = progress_cost_realisasi ? progress_cost_realisasi.map(res => res.total) : []
+
+ const costProyek = {
+ labels: labelCostPlaning,
+ datasets: [
+ {
+ label: 'Perencanaan',
+ data: valueCostPlaning,
+ fill: false,
+ backgroundColor: 'rgb(255, 99, 132)',
+ borderColor: 'rgba(255, 99, 132, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ {
+ label: 'Realisasi',
+ data: valueCostRealisasi,
+ fill: false,
+ backgroundColor: 'rgb(54, 162, 235)',
+ borderColor: 'rgba(54, 162, 235, 0.2)',
+ yAxisID: 'y-axis-1',
+ },
+ ],
+ };
+ this.setState({dataCostProyek: costProyek});
+
+ const valueStatusProyek = status_proyek ? status_proyek.map(res => res.total) : []
+
+ const statusProyek = {
+ labels: ['Aman', 'Alert', 'Critical'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: valueStatusProyek,
+ backgroundColor: [
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(255, 99, 132, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(255, 99, 132, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+ };
+ this.setState({dataStatusProyek: statusProyek});
+ } else {
+ toast.error('Gagal Mengambil Data!!');
+ }
+ }
+
+ getDailyInfo = async () => {
+ const payload = {
+ "columns": [
+ {"name": "created_at","logic_operator": "range","value": `${moment().format('YYYY-MM-DD')} 00:00:00`,"value1": `${moment().format('YYYY-MM-DD')} 23:59:59`,"operator": "AND"}
+ ],
+ "paging": {"start": 0,"length": -1}
+ }
+
+ const config = {
+ method: 'POST', // *GET, POST, PUT, DELETE, etc.
+ // mode: 'cors', // no-cors, *cors, same-origin
+ // cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+ // credentials: 'same-origin', // include, *same-origin, omit
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer '+window.localStorage.getItem('token')
+ // 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ // redirect: 'follow', // manual, *follow, error
+ // referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
+ body: JSON.stringify(payload) // body data type must match "Content-Type" header
+ }
+ try {
+ const result = await fetch(DASHBOARD_PROYEK_SEARCH, config).then(response => response.json()).then(res => res);
+ console.log('getDailyInfo result', result);
+ if (result.code === 200 && result.data) {
+ const dataSum = result.data;
+ // this.setState({
+ // planning: dataSum.planning,
+ // realisasi: dataSum.realisasi,
+ // status_project: dataSum.status_project,
+ // waspang_status: dataSum.waspang_status,
+ // panic_button: dataSum.panic_button,
+ // isReady: true
+ // });
+
+ const statusWaspang = {
+ labels: ['Hadir', 'Izin', 'Panic Button'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: [dataSum.waspang_status.presensi, dataSum.waspang_status.absensi, dataSum.panic_button],
+ backgroundColor: [
+ 'rgba(77,232,0, 0.2)',
+ 'rgba(255,146,3, 0.2)',
+ 'rgba(164,7,120, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(77,232,0, 1)',
+ 'rgba(255,146,3, 1)',
+ 'rgba(164,7,120, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+ };
+ this.setState({dataStatusWaspang: statusWaspang});
+
+
+ }
+ // const result = await axios
+ // .get(DASHBOARD_PROYEK_SEARCH, config)
+ // .then(res => res)
+ // .catch((error) => error.response);
+
+ // console.log('result', result);
+
+ // if (result && result.data && result.data.code == 200) {
+ // const dataSum = result.data;
+ // this.setState({
+ // planning: dataSum.planning,
+ // realisasi: dataSum.realisasi,
+ // status_project: dataSum.status_project,
+ // waspang_status: dataSum.waspang_status,
+ // panic_button: dataSum.panic_button,
+ // isReady: true
+ // });
+ // }
+ }
+ catch (e) {
+ toast.error('Gagal mengambil data');
+ // return false;
+ }
+ }
+
+ getLayerSearchLabel = async() => {
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_SEARCH_LABEL, param).then(response => response.json()).then(res => res)
+ if (result.data){
+ if (result.data.length > 0) {
+ // console.log('getLayerSearchLabel result', result);
+ this.setState({
+ searchLabelData: result.data
+ }, () => console.log('getLayerSearchLabel searchLabelData', this.state.searchLabelData));
+ }
+ } else {
+
+ }
+ } catch(err) {
+ console.log(err);
+ // alert(err.message.toString());
+ // toast.warn(err.message.toString());
+ }
+ }
+
+
+ getLayerInfo = async () => {
+ let layerInfo = [];
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_GET_CHART_KATEGORI, param).then(response => response.json()).then(res => res)
+ // console.log(result)
+
+ if(result.data){
+ if (result.data.length > 0) {
+ for(let i=0; i < result.data.length; i++) {
+ let layer_name = result.data[i].layer_name;
+ let layer_title = result.data[i].layer_title;
+ let layer_geom_type = result.data[i].layer_geom_type;
+ let total_features = result.data[i].total_features;
+
+ let SLD_URL = `${layerStyleUrl+layer_name}`;;
+ let reqColor = await getLayerColor(SLD_URL);
+ let color = '';
+ if (reqColor.success) {
+ color = reqColor.result;
+ }
+ layerInfo.push({
+ layer_name: layer_name,
+ layer_title: layer_title,
+ layer_geom_type: layer_geom_type,
+ layer_color: color,
+ total_features: total_features
+ });
+ }
+ this.setState({layerInfo: layerInfo}, () => console.log('layerInfo',this.state.layerInfo));
+ }
+ // this.setState({alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false})
+ } else {
+ // this.setState({chartKategori: pie});
+ // this.setState({alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true})
+ }
+ } catch(err) {
+ console.log(err);
+ // alert(err.message.toString());
+ // toast.warn(err.message.toString());
+ // this.setState({alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true})
+ }
+ }
+
+ setDefaultMap = () => {
+ this.olmap.getView().animate({
+ zoom: zoom,
+ center: Indonesia
+ });
+ }
+
+ changeBaseLayer(item) {
+ console.log('change baselayer', item);
+ // console.log(this.olmap.getLayers());
+ if (this.olmap.getLayers().values_.length == 0) {
+ // check if layers empty, so just insert base layer to position 0
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // check if layer exist
+ else if (this.olmap.getLayers().values_.length > 0) {
+ // check the position 0, if base layer then replace to new
+ if (this.olmap.getLayers().array_[0].get('type') === 'base') {
+ this.olmap.getLayers().removeAt(0);
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // else just insert base layer at position 0
+ else {
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ }
+ }
+
+ getHomeView = () => {
+ // this should request to siopas map api to get current map
+ // this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ const { mapZoom, mapCenter } = this.state;
+ if (mapZoom && mapCenter !== null) {
+ this.olmap.getView().animate({
+ zoom: mapZoom,
+ center: mapCenter
+ });
+ }
+ else {
+ // alert("Map Zoom and Map Center are not set yet");
+ this.olmap.getView().animate({
+ zoom: zoom,
+ center: Indonesia
+ });
+ }
+ }
+
+ mapOnClick = (evt) => {
+ evt.preventDefault();
+ let isDrawing = false;
+ let removedFeature = [];
+ let isRemoving = false;
+ let transformedCoords4326 = transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');
+ // console.log('transformedCoords4326', transformedCoords4326);
+
+ let mapInteractions = [];
+ this.olmap.getInteractions().forEach((interaction) => {
+ // console.log('interaction', interaction);
+ if (interaction instanceof Draw) {
+ console.log('drawing is active!!');
+ isDrawing = true;
+ }
+ // if (interaction instanceof Select) {
+ // console.log('select interaction is active');
+ // isRemoving = true;
+ // }
+
+ if (interaction instanceof Modify) {
+ console.log('modify feature is active');
+ isDrawing = true;
+ }
+ });
+
+ if (isDrawing) {
+ return;
+ }
+
+ let viewResolution = this.olmap.getView().getResolution();
+ let viewProjection = this.olmap.getView().getProjection();
+ let url = '';
+ let promises = [];
+ let featureGet = [];
+
+ let hitGeojson = null;
+
+ this.olmap.getLayers().forEach((layer, i) => {
+ console.log('layer', layer.get('name'));
+ if (layer.get('type') !== 'base') {
+ if (layer.get('type') == 'layerGroup') {
+ layer.getLayers().forEach((sublayer, i) => {
+ if (sublayer.getVisible()) {
+ url = sublayer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ });
+ }
+ else {
+ if (layer.getVisible()) {
+ if (layer.get('name') !== 'ChosenLayer') {
+ if (layer.get('source_type') && layer.get('source_type') === 'geojson') {
+ let layerSource = layer.getSource();
+ hitGeojson = this.olmap.getFeaturesAtPixel(evt.pixel);
+ console.log('hitGeojson', hitGeojson);
+ }
+ else if (layer.get('source_type') === "wms") {
+ url = layer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+
+
+ if (hitGeojson && hitGeojson.length > 0) {
+ for (let i=0; i < hitGeojson.length; i++) {
+ let feature = hitGeojson[i];
+
+ let feat = {
+ "type": "Feature",
+ "id": "",
+ "geometry": {
+ "type": "",
+ "coordinates": []
+ },
+ "geometry_name": "the_geom",
+ "properties": {}
+ }
+
+ feat.id = feature.id_;
+ feat.geometry.type = feature.getGeometry().getType();
+ // feat.geometry.coordinates = transform(feature.getGeometry().getCoordinates(), 'EPSG:3857', 'EPSG:4326');
+ feat.geometry.coordinates = feature.getGeometry().getCoordinates();
+ feat.properties = feature.getProperties();
+ delete feat.properties["geometry"];
+
+ console.log('feat', feat);
+ featureGet.push(feat);
+ }
+
+ console.log('featureGet geojson', featureGet);
+ }
+
+
+ // kalo dari WMS
+ if (promises.length > 0) {
+ axios.all(promises).then((results) => {
+ results.forEach((response) => {
+ console.log('mapOnClick response promises', response);
+ if (response.data !== undefined) {
+ if (response.data.features.length > 0) {
+ for(let i=0; i < response.data.features.length; i++) {
+ featureGet.push(response.data.features[i]);
+ }
+ }
+ }
+ })
+
+
+ console.log('featureGet WMS', featureGet);
+
+ // adding it here because it's trapped on axios callback
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ }, () => this.setActiveListFeature());
+ });
+ }
+
+ if (hitGeojson && promises) {
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ }, () => this.setActiveListFeature());
+ }
+ }
+
+ removeChosenLayer = () => {
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer) {
+ if (layer.get('name') !== undefined && layer.get('name') === 'ChosenLayer' ) {
+ layer.getSource().clear();
+ this.olmap.removeLayer(layer);
+ }
+ }
+ });
+ }
+
+ openPopupRight() {
+ // console.log('opening popup right...')
+ this.setState({popupRightVisible: true}, () => this.setActiveListFeature());
+ }
+
+ closePopupRight() {
+ // console.log('closing popup right...')
+ this.setState({popupRightVisible: false, popupDataTemp: []}, () => this.setActiveListFeature());
+ this.removeChosenLayer(); // selected features
+ // this.removeLayerByName('routeLayer');
+ this.setState({editGeometryVisible: false, routingBarVisible: false}); // disable editing when no ChosenLayer on Map
+ }
+
+ /*toggleImagePopup() {
+ this.setState({imagePopupVisible: !this.state.imagePopupVisible});
+ }*/
+
+ setPopupDataTemp = (feature) => {
+ // console.log('setPopupDataTemp', feature);
+ this.setState({popupDataTemp: [feature]}, () => this.setActiveListFeature());
+ }
+
+ reloadPopupData = () => {
+ const { evtCoordinate } = this.state;
+ }
+
+ setActiveListFeature = () => {
+ // console.log('this.state.popupDataTemp', this.state.popupDataTemp);
+ if (this.state.popupRightVisible) {
+ if (this.state.popupDataTemp.length === 1) {
+ this.setState({activeListFeatureId: this.state.popupDataTemp[0].id}, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ let layerName = this.state.activeListFeatureId ? this.state.activeListFeatureId.substr(0, this.state.activeListFeatureId.indexOf('.')) : '';
+ this.getLayerAttribute(layerName);
+ })
+ }
+ else {
+ this.setState({activeListFeatureId: ''}, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ })
+ }
+ }
+ else {
+ this.setState({activeListFeatureId: ''}, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ })
+ }
+ }
+
+ // getGeomType = async (layerName) => {
+
+ // let res = await getGeomType(layerName);
+ // console.log('getGeomType', res);
+ // return res;
+ // }
+
+ loadMap = async () => {
+ let response = await axios.get(API_LOAD_MAP).then(res => res).catch(error => error);
+ console.log('loadMap', response);
+ // this.getHomeView(response);
+ // this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ if (response.data !== undefined) {
+ if (response.data.length > 0) {
+ let dataMap = response.data[0];
+ let layersToRemove = [];
+
+ // if the API response about zoom is null
+ if (dataMap.zoom == null) {
+ this.setDefaultMap();
+ }
+ // if the API response about center_x and center_y is null
+ else if (dataMap.center_x == null && dataMap.center_y == null ) {
+ this.setDefaultMap();
+ }
+ // otherwise, add layer to map from map_layer response
+ else {
+ // set the zoom and center
+ this.setState({mapZoom: dataMap.zoom, mapCenter: [dataMap.center_x, dataMap.center_y]});
+ this.olmap.getView().animate({
+ zoom: dataMap.zoom,
+ center: [dataMap.center_x, dataMap.center_y]
+ });
+
+ // if map_layers from API is exist
+ if (dataMap.map_layers.length > 0) {
+ // first, removing all layers from the current map
+ this.olmap.getLayers().forEach((layer, i) => {
+ layersToRemove.push(layer);
+ });
+ if (layersToRemove.length > 0) {
+ for(let i=0; i < layersToRemove.length; i++) {
+ this.olmap.removeLayer(layersToRemove[i]);
+ }
+ }
+
+ // add map_layers from api to view
+ if (this.olmap.getLayers().array_.length < 1) {
+ // console.log('layer empty', response.data);
+ let map_layers = dataMap.map_layers;
+ if (map_layers !== undefined) {
+ // console.log('ada map_layers', map_layers);
+ if (map_layers.length > 0) {
+ for (let i=0; i < map_layers.length; i++) {
+ let newLayer = null;
+
+ // if layer_type is not base
+ if (map_layers[i].layer_type !== 'base') {
+ newLayer = new ImageLayer({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new OlSourceImageWMS(map_layers[i].layer_source),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ // if layer_type is base
+ else {
+ // if base is OSM (OlSourceOsm);
+ if (map_layers[i].layer_name == 'OSM') {
+ newLayer = new OlLayerTile({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new OlSourceOsm(),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ // if base is other than OSM
+ else {
+ newLayer = new OlLayerTile({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new XYZSource(map_layers[i].layer_source),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ }
+
+ // console.log('adding new layer', newLayer);
+
+ // add the map_layers from API
+ this.olmap.addLayer(newLayer);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ saveMap = () => {
+ /* What map update data that are needed?
+ - title of map (o)
+ - zoom
+ - projection
+ - center_x
+ - center_y
+ - base_layer_id
+ - mapLayers[]
+ - layer_name
+ - layer_type (base / layer)
+ - layer_geom_type
+ - layer_source
+ - layer_visible
+ - layer_position
+
+ Example of layer_source:
+ {
+ url: appConfig.geoserver_host+'wms',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':tanah_sekolah',
+ 'TILED': true,
+ 'SLD': layerStyleUrl+'tanah_sekolah'
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous'
+ }
+ */
+ let confirmation = window.confirm('Are you sure you want to save this map?');
+ // let mapId = localStorage.getItem('u_group') === "kominfo" ? 2 : 1;
+ let mapId = MAP_ID; // get from m_group
+ let mapTitle = localStorage.getItem('u_group')+"_map"; // get from m_group
+ let mapZoom = this.olmap.getView().getZoom();
+ let mapProjection = this.olmap.getView().getProjection().code_;
+ let mapCenter = this.olmap.getView().getCenter();
+ let center_x = mapCenter[0]; // longitude
+ let center_y = mapCenter[1]; // latitude
+ let mapLayers = [];
+ let requestPayload = null;
+ let layerType = '';
+ let layerGeomType = '';
+ let count = 0;
+
+ if (confirmation) {
+ this.olmap.getLayers().forEach( async (layer, i) => {
+
+ // console.log('layer after confirmation i', i, layer);
+ layerType = layer.get('type') !== undefined ? layer.get('type') : 'layer';
+
+ if (layer.get('name') !== "DrawingLayer" && layer.get('name') !== "ChosenLayer") {
+ if (layer.get('type') === "base") {
+ if (layer.get('name') === "OSM") {
+ // if the baselayer is OSM, use the OSM function from openlayers
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: 'base',
+ layer_source: "OlSourceOsm", // i don't know why null in database
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ else {
+ // or if the baselayer is other than OSM (such as ESRI, Google, etc), use the XYZSource
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: 'base',
+ layer_source: {
+ // url: 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
+ url: layer.getSource().urls[0],
+ projection: mapProjection,
+ maxZoom: 18
+ },
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ }
+ else {
+ // if the layer is not base layer
+ // layerGeomType = layer.get('geom_type') !== undefined ? layer.get('geom_type') : await this.getGeomType(layer.get('name'));
+ let reqGeomType = await getGeomType(layer.get('name'));
+ if (reqGeomType.success) {
+ layerGeomType = reqGeomType.result;
+
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: layerGeomType,
+ layer_source: {
+ url: appConfig.geoserver_host+'wms',
+ // url: appConfig.geoserver_host+'gwc/service/wms?SERVICE=WMS',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':'+layer.get('name'),
+ 'TILED': true,
+ 'SLD': layerStyleUrl+layer.get('name')
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous'
+ },
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ }
+ }
+ count = count + 1;
+
+ // the last loop, so send to updateMap API
+ // console.log('count', count);
+ // console.log('this.olmap.getLayers().array_.length',this.olmap.getLayers().array_.length);
+ // console.log('if count==this.olmap.getLayers().array_length', count == this.olmap.getLayers().array_.length);
+ if (count == this.olmap.getLayers().array_.length) {
+ console.log('terakhirrrrrr');
+ requestPayload = {
+ 'map_id': mapId,
+ 'map_title': mapTitle,
+ 'map_zoom': mapZoom,
+ 'map_projection': mapProjection,
+ 'center_x': center_x,
+ 'center_y': center_y,
+ 'map_layers': mapLayers
+ };
+ console.log('requestPayload',requestPayload);
+ this.saveMapToApi(requestPayload);
+ }
+ });
+ }
+ }
+
+ saveMapToApi = async (requestPayload) => {
+
+ const param = {
+ method: 'POST',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ body: JSON.stringify(requestPayload)
+ }
+
+ try {
+ const result = await fetch(API_UPDATE_MAP, param).then(response => response.json()).then(res => res)
+ if(result.data){
+ console.log('after save',result);
+ // this.();
+ this.setState({alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false})
+ } else {
+ this.setState({alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true})
+ }
+ } catch(err) {
+ this.setState({alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true})
+ }
+ }
+
+ toggleEditGeometry = (selectedPopupData) => {
+ let { editGeometryVisible } = this.state;
+ if (!editGeometryVisible) {
+ this.setState({
+ editGeometryVisible: true,
+ layerNameDraw: selectedPopupData.id,
+ geomTypeDraw: selectedPopupData.geometry.type
+ });
+
+ }
+ else {
+ this.cancelDraw();
+ }
+ }
+
+ cancelDraw = () => {
+ this.setState({
+ editGeometryVisible: false,
+ layerNameDraw: '',
+ geomTypeDraw: ''
+ });
+ }
+
+ toggleActiveStateAddGeometry = () => {
+ this.setState({activeStateAddGeometry: !this.state.activeStateAddGeometry});
+ }
+
+ printMap = () => {
+ this.olmap.once('rendercomplete', () => {
+ domtoimage
+ .toJpeg(this.olmap.getViewport())
+ .then((dataUrl) => {
+ console.log('dataUrl', dataUrl);
+ let link = document.getElementById('image-download');
+ link.href = dataUrl;
+ link.click();
+ toast.success("Success Print Map!")
+ })
+ .catch(e => toast.error(e.toString()));
+ });
+
+ }
+
+ signOut = (e) => {
+ e.preventDefault()
+ // localStorage.removeItem("u_group");
+ // localStorage.removeItem("fullname");
+ window.localStorage.clear();
+ // emptyConstants();
+ this.props.history.push('/login');
+ }
+
+ getLayerAttribute = async (layerName) => {
+ const res = await getLayerAttribute(layerName);
+ console.log('getLayerAttribute',res);
+ if (res.success) {
+ // console.log(res.result);
+ if (res.result.data) {
+ if (res.result.data.length > 0) {
+ this.setState({layer_attribute: res.result.data}, () => {
+ console.log(this.state.layer_attribute);
+ });
+ }
+ }
+ }
+ else {
+ // alert(res.result);
+ toast.warn(res.result);
+ }
+ }
+
+ // when checking chekbox on Layer Tree Panel
+ onCheckOpt = (state, checkedKeys) => {
+ this.setState({[state]: checkedKeys});
+ }
+
+ setLayer = async (state) => {
+ console.log('setLayer', state);
+
+ await this.setState({isProcessing: true});
+
+ this.closePopupRight();
+
+ const { checkedKeysSales, checkedKeysCustomer, checkedKeysOffice, checkedKeysDemografi, checkedKeysAnalisa, checkedKeysEmployeeDivision,
+ salesGroupTree, employeeDivisionTree, queryBuilderOutput, queryBuilderType, checkedKeysProjectTree, projectTree } = this.state;
+ let layersToAdd = [];
+ let newLayer = null;
+ let vectorSource = null;
+ let vectorLayer = null;
+
+ if (state === 'checkedKeysProjectTree') {
+ console.log('checkedKeysProjectTree', checkedKeysProjectTree);
+
+ // first remove projectLayer and its features
+ this.removeLayerByName('routeLayer');
+ this.removeLayerByName('projectLayer');
+ this.removeLayerByName('waspangLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+
+ this.getChosenProyekRealisasi();
+
+ if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+
+ /*
+ Logic:
+ - looping all tree
+ - there are 3 variables
+ 1. features (Array) -> untuk nampung features yg ada di laporan planning
+ 2. projectTree (Array)
+ 3. checkedKeysProjectTree (Array) -> projectTree yg tercentang
+
+ Jadi looping all nesting yg ada di projectTree (ambil object children)
+ Terus cek setiap levelnya dia ada di checkedKeysProjectTree gak?
+ Jika ada, cek apakah di object tersebut mengandung key namanya "plannings" tidak?
+ Jika iya, maka cek di dalamnya ada laporan_planning tidak?
+ Jika iya, maka push ke features[] dengan format:
+ {
+ "type": "Feature",
+ "properties": {}, // isian dari objectnya
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 107.90771484375, // object.lon
+ -6.795535025719518 // object.lat
+ ]
+ }
+ }
+ */
+
+ this.getChildrenTree(projectTree[0].children);
+ // this.getWaspangFeatures();
+
+ console.log('projectFeatures', this.projectFeatures);
+ // console.log('waspangFeatures', this.waspangFeatures);
+
+ let project = null;
+ project = {
+ type: "FeatureCollection",
+ features: this.projectFeatures
+ }
+
+ // console.log('project', project);
+
+
+ // generate new layer
+ if (project && project.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(project, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'projectLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: PROJECT_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ toast.warn('Data realisasi tidak ditemukan di project ini');
+ }
+
+ }
+ else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ this.removeLayerByName('projectLayer');
+ this.removeLayerByName('waspangLayer');
+ this.removeLayerByName('routeLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+ this.closePopupRight();
+ }
+ }
+
+ if (layersToAdd.length > 0) {
+ for (let i=0; i < layersToAdd.length; i++) {
+
+ this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+
+ console.log('check addLayer');
+ if (i === layersToAdd.length - 1) {
+ let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ if (extent) {
+ this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+ }
+ }
+ }
+
+ // this.olmap.getLayers().forEach((layer, i) => {
+ // console.log('getLayers', layer);
+ // });
+
+ await this.setState({isProcessing: false});
+ }
+
+ // find the lat lon inside laporan_plannings that the planning has been checked on projectTree
+ getChildrenTree = (data) => {
+ data.map((item, index) => {
+ if (item.children && item.children.length > 0) {
+ this.getChildrenTree(item.children);
+ }
+ else if (item.laporan_plannings && item.laporan_plannings.length > 0) {
+ if (this.state.checkedKeysProjectTree.includes(item.key)) {
+ for (let i=0; i < item.laporan_plannings.length; i++) {
+ console.log('got features!!!!!');
+ this.projectFeatures.push({
+ "type": "Feature",
+ "id": `realisasi.${item.laporan_plannings[i].id}`,
+ "properties": {...item.laporan_plannings[i]},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ item.laporan_plannings[i].lon,
+ item.laporan_plannings[i].lat
+ ]
+ }
+ })
+ }
+ }
+ }
+ });
+
+ // console.log('features end....', features);
+
+ // return features;
+ }
+
+ getWaspangFeatures = async () => {
+ // console.log('getWaspangFeatures', data);
+ const { waspangData, checkedKeysProjectTree } = this.state;
+ if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+ if (waspangData.length > 0) {
+ for (let i=0; i < waspangData.length; i++) {
+ let item = waspangData[i];
+ if (item.last_waypoint) {
+ this.waspangFeatures.push({
+ "type": "Feature",
+ "id": `m_waspang.${item.id}`,
+ "properties": {
+ "id": item.id,
+ "user_id": item.user_id,
+ "nama_user": item.join.m_users_name,
+ "nama_proyek": item.join.m_proyek_nama,
+ "mulai_tugas": item.mulai,
+ "akhir_tugas": item.akhir,
+ "_type": "waspang"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ item.last_waypoint.lon,
+ item.last_waypoint.lat
+ ]
+ }
+ })
+ }
+ }
+
+ console.log('this.waspangFeatures', this.waspangFeatures);
+
+ let layersToAdd = [];
+ let vectorSource = null;
+ let vectorLayer = null;
+ let waspang = null;
+ waspang = {
+ type: "FeatureCollection",
+ features: this.waspangFeatures
+ }
+
+ // generate new layer
+ if (waspang && waspang.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(waspang, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'waspangLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: WASPANG_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ toast.warn('Data waspang tidak ditemukan di project ini');
+ }
+
+ if (layersToAdd.length > 0) {
+ for (let i=0; i < layersToAdd.length; i++) {
+
+ this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+
+ console.log('check addLayer');
+ if (i === layersToAdd.length - 1) {
+ let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ if (extent) {
+ this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ this.removeLayerByName('projectLayer');
+ this.removeLayerByName('waspangLayer');
+ this.removeLayerByName('routeLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+ this.closePopupRight();
+ }
+
+ // this.waspangFeatures = [{
+ // "type": "Feature",
+ // "id": `m_waspang.1`,
+ // "properties": {
+ // "id": 1,
+ // "user_id": 10,
+ // "nama_user": "Ryan",
+ // "nama_proyek": "FTTH Paket 2",
+ // "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ // "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ // "_type": "waspang"
+ // },
+ // "geometry": {
+ // "type": "Point",
+ // "coordinates": [
+ // 106.89285278320312,
+ // -6.228275226686636
+ // ]
+ // }
+ // },
+ // {
+ // "type": "Feature",
+ // "id": `m_waspang.2`,
+ // "properties": {
+ // "id": 2,
+ // "user_id": 12,
+ // "nama_user": "Effendi",
+ // "nama_proyek": "FTTH Paket 2",
+ // "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ // "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ // "_type": "waspang"
+ // },
+ // "geometry": {
+ // "type": "Point",
+ // "coordinates": [
+ // 106.9357681274414,
+ // -6.267522831839373
+ // ]
+ // }
+ // },
+ // {
+ // "type": "Feature",
+ // "id": `m_waspang.3`,
+ // "properties": {
+ // "id": 1,
+ // "user_id": 16,
+ // "nama_user": "Waspang C",
+ // "nama_proyek": "FTTH Paket 2",
+ // "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ // "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ // "_type": "waspang"
+ // },
+ // "geometry": {
+ // "type": "Point",
+ // "coordinates": [
+ // 106.80564880371092,
+ // -6.263086293713913
+ // ]
+ // }
+ // }]
+ }
+
+ findChildLayerToRemove = (parentObj) => {
+
+ let layersToRemove = [];
+
+ if (parentObj.hasOwnProperty('children')) {
+
+ // get semua children layer name nya
+ for (let i=0; i < parentObj.children.length; i++) {
+ // newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+
+ layersToRemove.push(parentObj.children[i].layers.name)
+ }
+ }
+ else {
+ layersToRemove.push(parentObj.layers.name)
+ }
+
+ return layersToRemove;
+
+ }
+
+ // findChildLayerToAdd = (parentObj) => {
+ // for (let i=0; i < parentObj.length; i++) {
+
+ // }
+ // }
+
+ findChildLayerToAdd = (parentObj, checkedKeys) => {
+
+ let layersToAdd = [];
+ let newLayer = null;
+
+ // 1. cek apakah parentObj itu kecentang atau ngga
+ // 2. cek apakah parentObj itu punya child apa ngga
+ // kalo kecentang parent nya ya berarti loop aja
+ // 3. cek apakah childnya itu kecentang ngga
+
+ console.log('parentObj', parentObj);
+
+ if (checkedKeys.includes(parentObj["key"])) {
+ if (parentObj.hasOwnProperty('children')) {
+ // loop aja semua child layernya
+ for (let i=0; i < parentObj.children.length; i++) {
+ newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ newLayer = this.generateLayerWMSByName(parentObj.layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ if (parentObj.hasOwnProperty('children')) {
+
+ }
+
+ }
+
+ // // tapi dicek lagi kalo childrennya punya children
+ // if (parentObj.hasOwnProperty('children')) {
+
+ // // cek apakah parent nya kecentang gak? (berdasarkan key)
+ // if (checkedKeys.includes(parentObj["key"])) {
+
+ // // centang semua children nya
+ // for (let i=0; i < parentObj.children.length; i++) {
+ // newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+ // }
+ // }
+ // // just activate the selected nya aja
+ // else {
+ // // for (let i=0; i < checkedKeys.length; i++ ) {
+ // // let obj = parentObj.children.find(data => data.key == checkedKeys[i])
+ // // console.log('ngecek obj', obj);
+ // // newLayer = this.generateLayerWMSByName(obj.layers.name);
+ // // if (newLayer) {
+ // // layersToAdd.push(newLayer);
+ // // }
+ // // }
+ // }
+ // }
+ // else {
+ // newLayer = this.generateLayerWMSByName(parentObj.layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+ // }
+
+ return layersToAdd;
+
+ }
+
+ getExtentLayerByName = async (layer) => {
+
+ // console.log('getExtentLayerByName', layerName, source_type);
+
+ let layerName = layer.get('name');
+ let source_type = layer.get('source_type');
+
+ // if source_type is undefined = WMS
+ // otherwise source_type is not undefined = geojson
+
+ let extent = null;
+
+ if (source_type === 'wms') {
+ let getExt = await fetch(WMS_CAPABILITIES_URL_2).then((response) => {
+ return response.text();
+ }).then((text) => text);
+
+ let result = new WMSCapabilities().read(getExt);
+ if (result && result.Capability.Layer.Layer.find(l => l.Name === appConfig.workspace_name+':'+layerName)) {
+ extent = result.Capability.Layer.Layer.find(l => l.Name === appConfig.workspace_name+':'+layerName).EX_GeographicBoundingBox;
+ }
+ }
+ else if (source_type === 'geojson') {
+ // extent = layer.getSource().getExtent();
+
+ // layer.getSource().once('change',(e) => {
+ // if (layer.getSource().getState() === 'ready') {
+ // extent = layer.getSource().getExtent();
+ // console.log('extent------------', extent);
+ // // map.getView().fit(extent, map.getSize());
+ // }
+ // });
+ extent = null
+ }
+ console.log('extent', extent);
+ return extent;
+
+ }
+
+ generateLayerWMSByName = (layerName) => {
+ let theLayer = null;
+ if (layerName) {
+ theLayer = new OlLayerTile({
+ name: layerName,
+ source_type: 'wms',
+ source: new OlSourceTileWMS({
+ url: appConfig.geoserver_host+'wms',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':'+layerName,
+ 'TILED': true,
+ 'SLD': layerStyleUrl+layerName,
+ // 'CQL_FILTER': CQL_QUERY
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous',
+ }),
+ type: 'layer',
+ geom_type: 'Polygon'
+ });
+ }
+ return theLayer;
+ }
+
+ clearMapLayers = () => {
+ // console.log('clearing layers');
+ // clear map. removing all layer other than OSM
+ let removeLayers = [];
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('name') !== 'OSM') {
+ removeLayers.push(layer);
+ }
+ });
+ // console.log('removeLayers', removeLayers);
+ if (removeLayers.length > 0) {
+ for (let i=0; i < removeLayers.length; i++) {
+ this.olmap.removeLayer(removeLayers[i]);
+ }
+ }
+ }
+
+ removeLayerByName = (name) => {
+
+ let removeLayers = [];
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('name') === name) {
+ removeLayers.push(layer);
+ }
+ });
+ // console.log('removeLayers', removeLayers);
+ if (removeLayers.length > 0) {
+ for (let i=0; i < removeLayers.length; i++) {
+ this.olmap.removeLayer(removeLayers[i]);
+ }
+ }
+ }
+
+ getRoute = () => {
+ fetch(routeDummy).then((response) => {
+ response.json().then((result) => {
+ console.log('getRoute', result);
+ })
+ });
+ }
+
+ showRoute = (salesRoute) => {
+ const { mapProjection } = this.state;
+ console.log('showRoute', salesRoute);
+
+ this.removeLayerByName('routeLayer');
+ if (salesRoute.features && salesRoute.features.length < 1) {
+ toast.warn("Couldn't show route at selected time. Please select another range time.");
+ return;
+ }
+
+ let route = null;
+ let polyline = null;
+ let extent = null;
+
+ // polyline = routeDummy.routes[0].overview_polyline.points;
+ // console.log('polyline', polyline);
+
+ // route = new Polyline({
+ // }).readGeometry(polyline, {
+ // dataProjection: 'EPSG:4326',
+ // featureProjection: 'EPSG:4326',
+ // });
+
+ // let route = new Polyline().readGeometry(polyline);
+
+ // polyline = {
+ // "type": "LineString",
+ // "coordinates": [
+ // [
+ // 106.78853,
+ // -6.26235
+ // ],
+ // [
+ // 106.78863,
+ // -6.26201
+ // ],
+ // [
+ // 106.80065,
+ // -6.24523
+ // ]
+ // ]
+ // }
+
+ // console.log('check route', salesRoute.features.length > 0 && (salesRoute.features[0].geometry && salesRoute.features[0].geometry.coordinates));
+
+ if (salesRoute.features.length > 0 && (salesRoute.features[0].geometry && salesRoute.features[0].geometry.coordinates)) {
+ polyline = salesRoute.features[0].geometry;
+
+ route = new LineString(polyline.coordinates).transform('EPSG:4326', mapProjection);
+ extent = route.getExtent();
+
+ console.log('route', route);
+ console.log('extent', extent);
+
+ let routeFeature = new Feature({
+ type: 'route',
+ geometry: route,
+ geometry_name: salesRoute.features[0].geometry_name,
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties,
+ routeColor: getRandomColor()
+ });
+ let geoMarker = new Feature({
+ type: 'geoMarker',
+ geometry: new Point(route.getCoordinateAt(0)),
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties
+ });
+ let startMarker = new Feature({
+ type: 'pinRouteStart',
+ geometry: new Point(route.getCoordinateAt(0)),
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties
+ });
+ let endMarker = new Feature({
+ type: 'pinRouteEnd',
+ geometry: new Point(route.getCoordinateAt(1)),
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties
+ });
+
+ let animating = false;
+
+ let vectorLayer = new VectorLayer({
+ name: 'routeLayer',
+ source_type: 'routeLayer',
+ source: new VectorSource({
+ features: [routeFeature, geoMarker, startMarker, endMarker],
+ }),
+ style: (feature, resolution) => {
+ // hide geoMarker if animation is active
+ if (animating && feature.get('type') === 'geoMarker') {
+ return null;
+ }
+ // return ROUTE_MAP_STYLES[feature.get('type')];
+ return ROUTE_MAP_STYLES(feature, resolution);
+ },
+ });
+
+ this.olmap.addLayer(vectorLayer);
+
+ if (extent) {
+ // this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ this.olmap.getView().fit(extent, { size: this.olmap.getSize(), duration: 500 });
+
+ }
+ }
+ }
+
+ searchRouting = async (userId, dateString) => {
+ await this.setState({isSearchingRoute: true, isProcessing: true});
+
+ const {routeType} = this.state;
+ let routes = null;
+
+ if (routeType === 'waspang') {
+ routes = await getWaspangRoutingApi(userId, dateString);
+ }
+
+ if (routes) {
+ this.setState({isSearchingRoute: false, isProcessing: false}, () => this.showRoute(routes))
+ }
+ else {
+ this.setState({isSearchingRoute: false, isProcessing: false}, () => toast.warn("Sorry. Couldn't get user waypoint"));
+ }
+ }
+
+ handleQueryBuilder = (query, type, tree) => {
+ console.log("query builder "+type, query);
+ this.setState({ queryBuilderOutput:query, queryBuilderType:type, currentQbTree:tree,currentQbType:type }, () => {
+ if(type === "Sales"){
+ this.setLayer('checkedKeysSales');
+ }else if(type === "Customer"){
+ this.setLayer('checkedKeysCustomer');
+ }else if(type === "Office"){
+ this.setLayer('checkedKeysOffice');
+ }
+ })
+ }
+
+ handleQbReset = (type) => {
+ this.setState({
+ queryBuilderOutput:'',
+ queryBuilderType:'',
+ currentQbTree:'',
+ currentQbType:'' }, () => {
+ if(type === "Sales"){
+ this.setLayer('checkedKeysSales');
+ }else if(type === "Customer"){
+ this.setLayer('checkedKeysCustomer');
+ }else if(type === "Office"){
+ this.setLayer('checkedKeysOffice');
+ }
+ })
+ }
+
+
+ getChosenProyekRealisasi = () => {
+ const { chosenProyek, projectTree, checkedKeysProjectTree } = this.state;
+
+ this.chosenProyekTemp = [];
+ let chosenProyekId = [];
+
+ if (checkedKeysProjectTree.length > 0) {
+ chosenProyekId = this.getChosenProyekId(); // ini yang sudah diambil uniquenya
+ }
+ else {
+ chosenProyekId = []
+ }
+
+ console.log('chosenProyekId', chosenProyekId);
+ this.setState({chosenProyekIds: chosenProyekId});
+ }
+
+ // ambil id atau proyek_id berdasarkan key yang tercentang di projectTree
+ // dengan cara mencocokkan di levelnya
+ // kalau dia gak punya parent_id, ambil "id"
+ // kalau dia punya parent_id, ambil "proyek_id"
+ // khusus untuk key = "project-0" berarti dia tercentang semua, gak usah cek dalemannya lagi, langsung ambil children -> id nya.
+ // masukin ke array chosenProyekTemp
+ // ambil unique nya aja lalu return uniquenya
+ getChosenProyekId = () => {
+ const { checkedKeysProjectTree, projectTree } = this.state;
+ // console.log('checkedKeysProjectTree', checkedKeysProjectTree);
+
+ if (checkedKeysProjectTree.length > 0) {
+ if (checkedKeysProjectTree.includes('project-0')) {
+ // langsung ambil semua children di level pertama
+ for (let i=0; i < projectTree[0].children.length; i++) {
+ this.chosenProyekTemp.push(projectTree[0].children[i].id);
+ }
+ }
+ else {
+ // for (let i=0; i < projectTree[0].children.length; i++) {
+ this.getChosenProyekIdByKey(projectTree[0].children);
+ // }
+ }
+ }
+
+ // usage example:
+ // var myArray = ['a', 1, 'a', 2, '1'];
+ // var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);
+ let unique = this.chosenProyekTemp.filter((v, i, a) => a.indexOf(v) === i);
+ return unique;
+ }
+
+ getChosenProyekIdByKey = (dataTree) => {
+ const { checkedKeysProjectTree } = this.state;
+
+ for (let i=0; i < dataTree.length; i++) {
+ if (checkedKeysProjectTree.includes(dataTree[i].key)) {
+ // console.log('matched!!!', dataTree[i].key);
+ // get the proyek_id, then stop
+ if (dataTree[i].parent_id === undefined) {
+ this.chosenProyekTemp.push(dataTree[i].id) // ambil idnya, karena dia adalah level paling atas (proyek)
+ }
+ else if (dataTree[i].parent_id !== undefined && dataTree[i].parent_id === null) { // dia adalah subproyek pertama
+ this.chosenProyekTemp.push(dataTree[i].proyek_id); // ambil proyek_id
+ }
+ else if (dataTree[i].parent_id !== undefined && dataTree[i].parent_id !== null) { // dia adalah subproyek kedua, dst
+ this.chosenProyekTemp.push(dataTree[i].proyek_id); // ambil proyek_id
+ }
+ }
+ else {
+ // console.log('not matched, keep looping!', dataTree[i]);
+ // keep looping until get the matched key
+ if (dataTree[i].subproyeks) {
+ this.getChosenProyekIdByKey(dataTree[i].children);
+ }
+ }
+ }
+ }
+
+ toggleStatusRight = () => {
+ this.setState({statusRight:!this.state.statusRight});
+ }
+
+ toggleProggresBottom = () => {
+ this.setState({proggressBottom:!this.state.proggressBottom})
+ }
+
+ closeStatusRight = () => {
+ this.setState({statusRight:false});
+ }
+
+ closeProggressBottom = () => {
+ this.setState({proggressBottom:false})
+ }
+
+ render() {
+ const { alert, successAlert, dangerAlert, messageAlert,
+ dataStatusProyek, dataPersentaseProyek, dataCostProyek, dataStatusWaspang } = this.state;
+ return (
+ Loading...
+
+ resetCharts = () => {
+ this.setState({
+ dataStatusProyek: null,
+ dataPersentaseProyek: null,
+ dataCostProyek: null,
+ dataStatusWaspang: null,
+ })
+ }
+
+ resetLayerDashboard = () => {
+ this.removeLayerByName('projectLayer');
+ this.removeLayerByName('waspangLayer');
+ this.removeLayerByName('routeLayer');
+ this.removeLayerByName('laporanLayer');
+ this.removeLayerByName('presensiLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+ this.laporanFeatures = [];
+ this.presensiFeatures = [];
+ this.closePopupRight();
+ // this.resetCharts();
+ }
+
+ // ngerequest API buat ngepush ke this.waspangFeatures
+ // getDataUserToProyek = async () => {
+ // const { chosenProyekIds } = this.state;
+ // let payload = {
+ // "columns": [],
+ // "joins": [
+ // {
+ // "name": "m_proyek",
+ // "column_join": "proyek_id",
+ // "column_results": [
+ // "nama",
+ // // "biaya",
+ // // "color_progress",
+ // // "jumlah_pekerja",
+ // // "pic",
+ // "mulai_proyek",
+ // "akhir_proyek"
+ // ]
+ // },
+ // {
+ // "name": "m_subproyek",
+ // "column_join": "subproyek_id",
+ // "column_results": [
+ // "nama",
+ // // "biaya",
+ // // "color_progress",
+ // // "jumlah_pekerja",
+ // // "pic",
+ // "mulai_proyek",
+ // "akhir_proyek"
+ // ]
+ // },
+ // {
+ // "name": "m_users",
+ // "column_join": "user_id",
+ // "column_results": [
+ // "name",
+ // "username",
+ // "email",
+ // "phone_number",
+ // "gender"
+ // ]
+ // }
+ // ],
+ // "orders": {
+ // "columns": [
+ // "id"
+ // ],
+ // "ascending": true
+ // },
+ // "paging": {
+ // "start": 0,
+ // "length": 25
+ // }
+ // }
+
+ // if (chosenProyekIds.length > 0) {
+ // payload.columns.push({
+ // "name": "proyek_id",
+ // "logic_operator": "in",
+ // "value": chosenProyekIds.join(),
+ // "operator": "AND"
+ // });
+ // }
+
+ // // if(parseInt(localStorage.getItem('role_id'))!==1){
+ // // payload.columns.push(
+ // // {
+ // // "name": "id",
+ // // "logic_operator": "=",
+ // // "value": localStorage.getItem('proyek_id'),
+ // // "operator": "AND"
+ // // }
+ // // )
+ // // }
+
+ // const config = {
+ // method: 'POST', // *GET, POST, PUT, DELETE, etc.
+ // // mode: 'cors', // no-cors, *cors, same-origin
+ // // cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+ // // credentials: 'same-origin', // include, *same-origin, omit
+ // headers: {
+ // 'Content-Type': 'application/json',
+ // 'Authorization': 'Bearer ' + localStorage.getItem('token')
+ // // 'Content-Type': 'application/x-www-form-urlencoded',
+ // },
+ // // redirect: 'follow', // manual, *follow, error
+ // // referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
+ // body: JSON.stringify(payload) // body data type must match "Content-Type" header
+ // }
+
+ // const result = await fetch(USERPROYEK_SEARCH, config).then(response => response.json()).then(res => res);
+ // if (result && result.code == 200) {
+ // // this.getWaspangFeatures(result.data);
+ // this.setState({ waspangData: result.data }, () => this.getWaspangFeatures());
+ // } else {
+ // toast.error('Gagal Mengambil Data!!');
+ // }
+ // }
+
+ // ngerequest API buat ngepush data this.laporanFeatures
+ getDataLaporanMap = async () => {
+ let payload = {
+ project_id: []
+ }
+ if (this.state.chosenProyekIds && this.state.chosenProyekIds.length > 0) {
+ payload.project_id = this.state.chosenProyekIds;
+ }
+
+ const result = await axios
+ .post(DASHBOARD_REPORT_POINTS, payload, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ if (result && result.data && result.data.code == 200) {
+ console.log("cek laporan points", result)
+ let dataRes = result.data.data || []
+ this.setState({ laporanData: dataRes }, () => this.getLaporanFeatures())
+ }
+ }
+
+ getLaporanFeatures = async () => {
+ const { laporanData, checkedKeysProjectTree } = this.state;
+ if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+ if (laporanData.length > 0) {
+ for (let i = 0; i < laporanData.length; i++) {
+ let item = laporanData[i];
+ if (item) {
+ if (item.lat && item.lon) {
+ this.laporanFeatures.push({
+ "type": "Feature",
+ "id": `report_activity.${item.id}`,
+ "properties": {
+ "id": item.id,
+ "user_id": item.user_id,
+ "nama_user": item.created_by,
+ "nama_proyek": item.proyek_name,
+ "jumlah_pekerjaan": item.jumlah_pekerjaan,
+ "pekerjaan_yang_dilaporkan": item.job_count_report,
+ "tanggal_lapor": item.report_date ? moment(item.report_date).format("YYYY-MM-DD HH:mm:ss") : '-',
+ // "mulai_tugas": item.mulai,
+ // "akhir_tugas": item.akhir,
+ "_type": "report_activity"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ parseFloat(item.lon),
+ parseFloat(item.lat)
+ ]
+ }
+ })
+ }
+ }
+ }
+
+ console.log('this.laporanFeatures', this.laporanFeatures);
+
+ let layersToAdd = [];
+ let vectorSource = null;
+ let vectorLayer = null;
+ let laporan = null;
+ laporan = {
+ type: "FeatureCollection",
+ features: this.laporanFeatures
+ }
+
+ // generate new layer
+ if (laporan && laporan.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(laporan, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'laporanLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: LAPORAN_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ // toast.warn('Data laporan pada peta tidak ditemukan di project ini');
+ }
+
+ if (layersToAdd.length > 0) {
+ for (let i = 0; i < layersToAdd.length; i++) {
+ console.log('layersToAdd', layersToAdd[i]);
+ this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+ console.log('check addLayer');
+ if (i === layersToAdd.length - 1) {
+ let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ if (extent) {
+ this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+ }
+ }
+ }
+ }
+ }
+
+ else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ this.resetLayerDashboard();
+ this.resetCharts();
+ }
+ }
+
+ // ngerequest API buat ngepush data this.presensiFeatures
+ getDataPresensiMap = async () => {
+ // let payload = {
+ // project_id: []
+ // }
+ // if (this.state.chosenProyekIds && this.state.chosenProyekIds.length > 0) {
+ // payload.project_id = this.state.chosenProyekIds;
+ // }
+
+ // const result = await axios
+ // .post('', payload, HEADER)
+ // .then(res => res)
+ // .catch((error) => error.response);
+
+ // if (result && result.data && result.data.code == 200) {
+ // console.log("cek presensi points", result)
+ // let dataRes = result.data.data || []
+ // this.setState({ presensiData: dataRes }, () => this.getPresensiFeatures())
+ // }
+
+ let dateStart = moment(this.state.startDate).format("YYYY-MM-DD 00:00:00");
+ let dateEnd = moment(this.state.endDate).format("YYYY-MM-DD 23:59:59");
+
+ const payload = {
+ "paging": {"start": 0, "length": -1},
+ "columns": [
+ // {"name": "name", "logic_operator": "like", "value": search, "table_name": "m_users"},
+ {"name": "clock_in", "logic_operator": "range", "value": dateStart, "value1": dateEnd},
+ ],
+ "joins": [{
+ "name":"m_users",
+ "column_join":"user_id",
+ "column_results":[
+ "name",
+ "ktp_number"
+ ]
+ }],
+ "orders": {"columns": ["id"], "ascending": false}
+ }
+
+ const result = await axios
+ .post(PRESENCE_SEARCH, payload, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ // console.log(result)
+
+ if(result && result.data && result.data.code == 200) {
+ let dataRes = result.data.data || []
+ this.setState({ presensiData: dataRes }, () => this.getPresensiFeatures())
+ }else{
+ NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
+ }
+ }
+
+ getPresensiFeatures = async () => {
+ const { presensiData, checkedKeysProjectTree } = this.state;
+ console.log('getPresensiFeature presensiData', presensiData);
+ if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+ if (presensiData.length > 0) {
+ for (let i = 0; i < presensiData.length; i++) {
+ let item = presensiData[i];
+ if (item) {
+ if (item.clock_in_lat && item.clock_in_lng) {
+ this.presensiFeatures.push({
+ "type": "Feature",
+ "id": `m_presensi.${item.id}`,
+ "properties": {
+ "id": item.id,
+ "user_id": item.user_id,
+ "name": item.created_by, // mandatory to fill in popup routing
+ "clock_in": item.clock_in ? moment(item.clock_in).format('D-M-YYYY HH:mm:ss') : '-',
+ "clock_out": item.clock_out ? moment(item.clock_out).format('D-M-YYYY HH:mm:ss') : '-',
+ "clock_in_location": item.clock_in_loc !== '' ? item.clock_in_loc : '-',
+ "clock_out_location": item.clock_out_loc !== '' ? item.clock_out_loc : '-',
+ // "nama_proyek": item.proyek_name,
+ // "mulai_tugas": item.mulai,
+ // "akhir_tugas": item.akhir,
+ "_type": "presensi"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ parseFloat(item.clock_in_lng),
+ parseFloat(item.clock_in_lat)
+ ]
+ }
+ })
+ }
+ }
+ }
+
+ console.log('this.presensiFeatures', this.presensiFeatures);
+
+ let layersToAdd = [];
+ let vectorSource = null;
+ let vectorLayer = null;
+ let presensi = null;
+ presensi = {
+ type: "FeatureCollection",
+ features: this.presensiFeatures
+ }
+
+ // generate new layer
+ if (presensi && presensi.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(presensi, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'presensiLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: PRESENSI_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ // toast.warn('Data laporan pada peta tidak ditemukan di project ini');
+ }
+
+ if (layersToAdd.length > 0) {
+ for (let i = 0; i < layersToAdd.length; i++) {
+ console.log('layersToAdd', layersToAdd[i]);
+ this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+ console.log('check addLayer');
+ if (i === layersToAdd.length - 1) {
+ let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ if (extent) {
+ this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+ }
+ }
+ }
+ }
+ }
+
+ else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ this.resetLayerDashboard();
+ this.resetCharts();
+ }
+ }
+
+
+ // ngerequest API buat ngepush data chart
+ getChartData = async () => {
+
+ const payload = {
+ "project_id": [],
+ "period": "week"
+ }
+
+ if (this.state.chosenProyekIds.length > 0) {
+ console.log('chosenProyekIds', this.state.chosenProyekIds);
+ payload.project_id = this.state.chosenProyekIds;
+ }
+
+ // get cost proyek
+ const result = await axios
+ .post(DASHBOARD_KURVA_S, payload, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ if (result && result.data && result.data.code == 200) {
+ console.log("cek dashboard chart", result)
+ let dataRes = result.data.data || []
+ // const labelCostPlaning = dataRes ? dataRes.map(res => res.total) : [] // ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
+ // const valueCostPlaning = [10, 23, 39, 47, 55, 68, 70, 82, 90, 100]
+ // const valueCostRealisasi = [10, 23, 39, 47, 55, 68, 70, 82, 90, 100]
+
+ // const costProyek = {
+ // labels: labelCostPlaning,
+ // datasets: [
+ // {
+ // label: 'Perencanaan',
+ // data: valueCostPlaning,
+ // fill: false,
+ // backgroundColor: 'rgba(255, 99, 132, 0.5)',
+ // borderColor: 'rgba(255, 99, 132, 0.5)',
+ // yAxisID: 'y-axis-1',
+ // // stack: 'Stack-0'
+ // },
+ // {
+ // label: 'Aktual',
+ // data: valueCostRealisasi,
+ // fill: false,
+ // backgroundColor: 'rgba(54, 162, 235, 0.5)',
+ // borderColor: 'rgba(54, 162, 235, 0.5)',
+ // yAxisID: 'y-axis-1',
+ // // stack: 'Stack-1'
+ // },
+ // ],
+ // };
+ this.setState({ dataCostProyek: dataRes });
+
+ } else {
+ NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
+ }
+
+ // get persentase progress proyek
+ const result2 = await axios
+ .post(DASHBOARD_KURVA_S, payload, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ console.log('result kurva s', result2);
+
+ if (result2 && result2.data && result2.data.code == 200) {
+ let dataRes2 = result2.data.data || []
+
+ // const labelPersentaseProyek = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
+ // const valuePersentaseProyekPlan = [10, 23, 39, 47, 55, 68, 70, 82, 90, 100]
+ // const valuePersentaseProyekActual = [10, 23, 39, 47, 55, 68, 70, 82, 90, 100]
+ // const persentaseProyek = {
+ // labels: labelPersentaseProyek,
+ // datasets: [
+ // {
+ // label: 'Perencanaan',
+ // data: valuePersentaseProyekPlan,
+ // fill: false,
+ // backgroundColor: 'rgba(255, 99, 132, 0.5)',
+ // borderColor: 'rgba(255, 99, 132, 0.5)',
+ // // stack: 'Stack 0'
+ // yAxisID: 'y-axis-1',
+ // },
+ // {
+ // label: 'Aktual',
+ // data: valuePersentaseProyekActual,
+ // fill: false,
+ // backgroundColor: 'rgba(54, 162, 235, 0.5)',
+ // borderColor: 'rgba(54, 162, 235, 0.5)',
+ // // stack: 'Stack 1'
+ // yAxisID: 'y-axis-1',
+ // },
+ // ],
+ // };
+ // console.log("dataRes2", dataRes2);
+ // this.setState({ dataPersentaseProyek: dataRes2 });
+ this.setState({dataCurvaS: dataRes2});
+ console.log('dataRes2-----------', dataRes2);
+
+ // set status proyek for adw
+ if ((APP_MODE === 'ADW')) {
+ let budgetControl = [];
+ if (dataRes2.length > 0) {
+ dataRes2.map((item, index) => {
+ let proyek_name = item.proyek_name;
+ item.data.budget_control.proyek_name = proyek_name; // adding key proyek_name in budget_control object
+ budgetControl.push(item.data.budget_control);
+ });
+ }
+ this.setState({dataStatusProyekAdw: budgetControl});
+ }
+ }
+ else {
+ NotificationManager.error('Gagal Mengambil Data Persentase Progress Proyek!!', 'Failed');
+ }
+
+ // const valueStatusProyek = [70, 20, 10]
+ // const statusProyek = {
+ // labels: ['Aman', 'Alert', 'Critical'],
+ // datasets: [
+ // {
+ // label: '# of Votes',
+ // data: valueStatusProyek,
+ // backgroundColor: [
+ // // 'rgba(54, 162, 235, 0.2)',
+ // 'rgba(28, 165, 23, 0.2)',
+ // 'rgba(255, 206, 86, 0.2)',
+ // 'rgba(255, 99, 132, 0.2)',
+ // ],
+ // borderColor: [
+ // // 'rgba(54, 162, 235, 1)',
+ // 'rgba(28, 165, 23, 1)',
+ // 'rgba(255, 206, 86, 1)',
+ // 'rgba(255, 99, 132, 1)',
+ // ],
+ // borderWidth: 1,
+ // },
+ // ],
+ // };
+
+
+ // const statusProyek = [
+ // {
+ // "id": "1",
+ // "proyek_name": "Pembuatan Aplikasi Survey Covid Varian Baru",
+ // "total_task": 80,
+ // "task_on_progress": 60,
+ // "day_left": 7,
+ // "percentage": 75
+ // },
+ // {
+ // "id": "2",
+ // "proyek_name": "Pembuatan Aplikasi Survey Covid Varian Baru",
+ // "total_task": 70,
+ // "task_on_progress": 70,
+ // "day_left": 0,
+ // "percentage": 100
+ // },
+ // {
+ // "id": "3",
+ // "proyek_name": "Pembuatan Aplikasi Survey Covid Varian Baru",
+ // "total_task": 70,
+ // "task_on_progress": 70,
+ // "day_left": 0,
+ // "percentage": 100
+ // }
+ // ];
+
+ // get cost proyek
+ const result3 = await axios
+ .post(DASHBOARD_STATUS_PROYEK, payload, HEADER)
+ .then(res => res)
+ .catch((error) => error.response);
+
+ if (result3 && result3.data && result3.data.code == 200) {
+ let dataRes3 = result3.data.data || [];
+ console.log(" dataRes3 ", dataRes3)
+ this.setState({ dataStatusProyek: dataRes3 });
+ }
+ else {
+ NotificationManager.error('Gagal Mengambil Data Status Proyek!!', 'Failed');
+ }
+
+ if ((APP_MODE === 'ADW')) {
+ // request to API get status proyek for ADW and save to dataStatusProyekAdw state
+ // cek di result2
+ }
+ }
+
+ getDailyInfo = async () => {
+ const payload = {
+ "columns": [
+ { "name": "created_at", "logic_operator": "range", "value": `${moment().utc().format('YYYY-MM-DD')} 00:00:00`, "value1": `${moment().utc().format('YYYY-MM-DD')} 23:59:59`, "operator": "AND" }
+ ],
+ "paging": { "start": 0, "length": -1 }
+ }
+
+ const config = {
+ method: 'POST', // *GET, POST, PUT, DELETE, etc.
+ // mode: 'cors', // no-cors, *cors, same-origin
+ // cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+ // credentials: 'same-origin', // include, *same-origin, omit
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer ' + localStorage.getItem('token')
+ // 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ // redirect: 'follow', // manual, *follow, error
+ // referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
+ body: JSON.stringify(payload) // body data type must match "Content-Type" header
+ }
+ try {
+ const result = await fetch(DASHBOARD_PROYEK_SEARCH, config).then(response => response.json()).then(res => res);
+ console.log('getDailyInfo result', result);
+ if (result.code === 200 && result.data) {
+ const dataSum = result.data;
+ // this.setState({
+ // planning: dataSum.planning,
+ // realisasi: dataSum.realisasi,
+ // status_project: dataSum.status_project,
+ // waspang_status: dataSum.waspang_status,
+ // panic_button: dataSum.panic_button,
+ // isReady: true
+ // });
+
+ const statusWaspang = {
+ labels: ['Hadir', 'Izin', 'Panic Button'],
+ datasets: [
+ {
+ label: '# of Votes',
+ data: [dataSum.waspang_status.presensi, dataSum.waspang_status.absensi, dataSum.panic_button],
+ backgroundColor: [
+ 'rgba(77,232,0, 0.2)',
+ 'rgba(255,146,3, 0.2)',
+ 'rgba(164,7,120, 0.2)',
+ ],
+ borderColor: [
+ 'rgba(77,232,0, 1)',
+ 'rgba(255,146,3, 1)',
+ 'rgba(164,7,120, 1)',
+ ],
+ borderWidth: 1,
+ },
+ ],
+ };
+ this.setState({ dataStatusWaspang: statusWaspang, allDataWaspang: result.data });
+ }
+ }
+ catch (e) {
+ toast.error('Gagal mengambil data');
+ }
+ }
+
+ getLayerSearchLabel = async () => {
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({ 'Content-Type': 'application/json' }),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_SEARCH_LABEL, param).then(response => response.json()).then(res => res)
+ if (result.data) {
+ if (result.data.length > 0) {
+ // console.log('getLayerSearchLabel result', result);
+ this.setState({
+ searchLabelData: result.data
+ }, () => console.log('getLayerSearchLabel searchLabelData', this.state.searchLabelData));
+ }
+ } else {
+
+ }
+ } catch (err) {
+ console.log(err);
+ // alert(err.message.toString());
+ // toast.warn(err.message.toString());
+ }
+ }
+
+
+ getLayerInfo = async () => {
+ let layerInfo = [];
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({ 'Content-Type': 'application/json' }),
+ }
+
+ try {
+ const result = await fetch(API_GET_CHART_KATEGORI, param).then(response => response.json()).then(res => res)
+ // console.log(result)
+
+ if (result.data) {
+ if (result.data.length > 0) {
+ for (let i = 0; i < result.data.length; i++) {
+ let layer_name = result.data[i].layer_name;
+ let layer_title = result.data[i].layer_title;
+ let layer_geom_type = result.data[i].layer_geom_type;
+ let total_features = result.data[i].total_features;
+
+ let SLD_URL = `${layerStyleUrl + layer_name}`;;
+ let reqColor = await getLayerColor(SLD_URL);
+ let color = '';
+ if (reqColor.success) {
+ color = reqColor.result;
+ }
+ layerInfo.push({
+ layer_name: layer_name,
+ layer_title: layer_title,
+ layer_geom_type: layer_geom_type,
+ layer_color: color,
+ total_features: total_features
+ });
+ }
+ this.setState({ layerInfo: layerInfo }, () => console.log('layerInfo', this.state.layerInfo));
+ }
+ // this.setState({alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false})
+ } else {
+ // this.setState({chartKategori: pie});
+ // this.setState({alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true})
+ }
+ } catch (err) {
+ console.log(err);
+ // alert(err.message.toString());
+ // toast.warn(err.message.toString());
+ // this.setState({alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true})
+ }
+ }
+
+ setDefaultMap = () => {
+ this.olmap.getView().animate({
+ zoom: zoom,
+ maxZoom: maxZoom,
+ center: Indonesia
+ });
+ }
+
+ changeBaseLayer(item) {
+ console.log('change baselayer', item);
+ // console.log(this.olmap.getLayers());
+ if (this.olmap.getLayers().values_.length == 0) {
+ // check if layers empty, so just insert base layer to position 0
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // check if layer exist
+ else if (this.olmap.getLayers().values_.length > 0) {
+ // check the position 0, if base layer then replace to new
+ if (this.olmap.getLayers().array_[0].get('type') === 'base') {
+ this.olmap.getLayers().removeAt(0);
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // else just insert base layer at position 0
+ else {
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ }
+ }
+
+ getHomeView = () => {
+ // this should request to siopas map api to get current map
+ // this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ const { mapZoom, mapCenter } = this.state;
+ if (mapZoom && mapCenter !== null) {
+ this.olmap.getView().animate({
+ zoom: mapZoom,
+ center: mapCenter
+ });
+ }
+ else {
+ // alert("Map Zoom and Map Center are not set yet");
+ this.olmap.getView().animate({
+ zoom: zoom,
+ maxZoom: maxZoom,
+ center: Indonesia
+ });
+ }
+ }
+
+ mapOnClick = (evt) => {
+ evt.preventDefault();
+ let isDrawing = false;
+ let removedFeature = [];
+ let isRemoving = false;
+ let transformedCoords4326 = transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');
+ // console.log('transformedCoords4326', transformedCoords4326);
+
+ let mapInteractions = [];
+ this.olmap.getInteractions().forEach((interaction) => {
+ // console.log('interaction', interaction);
+ if (interaction instanceof Draw) {
+ console.log('drawing is active!!');
+ isDrawing = true;
+ }
+ // if (interaction instanceof Select) {
+ // console.log('select interaction is active');
+ // isRemoving = true;
+ // }
+
+ if (interaction instanceof Modify) {
+ console.log('modify feature is active');
+ isDrawing = true;
+ }
+ });
+
+ if (isDrawing) {
+ return;
+ }
+
+ let viewResolution = this.olmap.getView().getResolution();
+ let viewProjection = this.olmap.getView().getProjection();
+ let url = '';
+ let promises = [];
+ let featureGet = [];
+
+ let hitGeojson = null;
+
+ this.olmap.getLayers().forEach((layer, i) => {
+ console.log('layer', layer.get('name'));
+ if (layer.get('type') !== 'base') {
+ if (layer.get('type') == 'layerGroup') {
+ layer.getLayers().forEach((sublayer, i) => {
+ if (sublayer.getVisible()) {
+ url = sublayer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, { 'INFO_FORMAT': 'application/json' });
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ });
+ }
+ else {
+ if (layer.getVisible()) {
+ if (layer.get('name') !== 'ChosenLayer') {
+ if (layer.get('source_type') && layer.get('source_type') === 'geojson') {
+ let layerSource = layer.getSource();
+ hitGeojson = this.olmap.getFeaturesAtPixel(evt.pixel);
+ console.log('hitGeojson', hitGeojson);
+ }
+ else if (layer.get('source_type') === "wms") {
+ url = layer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, { 'INFO_FORMAT': 'application/json' });
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+
+
+ if (hitGeojson && hitGeojson.length > 0) {
+ for (let i = 0; i < hitGeojson.length; i++) {
+ let feature = hitGeojson[i];
+
+ let feat = {
+ "type": "Feature",
+ "id": "",
+ "geometry": {
+ "type": "",
+ "coordinates": []
+ },
+ "geometry_name": "the_geom",
+ "properties": {}
+ }
+
+ feat.id = feature.id_;
+ feat.geometry.type = feature.getGeometry().getType();
+ // feat.geometry.coordinates = transform(feature.getGeometry().getCoordinates(), 'EPSG:3857', 'EPSG:4326');
+ feat.geometry.coordinates = feature.getGeometry().getCoordinates();
+ feat.properties = feature.getProperties();
+ delete feat.properties["geometry"];
+
+ console.log('feat', feat);
+ featureGet.push(feat);
+ }
+
+ console.log('featureGet geojson', featureGet);
+ }
+
+
+ // kalo dari WMS
+ if (promises.length > 0) {
+ axios.all(promises).then((results) => {
+ results.forEach((response) => {
+ console.log('mapOnClick response promises', response);
+ if (response.data !== undefined) {
+ if (response.data.features.length > 0) {
+ for (let i = 0; i < response.data.features.length; i++) {
+ featureGet.push(response.data.features[i]);
+ }
+ }
+ }
+ })
+
+
+ console.log('featureGet WMS', featureGet);
+
+ // adding it here because it's trapped on axios callback
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ }, () => this.setActiveListFeature());
+ });
+ }
+
+ if (hitGeojson && promises) {
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ }, () => this.setActiveListFeature());
+ }
+ }
+
+ removeChosenLayer = () => {
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer) {
+ if (layer.get('name') !== undefined && layer.get('name') === 'ChosenLayer') {
+ layer.getSource().clear();
+ this.olmap.removeLayer(layer);
+ }
+ }
+ });
+ }
+
+ openPopupRight() {
+ // console.log('opening popup right...')
+ this.setState({ popupRightVisible: true }, () => this.setActiveListFeature());
+ }
+
+ closePopupRight() {
+ // console.log('closing popup right...')
+ this.setState({ popupRightVisible: false, popupDataTemp: [] }, () => this.setActiveListFeature());
+ this.removeChosenLayer(); // selected features
+ // this.removeLayerByName('routeLayer');
+ this.setState({ editGeometryVisible: false, routingBarVisible: false }); // disable editing when no ChosenLayer on Map
+ }
+
+ /*toggleImagePopup() {
+ this.setState({imagePopupVisible: !this.state.imagePopupVisible});
+ }*/
+
+ setPopupDataTemp = (feature) => {
+ // console.log('setPopupDataTemp', feature);
+ this.setState({ popupDataTemp: [feature] }, () => this.setActiveListFeature());
+ }
+
+ reloadPopupData = () => {
+ const { evtCoordinate } = this.state;
+ }
+
+ setActiveListFeature = () => {
+ // console.log('this.state.popupDataTemp', this.state.popupDataTemp);
+ if (this.state.popupRightVisible) {
+ if (this.state.popupDataTemp.length === 1) {
+ this.setState({ activeListFeatureId: this.state.popupDataTemp[0].id }, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ let layerName = this.state.activeListFeatureId ? this.state.activeListFeatureId.substr(0, this.state.activeListFeatureId.indexOf('.')) : '';
+ this.getLayerAttribute(layerName);
+ })
+ }
+ else {
+ this.setState({ activeListFeatureId: '' }, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ })
+ }
+ }
+ else {
+ this.setState({ activeListFeatureId: '' }, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ })
+ }
+ }
+
+ // getGeomType = async (layerName) => {
+
+ // let res = await getGeomType(layerName);
+ // console.log('getGeomType', res);
+ // return res;
+ // }
+
+ loadMap = async () => {
+ let response = await axios.get(API_LOAD_MAP).then(res => res).catch(error => error);
+ console.log('loadMap', response);
+ // this.getHomeView(response);
+ // this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ if (response.data !== undefined) {
+ if (response.data.length > 0) {
+ let dataMap = response.data[0];
+ let layersToRemove = [];
+
+ // if the API response about zoom is null
+ if (dataMap.zoom == null) {
+ this.setDefaultMap();
+ }
+ // if the API response about center_x and center_y is null
+ else if (dataMap.center_x == null && dataMap.center_y == null) {
+ this.setDefaultMap();
+ }
+ // otherwise, add layer to map from map_layer response
+ else {
+ // set the zoom and center
+ this.setState({ mapZoom: dataMap.zoom, mapCenter: [dataMap.center_x, dataMap.center_y] });
+ this.olmap.getView().animate({
+ zoom: dataMap.zoom,
+ center: [dataMap.center_x, dataMap.center_y]
+ });
+
+ // if map_layers from API is exist
+ if (dataMap.map_layers.length > 0) {
+ // first, removing all layers from the current map
+ this.olmap.getLayers().forEach((layer, i) => {
+ layersToRemove.push(layer);
+ });
+ if (layersToRemove.length > 0) {
+ for (let i = 0; i < layersToRemove.length; i++) {
+ this.olmap.removeLayer(layersToRemove[i]);
+ }
+ }
+
+ // add map_layers from api to view
+ if (this.olmap.getLayers().array_.length < 1) {
+ // console.log('layer empty', response.data);
+ let map_layers = dataMap.map_layers;
+ if (map_layers !== undefined) {
+ // console.log('ada map_layers', map_layers);
+ if (map_layers.length > 0) {
+ for (let i = 0; i < map_layers.length; i++) {
+ let newLayer = null;
+
+ // if layer_type is not base
+ if (map_layers[i].layer_type !== 'base') {
+ newLayer = new ImageLayer({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new OlSourceImageWMS(map_layers[i].layer_source),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ // if layer_type is base
+ else {
+ // if base is OSM (OlSourceOsm);
+ if (map_layers[i].layer_name == 'OSM') {
+ newLayer = new OlLayerTile({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new OlSourceOsm(),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ // if base is other than OSM
+ else {
+ newLayer = new OlLayerTile({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new XYZSource(map_layers[i].layer_source),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ }
+
+ // console.log('adding new layer', newLayer);
+
+ // add the map_layers from API
+ this.olmap.addLayer(newLayer);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ saveMap = () => {
+ /* What map update data that are needed?
+ - title of map (o)
+ - zoom
+ - projection
+ - center_x
+ - center_y
+ - base_layer_id
+ - mapLayers[]
+ - layer_name
+ - layer_type (base / layer)
+ - layer_geom_type
+ - layer_source
+ - layer_visible
+ - layer_position
+
+ Example of layer_source:
+ {
+ url: appConfig.geoserver_host+'wms',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':tanah_sekolah',
+ 'TILED': true,
+ 'SLD': layerStyleUrl+'tanah_sekolah'
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous'
+ }
+ */
+ let confirmation = window.confirm('Are you sure you want to save this map?');
+ // let mapId = localStorage.getItem('u_group') === "kominfo" ? 2 : 1;
+ let mapId = MAP_ID; // get from m_group
+ let mapTitle = localStorage.getItem('u_group') + "_map"; // get from m_group
+ let mapZoom = this.olmap.getView().getZoom();
+ let mapProjection = this.olmap.getView().getProjection().code_;
+ let mapCenter = this.olmap.getView().getCenter();
+ let center_x = mapCenter[0]; // longitude
+ let center_y = mapCenter[1]; // latitude
+ let mapLayers = [];
+ let requestPayload = null;
+ let layerType = '';
+ let layerGeomType = '';
+ let count = 0;
+
+ if (confirmation) {
+ this.olmap.getLayers().forEach(async (layer, i) => {
+
+ // console.log('layer after confirmation i', i, layer);
+ layerType = layer.get('type') !== undefined ? layer.get('type') : 'layer';
+
+ if (layer.get('name') !== "DrawingLayer" && layer.get('name') !== "ChosenLayer") {
+ if (layer.get('type') === "base") {
+ if (layer.get('name') === "OSM") {
+ // if the baselayer is OSM, use the OSM function from openlayers
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: 'base',
+ layer_source: "OlSourceOsm", // i don't know why null in database
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ else {
+ // or if the baselayer is other than OSM (such as ESRI, Google, etc), use the XYZSource
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: 'base',
+ layer_source: {
+ // url: 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
+ url: layer.getSource().urls[0],
+ projection: mapProjection,
+ maxZoom: 18
+ },
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ }
+ else {
+ // if the layer is not base layer
+ // layerGeomType = layer.get('geom_type') !== undefined ? layer.get('geom_type') : await this.getGeomType(layer.get('name'));
+ let reqGeomType = await getGeomType(layer.get('name'));
+ if (reqGeomType.success) {
+ layerGeomType = reqGeomType.result;
+
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: layerGeomType,
+ layer_source: {
+ url: appConfig.geoserver_host + 'wms',
+ // url: appConfig.geoserver_host+'gwc/service/wms?SERVICE=WMS',
+ params: {
+ 'LAYERS': appConfig.workspace_name + ':' + layer.get('name'),
+ 'TILED': true,
+ 'SLD': layerStyleUrl + layer.get('name')
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous'
+ },
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ }
+ }
+ count = count + 1;
+
+ // the last loop, so send to updateMap API
+ // console.log('count', count);
+ // console.log('this.olmap.getLayers().array_.length',this.olmap.getLayers().array_.length);
+ // console.log('if count==this.olmap.getLayers().array_length', count == this.olmap.getLayers().array_.length);
+ if (count == this.olmap.getLayers().array_.length) {
+ console.log('terakhirrrrrr');
+ requestPayload = {
+ 'map_id': mapId,
+ 'map_title': mapTitle,
+ 'map_zoom': mapZoom,
+ 'map_projection': mapProjection,
+ 'center_x': center_x,
+ 'center_y': center_y,
+ 'map_layers': mapLayers
+ };
+ console.log('requestPayload', requestPayload);
+ this.saveMapToApi(requestPayload);
+ }
+ });
+ }
+ }
+
+ saveMapToApi = async (requestPayload) => {
+
+ const param = {
+ method: 'POST',
+ header: JSON.stringify({ 'Content-Type': 'application/json' }),
+ body: JSON.stringify(requestPayload)
+ }
+
+ try {
+ const result = await fetch(API_UPDATE_MAP, param).then(response => response.json()).then(res => res)
+ if (result.data) {
+ console.log('after save', result);
+ // this.();
+ this.setState({ alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false })
+ } else {
+ this.setState({ alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true })
+ }
+ } catch (err) {
+ this.setState({ alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true })
+ }
+ }
+
+ toggleEditGeometry = (selectedPopupData) => {
+ let { editGeometryVisible } = this.state;
+ if (!editGeometryVisible) {
+ this.setState({
+ editGeometryVisible: true,
+ layerNameDraw: selectedPopupData.id,
+ geomTypeDraw: selectedPopupData.geometry.type
+ });
+
+ }
+ else {
+ this.cancelDraw();
+ }
+ }
+
+ cancelDraw = () => {
+ this.setState({
+ editGeometryVisible: false,
+ layerNameDraw: '',
+ geomTypeDraw: ''
+ });
+ }
+
+ toggleActiveStateAddGeometry = () => {
+ this.setState({ activeStateAddGeometry: !this.state.activeStateAddGeometry });
+ }
+
+ printMap = () => {
+ this.olmap.once('rendercomplete', () => {
+ domtoimage
+ .toJpeg(this.olmap.getViewport())
+ .then((dataUrl) => {
+ console.log('dataUrl', dataUrl);
+ let link = document.getElementById('image-download');
+ link.href = dataUrl;
+ link.click();
+ toast.success("Success Print Map!")
+ })
+ .catch(e => toast.error(e.toString()));
+ });
+
+ }
+
+ signOut = (e) => {
+ e.preventDefault()
+ // localStorage.removeItem("u_group");
+ // localStorage.removeItem("fullname");
+ window.localStorage.clear();
+ // emptyConstants();
+ this.props.history.push('/login');
+ }
+
+ getLayerAttribute = async (layerName) => {
+ const res = await getLayerAttribute(layerName);
+ console.log('getLayerAttribute', res);
+ if (res.success) {
+ // console.log(res.result);
+ if (res.result.data) {
+ if (res.result.data.length > 0) {
+ this.setState({ layer_attribute: res.result.data }, () => {
+ console.log(this.state.layer_attribute);
+ });
+ }
+ }
+ }
+ else {
+ // alert(res.result);
+ toast.warn(res.result);
+ }
+ }
+
+ // when checking chekbox on Layer Tree Panel
+ onCheckOpt = (state, checkedKeys) => {
+ this.setState({ [state]: checkedKeys });
+ }
+
+ setLayer = async (state) => {
+ console.log('setLayer', state);
+
+ await this.setState({ isProcessing: true });
+
+ this.closePopupRight();
+
+ const { checkedKeysSales, checkedKeysCustomer, checkedKeysOffice, checkedKeysDemografi, checkedKeysAnalisa, checkedKeysEmployeeDivision,
+ salesGroupTree, employeeDivisionTree, queryBuilderOutput, queryBuilderType, checkedKeysProjectTree, projectTree } = this.state;
+ let layersToAdd = [];
+ let newLayer = null;
+ let vectorSource = null;
+ let vectorLayer = null;
+
+ if (state === 'checkedKeysProjectTree') {
+ console.log('checkedKeysProjectTree', checkedKeysProjectTree);
+
+ // first remove projectLayer and its features
+
+ // this.removeLayerByName('routeLayer');
+ // this.removeLayerByName('projectLayer');
+ // this.removeLayerByName('waspangLayer');
+ // this.projectFeatures = [];
+ // this.waspangFeatures = [];
+ this.resetLayerDashboard();
+
+ this.getChosenProyekRealisasi();
+
+ if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+
+ /*
+ Logic:
+ - looping all tree
+ - there are 3 variables
+ 1. features (Array) -> untuk nampung features yg ada di laporan planning
+ 2. projectTree (Array)
+ 3. checkedKeysProjectTree (Array) -> projectTree yg tercentang
+
+ Jadi looping all nesting yg ada di projectTree (ambil object children)
+ Terus cek setiap levelnya dia ada di checkedKeysProjectTree gak?
+ Jika ada, cek apakah di object tersebut mengandung key namanya "plannings" tidak?
+ Jika iya, maka cek di dalamnya ada laporan_planning tidak?
+ Jika iya, maka push ke features[] dengan format:
+ {
+ "type": "Feature",
+ "properties": {}, // isian dari objectnya
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 107.90771484375, // object.lon
+ -6.795535025719518 // object.lat
+ ]
+ }
+ }
+ */
+
+ this.getChildrenTree(projectTree[0].children);
+ // this.getWaspangFeatures();
+
+ console.log('projectFeatures', this.projectFeatures);
+ // console.log('waspangFeatures', this.waspangFeatures);
+
+ let project = null;
+ project = {
+ type: "FeatureCollection",
+ features: this.projectFeatures
+ }
+
+ // console.log('project', project);
+
+
+ // generate new layer
+ if (project && project.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(project, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'projectLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: PROJECT_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ // toast.warn('Data realisasi tidak ditemukan di project ini');
+ }
+
+ }
+ else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ this.removeLayerByName('projectLayer');
+ this.removeLayerByName('waspangLayer');
+ this.removeLayerByName('routeLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+ this.closePopupRight();
+ this.resetCharts()
+ }
+ }
+
+ if (layersToAdd.length > 0) {
+ for (let i = 0; i < layersToAdd.length; i++) {
+
+ this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+
+ console.log('check addLayer');
+ if (i === layersToAdd.length - 1) {
+ let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ if (extent) {
+ this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+ }
+ }
+ }
+ await this.setState({ isProcessing: false });
+ }
+
+ // find the lat lon inside laporan_plannings that the planning has been checked on projectTree
+ getChildrenTree = (data) => {
+ data.map((item, index) => {
+ if (item.children && item.children.length > 0) {
+ this.getChildrenTree(item.children);
+ }
+ else if (item.laporan_plannings && item.laporan_plannings.length > 0) {
+ if (this.state.checkedKeysProjectTree.includes(item.key)) {
+ for (let i = 0; i < item.laporan_plannings.length; i++) {
+ console.log('got features!!!!!');
+ this.projectFeatures.push({
+ "type": "Feature",
+ "id": `realisasi.${item.laporan_plannings[i].id}`,
+ "properties": { ...item.laporan_plannings[i] },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ item.laporan_plannings[i].lon,
+ item.laporan_plannings[i].lat
+ ]
+ }
+ })
+ }
+ }
+ }
+ });
+ }
+
+ // getWaspangFeatures = async () => {
+ // // console.log('getWaspangFeatures', data);
+ // const { waspangData, checkedKeysProjectTree } = this.state;
+ // if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+ // if (waspangData.length > 0) {
+ // for (let i = 0; i < waspangData.length; i++) {
+ // let item = waspangData[i];
+ // if (item.last_waypoint) {
+ // this.waspangFeatures.push({
+ // "type": "Feature",
+ // "id": `m_waspang.${item.id}`,
+ // "properties": {
+ // "id": item.id,
+ // "user_id": item.user_id,
+ // "nama_user": item.join.m_users_name,
+ // "nama_proyek": item.join.m_proyek_nama,
+ // "mulai_tugas": item.mulai,
+ // "akhir_tugas": item.akhir,
+ // "_type": "waspang"
+ // },
+ // "geometry": {
+ // "type": "Point",
+ // "coordinates": [
+ // item.last_waypoint.lon,
+ // item.last_waypoint.lat
+ // ]
+ // }
+ // })
+ // }
+ // }
+
+ // console.log('this.waspangFeatures', this.waspangFeatures);
+
+ // let layersToAdd = [];
+ // let vectorSource = null;
+ // let vectorLayer = null;
+ // let waspang = null;
+ // waspang = {
+ // type: "FeatureCollection",
+ // features: this.waspangFeatures
+ // }
+
+ // // generate new layer
+ // if (waspang && waspang.features.length > 0) {
+ // vectorSource = new VectorSource({
+ // features: new GeoJSON().readFeatures(waspang, {
+ // dataProjection: projection4326, // from
+ // featureProjection: projection // to
+ // })
+ // })
+
+ // vectorLayer = new VectorLayer({
+ // name: 'waspangLayer',
+ // source_type: 'geojson',
+ // source: vectorSource,
+ // style: WASPANG_FEATURES_STYLE
+ // });
+
+ // layersToAdd.push(vectorLayer);
+ // }
+ // else {
+ // toast.warn('Data human resource tidak ditemukan di project ini');
+ // }
+
+ // if (layersToAdd.length > 0) {
+ // for (let i = 0; i < layersToAdd.length; i++) {
+
+ // this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+
+ // console.log('check addLayer');
+ // if (i === layersToAdd.length - 1) {
+ // let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ // if (extent) {
+ // this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ // }
+ // }
+ // }
+ // }
+
+ // }
+ // }
+
+ // else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ // this.removeLayerByName('projectLayer');
+ // this.removeLayerByName('waspangLayer');
+ // this.removeLayerByName('routeLayer');
+ // this.projectFeatures = [];
+ // this.waspangFeatures = [];
+ // this.closePopupRight();
+ // this.resetCharts();
+ // }
+
+ // // this.waspangFeatures = [{
+ // // "type": "Feature",
+ // // "id": `m_waspang.1`,
+ // // "properties": {
+ // // "id": 1,
+ // // "user_id": 10,
+ // // "nama_user": "Ryan",
+ // // "nama_proyek": "FTTH Paket 2",
+ // // "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ // // "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ // // "_type": "waspang"
+ // // },
+ // // "geometry": {
+ // // "type": "Point",
+ // // "coordinates": [
+ // // 106.89285278320312,
+ // // -6.228275226686636
+ // // ]
+ // // }
+ // // },
+ // // {
+ // // "type": "Feature",
+ // // "id": `m_waspang.2`,
+ // // "properties": {
+ // // "id": 2,
+ // // "user_id": 12,
+ // // "nama_user": "Effendi",
+ // // "nama_proyek": "FTTH Paket 2",
+ // // "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ // // "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ // // "_type": "waspang"
+ // // },
+ // // "geometry": {
+ // // "type": "Point",
+ // // "coordinates": [
+ // // 106.9357681274414,
+ // // -6.267522831839373
+ // // ]
+ // // }
+ // // },
+ // // {
+ // // "type": "Feature",
+ // // "id": `m_waspang.3`,
+ // // "properties": {
+ // // "id": 1,
+ // // "user_id": 16,
+ // // "nama_user": "Waspang C",
+ // // "nama_proyek": "FTTH Paket 2",
+ // // "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ // // "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ // // "_type": "waspang"
+ // // },
+ // // "geometry": {
+ // // "type": "Point",
+ // // "coordinates": [
+ // // 106.80564880371092,
+ // // -6.263086293713913
+ // // ]
+ // // }
+ // // }]
+ // }
+
+ findChildLayerToRemove = (parentObj) => {
+ let layersToRemove = [];
+ if (parentObj.hasOwnProperty('children')) {
+ // get semua children layer name nya
+ for (let i = 0; i < parentObj.children.length; i++) {
+ layersToRemove.push(parentObj.children[i].layers.name)
+ }
+ }
+ else {
+ layersToRemove.push(parentObj.layers.name)
+ }
+ return layersToRemove;
+ }
+
+ findChildLayerToAdd = (parentObj, checkedKeys) => {
+
+ let layersToAdd = [];
+ let newLayer = null;
+
+ // 1. cek apakah parentObj itu kecentang atau ngga
+ // 2. cek apakah parentObj itu punya child apa ngga
+ // kalo kecentang parent nya ya berarti loop aja
+ // 3. cek apakah childnya itu kecentang ngga
+
+ console.log('parentObj', parentObj);
+
+ if (checkedKeys.includes(parentObj["key"])) {
+ if (parentObj.hasOwnProperty('children')) {
+ // loop aja semua child layernya
+ for (let i = 0; i < parentObj.children.length; i++) {
+ newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ newLayer = this.generateLayerWMSByName(parentObj.layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ if (parentObj.hasOwnProperty('children')) {
+
+ }
+
+ }
+
+ return layersToAdd;
+
+ }
+
+ getExtentLayerByName = async (layer) => {
+
+ // console.log('getExtentLayerByName', layerName, source_type);
+
+ let layerName = layer.get('name');
+ let source_type = layer.get('source_type');
+
+ // if source_type is undefined = WMS
+ // otherwise source_type is not undefined = geojson
+
+ let extent = null;
+
+ if (source_type === 'wms') {
+ let getExt = await fetch(WMS_CAPABILITIES_URL_2).then((response) => {
+ return response.text();
+ }).then((text) => text);
+
+ let result = new WMSCapabilities().read(getExt);
+ if (result && result.Capability.Layer.Layer.find(l => l.Name === appConfig.workspace_name + ':' + layerName)) {
+ extent = result.Capability.Layer.Layer.find(l => l.Name === appConfig.workspace_name + ':' + layerName).EX_GeographicBoundingBox;
+ }
+ }
+ else if (source_type === 'geojson') {
+ // extent = layer.getSource().getExtent();
+
+ // layer.getSource().once('change',(e) => {
+ // if (layer.getSource().getState() === 'ready') {
+ // extent = layer.getSource().getExtent();
+ // console.log('extent------------', extent);
+ // // map.getView().fit(extent, map.getSize());
+ // }
+ // });
+ extent = null
+ }
+ console.log('extent', extent);
+ return extent;
+
+ }
+
+ generateLayerWMSByName = (layerName) => {
+ let theLayer = null;
+ if (layerName) {
+ theLayer = new OlLayerTile({
+ name: layerName,
+ source_type: 'wms',
+ source: new OlSourceTileWMS({
+ url: appConfig.geoserver_host + 'wms',
+ params: {
+ 'LAYERS': appConfig.workspace_name + ':' + layerName,
+ 'TILED': true,
+ 'SLD': layerStyleUrl + layerName,
+ // 'CQL_FILTER': CQL_QUERY
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous',
+ }),
+ type: 'layer',
+ geom_type: 'Polygon'
+ });
+ }
+ return theLayer;
+ }
+
+ clearMapLayers = () => {
+ // console.log('clearing layers');
+ // clear map. removing all layer other than OSM
+ let removeLayers = [];
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('name') !== 'OSM') {
+ removeLayers.push(layer);
+ }
+ });
+ // console.log('removeLayers', removeLayers);
+ if (removeLayers.length > 0) {
+ for (let i = 0; i < removeLayers.length; i++) {
+ this.olmap.removeLayer(removeLayers[i]);
+ }
+ }
+ }
+
+ removeLayerByName = (name) => {
+
+ let removeLayers = [];
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('name') === name) {
+ removeLayers.push(layer);
+ }
+ });
+ // console.log('removeLayers', removeLayers);
+ if (removeLayers.length > 0) {
+ for (let i = 0; i < removeLayers.length; i++) {
+ this.olmap.removeLayer(removeLayers[i]);
+ }
+ }
+ }
+
+ getRoute = () => {
+ fetch(routeDummy).then((response) => {
+ response.json().then((result) => {
+ console.log('getRoute', result);
+ })
+ });
+ }
+
+ handleGetPercentagePerDay = async () => {
+ console.log("GET_PERCENTAGE_PERDAY", GET_PERCENTAGE_PERDAY);
+ const result = await axios.post(GET_PERCENTAGE_PERDAY, HEADER).then(res => res).catch(err => err.response)
+ console.log("result", result);
+ if (result.data.code === 200) {
+ let dataRes = result.data.data
+ console.log("dataRes", dataRes);
+ } else {
+ NotificationManager.error('Gaga mengambil Data!!', 'Failed');
+ }
+ }
+
+ showRoute = (userRoute) => {
+ const { mapProjection } = this.state;
+ console.log('showRoute', userRoute);
+
+ this.removeLayerByName('routeLayer');
+ if (userRoute.features && userRoute.features.length < 1) {
+ toast.warn("Couldn't show route at selected time. Please select another range time.");
+ return;
+ }
+
+ let route = null;
+ let polyline = null;
+ let extent = null;
+
+ // polyline = routeDummy.routes[0].overview_polyline.points;
+ // console.log('polyline', polyline);
+
+ // route = new Polyline({
+ // }).readGeometry(polyline, {
+ // dataProjection: 'EPSG:4326',
+ // featureProjection: 'EPSG:4326',
+ // });
+
+ // let route = new Polyline().readGeometry(polyline);
+
+ // polyline = {
+ // "type": "LineString",
+ // "coordinates": [
+ // [
+ // 106.78853,
+ // -6.26235
+ // ],
+ // [
+ // 106.78863,
+ // -6.26201
+ // ],
+ // [
+ // 106.80065,
+ // -6.24523
+ // ]
+ // ]
+ // }
+
+ // console.log('check route', userRoute.features.length > 0 && (userRoute.features[0].geometry && userRoute.features[0].geometry.coordinates));
+
+ if (userRoute.features.length > 0 && (userRoute.features[0].geometry && userRoute.features[0].geometry.coordinates)) {
+ // polyline = userRoute.features[0].geometry;
+ polyline = {
+ "type": "LineString",
+ "coordinates": []
+ }
+
+ for (let i=0; i < userRoute.features.length; i++) {
+ polyline.coordinates.push(userRoute.features[i].geometry.coordinates);
+ }
+
+ route = new LineString(polyline.coordinates).transform('EPSG:4326', mapProjection);
+ extent = route.getExtent();
+
+ console.log('route', route);
+ console.log('extent', extent);
+
+ let routeFeature = new Feature({
+ type: 'route',
+ geometry: route,
+ geometry_name: userRoute.features[0].geometry_name,
+ id: userRoute.features[0].id,
+ properties: userRoute.features[0].properties,
+ routeColor: getRandomColor()
+ });
+ let geoMarker = new Feature({
+ type: 'geoMarker',
+ geometry: new Point(route.getCoordinateAt(0)),
+ id: userRoute.features[0].id,
+ properties: userRoute.features[0].properties
+ });
+ let startMarker = new Feature({
+ type: 'pinRouteStart',
+ geometry: new Point(route.getCoordinateAt(0)),
+ id: userRoute.features[0].id,
+ properties: userRoute.features[0].properties
+ });
+ let endMarker = new Feature({
+ type: 'pinRouteEnd',
+ geometry: new Point(route.getCoordinateAt(1)),
+ id: userRoute.features[0].id,
+ properties: userRoute.features[0].properties
+ });
+
+ let animating = false;
+
+ let vectorLayer = new VectorLayer({
+ name: 'routeLayer',
+ source_type: 'routeLayer',
+ source: new VectorSource({
+ features: [routeFeature, geoMarker, startMarker, endMarker],
+ }),
+ style: (feature, resolution) => {
+ // hide geoMarker if animation is active
+ if (animating && feature.get('type') === 'geoMarker') {
+ return null;
+ }
+ // return ROUTE_MAP_STYLES[feature.get('type')];
+ return ROUTE_MAP_STYLES(feature, resolution);
+ },
+ });
+
+ this.olmap.addLayer(vectorLayer);
+
+ if (extent) {
+ // this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ this.olmap.getView().fit(extent, { size: this.olmap.getSize(), duration: 500 });
+
+ }
+ }
+ }
+
+ searchRouting = async (userId, dateString) => {
+ await this.setState({ isSearchingRoute: true, isProcessing: true });
+
+ const { routeType } = this.state;
+ let routes = null;
+
+ if (routeType === 'waspang') {
+ routes = await getWaspangRoutingApi(userId, dateString);
+ }
+
+ if (routeType === 'presensi') {
+ routes = await getPresensiRoutingApi(userId, dateString);
+ }
+
+ if (routes) {
+ this.setState({ isSearchingRoute: false, isProcessing: false }, () => this.showRoute(routes))
+ }
+ else {
+ this.setState({ isSearchingRoute: false, isProcessing: false }, () => toast.warn("Sorry. Couldn't get user waypoint"));
+ }
+ }
+
+ handleQueryBuilder = (query, type, tree) => {
+ console.log("query builder " + type, query);
+ this.setState({ queryBuilderOutput: query, queryBuilderType: type, currentQbTree: tree, currentQbType: type }, () => {
+ if (type === "Sales") {
+ this.setLayer('checkedKeysSales');
+ } else if (type === "Customer") {
+ this.setLayer('checkedKeysCustomer');
+ } else if (type === "Office") {
+ this.setLayer('checkedKeysOffice');
+ }
+ })
+ }
+
+ handleQbReset = (type) => {
+ this.setState({
+ queryBuilderOutput: '',
+ queryBuilderType: '',
+ currentQbTree: '',
+ currentQbType: ''
+ }, () => {
+ if (type === "Sales") {
+ this.setLayer('checkedKeysSales');
+ } else if (type === "Customer") {
+ this.setLayer('checkedKeysCustomer');
+ } else if (type === "Office") {
+ this.setLayer('checkedKeysOffice');
+ }
+ })
+ }
+
+
+ getChosenProyekRealisasi = () => {
+ const { chosenProyek, projectTree, checkedKeysProjectTree } = this.state;
+
+ this.chosenProyekTemp = [];
+ let chosenProyekId = [];
+
+ if (checkedKeysProjectTree.length > 0) {
+ chosenProyekId = this.getChosenProyekId(); // ini yang sudah diambil uniquenya
+ }
+ else {
+ chosenProyekId = []
+ }
+
+ console.log('chosenProyekId', chosenProyekId);
+ this.setState({ chosenProyekIds: chosenProyekId });
+ }
+
+ // ambil id atau proyek_id berdasarkan key yang tercentang di projectTree
+ // dengan cara mencocokkan di levelnya
+ // kalau dia gak punya parent_id, ambil "id"
+ // kalau dia punya parent_id, ambil "proyek_id"
+ // khusus untuk key = "project-0" berarti dia tercentang semua, gak usah cek dalemannya lagi, langsung ambil children -> id nya.
+ // masukin ke array chosenProyekTemp
+ // ambil unique nya aja lalu return uniquenya
+ getChosenProyekId = () => {
+ const { checkedKeysProjectTree, projectTree } = this.state;
+ // console.log('checkedKeysProjectTree', checkedKeysProjectTree);
+
+ if (checkedKeysProjectTree.length > 0) {
+ if (checkedKeysProjectTree.includes('project-0')) {
+ // langsung ambil semua children di level pertama
+ for (let i = 0; i < projectTree[0].children.length; i++) {
+ this.chosenProyekTemp.push(projectTree[0].children[i].id);
+ }
+ }
+ else {
+ // for (let i=0; i < projectTree[0].children.length; i++) {
+ this.getChosenProyekIdByKey(projectTree[0].children);
+ // }
+ }
+ }
+
+ // usage example:
+ // var myArray = ['a', 1, 'a', 2, '1'];
+ // var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);
+ let unique = this.chosenProyekTemp.filter((v, i, a) => a.indexOf(v) === i);
+ return unique;
+ }
+
+ getChosenProyekIdByKey = (dataTree) => {
+ const { checkedKeysProjectTree } = this.state;
+
+ for (let i = 0; i < dataTree.length; i++) {
+ if (checkedKeysProjectTree.includes(dataTree[i].key)) {
+ // console.log('matched!!!', dataTree[i].key);
+ // get the proyek_id, then stop
+ if (dataTree[i].parent_id === undefined) {
+ this.chosenProyekTemp.push(dataTree[i].id) // ambil idnya, karena dia adalah level paling atas (proyek)
+ }
+ else if (dataTree[i].parent_id !== undefined && dataTree[i].parent_id === null) { // dia adalah subproyek pertama
+ this.chosenProyekTemp.push(dataTree[i].proyek_id); // ambil proyek_id
+ }
+ else if (dataTree[i].parent_id !== undefined && dataTree[i].parent_id !== null) { // dia adalah subproyek kedua, dst
+ this.chosenProyekTemp.push(dataTree[i].proyek_id); // ambil proyek_id
+ }
+ }
+ else {
+ // console.log('not matched, keep looping!', dataTree[i]);
+ // keep looping until get the matched key
+ if (dataTree[i].subproyeks) {
+ this.getChosenProyekIdByKey(dataTree[i].children);
+ }
+ }
+ }
+ }
+
+ toggleStatusRight = () => {
+ this.setState({ statusRight: !this.state.statusRight });
+ }
+
+ toggleProggresBottom = () => {
+ this.setState({ proggressBottom: !this.state.proggressBottom })
+ }
+
+ closeStatusRight = () => {
+ this.setState({ statusRight: false });
+ }
+
+ closeProggressBottom = () => {
+ this.setState({ proggressBottom: false })
+ }
+
+ toggleKurvaSWindowMode = () => {
+ const { kurvaSWindowMode } = this.state;
+ console.log('toggleKurvaSWindowMode', kurvaSWindowMode);
+ if (kurvaSWindowMode === 'default') {
+ this.setState({kurvaSWindowMode: 'maximize'}, () => this.renderCarouselKurvaS())
+ }
+ else {
+ this.setState({kurvaSWindowMode: 'default'}, () => this.renderCarouselKurvaS());
+ }
+ }
+
+ renderDurasiKerja = (jamMasuk, jamKeluar) => {
+
+ if (jamMasuk && jamKeluar) {
+
+ let start = moment(jamMasuk),
+ end = moment(jamKeluar);
+
+ let diff = end.diff(start);
+ let result = moment.utc(diff).format('HH:mm:ss');
+
+ if (result) {
+ return result;
+ } else {
+ return "-"
+ }
+
+ } else {
+ return "-"
+ }
+ }
+
+ handleRequestDataTable = async (url, payload) => {
+
+ const config = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer ' + localStorage.getItem('token')
+ },
+ body: JSON.stringify(payload) // body data type must match "Content-Type" header
+ }
+ try {
+ const result = await fetch(url, config).then(response => response.json()).then(res => res);
+ return result.data || []
+ }
+ catch (e) {
+ toast.error('Gagal mengambil data');
+ return []
+ }
+ }
+
+
+ handleClickChartPengawas = async param => {
+ const { dataStatusWaspang } = this.state
+ const { start_time, end_time } = dataStatusWaspang
+
+ // if (!param.length) return;
+
+ console.log('handleClickChartPengawas param', param);
+
+ const { _index } = param[0];
+ const label = dataStatusWaspang.labels[_index]
+ // console.log({ param, label })
+ console.log('label', label);
+
+ const payload = {
+ "columns": [
+ { "name": label == " Hadir" ? "clock_time" : "created_at", "logic_operator": "range", "value": `${moment(start_time).utc().format('YYYY-MM-DD')} 00:00:00`, "value1": `${moment(end_time).utc().format('YYYY-MM-DD')} 23:59:59`, "operator": "AND" }
+ ],
+ "joins": [
+ {
+ "name": "m_users",
+ "column_join": "user_id",
+ "column_results": [
+ "name",
+ ]
+ }
+ ],
+ "paging": { "start": 0, "length": -1 }
+ }
+ console.log(payload)
+ if (label == "Hadir") {
+ const result = await this.handleRequestDataTable(PRESENSI_SEARCH, payload)
+ console.log('data hadir pengawas', result)
+ this.setState({ dataWaspangHadir: result, openTablePengawas: true, tabelTypeWaspang: label, columnWaspang: columnPresensi });
+ }
+
+ if (label == "Izin") {
+ const result = await this.handleRequestDataTable(ABSENSI_SEARCH, payload)
+ console.log('data absen pengawas', result)
+ this.setState({ dataWaspangAbsent: result, openTablePengawas: true, tabelTypeWaspang: label, columnWaspang: columnAbssensi });
+ }
+
+ if (label == "Panic Button") {
+ const result = await this.handleRequestDataTable(PANIC_BUTTON_SEARCH, payload)
+ console.log('data panic pengawas', result)
+
+ let resultSortedDesc = sortBy(result, {
+ prop: "created_at",
+ desc: true,
+ });
+
+ const resultMod = resultSortedDesc.filter((value, index, self) => {
+ return self.findIndex(v => v.user_id === value.user_id) === index;
+ }).map(ele => ele);
+
+ console.log('resultMod', resultMod);
+
+ this.setState({ dataWaspangPanic: resultMod, openTablePengawas: true, tabelTypeWaspang: label, columnWaspang: columnPanic });
+ }
+ }
+
+ handleClickChartProyek = async param => {
+ const { dataStatusProyek, chosenProyekIds } = this.state
+ const { _index } = param[0];
+ const label = dataStatusProyek.labels[_index]
+ console.log({ param, label })
+ let str = ""
+ chosenProyekIds.map((res, idx) => {
+ if (idx == 0) str += `${res}`
+ if (idx != 0) str += `,${res}`
+
+ })
+ const val = label == "Aman" ? "green" : label == "Alert" ? "orange" : "red"
+
+ const payload = {
+ "columns": [
+ { "name": "color_progress", "logic_operator": "like", "value": val, "operator": "AND" },
+ { "name": "id", "logic_operator": "in", "value": str ? str : "0", "operator": "AND" },
+ ],
+ "joins": [
+ { "name": "subproyeks.m_proyek", "column_join": "proyek_id", "column_results": ["nama", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] },
+ { "name": "subproyeks.m_subproyek", "column_join": "parent_id", "column_results": ["nama", "color_progress", "jumlah_pekerja", "pic", "mulai_proyek", "akhir_proyek", "biaya_actual", "persentase_progress_plan", "persentase_progress_actual"] }
+ ],
+ "orders": { "columns": ["id"], "ascending": true },
+ "paging": { "start": 0, "length": 25 }
+ }
+ console.log(payload)
+ const result = await this.handleRequestDataTable(PROYEK_SEARCH, payload)
+ console.log('data status proyek', result)
+ this.setState({ dataTableStatusProyek: result, openTableStatusProyek: true, typeTableStatusProyek: label });
+
+ }
+
+ handleClickChartPersentase = async param => {
+ const { dataPersentaseProyek, chosenProyekIds } = this.state
+ const { _index } = param[0];
+ const label = dataPersentaseProyek.labels[_index]
+ // console.log({ param, label })
+ }
+
+ handleClickChartCost = async param => {
+ const { dataCostProyek, chosenProyekIds } = this.state
+ const { _index } = param[0];
+ const label = dataCostProyek.labels[_index]
+ }
+
+
+ renderTablePresensi = () => {
+ console.log('render hadir table', this.state.dataWaspangHadir)
+ const dataTable2 = this.state.dataWaspangHadir || [];
+ return (
+
+ Data tidak ditemukan. Pilih proyek untuk menampilkan data.
+
+ )
+ }
+
+ next = () => {
+ const { animating, activeIndex, dataStatusProyek, dataStatusProyekAdw } = this.state;
+ if (animating) return;
+ if ((APP_MODE === 'ADW')) {
+ const nextIndex = activeIndex === dataStatusProyekAdw.length - 1 ? 0 : activeIndex + 1;
+ this.setState({activeIndex: nextIndex});
+ }
+ else {
+ const nextIndex = activeIndex === dataStatusProyek.length - 1 ? 0 : activeIndex + 1;
+ this.setState({activeIndex: nextIndex});
+ }
+ }
+
+ next2 = () => {
+ const { animating2, activeIndex2, dataPersentaseProyek } = this.state;
+ if (animating2) return;
+ const nextIndex = activeIndex2 === dataPersentaseProyek.length - 1 ? 0 : activeIndex2 + 1;
+ this.setState({activeIndex2: nextIndex});
+ }
+
+ next3 = () => {
+ const { animating3, activeIndex3, dataCostProyek } = this.state;
+ if (animating3) return;
+ const nextIndex = activeIndex3 === dataCostProyek.length - 1 ? 0 : activeIndex3 + 1;
+ this.setState({activeIndex3: nextIndex});
+ }
+
+ previous = () => {
+ const { animating, activeIndex, dataStatusProyek, dataStatusProyekAdw } = this.state;
+ if (animating) return;
+ if ((APP_MODE === 'ADW')) {
+ const nextIndex = activeIndex === 0 ? dataStatusProyekAdw.length - 1 : activeIndex - 1;
+ this.setState({activeIndex: nextIndex});
+ }
+ else {
+ const nextIndex = activeIndex === 0 ? dataStatusProyek.length - 1 : activeIndex - 1;
+ this.setState({activeIndex: nextIndex});
+ }
+ }
+
+ previous2 = () => {
+ const { animating2, activeIndex2, dataPersentaseProyek } = this.state;
+ if (animating2) return;
+ const nextIndex = activeIndex2 === 0 ? dataPersentaseProyek.length - 1 : activeIndex2 - 1;
+ this.setState({activeIndex2: nextIndex});
+ }
+
+ previous3 = () => {
+ const { animating3, activeIndex3, dataCostProyek } = this.state;
+ if (animating3) return;
+ const nextIndex = activeIndex3 === 0 ? dataCostProyek.length - 1 : activeIndex3 - 1;
+ this.setState({activeIndex3: nextIndex});
+ }
+
+ goToIndex = (newIndex) => {
+ const { animating } = this.state;
+ if (animating) return;
+ this.setState({activeIndex: newIndex})
+ }
+
+ goToIndex2 = (newIndex) => {
+ const { animating2 } = this.state;
+ if (animating2) return;
+ this.setState({activeIndex2: newIndex})
+ }
+
+ goToIndex3 = (newIndex) => {
+ const { animating3 } = this.state;
+ if (animating3) return;
+ this.setState({activeIndex3: newIndex})
+ }
+
+ renderRemainingDays = (item) => {
+ const {day_left, percentage} = item;
+ if (day_left > 0 && day_left < 8) {
+ return Loading...
+
+ changeBaseLayer(item) {
+ console.log('change baselayer', item);
+ console.log(this.olmap.getLayers());
+ if (this.olmap.getLayers().values_.length == 0) {
+ // check if layers empty, so just insert base layer to position 0
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // check if layer exist
+ else if (this.olmap.getLayers().values_.length > 0) {
+ // check the position 0, if base layer then replace to new
+ if (this.olmap.getLayers().array_[0].get('type') === 'base') {
+ this.olmap.getLayers().removeAt(0);
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // else just insert base layer at position 0
+ else {
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ }
+ }
+
+ getHomeView = () => {
+ this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+
+ mapOnClick = (evt) => {
+ // console.log('map on click', evt);
+ evt.preventDefault();
+ let isDrawing = false;
+ let removedFeature = [];
+ let isRemoving = false;
+
+ let mapInteractions = [];
+ this.olmap.getInteractions().forEach((interaction) => {
+ // console.log('interaction', interaction);
+ if (interaction instanceof Draw) {
+ // console.log('drawing is active!!');
+ isDrawing = true;
+ }
+ // if (interaction instanceof Select) {
+ // console.log('select interaction is active');
+ // isRemoving = true;
+ // }
+ });
+
+ if (isDrawing) {
+ return;
+ }
+
+ // if (isRemoving) {
+ // this.olmap.getLayers().forEach((layer, i) => {
+ // if (layer.get('type') === 'vector') {
+ // let features = layer.getSource().getFeatures();
+ // features.forEach((feature) => {
+ // layer.getSource().removeFeature(feature);
+ // });
+ // }
+ // });
+ // }
+
+ let viewResolution = this.olmap.getView().getResolution();
+ let viewProjection = this.olmap.getView().getProjection();
+ let url = '';
+ let promises = [];
+ let featureGet = [];
+
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('type') !== 'base') {
+ if (layer.get('type') !== 'vector') {
+ if (layer.get('type') == 'layerGroup') {
+ layer.getLayers().forEach((sublayer, i) => {
+ if (sublayer.getVisible()) {
+ url = sublayer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ });
+ }
+ else {
+ if (layer.getVisible()) {
+ url = layer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ }
+ }
+ }
+ });
+
+ axios.all(promises).then((results) => {
+ results.forEach((response) => {
+ // console.log('response promises', response);
+ if (response.data !== undefined) {
+ if (response.data.features.length > 0) {
+ for(let i=0; i < response.data.features.length; i++) {
+ featureGet.push(response.data.features[i]);
+ }
+ }
+ }
+ })
+
+ // console.log('featureGet', featureGet);
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ });
+ });
+ }
+
+ initPopup = () => {
+ let popupCloser = document.getElementById("popup-closer");
+ // let showImageFeature = document.getElementById("showImageFeature");
+ popupCloser.addEventListener("click", () => this.closePopup());
+ // showImageFeature.addEventListener("click", () => this.closePopup());
+ }
+
+ showPopup = () => {
+ console.log('----------------- showPopup');
+ this.initPopup();
+ this.fillPopupContent();
+ this.overlay.setPosition(this.state.evtCoordinate);
+ }
+
+ fillPopupContent = () => {
+ const { popupDataTemp } = this.state;
+ console.log('popupDataTemp', popupDataTemp);
+
+ if (popupDataTemp.length === 1) {
+ this.popupOneFeature(popupDataTemp[0]);
+ }
+ else if (popupDataTemp.length > 1) {
+ this.popupMoreFeature();
+ }
+ }
+
+ // renderPopup = () => {
+ // ReactDOM.render(Loading...
+
+
+ getLayerSearchLabel = async() => {
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_LAYER_SEARCH_LABEL, param).then(response => response.json()).then(res => res)
+ if (result.data){
+ if (result.data.length > 0) {
+ // console.log('getLayerSearchLabel result', result);
+ this.setState({
+ searchLabelData: result.data
+ }, () => console.log('getLayerSearchLabel searchLabelData', this.state.searchLabelData));
+ }
+ } else {
+
+ }
+ } catch(err) {
+ console.log(err);
+ // alert(err.message.toString());
+ // toast.warn(err.message.toString());
+ }
+ }
+
+
+ getLayerInfo = async () => {
+ let layerInfo = [];
+ const param = {
+ method: 'GET',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ }
+
+ try {
+ const result = await fetch(API_GET_CHART_KATEGORI, param).then(response => response.json()).then(res => res)
+ // console.log(result)
+
+ if(result.data){
+ if (result.data.length > 0) {
+ for(let i=0; i < result.data.length; i++) {
+ let layer_name = result.data[i].layer_name;
+ let layer_title = result.data[i].layer_title;
+ let layer_geom_type = result.data[i].layer_geom_type;
+ let total_features = result.data[i].total_features;
+
+ let SLD_URL = `${layerStyleUrl+layer_name}`;;
+ let reqColor = await getLayerColor(SLD_URL);
+ let color = '';
+ if (reqColor.success) {
+ color = reqColor.result;
+ }
+ layerInfo.push({
+ layer_name: layer_name,
+ layer_title: layer_title,
+ layer_geom_type: layer_geom_type,
+ layer_color: color,
+ total_features: total_features
+ });
+ }
+ this.setState({layerInfo: layerInfo}, () => console.log('layerInfo',this.state.layerInfo));
+ }
+ // this.setState({alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false})
+ } else {
+ // this.setState({chartKategori: pie});
+ // this.setState({alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true})
+ }
+ } catch(err) {
+ console.log(err);
+ // alert(err.message.toString());
+ // toast.warn(err.message.toString());
+ // this.setState({alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true})
+ }
+ }
+
+ setDefaultMap = () => {
+ this.olmap.getView().animate({
+ zoom: zoom,
+ center: Indonesia
+ });
+ }
+
+ changeBaseLayer(item) {
+ console.log('change baselayer', item);
+ // console.log(this.olmap.getLayers());
+ if (this.olmap.getLayers().values_.length == 0) {
+ // check if layers empty, so just insert base layer to position 0
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // check if layer exist
+ else if (this.olmap.getLayers().values_.length > 0) {
+ // check the position 0, if base layer then replace to new
+ if (this.olmap.getLayers().array_[0].get('type') === 'base') {
+ this.olmap.getLayers().removeAt(0);
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // else just insert base layer at position 0
+ else {
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ }
+ }
+
+ getHomeView = () => {
+ // this should request to siopas map api to get current map
+ // this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ const { mapZoom, mapCenter } = this.state;
+ if (mapZoom && mapCenter !== null) {
+ this.olmap.getView().animate({
+ zoom: mapZoom,
+ center: mapCenter
+ });
+ }
+ else {
+ // alert("Map Zoom and Map Center are not set yet");
+ this.olmap.getView().animate({
+ zoom: zoom,
+ center: Indonesia
+ });
+ }
+ }
+
+ mapOnClick = (evt) => {
+ // console.log('map on click', evt);
+ // console.log('getEventCoordinate', this.olmap.getEventCoordinate());
+ // console.log('coordinate', evt.coordinate);
+ // console.log('pixel', evt.pixel);
+ evt.preventDefault();
+ let isDrawing = false;
+ let removedFeature = [];
+ let isRemoving = false;
+ let transformedCoords4326 = transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326');
+ // console.log('transformedCoords4326', transformedCoords4326);
+
+ let mapInteractions = [];
+ this.olmap.getInteractions().forEach((interaction) => {
+ // console.log('interaction', interaction);
+ if (interaction instanceof Draw) {
+ console.log('drawing is active!!');
+ isDrawing = true;
+ }
+ // if (interaction instanceof Select) {
+ // console.log('select interaction is active');
+ // isRemoving = true;
+ // }
+
+ if (interaction instanceof Modify) {
+ console.log('modify feature is active');
+ isDrawing = true;
+ }
+ });
+
+ if (isDrawing) {
+ return;
+ }
+
+ // if (isRemoving) {
+ // this.olmap.getLayers().forEach((layer, i) => {
+ // if (layer.get('type') === 'vector') {
+ // let features = layer.getSource().getFeatures();
+ // features.forEach((feature) => {
+ // layer.getSource().removeFeature(feature);
+ // });
+ // }
+ // });
+ // }
+
+ let viewResolution = this.olmap.getView().getResolution();
+ let viewProjection = this.olmap.getView().getProjection();
+ let url = '';
+ let promises = [];
+ let featureGet = [];
+
+ // this.olmap.getLayers().forEach((layer, i) => {
+ // if (layer.get('type') !== 'base') {
+ // if (layer.get('type') !== 'vector') {
+ // if (layer.get('type') == 'layerGroup') {
+ // layer.getLayers().forEach((sublayer, i) => {
+ // if (sublayer.getVisible()) {
+ // url = sublayer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ // if (url) {
+ // promises.push(axios.get(url));
+ // }
+ // }
+ // });
+ // }
+ // else {
+ // if (layer.getVisible()) {
+ // url = layer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ // if (url) {
+ // promises.push(axios.get(url));
+ // }
+ // }
+ // }
+ // }
+ // }
+ // });
+
+ // axios.all(promises).then((results) => {
+ // results.forEach((response) => {
+ // // console.log('mapOnClick response promises', response);
+ // if (response.data !== undefined) {
+ // if (response.data.features.length > 0) {
+ // for(let i=0; i < response.data.features.length; i++) {
+ // featureGet.push(response.data.features[i]);
+ // }
+ // }
+ // }
+ // })
+
+ // this.setState({
+ // popupDataTemp: featureGet,
+ // evtCoordinate: evt.coordinate
+ // }, () => this.setActiveListFeature());
+ // });
+
+ let hitGeojson = null;
+
+ this.olmap.getLayers().forEach((layer, i) => {
+ console.log('layer', layer.get('name'));
+ if (layer.get('type') !== 'base') {
+ if (layer.get('type') == 'layerGroup') {
+ layer.getLayers().forEach((sublayer, i) => {
+ if (sublayer.getVisible()) {
+ url = sublayer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ });
+ }
+ else {
+ if (layer.getVisible()) {
+ if (layer.get('name') !== 'ChosenLayer') {
+ if (layer.get('source_type') && layer.get('source_type') === 'geojson') {
+ let layerSource = layer.getSource();
+ // let geojsonVector = source.getFeatures();
+
+ // console.log('features', features);
+ // console.log('layer', layer);
+ // console.log('layerSource', layer.getSource());
+ // console.log('layerFeatures', layer.getSource().getFeaturesAtCoordinate(toStringXY(evt.coordinates)));
+ // console.log('layer coordinates', layer.getSource().getClosestFeatureToCoordinate(transformedCoords4326));
+ // layer.getSource().forEachFeature()
+
+ // layerSource.getFeatures(evt.pixel).then((features) => {
+ // console.log('get geojson layer', features);
+ // })
+
+
+
+ // this.olmap.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
+ // console.log('forEachFeatureAtPixel', feature, layer);
+
+ // feat.id = feature.id_;
+ // feat.geometry.type = feature.getGeometry().getType();
+ // // feat.geometry.coordinates = transform(feature.getGeometry().getCoordinates(), 'EPSG:3857', 'EPSG:4326');
+ // feat.geometry.coordinates = feature.getGeometry().getCoordinates();
+ // feat.properties = feature.getProperties();
+ // delete feat.properties["geometry"];
+
+ // console.log('feat', feat);
+ // featureGet.push(feat);
+ // })
+
+
+ hitGeojson = this.olmap.getFeaturesAtPixel(evt.pixel);
+ console.log('hitGeojson', hitGeojson);
+
+ // layerSource.getFeaturesAtCoordinate(evt.coordinate);
+ // console.log('layerSource.getFeatures', layerSource.getFeaturesAtCoordinate(transformedCoords4326));
+ // console.log('transform', transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326'));
+ }
+ else if (layer.get('source_type') === "wms") {
+ url = layer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+
+
+ if (hitGeojson && hitGeojson.length > 0) {
+ for (let i=0; i < hitGeojson.length; i++) {
+ let feature = hitGeojson[i];
+
+ let feat = {
+ "type": "Feature",
+ "id": "",
+ "geometry": {
+ "type": "",
+ "coordinates": []
+ },
+ "geometry_name": "the_geom",
+ "properties": {}
+ }
+
+ feat.id = feature.id_;
+ feat.geometry.type = feature.getGeometry().getType();
+ // feat.geometry.coordinates = transform(feature.getGeometry().getCoordinates(), 'EPSG:3857', 'EPSG:4326');
+ feat.geometry.coordinates = feature.getGeometry().getCoordinates();
+ feat.properties = feature.getProperties();
+ delete feat.properties["geometry"];
+
+ console.log('feat', feat);
+ featureGet.push(feat);
+ }
+
+ console.log('featureGet geojson', featureGet);
+ }
+
+
+ // kalo dari WMS
+ if (promises.length > 0) {
+ axios.all(promises).then((results) => {
+ results.forEach((response) => {
+ console.log('mapOnClick response promises', response);
+ if (response.data !== undefined) {
+ if (response.data.features.length > 0) {
+ for(let i=0; i < response.data.features.length; i++) {
+ /*data example:
+ {
+ "type": "FeatureCollection",
+ "totalFeatures": "unknown",
+ "features": [
+ {
+ "type": "Feature",
+ "id": "paxel_area_code_20210426.5083",
+ "geometry": {
+ "type": "MultiPolygon",
+ "coordinates": [
+ [
+ [
+ [
+ 106.522270001261,
+ -6.66321000044036
+ ],
+ [
+ 106.536260000699,
+ -6.66382999935416
+ ],
+ [
+ 106.556582195013,
+ -6.68497003983464
+ ],
+ [
+ 106.541310000657,
+ -6.71486999865072
+ ],
+ [
+ 106.542630000375,
+ -6.74058999942815
+ ],
+ [
+ 106.550740756582,
+ -6.7473471734325
+ ],
+ [
+ 106.533284161136,
+ -6.75148465469226
+ ],
+ [
+ 106.524773753407,
+ -6.76232523192311
+ ],
+ [
+ 106.498398062322,
+ -6.75218427058684
+ ],
+ [
+ 106.46682763259,
+ -6.75104031405846
+ ],
+ [
+ 106.459021692598,
+ -6.73381922767441
+ ],
+ [
+ 106.481760000125,
+ -6.72494999944212
+ ],
+ [
+ 106.504030000085,
+ -6.70412999979885
+ ],
+ [
+ 106.51431934866,
+ -6.65951255475977
+ ],
+ [
+ 106.522270001261,
+ -6.66321000044036
+ ]
+ ]
+ ]
+ ]
+ },
+ "geometry_name": "the_geom",
+ "properties": {
+ "fid": 37287,
+ "desa": "MALASARI",
+ "provinsi": "JAWA BARAT",
+ "kabkot": "BOGOR",
+ "kecamatan": "NANGGUNG",
+ "post_code": null,
+ "city_code": "",
+ "ph_code": "",
+ "locker_cod": "",
+ "area_code": "",
+ "id": 37287,
+ "cluster_area_code": "",
+ "service_ty": null
+ }
+ }
+ ],
+ "crs": {
+ "type": "name",
+ "properties": {
+ "name": "urn:ogc:def:crs:EPSG::4326"
+ }
+ }
+ }
+
+ */
+ featureGet.push(response.data.features[i]);
+ }
+ }
+ }
+ })
+
+
+ console.log('featureGet WMS', featureGet);
+
+ // adding it here because it's trapped on axios callback
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ }, () => this.setActiveListFeature());
+ });
+ }
+
+ if (hitGeojson && promises) {
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ }, () => this.setActiveListFeature());
+ }
+ }
+
+ removeChosenLayer = () => {
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer) {
+ if (layer.get('name') !== undefined && layer.get('name') === 'ChosenLayer' ) {
+ layer.getSource().clear();
+ this.olmap.removeLayer(layer);
+ }
+ }
+ });
+ }
+
+ openPopupRight() {
+ // console.log('opening popup right...')
+ this.setState({popupRightVisible: true}, () => this.setActiveListFeature());
+ }
+
+ closePopupRight() {
+ // console.log('closing popup right...')
+ this.setState({popupRightVisible: false, popupDataTemp: []}, () => this.setActiveListFeature());
+ this.removeChosenLayer(); // selected features
+ // this.removeLayerByName('routeLayer');
+ this.setState({editGeometryVisible: false, routingBarVisible: false}); // disable editing when no ChosenLayer on Map
+ }
+
+ /*toggleImagePopup() {
+ this.setState({imagePopupVisible: !this.state.imagePopupVisible});
+ }*/
+
+ setPopupDataTemp = (feature) => {
+ // console.log('setPopupDataTemp', feature);
+ this.setState({popupDataTemp: [feature]}, () => this.setActiveListFeature());
+ }
+
+ reloadPopupData = () => {
+ const { evtCoordinate } = this.state;
+ }
+
+ setActiveListFeature = () => {
+ // console.log('this.state.popupDataTemp', this.state.popupDataTemp);
+ if (this.state.popupRightVisible) {
+ if (this.state.popupDataTemp.length === 1) {
+ this.setState({activeListFeatureId: this.state.popupDataTemp[0].id}, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ let layerName = this.state.activeListFeatureId ? this.state.activeListFeatureId.substr(0, this.state.activeListFeatureId.indexOf('.')) : '';
+ this.getLayerAttribute(layerName);
+ })
+ }
+ else {
+ this.setState({activeListFeatureId: ''}, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ })
+ }
+ }
+ else {
+ this.setState({activeListFeatureId: ''}, () => {
+ // console.log('activeListFeatureId', this.state.activeListFeatureId);
+ })
+ }
+ }
+
+ // getGeomType = async (layerName) => {
+
+ // let res = await getGeomType(layerName);
+ // console.log('getGeomType', res);
+ // return res;
+ // }
+
+ loadMap = async () => {
+ let response = await axios.get(API_LOAD_MAP).then(res => res).catch(error => error);
+ console.log('loadMap', response);
+ // this.getHomeView(response);
+ // this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ if (response.data !== undefined) {
+ if (response.data.length > 0) {
+ let dataMap = response.data[0];
+ let layersToRemove = [];
+
+ // if the API response about zoom is null
+ if (dataMap.zoom == null) {
+ this.setDefaultMap();
+ }
+ // if the API response about center_x and center_y is null
+ else if (dataMap.center_x == null && dataMap.center_y == null ) {
+ this.setDefaultMap();
+ }
+ // otherwise, add layer to map from map_layer response
+ else {
+ // set the zoom and center
+ this.setState({mapZoom: dataMap.zoom, mapCenter: [dataMap.center_x, dataMap.center_y]});
+ this.olmap.getView().animate({
+ zoom: dataMap.zoom,
+ center: [dataMap.center_x, dataMap.center_y]
+ });
+
+ // if map_layers from API is exist
+ if (dataMap.map_layers.length > 0) {
+ // first, removing all layers from the current map
+ this.olmap.getLayers().forEach((layer, i) => {
+ layersToRemove.push(layer);
+ });
+ if (layersToRemove.length > 0) {
+ for(let i=0; i < layersToRemove.length; i++) {
+ this.olmap.removeLayer(layersToRemove[i]);
+ }
+ }
+
+ // add map_layers from api to view
+ if (this.olmap.getLayers().array_.length < 1) {
+ // console.log('layer empty', response.data);
+ let map_layers = dataMap.map_layers;
+ if (map_layers !== undefined) {
+ // console.log('ada map_layers', map_layers);
+ if (map_layers.length > 0) {
+ for (let i=0; i < map_layers.length; i++) {
+ let newLayer = null;
+
+ // if layer_type is not base
+ if (map_layers[i].layer_type !== 'base') {
+ newLayer = new ImageLayer({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new OlSourceImageWMS(map_layers[i].layer_source),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ // if layer_type is base
+ else {
+ // if base is OSM (OlSourceOsm);
+ if (map_layers[i].layer_name == 'OSM') {
+ newLayer = new OlLayerTile({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new OlSourceOsm(),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ // if base is other than OSM
+ else {
+ newLayer = new OlLayerTile({
+ name: map_layers[i].layer_name,
+ title: map_layers[i].layer_title,
+ source: new XYZSource(map_layers[i].layer_source),
+ type: map_layers[i].layer_type,
+ geom_type: map_layers[i].layer_geom_type,
+ visible: map_layers[i].layer_visible,
+ // zIndex: map_layers[i].layer_position
+ })
+ }
+ }
+
+ // console.log('adding new layer', newLayer);
+
+ // add the map_layers from API
+ this.olmap.addLayer(newLayer);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ saveMap = () => {
+ /* What map update data that are needed?
+ - title of map (o)
+ - zoom
+ - projection
+ - center_x
+ - center_y
+ - base_layer_id
+ - mapLayers[]
+ - layer_name
+ - layer_type (base / layer)
+ - layer_geom_type
+ - layer_source
+ - layer_visible
+ - layer_position
+
+ Example of layer_source:
+ {
+ url: appConfig.geoserver_host+'wms',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':tanah_sekolah',
+ 'TILED': true,
+ 'SLD': layerStyleUrl+'tanah_sekolah'
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous'
+ }
+ */
+ let confirmation = window.confirm('Are you sure you want to save this map?');
+ // let mapId = localStorage.getItem('u_group') === "kominfo" ? 2 : 1;
+ let mapId = MAP_ID; // get from m_group
+ let mapTitle = localStorage.getItem('u_group')+"_map"; // get from m_group
+ let mapZoom = this.olmap.getView().getZoom();
+ let mapProjection = this.olmap.getView().getProjection().code_;
+ let mapCenter = this.olmap.getView().getCenter();
+ let center_x = mapCenter[0]; // longitude
+ let center_y = mapCenter[1]; // latitude
+ let mapLayers = [];
+ let requestPayload = null;
+ let layerType = '';
+ let layerGeomType = '';
+ let count = 0;
+
+ if (confirmation) {
+ this.olmap.getLayers().forEach( async (layer, i) => {
+
+ // console.log('layer after confirmation i', i, layer);
+ layerType = layer.get('type') !== undefined ? layer.get('type') : 'layer';
+
+ if (layer.get('name') !== "DrawingLayer" && layer.get('name') !== "ChosenLayer") {
+ if (layer.get('type') === "base") {
+ if (layer.get('name') === "OSM") {
+ // if the baselayer is OSM, use the OSM function from openlayers
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: 'base',
+ layer_source: "OlSourceOsm", // i don't know why null in database
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ else {
+ // or if the baselayer is other than OSM (such as ESRI, Google, etc), use the XYZSource
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: 'base',
+ layer_source: {
+ // url: 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
+ url: layer.getSource().urls[0],
+ projection: mapProjection,
+ maxZoom: 18
+ },
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ }
+ else {
+ // if the layer is not base layer
+ // layerGeomType = layer.get('geom_type') !== undefined ? layer.get('geom_type') : await this.getGeomType(layer.get('name'));
+ let reqGeomType = await getGeomType(layer.get('name'));
+ if (reqGeomType.success) {
+ layerGeomType = reqGeomType.result;
+
+ mapLayers.push({
+ idx: i,
+ layer_name: layer.get('name'),
+ layer_type: layerType,
+ layer_geom_type: layerGeomType,
+ layer_source: {
+ url: appConfig.geoserver_host+'wms',
+ // url: appConfig.geoserver_host+'gwc/service/wms?SERVICE=WMS',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':'+layer.get('name'),
+ 'TILED': true,
+ 'SLD': layerStyleUrl+layer.get('name')
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous'
+ },
+ layer_visible: layer.getVisible(),
+ layer_position: i
+ });
+ }
+ }
+ }
+ count = count + 1;
+
+ // the last loop, so send to updateMap API
+ // console.log('count', count);
+ // console.log('this.olmap.getLayers().array_.length',this.olmap.getLayers().array_.length);
+ // console.log('if count==this.olmap.getLayers().array_length', count == this.olmap.getLayers().array_.length);
+ if (count == this.olmap.getLayers().array_.length) {
+ console.log('terakhirrrrrr');
+ requestPayload = {
+ 'map_id': mapId,
+ 'map_title': mapTitle,
+ 'map_zoom': mapZoom,
+ 'map_projection': mapProjection,
+ 'center_x': center_x,
+ 'center_y': center_y,
+ 'map_layers': mapLayers
+ };
+ console.log('requestPayload',requestPayload);
+ this.saveMapToApi(requestPayload);
+ }
+ });
+ }
+ }
+
+ saveMapToApi = async (requestPayload) => {
+ /*const config = {
+ headers: {'Content-Type': 'application/json'}
+ };
+ console.log('saveMapToApi requestPayload', requestPayload);
+ let reqAxios = await axios.post(API_UPDATE_MAP, requestPayload, config).then(res => res).catch(error => error);
+ console.log('updateMap API',reqAxios);*/
+
+
+ const param = {
+ method: 'POST',
+ header: JSON.stringify({'Content-Type': 'application/json'}),
+ body: JSON.stringify(requestPayload)
+ }
+
+ try {
+ const result = await fetch(API_UPDATE_MAP, param).then(response => response.json()).then(res => res)
+ if(result.data){
+ console.log('after save',result);
+ // this.();
+ this.setState({alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false})
+ } else {
+ this.setState({alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true})
+ }
+ } catch(err) {
+ this.setState({alert: true, messageAlert: err.message.toString(), successAlert: false, dangerAlert: true})
+ }
+ }
+
+ toggleEditGeometry = (selectedPopupData) => {
+ let { editGeometryVisible } = this.state;
+ if (!editGeometryVisible) {
+ this.setState({
+ editGeometryVisible: true,
+ layerNameDraw: selectedPopupData.id,
+ geomTypeDraw: selectedPopupData.geometry.type
+ });
+
+ }
+ else {
+ this.cancelDraw();
+ }
+ }
+
+ cancelDraw = () => {
+ this.setState({
+ editGeometryVisible: false,
+ layerNameDraw: '',
+ geomTypeDraw: ''
+ });
+ }
+
+ toggleActiveStateAddGeometry = () => {
+ this.setState({activeStateAddGeometry: !this.state.activeStateAddGeometry});
+ }
+
+ printMap = () => {
+ /*let content = document.getElementById('map');
+ content.print();*/
+
+ /*window.print();*/
+
+ /*let content = document.getElementById('map');
+ console.log('content', content);
+ let pri = document.getElementById('ifmcontentstoprint').contentWindow;
+ pri.document.open();
+ pri.document.write(content.innerHTML);
+ pri.document.close();
+ pri.focus();
+ pri.print();*/
+
+ // let canvas = document.getElementById("map").getElementsByClassName("ol-unselectable")[0];
+ // console.log('canvas', canvas);
+ // canvas.setAttribute('crossorigin', true);
+ // let img = canvas.toDataURL("image/png");
+ // console.log('img', img);
+ // let link = document.getElementById('image-download');
+ // link.href = img;
+ // link.click();
+
+ // this.olmap.once('rendercomplete', () => {
+ // // var mapCanvas = document.createElement('canvas');
+ // let mapCanvas = document.getElementById("map").getElementsByClassName("ol-unselectable")[0];
+ // var size = this.olmap.getSize();
+ // mapCanvas.width = size[0];
+ // mapCanvas.height = size[1];
+ // var mapContext = mapCanvas.getContext('2d');
+ // console.log('mapContext', mapContext);
+ // Array.prototype.forEach.call(
+ // document.querySelectorAll('.ol-layer canvas'),
+ // (canvas) => {
+ // if (canvas.width > 0) {
+ // var opacity = canvas.parentNode.style.opacity;
+ // mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
+ // var transform = canvas.style.transform;
+ // // Get the transform parameters from the style's transform matrix
+ // var matrix = transform
+ // .match(/^matrix\(([^\(]*)\)$/)[1]
+ // .split(',')
+ // .map(Number);
+ // // Apply the transform to the export map context
+ // CanvasRenderingContext2D.prototype.setTransform.apply(
+ // mapContext,
+ // matrix
+ // );
+ // mapContext.drawImage(canvas, 0, 0);
+ // }
+ // }
+ // );
+ // if (navigator.msSaveBlob) {
+ // // link download attribuute does not work on MS browsers
+ // navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png');
+ // } else {
+ // var link = document.getElementById('image-download');
+ // link.href = mapCanvas.toDataURL();
+ // link.click();
+ // }
+ // });
+ // this.olmap.renderSync();
+
+ this.olmap.once('rendercomplete', () => {
+ domtoimage
+ .toJpeg(this.olmap.getViewport())
+ .then((dataUrl) => {
+ console.log('dataUrl', dataUrl);
+ // var pdf = new jsPDF('landscape', undefined, 'a4');
+ // pdf.addImage(dataUrl, 'JPEG', 0, 0, 297, 210);
+ // pdf.save('map.pdf');
+
+ // let img = dataUrl.toDataURL("image/png");
+ // console.log('img', img);
+ let link = document.getElementById('image-download');
+ link.href = dataUrl;
+ link.click();
+ toast.success("Success Print Map!")
+ })
+ .catch(e => toast.error(e.toString()));
+ });
+
+ }
+
+ signOut = (e) => {
+ e.preventDefault()
+ // localStorage.removeItem("u_group");
+ // localStorage.removeItem("fullname");
+ window.localStorage.clear();
+ // emptyConstants();
+ this.props.history.push('/login');
+ }
+
+ getLayerAttribute = async (layerName) => {
+ const res = await getLayerAttribute(layerName);
+ console.log('getLayerAttribute',res);
+ if (res.success) {
+ // console.log(res.result);
+ if (res.result.data) {
+ if (res.result.data.length > 0) {
+ this.setState({layer_attribute: res.result.data}, () => {
+ console.log(this.state.layer_attribute);
+ });
+ }
+ }
+ }
+ else {
+ // alert(res.result);
+ toast.warn(res.result);
+ }
+ }
+
+ // when checking chekbox on Layer Tree Panel
+ onCheckOpt = (state, checkedKeys) => {
+ this.setState({[state]: checkedKeys});
+ }
+
+ setLayer = async (state) => {
+ console.log('setLayer', state);
+
+ // console.log('salesGeojson', salesGeojson);
+
+ // let extent = this.olmap.getView().calculateExtent(this.olmap.getSize());
+
+ // console.log('extent', extent);
+
+ await this.setState({isProcessing: true});
+
+ this.closePopupRight();
+ // this.clearMapLayers();
+
+ const { checkedKeysSales, checkedKeysCustomer, checkedKeysOffice, checkedKeysDemografi, checkedKeysAnalisa, checkedKeysEmployeeDivision,
+ salesGroupTree, employeeDivisionTree, queryBuilderOutput, queryBuilderType, checkedKeysProjectTree, projectTree } = this.state;
+ let layersToAdd = [];
+ let newLayer = null;
+ let vectorSource = null;
+ let vectorLayer = null;
+
+ // Sales
+ if (state === 'checkedKeysSales') {
+
+ let filterGroup = [];
+ let sales_group_id = null;
+
+ // first remove officeLayer & routeLayer
+ this.removeLayerByName('salesLayer');
+ this.removeLayerByName('routeLayer');
+
+ if (checkedKeysSales && checkedKeysSales.length > 0) {
+
+ // let sales = await this.getSalesFeatures();
+ // console.log('sales', sales);
+
+ // vectorSource = new VectorSource({
+ // format: new GeoJSON(),
+ // url: salesGeojson
+ // })
+
+ // vectorLayer = new VectorLayer({
+ // name: 'salesLayer',
+ // source_type: 'geojson',
+ // source: vectorSource
+ // });
+
+ // layersToAdd.push(vectorLayer);
+
+ // kalo centang parent nya
+ if (checkedKeysSales.includes('sales-0')) {
+ // ambil group_id children
+ for (let i=0; i < salesGroupTree[0].children.length; i++) {
+ // console.log('select all salesGroupTree', salesGroupTree[0].children[i]);
+ sales_group_id = salesGroupTree[0].children[i].sales_group_id;
+ filterGroup.push(sales_group_id);
+ }
+ }
+ else {
+ // ambil berdasarkan yang diselect
+ for (let i=0; i < checkedKeysSales.length; i++) {
+ let obj = salesGroupTree[0].children.find(data => (data.key == checkedKeysSales[i]))
+ // console.log('selected checkedKeysSales obj', obj);
+ sales_group_id = obj.sales_group_id;
+ filterGroup.push(sales_group_id);
+ }
+ }
+
+ // get the API data first
+ let sales = await getSalesFeatures(filterGroup, this.state.salesGroupTree);
+ console.log('sales', sales);
+ if(queryBuilderType === "Sales"){
+ if(queryBuilderOutput !== ""){
+ const data = sales.features;
+ let res = alasql(queryBuilderOutput, [data]);
+ console.log('res alasql', res);
+ sales = {
+ type:"FeatureCollection",
+ features:res
+ }
+ }
+ }
+
+ // generate new layer
+ if (sales && sales.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(sales, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'salesLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: SALES_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ toast.warn('Sales data is not found at this group');
+ }
+ }
+ else if (checkedKeysSales && checkedKeysSales.length < 1) {
+ this.removeLayerByName('salesLayer');
+ this.removeLayerByName('routeLayer');
+ this.closePopupRight();
+ }
+ }
+
+ // Customer
+ else if (state === 'checkedKeysCustomer') {
+
+ // first remove customerLayer
+ this.removeLayerByName('customerLayer');
+
+ // then add new customerLayer
+ if (checkedKeysCustomer && checkedKeysCustomer.length > 0) {
+
+ // get the API data first
+ let customer = await getCustomerFeatures();
+ console.log('customer', customer);
+ if(queryBuilderType === "Customer"){
+ if(queryBuilderOutput !== ""){
+ const data = customer.features;
+ let res = alasql(queryBuilderOutput, [data]);
+ customer = {
+ type:"FeatureCollection",
+ features:res
+ }
+ }
+ }
+
+
+ if (customer) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(customer, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'customerLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: CUSTOMER_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+
+
+ }
+ else {
+ toast.warn('Unable to load customer data.');
+ }
+
+ }
+ else if (checkedKeysCustomer && checkedKeysCustomer.length < 1) {
+ this.removeLayerByName('customerLayer');
+ this.closePopupRight();
+ }
+ }
+
+ // Office
+ else if (state === 'checkedKeysOffice') {
+
+ // first remove officeLayer
+ this.removeLayerByName('officeLayer');
+
+ // then add new layer
+ if (checkedKeysOffice && checkedKeysOffice.length > 0) {
+
+ // get the API data first
+ let office = await getOfficeFeatures();
+ // console.log('office', office);
+
+ if(queryBuilderType === "Office"){
+ if(queryBuilderOutput !== ""){
+ const data = office.features;
+ let res = alasql(queryBuilderOutput, [data]);
+ office = {
+ type:"FeatureCollection",
+ features:res
+ }
+ }
+ }
+
+ if (office) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(office, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'officeLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: OFFICE_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ toast.warn('Unable to load office data.');
+ }
+ }
+ else if (checkedKeysOffice && checkedKeysOffice.length < 1) {
+ this.removeLayerByName('officeLayer');
+ this.closePopupRight();
+ }
+ }
+
+ // Demografi (WMS)
+ else if (state === 'checkedKeysDemografi') {
+ // kalo checkedKeysDemografi mengandung parent keynya (demografi-0), otomatis di loop semua children nya
+ // otherwise, ya keluarin layer berdasarkan yang dicentang aja.
+
+ // first remove all layers demografi
+ for (let i=0; i < demografiTree[0].children.length; i++) {
+ this.removeLayerByName(demografiTree[0].children[i].layers.name);
+ }
+
+ // then populate new layer
+ if (checkedKeysDemografi.length > 0) {
+ if (checkedKeysDemografi.includes('demografi-0')) {
+ // ambil semua children
+ for (let i=0; i < demografiTree[0].children.length; i++) {
+ newLayer = this.generateLayerWMSByName(demografiTree[0].children[i].layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ // ambil salah satu objectnya berdasarkan yang diselect
+ for (let i=0; i < checkedKeysDemografi.length; i++) {
+ let obj = demografiTree[0].children.find(data => (data.key == checkedKeysDemografi[i]))
+ console.log('selected checkedKeysDemografi obj', obj);
+ newLayer = this.generateLayerWMSByName(obj.layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ }
+ }
+
+ // Analisa (WMS)
+ else if (state === 'checkedKeysAnalisa') {
+ // kalo checkedKeysAnalisa mengandung parent keynya (analisa-0), otomatis di loop semua children nya
+ // otherwise, ya keluarin layer berdasarkan yang dicentang aja,
+ // tapi dalemannya ngecek lagi ada yg punya children juga ngga
+
+ console.log('checkedKeysAnalisa', checkedKeysAnalisa);
+
+ // first remove all layers analisa
+ for (let i=0; i < analisaTree[0].children.length; i++) {
+ let childLayerToRemove = this.findChildLayerToRemove(analisaTree[0].children[i])
+ // console.log('childLayerToRemove', childLayerToRemove)
+ if (childLayerToRemove.length > 0) {
+ for (let j=0; j < childLayerToRemove.length; j++) {
+ this.removeLayerByName(childLayerToRemove[j]);
+ }
+ }
+ }
+
+ // // then populate new layer
+ // if (checkedKeysAnalisa.length > 0) {
+ // if (checkedKeysAnalisa.includes('analisa-0')) {
+ // // ambil semua children
+ // for (let i=0; i < analisaTree[0].children.length; i++) {
+
+ // let parentObj = analisaTree[0].children[i];
+
+ // let childLayer = this.findChildLayerToAdd(parentObj, checkedKeysAnalisa);
+
+ // layersToAdd.concat(childLayer);
+
+ // // newLayer = this.generateLayerWMSByName(analisaTree[0].children[i].layers.name);
+ // // if (newLayer) {
+ // // layersToAdd.push(newLayer);
+ // // }
+ // }
+ // }
+ // else {
+ // // ambil salah satu objectnya berdasarkan yang diselect
+ // for (let i=0; i < checkedKeysAnalisa.length; i++) {
+ // let obj = analisaTree[0].children.find(data => (data.key == checkedKeysAnalisa[i]))
+ // console.log('selected checkedKeysAnalisa obj', obj);
+ // if (obj) {
+ // newLayer = this.generateLayerWMSByName(obj.layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+ // }
+ // // else {
+ // // for (let i=0; i < analisaTree[0].children.length; i++) {
+ // // let parentObj = analisaTree[0].children[i];
+ // // // this.findChildLayerToAdd(parentObj);
+ // // let childLayer = this.findChildLayerToAdd(parentObj, checkedKeysAnalisa);
+ // // layersToAdd = [...layersToAdd, ...childLayer];
+ // // }
+ // // }
+ // }
+ // }
+ // }
+
+ // if (checkedKeysAnalisa.length > 0) {
+
+ // // if (checkedKeysAnalisa.includes('analisa-0')) {
+ // // semuanya sambil ngecek apakah childrennya punya child
+ // for (let i=0; i < analisaTree[0].children.length; i++) {
+ // let childLayer = this.findChildLayerToAdd(analisaTree[0].children[i], checkedKeysAnalisa);
+ // console.log('childLayer', childLayer);
+ // layersToAdd.concat(childLayer);
+ // }
+ // // }
+ // // else {
+ // // cek berdasarkan centang tapi ngecek apakah childrennya punya child
+ // // }
+
+ // // for (let i=0; i < analisaTree[0].children.length; i++) {
+ // // let parentObj = analisaTree[0].children[i];
+ // // console.log('parentObj', parentObj);
+ // // let childLayer = this.findChildLayerToAdd(parentObj, checkedKeysAnalisa);
+ // // console.log('childLayer', childLayer);
+ // // layersToAdd.concat(childLayer);
+ // // }
+ // }
+
+
+ // then populate new layer
+ if (checkedKeysAnalisa.length > 0) {
+
+ // for (let i=0; i < analisaTree.length; i++) {
+ // let childLayer = this.findChildLayerToAdd(analisaTree[i], checkedKeysAnalisa);
+ // console.log('childLayer', childLayer);
+ // layersToAdd.concat(childLayer);
+ // }
+
+ // const getChild = (item) => item.children;
+ // let arr = [];
+
+ // analisaTree.map((item, index) => {
+
+ // console.log('item', item);
+ // if (item.hasOwnProperty('children')) {
+ // // getChild(item);
+ // arr = [...arr, ...concat(getChild(item))];
+ // }
+ // else {
+ // arr = [...arr, ...concat(item)];
+ // }
+ // })
+
+ // console.log('flattenAnalisa'. flattenAnalisa);
+ // console.log('arr', arr);
+
+ // let flattenAnalisa = lodash.flatten(analisaTree);
+ // console.log('flattenAnalisa', flattenAnalisa);
+
+
+ if (checkedKeysAnalisa.includes('analisa-0')) {
+ // ambil semua children
+ for (let i=0; i < analisaTree[0].children.length; i++) {
+ newLayer = this.generateLayerWMSByName(analisaTree[0].children[i].layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ // ambil salah satu objectnya berdasarkan yang diselect
+ for (let i=0; i < checkedKeysAnalisa.length; i++) {
+ let obj = analisaTree[0].children.find(data => (data.key == checkedKeysAnalisa[i]))
+ console.log('selected checkedKeysAnalisa obj', obj);
+ newLayer = this.generateLayerWMSByName(obj.layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ }
+
+ }
+
+ else if (state === 'checkedKeysEmployeeDivision') {
+ let filterGroup = [];
+ let employee_division_id = null;
+
+ // first remove officeLayer & routeLayer
+ this.removeLayerByName('employeeLayer');
+ // this.removeLayerByName('routeLayer');
+
+ if (checkedKeysEmployeeDivision && checkedKeysEmployeeDivision.length > 0) {
+
+ // kalo centang parent nya
+ if (checkedKeysEmployeeDivision.includes('employee-0')) {
+ // ambil group_id children
+ for (let i=0; i < employeeDivisionTree[0].children.length; i++) {
+ // console.log('select all employeeDivisionTree', employeeDivisionTree[0].children[i]);
+ employee_division_id = employeeDivisionTree[0].children[i].employee_division_id;
+ filterGroup.push(employee_division_id);
+ }
+ }
+ else {
+ // ambil berdasarkan yang diselect
+ for (let i=0; i < checkedKeysEmployeeDivision.length; i++) {
+ let obj = employeeDivisionTree[0].children.find(data => (data.key == checkedKeysEmployeeDivision[i]))
+ // console.log('selected checkedKeysEmployeeDivision obj', obj);
+ employee_division_id = obj.employee_division_id;
+ filterGroup.push(employee_division_id);
+ }
+ }
+
+ // get the API data first
+ let employee = await getEmployeeFeatures(filterGroup, this.state.employeeDivisionTree);
+ console.log('employee', employee);
+ if(queryBuilderType === "Employee"){
+ if(queryBuilderOutput !== ""){
+ const data = employee.features;
+ let res = alasql(queryBuilderOutput, [data]);
+ console.log('res alasql', res);
+ employee = {
+ type: "FeatureCollection",
+ features: res
+ }
+ }
+ }
+
+ // generate new layer
+ if (employee && employee.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(employee, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'employeeLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: EMPLOYEE_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+ else {
+ toast.warn('Employee data is not found at this group');
+ }
+ }
+ else if (checkedKeysEmployeeDivision && checkedKeysEmployeeDivision.length < 1) {
+ this.removeLayerByName('employeeLayer');
+ // this.removeLayerByName('routeLayer');
+ this.closePopupRight();
+ }
+ }
+
+ else if (state === 'checkedKeysProjectTree') {
+ console.log('checkedKeysProjectTree', checkedKeysProjectTree);
+
+ // first remove projectLayer and its features
+ this.removeLayerByName('routeLayer');
+ this.removeLayerByName('projectLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+
+ if (checkedKeysProjectTree && checkedKeysProjectTree.length > 0) {
+
+ /*
+ Logic:
+ - looping all tree
+ - there are 3 variables
+ 1. features (Array) -> untuk nampung features yg ada di laporan planning
+ 2. projectTree (Array)
+ 3. checkedKeysProjectTree (Array) -> projectTree yg tercentang
+
+ Jadi looping all nesting yg ada di projectTree (ambil object children)
+ Terus cek setiap levelnya dia ada di checkedKeysProjectTree gak?
+ Jika ada, cek apakah di object tersebut mengandung key namanya "plannings" tidak?
+ Jika iya, maka cek di dalamnya ada laporan_planning tidak?
+ Jika iya, maka push ke features[] dengan format:
+ {
+ "type": "Feature",
+ "properties": {}, // isian dari objectnya
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 107.90771484375, // object.lon
+ -6.795535025719518 // object.lat
+ ]
+ }
+ }
+ */
+
+ // for (let i=0; i < projectTree[0].children.length; i++) {
+ // this.getChildrenTree(projectTree[0].children[i]);
+ // }
+ this.getChildrenTree(projectTree[0].children);
+ this.getWaspangFeatures();
+
+ console.log('projectFeatures', this.projectFeatures);
+
+ // get the API data first
+ // let project = await getEmployeeFeatures(filterGroup, this.state.employeeDivisionTree);
+ // console.log('employee', employee);
+ // if(queryBuilderType === "Employee"){
+ // if(queryBuilderOutput !== ""){
+ // const data = employee.features;
+ // let res = alasql(queryBuilderOutput, [data]);
+ // console.log('res alasql', res);
+ // employee = {
+ // type: "FeatureCollection",
+ // features: res
+ // }
+ // }
+ // }
+
+ let project = null;
+ project = {
+ type: "FeatureCollection",
+ features: this.projectFeatures
+ }
+
+ let waspang = null;
+ waspang = {
+ type: "FeatureCollection",
+ features: this.waspangFeatures
+ }
+
+ // console.log('project', project);
+
+
+ // generate new layer
+ if (project && project.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(project, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'projectLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: PROJECT_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+
+
+ // generate new layer
+ if (waspang && waspang.features.length > 0) {
+ vectorSource = new VectorSource({
+ features: new GeoJSON().readFeatures(waspang, {
+ dataProjection: projection4326, // from
+ featureProjection: projection // to
+ })
+ })
+
+ vectorLayer = new VectorLayer({
+ name: 'waspangLayer',
+ source_type: 'geojson',
+ source: vectorSource,
+ style: WASPANG_FEATURES_STYLE
+ });
+
+ layersToAdd.push(vectorLayer);
+ }
+
+ else {
+ toast.warn('Data realisasi tidak ditemukan di project ini');
+ }
+ }
+ else if (checkedKeysProjectTree && checkedKeysProjectTree.length < 1) {
+ this.removeLayerByName('projectLayer');
+ this.removeLayerByName('routeLayer');
+ this.projectFeatures = [];
+ this.waspangFeatures = [];
+ this.closePopupRight();
+ }
+ }
+
+ if (layersToAdd.length > 0) {
+ for (let i=0; i < layersToAdd.length; i++) {
+
+ this.olmap.addLayer(layersToAdd[i]); // adding layer to exist map
+
+ console.log('check addLayer');
+ if (i === layersToAdd.length - 1) {
+ let extent = await this.getExtentLayerByName(layersToAdd[i]);
+ if (extent) {
+ this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+ }
+ }
+ }
+
+ // this.olmap.getLayers().forEach((layer, i) => {
+ // console.log('getLayers', layer);
+ // });
+
+ await this.setState({isProcessing: false});
+ }
+
+ // find the lat lon inside laporan_plannings that the planning has been checked on projectTree
+ getChildrenTree = (data) => {
+ data.map((item, index) => {
+ if (item.children && item.children.length > 0) {
+ this.getChildrenTree(item.children);
+ }
+ else if (item.laporan_plannings && item.laporan_plannings.length > 0) {
+ if (this.state.checkedKeysProjectTree.includes(item.key)) {
+ for (let i=0; i < item.laporan_plannings.length; i++) {
+ console.log('got features!!!!!');
+ this.projectFeatures.push({
+ "type": "Feature",
+ "id": `realisasi.${item.laporan_plannings[i].id}`,
+ "properties": {...item.laporan_plannings[i]},
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ item.laporan_plannings[i].lon,
+ item.laporan_plannings[i].lat
+ ]
+ }
+ })
+ }
+ }
+ }
+ });
+
+ // console.log('features end....', features);
+
+ // return features;
+ }
+
+ getWaspangFeatures = () => {
+ this.waspangFeatures = [{
+ "type": "Feature",
+ "id": `m_waspang.1`,
+ "properties": {
+ "id": 1,
+ "user_id": 10,
+ "nama_user": "Ryan",
+ "nama_proyek": "FTTH Paket 2",
+ "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ "_type": "waspang"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.89285278320312,
+ -6.228275226686636
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "id": `m_waspang.2`,
+ "properties": {
+ "id": 2,
+ "user_id": 12,
+ "nama_user": "Effendi",
+ "nama_proyek": "FTTH Paket 2",
+ "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ "_type": "waspang"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.9357681274414,
+ -6.267522831839373
+ ]
+ }
+ },
+ {
+ "type": "Feature",
+ "id": `m_waspang.3`,
+ "properties": {
+ "id": 1,
+ "user_id": 16,
+ "nama_user": "Waspang C",
+ "nama_proyek": "FTTH Paket 2",
+ "mulai_tugas": "2021-11-01T09:31:32.775Z",
+ "akhir_tugas": "2021-11-30T09:31:32.775Z",
+ "_type": "waspang"
+ },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [
+ 106.80564880371092,
+ -6.263086293713913
+ ]
+ }
+ }]
+ }
+
+ findChildLayerToRemove = (parentObj) => {
+
+ let layersToRemove = [];
+
+ if (parentObj.hasOwnProperty('children')) {
+
+ // get semua children layer name nya
+ for (let i=0; i < parentObj.children.length; i++) {
+ // newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+
+ layersToRemove.push(parentObj.children[i].layers.name)
+ }
+ }
+ else {
+ layersToRemove.push(parentObj.layers.name)
+ }
+
+ return layersToRemove;
+
+ }
+
+ // findChildLayerToAdd = (parentObj) => {
+ // for (let i=0; i < parentObj.length; i++) {
+
+ // }
+ // }
+
+ findChildLayerToAdd = (parentObj, checkedKeys) => {
+
+ let layersToAdd = [];
+ let newLayer = null;
+
+ // 1. cek apakah parentObj itu kecentang atau ngga
+ // 2. cek apakah parentObj itu punya child apa ngga
+ // kalo kecentang parent nya ya berarti loop aja
+ // 3. cek apakah childnya itu kecentang ngga
+
+ console.log('parentObj', parentObj);
+
+ if (checkedKeys.includes(parentObj["key"])) {
+ if (parentObj.hasOwnProperty('children')) {
+ // loop aja semua child layernya
+ for (let i=0; i < parentObj.children.length; i++) {
+ newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ newLayer = this.generateLayerWMSByName(parentObj.layers.name);
+ if (newLayer) {
+ layersToAdd.push(newLayer);
+ }
+ }
+ }
+ else {
+ if (parentObj.hasOwnProperty('children')) {
+
+ }
+
+ }
+
+ // // tapi dicek lagi kalo childrennya punya children
+ // if (parentObj.hasOwnProperty('children')) {
+
+ // // cek apakah parent nya kecentang gak? (berdasarkan key)
+ // if (checkedKeys.includes(parentObj["key"])) {
+
+ // // centang semua children nya
+ // for (let i=0; i < parentObj.children.length; i++) {
+ // newLayer = this.generateLayerWMSByName(parentObj.children[i].layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+ // }
+ // }
+ // // just activate the selected nya aja
+ // else {
+ // // for (let i=0; i < checkedKeys.length; i++ ) {
+ // // let obj = parentObj.children.find(data => data.key == checkedKeys[i])
+ // // console.log('ngecek obj', obj);
+ // // newLayer = this.generateLayerWMSByName(obj.layers.name);
+ // // if (newLayer) {
+ // // layersToAdd.push(newLayer);
+ // // }
+ // // }
+ // }
+ // }
+ // else {
+ // newLayer = this.generateLayerWMSByName(parentObj.layers.name);
+ // if (newLayer) {
+ // layersToAdd.push(newLayer);
+ // }
+ // }
+
+ return layersToAdd;
+
+ }
+
+ getExtentLayerByName = async (layer) => {
+
+ // console.log('getExtentLayerByName', layerName, source_type);
+
+ let layerName = layer.get('name');
+ let source_type = layer.get('source_type');
+
+ // if source_type is undefined = WMS
+ // otherwise source_type is not undefined = geojson
+
+ let extent = null;
+
+ if (source_type === 'wms') {
+ let getExt = await fetch(WMS_CAPABILITIES_URL_2).then((response) => {
+ return response.text();
+ }).then((text) => text);
+
+ let result = new WMSCapabilities().read(getExt);
+ if (result && result.Capability.Layer.Layer.find(l => l.Name === appConfig.workspace_name+':'+layerName)) {
+ extent = result.Capability.Layer.Layer.find(l => l.Name === appConfig.workspace_name+':'+layerName).EX_GeographicBoundingBox;
+ }
+ }
+ else if (source_type === 'geojson') {
+ // extent = layer.getSource().getExtent();
+
+ // layer.getSource().once('change',(e) => {
+ // if (layer.getSource().getState() === 'ready') {
+ // extent = layer.getSource().getExtent();
+ // console.log('extent------------', extent);
+ // // map.getView().fit(extent, map.getSize());
+ // }
+ // });
+ extent = null
+ }
+ console.log('extent', extent);
+ return extent;
+
+ }
+
+ generateLayerWMSByName = (layerName) => {
+ let theLayer = null;
+ if (layerName) {
+ theLayer = new OlLayerTile({
+ name: layerName,
+ source_type: 'wms',
+ source: new OlSourceTileWMS({
+ url: appConfig.geoserver_host+'wms',
+ params: {
+ 'LAYERS': appConfig.workspace_name+':'+layerName,
+ 'TILED': true,
+ 'SLD': layerStyleUrl+layerName,
+ // 'CQL_FILTER': CQL_QUERY
+ },
+ serverType: 'geoserver',
+ transition: 0,
+ crossOrigin: 'anonymous',
+ }),
+ type: 'layer',
+ geom_type: 'Polygon'
+ });
+ }
+ return theLayer;
+ }
+
+ clearMapLayers = () => {
+ // console.log('clearing layers');
+ // clear map. removing all layer other than OSM
+ let removeLayers = [];
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('name') !== 'OSM') {
+ removeLayers.push(layer);
+ }
+ });
+ // console.log('removeLayers', removeLayers);
+ if (removeLayers.length > 0) {
+ for (let i=0; i < removeLayers.length; i++) {
+ this.olmap.removeLayer(removeLayers[i]);
+ }
+ }
+ }
+
+ removeLayerByName = (name) => {
+
+ let removeLayers = [];
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('name') === name) {
+ removeLayers.push(layer);
+ }
+ });
+ // console.log('removeLayers', removeLayers);
+ if (removeLayers.length > 0) {
+ for (let i=0; i < removeLayers.length; i++) {
+ this.olmap.removeLayer(removeLayers[i]);
+ }
+ }
+ }
+
+ getRoute = () => {
+ fetch(routeDummy).then((response) => {
+ response.json().then((result) => {
+ console.log('getRoute', result);
+ })
+ });
+ }
+
+ showRoute = (salesRoute) => {
+ const { mapProjection } = this.state;
+ console.log('showRoute', salesRoute);
+
+ this.removeLayerByName('routeLayer');
+ if (salesRoute.features && salesRoute.features.length < 1) {
+ toast.warn("Couldn't show route at selected time. Please select another range time.");
+ return;
+ }
+
+ let route = null;
+ let polyline = null;
+ let extent = null;
+
+ // polyline = routeDummy.routes[0].overview_polyline.points;
+ // console.log('polyline', polyline);
+
+ // route = new Polyline({
+ // }).readGeometry(polyline, {
+ // dataProjection: 'EPSG:4326',
+ // featureProjection: 'EPSG:4326',
+ // });
+
+ // let route = new Polyline().readGeometry(polyline);
+
+ // polyline = {
+ // "type": "LineString",
+ // "coordinates": [
+ // [
+ // 106.78853,
+ // -6.26235
+ // ],
+ // [
+ // 106.78863,
+ // -6.26201
+ // ],
+ // [
+ // 106.80065,
+ // -6.24523
+ // ]
+ // ]
+ // }
+
+ // console.log('check route', salesRoute.features.length > 0 && (salesRoute.features[0].geometry && salesRoute.features[0].geometry.coordinates));
+
+ if (salesRoute.features.length > 0 && (salesRoute.features[0].geometry && salesRoute.features[0].geometry.coordinates)) {
+ polyline = salesRoute.features[0].geometry;
+
+ route = new LineString(polyline.coordinates).transform('EPSG:4326', mapProjection);
+ extent = route.getExtent();
+
+ console.log('route', route);
+ console.log('extent', extent);
+
+ let routeFeature = new Feature({
+ type: 'route',
+ geometry: route,
+ geometry_name: salesRoute.features[0].geometry_name,
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties,
+ routeColor: getRandomColor()
+ });
+ let geoMarker = new Feature({
+ type: 'geoMarker',
+ geometry: new Point(route.getCoordinateAt(0)),
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties
+ });
+ let startMarker = new Feature({
+ type: 'pinRouteStart',
+ geometry: new Point(route.getCoordinateAt(0)),
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties
+ });
+ let endMarker = new Feature({
+ type: 'pinRouteEnd',
+ geometry: new Point(route.getCoordinateAt(1)),
+ id: salesRoute.features[0].id,
+ properties: salesRoute.features[0].properties
+ });
+
+ let animating = false;
+
+ let vectorLayer = new VectorLayer({
+ name: 'routeLayer',
+ source_type: 'routeLayer',
+ source: new VectorSource({
+ features: [routeFeature, geoMarker, startMarker, endMarker],
+ }),
+ style: (feature, resolution) => {
+ // hide geoMarker if animation is active
+ if (animating && feature.get('type') === 'geoMarker') {
+ return null;
+ }
+ // return ROUTE_MAP_STYLES[feature.get('type')];
+ return ROUTE_MAP_STYLES(feature, resolution);
+ },
+ });
+
+ this.olmap.addLayer(vectorLayer);
+
+ if (extent) {
+ // this.olmap.getView().fit(new transformExtent(extent, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ this.olmap.getView().fit(extent, { size: this.olmap.getSize(), duration: 500 });
+
+ }
+ }
+ }
+
+ searchRouting = async (userId, dateString) => {
+ await this.setState({isSearchingRoute: true, isProcessing: true});
+
+ const {routeType} = this.state;
+ let routes = null;
+
+ if (routeType === 'sales') {
+ routes = await getSalesRoutingApi(userId, dateString);
+ }
+ else if (routeType === 'employee') {
+ routes = await getEmployeeRoutingApi(userId, dateString);
+ }
+ else if (routeType === 'waspang') {
+ routes = await getWaspangRoutingApi(userId, dateString);
+ }
+
+ if (routes) {
+ this.setState({isSearchingRoute: false, isProcessing: false}, () => this.showRoute(routes))
+ }
+ else {
+ this.setState({isSearchingRoute: false, isProcessing: false}, () => toast.warn("Sorry. Couldn't get user waypoint"));
+ }
+ }
+
+ handleQueryBuilder = (query, type, tree) => {
+ console.log("query builder "+type, query);
+ this.setState({ queryBuilderOutput:query, queryBuilderType:type, currentQbTree:tree,currentQbType:type }, () => {
+ if(type === "Sales"){
+ this.setLayer('checkedKeysSales');
+ }else if(type === "Customer"){
+ this.setLayer('checkedKeysCustomer');
+ }else if(type === "Office"){
+ this.setLayer('checkedKeysOffice');
+ }
+ })
+ }
+
+ handleQbReset = (type) => {
+ this.setState({
+ queryBuilderOutput:'',
+ queryBuilderType:'',
+ currentQbTree:'',
+ currentQbType:'' }, () => {
+ if(type === "Sales"){
+ this.setLayer('checkedKeysSales');
+ }else if(type === "Customer"){
+ this.setLayer('checkedKeysCustomer');
+ }else if(type === "Office"){
+ this.setLayer('checkedKeysOffice');
+ }
+ })
+ }
+
+
+ render() {
+ const { alert, successAlert, dangerAlert, messageAlert } = this.state;
+ return (
+ Loading...
+
+ changeBaseLayer(item) {
+ console.log('change baselayer', item);
+ console.log(this.olmap.getLayers());
+ if (this.olmap.getLayers().values_.length == 0) {
+ // check if layers empty, so just insert base layer to position 0
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // check if layer exist
+ else if (this.olmap.getLayers().values_.length > 0) {
+ // check the position 0, if base layer then replace to new
+ if (this.olmap.getLayers().array_[0].get('type') === 'base') {
+ this.olmap.getLayers().removeAt(0);
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ // else just insert base layer at position 0
+ else {
+ this.olmap.getLayers().insertAt(0, item);
+ }
+ }
+ }
+
+ getHomeView = () => {
+ this.olmap.getView().fit(new transformExtent(Bali_bbox, 'EPSG:4326', this.olmap.getView().getProjection()), { size: this.olmap.getSize(), duration: 500 });
+ }
+
+ mapOnClick = (evt) => {
+ // console.log('map on click', evt);
+ evt.preventDefault();
+ let isDrawing = false;
+ let removedFeature = [];
+ let isRemoving = false;
+
+ let mapInteractions = [];
+ this.olmap.getInteractions().forEach((interaction) => {
+ // console.log('interaction', interaction);
+ if (interaction instanceof Draw) {
+ // console.log('drawing is active!!');
+ isDrawing = true;
+ }
+ // if (interaction instanceof Select) {
+ // console.log('select interaction is active');
+ // isRemoving = true;
+ // }
+ });
+
+ if (isDrawing) {
+ return;
+ }
+
+ // if (isRemoving) {
+ // this.olmap.getLayers().forEach((layer, i) => {
+ // if (layer.get('type') === 'vector') {
+ // let features = layer.getSource().getFeatures();
+ // features.forEach((feature) => {
+ // layer.getSource().removeFeature(feature);
+ // });
+ // }
+ // });
+ // }
+
+ let viewResolution = this.olmap.getView().getResolution();
+ let viewProjection = this.olmap.getView().getProjection();
+ let url = '';
+ let promises = [];
+ let featureGet = [];
+
+ this.olmap.getLayers().forEach((layer, i) => {
+ if (layer.get('type') !== 'base') {
+ if (layer.get('type') !== 'vector') {
+ if (layer.get('type') == 'layerGroup') {
+ layer.getLayers().forEach((sublayer, i) => {
+ if (sublayer.getVisible()) {
+ url = sublayer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ });
+ }
+ else {
+ if (layer.getVisible()) {
+ url = layer.getSource().getGetFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {'INFO_FORMAT': 'application/json'});
+ if (url) {
+ promises.push(axios.get(url));
+ }
+ }
+ }
+ }
+ }
+ });
+
+ axios.all(promises).then((results) => {
+ results.forEach((response) => {
+ // console.log('response promises', response);
+ if (response.data !== undefined) {
+ if (response.data.features.length > 0) {
+ for(let i=0; i < response.data.features.length; i++) {
+ featureGet.push(response.data.features[i]);
+ }
+ }
+ }
+ })
+
+ // console.log('featureGet', featureGet);
+ this.setState({
+ popupDataTemp: featureGet,
+ evtCoordinate: evt.coordinate
+ });
+ });
+ }
+
+ initPopup = () => {
+ let popupCloser = document.getElementById("popup-closer");
+ // let showImageFeature = document.getElementById("showImageFeature");
+ popupCloser.addEventListener("click", () => this.closePopup());
+ // showImageFeature.addEventListener("click", () => this.closePopup());
+ }
+
+ showPopup = () => {
+ console.log('----------------- showPopup');
+ this.initPopup();
+ this.fillPopupContent();
+ this.overlay.setPosition(this.state.evtCoordinate);
+ }
+
+ fillPopupContent = () => {
+ const { popupDataTemp } = this.state;
+ console.log('popupDataTemp', popupDataTemp);
+
+ if (popupDataTemp.length === 1) {
+ this.popupOneFeature(popupDataTemp[0]);
+ }
+ else if (popupDataTemp.length > 1) {
+ this.popupMoreFeature();
+ }
+ }
+
+ // renderPopup = () => {
+ // ReactDOM.render(