diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js index 90fb75fcd31..b2f485e77b5 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js @@ -23,15 +23,7 @@ import App from './App'; import Login from './scenes/Login'; import Home from './scenes/Home'; import './index.css'; -import Reports from './scenes/Home/scenes/Reports'; -import EnrollmentsVsUnenrollmentsReport from './scenes/Home/scenes/Reports/scenes/EnrolmentVsUnenrollments'; -import EnrollmentTypeReport from './scenes/Home/scenes/Reports/scenes/EnrollmentType'; -import PolicyReport from './scenes/Home/scenes/Reports/scenes/PolicyCompliance'; -import DeviceStatusReport from './scenes/Home/scenes/Reports/scenes/DeviceStatus'; -import AppNotInstalledDevicesReport from './scenes/Home/scenes/Reports/scenes/AppNotInstalledDevices'; import Geo from './scenes/Home/scenes/Geo'; -import EncryptionStatus from './scenes/Home/scenes/Reports/scenes/EncryptionStatus'; -import OutdatedOSversionReport from './scenes/Home/scenes/Reports/scenes/OutdatedOSVersion'; import Notifications from './scenes/Home/scenes/Notifications'; import DeviceEnroll from './scenes/Home/scenes/Devices/scenes/Enroll'; import Groups from './scenes/Home/scenes/Groups'; @@ -71,11 +63,6 @@ const routes = [ component: Geo, exact: true, }, - { - path: '/entgra/reports', - component: Reports, - exact: true, - }, { path: '/entgra/groups', component: Groups, @@ -126,41 +113,6 @@ const routes = [ component: Notifications, exact: true, }, - { - path: '/entgra/reports/enrollments', - component: EnrollmentsVsUnenrollmentsReport, - exact: true, - }, - { - path: '/entgra/reports/expired-devices', - component: OutdatedOSversionReport, - exact: true, - }, - { - path: '/entgra/reports/enrollment-type', - component: EnrollmentTypeReport, - exact: true, - }, - { - path: '/entgra/reports/policy/compliance', - component: PolicyReport, - exact: true, - }, - { - path: '/entgra/reports/device-status', - component: DeviceStatusReport, - exact: true, - }, - { - path: '/entgra/reports/app-not-installed', - component: AppNotInstalledDevicesReport, - exact: true, - }, - { - path: '/entgra/reports/encryption-status', - component: EncryptionStatus, - exact: true, - }, ], }, ]; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/components/DevicesTable/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/components/DevicesTable/index.js similarity index 98% rename from components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/components/DevicesTable/index.js rename to components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/components/DevicesTable/index.js index bc283b737dd..79ad40585f8 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/components/DevicesTable/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/components/DevicesTable/index.js @@ -22,7 +22,7 @@ import { Icon, message, notification, Table, Tag, Tooltip } 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 '../../../../../../components/ConfigContext'; +import { withConfigContext } from '../../../../components/ConfigContext'; let config = null; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/index.js index ab941cfb232..9dfb1b4e7a2 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/index.js @@ -58,7 +58,7 @@ class Home extends React.Component {
- + logo
@@ -91,12 +91,6 @@ class Home extends React.Component { - - - - Reports - - diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Groups/components/GroupsTable/components/GroupDevicesModal/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Groups/components/GroupsTable/components/GroupDevicesModal/index.js index c456b2e452e..f844b79db2b 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Groups/components/GroupsTable/components/GroupDevicesModal/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Groups/components/GroupsTable/components/GroupDevicesModal/index.js @@ -23,7 +23,7 @@ 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 '../../../../../../../../components/ConfigContext'; -import DevicesTable from '../../../../../Reports/components/DevicesTable'; +import DevicesTable from '../../../../../../components/DevicesTable'; let apiUrl; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/AddPolicy/components/ConfigureProfile/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/AddPolicy/components/ConfigureProfile/index.js index 9e6fedb7e92..b8af15f553e 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/AddPolicy/components/ConfigureProfile/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/AddPolicy/components/ConfigureProfile/index.js @@ -46,6 +46,7 @@ const { Option } = Select; const { TextArea } = Input; const subPanelpayloadAttributes = {}; +let formContainers = {}; class ConfigureProfile extends React.Component { constructor(props) { @@ -303,7 +304,7 @@ class ConfigureProfile extends React.Component { onHandleContinue = (e, formname) => { const allFields = this.props.form.getFieldsValue(); let activeFields = []; - // get currently active field list + let subContentsList = {}; for (let i = 0; i < this.state.activePanelKeys.length; i++) { Object.keys(allFields).map(key => { if (key.includes(`${this.state.activePanelKeys[i]}-`)) { @@ -312,14 +313,16 @@ class ConfigureProfile extends React.Component { `${this.state.activePanelKeys[i]}`, ) ) { - Object.keys( + Object.entries( subPanelpayloadAttributes[this.state.activePanelKeys[i]], - ).map(subPanel => { - if (`${this.state.activePanelKeys[i]}-${subPanel}` === true) { - if (key.includes(`-${subPanel}-`)) { - activeFields.push(key); - } - } else if (!key.includes(`-${subPanel}-`)) { + ).map(([subPanel, subContent]) => { + subContentsList[subContent] = {}; + if ( + allFields[`${this.state.activePanelKeys[i]}-${subPanel}`] === + true + ) { + activeFields.push(key); + } else if (!key.includes(`-${subPanel}`)) { activeFields.push(key); } }); @@ -337,17 +340,67 @@ class ConfigureProfile extends React.Component { let content = {}; Object.entries(values).map(([key, value]) => { if (key.includes(`${this.state.activePanelKeys[i]}-`)) { - content[ - key.replace(`${this.state.activePanelKeys[i]}-`, '') - ] = value; + if ( + subPanelpayloadAttributes.hasOwnProperty( + `${this.state.activePanelKeys[i]}`, + ) + ) { + Object.entries( + subPanelpayloadAttributes[this.state.activePanelKeys[i]], + ).map(([subPanel, contentKey]) => { + if (key.includes(`-${subPanel}-`)) { + subContentsList[contentKey][ + key.replace( + `${this.state.activePanelKeys[i]}-${subPanel}-`, + '', + ) + ] = value; + content = { ...content, ...subContentsList }; + } else { + content[ + key.replace(`${this.state.activePanelKeys[i]}-`, '') + ] = value; + } + }); + } else if (this.state.activePanelKeys[i] in formContainers) { + formContainers[this.state.activePanelKeys[i]].forEach( + subFeature => { + if ( + key.includes( + `${this.state.activePanelKeys[i]}-${subFeature}-`, + ) + ) { + let subFormContent = {}; + subFormContent[ + key.replace( + `${this.state.activePanelKeys[i]}-${subFeature}-`, + '', + ) + ] = value; + let feature = { + featureCode: subFeature, + deviceType: 'android', + content: subFormContent, + }; + profileFeaturesList.push(feature); + } + }, + ); + } else { + content[ + key.replace(`${this.state.activePanelKeys[i]}-`, '') + ] = value; + } } }); - let feature = { - featureCode: this.state.activePanelKeys[i], - deviceType: 'android', - content: content, - }; - profileFeaturesList.push(feature); + if (!(this.state.activePanelKeys[i] in formContainers)) { + let feature = { + featureCode: this.state.activePanelKeys[i], + deviceType: 'android', + content: content, + }; + profileFeaturesList.push(feature); + } } this.props.getPolicyPayloadData(formname, profileFeaturesList); this.props.getNextStep(); @@ -751,6 +804,7 @@ class ConfigureProfile extends React.Component { {element.name}} key={i}> {Object.values(element.panels).map((panel, j) => { panel = panel.panel; + let subForms = []; return (
{Object.values(panel.subFormLists).map( (form, i) => { + subForms.push(form.id); + formContainers[`${panel.panelId}`] = subForms; return (
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/EditPolicy/components/ConfigureProfile/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/EditPolicy/components/ConfigureProfile/index.js index 7766b8ac23e..bd2624e83df 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/EditPolicy/components/ConfigureProfile/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/EditPolicy/components/ConfigureProfile/index.js @@ -46,6 +46,7 @@ const { Option } = Select; const { TextArea } = Input; const subPanelpayloadAttributes = {}; +let subFormContainer = {}; class ConfigureProfile extends React.Component { constructor(props) { @@ -65,22 +66,57 @@ class ConfigureProfile extends React.Component { setProfileInfo = e => { let activePolicies = []; let activePolicyFields = {}; + let activeSubPanels = []; const allFields = this.props.form.getFieldsValue(); this.props.policyFeatureList.map(element => { activePolicies.push(element.featureCode); let featureData = JSON.parse(element.content); Object.keys(featureData).map(key => { - let regex = new RegExp(`${element.featureCode}.+${key}`, 'g'); - Object.keys(allFields).map(fieldName => { - if (fieldName.match(regex) != null) { - activePolicyFields[fieldName] = featureData[key]; - } - }); + if (element.featureCode in subPanelpayloadAttributes) { + Object.entries(subPanelpayloadAttributes[element.featureCode]).map( + ([panelKey, payloadAttr]) => { + if (key === payloadAttr) { + activeSubPanels.push(`${element.featureCode}-${panelKey}`); + } + }, + ); + + let regex = new RegExp(`${element.featureCode}.+${key}`, 'g'); + Object.keys(allFields).map(fieldName => { + if (fieldName.match(regex) != null) { + activePolicyFields[fieldName] = featureData[key]; + } + }); + } else if (element.featureCode in subFormContainer) { + let regex = new RegExp(`.+${element.featureCode}-${key}`, 'g'); + Object.keys(allFields).map(fieldName => { + if (fieldName.match(regex) != null) { + activePolicyFields[fieldName] = featureData[key]; + if ( + !activePolicies.includes( + fieldName.replace(`-${element.featureCode}-${key}`, ''), + ) + ) { + activePolicies.push( + fieldName.replace(`-${element.featureCode}-${key}`, ''), + ); + } + } + }); + } else { + let regex = new RegExp(`${element.featureCode}.+${key}`, 'g'); + Object.keys(allFields).map(fieldName => { + if (fieldName.match(regex) != null) { + activePolicyFields[fieldName] = featureData[key]; + } + }); + } }); }); this.props.form.setFieldsValue(activePolicyFields); this.setState({ activePanelKeys: activePolicies, + activeSubPanelKeys: activeSubPanels, }); }; @@ -795,6 +831,7 @@ class ConfigureProfile extends React.Component { @@ -829,6 +866,8 @@ class ConfigureProfile extends React.Component {
{Object.values(panel.subFormLists).map( (form, i) => { + subFormContainer[`${form.id}`] = + panel.panelId; return ( diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PoliciesTable/component/PolicyBulkActionBar/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PoliciesTable/component/PolicyBulkActionBar/index.js index 29643808051..c2751c20a0c 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PoliciesTable/component/PolicyBulkActionBar/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PoliciesTable/component/PolicyBulkActionBar/index.js @@ -65,7 +65,7 @@ class BulkActionBar extends React.Component { return (
-
+
+ > + APPLY CHANGES TO DEVICES +
@@ -110,7 +112,9 @@ class BulkActionBar extends React.Component { size={'default'} onClick={this.onCheckPolicyStatus} style={{ margin: '2px' }} - /> + > + Remove + @@ -135,7 +139,9 @@ class BulkActionBar extends React.Component { style={{ margin: '2px', }} - /> + > + Publish + @@ -158,7 +164,9 @@ class BulkActionBar extends React.Component { onClick={this.onCheckPolicyStatus} size={'default'} style={{ margin: '2px' }} - /> + > + Unpublish +
diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PolicyProfile/component/PolicyInfo/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PolicyProfile/component/PolicyInfo/index.js index 825897c830a..a24e6f5de88 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PolicyProfile/component/PolicyInfo/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Policies/components/PolicyProfile/component/PolicyInfo/index.js @@ -46,6 +46,7 @@ const { TextArea } = Input; const subPanelpayloadAttributes = {}; const fieldKeys = []; +let subFormContainer = {}; class PolicyInfo extends React.Component { constructor(props) { @@ -55,6 +56,7 @@ class PolicyInfo extends React.Component { data: {}, policyFeatureList: [], activePanelKeys: [], + activeSubPanelKeys: [], profilePreviewKey: '', customInputDataArray: [], inputTableDataSources: {}, @@ -65,22 +67,57 @@ class PolicyInfo extends React.Component { setProfileInfo = e => { let activePolicies = []; let activePolicyFields = {}; + let activeSubPanels = []; const allFields = this.props.form.getFieldsValue(); this.props.policyFeatureList.map(element => { activePolicies.push(element.featureCode); let featureData = JSON.parse(element.content); Object.keys(featureData).map(key => { - let regex = new RegExp(`${element.featureCode}.+${key}`, 'g'); - Object.keys(allFields).map(fieldName => { - if (fieldName.match(regex) != null) { - activePolicyFields[fieldName] = featureData[key]; - } - }); + if (element.featureCode in subPanelpayloadAttributes) { + Object.entries(subPanelpayloadAttributes[element.featureCode]).map( + ([panelKey, payloadAttr]) => { + if (key === payloadAttr) { + activeSubPanels.push(`${element.featureCode}-${panelKey}`); + } + }, + ); + + let regex = new RegExp(`${element.featureCode}.+${key}`, 'g'); + Object.keys(allFields).map(fieldName => { + if (fieldName.match(regex) != null) { + activePolicyFields[fieldName] = featureData[key]; + } + }); + } else if (element.featureCode in subFormContainer) { + let regex = new RegExp(`.+${element.featureCode}-${key}`, 'g'); + Object.keys(allFields).map(fieldName => { + if (fieldName.match(regex) != null) { + activePolicyFields[fieldName] = featureData[key]; + if ( + !activePolicies.includes( + fieldName.replace(`-${element.featureCode}-${key}`, ''), + ) + ) { + activePolicies.push( + fieldName.replace(`-${element.featureCode}-${key}`, ''), + ); + } + } + }); + } else { + let regex = new RegExp(`${element.featureCode}.+${key}`, 'g'); + Object.keys(allFields).map(fieldName => { + if (fieldName.match(regex) != null) { + activePolicyFields[fieldName] = featureData[key]; + } + }); + } }); }); this.props.form.setFieldsValue(activePolicyFields); this.setState({ activePanelKeys: activePolicies, + activeSubPanelKeys: activeSubPanels, }); }; @@ -235,7 +272,7 @@ class PolicyInfo extends React.Component { {getFieldDecorator(`${columnData.key}${i}`, { initialValue: columnData.others.initialDataIndex, })( - {columnData.others.option.map((option, i) => { return (
-
- -
-
- -
-
- ); - } -} - -export default withConfigContext(AppNotInstalledDevicesReport); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/DeviceStatus/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/DeviceStatus/index.js deleted file mode 100644 index 862c5200cde..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/DeviceStatus/index.js +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2020, 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 { PageHeader, Breadcrumb, Icon, Radio, Popover, Button } from 'antd'; - -import { Link } from 'react-router-dom'; -import { withConfigContext } from '../../../../../../components/ConfigContext'; -import axios from 'axios'; -import DateRangePicker from '../../components/DateRangePicker'; -import moment from 'moment'; -import { Chart, Geom, Axis, Tooltip, Legend } from 'bizcharts'; -import DataSet from '@antv/data-set'; -import { handleApiError } from '../../../../../../services/utils/errorHandler'; - -class DeviceStatusReport extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - this.state = { - paramsObject: { - from: moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - to: moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - }, - data: [], - fields: [], - durationMode: 'weekly', - visible: false, - }; - } - - handleDurationModeChange = e => { - const durationMode = e.target.value; - switch (durationMode) { - case 'daily': - this.updateDurationValue( - moment().format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'weekly': - this.updateDurationValue( - moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'monthly': - this.updateDurationValue( - moment() - .subtract(29, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - } - this.setState({ durationMode }); - }; - - handlePopoverVisibleChange = visible => { - this.setState({ visible }); - }; - - componentDidMount() { - this.fetchData(); - } - - // Get modified value from datepicker and set it to paramsObject - updateDurationValue = (modifiedFromDate, modifiedToDate) => { - let tempParamObj = this.state.paramsObject; - tempParamObj.from = modifiedFromDate; - tempParamObj.to = modifiedToDate; - this.setState({ paramsObject: tempParamObj }); - this.fetchData(); - }; - - // Call count APIs and get count for given parameters, then create data object to build pie chart - fetchData = () => { - this.setState({ loading: true }); - - const { paramsObject } = this.state; - const config = this.props.context; - - const encodedExtraParams = Object.keys(paramsObject) - .map(key => key + '=' + paramsObject[key]) - .join('&'); - - axios - .all([ - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?status=ACTIVE&' + - encodedExtraParams, - 'Active', - ), - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?status=INACTIVE&' + - encodedExtraParams, - 'Inactive', - ), - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?status=REMOVED&' + - encodedExtraParams, - 'Removed', - ), - ]) - .then(res => { - let keys = Object.keys(res[0].data.data); - let active = res[0].data.data; - let inactive = res[1].data.data; - let removed = res[2].data.data; - - if (Object.keys(active).length != 0) { - active.name = 'Active'; - inactive.name = 'Inactive'; - removed.name = 'Removed'; - } - - const finalData = [active, inactive, removed]; - - this.setState({ - data: finalData, - fields: keys, - }); - }) - .catch(error => { - handleApiError( - error, - 'Error occurred while trying to get device count.', - ); - }); - }; - - render() { - const { durationMode } = this.state; - - const ds = new DataSet(); - const dv = ds.createView().source(this.state.data); - dv.transform({ - type: 'fold', - fields: this.state.fields, - key: 'Time', - value: 'Number of Devices', - }); - - return ( -
- - - - - Home - - - - Reports - - Device Status Report - -
-

Device Status Report

- - - Today - Last Week - Last Month - - - - -
- } - visible={this.state.visible} - onVisibleChange={this.handlePopoverVisibleChange} - > - - - -
- - - - - - - -
-
- -
- - ); - } -} - -export default withConfigContext(DeviceStatusReport); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js deleted file mode 100644 index a18985d64b3..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2020, 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 { Icon, message, notification, Radio, Table, Tag, Tooltip } 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 '../../../../../../../../components/ConfigContext'; - -let config = null; - -const columns = [ - { - title: 'Device', - dataIndex: 'name', - }, - { - title: 'Type', - dataIndex: 'type', - key: 'type', - // eslint-disable-next-line react/display-name - 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', - render: enrolmentInfo => enrolmentInfo.ownership, - // todo add filtering options - }, - { - title: 'Status', - dataIndex: 'enrolmentInfo', - key: 'status', - // eslint-disable-next-line react/display-name - 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', - // eslint-disable-next-line react/display-name - 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 EncryptedDeviceTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, - loading: false, - isEncrypted: true, - }; - } - - componentDidMount() { - 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, - requireDeviceInfo: true, - isEncrypted: this.state.isEncrypted, - }; - - 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 + - '/reports/encryption-status?' + - 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, - }); - }; - - handleModeChange = value => { - this.setState( - { - isEncrypted: value.target.value, - }, - this.fetch, - ); - }; - - render() { - const { data, pagination, loading } = this.state; - - return ( -
- - Enabled Devices - Disabled Devices - -
- - record.deviceIdentifier + - record.enrolmentInfo.owner + - record.enrolmentInfo.ownership - } - dataSource={data} - pagination={{ - ...pagination, - size: 'small', - // position: "top", - showTotal: (total, range) => - `showing ${range[0]}-${range[1]} of ${total} devices`, - // showQuickJumper: true - }} - loading={loading} - onChange={this.handleTableChange} - /> - - - ); - } -} - -export default withConfigContext(EncryptedDeviceTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js deleted file mode 100644 index cd9f568ec73..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2020, 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 { PageHeader, Breadcrumb, Icon } from 'antd'; -import { Link } from 'react-router-dom'; -import EncryptedDeviceTable from './components/EncryptedDeviceTable/EncryptedDevicesTable'; - -class EncryptionStatus extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - } - render() { - return ( -
- - - - - Home - - - - Reports - - Encryption Status - -
-

Encryption Status Report

-
- -
-
-
- ); - } -} - -export default EncryptionStatus; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EnrollmentType/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EnrollmentType/index.js deleted file mode 100644 index 795c5daea70..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EnrollmentType/index.js +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2020, 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 { PageHeader, Breadcrumb, Icon, Radio, Popover, Button } from 'antd'; - -import { Link } from 'react-router-dom'; -import { withConfigContext } from '../../../../../../components/ConfigContext'; -import axios from 'axios'; -import DateRangePicker from '../../components/DateRangePicker'; -import moment from 'moment'; -import { Chart, Geom, Axis, Tooltip, Legend } from 'bizcharts'; -import DataSet from '@antv/data-set'; -import { handleApiError } from '../../../../../../services/utils/errorHandler'; - -class EnrollmentTypeReport extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - this.state = { - paramsObject: { - from: moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - to: moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - }, - data: [], - fields: [], - durationMode: 'weekly', - visible: false, - }; - } - - componentDidMount() { - this.fetchData(); - } - - handleDurationModeChange = e => { - const durationMode = e.target.value; - switch (durationMode) { - case 'daily': - this.updateDurationValue( - moment().format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'weekly': - this.updateDurationValue( - moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'monthly': - this.updateDurationValue( - moment() - .subtract(29, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - } - this.setState({ durationMode }); - }; - - handlePopoverVisibleChange = visible => { - this.setState({ visible }); - }; - - // Get modified value from datepicker and set it to paramsObject - updateDurationValue = (modifiedFromDate, modifiedToDate) => { - let tempParamObj = this.state.paramsObject; - tempParamObj.from = modifiedFromDate; - tempParamObj.to = modifiedToDate; - this.setState({ paramsObject: tempParamObj }); - this.fetchData(); - }; - - // Call count APIs and get count for given parameters, then create data object to build pie chart - fetchData = () => { - this.setState({ loading: true }); - - const { paramsObject } = this.state; - const config = this.props.context; - - const encodedExtraParams = Object.keys(paramsObject) - .map(key => key + '=' + paramsObject[key]) - .join('&'); - - axios - .all([ - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?ownership=BYOD&' + - encodedExtraParams, - 'BYOD', - ), - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?ownership=COPE&' + - encodedExtraParams, - 'COPE', - ), - ]) - .then(res => { - let keys = Object.keys(res[0].data.data); - let byod = res[0].data.data; - let cope = res[1].data.data; - if (Object.keys(byod).length != 0) { - byod.name = 'BYOD'; - cope.name = 'COPE'; - } - - const finalData = [byod, cope]; - - this.setState({ - data: finalData, - fields: keys, - }); - }) - .catch(error => { - handleApiError( - error, - 'Error occurred while trying to get device count.', - ); - }); - }; - - render() { - const { durationMode } = this.state; - - const ds = new DataSet(); - const dv = ds.createView().source(this.state.data); - dv.transform({ - type: 'fold', - fields: this.state.fields, - key: 'Time', - value: 'Number of Devices', - }); - - return ( -
- - - - - Home - - - - Reports - - Device Enrollment Type Report - -
-

Device Enrollment Type Report

- - Today - Last Week - Last Month - - - - -
- } - visible={this.state.visible} - onVisibleChange={this.handlePopoverVisibleChange} - > - - - -
- - - - - - - -
-
- -
- - ); - } -} - -export default withConfigContext(EnrollmentTypeReport); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EnrolmentVsUnenrollments/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EnrolmentVsUnenrollments/index.js deleted file mode 100644 index bf262d44761..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EnrolmentVsUnenrollments/index.js +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2020, 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 { PageHeader, Breadcrumb, Icon, Radio, Popover, Button } from 'antd'; - -import { Link } from 'react-router-dom'; -import { withConfigContext } from '../../../../../../components/ConfigContext'; -import axios from 'axios'; -import DateRangePicker from '../../components/DateRangePicker'; -import moment from 'moment'; -import { Chart, Geom, Axis, Tooltip, Legend } from 'bizcharts'; -import DataSet from '@antv/data-set'; -import { handleApiError } from '../../../../../../services/utils/errorHandler'; - -class EnrollmentsVsUnenrollmentsReport extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - this.state = { - paramsObject: { - from: moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - to: moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - }, - data: [], - fields: [], - durationMode: 'weekly', - visible: false, - }; - } - - componentDidMount() { - this.fetchData(); - } - - handleDurationModeChange = e => { - const durationMode = e.target.value; - switch (durationMode) { - case 'daily': - this.updateDurationValue( - moment().format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'weekly': - this.updateDurationValue( - moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'monthly': - this.updateDurationValue( - moment() - .subtract(29, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - } - this.setState({ durationMode }); - }; - - handlePopoverVisibleChange = visible => { - this.setState({ visible }); - }; - - // Get modified value from datepicker and set it to paramsObject - updateDurationValue = (modifiedFromDate, modifiedToDate) => { - let tempParamObj = this.state.paramsObject; - tempParamObj.from = modifiedFromDate; - tempParamObj.to = modifiedToDate; - this.setState({ paramsObject: tempParamObj }); - this.fetchData(); - }; - - // Call count APIs and get count for given parameters, then create data object to build pie chart - fetchData = () => { - this.setState({ loading: true }); - - const { paramsObject } = this.state; - const config = this.props.context; - - const encodedExtraParams = Object.keys(paramsObject) - .map(key => key + '=' + paramsObject[key]) - .join('&'); - - axios - .all([ - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?status=ACTIVE&status=INACTIVE&' + - encodedExtraParams, - 'Enrollments', - ), - axios.get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/reports/count?status=REMOVED&' + - encodedExtraParams, - 'Unenrollments', - ), - ]) - .then(res => { - let keys = Object.keys(res[0].data.data); - let enrollments = res[0].data.data; - let unenrollments = res[1].data.data; - if (Object.keys(enrollments).length != 0) { - enrollments.name = 'Enrollments'; - unenrollments.name = 'Unenrollments'; - } - - const finalData = [enrollments, unenrollments]; - - this.setState({ - data: finalData, - fields: keys, - }); - }) - .catch(error => { - handleApiError( - error, - 'Error occurred while trying to get device count.', - ); - }); - }; - - render() { - const { durationMode } = this.state; - - const ds = new DataSet(); - const dv = ds.createView().source(this.state.data); - dv.transform({ - type: 'fold', - fields: this.state.fields, - key: 'Time', - value: 'Number of Devices', - }); - - return ( -
- - - - - Home - - - - Reports - - - Enrollments vs Unenrollments Report - - -
-

Enrollments vs Unenrollments Report

- - - Today - Last Week - Last Month - - - - -
- } - visible={this.state.visible} - onVisibleChange={this.handlePopoverVisibleChange} - > - - - -
- - - - - - - -
-
- -
- - ); - } -} - -export default withConfigContext(EnrollmentsVsUnenrollmentsReport); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/OutdatedOSVersion/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/OutdatedOSVersion/index.js deleted file mode 100644 index fca5ca7534a..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/OutdatedOSVersion/index.js +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2020, 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 { - PageHeader, - Breadcrumb, - Icon, - Button, - Select, - message, - notification, -} from 'antd'; - -import { Link } from 'react-router-dom'; -import { withConfigContext } from '../../../../../../components/ConfigContext'; -import DeviceTable from '../../components/DevicesTable'; - -let config = null; -const { Option } = Select; -let { typeSelected, versionSelected } = false; - -class OutdatedOSversionReport extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - config = this.props.context; - - this.state = { - deviceType: null, - osVersion: null, - apiURL: null, - visible: false, - supportedOsVersions: [], - }; - } - - onDeviceTypeChange = value => { - typeSelected = true; - this.setState({ deviceType: value }); - this.getSupportedOsVersions(value); - }; - - onOSVersionChange = value => { - versionSelected = true; - this.setState({ osVersion: value }); - }; - - onClickGenerateButton = () => { - const { osVersion, deviceType } = this.state; - if (osVersion && deviceType != null) { - let apiURL = - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - `/reports/expired-devices/${deviceType}?osVersion=${osVersion}&`; - this.setState({ apiURL }); - } - }; - - getSupportedOsVersions = deviceType => { - const config = this.props.context; - axios - .get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - `/admin/device-types/${deviceType}/versions`, - ) - .then(res => { - if (res.status === 200) { - let supportedOsVersions = JSON.parse(res.data.data); - this.setState({ - supportedOsVersions, - }); - } - }) - .catch(error => { - if (error.hasOwnProperty('response') && error.response.status === 401) { - 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 OS Versions.', - }); - } - }); - }; - - render() { - const { apiURL, supportedOsVersions } = this.state; - return ( -
- - - - - Home - - - - Reports - - Outdated OS Version - -
-

Outdated OS Version Report

-

- This report displays devices with an OS Version below the - specified version. -

-
- - - {typeSelected && versionSelected ? ( - - ) : null} -
-
- -
-
-
-
-
- ); - } -} - -export default withConfigContext(OutdatedOSversionReport); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/PolicyDevicesTable/components/FeatureListModal/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/PolicyDevicesTable/components/FeatureListModal/index.js deleted file mode 100644 index 2b23bcb1413..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/PolicyDevicesTable/components/FeatureListModal/index.js +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2020, 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 { Button, message, Modal, notification, List, Typography } from 'antd'; -import axios from 'axios'; -import { withConfigContext } from '../../../../../../../../../../components/ConfigContext'; - -class FeatureListModal extends React.Component { - constructor(props) { - super(props); - this.state = { - modalVisible: false, - name: '', - description: '', - features: [], - }; - } - - fetchViolatedFeatures = id => { - const config = this.props.context; - - axios - .get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/devices/' + - id + - '/features', - ) - .then(res => { - if (res.status === 200) { - this.setState({ - features: JSON.parse(res.data.data), - }); - } - }) - .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 non compliance feature list.', - }); - } - }); - }; - - openModal = () => { - this.fetchViolatedFeatures(this.props.id); - this.setState({ - modalVisible: true, - }); - }; - - handleOk = e => { - this.setState({ - modalVisible: false, - }); - }; - - render() { - const { features, modalVisible } = this.state; - - let featureList = features.map(data => ( - - - {data.featureCode} - - - )); - - return ( -
-
- -
-
- - OK - , - ]} - > - - {featureList} - - -
-
- ); - } -} - -export default withConfigContext(FeatureListModal); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/PolicyDevicesTable/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/PolicyDevicesTable/index.js deleted file mode 100644 index 0c820d0f7b4..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/PolicyDevicesTable/index.js +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2020, 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 { Button, Icon, Table, Tooltip } from 'antd'; -import TimeAgo from 'javascript-time-ago'; -import moment from 'moment'; -// Load locale-specific relative date/time formatting rules. -import en from 'javascript-time-ago/locale/en'; -import { withConfigContext } from '../../../../../../../../components/ConfigContext'; -import FeatureListModal from './components/FeatureListModal'; -import { handleApiError } from '../../../../../../../../services/utils/errorHandler'; - -let config = null; - -// Table columns for non compliant devices -const columnsNonCompliant = [ - { - title: 'Device', - dataIndex: 'deviceName', - width: 100, - sorter: (a, b) => a.deviceName.localeCompare(b.deviceName), - }, - { - title: 'Type', - dataIndex: 'deviceType', - key: 'type', - // eslint-disable-next-line react/display-name - 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 ( - - - - ); - }, - }, - { - title: 'Owner', - dataIndex: 'owner', - key: 'owner', - }, - { - title: 'Policy', - dataIndex: 'policyName', - key: 'policy', - sorter: (a, b) => a.policyName.localeCompare(b.policyName), - }, - { - title: 'Last Failed Time', - dataIndex: 'lastFailedTime', - key: 'lastFailedTime', - render: data => { - if (data) { - return ( - - {moment(data).fromNow()} - - ); - } - return 'Not available'; - }, - }, - { - title: 'Last Success Time', - dataIndex: 'lastSucceededTime', - key: 'lastSucceededTime', - render: data => { - if (data) { - return ( - - {moment(data).fromNow()} - - ); - } - return 'Not available'; - }, - }, - { - title: 'Attempts', - dataIndex: 'attempts', - key: 'attempts', - }, - { - title: 'Violated Features', - dataIndex: 'id', - key: 'violated_features', - // eslint-disable-next-line react/display-name - render: id => , - }, - { - title: 'Device Details', - dataIndex: 'id', - key: 'device_details', - // eslint-disable-next-line react/display-name - render: id => ( - - ), - }, -]; - -// Table columns for compliant devices -const columnsCompliant = [ - { - title: 'Device', - dataIndex: 'deviceName', - width: 100, - sorter: (a, b) => a.deviceName.localeCompare(b.deviceName), - }, - { - title: 'Type', - dataIndex: 'deviceType', - key: 'type', - // eslint-disable-next-line react/display-name - 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 ( - - - - ); - }, - }, - { - title: 'Owner', - dataIndex: 'owner', - key: 'owner', - }, - { - title: 'Policy', - dataIndex: 'policyName', - key: 'policy', - sorter: (a, b) => a.policyName.localeCompare(b.policyName), - }, - { - title: 'Last Success Time', - dataIndex: 'lastSucceededTime', - key: 'lastSucceededTime', - render: data => { - if (data) { - return ( - - {moment(data).fromNow()} - - ); - } - return 'Not available'; - }, - }, - { - title: 'Attempts', - dataIndex: 'attempts', - key: 'attempts', - }, - { - title: 'Device Details', - dataIndex: 'id', - key: 'device_details', - // eslint-disable-next-line react/display-name - render: id => ( - - ), - }, -]; - -class PolicyDevicesTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, - loading: false, - selectedRows: [], - paramsObj: {}, - }; - } - - rowSelection = { - onChange: (selectedRowKeys, selectedRows) => { - this.setState({ - selectedRows: selectedRows, - }); - }, - }; - - componentDidMount() { - this.fetchData(); - } - - // Rerender component when parameters change - componentDidUpdate(prevProps, prevState, snapshot) { - if ( - prevProps.isCompliant !== this.props.isCompliant || - prevProps.policyReportData !== this.props.policyReportData - ) { - this.fetchData(); - } - } - - // fetch data from api - fetchData = (params = {}) => { - // const policyReportData = this.props; - this.setState({ loading: true }); - // get current page - const currentPage = params.hasOwnProperty('page') ? params.page : 1; - - let extraParams; - - if (this.props.policyReportData.policy) { - extraParams = { - policy: this.props.policyReportData.policy, - from: this.props.policyReportData.from, - to: this.props.policyReportData.to, - offset: 10 * (currentPage - 1), // calculate the offset - limit: 10, - }; - } else { - extraParams = { - from: this.props.policyReportData.from, - to: this.props.policyReportData.to, - offset: 10 * (currentPage - 1), // calculate the offset - limit: 10, - }; - } - - const encodedExtraParams = Object.keys(extraParams) - .map(key => key + '=' + extraParams[key]) - .join('&'); - - let apiUrl; - - if (this.props.isCompliant) { - apiUrl = - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/devices/compliance/true?' + - encodedExtraParams; - } else { - apiUrl = - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/devices/compliance/false?' + - encodedExtraParams; - } - - // send request to the invoker - axios - .get(apiUrl) - .then(res => { - if (res.status === 200) { - const pagination = { ...this.state.pagination }; - this.setState({ - loading: false, - data: res.data.data, - pagination, - }); - } - }) - .catch(error => { - handleApiError(error, '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.fetchData({ - results: pagination.pageSize, - page: pagination.current, - sortField: sorter.field, - sortOrder: sorter.order, - ...filters, - }); - }; - - render() { - let { data, pagination, loading } = this.state; - const { isCompliant } = this.props; - - return ( -
-
record.id} - dataSource={data.complianceData} - pagination={{ - ...pagination, - size: 'small', - // position: "top", - total: data.count, - showTotal: (total, range) => - `showing ${range[0]}-${range[1]} of ${total} devices`, - // showQuickJumper: true - }} - loading={loading} - onChange={this.handleTableChange} - rowSelection={this.rowSelection} - /> - - ); - } -} - -export default withConfigContext(PolicyDevicesTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/SelectPolicyDropDown/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/SelectPolicyDropDown/index.js deleted file mode 100644 index 1ec9aa2bfe1..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/components/SelectPolicyDropDown/index.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020, 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 { Select, message, notification } from 'antd'; - -import { withConfigContext } from '../../../../../../../../components/ConfigContext'; -import axios from 'axios'; - -const { Option } = Select; - -class SelectPolicyDropDown extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - this.state = { - isOpen: false, - currentPage: 1, - data: [], - pagination: {}, - loading: false, - }; - } - - componentDidMount() { - this.fetchPolicies(); - } - - // fetch data from api - fetchPolicies = (params = {}) => { - const config = this.props.context; - this.setState({ loading: true }); - - // send request to the invokerss - axios - .get( - window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - '/policies', - ) - .then(res => { - if (res.status === 200) { - this.setState({ - loading: false, - data: res.data.data.policies, - }); - } - }) - .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 }); - }); - }; - - handleChange = value => { - this.props.getPolicyId(value); - }; - - render() { - let item; - if (this.state.data) { - item = this.state.data.map(data => ( - - {data.profile.profileName} - - )); - } - - return ( - - ); - } -} - -export default withConfigContext(SelectPolicyDropDown); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/index.js deleted file mode 100644 index 29f789311d5..00000000000 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/PolicyCompliance/index.js +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2020, 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 { PageHeader, Breadcrumb, Icon, Radio, Popover, Button } from 'antd'; - -import { Link } from 'react-router-dom'; -import { withConfigContext } from '../../../../../../components/ConfigContext'; -import PolicyDevicesTable from './components/PolicyDevicesTable'; -import moment from 'moment'; -import DateRangePicker from '../../components/DateRangePicker'; -import SelectPolicyDropDown from './components/SelectPolicyDropDown'; - -// eslint-disable-next-line no-unused-vars -let config = null; - -class PolicyReport extends React.Component { - routes; - - constructor(props) { - super(props); - this.routes = props.routes; - config = this.props.context; - this.state = { - durationMode: 'weekly', - isCompliant: true, - // This object contains parameters which pass into API endpoint - policyReportData: { - from: moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - to: moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - }, - visible: false, - }; - } - - handleModeChange = e => { - const isCompliant = e.target.value; - this.setState({ isCompliant }); - }; - - handleDurationModeChange = e => { - const durationMode = e.target.value; - switch (durationMode) { - case 'daily': - this.updateDurationValue( - moment().format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'weekly': - this.updateDurationValue( - moment() - .subtract(6, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - case 'monthly': - this.updateDurationValue( - moment() - .subtract(29, 'days') - .format('YYYY-MM-DD'), - moment() - .add(1, 'days') - .format('YYYY-MM-DD'), - ); - break; - } - this.setState({ durationMode }); - }; - - hidePopover = () => { - this.setState({ - visible: false, - }); - }; - - handlePopoverVisibleChange = visible => { - this.setState({ visible }); - }; - - getPolicyId = policyId => { - let tempParamObj = this.state.policyReportData; - if (policyId === 'all') { - delete tempParamObj.policy; - } else { - tempParamObj.policy = policyId; - } - this.setState({ policyReportData: tempParamObj }); - }; - - // Get modified value from datepicker and set it to paramsObject - updateDurationValue = (modifiedFromDate, modifiedToDate) => { - let tempParamObj = this.state.policyReportData; - tempParamObj.from = modifiedFromDate; - tempParamObj.to = modifiedToDate; - this.setState({ policyReportData: tempParamObj }); - }; - - render() { - const { isCompliant, durationMode } = this.state; - const policyData = { ...this.state.policyReportData }; - return ( -
- - - - - Home - - - - Reports - - Policy Compliance Report - -
-

Policy Report

- - - Policy Compliant Devices - - Policy Non-Compliant Devices - - - - - Today - Last Week - Last Month - - - -
- } - visible={this.state.visible} - onVisibleChange={this.handlePopoverVisibleChange} - > - - - - - -
- -
-
- -
- - ); - } -} - -export default withConfigContext(PolicyReport); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypePluginExtensionServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypePluginExtensionServiceImpl.java index e32c9e2d573..d3a1330218b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypePluginExtensionServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/DeviceTypePluginExtensionServiceImpl.java @@ -19,7 +19,6 @@ package org.wso2.carbon.device.mgt.extensions.device.type.template; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.extensions.device.type.template.dao.DeviceTypePluginDAOManager; import org.wso2.carbon.device.mgt.extensions.device.type.template.exception.DeviceTypePluginExtensionException; import org.wso2.carbon.device.mgt.extensions.spi.DeviceTypePluginExtensionService; @@ -36,34 +35,29 @@ public class DeviceTypePluginExtensionServiceImpl implements DeviceTypePluginExt @Override public void addPluginDAOManager(String deviceType, DeviceTypePluginDAOManager pluginDAOManager) throws DeviceTypePluginExtensionException { - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); if (pluginDAOManager == null) { - String msg = "Cannot save DeviceTypePluginDAOManager against tenant id " + tenantId - + " and device type: " + deviceType + " since DeviceTypePluginDAOManager is null"; + String msg = "Cannot save DeviceTypePluginDAOManager of device type: " + deviceType + + " since DeviceTypePluginDAOManager is null"; log.error(msg); throw new DeviceTypePluginExtensionException(msg); } - if (!pluginDAOManagers.containsKey(tenantId + deviceType)) { + if (!pluginDAOManagers.containsKey(deviceType)) { if (log.isDebugEnabled()) { - log.debug("Saving DeviceTypePluginDAOManager against tenant id " + tenantId + - " and device type: " + deviceType); + log.debug("Saving DeviceTypePluginDAOManager of device type: " + deviceType); } - pluginDAOManagers.put(tenantId + deviceType, pluginDAOManager); + pluginDAOManagers.put(deviceType, pluginDAOManager); } } @Override public DeviceTypePluginDAOManager getPluginDAOManager(String deviceType) throws DeviceTypePluginExtensionException { - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); - if (pluginDAOManagers.containsKey(tenantId + deviceType)) { + if (pluginDAOManagers.containsKey(deviceType)) { if (log.isDebugEnabled()) { - log.debug("Retrieving DeviceTypePluginDAOManager against tenant id " + tenantId + - " and device type: " + deviceType); + log.debug("Retrieving DeviceTypePluginDAOManager of device type: " + deviceType); } - return pluginDAOManagers.get(tenantId + deviceType); + return pluginDAOManagers.get(deviceType); } else { - String msg = "DeviceTypePluginDAOManager could not be found against tenant id " + tenantId + - " and device type: " + deviceType; + String msg = "DeviceTypePluginDAOManager of device type: " + deviceType + " cannot be found"; log.error(msg); throw new DeviceTypePluginExtensionException(msg); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/SubPanelValuesList.java b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/SubPanelValuesList.java index 7758be4f26a..656c9c234ab 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/SubPanelValuesList.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.extensions/src/main/java/org/wso2/carbon/device/mgt/extensions/device/type/template/config/SubPanelValuesList.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.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. + */ + package org.wso2.carbon.device.mgt.extensions.device.type.template.config; import javax.xml.bind.annotation.XmlElement;