From d8b218026de674b90d12920aa1e0ae90869b99b5 Mon Sep 17 00:00:00 2001 From: Jayasanka Weerasinghe Date: Thu, 16 Jan 2020 07:27:29 +0000 Subject: [PATCH] Add ESLint to devicemgt react app --- .../io.entgra.device.mgt.ui/pom.xml | 10 + .../react-app/.eslintrc | 325 ++ .../react-app/.prettierrc | 5 + .../react-app/babel.config.js | 11 +- .../react-app/package.json | 11 +- .../react-app/src/App.js | 265 +- .../Certificates/CertificateTable.js | 432 +- .../DeviceTypes/DeviceTypesTable.js | 216 +- .../src/components/Devices/AddDevice.js | 104 +- .../src/components/Devices/BulkActionBar.js | 205 +- .../src/components/Devices/DeviceType.js | 231 +- .../src/components/Devices/DevicesTable.js | 922 ++-- .../src/components/Devices/EnrollAgent.js | 164 +- .../components/Devices/ReportDevicesTable.js | 430 +- .../Geo/geo-custom-map/GeoCustomMap.js | 106 +- .../Geo/geo-dashboard/GeoDashboard.js | 514 +- .../src/components/Groups/AddGroup.js | 285 +- .../src/components/Groups/GroupActions.js | 690 +-- .../src/components/Groups/GroupsTable.js | 344 +- .../src/components/Policies/AddPolicy.js | 168 +- .../components/Policies/ConfigureProfile.js | 506 +- .../src/components/Policies/PoliciesTable.js | 289 +- .../src/components/Policies/SelectPlatform.js | 231 +- .../src/components/Policies/configuration.js | 4210 +++++++++-------- .../src/components/Reports/DateRangePicker.js | 75 +- .../src/components/Reports/Filter.js | 85 +- .../Reports/Templates/DeviceStatusReport.js | 184 +- .../Reports/Templates/EnrollmentTypeReport.js | 166 +- .../EnrollmentsVsUnenrollmentsReport.js | 232 +- .../components/Reports/Widgets/CountWidget.js | 92 +- .../components/Reports/Widgets/PieChart.js | 628 +-- .../react-app/src/components/Roles/AddRole.js | 698 +-- .../src/components/Roles/RoleAction.js | 887 ++-- .../src/components/Roles/RolesTable.js | 448 +- .../src/components/RouteWithSubRoutes.js | 39 +- .../react-app/src/components/Users/AddUser.js | 430 +- .../src/components/Users/UserActions.js | 861 ++-- .../src/components/Users/UsersDevices.js | 426 +- .../src/components/Users/UsersTable.js | 565 +-- .../src/components/Utils/Filter/Filter.js | 67 +- .../react-app/src/context/ConfigContext.js | 18 +- .../react-app/src/index.js | 212 +- .../Certificates/Certificates.js | 78 +- .../src/pages/Dashboard/Dashboard.js | 356 +- .../Dashboard/DeviceTypes/DeviceTypes.js | 75 +- .../pages/Dashboard/Devices/DeviceEnroll.js | 81 +- .../src/pages/Dashboard/Devices/Devices.js | 76 +- .../react-app/src/pages/Dashboard/Geo/Geo.js | 78 +- .../src/pages/Dashboard/Groups/Groups.js | 69 +- .../src/pages/Dashboard/Logout/Logout.js | 97 +- .../pages/Dashboard/Policies/AddNewPolicy.js | 75 +- .../src/pages/Dashboard/Policies/Policies.js | 75 +- .../Reports/ReportDurationItemList.js | 296 +- .../src/pages/Dashboard/Reports/Reports.js | 125 +- .../src/pages/Dashboard/Roles/Roles.js | 69 +- .../src/pages/Dashboard/Users/Users.js | 71 +- .../react-app/src/pages/Login.js | 305 +- .../react-app/src/serviceWorker.js | 10 +- .../react-app/webpack.config.js | 210 +- 59 files changed, 9836 insertions(+), 9097 deletions(-) create mode 100644 components/device-mgt/io.entgra.device.mgt.ui/react-app/.eslintrc create mode 100644 components/device-mgt/io.entgra.device.mgt.ui/react-app/.prettierrc diff --git a/components/device-mgt/io.entgra.device.mgt.ui/pom.xml b/components/device-mgt/io.entgra.device.mgt.ui/pom.xml index 46481eb3e5..6e62bc0fc4 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/pom.xml +++ b/components/device-mgt/io.entgra.device.mgt.ui/pom.xml @@ -82,6 +82,16 @@ install + + lint + + npm + + + run-script lint + + generate-resources + prod diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/.eslintrc b/components/device-mgt/io.entgra.device.mgt.ui/react-app/.eslintrc new file mode 100644 index 0000000000..7958a91eaf --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/.eslintrc @@ -0,0 +1,325 @@ +{ + "parser": "babel-eslint", + "plugins": [ + "react", + "babel", + "jsx", + "prettier" + ], + "extends": [ + "eslint:recommended", + "plugin:react/recommended" + ], + "parserOptions": { + "ecmaVersion": 2016, + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + } + }, + "settings": { + "react": { + "createClass": "createReactClass", + "pragma": "React", + "version": "16.8.6" + } + }, + "env": { + "node": true, + "commonjs": true, + "browser": true, + "jasmine": true, + "es6": true + }, + "globals": { + "document": true, + "console": true, + // Only for development purposes + "setTimeout": true, + "window" : true + }, + "rules": { + "prettier/prettier": "error", + // Enforce the spacing around the * in generator functions. + "generator-star-spacing": [2, "after"], + // Disallow using variables outside the blocks they are defined (especially + // since only let and const are used, see "no-var"). + "block-scoped-var": 2, + // Require camel case names + "camelcase": 2, + // Allow trailing commas for easy list extension. Having them does not + // impair readability, but also not required either. + "comma-dangle": 0, + // Warn about cyclomatic complexity in functions. + "complexity": 1, + // Don't warn for inconsistent naming when capturing this (not so important + // with auto-binding fat arrow functions). + "consistent-this": 0, + // Enforce curly brace conventions for all control statements. + "curly": 2, + // Don't require a default case in switch statements. Avoid being forced to + // add a bogus default when you know all possible cases are handled. + "default-case": 0, + // Encourage the use of dot notation whenever possible. + "dot-notation": 2, + // Allow mixed 'LF' and 'CRLF' as linebreaks. + "linebreak-style": 0, + // Don't enforce the maximum depth that blocks can be nested. + "max-depth": 0, + // Maximum length of a line. + "max-len": [2, 120, 2, { "ignoreStrings": true, "ignoreUrls": true}], + // Maximum depth callbacks can be nested. + "max-nested-callbacks": [2, 3], + // Don't limit the number of parameters that can be used in a function. + "max-params": 0, + // Don't limit the maximum number of statement allowed in a function. + "max-statements": 0, + // Require a capital letter for constructors, only check if all new + // operators are followed by a capital letter. Don't warn when capitalized + // functions are used without the new operator. + "new-cap": [2, {"capIsNew": false}], + // Disallow use of the Array constructor. + "no-array-constructor": 2, + // Allow use of bitwise operators. + "no-bitwise": 0, + // Disallow use of arguments.caller or arguments.callee. + "no-caller": 2, + // Disallow the catch clause parameter name being the same as a variable in + // the outer scope, to avoid confusion. + "no-catch-shadow": 2, + // Disallow assignment in conditional expressions. + "no-cond-assign": 2, + // Allow using the console API. + "no-console": 0, + // Allow using constant expressions in conditions like while (true) + "no-constant-condition": 0, + // Allow use of the continue statement. + "no-continue": 0, + // Disallow control characters in regular expressions. + "no-control-regex": 2, + // Disallow deletion of variables (deleting properties is fine). + "no-delete-var": 2, + // Disallow duplicate arguments in functions. + "no-dupe-args": 2, + // Disallow duplicate keys when creating object literals. + "no-dupe-keys": 2, + // Disallow multiple empty lines + "no-multiple-empty-lines": "error", + // Disallow a duplicate case label. + "no-duplicate-case": 2, + // Disallow else after a return in an if. The else around the second return + // here is useless: + // if (something) { return false; } else { return true; } + "no-else-return": 2, + // Disallow empty statements. This will report an error for: + // try { something(); } catch (e) {} + // but will not report it for: + // try { something(); } catch (e) { /* Silencing the error because ...*/ } + // which is a valid use case. + "no-empty": 2, + // Disallow the use of empty character classes in regular expressions. + "no-empty-character-class": 2, + // Disallow use of labels for anything other then loops and switches. + "no-labels": 2, + // Disallow use of eval(). We have other APIs to evaluate code in content. + "no-eval": 2, + // Disallow assigning to the exception in a catch block. + "no-ex-assign": 2, + // Disallow adding to native types + "no-extend-native": 2, + // Disallow unnecessary function binding. + "no-extra-bind": 2, + // Disallow double-negation boolean casts in a boolean context. + "no-extra-boolean-cast": 2, + // Allow unnecessary parentheses, as they may make the code more readable. + "no-extra-parens": 0, + // Disallow fallthrough of case statements, except if there is a comment. + "no-fallthrough": 2, + // Allow the use of leading or trailing decimal points in numeric literals. + "no-floating-decimal": 0, + // Disallow if as the only statement in an else block. + "no-lonely-if": 2, + // Disallow use of multiline strings (use template strings instead). + "no-multi-str": 2, + // Disallow reassignments of native objects. + "no-native-reassign": 2, + // Disallow nested ternary expressions, they make the code hard to read. + "no-nested-ternary": 2, + // Allow use of new operator with the require function. + "no-new-require": 0, + // Disallow use of octal literals. + "no-octal": 2, + // Allow reassignment of function parameters. + "no-param-reassign": 0, + // Allow string concatenation with __dirname and __filename (not a node env). + "no-path-concat": 0, + // Allow use of unary operators, ++ and --. + "no-plusplus": 0, + // Allow using process.env (not a node environment). + "no-process-env": 0, + // Allow using process.exit (not a node environment). + "no-process-exit": 0, + // Disallow usage of __proto__ property. + "no-proto": 2, + // Disallow declaring the same variable more than once (we use let anyway). + "no-redeclare": 2, + // Disallow multiple spaces in a regular expression literal. + "no-regex-spaces": 2, + // Allow reserved words being used as object literal keys. + "no-reserved-keys": 0, + // Don't restrict usage of specified node modules (not a node environment). + "no-restricted-modules": 0, + // Disallow use of assignment in return statement. It is preferable for a + // single line of code to have only one easily predictable effect. + "no-return-assign": 2, + // Allow use of javascript: urls. + "no-script-url": 0, + // Disallow comparisons where both sides are exactly the same. + "no-self-compare": 2, + // Disallow use of comma operator. + "no-sequences": 2, + // Warn about declaration of variables already declared in the outer scope. + // This isn't an error because it sometimes is useful to use the same name + // in a small helper function rather than having to come up with another + // random name. + // Still, making this a warning can help people avoid being confused. + "no-shadow": 0, + // Require empty line at end of file + "eol-last": "error", + // Disallow shadowing of names such as arguments. + "no-shadow-restricted-names": 2, + "no-space-before-semi": 0, + // Disallow sparse arrays, eg. let arr = [,,2]. + // Array destructuring is fine though: + // for (let [, breakpointPromise] of aPromises) + "no-sparse-arrays": 2, + // Allow use of synchronous methods (not a node environment). + "no-sync": 0, + // Allow the use of ternary operators. + "no-ternary": 0, + // Don't allow spaces after end of line + "no-trailing-spaces": "error", + // Disallow throwing literals (eg. throw "error" instead of + // throw new Error("error")). + "no-throw-literal": 2, + // Disallow use of undeclared variables unless mentioned in a /*global */ + // block. Note that globals from head.js are automatically imported in tests + // by the import-headjs-globals rule form the mozilla eslint plugin. + "no-undef": 2, + // Allow use of undefined variable. + "no-undefined": 0, + // Disallow the use of Boolean literals in conditional expressions. + "no-unneeded-ternary": 2, + // Disallow unreachable statements after a return, throw, continue, or break + // statement. + "no-unreachable": 2, + // Allow using variables before they are defined. + "no-unused-vars": [2, {"vars": "all", "args": "none"}], + // Disallow global and local variables that arent used, but allow unused function arguments. + "no-use-before-define": 0, + // We use var-only-at-top-level instead of no-var as we allow top level + // vars. + "no-var": 0, + // Allow using TODO/FIXME comments. + "no-warning-comments": 0, + // Disallow use of the with statement. + "no-with": 2, + // Dont require method and property shorthand syntax for object literals. + // We use this in the code a lot, but not consistently, and this seems more + // like something to check at code review time. + "object-shorthand": 0, + // Allow more than one variable declaration per function. + "one-var": 0, + // Single quotes should be used. + "quotes": [2, "single", "avoid-escape"], + // Require use of the second argument for parseInt(). + "radix": 2, + // Dont require to sort variables within the same declaration block. + // Anyway, one-var is disabled. + "sort-vars": 0, + "space-after-function-name": 0, + "space-before-function-parentheses": 0, + // Disallow space before function opening parenthesis. + //"space-before-function-paren": [2, "never"], + // Disable the rule that checks if spaces inside {} and [] are there or not. + // Our code is split on conventions, and itd be nice to have 2 rules + // instead, one for [] and one for {}. So, disabling until we write them. + "space-in-brackets": 0, + // Deprecated, will be removed in 1.0. + "space-unary-word-ops": 0, + // Require a space immediately following the // in a line comment. + "spaced-comment": [2, "always"], + // Require "use strict" to be defined globally in the script. + "strict": [2, "global"], + // Disallow comparisons with the value NaN. + "use-isnan": 2, + // Warn about invalid JSDoc comments. + // Disabled for now because of https://github.com/eslint/eslint/issues/2270 + // The rule fails on some jsdoc comments like in: + // devtools/client/webconsole/console-output.js + "valid-jsdoc": 0, + // Ensure that the results of typeof are compared against a valid string. + "valid-typeof": 2, + // Allow vars to be declared anywhere in the scope. + "vars-on-top": 0, + // Dont require immediate function invocation to be wrapped in parentheses. + "wrap-iife": 0, + // Don't require regex literals to be wrapped in parentheses (which + // supposedly prevent them from being mistaken for division operators). + "wrap-regex": 0, + // Require for-in loops to have an if statement. + "guard-for-in": 0, + // allow/disallow an empty newline after var statement + "newline-after-var": 0, + // disallow the use of alert, confirm, and prompt + "no-alert": 0, + // disallow the use of deprecated react changes and lifecycle methods + "react/no-deprecated": 0, + // disallow comparisons to null without a type-checking operator + "no-eq-null": 0, + // disallow overwriting functions written as function declarations + "no-func-assign": 0, + // disallow use of eval()-like methods + "no-implied-eval": 0, + // disallow function or variable declarations in nested blocks + "no-inner-declarations": 0, + // disallow invalid regular expression strings in the RegExp constructor + "no-invalid-regexp": 0, + // disallow irregular whitespace outside of strings and comments + "no-irregular-whitespace": 0, + // disallow unnecessary nested blocks + "no-lone-blocks": 0, + // disallow creation of functions within loops + "no-loop-func": 0, + // disallow use of new operator when not part of the assignment or + // comparison + "no-new": 0, + // disallow use of new operator for Function object + "no-new-func": 0, + // disallow use of the Object constructor + "no-new-object": 0, + // disallows creating new instances of String,Number, and Boolean + "no-new-wrappers": 0, + // disallow the use of object properties of the global object (Math and + // JSON) as functions + "no-obj-calls": 0, + // disallow use of octal escape sequences in string literals, such as + // var foo = "Copyright \251"; + "no-octal-escape": 0, + // disallow use of undefined when initializing variables + "no-undef-init": 0, + // disallow usage of expressions in statement position + "no-unused-expressions": 0, + // disallow use of void operator + "no-void": 0, + // disallow wrapping of non-IIFE statements in parens + "no-wrap-func": 0, + // require assignment operator shorthand where possible or prohibit it + // entirely + "operator-assignment": 0, + // enforce operators to be placed before or after line breaks + "operator-linebreak": 0, + // disable chacking prop types + "react/prop-types": 0 + } +} diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/.prettierrc b/components/device-mgt/io.entgra.device.mgt.ui/react-app/.prettierrc new file mode 100644 index 0000000000..d281e2bd55 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "parser": "flow" +} diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/babel.config.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/babel.config.js index 7ec6d0936b..9cfcaf0bd9 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/babel.config.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/babel.config.js @@ -16,14 +16,13 @@ * under the License. */ -module.exports = function (api) { +module.exports = function(api) { api.cache(true); - const presets = [ "@babel/preset-env", - "@babel/preset-react" ]; - const plugins = ["@babel/plugin-proposal-class-properties"]; + const presets = ['@babel/preset-env', '@babel/preset-react']; + const plugins = ['@babel/plugin-proposal-class-properties']; return { presets, - plugins + plugins, }; -}; \ No newline at end of file +}; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json b/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json index 04c40c1edc..3aacd5da9b 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json @@ -8,6 +8,7 @@ "acorn": "^6.2.0", "antd": "^3.23.5", "axios": "^0.18.1", + "babel-eslint": "^9.0.0", "bizcharts": "^3.5.6", "bootstrap": "^4.3.1", "javascript-time-ago": "^2.0.1", @@ -46,6 +47,12 @@ "body-parser": "^1.19.0", "chai": "^4.1.2", "css-loader": "^0.28.11", + "eslint": "^5.16.0", + "eslint-config-prettier": "4.3.0", + "eslint-plugin-babel": "5.3.0", + "eslint-plugin-jsx": "0.0.2", + "eslint-plugin-prettier": "3.1.0", + "eslint-plugin-react": "7.14.2", "express": "^4.17.1", "express-pino-logger": "^4.0.0", "file-loader": "^2.0.0", @@ -64,6 +71,7 @@ "npm-run-all": "^4.1.5", "pino-colada": "^1.4.5", "postcss-loader": "^3.0.0", + "prettier": "1.18.1", "react": "^16.8.6", "react-dom": "^16.8.6", "react-intl": "^2.9.0", @@ -84,6 +92,7 @@ "build_prod": "NODE_ENV=production NODE_OPTIONS=--max_old_space_size=4096 webpack -p --display errors-only --hide-modules", "build_dev": "NODE_ENV=development webpack -d --watch ", "server": "node-env-run server --exec nodemon | pino-colada", - "dev2": "run-p server start" + "dev2": "run-p server start", + "lint": "eslint \"src/**/*.js\"" } } diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/App.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/App.js index 078ceaaaeb..5c6976f378 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/App.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/App.js @@ -16,153 +16,156 @@ * under the License. */ -import React from "react"; -import "antd/dist/antd.less"; -import RouteWithSubRoutes from "./components/RouteWithSubRoutes"; -import { - BrowserRouter as Router, - Redirect, Switch, -} from 'react-router-dom'; -import axios from "axios"; -import {Layout, Spin, Result, message, notification} from "antd"; -import ConfigContext from "./context/ConfigContext"; +import React from 'react'; +import 'antd/dist/antd.less'; +import RouteWithSubRoutes from './components/RouteWithSubRoutes'; +import { BrowserRouter as Router, Redirect, Switch } from 'react-router-dom'; +import axios from 'axios'; +import { Layout, Spin, Result, notification } from 'antd'; +import ConfigContext from './context/ConfigContext'; -const {Content} = Layout; +const { Content } = Layout; const loadingView = ( - - - - - + + + + + ); const errorView = ( - + ); class App extends React.Component { + constructor(props) { + super(props); + this.state = { + loading: true, + error: false, + config: {}, + }; + } - constructor(props) { - super(props); - this.state = { - loading: true, - error: false, - config: {} + componentDidMount() { + axios + .get(window.location.origin + '/entgra/public/conf/config.json') + .then(res => { + const config = res.data; + this.checkUserLoggedIn(config); + }) + .catch(error => { + this.setState({ + loading: false, + error: true, + }); + }); + } + + checkUserLoggedIn = config => { + axios + .post( + window.location.origin + '/entgra-ui-request-handler/user', + 'platform=entgra', + ) + .then(res => { + config.user = res.data.data; + const pageURL = window.location.pathname; + const lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1); + if (lastURLSegment === 'login') { + window.location.href = window.location.origin + '/entgra/'; + } else { + this.setState({ + loading: false, + config: config, + }); } - } - - componentDidMount() { - axios.get( - window.location.origin + "/entgra/public/conf/config.json", - ).then(res => { - const config = res.data; - this.checkUserLoggedIn(config); - }).catch((error) => { + this.getDeviceTypes(config); + }) + .catch(error => { + if (error.hasOwnProperty('response') && error.response.status === 401) { + const redirectUrl = encodeURI(window.location.href); + const pageURL = window.location.pathname; + const lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1); + if (lastURLSegment !== 'login') { + window.location.href = + window.location.origin + `/entgra/login?redirect=${redirectUrl}`; + } else { this.setState({ - loading: false, - error: true - }) - }); - } - - checkUserLoggedIn = (config) => { - axios.post( - window.location.origin + "/entgra-ui-request-handler/user", - "platform=entgra" - ).then(res => { - config.user = res.data.data; - const pageURL = window.location.pathname; - const lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1); - if (lastURLSegment === "login") { - window.location.href = window.location.origin + `/entgra/`; - } else { - this.setState({ - loading: false, - config: config - }); - } - this.getDeviceTypes(config); - }).catch((error) => { - if (error.hasOwnProperty("response") && error.response.status === 401) { - const redirectUrl = encodeURI(window.location.href); - const pageURL = window.location.pathname; - const lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1); - if (lastURLSegment !== "login") { - window.location.href = window.location.origin + `/entgra/login?redirect=${redirectUrl}`; - } else { - this.setState({ - loading: false, - config: config - }) - } - } else { - this.setState({ - loading: false, - error: true - }) - } - }); - }; - - getDeviceTypes = (config) => { - axios.get( - window.location.origin + "/entgra-ui-request-handler/invoke/device-mgt/v1.0/device-types", - ).then(res => { - config.deviceTypes = JSON.parse(res.data.data); - this.setState({ - config: config, - loading: false + loading: false, + config: config, }); - }).catch((error) => { - - notification["error"]({ - message: "There was a problem", - duration: 0, - description:"Error occurred while trying to load device types.", - }); + } + } else { + this.setState({ + loading: false, + error: true, + }); + } + }); + }; + getDeviceTypes = config => { + axios + .get( + window.location.origin + + '/entgra-ui-request-handler/invoke/device-mgt/v1.0/device-types', + ) + .then(res => { + config.deviceTypes = JSON.parse(res.data.data); + this.setState({ + config: config, + loading: false, }); - }; + }) + .catch(error => { + notification.error({ + message: 'There was a problem', + duration: 0, + description: 'Error occurred while trying to load device types.', + }); + }); + }; - render() { - const {loading, error} = this.state; + render() { + const { loading, error } = this.state; + const applicationView = ( + + +
+ + + {this.props.routes.map(route => ( + + ))} + +
+
+
+ ); - const abc = this.state.deviceTypes; - const applicationView = ( - - -
- - - {this.props.routes.map((route) => ( - - ))} - -
-
-
- ); - - return ( -
- {loading && loadingView} - {!loading && !error && applicationView} - {error && errorView} -
- ); - } + return ( +
+ {loading && loadingView} + {!loading && !error && applicationView} + {error && errorView} +
+ ); + } } export default App; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Configurations/Certificates/CertificateTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Configurations/Certificates/CertificateTable.js index 1dcb03e397..0e0c9d9bfd 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Configurations/Certificates/CertificateTable.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Configurations/Certificates/CertificateTable.js @@ -16,217 +16,247 @@ * under the License. */ -import React from "react"; -import axios from "axios"; -import {Icon, message, Modal, notification, Popconfirm, Select, Table, Tag, Tooltip, Typography} from "antd"; -import TimeAgo from 'javascript-time-ago' +import React from 'react'; +import axios from 'axios'; +import { + Icon, + message, + notification, + Popconfirm, + Table, + Tooltip, + Typography, +} 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 Moment from "react-moment"; +import en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../../context/ConfigContext'; +import Moment from 'react-moment'; -const {Paragraph, Text} = Typography; +const { Paragraph, Text } = Typography; let config = null; class CertificateTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, + constructor(props) { + super(props); + config = this.props.context; + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + }; + } + + componentDidMount() { + this.fetch(); + } + + // fetch data from api + fetch = (params = {}) => { + 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('&'); + + // send request to the invoker + axios + .get( + window.location.origin + + config.serverConfig.invoker.uri + + '/certificate-mgt/v1.0/admin/certificates' + + encodedExtraParams, + ) + .then(res => { + if (res.status === 200) { + const pagination = { ...this.state.pagination }; + this.setState({ loading: false, - }; - } - - componentDidMount() { - this.fetch(); - } - - //fetch data from api - fetch = (params = {}) => { - 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, - }; - - 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 + - '/certificate-mgt/v1.0/admin/certificates', - ).then(res => { - if (res.status === 200) { - const pagination = {...this.state.pagination}; - this.setState({ - loading: false, - data: res.data.data.certificates, - 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, - }); - }; - - deleteCertificate = (serialNumber) =>{ - axios.delete( - window.location.origin + config.serverConfig.invoker.uri + - '/certificate-mgt/v1.0/admin/certificates/'+ serialNumber, - {headers: {'Content-Type': 'application/json'}} - ).then(res => { - if (res.status === 200) { - this.fetch(); - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully deleted the certificate.", - }); - } - }).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 delete the certificate.", - }); - } - }); - - }; - - columns = [ - { - title: 'Serial Number', - dataIndex: 'serialNumber' - }, - { - title: 'Username', - dataIndex: 'username' - }, - { - title: 'Certificate Version', - dataIndex: 'certificateVersion' - }, - { - title: 'Certificate Serial', - dataIndex: 'certificateserial' - }, - { - title: 'Not Before', - dataIndex: 'notBefore', - render: notBefore => ( - - ) - }, - { - title: 'Not After', - dataIndex: 'notAfter', - render: notAfter => ( - - ) - }, - { - title: 'Subject', - dataIndex: 'subject', - render: subject => ( - {subject} - ) - }, - { - title: 'Issuer', - dataIndex: 'issuer', - render: issuer => ( - {issuer} - ) - }, - { - title: 'Actions', - key: 'actions', - dataIndex: 'serialNumber', - render: (serialNumber) => ( - - {this.deleteCertificate(serialNumber)}} - okText="Ok" - cancelText="Cancel"> - - - - ) + data: res.data.data.certificates, + 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.', + }); } - ]; - render() { - const {data, pagination, loading} = this.state; + this.setState({ loading: false }); + }); + }; - return ( -
-
- record.serialNumber} - 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} - /> - - - ); - } + 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, + }); + }; + + deleteCertificate = serialNumber => { + axios + .delete( + window.location.origin + + config.serverConfig.invoker.uri + + '/certificate-mgt/v1.0/admin/certificates/' + + serialNumber, + { headers: { 'Content-Type': 'application/json' } }, + ) + .then(res => { + if (res.status === 200) { + this.fetch(); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully deleted the certificate.', + }); + } + }) + .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 delete the certificate.', + }); + } + }); + }; + + columns = [ + { + title: 'Serial Number', + dataIndex: 'serialNumber', + }, + { + title: 'Username', + dataIndex: 'username', + }, + { + title: 'Certificate Version', + dataIndex: 'certificateVersion', + }, + { + title: 'Certificate Serial', + dataIndex: 'certificateserial', + }, + { + title: 'Not Before', + dataIndex: 'notBefore', + render: notBefore => ( + + ), + }, + { + title: 'Not After', + dataIndex: 'notAfter', + render: notAfter => , + }, + { + title: 'Subject', + dataIndex: 'subject', + render: subject => ( + + {subject} + + ), + }, + { + title: 'Issuer', + dataIndex: 'issuer', + render: issuer => ( + + {issuer} + + ), + }, + { + title: 'Actions', + key: 'actions', + dataIndex: 'serialNumber', + render: serialNumber => ( + + { + this.deleteCertificate(serialNumber); + }} + okText="Ok" + cancelText="Cancel" + > + + + + + + + + ), + }, + ]; + + render() { + const { data, pagination, loading } = this.state; + + return ( +
+
+
record.serialNumber} + 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(CertificateTable); 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 19a7b3f1b6..ca122604ec 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 @@ -16,129 +16,115 @@ * under the License. */ -import React from "react"; -import axios from "axios"; -import {Card, Col, Icon, message, notification, Row, Typography} from "antd"; -import TimeAgo from 'javascript-time-ago' +import React from 'react'; +import axios from 'axios'; +import { Card, Col, Icon, message, notification, Row } 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 en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../context/ConfigContext'; -const {Text} = Typography; - -let config = null; let apiUrl; class DeviceTypesTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, + constructor(props) { + super(props); + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + selectedRows: [], + }; + } + + componentDidMount() { + this.fetchUsers(); + } + + // fetch data from api + fetchUsers = (params = {}) => { + const config = this.props.context; + this.setState({ loading: true }); + + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/device-types'; + + // send request to the invokerss + axios + .get(apiUrl) + .then(res => { + if (res.status === 200) { + const pagination = { ...this.state.pagination }; + this.setState({ loading: false, - selectedRows: [] - }; - } + data: JSON.parse(res.data.data), + 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 device types.', + }); + } - componentDidMount() { - this.fetchUsers(); - } + this.setState({ loading: false }); + }); + }; - //fetch data from api - fetchUsers = (params = {}) => { - const config = this.props.context; - this.setState({loading: true}); + 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, + }); + }; - // 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 + - "/device-types"; - - //send request to the invokerss - axios.get(apiUrl).then(res => { - if (res.status === 200) { - const pagination = {...this.state.pagination}; - this.setState({ - loading: false, - data: JSON.parse(res.data.data), - 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 device types.", - }); - } - - 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; - const { Meta } = Card; - const itemCard = data.map((data) => - - , - ,]} - > - } - title={data.name} - /> - - - - ); - return ( -
- - {itemCard} - -
- ); - } + render() { + const { data } = this.state; + const { Meta } = Card; + const itemCard = data.map(data => ( + + , + , + ]} + > + } + title={data.name} + /> + + + )); + return ( +
+ {itemCard} +
+ ); + } } -export default withConfigContext(DeviceTypesTable); \ No newline at end of file +export default withConfigContext(DeviceTypesTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/AddDevice.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/AddDevice.js index c466b6825b..350e2db478 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/AddDevice.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/AddDevice.js @@ -1,66 +1,56 @@ import React from 'react'; -import {Button, Form, Row, Col, Card, Steps, Input, message, Modal, notification, Typography} from "antd"; -import axios from "axios"; -import {withConfigContext} from "../../context/ConfigContext"; -import DeviceType from "./DeviceType"; -import EnrollAgent from "./EnrollAgent"; -const {Step} = Steps; +import { Form, Row, Col, Card, Steps } from 'antd'; +import { withConfigContext } from '../../context/ConfigContext'; +import DeviceType from './DeviceType'; +import EnrollAgent from './EnrollAgent'; +const { Step } = Steps; class AddDevice extends React.Component { - - constructor(props) { - super(props); - this.config = this.props.context; - this.state = { - isAddDeviceModalVisible: false, - current : 0, - } + constructor(props) { + super(props); + this.config = this.props.context; + this.state = { + isAddDeviceModalVisible: false, + current: 0, }; + } - onClickType = () =>{ - this.setState({ - current: 1, - }) - }; + onClickType = () => { + this.setState({ + current: 1, + }); + }; - openAddDeviceModal = () =>{ - this.setState({ - isAddDeviceModalVisible : true, - }) - }; + render() { + const { current } = this.state; + return ( +
+ +
+ + + + + + + + +
+ +
+
+ +
- render() { - const {loading, current, isError, supportedOsVersions, errorText, forbiddenErrors} = this.state; - const { getFieldDecorator } = this.props.form; - return ( -
- -
- - - - - - - - - -
- -
-
- -
- -
-
-
- - - - - ); - } +
+ + + + + ); + } } -export default withConfigContext(Form.create({name: 'add-device'})(AddDevice)); \ No newline at end of file +export default withConfigContext( + Form.create({ name: 'add-device' })(AddDevice), +); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/BulkActionBar.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/BulkActionBar.js index ca1d51a83a..1376608d44 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/BulkActionBar.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/BulkActionBar.js @@ -16,109 +16,118 @@ * under the License. */ -import React from "react"; -import {Button, Tooltip, Popconfirm, Divider} from "antd"; +import React from 'react'; +import { Button, Tooltip, Popconfirm, Divider } from 'antd'; class BulkActionBar extends React.Component { + constructor(props) { + super(props); + this.state = { + selectedMultiple: false, + selectedSingle: false, + canDelete: true, + }; + } - constructor(props) { - super(props); - this.state = { - selectedMultiple: false, - selectedSingle: false, - canDelete: true, - } + // This method checks whether NON-REMOVED devices are selected + onDeleteDeviceCall = () => { + let tempDeleteState; + for (let i = 0; i < this.props.selectedRows.length; i++) { + if (this.props.selectedRows[i].enrolmentInfo.status != 'REMOVED') { + tempDeleteState = false; + break; + } + tempDeleteState = true; } + this.setState({ canDelete: tempDeleteState }); + }; - //This method checks whether NON-REMOVED devices are selected - onDeleteDeviceCall = () => { - let tempDeleteState; - for(let i=0; i < this.props.selectedRows.length; i++){ - if(this.props.selectedRows[i].enrolmentInfo.status != "REMOVED"){ - tempDeleteState = false; - break; + onConfirmDelete = () => { + if (this.state.canDelete) { + this.props.deleteDevice(); + } + }; + + onConfirmDisenroll = () => { + this.props.disenrollDevice(); + }; + + onDeviceGroupCall = () => { + this.props.getGroups(); + }; + + render() { + const isSelected = this.props.selectedRows.length > 0; + const isSelectedSingle = this.props.selectedRows.length == 1; + + return ( +
+ + { - if (this.state.canDelete) { - this.props.deleteDevice(); - } - }; - - onConfirmDisenroll = () => { - this.props.disenrollDevice(); - }; - - onDeviceGroupCall = () => { - this.props.getGroups(); - } - - render() { - const isSelected = this.props.selectedRows.length > 0; - const isSelectedSingle = this.props.selectedRows.length == 1; - - return ( -
- - - - -
- ) - } + onConfirm={this.onConfirmDelete} + okText="Ok" + cancelText="Cancel" + > +
+ ); + } } -export default BulkActionBar; \ No newline at end of file +export default BulkActionBar; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DeviceType.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DeviceType.js index 627998a533..ece71df116 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DeviceType.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DeviceType.js @@ -16,133 +16,126 @@ * under the License. */ -import React from "react"; -import axios from "axios"; -import {Card, Col, Icon, message, notification, Row, Typography} from "antd"; -import TimeAgo from 'javascript-time-ago' +import React from 'react'; +import axios from 'axios'; +import { Card, Col, Icon, message, notification, Row } 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 en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../context/ConfigContext'; -const {Text} = Typography; - -let config = null; let apiUrl; class DeviceType extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, + constructor(props) { + super(props); + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + selectedRows: [], + }; + } + + componentDidMount() { + this.fetchUsers(); + } + + onClickCard = data => { + console.log(data); + this.props.onClickType(); + }; + + // fetch data from api + fetchUsers = (params = {}) => { + const config = this.props.context; + this.setState({ loading: true }); + + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/device-types'; + + // send request to the invokerss + axios + .get(apiUrl) + .then(res => { + if (res.status === 200) { + const pagination = { ...this.state.pagination }; + this.setState({ loading: false, - selectedRows: [] - }; - } + data: JSON.parse(res.data.data), + 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 device types.', + }); + } - componentDidMount() { - this.fetchUsers(); - } + this.setState({ loading: false }); + }); + }; - onClickCard = (data) =>{ - console.log(data); - this.props.onClickType(); - }; + 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, + }); + }; - //fetch data from api - fetchUsers = (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 + - "/device-types"; - - //send request to the invokerss - axios.get(apiUrl).then(res => { - if (res.status === 200) { - const pagination = {...this.state.pagination}; - this.setState({ - loading: false, - data: JSON.parse(res.data.data), - 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 device types.", - }); - } - - 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; - const { Meta } = Card; - const itemCard = data.map((data) => - - } - > - - - - - ); - return ( -
- - {itemCard} - -
- ); - } + render() { + const { data } = this.state; + const { Meta } = Card; + const itemCard = data.map(data => ( + + + } + > + + + + )); + return ( +
+ {itemCard} +
+ ); + } } -export default withConfigContext(DeviceType); \ No newline at end of file +export default withConfigContext(DeviceType); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DevicesTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DevicesTable.js index d129d6a601..f1de1fa0a4 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DevicesTable.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/DevicesTable.js @@ -16,471 +16,523 @@ * under the License. */ -import React from "react"; -import axios from "axios"; -import {Icon, message, Modal, notification, Select, Table, Tag, Tooltip, Typography} from "antd"; -import TimeAgo from 'javascript-time-ago' +import React from 'react'; +import axios from 'axios'; +import { + Icon, + message, + Modal, + notification, + Select, + 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 "../../context/ConfigContext"; -import BulkActionBar from "./BulkActionBar"; - -const {Text} = Typography; +import en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../context/ConfigContext'; +import BulkActionBar from './BulkActionBar'; let config = null; 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; + { + title: 'Device', + dataIndex: 'name', + width: 100, + }, + { + 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; - } + if (defaultPlatformIcons.hasOwnProperty(type)) { + icon = defaultPlatformIcons[type].icon; + color = defaultPlatformIcons[type].color; + theme = defaultPlatformIcons[type].theme; + } - return ( - - - - ); - } - // todo add filtering options + return ( + + + + ); }, - { - title: 'Owner', - dataIndex: 'enrolmentInfo', - key: 'owner', - render: enrolmentInfo => enrolmentInfo.owner - // todo add filtering options + // 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}; }, - { - title: 'Ownership', - dataIndex: 'enrolmentInfo', - key: 'ownership', - render: enrolmentInfo => enrolmentInfo.ownership - // todo add filtering options + // 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} + + ); }, - { - title: 'Status', - dataIndex: 'enrolmentInfo', - 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 - } + // todo add filtering options + }, ]; -const getTimeAgo = (time) => { - const timeAgo = new TimeAgo('en-US'); - return timeAgo.format(time); +const getTimeAgo = time => { + const timeAgo = new TimeAgo('en-US'); + return timeAgo.format(time); }; - class DeviceTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, + constructor(props) { + super(props); + config = this.props.context; + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + selectedRows: [], + deviceGroups: [], + groupModalVisible: false, + selectedGroupId: [], + selectedRowKeys: [], + }; + } + + 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, + }; + + 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, - selectedRows: [], - deviceGroups: [], - groupModalVisible: false, - selectedGroupId: [], - selectedRowKeys:[] - }; - } - - 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, - }; - - 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}); - }); - }; - - deleteDevice = () => { - const config = this.props.context; - this.setState({loading: true}); - - const deviceData = this.state.selectedRows.map(obj => obj.deviceIdentifier); - - //send request to the invoker - axios.put( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/admin/devices/permanent-delete", - deviceData, - {headers: {'Content-Type': 'application/json'}} - ).then(res => { - if (res.status === 200) { - this.fetch(); - } - }).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 delete devices.", - }); - } - - this.setState({loading: false}); - }); - }; - - disenrollDevice = () => { - const config = this.props.context; - this.setState({loading: true}); - - const deviceData = this.state.selectedRows[0]; - - //send request to the invoker - axios.delete( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/devices/type/" + deviceData.type + "/id/" + deviceData.deviceIdentifier, - {headers: {'Content-Type': 'application/json'}} - - ).then(res => { - if (res.status === 200) { - this.fetch(); - this.setState({ - selectedRowKeys:[] - }) - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully dis-enrolled the device.", - }); - } - }).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 dis-enroll devices.", - }); - } - - this.setState({loading: false}); - }); - }; - - addDevicesToGroup = (groupId) => { - const config = this.props.context; - this.setState({loading: true}); - - let apiUrl; - let deviceData; - if (this.state.selectedRows.length === 1) { - apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups/device/assign"; - deviceData = { - deviceIdentifier: { - id: this.state.selectedRows[0].deviceIdentifier, - type: this.state.selectedRows[0].type - }, - deviceGroupIds: groupId - } - } else if (!groupId[0]){ - apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups/id/" + groupId + "/devices/add"; - deviceData = this.state.selectedRows.map(obj => ({id: obj.deviceIdentifier, type: obj.type})); - } else{ - apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups/id/" + groupId[0] + "/devices/add"; - deviceData = this.state.selectedRows.map(obj => ({id: obj.deviceIdentifier, type: obj.type})); + 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.', + }); } - //send request to the invoker - axios.post( - apiUrl, - deviceData, - {headers: {'Content-Type': 'application/json'}} - ).then(res => { - if (res.status === 200) { - this.setState({ - loading: false - }); - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully added to the device group.", - }); - } - }).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 adding to the device group.", - }); - } + this.setState({ loading: false }); + }); + }; - this.setState({loading: false}); - }); - }; + deleteDevice = () => { + const config = this.props.context; + this.setState({ loading: true }); - getGroups = () => { - this.setState({ - groupModalVisible: true - }); - //send request to the invoker - axios.get( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups" - ).then(res => { - this.setState({deviceGroups: res.data.data.deviceGroups}) - }).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 retrieving device groups.", - }); - } + const deviceData = this.state.selectedRows.map(obj => obj.deviceIdentifier); - this.setState({loading: false}); - }); - }; - - handleOk = e => { - if(this.state.selectedGroupId){ - this.addDevicesToGroup(this.state.selectedGroupId); - this.setState({ - groupModalVisible: false - }); - }else{ - notification["error"]({ - message: "There was a problem", - duration: 0, - description: - "Please select a group.", - }); + // send request to the invoker + axios + .put( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/admin/devices/permanent-delete', + deviceData, + { headers: { 'Content-Type': 'application/json' } }, + ) + .then(res => { + if (res.status === 200) { + this.fetch(); + } + }) + .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 delete devices.', + }); } - }; + this.setState({ loading: false }); + }); + }; - handleCancel = e => { - this.setState({ - groupModalVisible: false, - }); - }; + disenrollDevice = () => { + const config = this.props.context; + this.setState({ loading: true }); - onGroupSelectChange = (value) => { - this.setState({selectedGroupId: value}); - }; + const deviceData = this.state.selectedRows[0]; - 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, - }); - }; - - onSelectChange = (selectedRowKeys, selectedRows) => { - this.setState({ - selectedRowKeys, - selectedRows: selectedRows - }); - }; - - render() { - const {data, pagination, loading, selectedRows, selectedRowKeys} = this.state; - const isSelectedSingle = this.state.selectedRows.length == 1; - - let selectedText; - if(isSelectedSingle){ - selectedText = "You have selected 1 device" - }else{ - selectedText = "You have selected " + this.state.selectedRows.length + " devices" + // send request to the invoker + axios + .delete( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/devices/type/' + + deviceData.type + + '/id/' + + deviceData.deviceIdentifier, + { headers: { 'Content-Type': 'application/json' } }, + ) + .then(res => { + if (res.status === 200) { + this.fetch(); + this.setState({ + selectedRowKeys: [], + }); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully dis-enrolled the device.', + }); + } + }) + .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 dis-enroll devices.', + }); } - const rowSelection = { - selectedRowKeys, - selectedRows, - onChange: this.onSelectChange, - }; + this.setState({ loading: false }); + }); + }; - let item = this.state.deviceGroups.map((data) => - - {data.name} - ); - return ( -
- -
-
(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} - rowSelection={rowSelection} - /> - + addDevicesToGroup = groupId => { + const config = this.props.context; + this.setState({ loading: true }); - -

{selectedText}

- -
- - ); + let apiUrl; + let deviceData; + if (this.state.selectedRows.length === 1) { + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups/device/assign'; + deviceData = { + deviceIdentifier: { + id: this.state.selectedRows[0].deviceIdentifier, + type: this.state.selectedRows[0].type, + }, + deviceGroupIds: groupId, + }; + } else if (!groupId[0]) { + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups/id/' + + groupId + + '/devices/add'; + deviceData = this.state.selectedRows.map(obj => ({ + id: obj.deviceIdentifier, + type: obj.type, + })); + } else { + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups/id/' + + groupId[0] + + '/devices/add'; + deviceData = this.state.selectedRows.map(obj => ({ + id: obj.deviceIdentifier, + type: obj.type, + })); } + + // send request to the invoker + axios + .post(apiUrl, deviceData, { + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => { + if (res.status === 200) { + this.setState({ + loading: false, + }); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully added to the device group.', + }); + } + }) + .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 adding to the device group.', + }); + } + + this.setState({ loading: false }); + }); + }; + + getGroups = () => { + this.setState({ + groupModalVisible: true, + }); + // send request to the invoker + axios + .get( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups', + ) + .then(res => { + this.setState({ deviceGroups: res.data.data.deviceGroups }); + }) + .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 retrieving device groups.', + }); + } + + this.setState({ loading: false }); + }); + }; + + handleOk = e => { + if (this.state.selectedGroupId) { + this.addDevicesToGroup(this.state.selectedGroupId); + this.setState({ + groupModalVisible: false, + }); + } else { + notification.error({ + message: 'There was a problem', + duration: 0, + description: 'Please select a group.', + }); + } + }; + + handleCancel = e => { + this.setState({ + groupModalVisible: false, + }); + }; + + onGroupSelectChange = value => { + this.setState({ selectedGroupId: value }); + }; + + 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, + }); + }; + + onSelectChange = (selectedRowKeys, selectedRows) => { + this.setState({ + selectedRowKeys, + selectedRows: selectedRows, + }); + }; + + render() { + const { + data, + pagination, + loading, + selectedRows, + selectedRowKeys, + } = this.state; + const isSelectedSingle = this.state.selectedRows.length == 1; + + let selectedText; + if (isSelectedSingle) { + selectedText = 'You have selected 1 device'; + } else { + selectedText = + 'You have selected ' + this.state.selectedRows.length + ' devices'; + } + + const rowSelection = { + selectedRowKeys, + selectedRows, + onChange: this.onSelectChange, + }; + + let item = this.state.deviceGroups.map(data => ( + + {data.name} + + )); + return ( +
+ +
+
+ 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} + rowSelection={rowSelection} + /> + + + +

{selectedText}

+ +
+ + ); + } } -export default withConfigContext(DeviceTable); \ No newline at end of file +export default withConfigContext(DeviceTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/EnrollAgent.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/EnrollAgent.js index bb710853ea..356be76612 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/EnrollAgent.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Devices/EnrollAgent.js @@ -1,87 +1,97 @@ import React from 'react'; -import {Collapse, Button, Divider, message, notification , Select} from 'antd'; -import TimeAgo from "javascript-time-ago/modules/JavascriptTimeAgo"; -import en from "javascript-time-ago/locale/en"; -import axios from "axios"; -import {withConfigContext} from "../../context/ConfigContext"; -const { Option } = Select; +import { Button, Divider, message, notification } from 'antd'; +import TimeAgo from 'javascript-time-ago/modules/JavascriptTimeAgo'; +import en from 'javascript-time-ago/locale/en'; +import axios from 'axios'; +import { withConfigContext } from '../../context/ConfigContext'; class EnrollAgent extends React.Component { - constructor(props) { - super(props); - this.config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, - loading: false, - selectedRows: [], - visibleSelector: {display : 'none'} - }; - } - componentDidMount() { - this.getConfigData(); + constructor(props) { + super(props); + this.config = this.props.context; + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + selectedRows: [], + visibleSelector: { display: 'none' }, }; + } + componentDidMount() { + this.getConfigData(); + } - onGetEnrollmentQR = () =>{ - this.setState({ - visibleSelector: {display : 'block'} - }) - }; + onGetEnrollmentQR = () => { + this.setState({ + visibleSelector: { display: 'block' }, + }); + }; - getConfigData = () =>{ - axios.get( - window.location.origin + this.config.serverConfig.invoker.uri + - "/device-mgt/android/v1.0/configuration" - ).then(res => { - let data = 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 retrieving device groups.", - }); - } + getConfigData = () => { + axios + .get( + window.location.origin + + this.config.serverConfig.invoker.uri + + '/device-mgt/android/v1.0/configuration', + ) + .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 retrieving device groups.', + }); + } + }); + }; - }); - }; + render() { + return ( +
+ Step 01 - Get your Android Agent. +
+

+ The Android agent can be downloaded by using following QR. The + generated QR code can be scanned, and the agent APK downloaded from + the link, and transferred to the device and then installed. +

+
+
+ +
+ + Step 02 - Enroll the Android Agent. + - render() { - return ( -
- Step 01 - Get your Android Agent. -
-

The Android agent can be downloaded by using following QR. - The generated QR code can be scanned, and the agent APK downloaded from the link, - and transferred to the device and then installed.

-
-
- -
- Step 02 - Enroll the Android Agent. - -
-

Your device can be enrolled with Entgra IoTS automatically via QR code. - To enroll first download agent as mentioned in Step 1 then proceed with the ENROLL WITH - QR option from the device setup activity. Thereafter select the ownership configuration - and scan the generated QR to complete the process.

-
-
- -
-
- ); - } +
+

+ {' '} + Your device can be enrolled with Entgra IoTS automatically via QR + code. To enroll first download agent as mentioned in Step 1 then + proceed with the ENROLL WITH QR option from the device setup + activity. Thereafter select the ownership configuration and scan the + generated QR to complete the process. +

+
+
+ +
+
+ ); + } } -export default withConfigContext(EnrollAgent); \ No newline at end of file +export default withConfigContext(EnrollAgent); 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 61a8635564..98535a4adb 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 @@ -16,232 +16,252 @@ * under the License. */ -import React from "react"; -import axios from "axios"; -import {Icon, message, notification, Table, Tag, Tooltip, Typography} from "antd"; -import TimeAgo from 'javascript-time-ago' +import React from 'react'; +import axios from 'axios'; +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 "../../context/ConfigContext"; - -const {Text} = Typography; +import en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../context/ConfigContext'; 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; + { + title: 'Device', + dataIndex: 'name', + width: 100, + }, + { + 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; - } + if (defaultPlatformIcons.hasOwnProperty(type)) { + icon = defaultPlatformIcons[type].icon; + color = defaultPlatformIcons[type].color; + theme = defaultPlatformIcons[type].theme; + } - return ( - - - - ); - } - // todo add filtering options + return ( + + + + ); }, - { - title: 'Owner', - dataIndex: 'enrolmentInfo', - key: 'owner', - render: enrolmentInfo => enrolmentInfo.owner - // todo add filtering options + // 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}; }, - { - title: 'Ownership', - dataIndex: 'enrolmentInfo', - key: 'ownership', - render: enrolmentInfo => enrolmentInfo.ownership - // todo add filtering options + // 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} + + ); }, - { - title: 'Status', - dataIndex: 'enrolmentInfo', - 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 - } + // todo add filtering options + }, ]; -const getTimeAgo = (time) => { - const timeAgo = new TimeAgo('en-US'); - return timeAgo.format(time); +const getTimeAgo = time => { + const timeAgo = new TimeAgo('en-US'); + return timeAgo.format(time); }; class ReportDeviceTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, + 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.fetch(); + } + + // Rerender component when parameters change + componentDidUpdate(prevProps, prevState, snapshot) { + if (prevProps.paramsObject !== this.props.paramsObject) { + 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; + + this.props.paramsObject.offset = 10 * (currentPage - 1); // calculate the offset + this.props.paramsObject.limit = 10; + + const encodedExtraParams = Object.keys(this.props.paramsObject) + .map(key => key + '=' + this.props.paramsObject[key]) + .join('&'); + + if ( + this.props.paramsObject.from == null && + this.props.paramsObject.to == null + ) { + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/devices?' + + encodedExtraParams; + } else { + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/reports/devices?' + + encodedExtraParams; + } + + // send request to the invokerss + axios + .get(apiUrl) + .then(res => { + if (res.status === 200) { + const pagination = { ...this.state.pagination }; + this.setState({ loading: false, - selectedRows: [], - paramsObj:{} - }; - } - - rowSelection = { - onChange: (selectedRowKeys, selectedRows) => { - this.setState({ - selectedRows: selectedRows - }) + data: res.data.data.devices, + pagination, + }); } - }; - - componentDidMount() { - this.fetch(); - } - - //Rerender component when parameters change - componentDidUpdate(prevProps, prevState, snapshot) { - if(prevProps.paramsObject !== this.props.paramsObject){ - 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; - - this.props.paramsObject.offset = 10 * (currentPage -1); //calculate the offset - this.props.paramsObject.limit = 10; - - const encodedExtraParams = Object.keys(this.props.paramsObject) - .map(key => key + '=' + this.props.paramsObject[key]).join('&'); - - if(this.props.paramsObject.from==null && this.props.paramsObject.to==null){ - apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/devices?" + encodedExtraParams; - - }else{ - apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/reports/devices?" + encodedExtraParams; + }) + .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.', + }); } - //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.devices, - pagination, - }); - } + this.setState({ loading: false }); + }); + }; - }).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.", - }); - } + 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, + }); + }; - 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} - 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} - /> - - ); - } + render() { + const { data, pagination, loading } = this.state; + return ( +
+
+ 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} + rowSelection={this.rowSelection} + /> + + ); + } } -export default withConfigContext(ReportDeviceTable); \ No newline at end of file +export default withConfigContext(ReportDeviceTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js index 3c68ee0aaa..d16fc073f5 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js @@ -16,66 +16,64 @@ * under the License. */ -import React, {Component, Fragment} from "react"; +import React, { Component, Fragment } from 'react'; import { - Map, - TileLayer, - Marker, - Polyline, Popup, Tooltip -} from "react-leaflet"; -import {withConfigContext} from "../../../context/ConfigContext"; + Map, + TileLayer, + Marker, + Polyline, + Popup, + Tooltip, +} from 'react-leaflet'; +import { withConfigContext } from '../../../context/ConfigContext'; class GeoCustomMap extends Component { + constructor(props) { + super(props); + } - constructor(props) { - super(props); - } + /** + * Polyline draw for historical locations + * @param locationData - location data object + * @returns content + */ + polylineMarker = locationData => { + const polyMarkers = locationData.map(locationPoint => { + return [locationPoint.latitude, locationPoint.longitude]; + }); - /** - * Polyline draw for historical locations - * @param locationData - location data object - * @returns content - */ - polylineMarker = (locationData) => { + return ( +
+ { + + on the way + + } +
+ ); + }; - const polyMarkers = locationData - .map(locationPoint => { - return [locationPoint.latitude, locationPoint.longitude] - }); - - return ( -
{ - - on the way - - }
- ); - }; - - render() { - const locationData = this.props.locationData; - const config = this.props.context; - const attribution = config.geoMap.attribution; - const url = config.geoMap.url; - const startingPoint = [locationData[0].latitude, locationData[0].longitude]; - const zoom = config.geoMap.defaultZoomLevel; - return ( -
- - - - {this.polylineMarker(locationData)} - - Starting Location - - - -
- ); - } + render() { + const locationData = this.props.locationData; + const config = this.props.context; + const attribution = config.geoMap.attribution; + const url = config.geoMap.url; + const startingPoint = [locationData[0].latitude, locationData[0].longitude]; + const zoom = config.geoMap.defaultZoomLevel; + return ( +
+ + + + {this.polylineMarker(locationData)} + + Starting Location + + + +
+ ); + } } export default withConfigContext(GeoCustomMap); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-dashboard/GeoDashboard.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-dashboard/GeoDashboard.js index 07be907074..bf0ed0dcdd 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-dashboard/GeoDashboard.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-dashboard/GeoDashboard.js @@ -16,266 +16,300 @@ * under the License. */ -import React from "react"; -import moment from "moment"; -import {Button, Select, message, notification, Tag, Tooltip, Empty, DatePicker} from "antd"; -import axios from "axios"; -import {withConfigContext} from "../../../context/ConfigContext"; -import GeoCustomMap from "../geo-custom-map/GeoCustomMap"; -import "./GeoDashboard.css"; +import React from 'react'; +import moment from 'moment'; +import { + Button, + Select, + message, + notification, + Tag, + Tooltip, + Empty, + DatePicker, +} from 'antd'; +import axios from 'axios'; +import { withConfigContext } from '../../../context/ConfigContext'; +import GeoCustomMap from '../geo-custom-map/GeoCustomMap'; +import './GeoDashboard.css'; class GeoDashboard extends React.Component { - - constructor(props) { - super(props); - let start = moment( - new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 0, 0, 0, 0) - ); - let end = moment(start) - .add(1, "days") - .subtract(1, "seconds"); - this.state = { - deviceData: [], - selectedDevice: '', - locationData: [], - loading: false, - start: start, - end: end, - buttonTooltip: "Fetch Locations", - }; - } - - componentDidMount() { - this.fetchDevices(); - // this.fetchCurrentLocation(); - } - - /** - * Call back on apply button in the date time picker - * @param startDate - start date - * @param endDate - end date - */ - applyCallback = (dates, dateStrings) => { - console.log("Apply Callback"); - this.setState({ - start: dateStrings[0], - end: dateStrings[1] - }); + constructor(props) { + super(props); + let start = moment( + new Date( + new Date().getFullYear(), + new Date().getMonth(), + new Date().getDate(), + 0, + 0, + 0, + 0, + ), + ); + let end = moment(start) + .add(1, 'days') + .subtract(1, 'seconds'); + this.state = { + deviceData: [], + selectedDevice: '', + locationData: [], + loading: false, + start: start, + end: end, + buttonTooltip: 'Fetch Locations', }; + } - /** - * Api call handle on fetch location date button - */ - handleApiCall = () => { + componentDidMount() { + this.fetchDevices(); + // this.fetchCurrentLocation(); + } - if (this.state.selectedDevice && this.state.start && this.state.end) { - const toInMills = moment(this.state.end); - const fromInMills = moment(this.state.start); - const deviceType = this.state.selectedDevice.type; - const deviceId = this.state.selectedDevice.deviceIdentifier; - const config = this.props.context; - this.setState({loading: true}); + /** + * Call back on apply button in the date time picker + * @param startDate - start date + * @param endDate - end date + */ + applyCallback = (dates, dateStrings) => { + console.log('Apply Callback'); + this.setState({ + start: dateStrings[0], + end: dateStrings[1], + }); + }; - axios.get(window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt - + "/devices/" + deviceType + "/" + deviceId + "/location-history?" + "from=" + fromInMills + "&to=" + - toInMills,).then(res => { - if (res.status === 200) { - const locationData = JSON.parse(res.data.data); - this.setState({ - loading: false, - locationData, - }); - } - }).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 fetch locations......", - }); - } + /** + * Api call handle on fetch location date button + */ + handleApiCall = () => { + if (this.state.selectedDevice && this.state.start && this.state.end) { + const toInMills = moment(this.state.end); + const fromInMills = moment(this.state.start); + const deviceType = this.state.selectedDevice.type; + const deviceId = this.state.selectedDevice.deviceIdentifier; + const config = this.props.context; + this.setState({ loading: true }); - this.setState({loading: false}); - console.log(error); + axios + .get( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/devices/' + + deviceType + + '/' + + deviceId + + '/location-history?' + + 'from=' + + fromInMills + + '&to=' + + toInMills, + ) + .then(res => { + if (res.status === 200) { + const locationData = JSON.parse(res.data.data); + this.setState({ + loading: false, + locationData, }); - } else { - notification["error"]({ - message: "There was a problem", - duration: 0, - description: - "Please provide a date range and a device.", - }); - } - }; + } + }) + .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 fetch locations......', + }); + } - /** - * Device dropdown list handler - * @param e - selected device data - */ - handleDeviceList = (e) => { - let selectedDevice = this.state.deviceData[e]; - this.setState({selectedDevice}) - }; - - /** - * render fetch location button - */ - fetchLocationButton = () => { - let flag; - let toolTip = ""; - if (this.state.selectedDevice === "") { - flag = true; - toolTip = "Please select a Device"; - } - return ( - - - ); - - }; - - /** - * fetches device data to populate the dropdown list - */ - fetchDevices = () => { - const config = this.props.context; - this.setState({loading: true}); - - axios.get( - window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt + - "/devices?excludeStatus=REMOVED",).then(res => { - if (res.status === 200) { - this.setState({ - loading: false, - deviceData: res.data.data.devices, - }); - } - - }).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 devices.", - }); - } - - this.setState({loading: false}); + this.setState({ loading: false }); + console.log(error); }); - }; + } else { + notification.error({ + message: 'There was a problem', + duration: 0, + description: 'Please provide a date range and a device.', + }); + } + }; - /** - * Geo Dashboard controller - */ - controllerBar = () => { + /** + * Device dropdown list handler + * @param e - selected device data + */ + handleDeviceList = e => { + let selectedDevice = this.state.deviceData[e]; + this.setState({ selectedDevice }); + }; - const {RangePicker} = DatePicker; - let now = new Date(); - let start = moment( - new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0) - ); - let end = moment(start) - .add(1, "days") - .subtract(1, "seconds"); - let ranges = { - "Today Only": [moment(start), moment(end)], - "Yesterday Only": [ - moment(start).subtract(1, "days"), - moment(end).subtract(1, "days") - ], - "3 Days": [moment(start).subtract(3, "days"), moment(end)], - "5 Days": [moment(start).subtract(5, "days"), moment(end)], - "1 Week": [moment(start).subtract(7, "days"), moment(end)], - "2 Weeks": [moment(start).subtract(14, "days"), moment(end)], - "1 Month": [moment(start).subtract(1, "months"), moment(end)], - }; + /** + * render fetch location button + */ + fetchLocationButton = () => { + let flag; + let toolTip = ''; + if (this.state.selectedDevice === '') { + flag = true; + toolTip = 'Please select a Device'; + } + return ( + + + + ); + }; - let {deviceData} = this.state; + /** + * fetches device data to populate the dropdown list + */ + fetchDevices = () => { + const config = this.props.context; + this.setState({ loading: true }); - return ( -
- - - - - {this.fetchLocationButton()} -
- ); - }; - - /** - * Creates color based tags on device status - * @param device - device object - */ - statusTag = (device) => { - - const status = device.enrolmentInfo.status.toLowerCase(); - let color = "#f9ca24"; - switch (status) { - case "active": - color = "#badc58"; - break; - case "created": - color = "#6ab04c"; - break; - case "inactive": - color = "#f9ca24"; - break; - case "blocked": - color = "#636e72"; - break; + axios + .get( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/devices?excludeStatus=REMOVED', + ) + .then(res => { + if (res.status === 200) { + this.setState({ + loading: false, + deviceData: res.data.data.devices, + }); + } + }) + .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 devices.', + }); } - return {status} + this.setState({ loading: false }); + }); + }; + + /** + * Geo Dashboard controller + */ + controllerBar = () => { + const { RangePicker } = DatePicker; + let now = new Date(); + let start = moment( + new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0), + ); + let end = moment(start) + .add(1, 'days') + .subtract(1, 'seconds'); + let ranges = { + 'Today Only': [moment(start), moment(end)], + 'Yesterday Only': [ + moment(start).subtract(1, 'days'), + moment(end).subtract(1, 'days'), + ], + '3 Days': [moment(start).subtract(3, 'days'), moment(end)], + '5 Days': [moment(start).subtract(5, 'days'), moment(end)], + '1 Week': [moment(start).subtract(7, 'days'), moment(end)], + '2 Weeks': [moment(start).subtract(14, 'days'), moment(end)], + '1 Month': [moment(start).subtract(1, 'months'), moment(end)], }; - render() { - const locationData = [...this.state.locationData]; + let { deviceData } = this.state; - return ( -
- {this.controllerBar()} - {(locationData.length > 0) ? - - : - - } -
- ); + return ( +
+ + + + + {this.fetchLocationButton()} +
+ ); + }; + + /** + * Creates color based tags on device status + * @param device - device object + */ + statusTag = device => { + const status = device.enrolmentInfo.status.toLowerCase(); + let color = '#f9ca24'; + switch (status) { + case 'active': + color = '#badc58'; + break; + case 'created': + color = '#6ab04c'; + break; + case 'inactive': + color = '#f9ca24'; + break; + case 'blocked': + color = '#636e72'; + break; } + + return {status}; + }; + + render() { + const locationData = [...this.state.locationData]; + + return ( +
+ {this.controllerBar()} + {locationData.length > 0 ? ( + + ) : ( + + )} +
+ ); + } } export default withConfigContext(GeoDashboard); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/AddGroup.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/AddGroup.js index d828d20a88..a132361fd3 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/AddGroup.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/AddGroup.js @@ -16,160 +16,159 @@ * under the License. */ -import React from "react"; -import {Button, Form, Input, message, Modal, notification, Typography} from "antd"; -import axios from "axios"; -import {withConfigContext} from "../../context/ConfigContext"; - -const {Text} = Typography; -let config = null; +import React from 'react'; +import { Button, Form, Input, message, Modal, notification } from 'antd'; +import axios from 'axios'; +import { withConfigContext } from '../../context/ConfigContext'; class AddGroup extends React.Component { + constructor(props) { + super(props); + this.state = { + addModalVisible: false, + name: '', + description: '', + }; + } - constructor(props) { - super(props); - config = this.props.context; - this.state = { - addModalVisible: false, - name:'', - description:'', + onConfirmAdGroup = () => { + const config = this.props.context; + + const groupData = { + name: this.state.name, + description: this.state.description, + }; + + // send request to the invoker + axios + .post( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups', + groupData, + { headers: { 'Content-Type': 'application/json' } }, + ) + .then(res => { + if (res.status === 201) { + this.props.fetchGroups(); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully added the group.', + }); } - } - - onConfirmAdGroup = () => { - const config = this.props.context; - - const groupData = { - name: this.state.name, - description: this.state.description + }) + .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 add group.', + }); } + }); + }; - //send request to the invoker - axios.post( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups", - groupData, - {headers: {'Content-Type': 'application/json'}} - ).then(res => { - if (res.status === 201) { - this.props.fetchGroups(); - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully added the group.", - }); - } - }).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 add group.", - }); - } + openAddModal = () => { + this.setState({ + addModalVisible: true, + }); + }; + + handleAddOk = e => { + this.props.form.validateFields(err => { + if (!err) { + this.onConfirmAdGroup(); + this.setState({ + addModalVisible: false, }); - }; + } + }); + }; - openAddModal = () => { - this.setState({ - addModalVisible:true - }) - }; + handleAddCancel = e => { + this.setState({ + addModalVisible: false, + }); + }; - handleAddOk = e => { - this.props.form.validateFields(err => { - if (!err) { - this.onConfirmAdGroup(); - this.setState({ - addModalVisible: false, - }); - } - }); - }; + onChangeName = e => { + this.setState({ + name: e.currentTarget.value, + }); + }; - handleAddCancel = e => { - this.setState({ - addModalVisible: false, - }); - }; + onChangeDescription = e => { + this.setState({ + description: e.currentTarget.value, + }); + }; - onChangeName = (e) => { - this.setState({ - name:e.currentTarget.value - }) - }; - - onChangeDescription = (e) => { - this.setState({ - description:e.currentTarget.value - }) - }; - - render() { - const { getFieldDecorator } = this.props.form; - return( -
-
- -
-
- - Cancel - , - , - ]} - > -
-

Create new device group on IoT Server.

-
- - {getFieldDecorator('name', { - rules: [ - { - required: true, - message: 'Please input group name', - }, - ], - })()} - - - {getFieldDecorator('description', { - rules: [ - { - required: true, - message: 'Please input group description', - }, - ], - })()} - - -
-
-
+ render() { + const { getFieldDecorator } = this.props.form; + return ( +
+
+ +
+
+ + Cancel + , + , + ]} + > +
+

Create new device group on IoT Server.

+
+ + {getFieldDecorator('name', { + rules: [ + { + required: true, + message: 'Please input group name', + }, + ], + })()} + + + {getFieldDecorator('description', { + rules: [ + { + required: true, + message: 'Please input group description', + }, + ], + })()} + +
- ) - } +
+
+
+ ); + } } -export default withConfigContext(Form.create({name: 'add-group'})(AddGroup)); \ No newline at end of file +export default withConfigContext(Form.create({ name: 'add-group' })(AddGroup)); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupActions.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupActions.js index b82489a14a..b9e2d4a6c5 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupActions.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupActions.js @@ -16,364 +16,380 @@ * under the License. */ -import React from "react"; +import React from 'react'; import { - Button, - Divider, - Form, - Icon, - Input, - message, - Modal, - notification, - Popconfirm, - Select, - Tooltip, - Typography -} from "antd"; -import axios from "axios"; -import {withConfigContext} from "../../context/ConfigContext"; + Button, + Divider, + Form, + Icon, + Input, + message, + Modal, + notification, + Popconfirm, + Select, + Tooltip, + Typography, +} from 'antd'; +import axios from 'axios'; +import { withConfigContext } from '../../context/ConfigContext'; -const {Text} = Typography; -let config = null; +const { Text } = Typography; class GroupActions extends React.Component { + constructor(props) { + super(props); + this.state = { + editModalVisible: false, + shareModalVisible: false, + name: this.props.data.name, + description: this.props.data.description, + groupDataObject: {}, + rolesData: [], + shareRolesData: [], + }; + } - constructor(props) { - super(props); - config = this.props.context; - this.state = { - editModalVisible: false, - shareModalVisible: false, - name:this.props.data.name, - description:this.props.data.description, - groupDataObject:{}, - rolesData:[], - shareRolesData:[] + onConfirmDeleteGroup = () => { + const config = this.props.context; + + // send request to the invoker + axios + .delete( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups/id/' + + this.props.data.id, + { headers: { 'Content-Type': 'application/json' } }, + ) + .then(res => { + if (res.status === 200) { + this.props.fetchGroups(); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully deleted the group.', + }); } - } + }) + .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 delete group.', + }); + } + }); + }; - onConfirmDeleteGroup = () => { - const config = this.props.context; + onConfirmUpdateGroup = data => { + const config = this.props.context; - //send request to the invoker - axios.delete( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups/id/" + this.props.data.id, - {headers: {'Content-Type': 'application/json'}} + // send request to the invoker + axios + .put( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups/id/' + + this.props.data.id, + data, + ) + .then(res => { + if (res.status === 200) { + this.props.fetchGroups(); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully updated the group.', + }); + } + }) + .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 update group.', + }); + } + }); + }; - ).then(res => { - if (res.status === 200) { - this.props.fetchGroups(); - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully deleted the group.", - }); - } - }).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 delete group.", - }); - } - }); + fetchUserRoles = (params = {}) => { + const config = this.props.context; + + const apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/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.', + }); + } + }); + }; + + onConfirmShareGroup = data => { + const config = this.props.context; + + // send request to the invoker + axios + .post( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/groups/id/' + + this.props.data.id + + '/share', + data, + ) + .then(res => { + if (res.status === 200) { + this.props.fetchGroups(); + notification.success({ + message: 'Done', + duration: 4, + description: 'Successfully shared the group.', + }); + } + }) + .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 share group.', + }); + } + }); + }; + + openEditModal = () => { + this.setState({ + editModalVisible: true, + }); + }; + + openShareModal = () => { + this.fetchUserRoles(); + this.setState({ + shareModalVisible: true, + }); + }; + + handleEditOk = e => { + const groupDataObject = { + name: this.state.name, + description: this.state.description, + id: this.props.data.id, + owner: this.props.data.owner, + groupProperties: this.props.data.groupProperties, }; - onConfirmUpdateGroup = (data) => { - const config = this.props.context; + this.setState({ groupDataObject }); - //send request to the invoker - axios.put( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups/id/" + this.props.data.id, - data - ).then(res => { - if (res.status === 200) { - this.props.fetchGroups(); - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully updated the group.", - }); - } - }).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 update group.", - }); - } - }); - }; - - fetchUserRoles = (params = {}) => { - const config = this.props.context; - - const apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/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.", - }); - } - }); - }; - - onConfirmShareGroup = (data) => { - const config = this.props.context; - - //send request to the invoker - axios.post( - window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/groups/id/" + this.props.data.id + "/share", - data - ).then(res => { - if (res.status === 200) { - this.props.fetchGroups(); - notification["success"]({ - message: "Done", - duration: 4, - description: - "Successfully shared the group.", - }); - } - }).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 share group.", - }); - } - }); - } - - openEditModal = () => { + this.props.form.validateFields(err => { + if (!err) { + this.onConfirmUpdateGroup(this.state.groupDataObject); this.setState({ - editModalVisible:true - }) - }; - - openShareModal = () => { - this.fetchUserRoles(); - this.setState({ - shareModalVisible:true - }) - } - - handleEditOk = e => { - this.state.groupDataObject = { - name:this.state.name, - description:this.state.description, - id:this.props.data.id, - owner:this.props.data.owner, - groupProperties:this.props.data.groupProperties - }; - this.props.form.validateFields(err => { - if (!err) { - this.onConfirmUpdateGroup(this.state.groupDataObject); - this.setState({ - editModalVisible: false, - }); - } + editModalVisible: false, }); - }; + } + }); + }; - handleEditCancel = e => { - this.setState({ - editModalVisible: false, - }); - }; + handleEditCancel = e => { + this.setState({ + editModalVisible: false, + }); + }; - handleShareOk = e => { - this.setState({ - shareModalVisible: false, - }); - this.onConfirmShareGroup(this.state.shareRolesData); - }; + handleShareOk = e => { + this.setState({ + shareModalVisible: false, + }); + this.onConfirmShareGroup(this.state.shareRolesData); + }; - handleShareCancel = e => { - this.setState({ - shareModalVisible: false, - }); - }; + handleShareCancel = e => { + this.setState({ + shareModalVisible: false, + }); + }; - onChangeName = (e) => { - this.setState({ - name:e.currentTarget.value - }) - }; + onChangeName = e => { + this.setState({ + name: e.currentTarget.value, + }); + }; - onChangeDescription = (e) => { - this.setState({ - description:e.currentTarget.value - }) - }; + onChangeDescription = e => { + this.setState({ + description: e.currentTarget.value, + }); + }; - handleRolesDropdownChange = (value) => { - this.setState({ - shareRolesData:value - }) - }; + handleRolesDropdownChange = value => { + this.setState({ + shareRolesData: value, + }); + }; - render() { - const isAdminGroups = this.props.data.id==1 || this.props.data.id==2; - const { Option } = Select; - const { getFieldDecorator } = this.props.form; - let item = this.state.rolesData.map((data) => - - {data} - ); - return( -
-
- - - - - - - - - - - - - -
-
- - Cancel - , - , - ]} - > -
-

Enter new name and description for the group

-
- - {getFieldDecorator( - 'name', - { - initialValue: this.props.data.name, - rules: [ - { - required: true, - message: 'Please input group name', - }, - ], - })()} - - - {getFieldDecorator( - 'description', - { - initialValue: this.props.data.description, - rules: [ - { - required: true, - message: 'Please input group description', - }, - ], - })()} - - -
-
-
-
- - New Role - , - , - , - ]} - > -

Select user role(s)

- , -
-
+ render() { + const isAdminGroups = this.props.data.id == 1 || this.props.data.id == 2; + const { getFieldDecorator } = this.props.form; + let item = this.state.rolesData.map(data => ( + + {data} + + )); + return ( +
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+ + Cancel + , + , + ]} + > +
+

Enter new name and description for the group

+
+ + {getFieldDecorator('name', { + initialValue: this.props.data.name, + rules: [ + { + required: true, + message: 'Please input group name', + }, + ], + })()} + + + {getFieldDecorator('description', { + initialValue: this.props.data.description, + rules: [ + { + required: true, + message: 'Please input group description', + }, + ], + })()} + +
- ) - } +
+
+
+ + New Role + , + , + , + ]} + > +

Select user role(s)

+ + , +
+
+
+ ); + } } -export default withConfigContext(Form.create({name: 'group-actions'})(GroupActions)); \ No newline at end of file +export default withConfigContext( + Form.create({ name: 'group-actions' })(GroupActions), +); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupsTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupsTable.js index df3a4c6211..23768c48b0 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupsTable.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Groups/GroupsTable.js @@ -16,193 +16,191 @@ * under the License. */ -import React from "react"; -import axios from "axios"; -import {message, notification, Table, Typography} from "antd"; -import TimeAgo from 'javascript-time-ago' +import React from 'react'; +import axios from 'axios'; +import { message, notification, Table } 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 GroupActions from "./GroupActions"; -import AddGroup from "./AddGroup"; -import Filter from "../Utils/Filter/Filter"; - -const {Text} = Typography; +import en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../context/ConfigContext'; +import GroupActions from './GroupActions'; +import AddGroup from './AddGroup'; +import Filter from '../Utils/Filter/Filter'; const searchFields = [ - { - name: 'name', - placeholder: 'Name' - }, - { - name: 'owner', - placeholder: 'Owner' - } + { + name: 'name', + placeholder: 'Name', + }, + { + name: 'owner', + placeholder: 'Owner', + }, ]; -let config = null; let apiUrl; -const getTimeAgo = (time) => { - const timeAgo = new TimeAgo('en-US'); - return timeAgo.format(time); -}; - class GroupsTable extends React.Component { - constructor(props) { - super(props); - config = this.props.context; - TimeAgo.addLocale(en); - this.state = { - data: [], - pagination: {}, + constructor(props) { + super(props); + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + selectedRows: [], + }; + } + + columns = [ + { + title: 'Group Name', + dataIndex: 'name', + width: 100, + }, + { + title: 'Owner', + dataIndex: 'owner', + key: 'owner', + // render: enrolmentInfo => enrolmentInfo.owner + // todo add filtering options + }, + { + title: 'Description', + dataIndex: 'description', + key: 'description', + // render: enrolmentInfo => enrolmentInfo.ownership + // todo add filtering options + }, + { + title: 'Action', + dataIndex: 'id', + key: 'action', + render: (id, row) => ( + + + + ), + }, + ]; + + rowSelection = { + onChange: (selectedRowKeys, selectedRows) => { + this.setState({ + selectedRows: selectedRows, + }); + }, + }; + + componentDidMount() { + this.fetchGroups(); + } + + // fetch data from api + fetchGroups = (params = {}, filters = {}) => { + 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, + ...filters, + }; + + const encodedExtraParams = Object.keys(extraParams) + .map(key => key + '=' + extraParams[key]) + .join('&'); + + apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/admin/groups?' + + encodedExtraParams; + + // send request to the invokerss + axios + .get(apiUrl) + .then(res => { + if (res.status === 200) { + const pagination = { ...this.state.pagination }; + this.setState({ loading: false, - selectedRows: [] - }; - } - - columns = [ - { - title: 'Group Name', - dataIndex: 'name', - width: 100, - }, - { - title: 'Owner', - dataIndex: 'owner', - key: 'owner', - // render: enrolmentInfo => enrolmentInfo.owner - // todo add filtering options - }, - { - title: 'Description', - dataIndex: 'description', - key: 'description', - // render: enrolmentInfo => enrolmentInfo.ownership - // todo add filtering options - }, - { - title: 'Action', - dataIndex: 'id', - key: 'action', - render: (id, row) => ( - - - - ), - }, - ]; - - rowSelection = { - onChange: (selectedRowKeys, selectedRows) => { - this.setState({ - selectedRows: selectedRows - }) + data: res.data.data, + 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 device groups.', + }); } - }; - componentDidMount() { - this.fetchGroups(); - } + this.setState({ loading: false }); + }); + }; - //fetch data from api - fetchGroups = (params = {}, filters = {}) => { - const config = this.props.context; - this.setState({loading: true}); + handleTableChange = (pagination, filters, sorter) => { + const pager = { ...this.state.pagination }; + pager.current = pagination.current; + this.setState({ + pagination: pager, + }); + this.fetchGroups({ + results: pagination.pageSize, + page: pagination.current, + sortField: sorter.field, + sortOrder: sorter.order, + ...filters, + }); + }; - // get current page - const currentPage = (params.hasOwnProperty("page")) ? params.page : 1; + render() { + const { data, pagination, loading } = this.state; - const extraParams = { - offset: 10 * (currentPage - 1), //calculate the offset - limit: 10, - ...filters - }; - - const encodedExtraParams = Object.keys(extraParams) - .map(key => key + '=' + extraParams[key]).join('&'); - - apiUrl = window.location.origin + config.serverConfig.invoker.uri + - config.serverConfig.invoker.deviceMgt + - "/admin/groups?" + 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, - 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 device groups.", - }); - } - - this.setState({loading: false}); - }); - }; - - - - handleTableChange = (pagination, filters, sorter) => { - const pager = {...this.state.pagination}; - pager.current = pagination.current; - this.setState({ - pagination: pager, - }); - this.fetchGroups({ - 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.deviceGroups} - pagination={{ - ...pagination, - size: "small", - total: data.count, - pageSize: 10, - showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups` - }} - loading={loading} - onChange={this.handleTableChange} - rowSelection={this.rowSelection} - /> - - - ); - } + return ( +
+
+ +
+
+ +
+
+
record.id} + dataSource={data.deviceGroups} + pagination={{ + ...pagination, + size: 'small', + total: data.count, + pageSize: 10, + showTotal: (total, range) => + `showing ${range[0]}-${range[1]} of ${total} groups`, + }} + loading={loading} + onChange={this.handleTableChange} + rowSelection={this.rowSelection} + /> + + + ); + } } export default withConfigContext(GroupsTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/AddPolicy.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/AddPolicy.js index dbc5d89642..ecbd403ffa 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/AddPolicy.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/AddPolicy.js @@ -1,104 +1,86 @@ import React from 'react'; -import {Button, Form, Row, Col, Card, Steps, Input, message, Modal, notification, Typography} from "antd"; -import axios from "axios"; -import {withConfigContext} from "../../context/ConfigContext"; -import DeviceType from "../Devices/DeviceType"; -import SelectPlatform from "./SelectPlatform"; -import ConfigureProfile from "./ConfigureProfile"; -const {Step} = Steps; +import { Button, Form, Row, Col, Card, Steps } from 'antd'; +import { withConfigContext } from '../../context/ConfigContext'; +import SelectPlatform from './SelectPlatform'; +import ConfigureProfile from './ConfigureProfile'; +const { Step } = Steps; class AddPolicy extends React.Component { - - constructor(props) { - super(props); - this.config = this.props.context; - this.state = { - isAddDeviceModalVisible: false, - current : 0, - } + constructor(props) { + super(props); + this.config = this.props.context; + this.state = { + isAddDeviceModalVisible: false, + current: 0, }; + } - onClickType = () =>{ - this.setState({ - current: 1, - }) - }; + onClickType = () => { + this.setState({ + current: 1, + }); + }; - next() { - const current = this.state.current + 1; - this.setState({ current }); - } - - prev() { - const current = this.state.current - 1; - this.setState({ current }); - } - - openAddDeviceModal = () =>{ - this.setState({ - isAddDeviceModalVisible : true, - }) - }; - - render() { - const {loading, current, isError, supportedOsVersions, errorText, forbiddenErrors} = this.state; - const { getFieldDecorator } = this.props.form; - return ( -
- -
- - - - - - - - - - - -
- -
-
- -
-
-
-
-
-
-
-
-
-
- - -
- {current > 0 && ( - - )} - {current < 5 && current > 0 && ( - - )} - {current === 5 && ( - - )} -
- - + next() { + const current = this.state.current + 1; + this.setState({ current }); + } + prev() { + const current = this.state.current - 1; + this.setState({ current }); + } + render() { + const { current } = this.state; + return ( +
+ +
+ + + + + + + + + + + +
+ +
+
+ +
+
+
+
+
+
+ + +
+ {current > 0 && ( + + )} + {current < 5 && current > 0 && ( + + )} + {current === 5 && }
- ); - } + + + + ); + } } -export default withConfigContext(Form.create({name: 'add-policy'})(AddPolicy)); \ No newline at end of file +export default withConfigContext( + Form.create({ name: 'add-policy' })(AddPolicy), +); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/ConfigureProfile.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/ConfigureProfile.js index 0d595b1d8b..6241dc0136 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/ConfigureProfile.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Policies/ConfigureProfile.js @@ -1,268 +1,270 @@ import React from 'react'; -import {Tabs, Row, Col, Switch, Menu,Input, Typography, Form, Checkbox, Select, - Tooltip, Icon, Collapse, Alert, Upload, Button,Radio} from "antd"; -import {withConfigContext} from "../../context/ConfigContext"; -import "../../pages/Dashboard/Policies/policies.css"; -import jsonResponse from "./configuration"; -const { Title, Text, Paragraph } = Typography; +import { + Tabs, + Row, + Col, + Switch, + Input, + Typography, + Form, + Checkbox, + Select, + Tooltip, + Icon, + Alert, + Upload, + Button, + Radio, +} from 'antd'; +import { withConfigContext } from '../../context/ConfigContext'; +import '../../pages/Dashboard/Policies/policies.css'; +import jsonResponse from './configuration'; +const { Title, Paragraph } = Typography; const { TabPane } = Tabs; -const {Option} = Select; -const {Panel} = Collapse; +const { Option } = Select; const { TextArea } = Input; const policyConfigurationsList = jsonResponse.PolicyConfigurations; class ConfigureProfile extends React.Component { - constructor(props) { - super(props); - this.config = this.props.context; - this.policies = policyConfigurationsList.androidPolicy.Policy; - this.state = { - isDisplayMain: "none", - activeKeys: [] - } + constructor(props) { + super(props); + this.config = this.props.context; + this.policies = policyConfigurationsList.androidPolicy.Policy; + this.state = { + isDisplayMain: 'none', + activeKeys: [], }; + } - componentDidMount() { + componentDidMount() {} + + onChange = e => { + console.log(`checked = ${e.target.id}`); + }; + + onChecked = (e, i) => { + if (e) { + this.setState({ + isDisplayMain: 'block', + }); + } else { + this.setState({ + isDisplayMain: 'none', + }); } + }; - onChange = (e) =>{ - console.log(`checked = ${e.target.id}`); - }; + onClickSwitch = e => {}; - onChecked = (e,i) =>{ - if(e){ - this.setState({ - isDisplayMain: "block", - }); - }else{ - this.setState({ - isDisplayMain: "none", - }); + getPanelItems = panel => { + const { getFieldDecorator } = this.props.form; + return panel.map((item, k) => { + switch (item._type) { + case 'select': + return ( + + {item.Label}  + + + + + } + style={{ display: 'block' }} + > + {getFieldDecorator(`${item._id}`, { + initialValue: `${item.Optional.Option[0]}`, + })( + , + )} + + ); + case 'input': + return ( + + {item.Label}  + + + + + } + style={{ display: 'block' }} + > + {getFieldDecorator(`${item._id}`, { + rules: [ + { + pattern: new RegExp(`${item.Optional.rules.regex}`), + message: `${item.Optional.rules.validationMsg}`, + }, + ], + })()} + + ); + case 'checkbox': + return ( + + {getFieldDecorator(`${item._id}`, { + valuePropName: 'checked', + initialValue: `${item.Optional.checked}`, + })( + + + {item.Label}  + + + + + , + )} + + ); + case 'textArea': + return ( + + {item.Label}  + + + + + } + style={{ display: 'block' }} + > + {getFieldDecorator(`${item._id}`, {})( +