@ -0,0 +1,14 @@
|
||||
# Editor configuration, see http://editorconfig.org |
||||
root = true |
||||
|
||||
[*] |
||||
charset = utf-8 |
||||
end_of_line = lf |
||||
indent_size = 2 |
||||
indent_style = space |
||||
insert_final_newline = true |
||||
trim_trailing_whitespace = true |
||||
|
||||
[*.md] |
||||
max_line_length = off |
||||
trim_trailing_whitespace = false |
@ -0,0 +1,3 @@
|
||||
PORT=3000 |
||||
CHOKIDAR_USEPOLLING=true |
||||
GENERATE_SOURCEMAP=false |
@ -0,0 +1,28 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files. |
||||
|
||||
# dependencies |
||||
/node_modules |
||||
/src/views/Report/ControlMonitoringv1.rar |
||||
# testing |
||||
/coverage |
||||
|
||||
|
||||
# production |
||||
/build |
||||
|
||||
# misc |
||||
.DS_Store |
||||
.idea |
||||
.env.local |
||||
.env.development.local |
||||
.env.test.local |
||||
.env.production.local |
||||
|
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
package-lock.json |
||||
yarn.lock |
||||
|
||||
src/components/MapToolbar/MapToolbar_backup2.js |
||||
src/const/ApiConst.js |
@ -0,0 +1,410 @@
|
||||
|
||||
## API LOGIN |
||||
|
||||
Payload Login Sales |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/sales/login |
||||
{ |
||||
"username": null, //string |
||||
"password": null //string |
||||
} |
||||
``` |
||||
|
||||
|
||||
## API UPLOAD IMAGE |
||||
|
||||
Payload Upload Image |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/image/{category}/upload |
||||
//notes: gunakan form-data |
||||
Payload di form-data: |
||||
ref_id: "" //diambil dari id berdasarkan categorynya |
||||
files: tipe datanya file (ini file image1) |
||||
files: tipe datanya file (ini file image2) |
||||
files: tipe datanya file (ini file image3) |
||||
files: tipe datanya file (ini file image4, dst) |
||||
``` |
||||
|
||||
|
||||
## API OFFICE |
||||
|
||||
Search |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/office/monitoring |
||||
Payload |
||||
{ |
||||
"paging": {"start": 0, "length": 10}, |
||||
"columns": [ |
||||
{"name":"name", "logic_operator": "like", "value": "", "operator": "and"} |
||||
], |
||||
"orders": {"columns": ["name"], "ascending": true} |
||||
} |
||||
|
||||
Response |
||||
{ |
||||
"code": 200, |
||||
"data": { |
||||
"type": "FeatureCollection", |
||||
"features": [ |
||||
{ |
||||
"id": "m_office.37", |
||||
"geometry_name": "the_geom", |
||||
"type": "Feature", |
||||
"properties": { |
||||
"id": "m_office.37", |
||||
"company": 5, |
||||
"name": "goro", |
||||
"employes": "goro", |
||||
"address": "goro", |
||||
"description": "goro", |
||||
"buffer_radius": 100, |
||||
"lat": -6.178889275035602, |
||||
"lon": 106.83972036828338, |
||||
"geom": "POLYGON((93.8211107249645 106.839720368283,64.5317888436193 36.1290422496288,-6.17888927503533 6.83972036828345,-76.8895673936901 36.1290422496285,-106.178889275036 106.839720368283,-76.8895673936905 177.550398486938,-6.17888927503596 206.839720368283,64.5317888436189 177.550398486939,93.8211107249645 106.839720368283))", |
||||
"created_by": "@system", |
||||
"created_date": "2021-06-15T13:54:24.157516Z", |
||||
"modified_by": "@system", |
||||
"modified_date": "2021-06-15T13:54:24.157516Z", |
||||
"join": { |
||||
"": "" |
||||
} |
||||
}, |
||||
"geometry": { |
||||
"type": "Point", |
||||
"coordinates": [ |
||||
106.83972036828338, |
||||
-6.178889275035602 |
||||
] |
||||
} |
||||
}, |
||||
{ |
||||
"id": "m_office.36", |
||||
"geometry_name": "the_geom", |
||||
"type": "Feature", |
||||
"properties": { |
||||
"id": "m_office.36", |
||||
"company": 1, |
||||
"name": "tori", |
||||
"employes": "tori", |
||||
"address": "toritori", |
||||
"description": "toriaja", |
||||
"buffer_radius": 100, |
||||
"lat": -5.992300230787033, |
||||
"lon": 106.0353342769051, |
||||
"geom": "POLYGON((94.0076997692131 106.035334276905,64.7183778878679 35.3246561582504,-5.99230023078677 6.03533427690506,-76.7029783494415 35.3246561582501,-105.992300230787 106.035334276905,-76.702978349442 176.74601239556,-5.99230023078739 206.035334276905,64.7183778878674 176.74601239556,94.0076997692131 106.035334276905))", |
||||
"created_by": "@system", |
||||
"created_date": "2021-06-15T13:20:33.590436Z", |
||||
"modified_by": "@system", |
||||
"modified_date": "2021-06-15T13:52:05.91823Z", |
||||
"join": { |
||||
"": "" |
||||
} |
||||
}, |
||||
"geometry": { |
||||
"type": "Point", |
||||
"coordinates": [ |
||||
106.0353342769051, |
||||
-5.992300230787033 |
||||
] |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"executionTime": "2.122619ms", |
||||
"message": "OK", |
||||
"totalRecord": 2 |
||||
} |
||||
``` |
||||
|
||||
|
||||
Payload Add/Edit Office |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/office/add |
||||
[PUT] https://oslog.id/geohr-api/office/{id:[0-9]+}/edit |
||||
{ |
||||
"company": null, //int |
||||
"name": null, //string |
||||
"employes": null, //string |
||||
"address": null, //string |
||||
"description": null, //string |
||||
"geom": null //string |
||||
} |
||||
``` |
||||
|
||||
|
||||
## API CUSTOMER |
||||
|
||||
Monitoring |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/customer/monitoring |
||||
{ |
||||
"paging": {"start": 0, "length": 10}, |
||||
"columns": [ |
||||
{"name":"name", "logic_operator": "like", "value": "", "operator": "and"} |
||||
], |
||||
"orders": {"columns": ["name"], "ascending": true} |
||||
} |
||||
``` |
||||
|
||||
|
||||
|
||||
## API SALES |
||||
|
||||
Search |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/sales/monitoring |
||||
Payload |
||||
{ |
||||
"paging": {"start": 0, "length": 10}, |
||||
"columns": [ |
||||
{"name":"name", "logic_operator": "like", "value": "", "operator": "and", "table_name": "m_group_sales"} |
||||
], |
||||
"joins": [ |
||||
{"name": "group_sales", "column_results": ["name", "description"]} |
||||
], |
||||
"orders": {"columns": ["name"], "ascending": true} |
||||
} |
||||
|
||||
Response |
||||
{ |
||||
"code": 200, |
||||
"data": { |
||||
"type": "FeatureCollection", |
||||
"features": [ |
||||
{ |
||||
"id": "m_sales.1", |
||||
"geometry_name": "the_geom", |
||||
"type": "Feature", |
||||
"properties": { |
||||
"id": "m_sales.1", |
||||
"group_sales": 7, |
||||
"username": "ibnuh", |
||||
"password": "7f2ababa423061c509f4923dd04b6cf1", |
||||
"session_login": "5459aff0-82c9-40bb-a34e-e6278fd9c173", |
||||
"name": "ibnu hamdani", |
||||
"phone_number": "083823134569", |
||||
"email": "ibnuhamdani234@gmail.com", |
||||
"address": "jl tenjo bogor", |
||||
"achieve": null, |
||||
"type_sales": null, |
||||
"lat": -6.2622531, |
||||
"lon": 106.7881649, |
||||
"created_by": "admin", |
||||
"created_date": "2021-06-15T03:35:32.852925Z", |
||||
"modified_by": "admin", |
||||
"modified_date": "2021-06-15T03:35:32.852925Z", |
||||
"join": { |
||||
"group_sales_description": "Group Sales Wilayah Kebayoran baru", |
||||
"group_sales_name": "Kebayoran Baru" |
||||
} |
||||
}, |
||||
"geometry": { |
||||
"type": "Point", |
||||
"coordinates": [ |
||||
106.7881649, |
||||
-6.2622531 |
||||
] |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"executionTime": "1.916764ms", |
||||
"message": "OK", |
||||
"totalRecord": 1 |
||||
} |
||||
``` |
||||
|
||||
Payload Add/Edit Sales |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/sales/add |
||||
[PUT] https://oslog.id/geohr-api/sales/{id:[0-9]+}/edit |
||||
{ |
||||
"group_sales": null, //int |
||||
"username": null, //string |
||||
"password": null, //string |
||||
"name": null, //string |
||||
"phone_number": null, //string |
||||
"email": null, //string |
||||
"address": null, //string |
||||
"image": null //string |
||||
} |
||||
``` |
||||
|
||||
|
||||
## API GROUP SALES |
||||
|
||||
Search |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/group-sales/search |
||||
{ |
||||
"paging": {"start": 0, "length": 10}, |
||||
"columns": [ |
||||
{"name":"name", "logic_operator": "like", "value": "", "operator": "and"} |
||||
], |
||||
"orders": {"columns": ["name"], "ascending": true} |
||||
} |
||||
``` |
||||
|
||||
Payload Add/Edit Group Sales |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/group-sales/add |
||||
[PUT] https://oslog.id/geohr-api/group-sales/{id:[0-9]+}/edit |
||||
{ |
||||
"name": null, //string |
||||
"description": null //string |
||||
} |
||||
``` |
||||
|
||||
## API WAYPOINT SALES |
||||
|
||||
Search |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/waypoint-sales/monitoring?salesId=1 |
||||
Payload |
||||
{ |
||||
"paging": {"start": 0, "length": -1}, |
||||
"columns": [ |
||||
{"name":"wptime", "logic_operator": "range", "value": "2021-06-15 00:00:00", "value1": "2021-06-15 23:59:59", "operator": "and"} |
||||
], |
||||
"orders": {"columns": ["wptime"], "ascending": true} |
||||
} |
||||
``` |
||||
|
||||
Example Response (if waypoint is available) |
||||
``` |
||||
{ |
||||
"code": 200, |
||||
"data": { |
||||
"type": "FeatureCollection", |
||||
"features": [ |
||||
{ |
||||
"id": "m_sales.1", |
||||
"geometry_name": "the_geom", |
||||
"type": "Feature", |
||||
"properties": { |
||||
"id": "m_sales.1", |
||||
"group_sales": 7, |
||||
"username": "ibnuh", |
||||
"password": "7f2ababa423061c509f4923dd04b6cf1", |
||||
"session_login": "a5b5dff4-a7af-475c-9eb8-13f234d05472", |
||||
"name": "ibnu hamdani", |
||||
"phone_number": "083823134569", |
||||
"email": "ibnuhamdani234@gmail.com", |
||||
"address": "jl tenjo bogor", |
||||
"achieve": null, |
||||
"type_sales": "BTB", |
||||
"lat": -6.2623094, |
||||
"lon": 106.7880976, |
||||
"created_by": "admin", |
||||
"created_date": "2021-06-15T03:35:32.852925Z", |
||||
"modified_by": "@system", |
||||
"modified_date": "2021-06-16T07:24:31.227968Z", |
||||
"join": { |
||||
"group_sales_description": "Group Sales Wilayah Kebayoran baru", |
||||
"group_sales_name": "Kebayoran Baru" |
||||
} |
||||
}, |
||||
"geometry": { |
||||
"type": "LineString", |
||||
"coordinates": [ |
||||
[ |
||||
106.7881649, |
||||
-6.2622531 |
||||
], |
||||
..., |
||||
[ |
||||
106.7881603, |
||||
-6.2622923 |
||||
] |
||||
] |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"executionTime": "6.957314ms", |
||||
"message": "OK", |
||||
"totalRecord": 1 |
||||
} |
||||
``` |
||||
|
||||
Example Response (if waypoint is unavailable) |
||||
``` |
||||
{ |
||||
"code": 200, |
||||
"data": { |
||||
"type": "FeatureCollection", |
||||
"features": [ |
||||
{ |
||||
"id": "m_sales.2", |
||||
"geometry_name": "the_geom", |
||||
"type": "Feature", |
||||
"properties": { |
||||
"id": "m_sales.2", |
||||
"group_sales": 25, |
||||
"username": "jono", |
||||
"password": "jono123", |
||||
"session_login": null, |
||||
"name": "jono", |
||||
"phone_number": "0983838484", |
||||
"email": "jono@gmail.com", |
||||
"address": "jonoooo", |
||||
"achieve": null, |
||||
"type_sales": "BTB", |
||||
"lat": null, |
||||
"lon": null, |
||||
"created_by": "@system", |
||||
"created_date": "2021-06-16T04:06:23.743462Z", |
||||
"modified_by": "@system", |
||||
"modified_date": "2021-06-16T07:24:21.725833Z", |
||||
"join": { |
||||
"group_sales_description": "Group Sales Wilayah Cilandak", |
||||
"group_sales_name": "Cilandak" |
||||
} |
||||
}, |
||||
"geometry": { |
||||
"type": "LineString", |
||||
"coordinates": [] |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"executionTime": "2.73392ms", |
||||
"message": "OK", |
||||
"totalRecord": 0 |
||||
} |
||||
``` |
||||
|
||||
|
||||
Payload Add Waypoint Sales |
||||
``` |
||||
[POST] https://oslog.id/geohr-api/waypoint-sales/add |
||||
{ |
||||
"sales": null, //int |
||||
"lat": null, //float |
||||
"lon": null, //float |
||||
"wptime": null, //time now |
||||
"speed": null, //int |
||||
"angle": null, //float |
||||
"satelite": null, //int |
||||
} |
||||
``` |
||||
|
||||
|
||||
## API DAILY INFO |
||||
|
||||
Response (still dummy) |
||||
``` |
||||
{ |
||||
"code":200, |
||||
"data": { |
||||
"at_trip":{"total": 50, "id": [1, 2, 25]}, |
||||
"at_customer":"20", |
||||
"at_office":"30", |
||||
"present": "100", |
||||
"absent":"10", |
||||
"at_time":"2021-06-16T07:16:03.509928Z" |
||||
}, |
||||
"executionTime":"1.494754ms", |
||||
"message":"OK" |
||||
} |
||||
``` |
@ -0,0 +1,476 @@
|
||||
## [CoreUI](https://coreui.io/) for [react](./REACT.md) changelog |
||||
|
||||
##### `v2.6.0` |
||||
- move to `reactstrap v8`. Breaking changes and deprecations, see: https://github.com/reactstrap/reactstrap/blob/master/CHANGELOG.md#800-2019-04-03 |
||||
- fix(DefaultHeader): replace `AppHeaderDropdown` with `UncontrolledDropdown` |
||||
- refactor: add ie polyfills |
||||
|
||||
###### dependencies update |
||||
- update: `@coreui/coreui` to `^2.1.12` |
||||
- update: `@coreui/coreui-plugin-chartjs-custom-tooltips` to `^1.3.1` |
||||
- update: `@coreui/react` to `^2.5.1` |
||||
- update: `core-js` to `^3.1.4` |
||||
- update: `enzyme` to `^3.10.0` |
||||
- update: `enzyme-adapter-react-16` to `^1.14.0` |
||||
- update: `react-router-config` to `^5.0.1` |
||||
- update: `react-router-dom` to `^5.0.1` |
||||
- update: `reactstrap` to `^8.0.0` |
||||
|
||||
##### `v2.5.0` |
||||
- release for use with: |
||||
- react-router-dom `~5.0.0` |
||||
- @coreui/react `~2.5.0` |
||||
|
||||
###### dependencies update |
||||
- update: `@coreui/react` to `~2.5.0` |
||||
- update: `react-router-config` to `^5.0.0` |
||||
- update: `react-router-dom` to `^5.0.0` |
||||
|
||||
It turns out this is not such a breaking change, as it seemed at a glance. |
||||
Just update dependencies and you're good. |
||||
|
||||
#### _migration guide v2.1 -> v2.5_ :boom: |
||||
- update `dependencies` in `package.json` |
||||
- [ ] `@coreui/react` to `~2.5.0` |
||||
- [ ] `react-router-dom` to `^5.0.0` |
||||
- [ ] `react-router-config` to `^5.0.0` |
||||
|
||||
<del> |
||||
__BREAKING CHANGES__ :boom: |
||||
- use React Router `v5` |
||||
- drop 'Breadcrumb' in favour of `Breadcrumb2` |
||||
- drop 'SidebarNav' in favour of `SidebarNav2` |
||||
- __Breadcrumb2__: **mandatory** prop `router` 💥 see > [Breadcrumb](./src/Breadcrumb.md) |
||||
- __SidebarNav2__: **mandatory** prop `router` 💥 see > [SidebarNav](./src/SidebarNav.md) |
||||
|
||||
React Router v5 uses the new React Context API, which is incompatible with version used in 4.3. |
||||
That's a breaking change. With a raw upgrade to v5, you can encounter an error message: `You should not render a <Route> outside a <Router>` or `You should not use <Link> outside a <Router>` etc... It means that Route, Link etc, can't find the correct context object because `Breadcrumb` and `SidebarNav` components have their own context object. |
||||
|
||||
It's important to use the same instance of the `react-router-dom v5` library with template and coreui components. `@coreui/react` version `2.5.0` moves react-router-dom form dependencies to peerDependecies and takes the same library/module from the template/app instead. We have to pass `router` module object as a prop to `<AppSidebarNav>` and `<AppBreadcrumb>` |
||||
|
||||
#### _migration guide v2.1 -> v2.5_ :boom: |
||||
1. update `dependencies` in `package.json` |
||||
- [ ] `@coreui/react` to `~2.5.0` |
||||
- [ ] `react-router-dom` to `^5.0.0` |
||||
- [ ] `react-router-config` to `^5.0.0` |
||||
|
||||
2. modify `DefaultLayout.js` |
||||
- [ ] import react-router-dom module as an object |
||||
``` |
||||
import * as router from 'react-router-dom'; |
||||
``` |
||||
- [ ] import new versions of components `AppBreadcrumb2` and `AppSidebarNav2` (alias is optional, just keep consistency with markup) |
||||
```jsx |
||||
import { |
||||
... |
||||
AppBreadcrumb2 as AppBreadcrumb, |
||||
AppSidebarNav2 as AppSidebarNav |
||||
... |
||||
} from '@coreui/react'; |
||||
``` |
||||
- [ ] inject `router` object as a prop to `<AppSidebarNav>` and `<AppBreadcrumb>` |
||||
```html |
||||
<AppSidebarNav navConfig={navigation} {...this.props} router={router}/> |
||||
``` |
||||
|
||||
```html |
||||
<AppBreadcrumb appRoutes={routes} router={router}/> |
||||
``` |
||||
</del> |
||||
--- |
||||
|
||||
##### `v2.1.7` |
||||
- maintenance release for use with: |
||||
- react-router `v4.3.x` |
||||
- reactstrap `v7.x` |
||||
- @coreui/react `~2.1.7` |
||||
- chore: add `package-lock.json` with updated `tar` dependency |
||||
- chore: fix `test:cov` script |
||||
- fix(Popovers): add `trigger="legacy" delay={0}` (breaking change in reactstrap) |
||||
###### dependencies update |
||||
- update: `@coreui/react` to `~2.1.7` |
||||
- update: `@coreui/coreui-plugin-chartjs-custom-tooltips` to `^1.3.0` |
||||
- update: `enzyme-adapter-react-16` to `^1.13.0` |
||||
- update: `node-sass` to `^4.12.0` |
||||
- update: `react` to `^16.8.6` |
||||
- update: `react-app-polyfill` to `^1.0.1` |
||||
- update: `react-chartjs-2` to `^2.7.6` |
||||
- update: `react-dom` to `^16.8.6` |
||||
- update: `react-test-renderer` to `^16.8.6` |
||||
- update: `react-scripts` to `^3.0.1` |
||||
|
||||
##### `v2.1.6` |
||||
- fix(App): remove redundant react-loadable - thanks @sergeyt |
||||
- fix(routes) remove circular dependency - thanks @sergeyt |
||||
- refactor(App): change to render in Route |
||||
- fix(routes): add Home to routes - breadcrumb issue |
||||
- refactor(DefaultHeader): move to ReactRouter `NavLink` |
||||
- refactor(Forms): move to `InputGroupButtonDropdown` where applicable |
||||
|
||||
###### dependencies update |
||||
- update: `@coreui/coreui` to `^2.1.9` |
||||
- update: `@coreui/react` to `~2.1.5` |
||||
- update: `chart.js` to `^2.8.0` |
||||
- update: `enzyme-adapter-react-16` to `^1.11.2` |
||||
- update: `react` to `^16.8.5` |
||||
- update: `react-app-polyfill` to `^0.2.2` |
||||
- update: `react-dom` to `^16.8.5` |
||||
- update: `react-router-config` to `^4.4.0-beta.8` |
||||
- update: `react-router-dom` to `~4.3.1` |
||||
- update: `react-test-renderer` to `^16.8.5` |
||||
- update: `react-scripts` to `^2.1.8` |
||||
|
||||
##### `v2.1.5` |
||||
- fix: iOS 9 Safari sidebar toggle force issue `@coreui/react@2.1.5` |
||||
|
||||
###### dependencies update |
||||
- update: `@coreui/react` to `^2.1.5` |
||||
- update: `enzyme-adapter-react-16` to `^1.10.0` |
||||
- update: `flag-icon-css` to `^3.3.0` |
||||
- update: `react` to `^16.8.4` |
||||
- update: `react-dom` to `^16.8.4` |
||||
- update: `react-test-renderer` to `^16.8.4` |
||||
|
||||
##### `v2.1.4` |
||||
- maintenance release: fixes #151 #145 |
||||
###### dependencies update |
||||
- update: `@coreui/coreui` to `^2.1.7` |
||||
- update: `@coreui/react` to `^2.1.4` |
||||
- update: `bootstrap` to `^4.3.1` |
||||
- update: `core-js` to `^2.6.5` |
||||
- update: `enzyme` to `^3.9.0` |
||||
- update: `enzyme-adapter-react-16` to `^1.9.1` |
||||
- update: `prop-types` to `^15.7.2` |
||||
- update: `react` to `^16.8.2` |
||||
- update: `react-app-polyfill` to `^0.2.1` |
||||
- update: `react-dom` to `^16.8.2` |
||||
- update: `react-test-renderer` to `^16.8.2` |
||||
- update: `reactstrap` to `^7.1.0` |
||||
- update: `react-scripts` to `2.1.5` |
||||
|
||||
##### `v2.1.3` |
||||
- fix(Collapse): add `mb-0` to accordion cards |
||||
- fix(ButtonGroups): misplaced dropdownOpen |
||||
- chore: update `@coreui/coreui` to `^2.1.5` |
||||
- chore: update `@coreui/react` to `^2.1.3` |
||||
- chore: update `bootstrap` to `^4.2.1` |
||||
- chore: update `core-js` to `^2.6.1` |
||||
- chore: update `enzyme` to `^3.8.0` |
||||
- chore: update `enzyme-adapter-react-16` to `^1.7.1` |
||||
- chore: update `node-sass` to `^4.11.0` |
||||
- chore: update `react` to `^16.7.0` |
||||
- chore: update `react-app-polyfill` to `^0.2.0` |
||||
- chore: update `react-chartjs-2` to `^2.7.4` |
||||
- chore: update `react-dom` to `^16.7.0` |
||||
- chore: update `react-test-renderer` to `^16.7.0` |
||||
- chore: update `reactstrap` to `^7.0.2` |
||||
- chore: update `react-scripts` to `2.1.3` |
||||
|
||||
##### `v2.1.2` |
||||
- fix(scss): floating footer ie11 issue |
||||
- chore: update `@coreui/react` to `^2.1.1` |
||||
|
||||
##### `v2.1.1` |
||||
- refactor(App.js): code splitting with `react-loadable` (waiting for release of `react-router-dom`) |
||||
- refactor(routes.js): code splitting with `React.lazy`, remove `react-loadable` |
||||
- refactor(DefaultLayout): code splitting with `React.lazy` Aside, Footer, Header, routes |
||||
- refactor(Dashboard): tweak lazy and Suspense for Widget03 |
||||
- refactor(Login): add router link to `Register` button |
||||
- refactor(Register): add margins to social-media buttons |
||||
- chore: disable eslint warning for href="#" attribute |
||||
- chore: update `@coreui/coreui` to `^2.1.1` |
||||
- chore: update `enzyme-adapter-react-16` to `1.7.0` |
||||
- chore: update `react` to `16.6.3` |
||||
- chore: update `react-dom` to `16.6.3` |
||||
- chore: update `react-test-renderer` to `16.6.3` |
||||
|
||||
##### `v2.1.0` |
||||
- feat(SidebarNav): navLink `attributes` - optional JS object with valid JS API naming: |
||||
- valid attributes: `rel`, `target`, `hidden`, `disabled`, etc... |
||||
- starting with `@coreui/coreui`, `@coreui/react` version `2.1.0` and up |
||||
- closes #106 |
||||
- item example(`./src/_nav.js`): |
||||
```js |
||||
[ |
||||
{ |
||||
name: 'Disabled', |
||||
url: '/disabled', |
||||
icon: 'icon-ban', |
||||
attributes: { disabled: true }, |
||||
}, |
||||
{ |
||||
name: 'Try CoreUI PRO', |
||||
url: 'https://coreui.io/pro/react/', |
||||
icon: 'cui-layers icons', |
||||
variant: 'danger', |
||||
attributes: { target: '_blank', rel: "noopener" }, |
||||
} |
||||
] |
||||
``` |
||||
- fix(Cards): `card-header-actions` added to `CardHeader` for `rtl` support |
||||
- feat(Dashboard): new `Suspense` example with Widget03 |
||||
- chore: update `@coreui/coreui` to `2.1.0` |
||||
- chore: update `@coreui/react` to `2.1.0` |
||||
- chore: update `node-sass` to `4.10.0` |
||||
- chore: update `react` to `16.6.1` |
||||
- chore: update `react-dom` to `16.6.1` |
||||
- chore: update `react-test-renderer` to `16.6.1` |
||||
|
||||
##### `v2.0.14` |
||||
- chore: update `@coreui/coreui` to `2.0.25` |
||||
- chore: update `chart.js` to `2.7.3` |
||||
- chore: update `flag-icon-css` to `3.2.1` |
||||
- chore: update `node-sass` to `4.9.4` |
||||
- chore: update `react` to `16.6.0` |
||||
- chore: update `react-dom` to `16.6.0` |
||||
- chore: update `react-router-config` to `4.4.0-beta.6` |
||||
- chore: update `react-test-renderer` to `16.6.0` |
||||
- chore: update `react-scripts` to `2.1.1` |
||||
|
||||
##### `v2.0.13` |
||||
- refactor: migration to [Create React App 2.0](https://reactjs.org/blog/2018/10/01/create-react-app-v2.html) cleanup |
||||
- cleanup `package.json` scripts |
||||
- remove `babel-jest` dependency |
||||
- remove `node-sass-chokidar` dependency |
||||
- remove `npm-run-all` dependency |
||||
- move `App.js` import styles to `App.scss` |
||||
- replace imports from `node_modules/` with `~` prefix |
||||
- chore: remove unused `src/scss/vendors/charts.js/` directory |
||||
- chore: update `@coreui/coreui` to `^2.0.15` |
||||
- chore: update `@coreui/react` to `^2.0.9` |
||||
|
||||
##### `v2.0.12` |
||||
fixes some issues with `rtl`, `ie11`, `sidebar-minimized` behaviour and `aside` responsiveness |
||||
- fix(DefaultAside): `ListGroup` with `tag="div"` works better with `rtl` |
||||
- fix(DefaultLayout): `AppAside` remove deprecated `hidden` prop |
||||
- chore: update `@coreui/react` to `^2.0.8` |
||||
- chore: update `reactsrtrap` to `^6.5.0` |
||||
- chore: update `react-scripts` to `^2.0.4` |
||||
- chore: `enzyme` to `3.7.0` |
||||
- chore: `enzyme-adapter-react-16` to `1.6.0` |
||||
|
||||
##### `v2.0.11` |
||||
- chore: update `@coreui/react` to `^2.0.7` |
||||
- chore: migration to [Create React App 2.0](https://reactjs.org/blog/2018/10/01/create-react-app-v2.html) |
||||
- chore: update `react-scripts` to `^2.0.3` |
||||
- chore: update `node-sass-chokidar` to `^1.3.3` |
||||
- chore: add `node-sass v4.9.3` |
||||
- chore: add `react-app-polyfill v0.1.3` |
||||
- chore: add `eslintConfig` in `package.json` |
||||
- chore: add `browserslist` in `package.json` |
||||
- chore: update `manifest.json` |
||||
- refactor(index.js): add `react-app-polyfill` for `ie9-11` support |
||||
- refactor(index.js): migration to `serviceWorker.js` |
||||
|
||||
###### Migrating from CRA 1.x to 2.x: |
||||
affected files: |
||||
- `package.json` -> dependencies update |
||||
- `src/index.js` -> move to `serviceWorker`, add `react-app-polyfill` for `ie9-11` support when needed |
||||
|
||||
In most cases bumping the `react-scripts` version in `package.json` and running `npm install` in this folder should be enough, but it’s good to consult the [changelog](https://github.com/facebook/create-react-app/blob/master/CHANGELOG.md#migrating-from-1x-to-203) for potential breaking changes. |
||||
|
||||
--- |
||||
|
||||
##### `v2.0.10` |
||||
- chore: update `@coreui/coreui` to `^2.0.14` |
||||
- chore: update `@coreui/react` to `^2.0.6` |
||||
- chore: update `enzyme` to `^3.6.0` |
||||
- chore: update `enzyme-adapter-react-16` to `^1.5.0` |
||||
- chore: update `flag-icon-css` to `^3.2.0` |
||||
- chore: update `react` to `^16.5.2` |
||||
- chore: update `react-dom` to `^16.5.2` |
||||
- chore: update `react-router-config` to `^4.4.0-beta.1` |
||||
- chore: update `react-test-renderer` to `^16.5.2` |
||||
- chore: update `babel-jest` to `^23.6.0` |
||||
|
||||
##### `v2.0.9` |
||||
- chore: update `@coreui/icons` to `0.3.0` |
||||
- refactor(CoreUIIcons): move to `@coreui/icons v0.3.0` |
||||
- chore: update `enzyme` to `3.5.0` |
||||
- chore: update `enzyme-adapter-react-16` to `1.3.1` |
||||
- chore: update `react-loadable` to `5.5.0` |
||||
- chore: update `reactstrap` to `6.4.0` |
||||
- chore: update `react-scripts` to `1.1.5` |
||||
|
||||
##### `v2.0.8` |
||||
- fix(User): add missing unique key prop |
||||
- fix(Login): add missing form and autoComplete |
||||
- fix(Register): add missing form and autoComplete |
||||
- chore: update `@coreui/react` to `2.0.5` |
||||
- chore: update `bootstrap` to `4.1.3` |
||||
- chore: update `reactstrap` to `6.3.1` |
||||
- chore: update `babel-jest` to `23.4.2` |
||||
|
||||
##### `v2.0.5` |
||||
- feat(router): Users/User Breadcrumb example with `/users/:id` |
||||
- chore: update `@coreui/react` to `2.0.4`, |
||||
- chore: update `prop-types` to `15.6.2` |
||||
- chore: update `react` to `16.4.1` |
||||
- chore: update `react-dom` to `16.4.1` |
||||
- chore: update `react-test-renderer` to `16.4.1` |
||||
- chore: update `npm-run-all` to `4.1.3` |
||||
- chore: add `.env` file |
||||
|
||||
##### `v2.0.4` |
||||
- feat(Forms): FormFeedback valid, toggleFade |
||||
- refactor(Cards): toggleFade |
||||
- chore: update `@coreui/coreui` to `2.0.2`, |
||||
- chore: update `@coreui/react` to `2.0.1`, |
||||
- chore: update `classnames` to `2.2.6`, |
||||
- chore: update `core-js` to `2.5.7`, |
||||
- chore: update `react` to `16.4.0`, |
||||
- chore: update `react-dom` to `16.4.0`, |
||||
- chore: update `react-router-dom` to `4.3.1`, |
||||
- chore: update `react-test-renderer` to `16.4.0`, |
||||
- chore: update `reactstrap` to `6.1.0`, |
||||
- chore: update `babel-jest` to `23.0.1`, |
||||
|
||||
##### `v2.0.3` |
||||
- refactor: disable `ServiceWorker` by default |
||||
- fix(routes): mismatched `SimpleLineIcons` dynamic import |
||||
- refactor: CoreUI Icons `v0.2.0` |
||||
- chore: update`babel-jest` to `v22.4.4` |
||||
|
||||
##### `v2.0.2` |
||||
- chore: update `@coreui/react` to `v2.0.0`, |
||||
|
||||
##### `v2.0.1` |
||||
- refactor: code splitting via dynamic import |
||||
- refactor: switches view rearrange |
||||
- fix: update component names in package.json |
||||
- chore: update `node-sass-chokidar` to `v1.3.0` |
||||
- chore(release): dependencies update |
||||
|
||||
##### `v2.0.0-rc.1` |
||||
- feat: new CoreUI Icons set |
||||
|
||||
##### `v2.0.0-beta.2` |
||||
- feat: CoreUI custom tooltips plugin for chart.js |
||||
|
||||
##### `v2.0.0-beta.1` |
||||
- refactor(Switches): move to AppSwitch component |
||||
- fix: typo |
||||
|
||||
##### `v2.0.0-beta` |
||||
- update to `@coreui/react: ^2.0.0-beta` |
||||
|
||||
##### `v2.0.0-alpha.3` |
||||
- refactor(Colors): view layout, minor temp tweaks |
||||
- refactor(FullAside): - ListGroup (deprecate callout) |
||||
- refactor(Full*): containers minor fixes |
||||
- refactor(Dropdowns): minor fixes |
||||
- refactor(Forms): `card-header-actions` |
||||
- feat(Forms): `<Input type="date">` |
||||
- feat(Forms): `FormFeedback` |
||||
- feat(Collapses): Accordion, Custom Accordion |
||||
- feat(ListGroup): with TabPanes |
||||
- refactor(PaginationItem): `tag="button"` |
||||
- refactor(BrandButtons): spacing |
||||
- refactor:(Buttons): view layout |
||||
|
||||
##### `v2.0.0-alpha.2` |
||||
- refactor: FullHeader `<AppHeaderDropdown direction="down">` (required prop `direction`) |
||||
- refactor: ButtonDropdowns `<Dropdown direction="up">` (deprecate 'dropup') |
||||
- refactor: Dashboard legend badge pill |
||||
- refactor: SocialButtons to BrandButtons `btn-brand` |
||||
- refactor: Buttons spacing `mr-1` |
||||
- update: reactstrap to `5.0.0` |
||||
- update: react, react-dom to `16.3.1` |
||||
- update: node-sass-chokidar to `1.1.0` |
||||
- update: prop-types to `15.5.8` |
||||
- update: react-scripts to `1.1.4` |
||||
|
||||
##### `v2.0.0-alpha.1` |
||||
- refactor: separation of concerns - (CoreUI template vs CoreUI components) prepare to use CoreUI as dependency |
||||
- refactor: project structure change |
||||
- refactor: moved to [Create-React-App](CRA.md) |
||||
- chore: moved to [Semantic Versioning](https://semver.org/) |
||||
|
||||
##### `v1.0.10` |
||||
- refactor: `<InputGroupAddon addonType="prepend">` |
||||
- refactor: `<InputGroupAddon addonType="append">` |
||||
- refactor: `<InputGroupText>` |
||||
- refactor: remove `<InputGroupButton>` |
||||
- update: reactstrap to `5.0.0-beta` |
||||
- update: dependencies |
||||
|
||||
###### `v1.0.9` |
||||
- refactor: Sidebar structure change |
||||
|
||||
###### `v1.0.8` |
||||
- refactor: Dashboard radio buttons, new `onRadioBtnClick()` method |
||||
- update: react to `16.2.0` |
||||
- update: Bootstrap `4.0.0-beta.3` |
||||
- update: dependencies |
||||
- feature: some Bootstrap4 components added |
||||
- fix: rollback to webpack-dev-server `2.9.7` |
||||
- temp tweaks(b4 beta3): `InputGroupAddon` and `InputGroupButton` |
||||
- refactor(checkboxes, radios): temp tweaks |
||||
- feat: mobile sidebar link click closes the sidebar |
||||
- fix: .nav-tabs .nav-link `cursor: pointer` |
||||
|
||||
###### `v1.0.6` |
||||
|
||||
- update: react to `^16.1.1` |
||||
- update: reactstrap to `^5.0.0-alpha.4` |
||||
- refactor: deprecated reactstrap `NavDropdown` change to `Dropdown` with `nav` prop |
||||
- refactor: use prop `bsSize` instead of the `size` to bootstrap's input sizing |
||||
- update: dependencies |
||||
|
||||
###### `v1.0.5` |
||||
- feature: Sidebar add divider.class |
||||
- refactor: Sidebar |
||||
- moved to react: `^16.1.0` |
||||
- chore: dependencies update |
||||
|
||||
###### `v1.0.4` |
||||
- refactor: scss |
||||
|
||||
###### `v1.0.3` |
||||
- update: bootstrap to `4.0.0-beta.2` |
||||
|
||||
###### `v1.0.2` |
||||
- `HeaderDropdown` component example extracted out of `Header` |
||||
|
||||
###### `v1.0.1` |
||||
- moved to react: `^16.0.0` |
||||
- moved to reactstrap: `^5.0.0-alpha.3` |
||||
- moved to react-text-mask-hoc: `^0.10.4` |
||||
- moved from deprecated CardBlock to `CardBody` reactstrap component |
||||
- moved to `NavDropdown` in `Header` component |
||||
- fix for app-header navbar-nav dropdown-menu-right |
||||
- fix typo in Tables component PaginationItem |
||||
|
||||
###### `v1.0.0` |
||||
- Sidebar component: |
||||
- item with optional class (_nav.js) |
||||
- nav link with optional variant (_nav.js) |
||||
- external urls allowed (_nav.js) |
||||
- optional SidebarFooter, SidebarHeader, SidebarForm components |
||||
- SidebarMinimizer component |
||||
- .brand-minimized |
||||
- .sidebar-minimized, |
||||
- Header component - sidebarMinimize |
||||
- react-transition-group downgrade to v1 : (modals and alerts reactstrap:v4.8 issue) |
||||
|
||||
###### `2017.08.24` |
||||
- webpack.config env.prod |
||||
- Dashboard .dropdown-menu-right temp.scss hotfix (full) |
||||
- callout.scss .chart-wrapper hotfix (full) |
||||
|
||||
###### `2017.08.11` |
||||
- Bootstrap 4 beta |
||||
- Dashboard component (full): |
||||
- line chart for social box |
||||
- sparkline chart for callout |
||||
|
||||
###### `2017.08.01` |
||||
- Sidebar component: |
||||
- title item with optional wrapper and class (_nav.js) |
||||
- nav link item with optional badge |
||||
- code refactoring |
||||
|
||||
###### `2017.07.31` |
||||
- moved to [reactstrap](https://reactstrap.github.io/) |
||||
- moved to [webpack](https://webpack.js.org/) (dropping gulp) |
||||
- data driven Sidebar component (_nav.js) |
@ -0,0 +1,172 @@
|
||||
# Contributing to CoreUI Free React Admin Template |
||||
|
||||
Looking to contribute something to CoreUI Free React Admin Template? **Here's how you can help.** |
||||
|
||||
Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved. |
||||
|
||||
Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features. |
||||
|
||||
## Using the issue tracker |
||||
|
||||
The [issue tracker](https://github.com/coreui/coreui-free-react-admin-template/issues) is the preferred channel for [bug reports](#bug-reports), [features requests](#feature-requests) and [submitting pull requests](#pull-requests), but please respect the following restrictions: |
||||
|
||||
* Please **do not** use the issue tracker for personal support requests. |
||||
|
||||
* Please **do not** post comments consisting solely of "+1" or ":thumbsup:". |
||||
Use [GitHub's "reactions" feature](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) |
||||
instead. |
||||
|
||||
* Please **do not** open issues or pull requests regarding the code in [`@coreui/coreui`](https://github.com/coreui/coreui-react) (open them in their respective repositories). |
||||
|
||||
## Bug reports |
||||
|
||||
A bug is a _demonstrable problem_ that is caused by the code in the repository. |
||||
Good bug reports are extremely helpful, so thanks! |
||||
|
||||
Guidelines for bug reports: |
||||
|
||||
0. **Validate and lint your code** — to ensure your problem isn't caused by a simple error in your own code. |
||||
|
||||
1. **Use the GitHub issue search** — check if the issue has already been reported. |
||||
|
||||
2. **Check if the issue has been fixed** — try to reproduce it using the latest `master` or development branch in the repository. |
||||
|
||||
3. **Isolate the problem** — ideally create a [reduced test case](https://css-tricks.com/reduced-test-cases/) and a live example. [This JS Bin](http://jsbin.com/lefey/1/edit?html,output) is a helpful template. |
||||
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more |
||||
information. Please try to be as detailed as possible in your report. What is |
||||
your environment? What steps will reproduce the issue? What browser(s) and OS |
||||
experience the problem? Do other browsers show the bug differently? What |
||||
would you expect to be the outcome? All these details will help people to fix |
||||
any potential bugs. |
||||
|
||||
Example: |
||||
|
||||
> Short and descriptive example bug report title |
||||
> |
||||
> A summary of the issue and the browser/OS environment in which it occurs. If |
||||
> suitable, include the steps required to reproduce the bug. |
||||
> |
||||
> 1. This is the first step |
||||
> 2. This is the second step |
||||
> 3. Further steps, etc. |
||||
> |
||||
> `<url>` - a link to the reduced test case |
||||
> |
||||
> Any other information you want to share that is relevant to the issue being |
||||
> reported. This might include the lines of code that you have identified as |
||||
> causing the bug, and potential solutions (and your opinions on their |
||||
> merits). |
||||
|
||||
## Feature requests |
||||
|
||||
Feature requests are welcome. Before opening a feature request, please take a moment to find out whether your idea |
||||
fits with the scope and aims of the project. It's up to *you* to make a strong |
||||
case to convince the project's developers of the merits of this feature. Please |
||||
provide as much detail and context as possible. |
||||
|
||||
|
||||
## Pull requests |
||||
|
||||
Good pull requests—patches, improvements, new features—are a fantastic |
||||
help. They should remain focused in scope and avoid containing unrelated |
||||
commits. |
||||
|
||||
**Please ask first** before embarking on any significant pull request (e.g. |
||||
implementing features, refactoring code, porting to a different language), |
||||
otherwise you risk spending a lot of time working on something that the |
||||
project's developers might not want to merge into the project. |
||||
|
||||
Adhering to the following process is the best way to get your work |
||||
included in the project: |
||||
|
||||
1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, |
||||
and configure the remotes: |
||||
|
||||
```bash |
||||
# Clone your fork of the repo into the current directory |
||||
git clone https://github.com/<your-username>/free-react-admin-template.git |
||||
# Navigate to the newly cloned directory |
||||
cd free-react-admin-template |
||||
# Assign the original repo to a remote called "upstream" |
||||
git remote add upstream https://github.com/coreui/coreui-free-react-admin-template.git |
||||
``` |
||||
|
||||
2. If you cloned a while ago, get the latest changes from upstream: |
||||
|
||||
```bash |
||||
git checkout master |
||||
git pull upstream master |
||||
``` |
||||
|
||||
3. Create a new topic branch (off the main project development branch) to |
||||
contain your feature, change, or fix: |
||||
|
||||
```bash |
||||
git checkout -b <topic-branch-name> |
||||
``` |
||||
|
||||
4. Commit your changes in logical chunks. Please adhere to these [git commit |
||||
message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) |
||||
or your code is unlikely to be merged into the main project. Use Git's |
||||
[interactive rebase](https://help.github.com/articles/interactive-rebase) |
||||
feature to tidy up your commits before making them public. |
||||
|
||||
5. Locally merge (or rebase) the upstream development branch into your topic branch: |
||||
|
||||
```bash |
||||
git pull [--rebase] upstream master |
||||
``` |
||||
|
||||
6. Push your topic branch up to your fork: |
||||
|
||||
```bash |
||||
git push origin <topic-branch-name> |
||||
``` |
||||
|
||||
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title and description against the `master` branch. |
||||
|
||||
**IMPORTANT**: By submitting a patch, you agree to allow the project owners to license your work under the terms of the [MIT License](LICENSE). |
||||
|
||||
### Semantic Git commit messages |
||||
|
||||
Inspired by Sparkbox's awesome article on [semantic commit messages](http://seesparkbox.com/foundry/semantic_commit_messages). Please use following commit message format. |
||||
|
||||
* chore (updating npm tasks etc; no production code change) -> ```git test -m 'chore: commit-message-here'``` |
||||
* docs (changes to documentation) -> ```git commit -m 'docs: commit-message-here'``` |
||||
* feat (new feature) -> ```git commit -m 'feat: commit-message-here'``` |
||||
* fix (bug fix) -> ```git commit -m 'fix: commit-message-here'``` |
||||
* refactor (refactoring production code) -> ```git commit -m 'refactor: commit-message-here'``` |
||||
* style (formatting, missing semi colons, etc; no code change) -> ```git commit -m 'style: commit-message-here'``` |
||||
* test (adding missing tests, refactoring tests; no production code change) -> ```git test -m 'refactor: commit-message-here'``` |
||||
|
||||
|
||||
## Code guidelines |
||||
|
||||
### HTML |
||||
|
||||
[Adhere to the Code Guide.](http://codeguide.co/#html) |
||||
|
||||
- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags). |
||||
- Use CDNs and HTTPS for third-party JS when possible. We don't use protocol-relative URLs in this case because they break when viewing the page locally via `file://`. |
||||
- Use [WAI-ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) attributes in documentation examples to promote accessibility. |
||||
|
||||
### CSS |
||||
|
||||
[Adhere to the Code Guide.](http://codeguide.co/#css) |
||||
|
||||
- When feasible, default color palettes should comply with [WCAG color contrast guidelines](http://www.w3.org/TR/WCAG20/#visual-audio-contrast). |
||||
- Except in rare cases, don't remove default `:focus` styles (via e.g. `outline: none;`) without providing alternative styles. See [this A11Y Project post](http://a11yproject.com/posts/never-remove-css-outlines) for more details. |
||||
|
||||
### JS |
||||
|
||||
- No semicolons (in client-side JS) |
||||
- 2 spaces (no tabs) |
||||
- strict mode |
||||
- "Attractive" |
||||
- Don't use [jQuery event alias convenience methods](https://github.com/jquery/jquery/blob/master/src/event/alias.js) (such as `$().focus()`). Instead, use [`$().trigger(eventType, ...)`](http://api.jquery.com/trigger/) or [`$().on(eventType, ...)`](http://api.jquery.com/on/), depending on whether you're firing an event or listening for an event. (For example, `$().trigger('focus')` or `$().on('focus', function (event) { /* handle focus event */ })`) We do this to be compatible with custom builds of jQuery where the event aliases module has been excluded. |
||||
|
||||
## License |
||||
|
||||
By contributing your code, you agree to license your contribution under the [MIT License](LICENSE). |
@ -0,0 +1,20 @@
|
||||
Before opening an issue: |
||||
|
||||
- [Search for duplicate or closed issues](https://github.com/coreui/coreui-free-react-admin-template/issues?utf8=%E2%9C%93&q=is%3Aissue) |
||||
- Prepare a [reduced test case](https://css-tricks.com/reduced-test-cases/) for any bugs |
||||
- Read the [contributing guidelines](https://github.com/coreui/coreui-free-react-admin-template/blob/master/CONTRIBUTING.md) |
||||
|
||||
When asking general "how to" questions: |
||||
|
||||
- Please do not open an issue here |
||||
|
||||
When reporting a bug, include: |
||||
|
||||
- Operating system and version (Windows, Mac OS X, Android, iOS, Win10 Mobile) |
||||
- Browser and version (Chrome, Firefox, Safari, IE, MS Edge, Opera 15+, Android Browser) |
||||
- Reduced test cases and potential fixes using [CodePen](https://codepen.io/) or [JS Bin](https://jsbin.com/) |
||||
|
||||
When suggesting a feature, include: |
||||
|
||||
- As much detail as possible for what we should add and why it's important to CoreUI Admin Template |
||||
- Relevant links to prior art, screenshots, or live demos whenever possible |
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT) |
||||
|
||||
Copyright (c) 2018 creativeLabs Łukasz Holeczek. |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
THE SOFTWARE. |
@ -0,0 +1,41 @@
|
||||
# CoreUI React version |
||||
|
||||
## Intro |
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app) |
||||
|
||||
It uses Sass (with .scss). The styles are loaded at the template level with `node-sass-chokidar` css preprocessor |
||||
|
||||
Dependencies are handled by **npm**. |
||||
|
||||
## Directories |
||||
``` |
||||
CoreUI-React#v2.0.0 |
||||
├── public/ (static files) |
||||
│ ├── assets/ (assets) |
||||
│ ├── favicon.ico |
||||
│ └── index.html (html temlpate) |
||||
│ |
||||
├── src/ (project root) |
||||
│ ├── containers/ (container source) |
||||
│ ├── scss/ (scss/css source) |
||||
│ ├── views/ (views source) |
||||
│ ├── App.js |
||||
│ ├── App.test.js |
||||
│ ├── index.js |
||||
│ ├── _nav.js (sidebar config) |
||||
│ └── routes.js (routes config) |
||||
│ |
||||
└── package.json |
||||
``` |
||||
|
||||
## Usage |
||||
`npm i` - to install dependencies |
||||
|
||||
## Sctipts |
||||
`npm start` for developing (it runs webpack-dev-server) |
||||
`npm run build` to run a dev build |
||||
|
||||
## See also |
||||
[Create-React-App](CRA.md) |
||||
[Changelog](./CHANGELOG.md) |
||||
[Readme](./README.md) |
@ -0,0 +1,57 @@
|
||||
## GeoHR Installation |
||||
|
||||
``` bash |
||||
# clone the repo |
||||
$ git clone https://git.oslog.id/iu/GeoHR-website.git |
||||
|
||||
# go into app's directory |
||||
$ cd GeoHR-website |
||||
|
||||
# install app's dependencies |
||||
$ npm install |
||||
|
||||
# fix dependency |
||||
$ npm fix audit |
||||
|
||||
# start project |
||||
$ npm start |
||||
``` |
||||
|
||||
## API Documentation |
||||
Here is the [API Documentation](https://git.oslog.id/iu/GeoHR-website/src/branch/master/API_GeoHR_docs.md). |
||||
|
||||
|
||||
## GeoHR Build to Production |
||||
|
||||
``` bash |
||||
# build the project |
||||
$ npm run build |
||||
|
||||
# zip the files inside build folder -> name it as build.zip |
||||
|
||||
# copy the zip file to server |
||||
$ scp -rP 2001 build/build.zip dev@202.47.70.196:/var/www/html/geohr |
||||
|
||||
# login to dev@202.47.70.196 |
||||
$ ssh dev@202.47.70.196 -p 2001 |
||||
|
||||
# go to geohr folder |
||||
$ cd /var/www/html/geohr |
||||
|
||||
# unzip the build.zip |
||||
$ unzip build.zip |
||||
|
||||
# if prompt shown, choose [A] to replace all existing files |
||||
[dev@oscarp geohr]$ unzip build.zip |
||||
Archive: build.zip |
||||
replace favicon.ico? [y]es, [n]o, [A]ll, [N]one, [r]ename: A |
||||
inflating: favicon.ico |
||||
... |
||||
|
||||
# remove build.zip file |
||||
$ rm -rf build.zip |
||||
|
||||
# DONE ! |
||||
# Open siopas.co.id/geohr |
||||
# Don't forget to shift+reload on browser |
||||
``` |
@ -0,0 +1,177 @@
|
||||
[![@coreui coreui](https://img.shields.io/badge/@coreui%20-coreui-lightgrey.svg?style=flat-square)](https://github.com/coreui/coreui) |
||||
[![npm package][npm-coreui-badge]][npm-coreui] |
||||
[![NPM downloads][npm-coreui-download]][npm-coreui] |
||||
[![@coreui react](https://img.shields.io/badge/@coreui%20-react-lightgrey.svg?style=flat-square)](https://github.com/coreui/react) |
||||
[![npm package][npm-coreui-react-badge]][npm-coreui-react] |
||||
[![NPM downloads][npm-coreui-react-download]][npm-coreui-react] |
||||
|
||||
[npm-coreui]: https://www.npmjs.com/package/@coreui/coreui |
||||
[npm-coreui-badge]: https://img.shields.io/npm/v/@coreui/coreui.png?style=flat-square |
||||
[npm-coreui-download]: https://img.shields.io/npm/dm/@coreui/coreui.svg?style=flat-square |
||||
[npm-coreui-react]: https://www.npmjs.com/package/@coreui/react |
||||
[npm-coreui-react-badge]: https://img.shields.io/npm/v/@coreui/react.png?style=flat-square |
||||
[npm-coreui-react-download]: https://img.shields.io/npm/dm/@coreui/react.svg?style=flat-square |
||||
|
||||
# CoreUI Free React Admin Template v2 [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&logo=twitter)](https://twitter.com/intent/tweet?text=CoreUI%20-%20Free%20React%20Admin%20Template%20&url=https://coreui.io/react/&hashtags=bootstrap,admin,template,dashboard,panel,free,angular,react,vue) |
||||
|
||||
Please help us on [Product Hunt](https://www.producthunt.com/posts/coreui-open-source-bootstrap-4-admin-template-with-angular-2-react-js-vue-js-support) and [Designer News](https://www.designernews.co/stories/81127). Thanks in advance! |
||||
|
||||
Curious why I decided to create CoreUI? Please read this article: [Jack of all trades, master of none. Why Bootstrap Admin Templates suck.](https://medium.com/@lukaszholeczek/jack-of-all-trades-master-of-none-5ea53ef8a1f#.7eqx1bcd8) |
||||
|
||||
CoreUI is an Open Source Bootstrap Admin Template. But CoreUI is not just another Admin Template. It goes way beyond hitherto admin templates thanks to transparent code and file structure. And if that's not enough, let’s just add that CoreUI consists bunch of unique features and over 1000 high quality icons. |
||||
|
||||
CoreUI is based on Bootstrap 4 and offers 6 versions: [HTML5 AJAX](https://github.com/coreui/free-bootstrap-admin-template-ajax), [HTML5](https://github.com/coreui/free-angular-admin-template), [Angular 2+](https://github.com/coreui/free-angular-admin-template), [React.js](https://github.com/coreui/free-react-admin-template) & [Vue.js](https://github.com/coreui/free-vue-admin-template), [.NET Core 2](https://github.com/coreui/free-dotnet-admin-template). |
||||
|
||||
CoreUI is meant to be the UX game changer. Pure & transparent code is devoid of redundant components, so the app is light enough to offer ultimate user experience. This means mobile devices also, where the navigation is just as easy and intuitive as on a desktop or laptop. The CoreUI Layout API lets you customize your project for almost any device – be it Mobile, Web or WebApp – CoreUI covers them all! |
||||
|
||||
## Table of Contents |
||||
|
||||
* [Versions](#versions) |
||||
* [CoreUI Pro](#coreui-pro) |
||||
* [Admin Templates built on top of CoreUI Pro](#admin-templates-built-on-top-of-coreui-pro) |
||||
* [Installation](#installation) |
||||
* [Usage](#usage) |
||||
* [What's included](#whats-included) |
||||
* [Documentation](#documentation) |
||||
* [Contributing](#contributing) |
||||
* [Versioning](#versioning) |
||||
* [Creators](#creators) |
||||
* [Community](#community) |
||||
* [Community Projects](#community-projects) |
||||
* [License](#license) |
||||
* [Support CoreUI Development](#support-coreui-development) |
||||
|
||||
## Versions |
||||
|
||||
* [CoreUI Free Bootstrap Admin Template](https://github.com/coreui/coreui-free-bootstrap-admin-template) |
||||
* [CoreUI Free Bootstrap Admin Template (Ajax)](https://github.com/coreui/coreui-free-bootstrap-admin-template-ajax) |
||||
* [CoreUI Free Angular 2+ Admin Template](https://github.com/coreui/coreui-free-angular-admin-template) |
||||
* 🚧 CoreUI Free .NET Core 2 Admin Template (Available Soon) |
||||
* [CoreUI Free React.js Admin Template](https://github.com/coreui/coreui-free-react-admin-template) |
||||
* [CoreUI Free Vue.js Admin Template](https://github.com/coreui/coreui-free-vue-admin-template) |
||||
|
||||
## CoreUI Pro |
||||
|
||||
* 💪 [CoreUI Pro Bootstrap Admin Template](https://coreui.io/pro/) |
||||
* 💪 [CoreUI Pro Bootstrap Admin Template (Ajax)](https://coreui.io/pro/) |
||||
* 💪 [CoreUI Pro Angular Admin Template](https://coreui.io/pro/angular) |
||||
* 💪 [CoreUI Pro React Admin Template](https://coreui.io/pro/react) |
||||
* 💪 [CoreUI Pro Vue Admin Template](https://coreui.io/pro/vue) |
||||
|
||||
## Admin Templates built on top of CoreUI Pro |
||||
|
||||
| CoreUI Pro | Prime | Root | Alba | Leaf | |
||||
| --- | --- | --- | --- | --- | |
||||
| [![CoreUI Pro React Admin Template](https://coreui.io/assets/img/example-coureui.jpg)](https://coreui.io/pro/react/) | [![Prime React Admin Template](https://genesisui.com/assets/img/templates/prime1280.jpg)](https://genesisui.com/admin-templates/reactjs/prime/?support=1) | [![Root React Admin Template](https://genesisui.com/assets/img/templates/root1280.jpg)](https://genesisui.com/admin-templates/reactjs/root/?support=1) | [![Alba React Admin Template](https://genesisui.com/assets/img/templates/alba1280.jpg)](https://genesisui.com/admin-templates/reactjs/alba/?support=1) | [![Leaf React Admin Template](https://genesisui.com/assets/img/templates/leaf1280.jpg)](https://genesisui.com/admin-templates/reactjs/leaf/?support=1) |
||||
|
||||
## Installation |
||||
|
||||
``` bash |
||||
# clone the repo |
||||
$ git clone https://github.com/coreui/coreui-free-react-admin-template.git my-project |
||||
|
||||
# go into app's directory |
||||
$ cd my-project |
||||
|
||||
# install app's dependencies |
||||
$ npm install |
||||
``` |
||||
|
||||
## Create React App |
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app) |
||||
|
||||
see also: |
||||
[User Guide](CRA.md) |
||||
|
||||
### Basic usage |
||||
|
||||
``` bash |
||||
# dev server with hot reload at http://localhost:3000 |
||||
$ npm start |
||||
``` |
||||
|
||||
Navigate to [http://localhost:3000](http://localhost:3000). The app will automatically reload if you change any of the source files. |
||||
|
||||
### Build |
||||
|
||||
Run `build` to build the project. The build artifacts will be stored in the `build/` directory. |
||||
|
||||
```bash |
||||
# build for production with minification |
||||
$ npm run build |
||||
``` |
||||
|
||||
## What's included |
||||
|
||||
Within the download you'll find the following directories and files, logically grouping common assets and providing both compiled and minified variations. You'll see something like this: |
||||
|
||||
``` |
||||
CoreUI-React#v2.0.0 |
||||
├── public/ #static files |
||||
│ ├── assets/ #assets |
||||
│ └── index.html #html template |
||||
│ |
||||
├── src/ #project root |
||||
│ ├── containers/ #container source |
||||
│ ├── scss/ #user scss/css source |
||||
│ ├── views/ #views source |
||||
│ ├── App.js |
||||
│ ├── App.test.js |
||||
│ ├── index.js |
||||
│ ├── _nav.js #sidebar config |
||||
│ └── routes.js #routes config |
||||
│ |
||||
└── package.json |
||||
``` |
||||
|
||||
## Documentation |
||||
|
||||
The documentation for the CoreUI Admin Template is hosted at our website [CoreUI for React](https://coreui.io/react/) |
||||
|
||||
|
||||
## Contributing |
||||
|
||||
Please read through our [contributing guidelines](https://github.com/coreui/coreui-free-react-admin-template/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. |
||||
|
||||
Editor preferences are available in the [editor config](https://github.com/coreui/coreui-free-react-admin-template/blob/master/.editorconfig) for easy use in common text editors. Read more and download plugins at <http://editorconfig.org>. |
||||
|
||||
## Versioning |
||||
|
||||
For transparency into our release cycle and in striving to maintain backward compatibility, CoreUI Free Admin Template is maintained under [the Semantic Versioning guidelines](http://semver.org/). |
||||
|
||||
See [the Releases section of our project](https://github.com/coreui/coreui-free-react-admin-template/releases) for changelogs for each release version. |
||||
|
||||
## Creators |
||||
|
||||
**Łukasz Holeczek** |
||||
* <https://twitter.com/lukaszholeczek> |
||||
* <https://github.com/mrholek> |
||||
|
||||
**Andrzej Kopański** |
||||
* <https://github.com/xidedix> |
||||
|
||||
## Community |
||||
|
||||
Get updates on CoreUI's development and chat with the project maintainers and community members. |
||||
|
||||
- Follow [@core_ui on Twitter](https://twitter.com/core_ui). |
||||
- Read and subscribe to [CoreUI Blog](https://coreui.ui/blog/). |
||||
|
||||
### Community Projects |
||||
|
||||
Some of projects created by community but not maintained by CoreUI team. |
||||
|
||||
* [NuxtJS + Vue CoreUI](https://github.com/muhibbudins/nuxt-coreui) |
||||
* [Colmena](https://github.com/colmena/colmena) |
||||
* [mvelosop/AspNetCore2CoreUI](https://github.com/mvelosop/AspNetCore2CoreUI) |
||||
|
||||
## Copyright and license |
||||
|
||||
copyright 2018 creativeLabs Łukasz Holeczek. Code released under [the MIT license](LICENSE). |
||||
There is only one limitation you can't can’t re-distribute the CoreUI as stock. You can’t do this if you modify the CoreUI. In past we faced some problems with persons who tried to sell CoreUI based templates. |
||||
|
||||
## Support CoreUI Development |
||||
|
||||
CoreUI is an MIT licensed open source project and completely free to use. However, the amount of effort needed to maintain and develop new features for the project is not sustainable without proper financial backing. You can support development by donating on [PayPal](https://www.paypal.me/holeczek), buying [CoreUI Pro Version](https://coreui.io/pro) or buying one of our [premium admin templates](https://genesisui.com/?support=1). |
||||
|
||||
As of now I am exploring the possibility of working on CoreUI fulltime - if you are a business that is building core products using CoreUI, I am also open to conversations regarding custom sponsorship / consulting arrangements. Get in touch on [Twitter](https://twitter.com/lukaszholeczek). |
After Width: | Height: | Size: 77 KiB |
@ -0,0 +1,137 @@
|
||||
{ |
||||
"name": "simpro-web", |
||||
"version": "0.0.1", |
||||
"description": "Sistem Informasi Manajemen Proyek", |
||||
"author": "Ardhi", |
||||
"homepage": ".", |
||||
"copyright": "Copyright Integrasia Utama", |
||||
"license": "MIT", |
||||
"private": true, |
||||
"repository": { |
||||
"type": "http", |
||||
"url": "https://git.oslog.id/iu/simpro-website.git" |
||||
}, |
||||
"dependencies": { |
||||
"@coreui/coreui": "^2.1.12", |
||||
"@coreui/coreui-plugin-chartjs-custom-tooltips": "^1.3.1", |
||||
"@coreui/icons": "0.3.0", |
||||
"@coreui/react": "^2.5.1", |
||||
"@dabeng/react-orgchart": "^1.0.0", |
||||
"@iconify/icons-ant-design": "^1.0.6", |
||||
"@iconify/icons-fa-solid": "^1.0.6", |
||||
"@iconify/icons-fe": "^1.0.3", |
||||
"@iconify/icons-geo": "^1.0.3", |
||||
"@iconify/icons-ion": "^1.0.7", |
||||
"@iconify/icons-mdi": "^1.0.57", |
||||
"@iconify/icons-simple-line-icons": "^1.0.1", |
||||
"@iconify/icons-uil": "^1.0.6", |
||||
"@iconify/react": "^1.1.1", |
||||
"@nicholasadamou/react-iframe": "^1.0.3", |
||||
"@terrestris/react-geo": "^12.0.0", |
||||
"@tinymce/tinymce-react": "^3.13.0", |
||||
"alasql": "^1.7.3", |
||||
"antd": "^4.16.13", |
||||
"axios": "^0.21.1", |
||||
"bootstrap": "^4.3.1", |
||||
"chart.js": "^2.8.0", |
||||
"chartjs-plugin-datalabels": "^1.0.0", |
||||
"chartjs-plugin-zoom": "^0.7.7", |
||||
"classnames": "^2.2.6", |
||||
"compressorjs": "^1.0.7", |
||||
"core-js": "^3.1.4", |
||||
"dhtmlx-gantt": "^7.1.7", |
||||
"dom-to-image": "^2.6.0", |
||||
"enzyme": "^3.10.0", |
||||
"enzyme-adapter-react-16": "^1.14.0", |
||||
"faker": "^6.6.6", |
||||
"flag-icon-css": "^3.3.0", |
||||
"font-awesome": "^4.7.0", |
||||
"history": "^5.2.0", |
||||
"interactjs": "^1.10.11", |
||||
"leaflet": "^1.7.1", |
||||
"leaflet-defaulticon-compatibility": "^0.1.1", |
||||
"leaflet-draw": "^1.0.4", |
||||
"moment": "^2.24.0", |
||||
"node-sass": "^4.12.0", |
||||
"numeral": "^2.0.6", |
||||
"ol": "^5.3.3", |
||||
"plotly.js": "^1.45.3", |
||||
"prop-types": "^15.7.2", |
||||
"re-resizable": "^6.9.0", |
||||
"react": "^16.14.0", |
||||
"react-app-polyfill": "^1.0.1", |
||||
"react-awesome-query-builder": "^4.3.0", |
||||
"react-bootstrap-sweetalert": "^5.1.9", |
||||
"react-bootstrap-table-next": "^3.3.3", |
||||
"react-bootstrap-table2-editor": "^1.4.0", |
||||
"react-bootstrap-table2-paginator": "^2.1.0", |
||||
"react-bootstrap-table2-toolkit": "^2.1.1", |
||||
"react-calendar-timeline": "^0.27.0", |
||||
"react-chartjs-2": "^2.7.6", |
||||
"react-color": "^2.17.3", |
||||
"react-content-loader": "^6.0.3", |
||||
"react-dom": "^16.14.0", |
||||
"react-grid-layout": "^1.2.5", |
||||
"react-leaflet": "^3.2.0", |
||||
"react-leaflet-draw": "^0.19.8", |
||||
"react-loader-spinner": "^3.1.5", |
||||
"react-notifications": "^1.7.2", |
||||
"react-openlayers": "^0.2.1", |
||||
"react-plotly.js": "^2.4.0", |
||||
"react-rnd": "^10.1.3", |
||||
"react-router-config": "^5.0.1", |
||||
"react-router-dom": "^5.0.1", |
||||
"react-select": "^4.3.1", |
||||
"react-slick": "^0.28.1", |
||||
"react-test-renderer": "^16.8.6", |
||||
"react-toastify": "^5.5.0", |
||||
"react-top-loading-bar": "^1.2.0", |
||||
"reactstrap": "^8.0.0", |
||||
"redux": "^4.0.5", |
||||
"script-case": "^1.0.0", |
||||
"simple-line-icons": "^2.4.1", |
||||
"slick-carousel": "^1.8.1", |
||||
"underscore": "^1.13.1", |
||||
"xlsx": "^0.17.0" |
||||
}, |
||||
"devDependencies": { |
||||
"@babel/core": "^7.14.5", |
||||
"@faker-js/faker": "^6.0.0", |
||||
"babel-plugin-module-resolver": "^4.1.0", |
||||
"clean-webpack-plugin": "^3.0.0", |
||||
"react-scripts": "^3.0.1", |
||||
"webpack-sources": "1.0.1" |
||||
}, |
||||
"scripts": { |
||||
"start": "react-scripts start", |
||||
"build": "react-scripts --max_old_space_size=8096 build", |
||||
"test": "react-scripts test", |
||||
"test:cov": "npm test -- --coverage --watchAll=false", |
||||
"test:debug": "react-scripts --inspect-brk test --runInBand", |
||||
"eject": "react-scripts eject" |
||||
}, |
||||
"bugs": { |
||||
"url": "https://git.oslog.id/iu/simpro-website/issues" |
||||
}, |
||||
"eslintConfig": { |
||||
"extends": "react-app" |
||||
}, |
||||
"browserslist": [ |
||||
">0.2%", |
||||
"not dead", |
||||
"not ie <= 9", |
||||
"not op_mini all" |
||||
], |
||||
"jest": { |
||||
"collectCoverageFrom": [ |
||||
"src/**/*.{js,jsx}", |
||||
"!**/*index.js", |
||||
"!src/serviceWorker.js", |
||||
"!src/polyfill.js" |
||||
] |
||||
}, |
||||
"engines": { |
||||
"node": ">=8.10", |
||||
"npm": ">=6" |
||||
} |
||||
} |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 41 KiB |
@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
||||
<meta name="description" content="OSPRO"> |
||||
<meta name="author" content="Integrasia Utama"> |
||||
<meta name="keyword" content="OSPRO,Integrasia,OSLOG,Asset,WebGIS,Aplikasi,Tracking System"> |
||||
<title>OSPRO</title> |
||||
<!-- |
||||
manifest.json provides metadata used when your web app is added to the |
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/ |
||||
--> |
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> |
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/simpro-icon.ico"> |
||||
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon_bmd_denpasar.ico"> --> |
||||
<link rel="stylesheet" href="https://unpkg.com/@coreui/icons@1.0.0/css/all.min.css"> |
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" |
||||
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" |
||||
crossorigin="" /> |
||||
<link rel="stylesheet" |
||||
href="https://cdnjs.cloudflare.com/ajax/libs/material-design-iconic-font/2.2.0/css/material-design-iconic-font.min.css"> |
||||
<!-- |
||||
Notice the use of %PUBLIC_URL% in the tags above. |
||||
It will be replaced with the URL of the `public` folder during the build. |
||||
Only files inside the `public` folder can be referenced from the HTML. |
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will |
||||
work correctly both with client-side routing and a non-root public URL. |
||||
Learn how to configure a non-root public URL by running `npm run build`. |
||||
--> |
||||
<!-- Global site tag (gtag.js) - Google Analytics --> |
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-118965717-3"></script> |
||||
<script> |
||||
window.dataLayer = window.dataLayer || []; |
||||
|
||||
function gtag() { |
||||
dataLayer.push(arguments); |
||||
} |
||||
gtag('js', new Date()); |
||||
// Shared ID |
||||
gtag('config', 'UA-118965717-3'); |
||||
// React.js ID |
||||
gtag('config', 'UA-118965717-6'); |
||||
|
||||
</script> |
||||
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" |
||||
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" |
||||
crossorigin=""></script> |
||||
</head> |
||||
|
||||
<!-- BODY options, add following classes to body to change options |
||||
|
||||
// Header options |
||||
1. '.header-fixed' - Fixed Header |
||||
|
||||
// Brand options |
||||
1. '.brand-minimized' - Minimized brand (Only symbol) |
||||
|
||||
// Sidebar options |
||||
1. '.sidebar-fixed' - Fixed Sidebar |
||||
2. '.sidebar-hidden' - Hidden Sidebar |
||||
3. '.sidebar-off-canvas' - Off Canvas Sidebar |
||||
4. '.sidebar-minimized' - Minimized Sidebar (Only icons) |
||||
5. '.sidebar-compact' - Compact Sidebar |
||||
|
||||
// Aside options |
||||
1. '.aside-menu-fixed' - Fixed Aside Menu |
||||
2. '.aside-menu-hidden' - Hidden Aside Menu |
||||
3. '.aside-menu-off-canvas' - Off Canvas Aside Menu |
||||
|
||||
// Breadcrumb options |
||||
1. '.breadcrumb-fixed' - Fixed Breadcrumb |
||||
|
||||
// Footer options |
||||
1. '.footer-fixed' - Fixed footer |
||||
|
||||
--> |
||||
|
||||
<body> |
||||
<noscript> |
||||
You need to enable JavaScript to run this app. |
||||
</noscript> |
||||
<div id="root"> |
||||
|
||||
</div> |
||||
<!-- |
||||
This HTML file is a template. |
||||
If you open it directly in the browser, you will see an empty page. |
||||
|
||||
You can add webfonts, meta tags, or analytics to this file. |
||||
The build step will place the bundled scripts into the <body> tag. |
||||
|
||||
To begin the development, run `npm start` or `yarn start`. |
||||
To create a production bundle, use `npm run build` or `yarn build`. |
||||
--> |
||||
</body> |
||||
|
||||
</html> |
@ -0,0 +1,15 @@
|
||||
{ |
||||
"short_name": "GEOHR", |
||||
"name": "GEOHR", |
||||
"icons": [ |
||||
{ |
||||
"src": "./assets/img/favicon.png", |
||||
"sizes": "100x100", |
||||
"type": "image/png" |
||||
} |
||||
], |
||||
"start_url": ".", |
||||
"display": "standalone", |
||||
"theme_color": "#000000", |
||||
"background_color": "#ffffff" |
||||
} |
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,46 @@
|
||||
import React, { Component } from 'react'; |
||||
import { HashRouter, Route, Switch } from 'react-router-dom'; |
||||
import './App.scss'; |
||||
import 'react-notifications/lib/notifications.css'; |
||||
// import 'react-bootstrap-table-next/dist/react-bootstrap-table2.min.css';
|
||||
// import 'react-bootstrap-table-next/dist/react-bootstrap-table-next.min.js';
|
||||
// import 'react-bootstrap-table2-paginator/dist/react-bootstrap-table2-paginator.min.css';
|
||||
|
||||
const loading = () => <div className="animated fadeIn pt-3 text-center">Loading...</div>; |
||||
|
||||
// Containers
|
||||
const DefaultLayout = React.lazy(() => import('./containers/DefaultLayout')); |
||||
|
||||
// Pages
|
||||
const Login = React.lazy(() => import('./views/Pages/Login')); |
||||
const Register = React.lazy(() => import('./views/Pages/Register')); |
||||
const Page403 = React.lazy(() => import('./views/Pages/Page403')); |
||||
const Page404 = React.lazy(() => import('./views/Pages/Page404')); |
||||
const Page500 = React.lazy(() => import('./views/Pages/Page500')); |
||||
const SiopasMap = React.lazy(() => import('./views/Map')); |
||||
|
||||
class App extends Component { |
||||
|
||||
render() { |
||||
return ( |
||||
<HashRouter> |
||||
<React.Suspense fallback={loading()}> |
||||
<Switch> |
||||
<Route exact path="/login" name="Login Page" render={props => <Login {...props}/>} /> |
||||
{/* <Route exact path="/home" name="Home" render={props => <DefaultLayout {...props}/>} /> */} |
||||
<Route exact path="/register" name="Register Page" render={props => <Register {...props}/>} /> |
||||
<Route exact path="/404" name="Page 404" render={props => <Page404 {...props}/>} /> |
||||
<Route exact path="/403" name="Page 403" render={props => <Page403 {...props}/>} /> |
||||
<Route exact path="/500" name="Page 500" render={props => <Page500 {...props}/>} /> |
||||
<Route exact path="/map/view" name="Map" render={props => <SiopasMap {...props}/>} /> |
||||
{/*<Route exact path="/layerswitcher" name="Layer Switcher" render={props => <LayerSwitcherExample {...props}/>} />*/} |
||||
{/*<Route exact path="/muidt" name="Mui Datatable Example" render={props => <MuiDatatablesExample {...props}/>} />*/} |
||||
<Route path="/" name="Home" render={props => <DefaultLayout {...props}/>} /> |
||||
</Switch> |
||||
</React.Suspense> |
||||
</HashRouter> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default App; |
@ -0,0 +1,11 @@
|
||||
// Styles |
||||
// CoreUI Icons Set |
||||
@import '~@coreui/icons/css/coreui-icons.css'; |
||||
// Import Flag Icons Set |
||||
@import '~flag-icon-css/css/flag-icon.min.css'; |
||||
// Import Font Awesome Icons Set |
||||
@import '~font-awesome/css/font-awesome.min.css'; |
||||
// Import Simple Line Icons Set |
||||
@import '~simple-line-icons/css/simple-line-icons.css'; |
||||
// Import Main styles for this application |
||||
@import './scss/style.scss'; |
@ -0,0 +1,9 @@
|
||||
import React from 'react'; |
||||
import {shallow} from 'enzyme/build'; |
||||
import App from './App'; |
||||
|
||||
|
||||
it('mounts without crashing', () => { |
||||
const wrapper = shallow(<App />); |
||||
wrapper.unmount()
|
||||
}); |
@ -0,0 +1,151 @@
|
||||
let dashboardUrl = ''; |
||||
let menu = {}; |
||||
|
||||
if (localStorage.getItem('u_group') === "kominfo") { |
||||
dashboardUrl = '/dashboard-kominfo'; |
||||
menu = { |
||||
items: [ |
||||
{ |
||||
name: 'Dashboard', |
||||
url: dashboardUrl, |
||||
icon: 'icon-speedometer', |
||||
}, |
||||
{ |
||||
name: 'Map', |
||||
url: '/map/view', |
||||
icon: 'icon-map', |
||||
} |
||||
] |
||||
} |
||||
} |
||||
else { |
||||
dashboardUrl = '/dashboard'; |
||||
menu = { |
||||
items: [ |
||||
{ |
||||
name: 'Dashboard', |
||||
url: dashboardUrl, |
||||
icon: 'icon-speedometer', |
||||
}, |
||||
// {
|
||||
// name: 'Dashboard B2C',
|
||||
// url: './dashboardb2c',
|
||||
// icon: 'icon-speedometer',
|
||||
|
||||
// },
|
||||
// {
|
||||
// name: 'Users',
|
||||
// url: '/users',
|
||||
// icon: 'icon-user',
|
||||
// },
|
||||
// {
|
||||
// name: 'Offices',
|
||||
// url: '/offices',
|
||||
// icon: 'cil-home',
|
||||
// },
|
||||
// {
|
||||
// name: 'Group Sales',
|
||||
// url: '/group-sales',
|
||||
// icon: 'cil-sitemap',
|
||||
// },
|
||||
// {
|
||||
// name: 'Sales',
|
||||
// url: '/sales',
|
||||
// icon: 'icon-user',
|
||||
// },
|
||||
// {
|
||||
// name: 'Office Hours',
|
||||
// url: '/office-hours',
|
||||
// icon: 'cil-alarm',
|
||||
// },
|
||||
// {
|
||||
// name: 'Customer',
|
||||
// url: '/customer',
|
||||
// icon: 'cil-home',
|
||||
// },
|
||||
// {
|
||||
// name: 'Layers',
|
||||
// url: '/map/layers',
|
||||
// icon: 'icon-layers',
|
||||
// },
|
||||
{ |
||||
name: 'Peta', |
||||
url: '/map/view', |
||||
icon: 'icon-map', |
||||
}, |
||||
// new
|
||||
{ |
||||
name: 'Karyawan', |
||||
url: '/karyawan', |
||||
icon: 'icon-user', |
||||
}, |
||||
// {
|
||||
// name: 'Divisi Karyawan',
|
||||
// url: '/divisi-karyawan',
|
||||
// icon: 'cil-sitemap',
|
||||
// },
|
||||
// {
|
||||
// name: 'Jam Kerja',
|
||||
// url: '/office-hours',
|
||||
// icon: 'cil-alarm',
|
||||
// },
|
||||
{ |
||||
name: 'Presensi', |
||||
url: '/presensi', |
||||
icon: 'fa fa-calendar-check-o', |
||||
}, |
||||
{ |
||||
name: 'Absensi', |
||||
url: '/absensi', |
||||
icon: 'fa fa-calendar-times-o' |
||||
}, |
||||
{ |
||||
name: 'Laporan Tugas Karyawan', |
||||
url: '/laporan-tugas-karyawan', |
||||
icon: 'cil-task', |
||||
}, |
||||
// {
|
||||
// name: 'Izin',
|
||||
// url: '/izin',
|
||||
// icon: 'cil-media-pause',
|
||||
// },
|
||||
// {
|
||||
// name: 'Broadcast',
|
||||
// url: '/broadcast',
|
||||
// icon: 'cil-bullhorn',
|
||||
// },
|
||||
{ |
||||
name: 'Tombol Darurat', |
||||
url: '/panic-button', |
||||
icon: 'fa fa-dot-circle-o ', |
||||
}, |
||||
// {
|
||||
// name: 'Reimbuse',
|
||||
// url: '/reimbuse',
|
||||
// icon: 'cil-money',
|
||||
// },
|
||||
// {
|
||||
// name: 'Visit Customer',
|
||||
// url: '/visit-customer',
|
||||
// icon: 'cil-location-pin',
|
||||
// },
|
||||
{ |
||||
name: 'Menu', |
||||
url: '/menu', |
||||
icon: 'cil-menu', |
||||
}, |
||||
{ |
||||
name: 'Roles', |
||||
url: '/roles', |
||||
icon: 'cil-people', |
||||
}, |
||||
{ |
||||
name: 'Lembur', |
||||
url: '/lembur', |
||||
icon: 'fa fa-clock-o', |
||||
}, |
||||
], |
||||
}; |
||||
} |
||||
|
||||
export default menu; |
@ -0,0 +1,16 @@
|
||||
.custom-scroll::-webkit-scrollbar-track { |
||||
border-radius: 10px; |
||||
background-color: #F5F5F5; |
||||
} |
||||
|
||||
.custom-scroll::-webkit-scrollbar { |
||||
width: 10px; |
||||
height: 10px; |
||||
background-color: #F5F5F5; |
||||
} |
||||
|
||||
.custom-scroll::-webkit-scrollbar-thumb { |
||||
border-radius: 5px; |
||||
-webkit-box-shadow: 0 0 3px rgba(0,0,0,0.3); |
||||
background-color: #eaeaea; |
||||
} |
@ -0,0 +1,13 @@
|
||||
==================================================================================================================== |
||||
Layer Legend |
||||
Author: Ardhi |
||||
Description: This documentation is an example of a guidance to know how to get a legend graphic of a layer |
||||
Created on: 29th January 2020 |
||||
Full documentation here: |
||||
https://docs.geoserver.org/latest/en/user/services/wms/get_legend_graphic/index.html |
||||
I use this library: https://terrestris.github.io/react-geo/docs/latest/index.html#section-legend |
||||
==================================================================================================================== |
||||
|
||||
URL: http://192.168.99.110/geoserver/wms?request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=bmd_denpasar:test_bmd_1&transparent=true&legend_options=fontColor:0xFFFFFF;fontAntiAliasing:true;fontSize:14;fontStyle:bold; |
||||
Method: GET |
||||
Response: The image of layer symbol |
@ -0,0 +1,208 @@
|
||||
==================================================================================================================== |
||||
Layer Styles |
||||
Author: Ardhi |
||||
Description: This documentation is an example of a guidance to know how to style a layer, |
||||
a payload example using geoserver SLD file |
||||
Created on: 28th January 2020 |
||||
Full documentation here: |
||||
https://docs.geoserver.org/stable/en/user/styling/index.html |
||||
https://docs.geoserver.org/stable/en/user/styling/sld/index.html |
||||
==================================================================================================================== |
||||
|
||||
Type: Point (using Symbolizer, ex: star) |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetStyles&LAYERS=bmd_denpasar:test_bmd_2_point |
||||
Method: GET |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> |
||||
<sld:NamedLayer> |
||||
<sld:Name>bmd_denpasar:test_bmd_2_point</sld:Name> |
||||
<sld:UserStyle> |
||||
<sld:Name>point</sld:Name> |
||||
<sld:Title>Default Point</sld:Title> |
||||
<sld:IsDefault>1</sld:IsDefault> |
||||
<sld:Abstract>A sample style that draws a point</sld:Abstract> |
||||
<sld:FeatureTypeStyle> |
||||
<sld:Name>name</sld:Name> |
||||
<sld:Rule> |
||||
<sld:Name>rule1</sld:Name> |
||||
<sld:Title>Target</sld:Title> |
||||
<sld:Abstract>A 6 pixel square with a red fill and no stroke</sld:Abstract> |
||||
<sld:PointSymbolizer> |
||||
<sld:Graphic> |
||||
<sld:Mark> |
||||
<sld:WellKnownName>star</sld:WellKnownName> |
||||
<sld:Fill> |
||||
<sld:CssParameter name="fill">#11CCF1</sld:CssParameter> |
||||
</sld:Fill> |
||||
<sld:Stroke/> |
||||
</sld:Mark> |
||||
<sld:Size>15</sld:Size> |
||||
</sld:Graphic> |
||||
</sld:PointSymbolizer> |
||||
</sld:Rule> |
||||
</sld:FeatureTypeStyle> |
||||
</sld:UserStyle> |
||||
</sld:NamedLayer> |
||||
</sld:StyledLayerDescriptor> |
||||
|
||||
|
||||
Type: MultiPoint (using FillColor) |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetStyles&LAYERS=bmd_denpasar:point_tanah_sekolah0 |
||||
Method: GET |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> |
||||
<sld:NamedLayer> |
||||
<sld:Name>bmd_denpasar:point_tanah_sekolah0</sld:Name> |
||||
<sld:UserStyle> |
||||
<sld:Name>bmd_denpasar_point_tanah_sekolah1</sld:Name> |
||||
<sld:Title>azure square point style</sld:Title> |
||||
<sld:IsDefault>1</sld:IsDefault> |
||||
<sld:FeatureTypeStyle> |
||||
<sld:Name>name</sld:Name> |
||||
<sld:Rule> |
||||
<sld:Title>azure point</sld:Title> |
||||
<sld:PointSymbolizer> |
||||
<sld:Graphic> |
||||
<sld:Mark> |
||||
<sld:Fill> |
||||
<sld:CssParameter name="fill">#0033cc</sld:CssParameter> |
||||
</sld:Fill> |
||||
</sld:Mark> |
||||
<sld:Size>6</sld:Size> |
||||
</sld:Graphic> |
||||
</sld:PointSymbolizer> |
||||
</sld:Rule> |
||||
</sld:FeatureTypeStyle> |
||||
</sld:UserStyle> |
||||
</sld:NamedLayer> |
||||
</sld:StyledLayerDescriptor> |
||||
|
||||
|
||||
Type: LineString |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetStyles&LAYERS=bmd_denpasar:test_bmd_line_1 |
||||
Method: GET |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> |
||||
<sld:NamedLayer> |
||||
<sld:Name>bmd_denpasar:test_bmd_line_1</sld:Name> |
||||
<sld:UserStyle> |
||||
<sld:Name>line</sld:Name> |
||||
<sld:Title>Default Line</sld:Title> |
||||
<sld:IsDefault>1</sld:IsDefault> |
||||
<sld:Abstract>A sample style that draws a line</sld:Abstract> |
||||
<sld:FeatureTypeStyle> |
||||
<sld:Name>name</sld:Name> |
||||
<sld:Rule> |
||||
<sld:Name>rule1</sld:Name> |
||||
<sld:Title>Blue Line</sld:Title> |
||||
<sld:Abstract>A solid blue line with a 1 pixel width</sld:Abstract> |
||||
<sld:LineSymbolizer> |
||||
<sld:Stroke> |
||||
<sld:CssParameter name="stroke">#0000FF</sld:CssParameter> |
||||
</sld:Stroke> |
||||
</sld:LineSymbolizer> |
||||
</sld:Rule> |
||||
</sld:FeatureTypeStyle> |
||||
</sld:UserStyle> |
||||
</sld:NamedLayer> |
||||
</sld:StyledLayerDescriptor> |
||||
|
||||
|
||||
Type: MultiLineString |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetStyles&LAYERS=bmd_denpasar:test_multilinestring1 |
||||
Method: GET |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> |
||||
<sld:NamedLayer> |
||||
<sld:Name>bmd_denpasar:test_multilinestring1</sld:Name> |
||||
<sld:UserStyle> |
||||
<sld:Name>line</sld:Name> |
||||
<sld:Title>Default Line</sld:Title> |
||||
<sld:IsDefault>1</sld:IsDefault> |
||||
<sld:Abstract>A sample style that draws a line</sld:Abstract> |
||||
<sld:FeatureTypeStyle> |
||||
<sld:Name>name</sld:Name> |
||||
<sld:Rule> |
||||
<sld:Name>rule1</sld:Name> |
||||
<sld:Title>Blue Line</sld:Title> |
||||
<sld:Abstract>A solid blue line with a 1 pixel width</sld:Abstract> |
||||
<sld:LineSymbolizer> |
||||
<sld:Stroke> |
||||
<sld:CssParameter name="stroke">#0000FF</sld:CssParameter> |
||||
</sld:Stroke> |
||||
</sld:LineSymbolizer> |
||||
</sld:Rule> |
||||
</sld:FeatureTypeStyle> |
||||
</sld:UserStyle> |
||||
</sld:NamedLayer> |
||||
</sld:StyledLayerDescriptor> |
||||
|
||||
|
||||
Type: Polygon |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetStyles&LAYERS=bmd_denpasar:test_bmd_1 |
||||
Method: GET |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> |
||||
<sld:NamedLayer> |
||||
<sld:Name>bmd_denpasar:test_bmd_1</sld:Name> |
||||
<sld:UserStyle> |
||||
<sld:Name>polygon</sld:Name> |
||||
<sld:Title>Default Polygon</sld:Title> |
||||
<sld:IsDefault>1</sld:IsDefault> |
||||
<sld:Abstract>A sample style that draws a polygon</sld:Abstract> |
||||
<sld:FeatureTypeStyle> |
||||
<sld:Name>name</sld:Name> |
||||
<sld:Rule> |
||||
<sld:Name>rule1</sld:Name> |
||||
<sld:Title>Gray Polygon with Black Outline</sld:Title> |
||||
<sld:Abstract>A polygon with a gray fill and a 1 pixel black outline</sld:Abstract> |
||||
<sld:PolygonSymbolizer> |
||||
<sld:Fill> |
||||
<sld:CssParameter name="fill">#E72020</sld:CssParameter> |
||||
<sld:CssParameter name="fill-opacity">0.2</sld:CssParameter> |
||||
</sld:Fill> |
||||
<sld:Stroke/> |
||||
</sld:PolygonSymbolizer> |
||||
</sld:Rule> |
||||
</sld:FeatureTypeStyle> |
||||
</sld:UserStyle> |
||||
</sld:NamedLayer> |
||||
</sld:StyledLayerDescriptor> |
||||
|
||||
|
||||
Type: MultiPolygon |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetStyles&LAYERS=bmd_denpasar:test_multipolygon1 |
||||
Method: GET |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" version="1.0.0"> |
||||
<sld:NamedLayer> |
||||
<sld:Name>bmd_denpasar:test_multipolygon1</sld:Name> |
||||
<sld:UserStyle> |
||||
<sld:Name>polygon</sld:Name> |
||||
<sld:Title>Default Polygon</sld:Title> |
||||
<sld:IsDefault>1</sld:IsDefault> |
||||
<sld:Abstract>A sample style that draws a polygon</sld:Abstract> |
||||
<sld:FeatureTypeStyle> |
||||
<sld:Name>name</sld:Name> |
||||
<sld:Rule> |
||||
<sld:Name>rule1</sld:Name> |
||||
<sld:Title>Gray Polygon with Black Outline</sld:Title> |
||||
<sld:Abstract>A polygon with a gray fill and a 1 pixel black outline</sld:Abstract> |
||||
<sld:PolygonSymbolizer> |
||||
<sld:Fill> |
||||
<sld:CssParameter name="fill">#E72020</sld:CssParameter> |
||||
<sld:CssParameter name="fill-opacity">0.2</sld:CssParameter> |
||||
</sld:Fill> |
||||
<sld:Stroke/> |
||||
</sld:PolygonSymbolizer> |
||||
</sld:Rule> |
||||
</sld:FeatureTypeStyle> |
||||
</sld:UserStyle> |
||||
</sld:NamedLayer> |
||||
</sld:StyledLayerDescriptor> |
@ -0,0 +1,643 @@
|
||||
==================================================================================================================== |
||||
WFS Example |
||||
Author: Ardhi |
||||
Description: This documentation is an example of a guidance to know how geometry are saved in geoserver, |
||||
how to show table, a payload example, to update or delete geometry using geoserver rest API |
||||
Created on: 25th January 2020 |
||||
==================================================================================================================== |
||||
Create New Feature |
||||
------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
- layer name |
||||
- geom type (multi / single) |
||||
- map projection |
||||
- coordinates |
||||
- other feature atrributes (fields) |
||||
|
||||
Examples: |
||||
(Point) |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_bmd_2_point xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:Point srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11886499.833369536,-693527.4813667177</gml:coordinates> |
||||
</gml:Point> |
||||
</feature:the_geom> |
||||
<feature:nama_point>point1</feature:nama_point> |
||||
</feature:test_bmd_2_point> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult handle="Added 1 feature to '' via MapLoom."> |
||||
<ogc:FeatureId fid="test_bmd_2_point.2"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
(MultiPoint) |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_multipoint1 xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:MultiPoint srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:pointMember> |
||||
<gml:Point> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11892025.868385417,-694976.24551184</gml:coordinates> |
||||
</gml:Point> |
||||
</gml:pointMember> |
||||
<gml:pointMember> |
||||
<gml:Point> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11893350.776915178,-694453.9258029916</gml:coordinates> |
||||
</gml:Point> |
||||
</gml:pointMember> |
||||
<gml:pointMember> |
||||
<gml:Point> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11895096.089113038,-695969.9269091613</gml:coordinates> |
||||
</gml:Point> |
||||
</gml:pointMember> |
||||
</gml:MultiPoint> |
||||
</feature:the_geom> |
||||
<feature:nama_titik>area rawan bencana</feature:nama_titik> |
||||
</feature:test_multipoint1> |
||||
</wfs:Insert> |
||||
</wfs:Transaction>Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"><wfs:InsertResult handle="Added 1 feature to '' via MapLoom."><ogc:FeatureId fid="test_multipoint1.2"/></wfs:InsertResult> <wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> <wfs:Status> <wfs:SUCCESS/> </wfs:Status> </wfs:TransactionResult></wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
(LineString) |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_bmd_line_1 xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:LineString srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11886123.154847158,-693341.4126344601 11886223.617927274,-693431.829327727 11886527.877188448,-693645.671983231 11886525.006817233,-693496.4126800604 11886424.543824714,-693446.1812275994 11886384.358627707,-693416.0423298439 11886370.00685923,-693345.7181912824</gml:coordinates> |
||||
</gml:LineString> |
||||
</feature:the_geom> |
||||
<feature:nama_jalan>jalan cinta</feature:nama_jalan> |
||||
</feature:test_bmd_line_1> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"><wfs:InsertResult handle="Added 1 feature to '' via MapLoom."><ogc:FeatureId fid="test_bmd_line_1.1"/></wfs:InsertResult> <wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> <wfs:Status> <wfs:SUCCESS/> </wfs:Status> </wfs:TransactionResult></wfs:WFS_TransactionResponse> |
||||
|
||||
(MultiLineString) |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_multilinestring1 xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:MultiLineString srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:lineMember> |
||||
<gml:LineString> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11889089.199553609,-694806.789552831 11889515.599038912,-694806.789552831 11889982.886502603,-695028.7507504856 11890397.603453713,-695314.9642818893 11890607.882651944,-695817.2977438518</gml:coordinates> |
||||
</gml:LineString> |
||||
</gml:lineMember> |
||||
<gml:lineMember> |
||||
<gml:LineString> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11889001.58322468,-694941.1344097083 11888989.901047,-695297.4406506772 11889141.769713346,-695624.5418039591 11889235.22677827,-696015.8945779663 11889223.544600591,-696173.6039766396</gml:coordinates> |
||||
</gml:LineString> |
||||
</gml:lineMember> |
||||
</gml:MultiLineString> |
||||
</feature:the_geom> |
||||
<feature:nama_jalan>jalan cinta</feature:nama_jalan> |
||||
</feature:test_multilinestring1> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"><wfs:InsertResult handle="Added 1 feature to '' via MapLoom."><ogc:FeatureId fid="test_multilinestring1.2"/></wfs:InsertResult> <wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> <wfs:Status> <wfs:SUCCESS/> </wfs:Status> </wfs:TransactionResult></wfs:WFS_TransactionResponse> |
||||
|
||||
(Polygon) |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_bmd_1 xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:Polygon srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:outerBoundaryIs> |
||||
<gml:LinearRing> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11885890.360625308,-693614.4345447493 11886066.325063715,-693607.6666826681 11886047.016727008,-693545.3625436059 11885890.360625308,-693556.9077170598 11885891.754008677,-693576.0169747006 11885881.005051253,-693576.0169747006 11885890.360625308,-693614.4345447493</gml:coordinates> |
||||
</gml:LinearRing> |
||||
</gml:outerBoundaryIs> |
||||
</gml:Polygon> |
||||
</feature:the_geom> |
||||
<feature:nama_area>makam al falah</feature:nama_area> |
||||
<feature:status_area>baik</feature:status_area> |
||||
<feature:penggunaan>tempat pemakaman</feature:penggunaan> |
||||
</feature:test_bmd_1> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"><wfs:InsertResult handle="Added 1 feature to '' via MapLoom."><ogc:FeatureId fid="test_bmd_1.2"/></wfs:InsertResult> <wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> <wfs:Status> <wfs:SUCCESS/> </wfs:Status> </wfs:TransactionResult></wfs:WFS_TransactionResponse> |
||||
|
||||
(MultiPolygon) |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_multipolygon1 xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:MultiPolygon srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:polygonMember> |
||||
<gml:Polygon> |
||||
<gml:outerBoundaryIs> |
||||
<gml:LinearRing> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11886589.213954791,-694367.2474235861 11886875.42730794,-694519.1158225475 11887167.481749926,-694495.7515563164 11887161.640661087,-694805.3290865673 11886729.400086945,-694787.805820048 11886612.57831015,-694700.1894874518 11886589.213954791,-694367.2474235861</gml:coordinates> |
||||
</gml:LinearRing> |
||||
</gml:outerBoundaryIs> |
||||
</gml:Polygon> |
||||
</gml:polygonMember> |
||||
<gml:polygonMember> |
||||
<gml:Polygon> |
||||
<gml:outerBoundaryIs> |
||||
<gml:LinearRing> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11886314.682992412,-694449.02275473 11886343.88843661,-694852.0578846727 11885800.667174513,-694822.852262218 11885765.620641476,-694449.02275473 11886314.682992412,-694449.02275473</gml:coordinates> |
||||
</gml:LinearRing> |
||||
</gml:outerBoundaryIs> |
||||
</gml:Polygon> |
||||
</gml:polygonMember> |
||||
</gml:MultiPolygon> |
||||
</feature:the_geom> |
||||
<feature:nama_area>kos-kosan Ibu Jamil</feature:nama_area> |
||||
</feature:test_multipolygon1> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?><wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"><wfs:InsertResult handle="Added 1 feature to '' via MapLoom."><ogc:FeatureId fid="test_multipolygon1.1"/></wfs:InsertResult> <wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> <wfs:Status> <wfs:SUCCESS/> </wfs:Status> </wfs:TransactionResult></wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Edit Geometry |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Modified 1 feature in '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Update handle="Modified 1 feature in '' via MapLoom." typeName="geonode:test12" xmlns:feature="http://www.geonode.org/"> |
||||
<wfs:Property> |
||||
<wfs:Name>the_geom</wfs:Name> |
||||
<wfs:Value> |
||||
<gml:Polygon srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:outerBoundaryIs> |
||||
<gml:LinearRing> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11901975.891860606,-698153.9913410997 11901566.635257043,-699013.9079201279 11902842.178206988,-699160.4120491266 11902674.97220021,-698612.6135096712 11901975.891860606,-698153.9913410997</gml:coordinates> |
||||
</gml:LinearRing> |
||||
</gml:outerBoundaryIs> |
||||
</gml:Polygon> |
||||
</wfs:Value> |
||||
</wfs:Property> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test12.3"/> |
||||
</ogc:Filter> |
||||
</wfs:Update> |
||||
</wfs:Transaction> |
||||
|
||||
|
||||
IF GEOM IS NULL, THEN RESPONSE IS ERROR: |
||||
<?xml version="1.0" encoding="UTF-8"?><wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"><wfs:InsertResult><ogc:FeatureId fid="none"/></wfs:InsertResult> <wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> <wfs:Status> <wfs:FAILED/> </wfs:Status> <wfs:Message>Error performing insert: java.lang.String cannot be cast to com.vividsolutions.jts.geom.Geometry</wfs:Message> </wfs:TransactionResult></wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Edit Attributes / Edit Feature |
||||
--------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Modified 1 feature in '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Update handle="Modified 1 feature in '' via MapLoom." typeName="geonode:test12" xmlns:feature="http://www.geonode.org/"> |
||||
<wfs:Property> |
||||
<wfs:Name>nama_area</wfs:Name> |
||||
<wfs:Value>bandara3_edit</wfs:Value> |
||||
</wfs:Property> |
||||
<wfs:Property> |
||||
<wfs:Name>status_area</wfs:Name> |
||||
<wfs:Value>0</wfs:Value> |
||||
</wfs:Property> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test12.3"/> |
||||
</ogc:Filter> |
||||
</wfs:Update> |
||||
</wfs:Transaction> |
||||
|
||||
|
||||
Show Table |
||||
-------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:GetFeature maxFeatures="25" outputFormat="JSON" service="WFS" startIndex="0" version="1.1.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"> |
||||
<wfs:Query srsName="EPSG:4326" typeName="geonode:test12"/> |
||||
</wfs:GetFeature> |
||||
|
||||
|
||||
|
||||
|
||||
=================================================== |
||||
Projection: EPSG:4326 (test_bmd_1 layer / polygon) |
||||
=================================================== |
||||
|
||||
Create New Feature |
||||
-------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_bmd_1 xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:Polygon srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:outerBoundaryIs> |
||||
<gml:LinearRing> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11912150.70602516,-696067.2297045494 11912208.034207555,-696640.5074453525 11913341.849953607,-696440.5964197303 11913195.345645027,-695809.9910147788 11912150.70602516,-696067.2297045494</gml:coordinates> |
||||
</gml:LinearRing> |
||||
</gml:outerBoundaryIs> |
||||
</gml:Polygon> |
||||
</feature:the_geom> |
||||
<feature:nama_area>feature1_bmd</feature:nama_area> |
||||
<feature:status_area>digunakan</feature:status_area> |
||||
<feature:penggunaan>mall</feature:penggunaan> |
||||
</feature:test_bmd_1> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult handle="Added 1 feature to '' via MapLoom."> |
||||
<ogc:FeatureId fid="test_bmd_1.1"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
Edit Geometry |
||||
-------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Modified 1 feature in '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Update handle="Modified 1 feature in '' via MapLoom." typeName="bmd_denpasar:test_bmd_1" xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<wfs:Property> |
||||
<wfs:Name>the_geom</wfs:Name> |
||||
<wfs:Value> |
||||
<gml:Polygon srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:outerBoundaryIs> |
||||
<gml:LinearRing> |
||||
<gml:coordinates cs="," decimal="." ts=" ">11912443.71484449,-695572.7177419447 11912169.81548497,-696120.5165581756 11912876.858017681,-696470.8527538674 11913150.757377198,-695929.4239817676 11912443.71484449,-695572.7177419447</gml:coordinates> |
||||
</gml:LinearRing> |
||||
</gml:outerBoundaryIs> |
||||
</gml:Polygon> |
||||
</wfs:Value> |
||||
</wfs:Property> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test_bmd_1.1"/> |
||||
</ogc:Filter> |
||||
</wfs:Update> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult> |
||||
<ogc:FeatureId fid="none"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Modified 1 feature in '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Edit Attributes / Edit Feature |
||||
------------------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Modified 1 feature in '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Update handle="Modified 1 feature in '' via MapLoom." typeName="bmd_denpasar:test_bmd_1" xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<wfs:Property> |
||||
<wfs:Name>nama_area</wfs:Name> |
||||
<wfs:Value>feature1_bmd_edit</wfs:Value> |
||||
</wfs:Property> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test_bmd_1.1"/> |
||||
</ogc:Filter> |
||||
</wfs:Update> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult> |
||||
<ogc:FeatureId fid="none"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Modified 1 feature in '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Show Table |
||||
------------------ |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:GetFeature maxFeatures="25" outputFormat="JSON" service="WFS" startIndex="0" version="1.1.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"> |
||||
<wfs:Query srsName="EPSG:4326" typeName="bmd_denpasar:test_bmd_1"/> |
||||
</wfs:GetFeature> |
||||
Response: |
||||
{ |
||||
"crs": { |
||||
"properties": { |
||||
"name": "urn:ogc:def:crs:EPSG::4326" |
||||
}, |
||||
"type": "name" |
||||
}, |
||||
"features": [ |
||||
{ |
||||
"geometry": { |
||||
"coordinates": [ |
||||
[ |
||||
[ |
||||
107.01130260258336, |
||||
-6.236087122949689 |
||||
], |
||||
[ |
||||
107.0088421227737, |
||||
-6.240978942036793 |
||||
], |
||||
[ |
||||
107.01519359391025, |
||||
-6.244107404753763 |
||||
], |
||||
[ |
||||
107.0176540737199, |
||||
-6.2392724990064 |
||||
], |
||||
[ |
||||
107.01130260258336, |
||||
-6.236087122949689 |
||||
] |
||||
] |
||||
], |
||||
"type": "Polygon" |
||||
}, |
||||
"geometry_name": "the_geom", |
||||
"id": "test_bmd_1.1", |
||||
"properties": { |
||||
"nama_area": "feature1_bmd_edit", |
||||
"penggunaan": "mall", |
||||
"status_area": "digunakan" |
||||
}, |
||||
"type": "Feature" |
||||
} |
||||
], |
||||
"totalFeatures": 1, |
||||
"type": "FeatureCollection" |
||||
} |
||||
|
||||
Delete Feature |
||||
------------------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Removed 1 feature from '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Delete handle="Removed 1 feature from '' via MapLoom." typeName="bmd_denpasar:test_bmd_1" xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test_bmd_1.1"/> |
||||
</ogc:Filter> |
||||
</wfs:Delete> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult> |
||||
<ogc:FeatureId fid="none"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Removed 1 feature from '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
====================================================== |
||||
Projection: EPSG:4326 (test_bmd_2_point layer / point) |
||||
====================================================== |
||||
|
||||
Create New Feature: |
||||
-------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Added 1 feature to '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Insert handle="Added 1 feature to '' via MapLoom."> |
||||
<feature:test_bmd_2_point xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<feature:the_geom> |
||||
<gml:Point srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:coordinates cs="," decimal="." ts=" ">12602498.558283165,-869310.3742524114</gml:coordinates> |
||||
</gml:Point> |
||||
</feature:the_geom> |
||||
<feature:nama_point>test_bmd_2_point1</feature:nama_point> |
||||
</feature:test_bmd_2_point> |
||||
</wfs:Insert> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult handle="Added 1 feature to '' via MapLoom."> |
||||
<ogc:FeatureId fid="test_bmd_2_point.1"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Added 1 feature to '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Edit Geometry |
||||
----------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Modified 1 feature in '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Update handle="Modified 1 feature in '' via MapLoom." typeName="bmd_denpasar:test_bmd_2_point" xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<wfs:Property> |
||||
<wfs:Name>the_geom</wfs:Name> |
||||
<wfs:Value> |
||||
<gml:Point srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:coordinates cs="," decimal="." ts=" ">12630296.161275087,-871501.5712076114</gml:coordinates> |
||||
</gml:Point> |
||||
</wfs:Value> |
||||
</wfs:Property> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test_bmd_2_point.1"/> |
||||
</ogc:Filter> |
||||
</wfs:Update> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult> |
||||
<ogc:FeatureId fid="none"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Modified 1 feature in '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Edit Feature / Attributes |
||||
------------------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Modified 1 feature in '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Update handle="Modified 1 feature in '' via MapLoom." typeName="bmd_denpasar:test_bmd_2_point" xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<wfs:Property> |
||||
<wfs:Name>nama_point</wfs:Name> |
||||
<wfs:Value>test_bmd_2_point1_edit</wfs:Value> |
||||
</wfs:Property> |
||||
<wfs:Property> |
||||
<wfs:Name>the_geom</wfs:Name> |
||||
<wfs:Value> |
||||
<gml:Point srsName="EPSG:3857" xmlns:gml="http://www.opengis.net/gml"> |
||||
<gml:coordinates cs="," decimal="." ts=" ">12630296.161687493,-871501.571241029</gml:coordinates> |
||||
</gml:Point> |
||||
</wfs:Value> |
||||
</wfs:Property> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test_bmd_2_point.1"/> |
||||
</ogc:Filter> |
||||
</wfs:Update> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult> |
||||
<ogc:FeatureId fid="none"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Modified 1 feature in '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
||||
|
||||
|
||||
Show Table |
||||
------------------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:GetFeature maxFeatures="25" outputFormat="JSON" service="WFS" startIndex="0" version="1.1.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"> |
||||
<wfs:Query srsName="EPSG:4326" typeName="bmd_denpasar:test_bmd_2_point"/> |
||||
</wfs:GetFeature> |
||||
Response: |
||||
{ |
||||
"crs": { |
||||
"properties": { |
||||
"name": "urn:ogc:def:crs:EPSG::4326" |
||||
}, |
||||
"type": "name" |
||||
}, |
||||
"features": [ |
||||
{ |
||||
"geometry": { |
||||
"coordinates": [ |
||||
113.45988085000002, |
||||
-7.804583949999995 |
||||
], |
||||
"type": "Point" |
||||
}, |
||||
"geometry_name": "the_geom", |
||||
"id": "test_bmd_2_point.1", |
||||
"properties": { |
||||
"nama_point": "test_bmd_2_point1_edit" |
||||
}, |
||||
"type": "Feature" |
||||
} |
||||
], |
||||
"totalFeatures": 1, |
||||
"type": "FeatureCollection" |
||||
} |
||||
|
||||
|
||||
Map on click (to get features) |
||||
-------------------------------- |
||||
URL: http://192.168.99.110/geoserver/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&FORMAT=image%2Fpng&TRANSPARENT=true&QUERY_LAYERS=bmd_denpasar%3Atest_bmd_2_point&LAYERS=bmd_denpasar%3Atest_bmd_2_point&tiled=true&_dc=1574761400330&INFO_FORMAT=application%2Fjson&FEATURE_COUNT=5&I=177&J=70&WIDTH=256&HEIGHT=256&CRS=EPSG%3A3857&STYLES=&BBOX=12601714.231207296%2C-900122.445086237%2C12640849.989689307%2C-860986.6866042268 |
||||
Method: GET |
||||
|
||||
Query String Parameters: |
||||
SERVICE: WMS |
||||
VERSION: 1.3.0 |
||||
REQUEST: GetFeatureInfo |
||||
FORMAT: image/png |
||||
TRANSPARENT: true |
||||
QUERY_LAYERS: bmd_denpasar:test_bmd_2_point |
||||
LAYERS: bmd_denpasar:test_bmd_2_point |
||||
tiled: true |
||||
_dc: 1574761400330 |
||||
INFO_FORMAT: application/json |
||||
FEATURE_COUNT: 5 |
||||
I: 177 |
||||
J: 70 |
||||
WIDTH: 256 |
||||
HEIGHT: 256 |
||||
CRS: EPSG:3857 |
||||
STYLES: |
||||
BBOX: 12601714.231207296,-900122.445086237,12640849.989689307,-860986.6866042268 |
||||
|
||||
|
||||
Delete Feature |
||||
------------------------------- |
||||
URL: http://192.168.99.110/geoserver/wfs/WfsDispatcher |
||||
Method: POST |
||||
Request Payload: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:Transaction handle="Removed 1 feature from '' via MapLoom." service="WFS" version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd"> |
||||
<wfs:Delete handle="Removed 1 feature from '' via MapLoom." typeName="bmd_denpasar:test_bmd_2_point" xmlns:feature="http://siopas.co.id/bmd-denpasar"> |
||||
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> |
||||
<ogc:FeatureId fid="test_bmd_2_point.1"/> |
||||
</ogc:Filter> |
||||
</wfs:Delete> |
||||
</wfs:Transaction> |
||||
Response: |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://192.168.99.110:80/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd"> |
||||
<wfs:InsertResult> |
||||
<ogc:FeatureId fid="none"/> |
||||
</wfs:InsertResult> |
||||
<wfs:TransactionResult handle="Removed 1 feature from '' via MapLoom."> |
||||
<wfs:Status> |
||||
<wfs:SUCCESS/> |
||||
</wfs:Status> |
||||
</wfs:TransactionResult> |
||||
</wfs:WFS_TransactionResponse> |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 297 KiB |
After Width: | Height: | Size: 2.4 MiB |
After Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 346 KiB |
After Width: | Height: | Size: 515 KiB |
After Width: | Height: | Size: 188 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 3.6 MiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 288 KiB |
After Width: | Height: | Size: 216 KiB |
After Width: | Height: | Size: 305 KiB |
After Width: | Height: | Size: 234 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 173 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,9 @@
|
||||
.add-input-container { |
||||
max-height: 300px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.row-input { |
||||
margin-right: 0px !important; |
||||
margin-left: -10px !important; |
||||
} |
@ -0,0 +1,141 @@
|
||||
import React, { Component } from 'react'; |
||||
import { Modal, ModalHeader, ModalBody, ModalFooter, Button, |
||||
UncontrolledTooltip, UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem, |
||||
Form, FormGroup, Label, Input, Row, Col } from 'reactstrap'; |
||||
import { Icon } from '@iconify/react'; |
||||
import removeCircle from '@iconify/icons-ion/remove-circle'; |
||||
import './AddFeature.css'; |
||||
import '../../assets/css/customscroll.css'; |
||||
import { findWhere } from 'underscore'; |
||||
import { createNewFeature } from '../../const/GeoserverFunc.js'; |
||||
|
||||
class AddFeature extends Component { |
||||
|
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
// dataArr: null,
|
||||
objToSave: null, |
||||
isReady: false |
||||
} |
||||
} |
||||
|
||||
componentDidMount() { |
||||
const { columns, addFeatureValue } = this.props; |
||||
console.log('columns', columns); |
||||
let dataArr = []; |
||||
if (columns !== undefined) { |
||||
if (columns !== null) { |
||||
if (columns.length > 0) { |
||||
for (let i=0; i < columns.length; i++) { |
||||
// console.log('column_name', columns[i].column_name);
|
||||
// let column_name = columns[i].column_name;
|
||||
dataArr.push({ |
||||
idx: i, |
||||
label: columns[i].column_name, |
||||
value: '' |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
console.log('dataArr', dataArr); |
||||
|
||||
addFeatureValue.layer_attributes = dataArr; |
||||
|
||||
console.log('addFeatureValue', addFeatureValue); |
||||
|
||||
this.setState({ objToSave: addFeatureValue, isReady: true}); |
||||
// this.setState({
|
||||
// objToSave: this.props.addFeatureValue,
|
||||
// dataArr: dataArr
|
||||
// )};
|
||||
|
||||
} |
||||
|
||||
renderInputs = () => { |
||||
const { objToSave } = this.state; |
||||
return objToSave.layer_attributes.map((item, index) => { |
||||
return ( |
||||
<Row key={item.idx} className="row-input"> |
||||
<Col xl={12} xs={12}> |
||||
<FormGroup> |
||||
<Label>{item.label}</Label> |
||||
<Input key={item.idx} type="text" name={item.label} placeholder="" value={item.value ? item.value : ''} onChange={this.handleChangeInputValue.bind(this, item.idx)} /> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
) |
||||
}); |
||||
} |
||||
|
||||
handleChangeInputValue = (idx, event) => { |
||||
event.preventDefault();
|
||||
let value = event.target.value; |
||||
let { objToSave } = this.state; |
||||
let changedItem = findWhere(objToSave.layer_attributes, {idx: idx}); |
||||
changedItem.value = value; |
||||
this.setState({objToSave: objToSave}, () => { |
||||
// console.log('objToSave now', this.state.objToSave);
|
||||
}); |
||||
} |
||||
|
||||
saveFeature = async (e) => { |
||||
// let { addFeatureValue } = this.props;
|
||||
e.preventDefault(); |
||||
let { objToSave } = this.state; |
||||
console.log('objToSave', objToSave); |
||||
let response = await createNewFeature(objToSave); |
||||
console.log('saveFeature response', response); |
||||
|
||||
if (response.success) { |
||||
alert(response.result); |
||||
this.props.toggleAddFeatureVisible(); |
||||
this.props.closeDrawing(); |
||||
this.props.finishDrawingAdd(); |
||||
// window.location.reload();
|
||||
} |
||||
else { |
||||
alert(response.result); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
render() { |
||||
const { objToSave, isReady } = this.state; |
||||
return( |
||||
<div> |
||||
<Modal isOpen={this.props.addFeatureVisible} toggle={this.props.toggleAddFeatureVisible}> |
||||
<ModalHeader toggle={this.props.toggleAddFeatureVisible}>{this.props.addFeatureTitle ? this.props.addFeatureTitle : 'Add Feature' }</ModalHeader> |
||||
<ModalBody> |
||||
{ isReady ?
|
||||
<div className="add-input-container custom-scroll"> |
||||
<Form onSubmit={(e) => this.saveFeature(e)}> |
||||
{ this.renderInputs() } |
||||
</Form> |
||||
</div> |
||||
: "Loading..." |
||||
} |
||||
|
||||
{/*{objToSave.layer_attributes !== undefined ? |
||||
objToSave.layer_attributes !== null ? |
||||
<div className="add-input-container custom-scroll"> |
||||
<Form> |
||||
{ this.renderInputs() } |
||||
</Form> |
||||
</div> |
||||
: 'Data is null' |
||||
: 'Data is undefined' |
||||
}*/} |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color="success" onClick={(e) => this.saveFeature(e)}>Save</Button> |
||||
<Button color="secondary" onClick={this.props.toggleAddFeatureVisible}>Cancel</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default AddFeature; |
@ -0,0 +1,6 @@
|
||||
{ |
||||
"name": "AddFeature", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./AddFeature.js" |
||||
} |
@ -0,0 +1,101 @@
|
||||
.adm-tree { |
||||
font-size: 12px; |
||||
} |
||||
|
||||
.adm-tree-checkbox-container { |
||||
margin-left: 10px; |
||||
margin-bottom: 5px; |
||||
margin-top: 5px; |
||||
} |
||||
|
||||
#adm-tree-container { |
||||
font-size: 12px; |
||||
/*height: 220px;*/ |
||||
height: 440px; |
||||
overflow: auto; |
||||
padding: 0px !important; |
||||
} |
||||
|
||||
.checkbox-opt { |
||||
font-size: 11px; |
||||
padding: 0px !important; |
||||
} |
||||
|
||||
.ant-tree-child-tree > li:first-child { |
||||
padding-top: 0px !important; |
||||
} |
||||
|
||||
.ant-tree li { |
||||
margin: 0; |
||||
padding: 0px 0 !important; |
||||
white-space: nowrap; |
||||
list-style: none; |
||||
outline: 0; |
||||
} |
||||
|
||||
.adm-tree-checkbox-opt-container { |
||||
padding-left: 0px !important |
||||
} |
||||
|
||||
.adm-dropdown-container { |
||||
z-index: 50; |
||||
position: absolute; |
||||
max-height: 350px; |
||||
border-radius: 5px; |
||||
background-color: rgba(0,0,0,0.5); |
||||
/*background-color: #ebebeb;*/ |
||||
color: #ffffff; |
||||
/*color: #000000;*/ |
||||
} |
||||
|
||||
.adm-dropdown-title { |
||||
font-size: 14px; |
||||
margin-top: 0px; |
||||
margin-left: 10px; |
||||
margin-bottom: 5px; |
||||
font-weight: bold; |
||||
width: 200px; |
||||
} |
||||
|
||||
.adm-dropdown-close { |
||||
float: right; |
||||
font-size: 18px; |
||||
font-weight: bold; |
||||
margin-left: 0px; |
||||
margin-right: 10px; |
||||
margin-top: -5px; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.adm-dropdown-body { |
||||
max-height: 200px; |
||||
overflow: auto; |
||||
margin: 5px; |
||||
text-align: left; |
||||
} |
||||
|
||||
.adm-dropdown-list { |
||||
cursor: pointer; |
||||
font-size: 14px; |
||||
padding: 5px; |
||||
margin-left: 0px; |
||||
text-align: left; |
||||
} |
||||
|
||||
.adm-dropdown-icon { |
||||
margin-right: 5px; |
||||
} |
||||
|
||||
.adm-dropdown-list:hover { |
||||
background-color: rgba(0,0,0,0.25); |
||||
} |
||||
|
||||
.filter-coverage-container { |
||||
margin-left: 25px; |
||||
margin-top: 5px; |
||||
margin-bottom: 5px; |
||||
margin-right: 25px; |
||||
color: blue; |
||||
cursor: pointer; |
||||
/*float: right;*/ |
||||
} |
@ -0,0 +1,734 @@
|
||||
import React, { Component, Fragment } from 'react'; |
||||
import { Form, FormGroup, Label, Input, Row, Col, ListGroup, ListGroupItem } from 'reactstrap'; |
||||
// Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||
import { Tree, Input as SearchInput, Menu, Dropdown } from 'antd'; |
||||
import { API_KOMINFO_GET_PROV, API_KOMINFO_GET_KABKOT, API_KOMINFO_GET_KEC, API_KOMINFO_GET_DESA } from '../../const/ApiConst.js'; |
||||
import Loader from 'react-loader-spinner' |
||||
import "react-loader-spinner/dist/loader/css/react-spinner-loader.css" |
||||
import './AdmTree.css' |
||||
import '../../assets/css/customscroll.css' |
||||
import { findWhere } from 'underscore'; |
||||
import { opt2G, opt3G, opt4G, netQuality2G, netQuality3G, netQuality4G, bts, mukim } from '../../const/Kominfo.js'; |
||||
import { ToastContainer, toast } from 'react-toastify'; |
||||
import 'react-toastify/dist/ReactToastify.css'; |
||||
// npm install --save-dev @iconify/react @iconify/icons-mdi
|
||||
import { Icon, InlineIcon } from '@iconify/react'; |
||||
import mapMarker from '@iconify/icons-mdi/map-marker'; |
||||
|
||||
const { TreeNode } = Tree; |
||||
const { Search } = SearchInput; |
||||
|
||||
const menu = ( |
||||
<Menu> |
||||
<Menu.Item key="1">1st menu item</Menu.Item> |
||||
<Menu.Item key="2">2nd menu item</Menu.Item> |
||||
<Menu.Item key="3">3rd menu item</Menu.Item> |
||||
</Menu> |
||||
); |
||||
|
||||
|
||||
|
||||
class AdmTree extends Component { |
||||
|
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
treeData: [], |
||||
checkedKeys: [], |
||||
isReady: false, |
||||
admDropdownOpen: false, |
||||
admDropdownVisible: false, |
||||
allCheckNodes: [], |
||||
rightClickNodeTreeItem: { |
||||
pageX: "", |
||||
pageY: "", |
||||
id: "", |
||||
dropdownTitle: "" |
||||
}, |
||||
searchAdmValue: "" |
||||
} |
||||
} |
||||
|
||||
componentDidMount() { |
||||
this.getProv(); |
||||
} |
||||
|
||||
getProv = async () => { |
||||
const param = { |
||||
method: 'GET', |
||||
header: JSON.stringify({'Content-Type': 'application/json'}), |
||||
} |
||||
|
||||
try { |
||||
const result = await fetch(API_KOMINFO_GET_PROV, param).then(response => response.json()).then(res => res) |
||||
// console.log(result);
|
||||
if (result.data){ |
||||
let treeData = []; |
||||
let checkedKeys = []; |
||||
let allProv = []; |
||||
let checkNodes = []; |
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i].PROV, |
||||
key: i, |
||||
group: 'prov' |
||||
}); |
||||
checkedKeys.push(i); |
||||
allProv.push(i); |
||||
let checkNode_ = { |
||||
props: { |
||||
dataRef: { |
||||
title: result.data[i].PROV, |
||||
key: i, |
||||
group: 'prov' |
||||
} |
||||
} |
||||
} |
||||
checkNodes.push(checkNode_); |
||||
} |
||||
this.setState({ |
||||
// treeData: treeData,
|
||||
// checkedKeys: checkedKeys,
|
||||
allProv: allProv, |
||||
allCheckNodes: checkNodes, |
||||
isReady: true}); |
||||
// console.log('checkNodes', checkNodes);
|
||||
this.props.initAdmTree(treeData, checkNodes); |
||||
this.props.setCheckKeysAdm(checkedKeys); |
||||
this.props.setAllProv(allProv, true); |
||||
this.props.setToggleCheckAllValue(true); |
||||
|
||||
} else { |
||||
|
||||
} |
||||
} catch(err) { |
||||
console.log(err); |
||||
// alert(err.message.toString());
|
||||
toast.warn(err.message.toString()); |
||||
} |
||||
} |
||||
|
||||
getChild = async (title, group, prov, kabkot, kec, childKey) => { |
||||
|
||||
let URL = ''; |
||||
let childGroup = ''; |
||||
let childTitle = ''; |
||||
let bodyParam = {}; |
||||
|
||||
if (group == 'prov') { // buat nyari kabkot
|
||||
URL = API_KOMINFO_GET_KABKOT; |
||||
childGroup = 'kabkot'; |
||||
childTitle = 'KAB_KOT'; |
||||
bodyParam = { |
||||
[group]: title |
||||
}; |
||||
} |
||||
else if (group == 'kabkot') { // buat nyari kecamatan
|
||||
URL = API_KOMINFO_GET_KEC; |
||||
childGroup = 'kec'; |
||||
childTitle = 'KEC'; |
||||
bodyParam = { |
||||
[group]: title, |
||||
prov: prov |
||||
}; |
||||
} |
||||
else if (group == 'kec') { // buat nyari desa
|
||||
URL = API_KOMINFO_GET_DESA; |
||||
childGroup = 'desa'; |
||||
childTitle = 'KEL_DES'; |
||||
bodyParam = { |
||||
[group]: title, |
||||
prov: prov, |
||||
kabkot, kabkot |
||||
}; |
||||
} |
||||
|
||||
const param = { |
||||
method: 'POST', |
||||
header: JSON.stringify({'Content-Type': 'application/json'}), |
||||
body: JSON.stringify(bodyParam) |
||||
} |
||||
|
||||
try { |
||||
console.log(URL); |
||||
|
||||
const result = await fetch(URL, param).then(response => response.json()).then(res => res) |
||||
console.log(result); |
||||
if (result.data){ |
||||
let treeData = []; |
||||
if (group == 'prov') { // buat nyari kabkot
|
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i][childTitle], |
||||
key: childKey+'-'+i, |
||||
group: childGroup, |
||||
prov: result.data[i].PROV, |
||||
kabkot: result.data[i].KAB_KOT |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kabkot') { // buat nyari kecamatan
|
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i][childTitle], |
||||
key: childKey+'-'+i, |
||||
group: childGroup, |
||||
prov: result.data[i].PROV, |
||||
kabkot: result.data[i].KAB_KOT, |
||||
kec: result.data[i].KEC |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kec') { // buat nyari desa
|
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i][childTitle], |
||||
key: childKey+'-'+i, |
||||
group: childGroup, |
||||
prov: result.data[i].PROV, |
||||
kabkot: result.data[i].KAB_KOT, |
||||
kec: result.data[i].KEC, |
||||
desa: result.data[i].KEL_DES |
||||
}); |
||||
} |
||||
} |
||||
|
||||
|
||||
// this.setState({treeData: treeData, isReady: true});
|
||||
// console.log('getChild func', treeData);
|
||||
return treeData; |
||||
} else { |
||||
|
||||
} |
||||
} catch(err) { |
||||
console.log(err); |
||||
// alert(err.message.toString());
|
||||
toast.warn(err.message.toString()); |
||||
} |
||||
} |
||||
|
||||
/*onLoadData = treeNode => |
||||
new Promise(resolve => {
|
||||
if (treeNode.props.children) { |
||||
resolve(); |
||||
return; |
||||
} |
||||
setTimeout(() => { |
||||
console.log('treeNode', treeNode); |
||||
let title = treeNode.props.dataRef.title; |
||||
let group = treeNode.props.dataRef.group; |
||||
let childKey = treeNode.props.eventKey; |
||||
let getChild = this.getChild(title, group, childKey); |
||||
console.log('getChild',getChild); |
||||
|
||||
treeNode.props.dataRef.children = [ |
||||
{ title: 'Child Node', key: `${treeNode.props.eventKey}-0` }, |
||||
{ title: 'Child Node', key: `${treeNode.props.eventKey}-1` }, |
||||
]; |
||||
this.setState({ |
||||
treeData: [...this.state.treeData], |
||||
}); |
||||
resolve(); |
||||
}, 1000); |
||||
});*/ |
||||
|
||||
onLoadData = async (treeNode) => { |
||||
console.log('onLoadData treeNode',treeNode); |
||||
if (treeNode.props.children) { |
||||
return; |
||||
} |
||||
let title = treeNode.props.dataRef.title; |
||||
let group = treeNode.props.dataRef.group; |
||||
let childKey = treeNode.props.eventKey; |
||||
let getChild = null; |
||||
|
||||
// let getChild = await this.getChild(title, group, prov, kabkot, kec, childKey);
|
||||
if (group == 'prov') { |
||||
getChild = await this.getChild(title, group, group, null, null, childKey); |
||||
} |
||||
else if (group == 'kabkot') { |
||||
let prov = treeNode.props.dataRef.prov; |
||||
getChild = await this.getChild(title, group, prov, group, null, childKey); |
||||
} |
||||
else if (group == 'kec') { |
||||
let prov = treeNode.props.dataRef.prov; |
||||
let kabkot = treeNode.props.dataRef.kabkot; |
||||
getChild = await this.getChild(title, group, prov, kabkot, group, childKey); |
||||
} |
||||
|
||||
// let getChild = await this.getChild(title, group, childKey);
|
||||
console.log('getChild',getChild); |
||||
|
||||
if (getChild.length > 0) { |
||||
let treeDataChild = []; |
||||
let treeDataChildKeys = []; |
||||
|
||||
if (group == 'prov') { // buat nyari kabkot
|
||||
this.props.setExpandedTree('prov'); |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChild.push({ |
||||
title: getChild[i].title, |
||||
key: getChild[i].key, |
||||
group: getChild[i].group, |
||||
prov: getChild[i].prov, |
||||
kabkot: getChild[i].kabkot |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kabkot') { // buat nyari kec
|
||||
this.props.setExpandedTree('kab'); |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChild.push({ |
||||
title: getChild[i].title, |
||||
key: getChild[i].key, |
||||
group: getChild[i].group, |
||||
prov: getChild[i].prov, |
||||
kabkot: getChild[i].kabkot, |
||||
kec: getChild[i].kec |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kec') { // buat nyari desa / kel_des
|
||||
this.props.setExpandedTree('kec'); |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChild.push({ |
||||
title: getChild[i].title, |
||||
key: getChild[i].key, |
||||
group: getChild[i].group, |
||||
prov: getChild[i].prov, |
||||
kabkot: getChild[i].kabkot, |
||||
kec: getChild[i].kec, |
||||
desa: getChild[i].desa, |
||||
isLeaf: true |
||||
}); |
||||
} |
||||
} |
||||
|
||||
if (treeNode.props.checked) { |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChildKeys.push(getChild[i].key); |
||||
} |
||||
this.props.setAdmTreeData(treeNode, treeDataChild); |
||||
this.props.appendCheckedKeysAdm(treeDataChildKeys, treeNode.props.children) |
||||
} |
||||
else { |
||||
this.props.setAdmTreeData(treeNode, treeDataChild); |
||||
this.props.appendCheckedKeysAdm(treeDataChildKeys, []) |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
onInitData = (loadedKeys, e) => { |
||||
console.log('onInitData', e); |
||||
} |
||||
|
||||
onCheckAdmTree = (checkedKeys, e) => { |
||||
console.log('onCheckAdmTree', checkedKeys); |
||||
console.log('onCheckAdmTree checkedNodes', e.checkedNodes); |
||||
this.props.setCheckKeysAdm(checkedKeys); |
||||
this.props.setCheckNodesAdm(e.checkedNodes); |
||||
|
||||
// this.setState({ checkedKeysAdm, checkedNodesAdm: e.checkedNodes }, () => {
|
||||
// let getCheckedValue = this.getCheckedValue();
|
||||
// console.log('getCheckedValue', getCheckedValue);
|
||||
// });
|
||||
}; |
||||
|
||||
onCheckAllAdmTree = () => { |
||||
|
||||
/*const { checkedKeys, allProv } = this.state; |
||||
const totalProv = 34; |
||||
|
||||
if (checkedKeys.length > 0) { |
||||
this.setState({checkedKeys: [], toggleCheckAllValue: false}) |
||||
} |
||||
else if (checkedKeys.length == 0) { |
||||
this.setState({checkedKeys: allProv, toggleCheckAllValue: true}) |
||||
}*/ |
||||
const { checkedKeysAdm, checkedKeysAdmTemp, toggleCheckAllValue, allProv } = this.props; |
||||
const { allCheckNodes } = this.state; |
||||
this.props.setToggleCheckAllValue(!toggleCheckAllValue); |
||||
} |
||||
|
||||
onCheckOpt = (checkedKeys, e) => { |
||||
const { mode } = this.props; |
||||
this.props.setCheckKeysOpt(mode, checkedKeys); |
||||
} |
||||
|
||||
onCheckQty = (checkedKeys) => { |
||||
const { mode } = this.props; |
||||
this.props.setCheckKeysQty(mode, checkedKeys); |
||||
} |
||||
|
||||
onCheckBts = (checkedKeys) => { |
||||
this.props.setCheckKeysBts(checkedKeys); |
||||
} |
||||
|
||||
/*onRightClickAdmTree = (callback) => { |
||||
console.log('onRightClickAdmTree', callback); |
||||
this.admDropdownToggle(); |
||||
}*/ |
||||
|
||||
// tree right-click events on the list
|
||||
onRightClickAdmTree = e => { |
||||
e.event.persist() |
||||
console.log('onRightClickAdmTree', e); |
||||
this.setState({ |
||||
rightClickNodeTreeItem: { |
||||
pageX: e.event.pageX, |
||||
pageY: e.event.pageY, |
||||
id: e.node.props.dataRef.key, |
||||
dropdownTitle: e.node.props.dataRef.title |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
closeAdmDropdown = () => { |
||||
this.setState({ |
||||
rightClickNodeTreeItem: { |
||||
pageX: "", |
||||
pageY: "", |
||||
id: "", |
||||
dropdownTitle: "" |
||||
} |
||||
}) |
||||
} |
||||
|
||||
getNodeTreeRightClickMenu = () => { |
||||
const { pageX, pageY, id, dropdownTitle } = { ...this.state.rightClickNodeTreeItem }; |
||||
// const tmpStyle = {
|
||||
// position: "absolute",
|
||||
// left: `${pageX - 220}px`,
|
||||
// top: `${pageY - 102}px`
|
||||
// };
|
||||
const tmpStyle = { |
||||
position:"absolute", |
||||
left: `${pageX - 50}px`, |
||||
top: `${pageY - 80}px`, |
||||
zIndex:10000, |
||||
width:"200px", |
||||
background:"#ededed", |
||||
borderRadius:"5px" |
||||
} |
||||
const menu = ( |
||||
<div style={tmpStyle}> |
||||
<div className="adm-dropdown-container"> |
||||
<span className="adm-dropdown-close" onClick={this.closeAdmDropdown}>x</span> |
||||
<div className="adm-dropdown-title">{ dropdownTitle }</div> |
||||
<div className="adm-dropdown-body custom-scroll"> |
||||
<div className="adm-dropdown-list" onClick={this.goToLocation()}><Icon icon={mapMarker} className="adm-dropdown-icon" />Go to map</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
); |
||||
return this.state.rightClickNodeTreeItem.dropdownTitle == "" ? "" : menu; |
||||
}; |
||||
|
||||
getCheckedValue = () => { |
||||
const { treeData, checkedKeys } = this.state; |
||||
let checkedData = []; |
||||
|
||||
for(let i=0; i < checkedKeys.length; i++) { |
||||
let item = findWhere(treeData, {key: parseInt(checkedKeys[i])}); |
||||
checkedData.push(item); |
||||
} |
||||
return checkedData; |
||||
} |
||||
|
||||
renderCheckboxOpt = () => { |
||||
let checkboxes = []; |
||||
const { mode, checkedKeys2GOpt, checkedKeys3GOpt, checkedKeys4GOpt} = this.props; |
||||
|
||||
if (mode == '2G') { |
||||
// checkboxes = opt2G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys2GOpt} |
||||
onCheck={(checkedKeys2GOpt, e) => this.onCheckOpt(checkedKeys2GOpt, e)} |
||||
> |
||||
{this.renderTreeNodes(opt2G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else if (mode == '3G') { |
||||
// checkboxes = opt3G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys3GOpt} |
||||
onCheck={(checkedKeys3GOpt) => this.onCheckOpt(checkedKeys3GOpt)} |
||||
> |
||||
{this.renderTreeNodes(opt3G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else { |
||||
// checkboxes = opt4G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys4GOpt} |
||||
onCheck={(checkedKeys4GOpt) => this.onCheckOpt(checkedKeys4GOpt)} |
||||
> |
||||
{this.renderTreeNodes(opt4G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
} |
||||
|
||||
onExpand = expandedKeys => { |
||||
// console.log('onExpand', expandedKeys);
|
||||
const {closeChart} = this.props |
||||
console.log("length", expandedKeys.length) |
||||
console.log("closeChart", closeChart) |
||||
if(expandedKeys.length === 1){ |
||||
if(closeChart) { |
||||
document.getElementById('adm-tree-container').style.height = '320px' |
||||
} else { |
||||
document.getElementById('adm-tree-container').style.height = '120px' |
||||
} |
||||
} else { |
||||
if(closeChart) { |
||||
document.getElementById('adm-tree-container').style.height = '440px' |
||||
} else { |
||||
document.getElementById('adm-tree-container').style.height = '220px' |
||||
} |
||||
} |
||||
}; |
||||
|
||||
renderCheckboxQuality = () => { |
||||
let checkboxes = []; |
||||
const { mode, checkedKeys2GQty, checkedKeys3GQty, checkedKeys4GQty } = this.props; |
||||
|
||||
if (mode == '2G') { |
||||
// checkboxes = netQuality2G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys2GQty} |
||||
onCheck={(checkedKeys2GQty) => this.onCheckQty(checkedKeys2GQty)} |
||||
> |
||||
{this.renderTreeNodes(netQuality2G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else if (mode == '3G') { |
||||
// checkboxes = netQuality3G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys3GQty} |
||||
onCheck={(checkedKeys3GQty) => this.onCheckQty(checkedKeys3GQty)} |
||||
> |
||||
{this.renderTreeNodes(netQuality3G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else { |
||||
// checkboxes = netQuality4G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys4GQty} |
||||
onCheck={(checkedKeys4GQty) => this.onCheckQty(checkedKeys4GQty)} |
||||
> |
||||
{this.renderTreeNodes(netQuality4G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
} |
||||
|
||||
renderCheckboxBts = () => { |
||||
const { checkedKeysBts } = this.props; |
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeysBts} |
||||
onCheck={(checkedKeysBts) => this.onCheckBts(checkedKeysBts)} |
||||
> |
||||
{this.renderTreeNodes(bts)} |
||||
</Tree> |
||||
) |
||||
} |
||||
|
||||
|
||||
/*renderTreeNodes = data => |
||||
data.map(item => { |
||||
if (item.children) { |
||||
return ( |
||||
<TreeNode title={item.title} key={item.key} dataRef={item}> |
||||
{this.renderTreeNodes(item.children)} |
||||
</TreeNode> |
||||
); |
||||
} |
||||
return <TreeNode key={item.key} {...item} dataRef={item} />; |
||||
})*/ |
||||
|
||||
renderTreeNodes = data => |
||||
data.map(item => { |
||||
if (item.children) { |
||||
return ( |
||||
|
||||
<TreeNode title={item.title} key={item.key} dataRef={item}> |
||||
{this.renderTreeNodes(item.children)} |
||||
</TreeNode> |
||||
|
||||
); |
||||
} |
||||
return ( |
||||
|
||||
<TreeNode key={item.key} {...item} dataRef={item} /> |
||||
|
||||
); |
||||
}) |
||||
|
||||
admDropdownToggle = () => { |
||||
// this.setState({admDropdownOpen: !this.state.admDropdownOpen})
|
||||
this.setState({admDropdownVisible: !this.state.admDropdownVisible}); |
||||
} |
||||
|
||||
admMenu = () => { |
||||
const menu = ( |
||||
<Menu> |
||||
<Menu.Item key="1">1st menu item</Menu.Item> |
||||
<Menu.Item key="2">2nd menu item</Menu.Item> |
||||
<Menu.Item key="3">3rd menu item</Menu.Item> |
||||
</Menu> |
||||
); |
||||
|
||||
return menu; |
||||
} |
||||
|
||||
goToLocation = () => { |
||||
|
||||
} |
||||
|
||||
onChangeSearchAdm = (e) => { |
||||
const { value } = e.target; |
||||
this.setState({searchAdmValue: value}, () => console.log('searchAdmValue:', this.state.searchAdmValue)); |
||||
} |
||||
|
||||
renderCheckboxMukim = () => { |
||||
const { checkedKeysMukim } = this.props; |
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeysMukim} |
||||
onCheck={(checkedKeysMukim) => this.onCheckMukim(checkedKeysMukim)} |
||||
> |
||||
{this.renderTreeNodes(mukim)} |
||||
</Tree> |
||||
) |
||||
} |
||||
|
||||
onCheckMukim = (checkedKeys) => { |
||||
this.props.setCheckKeysMukim(checkedKeys); |
||||
} |
||||
|
||||
renderFilterCoverage = () => { |
||||
return <div className="filter-coverage-container" onClick={() => this.filterCoverage()}>Filter Coverage</div> |
||||
} |
||||
|
||||
filterCoverage = () => { |
||||
this.props.toggleModalOptions(); |
||||
} |
||||
|
||||
render() { |
||||
const { isReady, checkedKeys, admDropdownOpen, admDropdownVisible, searchAdmValue } = this.state; |
||||
const { admTreeData, checkedKeysAdm, toggleCheckAllValue } = this.props; |
||||
if (!isReady) { |
||||
return (<div className="loader-container"> |
||||
<Loader |
||||
type="TailSpin" |
||||
color="#36D7B7" |
||||
height={100} |
||||
width={100} |
||||
/> |
||||
</div>) |
||||
} |
||||
|
||||
return ( |
||||
<Fragment> |
||||
|
||||
{/*This is future kominfo feature*/} |
||||
<Row> |
||||
<Col xs="12" sm="12" md="6" lg="6"> |
||||
{ this.renderCheckboxMukim() } |
||||
</Col> |
||||
<Col xs="12" sm="12" md="6" lg="6" className="not-left-col"> |
||||
{ this.renderCheckboxBts() } |
||||
</Col> |
||||
</Row> |
||||
{/*end This is future kominfo feature*/} |
||||
|
||||
<Row> |
||||
<Col xs="12" sm="12" md="6" lg="6"> |
||||
{ this.renderCheckboxOpt() } |
||||
</Col> |
||||
<Col xs="12" sm="12" md="6" lg="6" className="not-left-col"> |
||||
{ this.renderCheckboxQuality() } |
||||
</Col> |
||||
</Row> |
||||
|
||||
{/*<div className="adm-tree-checkbox-quality-container"> |
||||
{ this.renderCheckboxQuality() } |
||||
</div>*/} |
||||
{/*<Row> |
||||
<Col xs="12" sm="12" md="12" lg="12"> |
||||
{ this.renderCheckboxBts() } |
||||
</Col> |
||||
</Row>*/} |
||||
|
||||
{/*This is future kominfo feature*/} |
||||
<Row> |
||||
<Col xs="12" sm="12" md="12" lg="12"> |
||||
{ this.renderFilterCoverage() } |
||||
</Col> |
||||
</Row> |
||||
{/*end This is future kominfo feature*/} |
||||
<div className="adm-tree-checkbox-container"> |
||||
|
||||
{/*This is future kominfo feature*/} |
||||
<Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChangeSearchAdm} /> |
||||
{/*end This is future kominfo feature*/} |
||||
|
||||
<Form> |
||||
<FormGroup check inline> |
||||
<Label check> |
||||
<Input type="checkbox" checked={toggleCheckAllValue} onClick={() => this.onCheckAllAdmTree()}/> Toggle Select All Wilayah |
||||
</Label> |
||||
</FormGroup> |
||||
</Form> |
||||
</div> |
||||
<div id="adm-tree-container" className="custom-scroll"> |
||||
<Tree |
||||
className="adm-tree"
|
||||
loadData={this.onLoadData} |
||||
checkable={true} |
||||
checkedKeys={checkedKeysAdm} |
||||
onCheck={(checkedKeys, e) => this.onCheckAdmTree(checkedKeys, e)} |
||||
onRightClick={this.onRightClickAdmTree} |
||||
onSelect={this.closeAdmDropdown} |
||||
> |
||||
{/*<Dropdown overlay={this.admMenu} trigger={['contextMenu']} visible={admDropdownVisible} onVisibleChange={() => this.admDropdownToggle()}>*/} |
||||
{this.renderTreeNodes(admTreeData)} |
||||
{/*</Dropdown>*/} |
||||
</Tree> |
||||
{this.getNodeTreeRightClickMenu()} |
||||
</div> |
||||
</Fragment> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default AdmTree; |
@ -0,0 +1,544 @@
|
||||
import React, { Component, Fragment } from 'react'; |
||||
import { Form, FormGroup, Label, Input, Row, Col } from 'reactstrap';
|
||||
import { Tree, Input as SearchInput } from 'antd'; |
||||
import { API_KOMINFO_GET_PROV, API_KOMINFO_GET_KABKOT, API_KOMINFO_GET_KEC, API_KOMINFO_GET_DESA } from '../../const/ApiConst.js'; |
||||
import Loader from 'react-loader-spinner' |
||||
import "react-loader-spinner/dist/loader/css/react-spinner-loader.css" |
||||
import './AdmTree.css' |
||||
import '../../assets/css/customscroll.css' |
||||
import { findWhere } from 'underscore'; |
||||
import { opt2G, opt3G, opt4G, netQuality2G, netQuality3G, netQuality4G } from '../../const/Kominfo.js'; |
||||
import { ToastContainer, toast } from 'react-toastify'; |
||||
import 'react-toastify/dist/ReactToastify.css'; |
||||
|
||||
const { TreeNode } = Tree; |
||||
const { Search } = SearchInput; |
||||
|
||||
|
||||
|
||||
class AdmTree extends Component { |
||||
|
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
treeData: [], |
||||
checkedKeys: [], |
||||
isReady: false |
||||
} |
||||
} |
||||
|
||||
componentDidMount() { |
||||
this.getProv(); |
||||
} |
||||
|
||||
getProv = async () => { |
||||
const param = { |
||||
method: 'GET', |
||||
header: JSON.stringify({'Content-Type': 'application/json'}), |
||||
} |
||||
|
||||
try { |
||||
const result = await fetch(API_KOMINFO_GET_PROV, param).then(response => response.json()).then(res => res) |
||||
// console.log(result);
|
||||
if (result.data){ |
||||
let treeData = []; |
||||
let checkedKeys = []; |
||||
let allProv = []; |
||||
let checkNodes = []; |
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i].PROV, |
||||
key: i, |
||||
group: 'prov' |
||||
}); |
||||
checkedKeys.push(i); |
||||
allProv.push(i); |
||||
let checkNode_ = { |
||||
props: { |
||||
dataRef: { |
||||
title: result.data[i].PROV, |
||||
key: i, |
||||
group: 'prov' |
||||
} |
||||
} |
||||
} |
||||
checkNodes.push(checkNode_); |
||||
} |
||||
this.setState({ |
||||
// treeData: treeData,
|
||||
// checkedKeys: checkedKeys,
|
||||
allProv: allProv, |
||||
isReady: true}); |
||||
// console.log('checkNodes', checkNodes);
|
||||
this.props.initAdmTree(treeData, checkNodes); |
||||
this.props.setCheckKeysAdm(checkedKeys); |
||||
this.props.setAllProv(allProv, true); |
||||
this.props.setToggleCheckAllValue(true); |
||||
|
||||
} else { |
||||
|
||||
} |
||||
} catch(err) { |
||||
console.log(err); |
||||
// alert(err.message.toString());
|
||||
toast.warn(err.message.toString()); |
||||
} |
||||
} |
||||
|
||||
getChild = async (title, group, prov, kabkot, kec, childKey) => { |
||||
|
||||
let URL = ''; |
||||
let childGroup = ''; |
||||
let childTitle = ''; |
||||
let bodyParam = {}; |
||||
|
||||
if (group == 'prov') { // buat nyari kabkot
|
||||
URL = API_KOMINFO_GET_KABKOT; |
||||
childGroup = 'kabkot'; |
||||
childTitle = 'KAB_KOT'; |
||||
bodyParam = { |
||||
[group]: title |
||||
}; |
||||
} |
||||
else if (group == 'kabkot') { // buat nyari kecamatan
|
||||
URL = API_KOMINFO_GET_KEC; |
||||
childGroup = 'kec'; |
||||
childTitle = 'KEC'; |
||||
bodyParam = { |
||||
[group]: title, |
||||
prov: prov |
||||
}; |
||||
} |
||||
else if (group == 'kec') { // buat nyari desa
|
||||
URL = API_KOMINFO_GET_DESA; |
||||
childGroup = 'desa'; |
||||
childTitle = 'KEL_DES'; |
||||
bodyParam = { |
||||
[group]: title, |
||||
prov: prov, |
||||
kabkot, kabkot |
||||
}; |
||||
} |
||||
|
||||
const param = { |
||||
method: 'POST', |
||||
header: JSON.stringify({'Content-Type': 'application/json'}), |
||||
body: JSON.stringify(bodyParam) |
||||
} |
||||
|
||||
try { |
||||
console.log(URL); |
||||
|
||||
const result = await fetch(URL, param).then(response => response.json()).then(res => res) |
||||
console.log(result); |
||||
if (result.data){ |
||||
let treeData = []; |
||||
if (group == 'prov') { // buat nyari kabkot
|
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i][childTitle], |
||||
key: childKey+'-'+i, |
||||
group: childGroup, |
||||
prov: result.data[i].PROV, |
||||
kabkot: result.data[i].KAB_KOT |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kabkot') { // buat nyari kecamatan
|
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i][childTitle], |
||||
key: childKey+'-'+i, |
||||
group: childGroup, |
||||
prov: result.data[i].PROV, |
||||
kabkot: result.data[i].KAB_KOT, |
||||
kec: result.data[i].KEC |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kec') { // buat nyari desa
|
||||
for(let i=0; i < result.data.length; i++) { |
||||
treeData.push({ |
||||
title: result.data[i][childTitle], |
||||
key: childKey+'-'+i, |
||||
group: childGroup, |
||||
prov: result.data[i].PROV, |
||||
kabkot: result.data[i].KAB_KOT, |
||||
kec: result.data[i].KEC, |
||||
desa: result.data[i].KEL_DES |
||||
}); |
||||
} |
||||
} |
||||
|
||||
|
||||
// this.setState({treeData: treeData, isReady: true});
|
||||
// console.log('getChild func', treeData);
|
||||
return treeData; |
||||
} else { |
||||
|
||||
} |
||||
} catch(err) { |
||||
console.log(err); |
||||
// alert(err.message.toString());
|
||||
toast.warn(err.message.toString()); |
||||
} |
||||
} |
||||
|
||||
/*onLoadData = treeNode => |
||||
new Promise(resolve => {
|
||||
if (treeNode.props.children) { |
||||
resolve(); |
||||
return; |
||||
} |
||||
setTimeout(() => { |
||||
console.log('treeNode', treeNode); |
||||
let title = treeNode.props.dataRef.title; |
||||
let group = treeNode.props.dataRef.group; |
||||
let childKey = treeNode.props.eventKey; |
||||
let getChild = this.getChild(title, group, childKey); |
||||
console.log('getChild',getChild); |
||||
|
||||
treeNode.props.dataRef.children = [ |
||||
{ title: 'Child Node', key: `${treeNode.props.eventKey}-0` }, |
||||
{ title: 'Child Node', key: `${treeNode.props.eventKey}-1` }, |
||||
]; |
||||
this.setState({ |
||||
treeData: [...this.state.treeData], |
||||
}); |
||||
resolve(); |
||||
}, 1000); |
||||
});*/ |
||||
|
||||
onLoadData = async (treeNode) => { |
||||
console.log('onLoadData treeNode',treeNode); |
||||
if (treeNode.props.children) { |
||||
return; |
||||
} |
||||
let title = treeNode.props.dataRef.title; |
||||
let group = treeNode.props.dataRef.group; |
||||
let childKey = treeNode.props.eventKey; |
||||
let getChild = null; |
||||
|
||||
// let getChild = await this.getChild(title, group, prov, kabkot, kec, childKey);
|
||||
if (group == 'prov') { |
||||
getChild = await this.getChild(title, group, group, null, null, childKey); |
||||
} |
||||
else if (group == 'kabkot') { |
||||
let prov = treeNode.props.dataRef.prov; |
||||
getChild = await this.getChild(title, group, prov, group, null, childKey); |
||||
} |
||||
else if (group == 'kec') { |
||||
let prov = treeNode.props.dataRef.prov; |
||||
let kabkot = treeNode.props.dataRef.kabkot; |
||||
getChild = await this.getChild(title, group, prov, kabkot, group, childKey); |
||||
} |
||||
|
||||
// let getChild = await this.getChild(title, group, childKey);
|
||||
console.log('getChild',getChild); |
||||
|
||||
if (getChild.length > 0) { |
||||
let treeDataChild = []; |
||||
let treeDataChildKeys = []; |
||||
|
||||
if (group == 'prov') { // buat nyari kabkot
|
||||
this.props.setExpandedTree('prov'); |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChild.push({ |
||||
title: getChild[i].title, |
||||
key: getChild[i].key, |
||||
group: getChild[i].group, |
||||
prov: getChild[i].prov, |
||||
kabkot: getChild[i].kabkot |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kabkot') { // buat nyari kec
|
||||
this.props.setExpandedTree('kab'); |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChild.push({ |
||||
title: getChild[i].title, |
||||
key: getChild[i].key, |
||||
group: getChild[i].group, |
||||
prov: getChild[i].prov, |
||||
kabkot: getChild[i].kabkot, |
||||
kec: getChild[i].kec |
||||
}); |
||||
} |
||||
} |
||||
else if (group == 'kec') { // buat nyari desa / kel_des
|
||||
this.props.setExpandedTree('kec'); |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChild.push({ |
||||
title: getChild[i].title, |
||||
key: getChild[i].key, |
||||
group: getChild[i].group, |
||||
prov: getChild[i].prov, |
||||
kabkot: getChild[i].kabkot, |
||||
kec: getChild[i].kec, |
||||
desa: getChild[i].desa, |
||||
isLeaf: true |
||||
}); |
||||
} |
||||
} |
||||
|
||||
if (treeNode.props.checked) { |
||||
for (let i=0; i < getChild.length; i++) { |
||||
treeDataChildKeys.push(getChild[i].key); |
||||
} |
||||
this.props.setAdmTreeData(treeNode, treeDataChild); |
||||
this.props.appendCheckedKeysAdm(treeDataChildKeys, treeNode.props.children) |
||||
} |
||||
else { |
||||
this.props.setAdmTreeData(treeNode, treeDataChild); |
||||
this.props.appendCheckedKeysAdm(treeDataChildKeys, []) |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
onInitData = (loadedKeys, e) => { |
||||
console.log('onInitData', e); |
||||
} |
||||
|
||||
onCheckAdmTree = (checkedKeys, e) => { |
||||
console.log('onCheckAdmTree', checkedKeys); |
||||
console.log('onCheckAdmTree checkedNodes', e.checkedNodes); |
||||
this.props.setCheckKeysAdm(checkedKeys); |
||||
this.props.setCheckNodesAdm(e.checkedNodes); |
||||
|
||||
// this.setState({ checkedKeysAdm, checkedNodesAdm: e.checkedNodes }, () => {
|
||||
// let getCheckedValue = this.getCheckedValue();
|
||||
// console.log('getCheckedValue', getCheckedValue);
|
||||
// });
|
||||
}; |
||||
|
||||
onCheckAllAdmTree = () => { |
||||
|
||||
/*const { checkedKeys, allProv } = this.state; |
||||
const totalProv = 34; |
||||
|
||||
if (checkedKeys.length > 0) { |
||||
this.setState({checkedKeys: [], toggleCheckAllValue: false}) |
||||
} |
||||
else if (checkedKeys.length == 0) { |
||||
this.setState({checkedKeys: allProv, toggleCheckAllValue: true}) |
||||
}*/ |
||||
const { checkedKeysAdm, checkedKeysAdmTemp, toggleCheckAllValue, allProv } = this.props; |
||||
this.props.setToggleCheckAllValue(!toggleCheckAllValue); |
||||
} |
||||
|
||||
onCheckOpt = (checkedKeys, e) => { |
||||
const { mode } = this.props; |
||||
this.props.setCheckKeysOpt(mode, checkedKeys); |
||||
} |
||||
|
||||
onCheckQty = (checkedKeys) => { |
||||
const { mode } = this.props; |
||||
this.props.setCheckKeysQty(mode, checkedKeys); |
||||
} |
||||
|
||||
onRightClickAdmTree = (callback) => { |
||||
console.log('onRightClickAdmTree', callback); |
||||
} |
||||
|
||||
getCheckedValue = () => { |
||||
const { treeData, checkedKeys } = this.state; |
||||
let checkedData = []; |
||||
|
||||
for(let i=0; i < checkedKeys.length; i++) { |
||||
let item = findWhere(treeData, {key: parseInt(checkedKeys[i])}); |
||||
checkedData.push(item); |
||||
} |
||||
return checkedData; |
||||
} |
||||
|
||||
renderCheckboxOpt = () => { |
||||
let checkboxes = []; |
||||
const { mode, checkedKeys2GOpt, checkedKeys3GOpt, checkedKeys4GOpt} = this.props; |
||||
|
||||
if (mode == '2G') { |
||||
// checkboxes = opt2G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys2GOpt} |
||||
onCheck={(checkedKeys2GOpt, e) => this.onCheckOpt(checkedKeys2GOpt, e)} |
||||
> |
||||
{this.renderTreeNodes(opt2G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else if (mode == '3G') { |
||||
// checkboxes = opt3G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys3GOpt} |
||||
onCheck={(checkedKeys3GOpt) => this.onCheckOpt(checkedKeys3GOpt)} |
||||
> |
||||
{this.renderTreeNodes(opt3G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else { |
||||
// checkboxes = opt4G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys4GOpt} |
||||
onCheck={(checkedKeys4GOpt) => this.onCheckOpt(checkedKeys4GOpt)} |
||||
> |
||||
{this.renderTreeNodes(opt4G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
|
||||
/*return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeysOpt} |
||||
onCheck={(checkedKeysOpt) => this.onCheckOpt(checkedKeysOpt)} |
||||
> |
||||
{this.renderTreeNodes(checkboxes)} |
||||
</Tree> |
||||
)*/ |
||||
} |
||||
|
||||
onExpand = expandedKeys => { |
||||
// console.log('onExpand', expandedKeys);
|
||||
const {closeChart} = this.props |
||||
console.log("length", expandedKeys.length) |
||||
console.log("closeChart", closeChart) |
||||
if(expandedKeys.length === 1){ |
||||
if(closeChart) { |
||||
document.getElementById('adm-tree-container').style.height = '320px' |
||||
} else { |
||||
document.getElementById('adm-tree-container').style.height = '120px' |
||||
} |
||||
} else { |
||||
if(closeChart) { |
||||
document.getElementById('adm-tree-container').style.height = '440px' |
||||
} else { |
||||
document.getElementById('adm-tree-container').style.height = '220px' |
||||
} |
||||
} |
||||
}; |
||||
|
||||
renderCheckboxQuality = () => { |
||||
let checkboxes = []; |
||||
const { mode, checkedKeys2GQty, checkedKeys3GQty, checkedKeys4GQty } = this.props; |
||||
|
||||
if (mode == '2G') { |
||||
// checkboxes = netQuality2G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys2GQty} |
||||
onCheck={(checkedKeys2GQty) => this.onCheckQty(checkedKeys2GQty)} |
||||
> |
||||
{this.renderTreeNodes(netQuality2G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else if (mode == '3G') { |
||||
// checkboxes = netQuality3G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys3GQty} |
||||
onCheck={(checkedKeys3GQty) => this.onCheckQty(checkedKeys3GQty)} |
||||
> |
||||
{this.renderTreeNodes(netQuality3G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
else { |
||||
// checkboxes = netQuality4G;
|
||||
return ( |
||||
<Tree |
||||
className="checkbox-opt" |
||||
checkable={true} |
||||
checkedKeys={checkedKeys4GQty} |
||||
onCheck={(checkedKeys4GQty) => this.onCheckQty(checkedKeys4GQty)} |
||||
> |
||||
{this.renderTreeNodes(netQuality4G)} |
||||
</Tree> |
||||
) |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
renderTreeNodes = data => |
||||
data.map(item => { |
||||
if (item.children) { |
||||
return ( |
||||
<TreeNode title={item.title} key={item.key} dataRef={item}> |
||||
{this.renderTreeNodes(item.children)} |
||||
</TreeNode> |
||||
); |
||||
} |
||||
return <TreeNode key={item.key} {...item} dataRef={item} />; |
||||
}) |
||||
|
||||
render() { |
||||
const { isReady, checkedKeys } = this.state; |
||||
const { admTreeData, checkedKeysAdm, toggleCheckAllValue } = this.props; |
||||
if (!isReady) { |
||||
return (<div className="loader-container"> |
||||
<Loader |
||||
type="TailSpin" |
||||
color="#36D7B7" |
||||
height={100} |
||||
width={100} |
||||
/> |
||||
</div>) |
||||
} |
||||
|
||||
return ( |
||||
<Fragment> |
||||
<Row> |
||||
<Col xs="12" sm="12" md="6" lg="6"> |
||||
{ this.renderCheckboxOpt() } |
||||
</Col> |
||||
<Col xs="12" sm="12" md="6" lg="6" className="not-left-col"> |
||||
{ this.renderCheckboxQuality() } |
||||
</Col> |
||||
</Row> |
||||
{/*<div className="adm-tree-checkbox-quality-container"> |
||||
{ this.renderCheckboxQuality() } |
||||
</div>*/} |
||||
<div className="adm-tree-checkbox-container"> |
||||
<Form> |
||||
<FormGroup check inline> |
||||
<Label check> |
||||
<Input type="checkbox" checked={toggleCheckAllValue} onClick={() => this.onCheckAllAdmTree()}/> Toggle Select All Wilayah |
||||
</Label> |
||||
</FormGroup> |
||||
</Form> |
||||
</div> |
||||
<div id="adm-tree-container" className="custom-scroll"> |
||||
<Tree |
||||
className="adm-tree"
|
||||
loadData={this.onLoadData} |
||||
checkable={true} |
||||
checkedKeys={checkedKeysAdm} |
||||
onCheck={(checkedKeys, e) => this.onCheckAdmTree(checkedKeys, e)} |
||||
onRightClick={(callback) => this.onRightClickAdmTree(callback)} |
||||
> |
||||
{this.renderTreeNodes(admTreeData)} |
||||
</Tree> |
||||
</div> |
||||
</Fragment> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default AdmTree; |
@ -0,0 +1,136 @@
|
||||
import React from 'react'; |
||||
import ReactDOM from 'react-dom'; |
||||
import 'antd/dist/antd.css'; |
||||
import { Tree, Input } from 'antd'; |
||||
|
||||
const { Search } = Input; |
||||
|
||||
const x = 3; |
||||
const y = 2; |
||||
const z = 1; |
||||
const gData = []; |
||||
|
||||
const generateData = (_level, _preKey, _tns) => { |
||||
const preKey = _preKey || '0'; |
||||
const tns = _tns || gData; |
||||
|
||||
const children = []; |
||||
for (let i = 0; i < x; i++) { |
||||
const key = `${preKey}-${i}`; |
||||
tns.push({ title: key, key }); |
||||
if (i < y) { |
||||
children.push(key); |
||||
} |
||||
} |
||||
if (_level < 0) { |
||||
return tns; |
||||
} |
||||
const level = _level - 1; |
||||
children.forEach((key, index) => { |
||||
tns[index].children = []; |
||||
return generateData(level, key, tns[index].children); |
||||
}); |
||||
}; |
||||
generateData(z); |
||||
|
||||
const dataList = []; |
||||
const generateList = data => { |
||||
for (let i = 0; i < data.length; i++) { |
||||
const node = data[i]; |
||||
const { key } = node; |
||||
dataList.push({ key, title: key }); |
||||
if (node.children) { |
||||
generateList(node.children); |
||||
} |
||||
} |
||||
}; |
||||
generateList(gData); |
||||
|
||||
const getParentKey = (key, tree) => { |
||||
let parentKey; |
||||
for (let i = 0; i < tree.length; i++) { |
||||
const node = tree[i]; |
||||
if (node.children) { |
||||
if (node.children.some(item => item.key === key)) { |
||||
parentKey = node.key; |
||||
} else if (getParentKey(key, node.children)) { |
||||
parentKey = getParentKey(key, node.children); |
||||
} |
||||
} |
||||
} |
||||
return parentKey; |
||||
}; |
||||
|
||||
class SearchTree extends React.Component { |
||||
state = { |
||||
expandedKeys: [], |
||||
searchValue: '', |
||||
autoExpandParent: true, |
||||
}; |
||||
|
||||
onExpand = expandedKeys => { |
||||
this.setState({ |
||||
expandedKeys, |
||||
autoExpandParent: false, |
||||
}); |
||||
}; |
||||
|
||||
onChange = e => { |
||||
const { value } = e.target; |
||||
const expandedKeys = dataList |
||||
.map(item => { |
||||
if (item.title.indexOf(value) > -1) { |
||||
return getParentKey(item.key, gData); |
||||
} |
||||
return null; |
||||
}) |
||||
.filter((item, i, self) => item && self.indexOf(item) === i); |
||||
this.setState({ |
||||
expandedKeys, |
||||
searchValue: value, |
||||
autoExpandParent: true, |
||||
}); |
||||
}; |
||||
|
||||
render() { |
||||
const { searchValue, expandedKeys, autoExpandParent } = this.state; |
||||
const loop = data => |
||||
data.map(item => { |
||||
const index = item.title.indexOf(searchValue); |
||||
const beforeStr = item.title.substr(0, index); |
||||
const afterStr = item.title.substr(index + searchValue.length); |
||||
const title = |
||||
index > -1 ? ( |
||||
<span> |
||||
{beforeStr} |
||||
<span className="site-tree-search-value">{searchValue}</span> |
||||
{afterStr} |
||||
</span> |
||||
) : ( |
||||
<span>{item.title}</span> |
||||
); |
||||
if (item.children) { |
||||
return { title, key: item.key, children: loop(item.children) }; |
||||
} |
||||
|
||||
return { |
||||
title, |
||||
key: item.key, |
||||
}; |
||||
}); |
||||
return ( |
||||
<div> |
||||
<Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange} /> |
||||
<Tree |
||||
onExpand={this.onExpand} |
||||
expandedKeys={expandedKeys} |
||||
autoExpandParent={autoExpandParent} |
||||
treeData={loop(gData)} |
||||
/> |
||||
</div> |
||||
); |
||||
} |
||||
} |
||||
|
||||
// ReactDOM.render(<SearchTree />, document.getElementById('container'));
|
||||
export default SearchTree; |
@ -0,0 +1,6 @@
|
||||
{ |
||||
"name": "AdmTree", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./AdmTree.js" |
||||
} |
@ -0,0 +1,74 @@
|
||||
.basemap-container { |
||||
z-index: 50; |
||||
top: 60px; |
||||
right: 50px; |
||||
/*background-color: red;*/ |
||||
/*padding: 100px;*/ |
||||
position: absolute; |
||||
max-height: 350px; |
||||
border-radius: 5px; |
||||
background-color: rgba(0,0,0,0.5); |
||||
/*float: right;*/ |
||||
color: #ffffff; |
||||
min-width: 180px; |
||||
justify-content: center; |
||||
} |
||||
|
||||
.basemap-title { |
||||
font-size: 14px; |
||||
margin-top: 5px; |
||||
margin-left: 20px; |
||||
margin-bottom: 10px; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.basemap-close { |
||||
float: right; |
||||
margin-right: 15px; |
||||
margin-top: -5px; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.basemap-body { |
||||
max-height: 200px; |
||||
overflow: auto; |
||||
margin: 5px; |
||||
text-align: center; |
||||
} |
||||
|
||||
.basemap-text-container { |
||||
display: block; |
||||
} |
||||
|
||||
.basemap-graphic { |
||||
display: inline-block; |
||||
} |
||||
|
||||
.basemap-text { |
||||
display: inline-block; |
||||
margin-left: 10px; |
||||
margin-right: 10px; |
||||
font-size: 12px; |
||||
} |
||||
|
||||
.basemap-active { |
||||
border-color: #ffffff !important; |
||||
background-color: #ffffff !important; |
||||
} |
||||
|
||||
.basemap-item { |
||||
display: inline-block; |
||||
padding: 10px; |
||||
border: solid; |
||||
border-radius: 5px; |
||||
margin: 2px; |
||||
cursor: pointer; |
||||
background-color: #d4d4d4; |
||||
margin-bottom: 10px; |
||||
text-align: center; |
||||
border-color: #d4d4d4; |
||||
} |
||||
|
||||
.basemap-item-title { |
||||
color: #000000; |
||||
} |
@ -0,0 +1,71 @@
|
||||
import React, { Component } from 'react'; |
||||
import './BaseMap.css';
|
||||
import '../../assets/css/customscroll.css'; |
||||
import { Row, Col } from 'reactstrap'; |
||||
// import Legend from '@terrestris/react-geo/dist/Legend/Legend';
|
||||
|
||||
class BaseMap extends Component { |
||||
|
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
activeBaseMap: '' |
||||
} |
||||
} |
||||
|
||||
componentDidMount() { |
||||
this.getActiveBaseMap(); |
||||
} |
||||
|
||||
componentDidUpdate(prevState, prevProps) { |
||||
|
||||
} |
||||
|
||||
getActiveBaseMap = () => { |
||||
let activeBaseMap = ''; |
||||
this.props.olmap.getLayers().forEach((layer, i) => { |
||||
if (layer.get('type') == 'base') { |
||||
console.log('activeBaseMap', layer.get('name')); |
||||
activeBaseMap = layer.get('name'); |
||||
} |
||||
}); |
||||
|
||||
this.setState({activeBaseMap: activeBaseMap}, () => this.renderBaseMap()); |
||||
} |
||||
|
||||
changeBaseLayer = (layer) => { |
||||
this.setState({activeBaseMap: layer.get('name')}, () =>{ |
||||
this.renderBaseMap(); |
||||
this.props.changeBaseLayer(layer); |
||||
}); |
||||
} |
||||
|
||||
renderBaseMap = () => { |
||||
return this.props.baseLayers.map((item, index) => { |
||||
// console.log('activeBaseMap', this.state.activeBaseMap);
|
||||
// console.log('layerName', item.get('name'));
|
||||
// console.log('active?', this.state.activeBaseMap == item.get('name'));
|
||||
|
||||
return ( |
||||
<div key={index} className={`basemap-item ${this.state.activeBaseMap == item.get('name') ? 'basemap-active' : ''}`} onClick={() => this.changeBaseLayer(item)}> |
||||
<img src={require(`../../assets/img/base_map/${item.get('imageName')}`)} alt={item.get('imageName')} width="75" height="50" /> <br /> |
||||
<div className="basemap-item-title">{item.get('name')}</div> |
||||
</div> |
||||
) |
||||
}) |
||||
} |
||||
|
||||
render() { |
||||
const { toggleBaseMap } = this.props; |
||||
return ( |
||||
<div className="basemap-container"> |
||||
<div className="basemap-title">Change Base Map <span className="basemap-close" onClick={toggleBaseMap}>x</span></div> |
||||
<div className="basemap-body custom-scroll"> |
||||
{ this.renderBaseMap() } |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default BaseMap; |
@ -0,0 +1,6 @@
|
||||
{ |
||||
"name": "BaseMap", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./BaseMap.js" |
||||
} |
@ -0,0 +1,19 @@
|
||||
.modal-dialog-newlayer { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.modal-content-newlayer { |
||||
width: 100%; |
||||
} |
||||
|
||||
.modal-dialog-body { |
||||
max-height: 325px; |
||||
width: 100%; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.row-input { |
||||
margin-right: 0px !important; |
||||
margin-left: -10px !important; |
||||
} |
@ -0,0 +1,348 @@
|
||||
import React, { Component } from 'react'; |
||||
import { Modal, ModalHeader, ModalBody, ModalFooter, Button, Row, Col, Form, FormGroup, Label, Input} from 'reactstrap'; |
||||
import { Icon, InlineIcon } from '@iconify/react'; |
||||
import removeCircle from '@iconify/icons-ion/remove-circle'; |
||||
import { findWhere, without } from 'underscore'; |
||||
import './CreateNewLayer.css'; |
||||
import '../../assets/css/customscroll.css'; |
||||
import { createNewLayer } from '../../const/GeoserverFunc.js'; |
||||
|
||||
class CreateNewLayer extends Component { |
||||
constructor(props) { |
||||
super(props); |
||||
this.state = { |
||||
layerName: '', |
||||
layerType: '', |
||||
columns: [], |
||||
disableCreateLayerButton: true |
||||
} |
||||
// this.handleChangeInputColumnName = this.handleChangeInputColumnName.bind(this);
|
||||
// this.sendCreateNewLayer = this.sendCreateNewLayer.bind(this);
|
||||
// this.checkBeforeSend = this.checkBeforeSend.bind(this);
|
||||
} |
||||
|
||||
componentDidMount() { |
||||
// console.log('CreateNewLayer resTableData', this.props.resTableData);
|
||||
} |
||||
|
||||
componentDidUpdate(prevProps, prevState) { |
||||
// this.checkBeforeSend();
|
||||
// if (prevState.layerName !== this.state.layerName) {
|
||||
// this.checkBeforeSend();
|
||||
// }
|
||||
// if (prevState.layerType !== this.state.layerType) {
|
||||
// this.checkBeforeSend();
|
||||
// }
|
||||
// if (prevState.columns !== this.state.columns) {
|
||||
// this.checkBeforeSend();
|
||||
// }
|
||||
} |
||||
|
||||
addColumn = () => { |
||||
let { columns } = this.state; |
||||
let maxIdx = null; |
||||
let newIdx = null; |
||||
if (columns.length < 1) { |
||||
newIdx = 1; |
||||
} |
||||
else { |
||||
maxIdx = Math.max.apply(Math, columns.map((column) => column.idx)); |
||||
console.log('maxIdx',maxIdx); |
||||
newIdx = maxIdx + 1; |
||||
} |
||||
let oneColumn = { |
||||
idx: newIdx, |
||||
column_name: "", |
||||
column_type: "" |
||||
} |
||||
this.setState({columns: [...columns, oneColumn]}, () => { |
||||
console.log(this.state.columns) |
||||
this.renderColumnAttribute(); |
||||
}); |
||||
} |
||||
|
||||
renderColumnAttribute = () => { |
||||
let { columns } = this.state; |
||||
|
||||
if (columns.length < 1) { |
||||
return null; |
||||
}
|
||||
else { |
||||
return columns.map((item, index) => { |
||||
return (<Row key={item.idx} className="row-input"> |
||||
<Col xl={5} xs={5}> |
||||
<FormGroup> |
||||
<Input type="text" name="column_name" id="column_name" placeholder="Input Column Name" value={item.column_name} onChange={this.handleChangeInputColumnName.bind(this, item.idx)} /> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col xl={5} xs={5}> |
||||
<FormGroup> |
||||
<Input type="select" name="column_type" id="column_type" value={item.column_type} onChange={this.handleChangeInputColumnType.bind(this, item.idx)}> |
||||
<option value="">Select column type</option> |
||||
<option value="integer">Integer</option> |
||||
<option value="character varying">Text</option> |
||||
<option value="double precision">Double</option> |
||||
</Input> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col xl={2} xs={2}> |
||||
<FormGroup> |
||||
<Button color="danger" id="remove_column" size="sm" onClick={() => this.deleteColumn(item.idx)}><Icon icon={removeCircle} width={20} height={20} /></Button> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row>) |
||||
}) |
||||
// for (let i=0; i < columns.length; i++) {
|
||||
// return (
|
||||
// <Row key={columns.idx}>
|
||||
// <Col xl={5} xs={5}>
|
||||
// <FormGroup>
|
||||
// <Input type="text" name="column_name" id="column_name" placeholder="Input Column Name" />
|
||||
// </FormGroup>
|
||||
// </Col>
|
||||
// <Col xl={5} xs={5}>
|
||||
// <FormGroup>
|
||||
// <Input type="select" name="column_type" id="column_type">
|
||||
// <option>Select column type</option>
|
||||
// <option value="integer">Integer</option>
|
||||
// <option value="text">Text</option>
|
||||
// <option value="double">Double</option>
|
||||
// </Input>
|
||||
// </FormGroup>
|
||||
// </Col>
|
||||
// <Col xl={2} xs={2}>
|
||||
// <FormGroup>
|
||||
// <Button color="danger" id="remove_column" size="sm"><Icon icon={removeCircle} width={20} height={20} /></Button>
|
||||
// </FormGroup>
|
||||
// </Col>
|
||||
// </Row>
|
||||
// )
|
||||
// }
|
||||
} |
||||
} |
||||
|
||||
deleteColumn = (idx) => { |
||||
console.log('deleteColumn', idx); |
||||
let { columns } = this.state; |
||||
console.log('columns', columns); |
||||
let deletedItem = findWhere(columns, {idx: idx}); |
||||
console.log(deletedItem); |
||||
let afterRemove = without(columns, deletedItem); |
||||
console.log(console.log('afterRemove', afterRemove)); |
||||
this.setState({columns: afterRemove}); |
||||
} |
||||
|
||||
handleChangeInputLayerName(event) { |
||||
// const validation = !/[0-9a-zA-Z-_]/.test(String.fromCharCode(event.which));
|
||||
// console.log('validation', validation);
|
||||
// const value = event.target.value.split(" ").join("");
|
||||
let value = event.target.value; |
||||
// value = value.replace(/[^A-Za-z_]/gi, "");
|
||||
// value = value.replace(/[^\w]/gi, "");
|
||||
value = value.replace(/[^\w]/gi, ""); |
||||
// if (validation) { return false; }
|
||||
this.setState({layerName: value}, () => console.log('layerName', this.state.layerName)); |
||||
} |
||||
|
||||
handleChangeInputLayerType(event) { |
||||
const value = event.target.value.split(" ").join(""); |
||||
this.setState({layerType: value}, () => console.log('layerType', this.state.layerType)); |
||||
} |
||||
|
||||
handleChangeInputColumnName(idx, event) { |
||||
// dicari state columns terus dicari idx nya, kemudian set text nya
|
||||
|
||||
let { columns } = this.state; |
||||
let changedItem = findWhere(columns, {idx: idx}); |
||||
// let value = event.target.value.split(" ").join("");
|
||||
let value = event.target.value; |
||||
// value = value.replace(/[^A-Za-z0-9_]/gi, "");
|
||||
value = value.replace(/[^\w]/gi, ""); |
||||
changedItem.column_name = value; |
||||
console.log('changedItem', changedItem); |
||||
this.setState({columns: columns}); |
||||
console.log('columns', this.state.columns); |
||||
} |
||||
|
||||
handleChangeInputColumnType(idx, event) { |
||||
let { columns } = this.state; |
||||
let changedItem = findWhere(columns, {idx: idx}); |
||||
// let value = event.target.value.split(" ").join("");
|
||||
let value = event.target.value; |
||||
changedItem.column_type = value; |
||||
console.log('changedItem', changedItem); |
||||
this.setState({columns: columns}); |
||||
console.log('columns', this.state.columns); |
||||
} |
||||
|
||||
preventSpace(e) { |
||||
// Prevent space in attribute name
|
||||
// $('input[name^="column_name"]').on("keypress", function(e) {
|
||||
// if(!/[0-9a-zA-Z-_]/.test(String.fromCharCode(e.which)))
|
||||
// return false;
|
||||
// });
|
||||
console.log('event keypress',e); |
||||
// console.log(!/[0-9a-zA-Z-_]/.test(String.fromCharCode(e.which)));
|
||||
// if(!/[0-9a-zA-Z-_]/.test(String.fromCharCode(e.which))) {
|
||||
// return false;
|
||||
// }
|
||||
} |
||||
|
||||
// checkBeforeSend = () => {
|
||||
// // make sure no empty fields
|
||||
// // enable disableCreateLayerButton if no empty fields
|
||||
// const { layerName, layerType, columns, disableCreateLayerButton } = this.state;
|
||||
// let toEnableValue = false;
|
||||
|
||||
// if (layerName !== "" && layerType !== "") {
|
||||
// if (columns.length > 0) {
|
||||
// for (let i = 0; i < columns.length; i++) {
|
||||
// if (columns[i].column_name === "") {
|
||||
// toEnableValue = false;
|
||||
// // return false;
|
||||
// }
|
||||
// else if (columns[i].column_type === "") {
|
||||
// toEnableValue = false;
|
||||
// // return false;
|
||||
// }
|
||||
// else {
|
||||
// toEnableValue = true;
|
||||
// // return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// toEnableValue = false;
|
||||
// // return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// console.log('toEnableValue', toEnableValue);
|
||||
// if (toEnableValue === true) {
|
||||
// // this.setState({disableCreateLayerButton: toEnableValue});
|
||||
// // this.enableCreateLayerButton();
|
||||
// console.log('enabling create layer button....')
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// enableCreateLayerButton = () => {
|
||||
// // this.setState({disableCreateLayerButton: true});
|
||||
// console.log('enabling create layer button....')
|
||||
// }
|
||||
|
||||
sendCreateNewLayer = async () => { |
||||
const { layerName, layerType, columns } = this.state; |
||||
let reqPayload = { |
||||
layer_name: layerName, |
||||
layer_type: layerType, |
||||
columns: columns |
||||
} |
||||
|
||||
if (layerName === '') { |
||||
alert("Please input the layer name"); |
||||
return; |
||||
} |
||||
if (layerType === '') { |
||||
alert("Please input the layer type"); |
||||
return; |
||||
} |
||||
if (columns.length < 1) { |
||||
alert("Please add at least one attribute column"); |
||||
return; |
||||
} |
||||
if (columns.length > 0) { |
||||
for (let i = 0; i < columns.length; i++) { |
||||
if (columns[i].column_name === '') { |
||||
alert("Please make sure attibute column name is filled") |
||||
return; |
||||
} |
||||
if (columns[i].column_type === '') { |
||||
alert("Please make sure attibute column type is filled") |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
let processCreateNewLayer = await createNewLayer(reqPayload); |
||||
console.log('sendCreateNewLayer',processCreateNewLayer); |
||||
alert("Success sending create new layer"); |
||||
} |
||||
|
||||
|
||||
|
||||
render() { |
||||
return ( |
||||
<Modal isOpen={this.props.createNewLayerVisible} toggle={this.props.toggleCreateNewLayer} className="modal-dialog-newlayer" contentClassName="modal-content-newlayer"> |
||||
<ModalHeader toggle={this.props.toggleCreateNewLayer}>{this.props.createNewLayerTitle ? this.props.createNewLayerTitle : 'Create New Layer'}</ModalHeader> |
||||
<ModalBody> |
||||
<div className="modal-dialog-body custom-scroll"> |
||||
{/*<div className="modal-body-wrap">*/} |
||||
{/*<div className="row">*/} |
||||
{/*<div className="col-md-12">*/} |
||||
{/*<Row> |
||||
<Col xl={6} xs={6}> |
||||
|
||||
</Col> |
||||
</Row>*/} |
||||
<Form> |
||||
<FormGroup> |
||||
<Label for="layer_name">Layer Name</Label> |
||||
<Input type="text" name="layer_name" id="layer_name" placeholder="Input Layer Name" value={this.state.layerName} onChange={this.handleChangeInputLayerName.bind(this)}/> |
||||
</FormGroup> |
||||
<FormGroup> |
||||
<Label for="layer_type">Layer Type</Label> |
||||
<Input type="select" name="layer_type" id="layer_type" value={this.state.layerType} onChange={this.handleChangeInputLayerType.bind(this)}> |
||||
<option value="">Select layer type</option> |
||||
<option value="point">Point</option> |
||||
<option value="linestring">LineString</option> |
||||
<option value="polygon">Polygon</option> |
||||
</Input> |
||||
</FormGroup> |
||||
</Form> |
||||
<FormGroup> |
||||
<Label for="attributes">Attributes</Label> |
||||
<Row className="row-input"> |
||||
<Col xl={5} xs={5}> |
||||
<FormGroup> |
||||
<Label for="column_name">Column Name</Label> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col xl={5} xs={5}> |
||||
<FormGroup> |
||||
<Label for="column_type">Column Type</Label> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col xl={2} xs={2}> |
||||
<FormGroup> |
||||
<Label for="remove_column">{' '}</Label> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
{ this.renderColumnAttribute() } |
||||
<Row className="row-input"> |
||||
<Col xl={9} xs={9}></Col> |
||||
<Col xl={3} xs={3}> |
||||
<FormGroup> |
||||
<Button color="primary" id="add_column" size="sm" onClick={() => this.addColumn()}>Add Column</Button> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</FormGroup> |
||||
{/*</div>*/} |
||||
{/*</div>*/} |
||||
{/*</div>*/} |
||||
|
||||
</div> |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
{/*<Button color="success" onClick={this.sendCreateNewLayer} disabled={this.state.disableCreateLayerButton}>Create</Button>{' '}*/} |
||||
<Button color="success" onClick={() => this.sendCreateNewLayer()} >Create</Button>{' '} |
||||
<Button color="secondary" onClick={this.props.toggleCreateNewLayer}>Cancel</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default CreateNewLayer; |
@ -0,0 +1,6 @@
|
||||
{ |
||||
"name": "CreateNewLayer", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./CreateNewLayer.js" |
||||
} |
@ -0,0 +1,25 @@
|
||||
import React, { Component } from 'react'; |
||||
import { Modal, ModalHeader, ModalBody, ModalFooter, Button, |
||||
UncontrolledTooltip, UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; |
||||
|
||||
class CustomModal extends Component { |
||||
constructor(props) { |
||||
super(props) |
||||
} |
||||
|
||||
render() { |
||||
return( |
||||
<Modal isOpen={this.props.mapTableModalVisible} toggle={this.props.toggleMapTable} className="modal-dialog-data" contentClassName="modal-content-data"> |
||||
<ModalHeader toggle={this.props.toggleMapTable}>{this.props.mapTableTitle}</ModalHeader> |
||||
<ModalBody> |
||||
Lorem ipsum..... |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color="secondary" onClick={this.props.toggleMapTable}>Cancel</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default CustomModal; |
@ -0,0 +1,6 @@
|
||||
{ |
||||
"name": "CustomModal", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./CustomModal.js" |
||||
} |
@ -0,0 +1,52 @@
|
||||
.daily-info-container { |
||||
margin-top: -10px; |
||||
} |
||||
|
||||
.daily-info-container-empty { |
||||
/*z-index: 9999;*/ |
||||
/*position: fixed;*/ |
||||
/*height: 200px;*/ |
||||
} |
||||
|
||||
.daily-info-group-container { |
||||
margin-bottom: -10px; |
||||
} |
||||
|
||||
.daily-info-group-title { |
||||
font-weight: 700; |
||||
} |
||||
|
||||
.daily-info-list { |
||||
width: 100%; |
||||
display: inline-block; |
||||
padding-left: 10px; |
||||
padding-right: 5px; |
||||
padding-top: 7px; |
||||
padding-bottom: 7px; |
||||
margin-bottom: 5px; |
||||
border-radius: 10px; |
||||
background-color: #f2f2f2; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.daily-info-list:hover { |
||||
background-color: #d9d9d9; |
||||
} |
||||
|
||||
.daily-info-name { |
||||
width: 70%; |
||||
display: inline-block; |
||||
font-weight: 700; |
||||
font-size: 12px; |
||||
} |
||||
|
||||
.daily-info-count { |
||||
width: 30%; |
||||
display: inline-block; |
||||
text-align: center; |
||||
} |
||||
|
||||
.daily-info-badge { |
||||
font-size: 14px !important; |
||||
text-align: right; |
||||
} |
@ -0,0 +1,655 @@
|
||||
import * as React from 'react'; |
||||
|
||||
import { Row, Col, Badge } from 'reactstrap'; |
||||
import './DailyInfo.css'; |
||||
import '../../assets/css/customscroll.css'; |
||||
import { formatLabel, COLUMN_DAILY_INFO_TABLE } from '../../const/CustomFunc.js' |
||||
import { getDailyInfoApi, requestTableDailyInfoApi } from '../../const/GeohrApiFunc.js'; |
||||
import ContentLoader from 'react-content-loader' |
||||
import { |
||||
AT_TRIP_COLOR, |
||||
AT_CUSTOMER_COLOR, |
||||
AT_OFFICE_COLOR, |
||||
PRESENT_COLOR, |
||||
ABSENT_COLOR, |
||||
TOTAL_ATTENDANCE_COLOR, |
||||
ACHIEVE_COLOR, |
||||
NOT_ACHIEVE_COLOR, |
||||
DONE_COLOR, |
||||
NOT_YET_COLOR, |
||||
IZIN_COLOR, |
||||
TOTAL_COLOR, |
||||
RED_COLOR, |
||||
ORANGE_COLOR, |
||||
GREEN_COLOR, |
||||
DARK_GREY_COLOR, |
||||
BLUE_COLOR, |
||||
PURPLE_COLOR, |
||||
BROWN_COLOR, |
||||
YELLOW_COLOR, |
||||
WHITE_COLOR, |
||||
BLACK_COLOR |
||||
} from '../../const/AppConst.js' |
||||
import axios from 'axios'; |
||||
import { API_GEOHR_KARYAWAN, API_DAILY_INFO, API_DAILY_INFO_DETAIL, DASHBOARD_PROYEK_SEARCH, PROYEK_SEARCH } from '../../const/ApiConst'; |
||||
// import DialogBottom from './DialogBottom'
|
||||
import { toast } from 'react-toastify'; |
||||
import moment from 'moment'; |
||||
const id_org = window.localStorage.getItem('id_org'); |
||||
|
||||
// const token = window.localStorage.getItem('token');
|
||||
// const config = {
|
||||
// headers:
|
||||
// {
|
||||
// "Authorization": `Bearer ${token}`,
|
||||
// "Content-type": `application/json`
|
||||
// }
|
||||
// };
|
||||
|
||||
class DailyInfo extends React.Component { |
||||
|
||||
constructor(props) { |
||||
|
||||
super(props); |
||||
this.state = { |
||||
menu: null, |
||||
isReady: false, |
||||
sumPresensi: 0, |
||||
sumAbsensi: 0, |
||||
sumIzin: 0, |
||||
sumTracked: 0, |
||||
sumUntracked: 0, |
||||
sumEmployee: 0, |
||||
sumPanicBtn: 0, |
||||
dataNyPresence: [], |
||||
dataPresence: [], |
||||
dataPermission: [], |
||||
dataAbsent: [], |
||||
openDialogBottom: false, |
||||
itemDialog: [], |
||||
dataTableDialog: [], |
||||
sumTelat: 0, |
||||
sumTanpaKet: 0, |
||||
dataTelat: [], |
||||
dataTanpaKet: [], |
||||
dataAbsensi:[], |
||||
dataPanicBtn: [], |
||||
dataEmployee: [], |
||||
totalProyek: 0, |
||||
planning: 0, |
||||
realisasi: 0, |
||||
status_project: { |
||||
good: 0, |
||||
warning: 0, |
||||
critical: 0 |
||||
}, |
||||
waspang_status: { |
||||
presensi: 0, |
||||
absensi: 0 |
||||
}, |
||||
panic_button: 0 |
||||
} |
||||
} |
||||
|
||||
async componentDidMount() { |
||||
// this.getTotalProyek();
|
||||
// this.getDailyInfo()
|
||||
// this.getDailyEmployee();
|
||||
// this.setState({ isReady: true })
|
||||
} |
||||
|
||||
componentDidUpdate(prevProps, prevState) { |
||||
|
||||
} |
||||
|
||||
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 '+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 result = await axios
|
||||
// .get(DASHBOARD_PROYEK, 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) { |
||||
console.log('error getDailyInfo', e); |
||||
// return false;
|
||||
} |
||||
} |
||||
|
||||
getTotalProyek = async () => { |
||||
const payload = { |
||||
|
||||
} |
||||
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(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({ |
||||
totalProyek: result.data.length, |
||||
isReady: true |
||||
}); |
||||
} |
||||
|
||||
// const result = await axios
|
||||
// .get(PROYEK_LIST, config)
|
||||
// .then(res => res)
|
||||
// .catch((error) => error.response);
|
||||
|
||||
// if (result && result.data && result.data.code == 200) {
|
||||
// const dataSum = result.data;
|
||||
// this.setState({
|
||||
// totalProyek: result.data.length,
|
||||
// isReady: true
|
||||
// });
|
||||
// }
|
||||
|
||||
} |
||||
catch (e) { |
||||
console.log('error getDailyInfo', e); |
||||
// return false;
|
||||
} |
||||
} |
||||
|
||||
openDialogBottom = async(item) => { |
||||
let data = [] |
||||
const { dataPresence, dataAbsensi, dataEmployee, dataPanicBtn, dataTelat, dataTanpaKet } = this.state |
||||
if (item.key === "presensi") { |
||||
data = dataPresence |
||||
} else if (item.key === "absensi") { |
||||
data = dataAbsensi |
||||
} else if (item.key === "panic button") { |
||||
data = dataPanicBtn |
||||
} else if (item.key === "total dengan keterangan") { |
||||
data = dataTelat |
||||
} else if (item.key === "total tanpa keterangan") { |
||||
data = dataTanpaKet |
||||
} else if (item.key === "total karyawan") { |
||||
data = dataEmployee |
||||
} |
||||
this.setState({ openDialogBottom: true, itemDialog: item, dataTableDialog: data }) |
||||
} |
||||
|
||||
closeDialogBottom = () => { |
||||
this.setState({ openDialogBottom: false }) |
||||
} |
||||
|
||||
// getListDailyInfo = () => {
|
||||
// let menu = [
|
||||
// {
|
||||
// "id": 1,
|
||||
// "title": "TOTAL KARYAWAN",
|
||||
// "key": "total karyawan",
|
||||
// "total": this.state.sumEmployee,
|
||||
// "color": TOTAL_COLOR,
|
||||
// "text_color": WHITE_COLOR
|
||||
// },
|
||||
// {
|
||||
// "id": 2,
|
||||
// "title": "HADIR",
|
||||
// "key": "presensi",
|
||||
// "total": this.state.sumPresensi,
|
||||
// "color": PRESENT_COLOR,
|
||||
// "text_color": WHITE_COLOR
|
||||
// },
|
||||
// {
|
||||
// "id": 3,
|
||||
// "title": "TIDAK HADIR",
|
||||
// "key": "izin",
|
||||
// "total": this.state.sumAbsensi,
|
||||
// "color": IZIN_COLOR,
|
||||
// "text_color": WHITE_COLOR
|
||||
// },
|
||||
// {
|
||||
// "id": 4,
|
||||
// "title": "KARYAWAN TELAT",
|
||||
// "key": "total dengan keterangan",
|
||||
// "total": this.state.sumTelat,
|
||||
// "color": NOT_YET_COLOR,
|
||||
// "text_color": WHITE_COLOR
|
||||
// },
|
||||
// {
|
||||
// "id": 5,
|
||||
// "title": "KARYAWAN TANPA KETERANGAN",
|
||||
// "key": "total tanpa keterangan",
|
||||
// "total": this.state.sumTanpaKet,
|
||||
// "color": DONE_COLOR,
|
||||
// "text_color": WHITE_COLOR
|
||||
// },
|
||||
// {
|
||||
// "id": 6,
|
||||
// "title": "PANIK BUTTON",
|
||||
// "key": "panic button",
|
||||
// "total": this.state.sumPanicBtn,
|
||||
// "color": ABSENT_COLOR,
|
||||
// "text_color": WHITE_COLOR
|
||||
// }
|
||||
// ]
|
||||
|
||||
// return menu;
|
||||
// }
|
||||
|
||||
// renderDailyInfo = () => {
|
||||
// const list = this.getListDailyInfo() || [];
|
||||
// return (
|
||||
// list.map((item) => {
|
||||
// return (
|
||||
// <div onClick={() => this.openTable(item)} key={item.id} className="daily-info-list">
|
||||
// <div className="daily-info-name">
|
||||
// {item.title}
|
||||
// </div>
|
||||
// <div className="daily-info-count">
|
||||
// <Badge color="primary" pill className="daily-info-badge" style={{ backgroundColor: item.color }}>{item.total}</Badge>
|
||||
// </div>
|
||||
// </div>
|
||||
// )
|
||||
// })
|
||||
// )
|
||||
// }
|
||||
|
||||
getListDailyInfo = () => { |
||||
let menu = [ |
||||
{ |
||||
"id": 1, |
||||
"title": "PROYEK", |
||||
"key": "proyek", |
||||
"total": this.state.totalProyek, |
||||
"color": BROWN_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}, |
||||
{ |
||||
"id": 2, |
||||
"title": "PLANNING", |
||||
"key": "plannng", |
||||
"total": this.state.planning, |
||||
"color": DARK_GREY_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}, |
||||
{ |
||||
"id": 3, |
||||
"title": "REALISASI", |
||||
"key": "realisasi", |
||||
"total": this.state.realisasi, |
||||
"color": BLUE_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}, |
||||
{ |
||||
"id": 4, |
||||
"title": "STATUS PROJECT", |
||||
"key": "status_project", |
||||
"total": undefined, |
||||
"color": DONE_COLOR, |
||||
"text_color": WHITE_COLOR, |
||||
"children": [ |
||||
{ |
||||
"id": 1, |
||||
"title": "Aman", |
||||
"key": "status_project_good", |
||||
"total": this.state.status_project.good, |
||||
"color": GREEN_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}, |
||||
{ |
||||
"id": 2, |
||||
"title": "Alert", |
||||
"key": "status_project_warning", |
||||
"total": this.state.status_project.warning, |
||||
"color": YELLOW_COLOR, |
||||
"text_color": DARK_GREY_COLOR |
||||
}, |
||||
{ |
||||
"id": 3, |
||||
"title": "Critical", |
||||
"key": "status_project_critical", |
||||
"total": this.state.status_project.critical, |
||||
"color": RED_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}] |
||||
}, |
||||
{ |
||||
"id": 5, |
||||
"title": "WASPANG STATUS", |
||||
"key": "waspang_status", |
||||
"total": undefined, |
||||
"color": IZIN_COLOR, |
||||
"text_color": WHITE_COLOR, |
||||
"children": [ |
||||
{ |
||||
"id": 1, |
||||
"title": "Presensi", |
||||
"key": "waspang_status_presensi", |
||||
"total": this.state.waspang_status.presensi, |
||||
"color": GREEN_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}, |
||||
{ |
||||
"id": 2, |
||||
"title": "Absensi", |
||||
"key": "waspang_status_absensi", |
||||
"total": this.state.waspang_status.absensi, |
||||
"color": ORANGE_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}], |
||||
}, |
||||
{ |
||||
"id": 6, |
||||
"title": "PANIC BUTTON", |
||||
"key": "panic_button", |
||||
"total": this.state.panic_button, |
||||
"color": PURPLE_COLOR, |
||||
"text_color": WHITE_COLOR |
||||
}, |
||||
] |
||||
|
||||
return menu; |
||||
} |
||||
|
||||
renderDailyInfo = () => { |
||||
const list = this.getListDailyInfo() || []; |
||||
return this.renderChildDailyInfo(list); |
||||
} |
||||
|
||||
renderChildDailyInfo = (data) => { |
||||
return ( |
||||
data.map((item) => { |
||||
return ( |
||||
<div key={item.id} className="daily-info-list"> |
||||
<div className="daily-info-name"> |
||||
{item.title} |
||||
</div> |
||||
<div className="daily-info-count"> |
||||
<Badge color="primary" pill className="daily-info-badge" style={{ backgroundColor: item.color, color: item.text_color }}>{item.total !== undefined ? item.total : null}</Badge> |
||||
</div> |
||||
{ item.children ? this.renderChildDailyInfo(item.children) : null } |
||||
</div> |
||||
) |
||||
}) |
||||
) |
||||
} |
||||
|
||||
// requestTableDailyInfoApi = async (table_type) => {
|
||||
// const formData = new FormData();
|
||||
// // formData.append('start', 0);
|
||||
// // formData.append('length', 100);
|
||||
// formData.append('table_type', table_type);
|
||||
|
||||
// // if(this.state.search!==""){
|
||||
// // formData.append('value', this.state.search);
|
||||
// // }
|
||||
|
||||
// const start = 0;
|
||||
// const length = 100;
|
||||
|
||||
// const param = {
|
||||
// method: 'POST',
|
||||
// header: JSON.stringify({'Content-Type': 'multipart/form-data'}),
|
||||
// body: formData
|
||||
// }
|
||||
|
||||
// try {
|
||||
// const result = await fetch(API_DAILY_INFO_DETAIL(start,length), param).then(response => response.json()).then(res => res);
|
||||
// console.log('requestTableDailyInfoApi result', result);
|
||||
// if (result.code_status === 200 && result.data) {
|
||||
// return result.data;
|
||||
// }
|
||||
// else {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// catch (e) {
|
||||
// console.log('error get', e);
|
||||
// toast.warn(e.toString());
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
openTable = async (item) => { |
||||
const { dataPresence, dataAbsensi, dataEmployee, dataPanicBtn, dataTelat, dataTanpaKet} = this.state |
||||
|
||||
console.log('openTable', item); |
||||
|
||||
await this.props.setIsProcessing(true); |
||||
this.props.removeLayerByName('routeLayer'); // remove the previous routeLayer
|
||||
|
||||
let nameUpperCase = item.title.toUpperCase(); |
||||
this.props.setMapTableTitle(nameUpperCase); |
||||
// let table = await requestTableDailyInfoApi(item);
|
||||
// console.log('[DailyInfo] openTable table', table);
|
||||
|
||||
let column = []; |
||||
|
||||
let data = null; |
||||
|
||||
// const editFormatter = () => {
|
||||
// return (
|
||||
// <div>
|
||||
// <i className="cil-search fa-lg" style={{ color: 'lightblue', marginRight: '10px', cursor: "pointer" }} onClick={() => console.log('goToFeature')}></i>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
|
||||
// if (table && table.length > 0) {
|
||||
// let oneRow = table[0];
|
||||
// let optionCell = {
|
||||
// dataField: '_option_',
|
||||
// text: 'Action',
|
||||
// formatter: editFormatter
|
||||
// }
|
||||
|
||||
// for (let key in oneRow) {
|
||||
// column.push({
|
||||
// "dataField": key,
|
||||
// "text": formatLabel(key)
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// data = table;
|
||||
// }
|
||||
|
||||
// await this.requestTableDailyInfoApi(item.key);
|
||||
// let table_type = '';
|
||||
// if(type==="presensi"){
|
||||
// table_type = "hadir";
|
||||
// }else if(type==="panic button"){
|
||||
// table_type = "panik_button";
|
||||
// }else if(type==="absent"){
|
||||
// table_type = "tidak_hadir";
|
||||
// }else if(type==="late"){
|
||||
// table_type = "karyawan_telat";
|
||||
// }else if(type==="without_ket"){
|
||||
// table_type = "karyawan_tanpa_keterangan";
|
||||
// }else if(type==="sum_employee"){
|
||||
// table_type = "total_karyawan";
|
||||
// }
|
||||
|
||||
|
||||
let table_type = ''; |
||||
|
||||
// if (item.key === "presensi") {
|
||||
// data = dataPresence
|
||||
// } else if (item.key === "absensi") {
|
||||
// data = dataAbsensi
|
||||
// } else if (item.key === "panic button") {
|
||||
// data = dataPanicBtn
|
||||
// } else if (item.key === "total dengan keterangan") {
|
||||
// data = dataTelat
|
||||
// } else if (item.key === "total tanpa keterangan") {
|
||||
// data = dataTanpaKet
|
||||
// } else if (item.key === "total karyawan") {
|
||||
// data = dataEmployee
|
||||
// }
|
||||
|
||||
if (item.key === "total karyawan") { |
||||
table_type = "total_karyawan"; |
||||
} |
||||
else if (item.key === "presensi") { |
||||
table_type = "hadir"; |
||||
} |
||||
else if (item.key === "izin") { |
||||
table_type = "tidak_hadir"; |
||||
} |
||||
else if (item.key === "total dengan keterangan") { |
||||
table_type = "karyawan_telat"; |
||||
} |
||||
else if (item.key === "total tanpa keterangan") { |
||||
table_type = "karyawan_tanpa_keterangan"; |
||||
} |
||||
else if (item.key === "panic button") { |
||||
table_type = "panik_button"; |
||||
} |
||||
this.props.setTableType(table_type) |
||||
|
||||
// let dataRes = await requestTableDailyInfoApi(table_type);
|
||||
|
||||
// this.props.setMapTableData(dataRes)
|
||||
|
||||
|
||||
if (!this.props.mapTableModalVisible) { |
||||
this.props.toggleMapTable(); |
||||
} |
||||
|
||||
await this.props.setIsProcessing(false); |
||||
} |
||||
|
||||
render() { |
||||
const { openDialogBottom, itemDialog, dataTableDialog, isReady } = this.state; |
||||
if (!isReady) { |
||||
return ( |
||||
<div className="daily-info-container-empty"> |
||||
<ContentLoader |
||||
speed={2} |
||||
width="100%" |
||||
height="200" |
||||
viewBox="0 0 200 200" |
||||
backgroundColor="#f3f3f3" |
||||
foregroundColor="#ecebeb" |
||||
> |
||||
<rect x="0" y="0" rx="6" ry="6" width="100" height="25" /> |
||||
<rect x="0" y="30" rx="10" ry="10" width="100%" height="40" /> |
||||
<rect x="0" y="75" rx="10" ry="10" width="100%" height="40" /> |
||||
<rect x="0" y="120" rx="10" ry="10" width="100%" height="40" /> |
||||
<rect x="0" y="175" rx="0" ry="0" width="100%" height="2" /> |
||||
</ContentLoader> |
||||
<ContentLoader |
||||
speed={2} |
||||
width="100%" |
||||
height="200" |
||||
viewBox="0 0 200 200" |
||||
backgroundColor="#f3f3f3" |
||||
foregroundColor="#ecebeb" |
||||
> |
||||
<rect x="0" y="0" rx="6" ry="6" width="100" height="25" /> |
||||
<rect x="0" y="30" rx="10" ry="10" width="100%" height="40" /> |
||||
<rect x="0" y="75" rx="10" ry="10" width="100%" height="40" /> |
||||
<rect x="0" y="120" rx="10" ry="10" width="100%" height="40" /> |
||||
<rect x="0" y="175" rx="0" ry="0" width="100%" height="2" /> |
||||
</ContentLoader> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
return ( |
||||
<div style={{ width: "100%", height: "100%" }} className="daily-info-container"> |
||||
{/* {openDialogBottom && ( |
||||
<DialogBottom |
||||
isCloseDialog={this.closeDialogBottom} |
||||
itemDialog={itemDialog} |
||||
dataTable={dataTableDialog} |
||||
/> |
||||
)} */} |
||||
|
||||
<div className="daily-info-group-container"> |
||||
{/*<h6 className="daily-info-group-title">Status</h6> */} |
||||
{this.renderDailyInfo()} |
||||
</div> |
||||
|
||||
{/* {menu && menu.length > 0 && menu.map((menuItem, index) => { |
||||
return ( |
||||
<div className="daily-info-group-container" key={index}> |
||||
<h6 className="daily-info-group-title">{menuItem.title.toUpperCase()}</h6> |
||||
{menuItem.children.length > 0 && menuItem.children.map((childMenuItem, index) => { |
||||
return ( |
||||
<div className="daily-info-list" key={index} onClick={() => this.openTable(childMenuItem)} key={index}> |
||||
<div className="daily-info-name"> |
||||
{childMenuItem.name.toUpperCase()} |
||||
</div> |
||||
<div className="daily-info-count"> |
||||
<Badge color="primary" pill className="daily-info-badge" style={{ backgroundColor: childMenuItem.color }}>{childMenuItem.total}</Badge> |
||||
</div> |
||||
</div> |
||||
) |
||||
})} |
||||
|
||||
</div> |
||||
) |
||||
}) |
||||
} */} |
||||
</div> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default DailyInfo; |
@ -0,0 +1,357 @@
|
||||
import React, { Component } from 'react' |
||||
import { Resizable } from "re-resizable"; |
||||
import closeCircleOutline from '@iconify/icons-ion/close-circle-outline'; |
||||
import removeCircleOutline from '@iconify/icons-ion/remove-circle-outline'; |
||||
import windowMaximaze from '@iconify/icons-mdi/window-maximize'; |
||||
import { Col, Row, Table, Card, CardHeader, CardBody, CardFooter } from 'reactstrap'; |
||||
import { Icon } from '@iconify/react'; |
||||
import '../../views/Dashboard/Dashboard.css'; |
||||
import moment from 'moment'; |
||||
|
||||
const style = { |
||||
position: "fixed", |
||||
width: "100%", |
||||
bottom: 0, |
||||
left: 0, |
||||
right: 0, |
||||
border: "solid 1px #ddd", |
||||
background: "#ffffff", |
||||
zIndex: 9999 |
||||
}; |
||||
|
||||
class DialogBottom extends Component { |
||||
|
||||
state = { |
||||
tableHeight: 150, |
||||
resizableWidth: "100%", |
||||
resizableHeight: 300, |
||||
maximizeTitle: "maximize" |
||||
} |
||||
|
||||
setMapTableWindow = (type) => { |
||||
console.log('setMapTableWindow', type); |
||||
if (type === 'min') { |
||||
this.setState({ resizableHeight: 55, tableHeight: 150 }); |
||||
} |
||||
else if (type === "max") { |
||||
if (this.state.resizableHeight === 725) { |
||||
// restore (back to default)
|
||||
this.setState({ resizableHeight: 300, tableHeight: 150, maximizeTitle: "maximize" }); |
||||
} |
||||
else { |
||||
// maximize
|
||||
this.setState({ resizableHeight: 725, tableHeight: 950, maximizeTitle: "restore" }); |
||||
} |
||||
|
||||
} |
||||
} |
||||
render() { |
||||
const { isCloseDialog, itemDialog, dataTable } = this.props |
||||
const { resizableHeight } = this.state |
||||
// console.log('dataTable', dataTable.length)
|
||||
// console.log('itemDialog', itemDialog)
|
||||
console.log(`resizableHeight`, resizableHeight) |
||||
return ( |
||||
<Resizable |
||||
style={style} |
||||
size={{ |
||||
width: this.state.resizableWidth, |
||||
height: this.state.resizableHeight |
||||
}} |
||||
maxHeight={625} |
||||
enable={{ top: true, right: false, bottom: false, left: false, topRight: false, bottomRight: false, bottomLeft: false, topLeft: false }} |
||||
onResizeStop={(e, direction, ref, d) => { |
||||
// console.log('onResizeStop,e,direction,ref,d', { e, direction, ref, d })
|
||||
this.setState({ |
||||
resizableWidth: "100%", // to keep always full width
|
||||
resizableHeight: this.state.resizableHeight + d.height |
||||
}); |
||||
|
||||
// if drag the table header
|
||||
if (e.screenY < 100) { |
||||
this.setState({ tableHeight: 450 }) |
||||
} |
||||
else if (e.screenY < 150) { |
||||
this.setState({ tableHeight: 400 }) |
||||
} |
||||
else if (e.screenY < 200) { |
||||
this.setState({ tableHeight: 350 }) |
||||
} |
||||
else if (e.screenY < 250) { |
||||
this.setState({ tableHeight: 300 }) |
||||
} |
||||
else if (e.screenY < 300) { |
||||
this.setState({ tableHeight: 250 }) |
||||
} |
||||
else if (e.screenY < 400) { |
||||
this.setState({ tableHeight: 200 }) |
||||
} |
||||
else if (e.screenY < 600) { |
||||
this.setState({ tableHeight: 150 }) // default
|
||||
} |
||||
else if (e.screenY >= 600) { |
||||
// this.props.toggleMapTable(); // close the MapTable
|
||||
this.setMapTableWindow('min'); |
||||
} |
||||
}} |
||||
> |
||||
<div style={{ paddingTop: 10, position: "relative", height: "100%" }}> |
||||
<Row className="maptable-header"> |
||||
<Col md={9}> |
||||
{/* <p className="maptable-title">{itemDialog.title}</p> */} |
||||
</Col> |
||||
<Col md={3} style={{ paddingLeft: '15%' }} className="maptable-window-button-container"> |
||||
<span className="maptable-minimize" title="minimize" |
||||
onClick={() => this.setMapTableWindow("min")} |
||||
> |
||||
<Icon icon={removeCircleOutline} width={30} height={30} /> |
||||
</span> |
||||
<span className="maptable-maximize" title={this.state.maximizeTitle} |
||||
onClick={() => this.setMapTableWindow("max")} |
||||
> |
||||
<Icon icon={windowMaximaze} width={30} height={30} /> |
||||
</span> |
||||
<span className="maptable-close" title="close" |
||||
onClick={() => isCloseDialog()} |
||||
> |
||||
<Icon icon={closeCircleOutline} width={30} height={30} /> |
||||
</span> |
||||
</Col> |
||||
</Row> |
||||
{itemDialog.key === "presensi" && ( |
||||
<Card style={{ margin: 10 }}> |
||||
<CardHeader> |
||||
<b>Daftar Kehadiran Karyawan Hari Ini</b> |
||||
</CardHeader> |
||||
<CardBody style={{ overflowY: 'auto', height: resizableHeight === 300 ? 200 : 510 }}> |
||||
{dataTable.length === 0 ?
|
||||
<Table> |
||||
<tr> |
||||
<td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td> |
||||
</tr> |
||||
</Table> |
||||
:
|
||||
<Table> |
||||
<thead> |
||||
<tr> |
||||
<th>#</th> |
||||
<th>Nama Karyawan</th> |
||||
<th>Jam Masuk</th> |
||||
<th>Jam Keluar</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody > |
||||
{dataTable.map((item, index) => {
|
||||
return ( |
||||
<tr key={index}> |
||||
<td>{++index}</td> |
||||
<td>{item.employee_name}</td> |
||||
<td>{item.clock_time ? moment(item.clock_time).format('DD-MM-YYYY HH:mm') : "-"}</td> |
||||
<td>{item.clock_out_time ? moment(item.clock_out_time).format('DD-MM-YYYY HH:mm') : "-"}</td> |
||||
</tr> |
||||
) |
||||
})} |
||||
</tbody> |
||||
</Table> |
||||
} |
||||
</CardBody> |
||||
</Card> |
||||
)} |
||||
{itemDialog.key === "karyawan telat" && ( |
||||
<Card style={{ margin: 10 }}> |
||||
<CardHeader> |
||||
<b>Daftar Karyawan Telat Hari Ini</b> |
||||
</CardHeader> |
||||
<CardBody style={{ overflowY: 'auto', height: resizableHeight === 300 ? 200 : 510 }}> |
||||
{dataTable.length === 0 ?
|
||||
<Table> |
||||
<tr> |
||||
<td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td> |
||||
</tr> |
||||
</Table> |
||||
:
|
||||
<Table> |
||||
<thead> |
||||
<tr> |
||||
<th>#</th> |
||||
<th>Nama Karyawan</th> |
||||
<th>Jam Masuk</th> |
||||
<th>Jam Keluar</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody > |
||||
{dataTable.map((item, index) => {
|
||||
return ( |
||||
<tr key={index}> |
||||
<td>{++index}</td> |
||||
<td>{item.employee_name}</td> |
||||
<td>{item.clock_time ? moment(item.clock_time).format('DD-MM-YYYY HH:mm') : "-"}</td> |
||||
<td>{item.clock_out_time ? moment(item.clock_out_time).format('DD-MM-YYYY HH:mm') : "-"}</td> |
||||
</tr> |
||||
) |
||||
})} |
||||
</tbody> |
||||
</Table> |
||||
} |
||||
</CardBody> |
||||
</Card> |
||||
)} |
||||
{itemDialog.key === "total karyawan" && ( |
||||
<Card style={{ margin: 10 }}> |
||||
<CardHeader> |
||||
<b>Daftar Total Karyawan</b> |
||||
</CardHeader> |
||||
<CardBody style={{ overflowY: 'auto', height: resizableHeight === 300 ? 200 : 510 }}> |
||||
{dataTable.length === 0 ?
|
||||
<Table> |
||||
<tr> |
||||
<td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td> |
||||
</tr> |
||||
</Table> |
||||
:
|
||||
<Table> |
||||
<thead> |
||||
<tr> |
||||
<th>#</th> |
||||
<th>Devisi</th> |
||||
<th>Nama Karyawan</th> |
||||
<th>Jenis Kelamin</th> |
||||
<th>No HP</th> |
||||
<th>Alamat</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody > |
||||
{dataTable.map((item, index) => {
|
||||
return ( |
||||
<tr key={index}> |
||||
<td>{++index}</td> |
||||
<td>{item.devisi_name}</td> |
||||
<td>{item.name}</td> |
||||
<td>{item.gender == "P" ? "Perempuan" : "Laki-laki"}</td> |
||||
<td>{item.phone_number}</td> |
||||
<td>{item.address}</td> |
||||
</tr> |
||||
) |
||||
})} |
||||
</tbody> |
||||
</Table> |
||||
} |
||||
</CardBody> |
||||
</Card> |
||||
)} |
||||
{itemDialog.key === "absent" && ( |
||||
<Card style={{ margin: 10 }}> |
||||
<CardHeader> |
||||
<b>Daftar Karyawan Absent Hari ini </b> |
||||
</CardHeader> |
||||
<CardBody style={{ overflowY: 'auto', height: resizableHeight === 300 ? 200 : 510 }}> |
||||
{dataTable.length === 0 ?
|
||||
<Table> |
||||
<tr> |
||||
<td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td> |
||||
</tr> |
||||
</Table> |
||||
:
|
||||
<Table> |
||||
<thead> |
||||
<tr> |
||||
<th>#</th> |
||||
<th>Nama Karyawan</th> |
||||
<th>Jam Masuk</th> |
||||
<th>Jam Keluar</th> |
||||
</tr> |
||||
</thead> |
||||
</Table>} |
||||
|
||||
</CardBody> |
||||
</Card> |
||||
)} |
||||
{itemDialog.key === "karyawan tanpa keterangan" && ( |
||||
<Card style={{ margin: 10 }}> |
||||
<CardHeader> |
||||
<b>Daftar Karyawan Tanpa Keterangan</b> |
||||
</CardHeader> |
||||
<CardBody style={{ overflowY: 'auto', height: resizableHeight === 300 ? 200 : 510 }}> |
||||
{dataTable.length === 0 ?
|
||||
<Table> |
||||
<tr> |
||||
<td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td> |
||||
</tr> |
||||
</Table> |
||||
:
|
||||
<Table> |
||||
<thead> |
||||
<tr> |
||||
<th>#</th> |
||||
<th>Devisi</th> |
||||
<th>Nama Karyawan</th> |
||||
<th>Jenis Kelamin</th> |
||||
<th>No HP</th> |
||||
<th>Alamat</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody > |
||||
{dataTable.map((item, index) => {
|
||||
return ( |
||||
<tr key={index}> |
||||
<td>{++index}</td> |
||||
<td>{item.devisi_name}</td> |
||||
<td>{item.name}</td> |
||||
<td>{item.gender == "P" ? "Perempuan" : "Laki-laki"}</td> |
||||
<td>{item.phone_number}</td> |
||||
<td>{item.address}</td> |
||||
</tr> |
||||
) |
||||
})} |
||||
</tbody> |
||||
</Table> |
||||
} |
||||
</CardBody> |
||||
</Card> |
||||
)} |
||||
{itemDialog.key === "panic button" && ( |
||||
<Card style={{ margin: 10 }}> |
||||
<CardHeader> |
||||
<b>Daftar Karyawan Melakukan Panik Button Hari Ini</b> |
||||
</CardHeader> |
||||
<CardBody style={{ overflowY: 'auto', height: resizableHeight === 300 ? 200 : 510 }}> |
||||
{dataTable.length === 0 ?
|
||||
<Table> |
||||
<tr> |
||||
<td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td> |
||||
</tr> |
||||
</Table> |
||||
:
|
||||
<Table> |
||||
<thead> |
||||
<tr> |
||||
<th>#</th> |
||||
<th>Nama Karyawan</th> |
||||
<th>Jam Masuk</th> |
||||
<th>Jam Keluar</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody > |
||||
{dataTable.map((item, index) => {
|
||||
return ( |
||||
<tr key={index}> |
||||
<td>{++index}</td> |
||||
<td>{item.employee_name}</td> |
||||
<td>{item.clock_time ? moment(item.clock_time).format('DD-MM-YYYY HH:mm') : "-"}</td> |
||||
<td>{item.clock_out_time ? moment(item.clock_out_time).format('DD-MM-YYYY HH:mm') : "-"}</td> |
||||
</tr> |
||||
) |
||||
})} |
||||
</tbody> |
||||
</Table> |
||||
} |
||||
</CardBody> |
||||
</Card> |
||||
)} |
||||
</div> |
||||
</Resizable> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default DialogBottom |
@ -0,0 +1,6 @@
|
||||
{ |
||||
"name": "DailyInfo", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./DailyInfo.js" |
||||
} |