diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/DeviceTypes/DeviceTypesTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/DeviceTypes/DeviceTypesTable.js
index ee5bed4129..5e1a5494ca 100644
--- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/DeviceTypes/DeviceTypesTable.js
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/DeviceTypes/DeviceTypesTable.js
@@ -77,7 +77,6 @@ class DeviceTypesTable extends React.Component {
pagination,
});
}
- console.log(JSON.parse(res.data.data))
}).catch((error) => {
if (error.hasOwnProperty("response") && error.response.status === 401) {
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/ReportDevicesTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/ReportDevicesTable.js
index 5d24e85986..80f577bcb8 100644
--- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/ReportDevicesTable.js
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/ReportDevicesTable.js
@@ -151,7 +151,7 @@ class ReportDeviceTable extends React.Component {
if(prevProps.paramsObject !== this.props.paramsObject){
this.fetch();
}
- }
+ }
//fetch data from api
fetch = (params = {}) => {
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/PoliciesTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/PoliciesTable.js
new file mode 100644
index 0000000000..29394b9cde
--- /dev/null
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/PoliciesTable.js
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
+ *
+ * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from "react";
+import axios from "axios";
+import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider} from "antd";
+import TimeAgo from 'javascript-time-ago'
+
+// Load locale-specific relative date/time formatting rules.
+import en from 'javascript-time-ago/locale/en'
+import {withConfigContext} from "../../context/ConfigContext";
+
+const {Text} = Typography;
+
+let config = null;
+let apiUrl;
+
+const columns = [
+ {
+ title: 'Policy Name',
+ dataIndex: 'policyName',
+ width: 100,
+ },
+ {
+ title: 'Description',
+ dataIndex: 'description',
+ key: 'description',
+ // render: enrolmentInfo => enrolmentInfo.owner
+ // todo add filtering options
+ },
+ {
+ title: 'Compilance',
+ dataIndex: 'compliance',
+ key: 'compliance',
+ // render: enrolmentInfo => enrolmentInfo.ownership
+ // todo add filtering options
+ },
+ {
+ title: 'Policy Type',
+ dataIndex: 'policyType',
+ key: 'policyType',
+ // render: enrolmentInfo => enrolmentInfo.ownership
+ // todo add filtering options
+ }
+];
+
+const getTimeAgo = (time) => {
+ const timeAgo = new TimeAgo('en-US');
+ return timeAgo.format(time);
+};
+
+class PoliciesTable extends React.Component {
+ constructor(props) {
+ super(props);
+ config = this.props.context;
+ TimeAgo.addLocale(en);
+ this.state = {
+ data: [],
+ pagination: {},
+ loading: false,
+ selectedRows: []
+ };
+ }
+
+ rowSelection = {
+ onChange: (selectedRowKeys, selectedRows) => {
+ this.setState({
+ selectedRows: selectedRows
+ })
+ }
+ };
+
+ componentDidMount() {
+ this.fetchGroups();
+ }
+
+ //fetch data from api
+ fetchGroups = (params = {}) => {
+ const config = this.props.context;
+ this.setState({loading: true});
+
+ // get current page
+ const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
+
+ const extraParams = {
+ offset: 10 * (currentPage - 1), //calculate the offset
+ limit: 10,
+ };
+
+ const encodedExtraParams = Object.keys(extraParams)
+ .map(key => key + '=' + extraParams[key]).join('&');
+
+ apiUrl = window.location.origin + config.serverConfig.invoker.uri +
+ config.serverConfig.invoker.deviceMgt +
+ "/policies?" + encodedExtraParams;
+
+ //send request to the invokerss
+ axios.get(apiUrl).then(res => {
+ if (res.status === 200) {
+ const pagination = {...this.state.pagination};
+ this.setState({
+ loading: false,
+ data: res.data.data.policies,
+ pagination,
+ });
+ }
+
+ }).catch((error) => {
+ if (error.hasOwnProperty("response") && error.response.status === 401) {
+ //todo display a popop with error
+ message.error('You are not logged in');
+ window.location.href = window.location.origin + '/entgra/login';
+ } else {
+ notification["error"]({
+ message: "There was a problem",
+ duration: 0,
+ description:"Error occurred while trying to load policies.",
+ });
+ }
+
+ this.setState({loading: false});
+ });
+ };
+
+ handleTableChange = (pagination, filters, sorter) => {
+ const pager = {...this.state.pagination};
+ pager.current = pagination.current;
+ this.setState({
+ pagination: pager,
+ });
+ this.fetch({
+ results: pagination.pageSize,
+ page: pagination.current,
+ sortField: sorter.field,
+ sortOrder: sorter.order,
+ ...filters,
+ });
+ };
+
+ render() {
+
+ const {data, pagination, loading, selectedRows} = this.state;
+ return (
+
+
(record.id)}
+ dataSource={data}
+ pagination={{
+ ...pagination,
+ size: "small",
+ // position: "top",
+ showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups`
+ // showQuickJumper: true
+ }}
+ loading={loading}
+ onChange={this.handleTableChange}
+ rowSelection={this.rowSelection}
+ scroll={{x: 1000}}
+ />
+
+ );
+ }
+}
+
+export default withConfigContext(PoliciesTable);
\ No newline at end of file
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersDevices.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersDevices.js
new file mode 100644
index 0000000000..13ce62e98e
--- /dev/null
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersDevices.js
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
+ *
+ * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from "react";
+import axios from "axios";
+import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider} from "antd";
+import TimeAgo from 'javascript-time-ago'
+
+// Load locale-specific relative date/time formatting rules.
+import en from 'javascript-time-ago/locale/en'
+import {withConfigContext} from "../../context/ConfigContext";
+
+const {Text} = Typography;
+
+let config = null;
+let apiUrl;
+
+const columns = [
+ {
+ title: 'Device',
+ dataIndex: 'name',
+ width: 100,
+ },
+ {
+ title: 'Type',
+ dataIndex: 'type',
+ key: 'type',
+ render: type => {
+ const defaultPlatformIcons = config.defaultPlatformIcons;
+ let icon = defaultPlatformIcons.default.icon;
+ let color = defaultPlatformIcons.default.color;
+ let theme = defaultPlatformIcons.default.theme;
+
+ if (defaultPlatformIcons.hasOwnProperty(type)) {
+ icon = defaultPlatformIcons[type].icon;
+ color = defaultPlatformIcons[type].color;
+ theme = defaultPlatformIcons[type].theme;
+ }
+
+ return (
+
+
+
+ );
+ }
+ // todo add filtering options
+ },
+ {
+ title: 'Owner',
+ dataIndex: 'enrolmentInfo',
+ key: 'owner',
+ render: enrolmentInfo => enrolmentInfo.owner
+ // todo add filtering options
+ },
+ {
+ title: 'Ownership',
+ dataIndex: 'enrolmentInfo',
+ key: 'ownership',
+ width: 100,
+ render: enrolmentInfo => enrolmentInfo.ownership
+ // todo add filtering options
+ },
+ {
+ title: 'Status',
+ dataIndex: 'enrolmentInfo',
+ width: 100,
+ key: 'status',
+ render: (enrolmentInfo) => {
+ const status = enrolmentInfo.status.toLowerCase();
+ let color = "#f9ca24";
+ switch (status) {
+ case "active":
+ color = "#badc58";
+ break;
+ case "created":
+ color = "#6ab04c";
+ break;
+ case "removed":
+ color = "#ff7979";
+ break;
+ case "inactive":
+ color = "#f9ca24";
+ break;
+ case "blocked":
+ color = "#636e72";
+ break;
+ }
+ return {status};
+ }
+ // todo add filtering options
+ },
+ {
+ title: 'Last Updated',
+ dataIndex: 'enrolmentInfo',
+ key: 'dateOfLastUpdate',
+ render: (data) => {
+ const {dateOfLastUpdate} = data;
+ const timeAgoString = getTimeAgo(dateOfLastUpdate);
+ return {timeAgoString};
+ }
+ // todo add filtering options
+ }
+];
+
+const getTimeAgo = (time) => {
+ const timeAgo = new TimeAgo('en-US');
+ return timeAgo.format(time);
+};
+
+class UsersDevices extends React.Component {
+ constructor(props) {
+ super(props);
+ config = this.props.context;
+ TimeAgo.addLocale(en);
+ this.state = {
+ data: [],
+ pagination: {},
+ loading: false,
+ selectedRows: []
+ };
+ }
+
+ rowSelection = {
+ onChange: (selectedRowKeys, selectedRows) => {
+ this.setState({
+ selectedRows: selectedRows
+ })
+ }
+ };
+
+ componentDidMount() {
+ this.fetch();
+ }
+
+ //Rerender component when parameters change
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ if(prevProps.user !== this.props.user){
+ this.fetch();
+ }
+ }
+
+ //fetch data from api
+ fetch = (params = {}) => {
+ const config = this.props.context;
+ this.setState({loading: true});
+ // get current page
+ const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
+
+ const extraParams = {
+ offset: 10 * (currentPage - 1), //calculate the offset
+ limit: 10,
+ user: this.props.user,
+ requireDeviceInfo: true,
+ };
+
+ const encodedExtraParams = Object.keys(extraParams)
+ .map(key => key + '=' + extraParams[key]).join('&');
+
+ //send request to the invoker
+ axios.get(
+ window.location.origin + config.serverConfig.invoker.uri +
+ config.serverConfig.invoker.deviceMgt +
+ "/devices?" + encodedExtraParams,
+ ).then(res => {
+ if (res.status === 200) {
+ const pagination = {...this.state.pagination};
+ this.setState({
+ loading: false,
+ data: res.data.data.devices,
+ pagination
+ });
+ }
+
+ }).catch((error) => {
+ if (error.hasOwnProperty("response") && error.response.status === 401) {
+ //todo display a popop with error
+ message.error('You are not logged in');
+ window.location.href = window.location.origin + '/entgra/login';
+ } else {
+ notification["error"]({
+ message: "There was a problem",
+ duration: 0,
+ description:
+ "Error occurred while trying to load devices.",
+ });
+ }
+
+ this.setState({loading: false});
+ });
+ };
+
+ handleTableChange = (pagination, filters, sorter) => {
+ const pager = {...this.state.pagination};
+ pager.current = pagination.current;
+ this.setState({
+ pagination: pager,
+ });
+ this.fetch({
+ results: pagination.pageSize,
+ page: pagination.current,
+ sortField: sorter.field,
+ sortOrder: sorter.order,
+ ...filters,
+ });
+ };
+
+ render() {
+
+ const {data, pagination, loading, selectedRows} = this.state;
+ return (
+
+
(record.deviceIdentifier + record.enrolmentInfo.owner + record.enrolmentInfo.ownership)}
+ dataSource={data}
+ showHeader={false}
+ size="small"
+ pagination={{
+ ...pagination,
+ size: "small",
+ // position: "top",
+ showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} devices`
+ // showQuickJumper: true
+ }}
+ loading={loading}
+ onChange={this.handleTableChange}
+ rowSelection={this.rowSelection}
+ scroll={{x: 1000}}
+ />
+
+ );
+ }
+}
+
+export default withConfigContext(UsersDevices);
\ No newline at end of file
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersTable.js
index beb34a94d6..ac7fc9c66a 100644
--- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersTable.js
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Users/UsersTable.js
@@ -18,12 +18,14 @@
import React from "react";
import axios from "axios";
-import {Tag, message, notification, Table, Typography, Tooltip, Icon, Divider, Card, Col, Row, Select} from "antd";
+import {message, notification, Table, Typography, Panel, Collapse, Button, List, Modal, Icon} from "antd";
import TimeAgo from 'javascript-time-ago'
// Load locale-specific relative date/time formatting rules.
import en from 'javascript-time-ago/locale/en'
import {withConfigContext} from "../../context/ConfigContext";
+import DeviceTable from "../Devices/DevicesTable";
+import UsersDevices from "./UsersDevices";
const {Text} = Typography;
@@ -39,10 +41,21 @@ class UsersTable extends React.Component {
data: [],
pagination: {},
loading: false,
- selectedRows: []
+ selectedRows: [],
+ rolesModalVisible: false,
+ rolesData: [],
+ user:''
};
}
+ rowSelection = {
+ onChange: (selectedRowKeys, selectedRows) => {
+ this.setState({
+ selectedRows: selectedRows
+ })
+ }
+ };
+
componentDidMount() {
this.fetchUsers();
}
@@ -65,7 +78,7 @@ class UsersTable extends React.Component {
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
config.serverConfig.invoker.deviceMgt +
- "/users";
+ "/users?" + encodedExtraParams;
//send request to the invokerss
axios.get(apiUrl).then(res => {
@@ -95,6 +108,44 @@ class UsersTable extends React.Component {
});
};
+ //fetch data from api
+ fetchRoles = (username) => {
+ const config = this.props.context;
+
+ this.setState({
+ rolesModalVisible: true,
+ user: username
+ });
+
+ apiUrl = window.location.origin + config.serverConfig.invoker.uri +
+ config.serverConfig.invoker.deviceMgt +
+ "/users/" + username + "/roles";
+
+ //send request to the invokerss
+ axios.get(apiUrl).then(res => {
+ if (res.status === 200) {
+ this.setState({
+ rolesData: res.data.data.roles,
+ });
+ }
+
+ }).catch((error) => {
+ if (error.hasOwnProperty("response") && error.response.status === 401) {
+ //todo display a popop with error
+ message.error('You are not logged in');
+ window.location.href = window.location.origin + '/entgra/login';
+ } else {
+ notification["error"]({
+ message: "There was a problem",
+ duration: 0,
+ description:"Error occurred while trying to load roles.",
+ });
+ }
+
+ this.setState({loading: false});
+ });
+ };
+
handleTableChange = (pagination, filters, sorter) => {
const pager = {...this.state.pagination};
pager.current = pagination.current;
@@ -110,22 +161,102 @@ class UsersTable extends React.Component {
});
};
+ handleOk = e => {
+ this.setState({
+ rolesModalVisible: false,
+ });
+ };
+
+ handleCancel = e => {
+ this.setState({
+ rolesModalVisible: false,
+ });
+ };
+
render() {
const {data, pagination, loading, selectedRows} = this.state;
-
- const itemCard = data.map((data) =>
-
-
- {data.username}
-
-
- );
+ const { Panel } = Collapse;
+ const columns = [
+ {
+ title: 'User Name',
+ dataIndex: 'username',
+ width: 150,
+ key: "username",
+ },
+ {
+ title: 'First Name',
+ width: 150,
+ dataIndex: 'firstname',
+ key: 'firstname',
+ },
+ {
+ title: 'Last Name',
+ width: 150,
+ dataIndex: 'lastname',
+ key: 'lastname',
+ },
+ {
+ title: 'Email',
+ width: 100,
+ dataIndex: 'emailAddress',
+ key: 'emailAddress',
+ },
+ {
+ title: '',
+ dataIndex: 'username',
+ key: 'roles',
+ render: (username) =>
+
+ }
+ ];
return (
-
-
- {itemCard}
-
+
+
+
(record.username)}
+ dataSource={data}
+ pagination={{
+ ...pagination,
+ size: "small",
+ // position: "top",
+ showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups`
+ // showQuickJumper: true
+ }}
+ loading={loading}
+ onChange={this.handleTableChange}
+ rowSelection={this.rowSelection}
+ scroll={{x: 1000}}
+ />
+
+
+
+
+
+ {item}}
+ />
+
+
+
+
+
+
+
);
}
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Groups/Groups.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Groups/Groups.js
index e17cac8665..b96f869872 100644
--- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Groups/Groups.js
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Groups/Groups.js
@@ -54,6 +54,9 @@ class Groups extends React.Component {
+
+
+
);
}
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Policies/Policies.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Policies/Policies.js
index bedaff0b57..7c32b7a0a2 100644
--- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Policies/Policies.js
+++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/pages/Dashboard/Policies/Policies.js
@@ -24,6 +24,7 @@ import {
Icon
} from "antd";
import {Link} from "react-router-dom";
+import PoliciesTable from "../../../components/Policies/PoliciesTable";
const {Paragraph} = Typography;
@@ -50,9 +51,12 @@ class Policies extends React.Component {
All policies for device management
+
+
+
);
}