mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Merge branch 'dmgt-ra/feature/eslint' into 'master'
Add ESLint to devicemgt react app Closes product-iots#291 See merge request entgra/carbon-device-mgt!419
This commit is contained in:
commit
c34811f0e7
@ -82,6 +82,16 @@
|
||||
<arguments>install</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>lint</id>
|
||||
<goals>
|
||||
<goal>npm</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<arguments>run-script lint</arguments>
|
||||
</configuration>
|
||||
<phase>generate-resources</phase>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>prod</id>
|
||||
<goals>
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"parser": "flow"
|
||||
}
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -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\""
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 = (
|
||||
<Layout>
|
||||
<Content style={{
|
||||
padding: '0 0',
|
||||
paddingTop: 300,
|
||||
backgroundColor: '#fff',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
<Spin tip="Loading..."/>
|
||||
</Content>
|
||||
</Layout>
|
||||
<Layout>
|
||||
<Content
|
||||
style={{
|
||||
padding: '0 0',
|
||||
paddingTop: 300,
|
||||
backgroundColor: '#fff',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<Spin tip="Loading..." />
|
||||
</Content>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
const errorView = (
|
||||
<Result
|
||||
style={{
|
||||
paddingTop: 200
|
||||
}}
|
||||
status="500"
|
||||
title="Error occurred while loading the configuration"
|
||||
subTitle="Please refresh your browser window"
|
||||
/>
|
||||
<Result
|
||||
style={{
|
||||
paddingTop: 200,
|
||||
}}
|
||||
status="500"
|
||||
title="Error occurred while loading the configuration"
|
||||
subTitle="Please refresh your browser window"
|
||||
/>
|
||||
);
|
||||
|
||||
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 = (
|
||||
<Router>
|
||||
<ConfigContext.Provider value={this.state.config}>
|
||||
<div>
|
||||
<Switch>
|
||||
<Redirect exact from="/entgra" to="/entgra/devices" />
|
||||
{this.props.routes.map(route => (
|
||||
<RouteWithSubRoutes key={route.path} {...route} />
|
||||
))}
|
||||
</Switch>
|
||||
</div>
|
||||
</ConfigContext.Provider>
|
||||
</Router>
|
||||
);
|
||||
|
||||
const abc = this.state.deviceTypes;
|
||||
const applicationView = (
|
||||
<Router>
|
||||
<ConfigContext.Provider value={this.state.config}>
|
||||
<div>
|
||||
<Switch>
|
||||
<Redirect exact from="/entgra" to="/entgra/devices"/>
|
||||
{this.props.routes.map((route) => (
|
||||
<RouteWithSubRoutes key={route.path} {...route} />
|
||||
))}
|
||||
</Switch>
|
||||
</div>
|
||||
</ConfigContext.Provider>
|
||||
</Router>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{loading && loadingView}
|
||||
{!loading && !error && applicationView}
|
||||
{error && errorView}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{loading && loadingView}
|
||||
{!loading && !error && applicationView}
|
||||
{error && errorView}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
@ -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 => (
|
||||
<Moment format="YYYY/MM/DD HH:mm" date={notBefore} />
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Not After',
|
||||
dataIndex: 'notAfter',
|
||||
render: notAfter => (
|
||||
<Moment format="YYYY/MM/DD HH:mm" date={notAfter} />
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Subject',
|
||||
dataIndex: 'subject',
|
||||
render: subject => (
|
||||
<Paragraph style={{marginBottom: 0}} ellipsis={{rows:1, expandable: true}}>{subject}</Paragraph>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Issuer',
|
||||
dataIndex: 'issuer',
|
||||
render: issuer => (
|
||||
<Paragraph style={{marginBottom: 0}} ellipsis={{rows:1, expandable: true}}>{issuer}</Paragraph>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
key: 'actions',
|
||||
dataIndex: 'serialNumber',
|
||||
render: (serialNumber) => (
|
||||
<Tooltip placement="bottom" title={"Remove User"}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={"Are you sure?"}
|
||||
onConfirm={() => {this.deleteCertificate(serialNumber)}}
|
||||
okText="Ok"
|
||||
cancelText="Cancel">
|
||||
<a><Text type="danger"><Icon type="delete"/></Text></a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
)
|
||||
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 (
|
||||
<div>
|
||||
<div>
|
||||
<Table
|
||||
columns={this.columns}
|
||||
rowKey={record => 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}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
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 => (
|
||||
<Moment format="YYYY/MM/DD HH:mm" date={notBefore} />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Not After',
|
||||
dataIndex: 'notAfter',
|
||||
render: notAfter => <Moment format="YYYY/MM/DD HH:mm" date={notAfter} />,
|
||||
},
|
||||
{
|
||||
title: 'Subject',
|
||||
dataIndex: 'subject',
|
||||
render: subject => (
|
||||
<Paragraph
|
||||
style={{ marginBottom: 0 }}
|
||||
ellipsis={{ rows: 1, expandable: true }}
|
||||
>
|
||||
{subject}
|
||||
</Paragraph>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Issuer',
|
||||
dataIndex: 'issuer',
|
||||
render: issuer => (
|
||||
<Paragraph
|
||||
style={{ marginBottom: 0 }}
|
||||
ellipsis={{ rows: 1, expandable: true }}
|
||||
>
|
||||
{issuer}
|
||||
</Paragraph>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
key: 'actions',
|
||||
dataIndex: 'serialNumber',
|
||||
render: serialNumber => (
|
||||
<Tooltip placement="bottom" title={'Remove User'}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={'Are you sure?'}
|
||||
onConfirm={() => {
|
||||
this.deleteCertificate(serialNumber);
|
||||
}}
|
||||
okText="Ok"
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<a>
|
||||
<Text type="danger">
|
||||
<Icon type="delete" />
|
||||
</Text>
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
render() {
|
||||
const { data, pagination, loading } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Table
|
||||
columns={this.columns}
|
||||
rowKey={record => 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}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(CertificateTable);
|
||||
|
||||
@ -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) =>
|
||||
<Col span={5} key={data.id}>
|
||||
<Card
|
||||
size="default"
|
||||
style={{ width: 200 }}
|
||||
bordered={true}
|
||||
actions={[
|
||||
<Icon type="setting" key="setting" />,
|
||||
<Icon type="edit" key="edit" />,]}
|
||||
>
|
||||
<Meta
|
||||
avatar={<Icon type="desktop" key="device-types"/>}
|
||||
title={data.name}
|
||||
/>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
return (
|
||||
<div style={{ background: '#ECECEC', padding: '20px' }}>
|
||||
<Row gutter={16}>
|
||||
{itemCard}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data } = this.state;
|
||||
const { Meta } = Card;
|
||||
const itemCard = data.map(data => (
|
||||
<Col span={5} key={data.id}>
|
||||
<Card
|
||||
size="default"
|
||||
style={{ width: 200 }}
|
||||
bordered={true}
|
||||
actions={[
|
||||
<Icon type="setting" key="setting" />,
|
||||
<Icon type="edit" key="edit" />,
|
||||
]}
|
||||
>
|
||||
<Meta
|
||||
avatar={<Icon type="desktop" key="device-types" />}
|
||||
title={data.name}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
));
|
||||
return (
|
||||
<div style={{ background: '#ECECEC', padding: '20px' }}>
|
||||
<Row gutter={16}>{itemCard}</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(DeviceTypesTable);
|
||||
export default withConfigContext(DeviceTypesTable);
|
||||
|
||||
@ -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 (
|
||||
<div>
|
||||
<Row>
|
||||
<Col span={16} offset={4}>
|
||||
<Steps style={{ minHeight: 32 }} current={current}>
|
||||
<Step key="DeviceType" title="Device Type" />
|
||||
<Step key="EnrollAgent" title="Enroll Agent" />
|
||||
<Step key="Result" title="Result" />
|
||||
</Steps>
|
||||
</Col>
|
||||
<Col span={16} offset={4}>
|
||||
<Card style={{ marginTop: 24 }}>
|
||||
<div style={{ display: current === 0 ? 'unset' : 'none' }}>
|
||||
<DeviceType onClickType={this.onClickType} />
|
||||
</div>
|
||||
<div style={{ display: current === 1 ? 'unset' : 'none' }}>
|
||||
<EnrollAgent />
|
||||
</div>
|
||||
|
||||
render() {
|
||||
const {loading, current, isError, supportedOsVersions, errorText, forbiddenErrors} = this.state;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<Row>
|
||||
<Col span={16} offset={4}>
|
||||
<Steps style={{minHeight: 32}} current={current}>
|
||||
<Step key="DeviceType" title="Device Type"/>
|
||||
<Step key="EnrollAgent" title="Enroll Agent"/>
|
||||
<Step key="Result" title="Result"/>
|
||||
</Steps>
|
||||
</Col>
|
||||
<Col span={16} offset={4}>
|
||||
|
||||
<Card style={{marginTop: 24}}>
|
||||
<div style={{display: (current === 0 ? 'unset' : 'none')}}>
|
||||
<DeviceType onClickType={this.onClickType}/>
|
||||
</div>
|
||||
<div style={{display: (current === 1 ? 'unset' : 'none')}}>
|
||||
<EnrollAgent />
|
||||
</div>
|
||||
|
||||
<div style={{display: (current === 2 ? 'unset' : 'none')}}>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div style={{ display: current === 2 ? 'unset' : 'none' }}></div>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'add-device'})(AddDevice));
|
||||
export default withConfigContext(
|
||||
Form.create({ name: 'add-device' })(AddDevice),
|
||||
);
|
||||
|
||||
@ -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 (
|
||||
<div style={{ display: isSelected ? 'inline' : 'none', padding: '11px' }}>
|
||||
<Tooltip
|
||||
placement="bottom"
|
||||
title={'Delete Device'}
|
||||
autoAdjustOverflow={true}
|
||||
>
|
||||
<Popconfirm
|
||||
placement="topLeft"
|
||||
title={
|
||||
this.state.canDelete
|
||||
? 'Are you sure you want to delete?'
|
||||
: 'You can only delete disenrolled devices'
|
||||
}
|
||||
tempDeleteState = true;
|
||||
}
|
||||
this.setState({canDelete:tempDeleteState})
|
||||
};
|
||||
|
||||
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 (
|
||||
<div style={{display: isSelected ? "inline" : "none", padding: '11px'}}>
|
||||
|
||||
<Tooltip
|
||||
placement="bottom"
|
||||
title={"Delete Device"}
|
||||
autoAdjustOverflow={true}>
|
||||
<Popconfirm
|
||||
placement="topLeft"
|
||||
title={
|
||||
this.state.canDelete ?
|
||||
"Are you sure you want to delete?" : "You can only delete disenrolled devices"}
|
||||
onConfirm={this.onConfirmDelete}
|
||||
okText="Ok"
|
||||
cancelText="Cancel">
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
shape="circle"
|
||||
icon="delete"
|
||||
size={'default'}
|
||||
onClick={this.onDeleteDeviceCall}
|
||||
disabled={isSelected ? false : true}
|
||||
style={{margin: "2px"}}/>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
<Divider type="vertical"/>
|
||||
<Tooltip placement="bottom" title={"Disenroll Device"}>
|
||||
<Popconfirm
|
||||
placement="topLeft"
|
||||
title={"Are you sure?"}
|
||||
onConfirm={this.onConfirmDisenroll}
|
||||
okText="Ok"
|
||||
disabled={isSelectedSingle ? false : true}
|
||||
cancelText="Cancel">
|
||||
<Button
|
||||
type="link"
|
||||
shape="circle"
|
||||
icon="close"
|
||||
size={'default'}
|
||||
style={{display:isSelectedSingle ? "inline" : "none", margin: "2px"}}/>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" style={{display:isSelectedSingle ? "inline-block" : "none"}}/>
|
||||
<Tooltip placement="bottom" title={"Add to group"}>
|
||||
|
||||
<Button
|
||||
type="link"
|
||||
shape="circle"
|
||||
icon="deployment-unit"
|
||||
size={'default'}
|
||||
onClick={this.onDeviceGroupCall}
|
||||
style={{margin: "2px"}}/>
|
||||
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
onConfirm={this.onConfirmDelete}
|
||||
okText="Ok"
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
shape="circle"
|
||||
icon="delete"
|
||||
size={'default'}
|
||||
onClick={this.onDeleteDeviceCall}
|
||||
disabled={!isSelected}
|
||||
style={{ margin: '2px' }}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={'Disenroll Device'}>
|
||||
<Popconfirm
|
||||
placement="topLeft"
|
||||
title={'Are you sure?'}
|
||||
onConfirm={this.onConfirmDisenroll}
|
||||
okText="Ok"
|
||||
disabled={!isSelectedSingle}
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
shape="circle"
|
||||
icon="close"
|
||||
size={'default'}
|
||||
style={{
|
||||
display: isSelectedSingle ? 'inline' : 'none',
|
||||
margin: '2px',
|
||||
}}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
<Divider
|
||||
type="vertical"
|
||||
style={{ display: isSelectedSingle ? 'inline-block' : 'none' }}
|
||||
/>
|
||||
<Tooltip placement="bottom" title={'Add to group'}>
|
||||
<Button
|
||||
type="link"
|
||||
shape="circle"
|
||||
icon="deployment-unit"
|
||||
size={'default'}
|
||||
onClick={this.onDeviceGroupCall}
|
||||
style={{ margin: '2px' }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BulkActionBar;
|
||||
export default BulkActionBar;
|
||||
|
||||
@ -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) =>
|
||||
<Col span={5} key={data.id}>
|
||||
<Card
|
||||
size="default"
|
||||
style={{ width: 150 }}
|
||||
bordered={true}
|
||||
onClick={this.onClickCard}
|
||||
cover={<Icon type="android" key="device-types" style={{color:'#ffffff',
|
||||
backgroundColor:'#4b92db', fontSize: '100px', padding:'20px'}}/>}
|
||||
>
|
||||
<Meta
|
||||
title={data.name}
|
||||
/>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={16}>
|
||||
{itemCard}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data } = this.state;
|
||||
const { Meta } = Card;
|
||||
const itemCard = data.map(data => (
|
||||
<Col span={5} key={data.id}>
|
||||
<Card
|
||||
size="default"
|
||||
style={{ width: 150 }}
|
||||
bordered={true}
|
||||
onClick={this.onClickCard}
|
||||
cover={
|
||||
<Icon
|
||||
type="android"
|
||||
key="device-types"
|
||||
style={{
|
||||
color: '#ffffff',
|
||||
backgroundColor: '#4b92db',
|
||||
fontSize: '100px',
|
||||
padding: '20px',
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Meta title={data.name} />
|
||||
</Card>
|
||||
</Col>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={16}>{itemCard}</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(DeviceType);
|
||||
export default withConfigContext(DeviceType);
|
||||
|
||||
@ -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 (
|
||||
<span style={{fontSize: 20, color: color, textAlign: "center"}}>
|
||||
<Icon type={icon} theme={theme}/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
// todo add filtering options
|
||||
return (
|
||||
<span style={{ fontSize: 20, color: color, textAlign: 'center' }}>
|
||||
<Icon type={icon} theme={theme} />
|
||||
</span>
|
||||
);
|
||||
},
|
||||
{
|
||||
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 <Tag color={color}>{status}</Tag>;
|
||||
},
|
||||
{
|
||||
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 (
|
||||
<Tooltip title={new Date(dateOfLastUpdate).toString()}>
|
||||
{timeAgoString}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
{
|
||||
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 <Tag color={color}>{status}</Tag>;
|
||||
}
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Last Updated',
|
||||
dataIndex: 'enrolmentInfo',
|
||||
key: 'dateOfLastUpdate',
|
||||
render: (data) => {
|
||||
const {dateOfLastUpdate} = data;
|
||||
const timeAgoString = getTimeAgo(dateOfLastUpdate);
|
||||
return <Tooltip title={new Date(dateOfLastUpdate).toString()}>{timeAgoString}</Tooltip>;
|
||||
}
|
||||
// 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) =>
|
||||
<Select.Option
|
||||
value={data.id}
|
||||
key={data.id}>
|
||||
{data.name}
|
||||
</Select.Option>);
|
||||
return (
|
||||
<div>
|
||||
<BulkActionBar
|
||||
deleteDevice={this.deleteDevice}
|
||||
getGroups={this.getGroups}
|
||||
disenrollDevice={this.disenrollDevice}
|
||||
selectedRows={this.state.selectedRows}/>
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => (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}
|
||||
/>
|
||||
</div>
|
||||
addDevicesToGroup = groupId => {
|
||||
const config = this.props.context;
|
||||
this.setState({ loading: true });
|
||||
|
||||
<Modal
|
||||
title="Grouping Devices"
|
||||
width="350px"
|
||||
visible={this.state.groupModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
>
|
||||
<p>{selectedText}</p>
|
||||
<Select
|
||||
mode={isSelectedSingle ? "multiple" : "default"}
|
||||
showSearch
|
||||
style={{display:"block"}}
|
||||
placeholder="Select Group"
|
||||
optionFilterProp="children"
|
||||
onChange={this.onGroupSelectChange}
|
||||
>
|
||||
{item}
|
||||
</Select>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
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 => (
|
||||
<Select.Option value={data.id} key={data.id}>
|
||||
{data.name}
|
||||
</Select.Option>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
<BulkActionBar
|
||||
deleteDevice={this.deleteDevice}
|
||||
getGroups={this.getGroups}
|
||||
disenrollDevice={this.disenrollDevice}
|
||||
selectedRows={this.state.selectedRows}
|
||||
/>
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record =>
|
||||
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}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
title="Grouping Devices"
|
||||
width="350px"
|
||||
visible={this.state.groupModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
>
|
||||
<p>{selectedText}</p>
|
||||
<Select
|
||||
mode={isSelectedSingle ? 'multiple' : 'default'}
|
||||
showSearch
|
||||
style={{ display: 'block' }}
|
||||
placeholder="Select Group"
|
||||
optionFilterProp="children"
|
||||
onChange={this.onGroupSelectChange}
|
||||
>
|
||||
{item}
|
||||
</Select>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(DeviceTable);
|
||||
export default withConfigContext(DeviceTable);
|
||||
|
||||
@ -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 (
|
||||
<div>
|
||||
<Divider orientation="left">Step 01 - Get your Android Agent.</Divider>
|
||||
<div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ margin: '30px' }}>
|
||||
<Button type="primary" size={'default'}>
|
||||
Get Android Agent
|
||||
</Button>
|
||||
</div>
|
||||
<Divider orientation="left">
|
||||
Step 02 - Enroll the Android Agent.
|
||||
</Divider>
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Divider orientation="left">Step 01 - Get your Android Agent.</Divider>
|
||||
<div>
|
||||
<p>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.</p>
|
||||
</div>
|
||||
<div style={{ margin:'30px'}}>
|
||||
<Button type="primary" size={"default"}>
|
||||
Get Android Agent
|
||||
</Button>
|
||||
</div>
|
||||
<Divider orientation="left">Step 02 - Enroll the Android Agent.</Divider>
|
||||
|
||||
<div>
|
||||
<p> 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.</p>
|
||||
</div>
|
||||
<div style={{ margin:'30px'}}>
|
||||
<Button type="primary" size={"default"} onClick={this.onGetEnrollmentQR}>
|
||||
Enroll Using QR
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div>
|
||||
<p>
|
||||
{' '}
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ margin: '30px' }}>
|
||||
<Button
|
||||
type="primary"
|
||||
size={'default'}
|
||||
onClick={this.onGetEnrollmentQR}
|
||||
>
|
||||
Enroll Using QR
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(EnrollAgent);
|
||||
export default withConfigContext(EnrollAgent);
|
||||
|
||||
@ -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 (
|
||||
<span style={{fontSize: 20, color: color, textAlign: "center"}}>
|
||||
<Icon type={icon} theme={theme}/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
// todo add filtering options
|
||||
return (
|
||||
<span style={{ fontSize: 20, color: color, textAlign: 'center' }}>
|
||||
<Icon type={icon} theme={theme} />
|
||||
</span>
|
||||
);
|
||||
},
|
||||
{
|
||||
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 <Tag color={color}>{status}</Tag>;
|
||||
},
|
||||
{
|
||||
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 (
|
||||
<Tooltip title={new Date(dateOfLastUpdate).toString()}>
|
||||
{timeAgoString}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
{
|
||||
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 <Tag color={color}>{status}</Tag>;
|
||||
}
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Last Updated',
|
||||
dataIndex: 'enrolmentInfo',
|
||||
key: 'dateOfLastUpdate',
|
||||
render: (data) => {
|
||||
const {dateOfLastUpdate} = data;
|
||||
const timeAgoString = getTimeAgo(dateOfLastUpdate);
|
||||
return <Tooltip title={new Date(dateOfLastUpdate).toString()}>{timeAgoString}</Tooltip>;
|
||||
}
|
||||
// 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 (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => (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}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data, pagination, loading } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record =>
|
||||
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}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(ReportDeviceTable);
|
||||
export default withConfigContext(ReportDeviceTable);
|
||||
|
||||
@ -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 (
|
||||
<div style={{ display: 'none' }}>
|
||||
{
|
||||
<Polyline color="green" positions={polyMarkers}>
|
||||
<Popup>on the way</Popup>
|
||||
</Polyline>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const polyMarkers = locationData
|
||||
.map(locationPoint => {
|
||||
return [locationPoint.latitude, locationPoint.longitude]
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{display: "none"}}>{
|
||||
<Polyline color="green" positions={polyMarkers}>
|
||||
<Popup>on the way</Popup>
|
||||
</Polyline>
|
||||
}</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<div style={{backgroundColor: "#ffffff", borderRadius: 5, padding: 5}}>
|
||||
<Map center={startingPoint} zoom={zoom}>
|
||||
<TileLayer
|
||||
url={url}
|
||||
attribution={attribution}
|
||||
/>
|
||||
<Fragment>
|
||||
{this.polylineMarker(locationData)}
|
||||
<Marker position={startingPoint}>
|
||||
<Tooltip>Starting Location</Tooltip>
|
||||
</Marker>
|
||||
</Fragment>
|
||||
</Map>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
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 (
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5, padding: 5 }}>
|
||||
<Map center={startingPoint} zoom={zoom}>
|
||||
<TileLayer url={url} attribution={attribution} />
|
||||
<Fragment>
|
||||
{this.polylineMarker(locationData)}
|
||||
<Marker position={startingPoint}>
|
||||
<Tooltip>Starting Location</Tooltip>
|
||||
</Marker>
|
||||
</Fragment>
|
||||
</Map>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(GeoCustomMap);
|
||||
|
||||
@ -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 (
|
||||
<Tooltip placement="rightBottom" title={toolTip}>
|
||||
<Button disabled={flag}
|
||||
onClick={this.handleApiCall}>
|
||||
Fetch Locations
|
||||
</Button>
|
||||
</Tooltip>);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 (
|
||||
<Tooltip placement="rightBottom" title={toolTip}>
|
||||
<Button disabled={flag} onClick={this.handleApiCall}>
|
||||
Fetch Locations
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
let {deviceData} = this.state;
|
||||
/**
|
||||
* fetches device data to populate the dropdown list
|
||||
*/
|
||||
fetchDevices = () => {
|
||||
const config = this.props.context;
|
||||
this.setState({ loading: true });
|
||||
|
||||
return (
|
||||
<div className="controllerDiv">
|
||||
<RangePicker
|
||||
ranges={ranges}
|
||||
style={{marginRight: 20}}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
defaultValue={[this.state.start, this.state.end]}
|
||||
onChange={this.applyCallback}
|
||||
|
||||
/>
|
||||
|
||||
<Select
|
||||
showSearch
|
||||
style={{width: 220, marginRight: 20}}
|
||||
placeholder="Select a Device"
|
||||
optionFilterProp="children"
|
||||
onChange={this.handleDeviceList}
|
||||
filterOption={(input, option) =>
|
||||
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
>
|
||||
{deviceData.map((device, index) =>
|
||||
<Select.Option key={index} value={index}>
|
||||
{device.name + " "}{this.statusTag(device)}
|
||||
</Select.Option>)}
|
||||
</Select>
|
||||
|
||||
{this.fetchLocationButton()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 <Tag color={color}>{status}</Tag>
|
||||
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 (
|
||||
<div className="container">
|
||||
{this.controllerBar()}
|
||||
{(locationData.length > 0) ?
|
||||
<GeoCustomMap locationData={locationData}/>
|
||||
:
|
||||
<Empty/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="controllerDiv">
|
||||
<RangePicker
|
||||
ranges={ranges}
|
||||
style={{ marginRight: 20 }}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
defaultValue={[this.state.start, this.state.end]}
|
||||
onChange={this.applyCallback}
|
||||
/>
|
||||
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: 220, marginRight: 20 }}
|
||||
placeholder="Select a Device"
|
||||
optionFilterProp="children"
|
||||
onChange={this.handleDeviceList}
|
||||
filterOption={(input, option) =>
|
||||
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >=
|
||||
0
|
||||
}
|
||||
>
|
||||
{deviceData.map((device, index) => (
|
||||
<Select.Option key={index} value={index}>
|
||||
{device.name + ' '}
|
||||
{this.statusTag(device)}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
{this.fetchLocationButton()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 <Tag color={color}>{status}</Tag>;
|
||||
};
|
||||
|
||||
render() {
|
||||
const locationData = [...this.state.locationData];
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
{this.controllerBar()}
|
||||
{locationData.length > 0 ? (
|
||||
<GeoCustomMap locationData={locationData} />
|
||||
) : (
|
||||
<Empty />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(GeoDashboard);
|
||||
|
||||
@ -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(
|
||||
<div>
|
||||
<div>
|
||||
<Button type="primary" icon="plus" size={"default"} onClick={this.openAddModal}>
|
||||
Add Group
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ADD NEW GROUP"
|
||||
width="40%"
|
||||
visible={this.state.addModalVisible}
|
||||
onOk={this.handleAddOk}
|
||||
onCancel={this.handleAddCancel}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.handleAddCancel}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleAddOk}>
|
||||
Submit
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{alignItems:"center"}}>
|
||||
<p>Create new device group on IoT Server.</p>
|
||||
<Form
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 18 }}
|
||||
>
|
||||
<Form.Item label="Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group name',
|
||||
},
|
||||
],
|
||||
})(<Input onChange={this.onChangeName}/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" style={{display:"block"}}>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group description',
|
||||
},
|
||||
],
|
||||
})(<Input onChange={this.onChangeDescription}/>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
size={'default'}
|
||||
onClick={this.openAddModal}
|
||||
>
|
||||
Add Group
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ADD NEW GROUP"
|
||||
width="40%"
|
||||
visible={this.state.addModalVisible}
|
||||
onOk={this.handleAddOk}
|
||||
onCancel={this.handleAddCancel}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.handleAddCancel}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleAddOk}>
|
||||
Submit
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<p>Create new device group on IoT Server.</p>
|
||||
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 18 }}>
|
||||
<Form.Item label="Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group name',
|
||||
},
|
||||
],
|
||||
})(<Input onChange={this.onChangeName} />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group description',
|
||||
},
|
||||
],
|
||||
})(<Input onChange={this.onChangeDescription} />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'add-group'})(AddGroup));
|
||||
export default withConfigContext(Form.create({ name: 'add-group' })(AddGroup));
|
||||
|
||||
@ -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) =>
|
||||
<Select.Option
|
||||
value={data}
|
||||
key={data}>
|
||||
{data}
|
||||
</Select.Option>);
|
||||
return(
|
||||
<div>
|
||||
<div style={{display:isAdminGroups ? "none" : "inline"}}>
|
||||
<Tooltip placement="top" title={"Share Group"}>
|
||||
<a><Icon type="share-alt" onClick={this.openShareModal}/></a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="top" title={"Edit Group"}>
|
||||
<a><Icon type="edit" onClick={this.openEditModal}/></a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={"Delete Group"}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={"Are you sure?"}
|
||||
onConfirm={this.onConfirmDeleteGroup}
|
||||
okText="Ok"
|
||||
cancelText="Cancel">
|
||||
<a><Text type="danger"><Icon type="delete"/></Text></a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="Update Group"
|
||||
width="40%"
|
||||
visible={this.state.editModalVisible}
|
||||
onOk={this.handleEditOk}
|
||||
onCancel={this.handleEditCancel}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.handleEditCancel}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleEditOk}>
|
||||
Submit
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{alignItems:"center"}}>
|
||||
<p>Enter new name and description for the group</p>
|
||||
<Form
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 18 }}
|
||||
>
|
||||
<Form.Item label="Name" style={{display:"block"}}>
|
||||
{getFieldDecorator(
|
||||
'name',
|
||||
{
|
||||
initialValue: this.props.data.name,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group name',
|
||||
},
|
||||
],
|
||||
})(<Input
|
||||
onChange={this.onChangeName}/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" style={{display:"block"}}>
|
||||
{getFieldDecorator(
|
||||
'description',
|
||||
{
|
||||
initialValue: this.props.data.description,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group description',
|
||||
},
|
||||
],
|
||||
})(<Input
|
||||
onChange={this.onChangeDescription}/>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="Share Group"
|
||||
width="500px"
|
||||
visible={this.state.shareModalVisible}
|
||||
onOk={this.handleShareOk}
|
||||
onCancel={this.handleShareCancel}
|
||||
footer={[
|
||||
<Button key="new-role" onClick={this.handleShareCancel}>
|
||||
New Role
|
||||
</Button>,
|
||||
<Button key="new-role-selection" onClick={this.handleShareCancel}>
|
||||
New Role from Selection
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleShareOk}>
|
||||
Share
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<p>Select user role(s)</p>
|
||||
<Select
|
||||
mode="multiple"
|
||||
defaultValue={"admin"}
|
||||
style={{ width: '100%' }}
|
||||
onChange={this.handleRolesDropdownChange}>
|
||||
{item}
|
||||
</Select>,
|
||||
</Modal>
|
||||
</div>
|
||||
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 => (
|
||||
<Select.Option value={data} key={data}>
|
||||
{data}
|
||||
</Select.Option>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: isAdminGroups ? 'none' : 'inline' }}>
|
||||
<Tooltip placement="top" title={'Share Group'}>
|
||||
<a>
|
||||
<Icon type="share-alt" onClick={this.openShareModal} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="top" title={'Edit Group'}>
|
||||
<a>
|
||||
<Icon type="edit" onClick={this.openEditModal} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={'Delete Group'}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={'Are you sure?'}
|
||||
onConfirm={this.onConfirmDeleteGroup}
|
||||
okText="Ok"
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<a>
|
||||
<Text type="danger">
|
||||
<Icon type="delete" />
|
||||
</Text>
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="Update Group"
|
||||
width="40%"
|
||||
visible={this.state.editModalVisible}
|
||||
onOk={this.handleEditOk}
|
||||
onCancel={this.handleEditCancel}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.handleEditCancel}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleEditOk}>
|
||||
Submit
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<p>Enter new name and description for the group</p>
|
||||
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 18 }}>
|
||||
<Form.Item label="Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('name', {
|
||||
initialValue: this.props.data.name,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group name',
|
||||
},
|
||||
],
|
||||
})(<Input onChange={this.onChangeName} />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('description', {
|
||||
initialValue: this.props.data.description,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Please input group description',
|
||||
},
|
||||
],
|
||||
})(<Input onChange={this.onChangeDescription} />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="Share Group"
|
||||
width="500px"
|
||||
visible={this.state.shareModalVisible}
|
||||
onOk={this.handleShareOk}
|
||||
onCancel={this.handleShareCancel}
|
||||
footer={[
|
||||
<Button key="new-role" onClick={this.handleShareCancel}>
|
||||
New Role
|
||||
</Button>,
|
||||
<Button key="new-role-selection" onClick={this.handleShareCancel}>
|
||||
New Role from Selection
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleShareOk}>
|
||||
Share
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<p>Select user role(s)</p>
|
||||
<Select
|
||||
mode="multiple"
|
||||
defaultValue={'admin'}
|
||||
style={{ width: '100%' }}
|
||||
onChange={this.handleRolesDropdownChange}
|
||||
>
|
||||
{item}
|
||||
</Select>
|
||||
,
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'group-actions'})(GroupActions));
|
||||
export default withConfigContext(
|
||||
Form.create({ name: 'group-actions' })(GroupActions),
|
||||
);
|
||||
|
||||
@ -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) => (
|
||||
<span>
|
||||
<GroupActions data={row} fetchGroups={this.fetchGroups} />
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
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) => (
|
||||
<span>
|
||||
<GroupActions data={row} fetchGroups={this.fetchGroups}/>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
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 (
|
||||
<div>
|
||||
<div style={{background: '#f0f2f5'}}>
|
||||
<AddGroup fetchGroups={this.fetchGroups} style={{marginBottom:"10px"}}/>
|
||||
</div>
|
||||
<div style={{textAlign: 'right'}}>
|
||||
<Filter fields={searchFields} callback={this.fetchGroups}/>
|
||||
</div>
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<Table
|
||||
columns={this.columns}
|
||||
rowKey={record => (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}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div style={{ background: '#f0f2f5' }}>
|
||||
<AddGroup
|
||||
fetchGroups={this.fetchGroups}
|
||||
style={{ marginBottom: '10px' }}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<Filter fields={searchFields} callback={this.fetchGroups} />
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<Table
|
||||
columns={this.columns}
|
||||
rowKey={record => 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}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(GroupsTable);
|
||||
|
||||
@ -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 (
|
||||
<div>
|
||||
<Row>
|
||||
<Col span={20} offset={2}>
|
||||
<Steps style={{minHeight: 32}} current={current}>
|
||||
<Step key="Platform" title="Select a Platform"/>
|
||||
<Step key="ProfileConfigure" title="Configure profile"/>
|
||||
<Step key="PolicyType" title="Select policy type"/>
|
||||
<Step key="AssignGroups" title="Assign to groups"/>
|
||||
<Step key="Publish" title="Publish to devices"/>
|
||||
<Step key="Result" title="Result"/>
|
||||
</Steps>
|
||||
</Col>
|
||||
<Col span={16} offset={4}>
|
||||
<Card style={{marginTop: 24}}>
|
||||
<div style={{display: (current === 0 ? 'unset' : 'none')}}>
|
||||
<SelectPlatform onClickType={this.onClickType}/>
|
||||
</div>
|
||||
<div style={{display: (current === 1 ? 'unset' : 'none')}}>
|
||||
<ConfigureProfile/>
|
||||
</div>
|
||||
<div style={{display: (current === 2 ? 'unset' : 'none')}}>
|
||||
</div>
|
||||
<div style={{display: (current === 3 ? 'unset' : 'none')}}>
|
||||
</div>
|
||||
<div style={{display: (current === 4 ? 'unset' : 'none')}}>
|
||||
</div>
|
||||
<div style={{display: (current === 5 ? 'unset' : 'none')}}>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={16} offset={4}>
|
||||
<div style={{marginTop: 24}}>
|
||||
{current > 0 && (
|
||||
<Button style={{ marginRight: 8 }} onClick={() => this.prev()}>
|
||||
Previous
|
||||
</Button>
|
||||
)}
|
||||
{current < 5 && current > 0 && (
|
||||
<Button type="primary" onClick={() => this.next()}>
|
||||
Next
|
||||
</Button>
|
||||
)}
|
||||
{current === 5 && (
|
||||
<Button type="primary">
|
||||
Done
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
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 (
|
||||
<div>
|
||||
<Row>
|
||||
<Col span={20} offset={2}>
|
||||
<Steps style={{ minHeight: 32 }} current={current}>
|
||||
<Step key="Platform" title="Select a Platform" />
|
||||
<Step key="ProfileConfigure" title="Configure profile" />
|
||||
<Step key="PolicyType" title="Select policy type" />
|
||||
<Step key="AssignGroups" title="Assign to groups" />
|
||||
<Step key="Publish" title="Publish to devices" />
|
||||
<Step key="Result" title="Result" />
|
||||
</Steps>
|
||||
</Col>
|
||||
<Col span={16} offset={4}>
|
||||
<Card style={{ marginTop: 24 }}>
|
||||
<div style={{ display: current === 0 ? 'unset' : 'none' }}>
|
||||
<SelectPlatform onClickType={this.onClickType} />
|
||||
</div>
|
||||
<div style={{ display: current === 1 ? 'unset' : 'none' }}>
|
||||
<ConfigureProfile />
|
||||
</div>
|
||||
<div style={{ display: current === 2 ? 'unset' : 'none' }}></div>
|
||||
<div style={{ display: current === 3 ? 'unset' : 'none' }}></div>
|
||||
<div style={{ display: current === 4 ? 'unset' : 'none' }}></div>
|
||||
<div style={{ display: current === 5 ? 'unset' : 'none' }}></div>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={16} offset={4}>
|
||||
<div style={{ marginTop: 24 }}>
|
||||
{current > 0 && (
|
||||
<Button style={{ marginRight: 8 }} onClick={() => this.prev()}>
|
||||
Previous
|
||||
</Button>
|
||||
)}
|
||||
{current < 5 && current > 0 && (
|
||||
<Button type="primary" onClick={() => this.next()}>
|
||||
Next
|
||||
</Button>
|
||||
)}
|
||||
{current === 5 && <Button type="primary">Done</Button>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'add-policy'})(AddPolicy));
|
||||
export default withConfigContext(
|
||||
Form.create({ name: 'add-policy' })(AddPolicy),
|
||||
);
|
||||
|
||||
@ -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 (
|
||||
<Form.Item
|
||||
key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
initialValue: `${item.Optional.Option[0]}`,
|
||||
})(
|
||||
<Select>
|
||||
{item.Optional.Option.map(option => {
|
||||
return <Option key={option}>{option}</Option>;
|
||||
})}
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case 'input':
|
||||
return (
|
||||
<Form.Item
|
||||
key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
rules: [
|
||||
{
|
||||
pattern: new RegExp(`${item.Optional.rules.regex}`),
|
||||
message: `${item.Optional.rules.validationMsg}`,
|
||||
},
|
||||
],
|
||||
})(<Input placeholder={item.Optional.Placeholder} />)}
|
||||
</Form.Item>
|
||||
);
|
||||
case 'checkbox':
|
||||
return (
|
||||
<Form.Item key={k}>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
valuePropName: 'checked',
|
||||
initialValue: `${item.Optional.checked}`,
|
||||
})(
|
||||
<Checkbox
|
||||
// checked={item.Optional.checked}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</Checkbox>,
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case 'textArea':
|
||||
return (
|
||||
<Form.Item
|
||||
key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator(`${item._id}`, {})(
|
||||
<TextArea
|
||||
placeholder={item.Optional.Placeholder}
|
||||
rows={item.Optional.Row}
|
||||
/>,
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case 'radioGroup':
|
||||
return (
|
||||
<Form.Item
|
||||
key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator(`${item._id}`, {})(
|
||||
<Radio.Group>
|
||||
{item.Optional.Radio.map(option => {
|
||||
return (
|
||||
<Radio key={option} value={option}>
|
||||
{option}
|
||||
</Radio>
|
||||
);
|
||||
})}
|
||||
</Radio.Group>,
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case 'title':
|
||||
return (
|
||||
<Title key={k} level={4}>
|
||||
{item.Label}{' '}
|
||||
</Title>
|
||||
);
|
||||
case 'paragraph':
|
||||
return (
|
||||
<Paragraph key={k} style={{ marginTop: 20 }}>
|
||||
{item.Label}{' '}
|
||||
</Paragraph>
|
||||
);
|
||||
case 'alert':
|
||||
return (
|
||||
<Alert key={k} description={item.Label} type="warning" showIcon />
|
||||
);
|
||||
case 'upload':
|
||||
return (
|
||||
<Form.Item
|
||||
key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{getFieldDecorator('upload', {})(
|
||||
<Upload>
|
||||
<Button>
|
||||
<Icon type="upload" /> Click to upload
|
||||
</Button>
|
||||
</Upload>,
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
onClickSwitch = (e) =>{
|
||||
|
||||
};
|
||||
|
||||
|
||||
getPanelItems = (panel)=>{
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
panel.map((item,k)=>{
|
||||
switch(item._type){
|
||||
case "select":
|
||||
return(
|
||||
<Form.Item key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{display: "block"}}>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
initialValue: `${item.Optional.Option[0]}`
|
||||
})(
|
||||
<Select>
|
||||
{item.Optional.Option.map((option)=>{
|
||||
return(
|
||||
<Option key={option}>{option}</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case "input":
|
||||
return(
|
||||
<Form.Item key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{display: "block"}}>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
rules: [
|
||||
{
|
||||
pattern: new RegExp(`${item.Optional.rules.regex}`),
|
||||
message: `${item.Optional.rules.validationMsg}`,
|
||||
},
|
||||
],
|
||||
})(
|
||||
<Input placeholder={item.Optional.Placeholder}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case "checkbox":
|
||||
return(
|
||||
<Form.Item key={k}>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
valuePropName: 'checked',
|
||||
initialValue: `${item.Optional.checked}`,
|
||||
})(
|
||||
<Checkbox
|
||||
// checked={item.Optional.checked}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case "textArea":
|
||||
return(
|
||||
<Form.Item key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{display: "block"}}>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
|
||||
})(
|
||||
<TextArea placeholder={item.Optional.Placeholder}
|
||||
rows={item.Optional.Row} />
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case "radioGroup":
|
||||
return(
|
||||
<Form.Item key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
style={{display: "block"}}>
|
||||
{getFieldDecorator(`${item._id}`, {
|
||||
})(
|
||||
<Radio.Group>
|
||||
{item.Optional.Radio.map((option)=>{
|
||||
return(
|
||||
<Radio value={option}>{option}</Radio>
|
||||
);
|
||||
})}
|
||||
</Radio.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
case "title":
|
||||
return(
|
||||
<Title key={k} level={4}>{item.Label} </Title>
|
||||
);
|
||||
case "paragraph":
|
||||
return(
|
||||
<Paragraph key={k} style={{marginTop:20}}>{item.Label} </Paragraph>
|
||||
);
|
||||
case "alert":
|
||||
return(
|
||||
<Alert
|
||||
key={k}
|
||||
description={item.Label}
|
||||
type="warning"
|
||||
showIcon
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Tabs tabPosition={'left'} size={'large'}>
|
||||
{this.policies.map((element, i) => {
|
||||
return (
|
||||
<TabPane tab={element.Name} key={i}>
|
||||
{/* <div style={{ height: 800, overflowY: "scroll"}}>*/}
|
||||
{Object.values(element.Panel).map((panel, j) => {
|
||||
return (
|
||||
<div key={j}>
|
||||
<div>
|
||||
<Row>
|
||||
<Col offset={0} span={14}>
|
||||
<Title level={4}>{panel.title} </Title>
|
||||
</Col>
|
||||
<Col offset={8} span={1}>
|
||||
<Switch
|
||||
checkedChildren="ON"
|
||||
unCheckedChildren="OFF"
|
||||
id={i}
|
||||
onClick={this.onClickSwitch}
|
||||
onChange={this.onChecked}
|
||||
/>
|
||||
);
|
||||
case "upload":
|
||||
return(
|
||||
<Form.Item key={k}
|
||||
label={
|
||||
<span>
|
||||
{item.Label}
|
||||
<Tooltip title={item.tooltip} placement="right">
|
||||
<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{getFieldDecorator('upload', {
|
||||
|
||||
})(
|
||||
|
||||
<Upload>
|
||||
<Button>
|
||||
<Icon type="upload" /> Click to upload
|
||||
</Button>
|
||||
</Upload>,
|
||||
)}
|
||||
</Form.Item>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})
|
||||
)
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Tabs tabPosition={"left"} size={"large"}>
|
||||
{ this.policies.map((element, i) =>{
|
||||
return(
|
||||
|
||||
<TabPane tab={element.Name} key={i} >
|
||||
{/*<div style={{ height: 800, overflowY: "scroll"}}>*/}
|
||||
{ Object.values(element.Panel).map((panel, j)=>{
|
||||
return(
|
||||
<div key={j} >
|
||||
<div>
|
||||
<Row>
|
||||
<Col offset={0} span={14}>
|
||||
<Title level={4}>{panel.title} </Title>
|
||||
</Col>
|
||||
<Col offset={8} span={1}>
|
||||
<Switch
|
||||
checkedChildren="ON"
|
||||
unCheckedChildren="OFF"
|
||||
id={i}
|
||||
onClick={this.onClickSwitch}
|
||||
onChange={this.onChecked}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>{panel.description}</Row>
|
||||
</div>
|
||||
<div style={{display: `${this.state.isDisplayMain}`}}>
|
||||
<Form >
|
||||
{this.getPanelItems(panel.PanelItem)}
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
})
|
||||
}
|
||||
</TabPane>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>{panel.description}</Row>
|
||||
</div>
|
||||
<div style={{ display: `${this.state.isDisplayMain}` }}>
|
||||
<Form>{this.getPanelItems(panel.PanelItem)}</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</TabPane>
|
||||
);
|
||||
})}
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create()(ConfigureProfile));
|
||||
export default withConfigContext(Form.create()(ConfigureProfile));
|
||||
|
||||
@ -16,165 +16,162 @@
|
||||
* 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 en from 'javascript-time-ago/locale/en';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
|
||||
const {Text} = Typography;
|
||||
|
||||
let config = null;
|
||||
let apiUrl;
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Policy Name',
|
||||
dataIndex: 'policyName',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
// render: enrolmentInfo => enrolmentInfo.owner
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Compilance',
|
||||
dataIndex: 'compliance',
|
||||
key: 'compliance',
|
||||
// render: enrolmentInfo => enrolmentInfo.ownership
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Policy Type',
|
||||
dataIndex: 'policyType',
|
||||
key: 'policyType',
|
||||
// render: enrolmentInfo => enrolmentInfo.ownership
|
||||
// todo add filtering options
|
||||
}
|
||||
{
|
||||
title: 'Policy Name',
|
||||
dataIndex: 'policyName',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
// render: enrolmentInfo => enrolmentInfo.owner
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Compilance',
|
||||
dataIndex: 'compliance',
|
||||
key: 'compliance',
|
||||
// render: enrolmentInfo => enrolmentInfo.ownership
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Policy Type',
|
||||
dataIndex: 'policyType',
|
||||
key: 'policyType',
|
||||
// render: enrolmentInfo => enrolmentInfo.ownership
|
||||
// todo add filtering options
|
||||
},
|
||||
];
|
||||
|
||||
const getTimeAgo = (time) => {
|
||||
const timeAgo = new TimeAgo('en-US');
|
||||
return timeAgo.format(time);
|
||||
};
|
||||
|
||||
class PoliciesTable extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
config = this.props.context;
|
||||
TimeAgo.addLocale(en);
|
||||
this.state = {
|
||||
data: [],
|
||||
pagination: {},
|
||||
constructor(props) {
|
||||
super(props);
|
||||
TimeAgo.addLocale(en);
|
||||
this.state = {
|
||||
data: [],
|
||||
pagination: {},
|
||||
loading: false,
|
||||
selectedRows: [],
|
||||
};
|
||||
}
|
||||
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchGroups();
|
||||
}
|
||||
|
||||
// fetch data from api
|
||||
fetchGroups = (params = {}) => {
|
||||
const config = this.props.context;
|
||||
this.setState({ loading: true });
|
||||
|
||||
// get current page
|
||||
const currentPage = params.hasOwnProperty('page') ? params.page : 1;
|
||||
|
||||
const extraParams = {
|
||||
offset: 10 * (currentPage - 1), // calculate the offset
|
||||
limit: 10,
|
||||
};
|
||||
|
||||
const encodedExtraParams = Object.keys(extraParams)
|
||||
.map(key => key + '=' + extraParams[key])
|
||||
.join('&');
|
||||
|
||||
apiUrl =
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/policies?' +
|
||||
encodedExtraParams;
|
||||
|
||||
// send request to the invokerss
|
||||
axios
|
||||
.get(apiUrl)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
const pagination = { ...this.state.pagination };
|
||||
this.setState({
|
||||
loading: false,
|
||||
selectedRows: []
|
||||
};
|
||||
}
|
||||
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows
|
||||
})
|
||||
data: res.data.data.policies,
|
||||
pagination,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 401) {
|
||||
// todo display a popop with error
|
||||
message.error('You are not logged in');
|
||||
window.location.href = window.location.origin + '/entgra/login';
|
||||
} else {
|
||||
notification.error({
|
||||
message: 'There was a problem',
|
||||
duration: 0,
|
||||
description: 'Error occurred while trying to load policies.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchGroups();
|
||||
}
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
};
|
||||
|
||||
//fetch data from api
|
||||
fetchGroups = (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 +
|
||||
"/policies?" + encodedExtraParams;
|
||||
|
||||
//send request to the invokerss
|
||||
axios.get(apiUrl).then(res => {
|
||||
if (res.status === 200) {
|
||||
const pagination = {...this.state.pagination};
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data.data.policies,
|
||||
pagination,
|
||||
});
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
||||
//todo display a popop with error
|
||||
message.error('You are not logged in');
|
||||
window.location.href = window.location.origin + '/entgra/login';
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: "There was a problem",
|
||||
duration: 0,
|
||||
description:"Error occurred while trying to load policies.",
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({loading: false});
|
||||
});
|
||||
};
|
||||
|
||||
handleTableChange = (pagination, filters, sorter) => {
|
||||
const pager = {...this.state.pagination};
|
||||
pager.current = pagination.current;
|
||||
this.setState({
|
||||
pagination: pager,
|
||||
});
|
||||
this.fetch({
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
const {data, pagination, loading, selectedRows} = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => (record.id)}
|
||||
dataSource={data}
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: "small",
|
||||
// position: "top",
|
||||
showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups`
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data, pagination, loading } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => record.id}
|
||||
dataSource={data}
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: 'small',
|
||||
// position: "top",
|
||||
showTotal: (total, range) =>
|
||||
`showing ${range[0]}-${range[1]} of ${total} groups`,
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(PoliciesTable);
|
||||
export default withConfigContext(PoliciesTable);
|
||||
|
||||
@ -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 SelectPlatform 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) =>
|
||||
<Col span={5} key={data.id}>
|
||||
<Card
|
||||
size="default"
|
||||
style={{ width: 150 }}
|
||||
bordered={true}
|
||||
onClick={this.onClickCard}
|
||||
cover={<Icon type="android" key="device-types" style={{color:'#ffffff',
|
||||
backgroundColor:'#4b92db', fontSize: '100px', padding:'20px'}}/>}
|
||||
>
|
||||
<Meta
|
||||
title={data.name}
|
||||
/>
|
||||
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={16}>
|
||||
{itemCard}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data } = this.state;
|
||||
const { Meta } = Card;
|
||||
const itemCard = data.map(data => (
|
||||
<Col span={5} key={data.id}>
|
||||
<Card
|
||||
size="default"
|
||||
style={{ width: 150 }}
|
||||
bordered={true}
|
||||
onClick={this.onClickCard}
|
||||
cover={
|
||||
<Icon
|
||||
type="android"
|
||||
key="device-types"
|
||||
style={{
|
||||
color: '#ffffff',
|
||||
backgroundColor: '#4b92db',
|
||||
fontSize: '100px',
|
||||
padding: '20px',
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Meta title={data.name} />
|
||||
</Card>
|
||||
</Col>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
<Row gutter={16}>{itemCard}</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(SelectPlatform);
|
||||
export default withConfigContext(SelectPlatform);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -16,50 +16,47 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
class DateRangePicker extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
// Send updated date range to Reports.js when duration change
|
||||
onChange = (dates, dateStrings) => {
|
||||
this.props.updateDurationValue(dateStrings[0], dateStrings[1]);
|
||||
};
|
||||
|
||||
//Send updated date range to Reports.js when duration change
|
||||
onChange = (dates, dateStrings) => {
|
||||
this.props.updateDurationValue(dateStrings[0],dateStrings[1]);
|
||||
}
|
||||
|
||||
render(){
|
||||
const { RangePicker } = DatePicker;
|
||||
return(
|
||||
<RangePicker
|
||||
ranges={{
|
||||
'Today': [
|
||||
moment(),
|
||||
moment()],
|
||||
'Yesterday': [
|
||||
moment().subtract(1, 'days'),
|
||||
moment().subtract(1, 'days')],
|
||||
'Last 7 Days': [
|
||||
moment().subtract(6, 'days'),
|
||||
moment()],
|
||||
'Last 30 Days': [
|
||||
moment().subtract(29, 'days'),
|
||||
moment()],
|
||||
'This Month': [
|
||||
moment().startOf('month'),
|
||||
moment().endOf('month')],
|
||||
'Last Month': [
|
||||
moment().subtract(1, 'month').startOf('month'),
|
||||
moment().subtract(1, 'month').endOf('month')]
|
||||
}}
|
||||
format="YYYY-MM-DD"
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
}
|
||||
render() {
|
||||
const { RangePicker } = DatePicker;
|
||||
return (
|
||||
<RangePicker
|
||||
ranges={{
|
||||
Today: [moment(), moment()],
|
||||
Yesterday: [
|
||||
moment().subtract(1, 'days'),
|
||||
moment().subtract(1, 'days'),
|
||||
],
|
||||
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
|
||||
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
|
||||
'This Month': [moment().startOf('month'), moment().endOf('month')],
|
||||
'Last Month': [
|
||||
moment()
|
||||
.subtract(1, 'month')
|
||||
.startOf('month'),
|
||||
moment()
|
||||
.subtract(1, 'month')
|
||||
.endOf('month'),
|
||||
],
|
||||
}}
|
||||
format="YYYY-MM-DD"
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DateRangePicker;
|
||||
export default DateRangePicker;
|
||||
|
||||
@ -16,52 +16,53 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
import { Select } from 'antd';
|
||||
|
||||
class Filter extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedItem: null,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
const { Option } = Select;
|
||||
this.state = {
|
||||
selectedItem:null
|
||||
// Send updated filter value to Reports.js
|
||||
onChange = value => {
|
||||
this.setState({ selectedItem: value }, () => {
|
||||
if (this.props.dropDownName == 'Device Status') {
|
||||
this.props.updateFiltersValue(this.state.selectedItem, 'Device Status');
|
||||
} else {
|
||||
this.props.updateFiltersValue(
|
||||
this.state.selectedItem,
|
||||
'Device Ownership',
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
// Dynamically generate dropdown items from dropDownItems array
|
||||
let item = this.props.dropDownItems.map(data => (
|
||||
<Select.Option value={data} key={data}>
|
||||
{data}
|
||||
</Select.Option>
|
||||
));
|
||||
return (
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: 200 }}
|
||||
placeholder={this.props.dropDownName}
|
||||
optionFilterProp="children"
|
||||
onChange={this.onChange}
|
||||
filterOption={(input, option) =>
|
||||
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
//Send updated filter value to Reports.js
|
||||
onChange = value => {
|
||||
this.setState({selectedItem:value},() => {
|
||||
if(this.props.dropDownName=="Device Status"){
|
||||
this.props.updateFiltersValue(this.state.selectedItem,"Device Status");
|
||||
}else{
|
||||
this.props.updateFiltersValue(this.state.selectedItem, "Device Ownership");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
//Dynamically generate dropdown items from dropDownItems array
|
||||
let item = this.props.dropDownItems.map((data) =>
|
||||
<Select.Option
|
||||
value={data}
|
||||
key={data}>
|
||||
{data}
|
||||
</Select.Option>);
|
||||
return(
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: 200 }}
|
||||
placeholder={this.props.dropDownName}
|
||||
optionFilterProp="children"
|
||||
onChange={this.onChange}
|
||||
filterOption={(input, option) =>
|
||||
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}>
|
||||
{item}
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
>
|
||||
{item}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Filter;
|
||||
export default Filter;
|
||||
|
||||
@ -16,110 +16,112 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
Tag,
|
||||
Radio, Select, Button, Card,
|
||||
Row, Col, message, notification
|
||||
} from "antd";
|
||||
import React from 'react';
|
||||
import { PageHeader, Breadcrumb, Icon, Select, Button, Card } from 'antd';
|
||||
|
||||
import {Link} from "react-router-dom";
|
||||
import PoliciesTable from "../../../components/Policies/PoliciesTable";
|
||||
import DevicesTable from "../../../components/Devices/DevicesTable";
|
||||
import DateRangePicker from "../../../components/Reports/DateRangePicker";
|
||||
import ReportDeviceTable from "../../../components/Devices/ReportDevicesTable";
|
||||
import PieChart from "../../../components/Reports/Widgets/PieChart";
|
||||
import axios from "axios";
|
||||
import CountWidget from "../../../components/Reports/Widgets/CountWidget";
|
||||
import {withConfigContext} from "../../../context/ConfigContext";
|
||||
const {Paragraph} = Typography;
|
||||
const { CheckableTag } = Tag;
|
||||
import { Link } from 'react-router-dom';
|
||||
import ReportDeviceTable from '../../../components/Devices/ReportDevicesTable';
|
||||
import PieChart from '../../../components/Reports/Widgets/PieChart';
|
||||
import { withConfigContext } from '../../../context/ConfigContext';
|
||||
|
||||
const { Option } = Select;
|
||||
let config = null;
|
||||
|
||||
|
||||
class DeviceStatusReport extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
config = this.props.context;
|
||||
const { reportData } = this.props.location;
|
||||
this.state = {
|
||||
selectedTags: ['Enrolled'],
|
||||
paramsObject:{
|
||||
from:reportData.duration[0],
|
||||
to:reportData.duration[1]
|
||||
},
|
||||
statsObject:{},
|
||||
statArray:[{item:"ACTIVE",count:0},{item:"INACTIVE",count:0},{item:"REMOVED",count:0}]
|
||||
};
|
||||
}
|
||||
|
||||
onClickPieChart = (value) => {
|
||||
console.log(value.data.point.item);
|
||||
const chartValue = value.data.point.item;
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
|
||||
tempParamObj.status = chartValue;
|
||||
|
||||
|
||||
this.setState({paramsObject:tempParamObj});
|
||||
console.log(this.state.paramsObject)
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
const { reportData } = this.props.location;
|
||||
this.state = {
|
||||
selectedTags: ['Enrolled'],
|
||||
paramsObject: {
|
||||
from: reportData.duration[0],
|
||||
to: reportData.duration[1],
|
||||
},
|
||||
statsObject: {},
|
||||
statArray: [
|
||||
{ item: 'ACTIVE', count: 0 },
|
||||
{ item: 'INACTIVE', count: 0 },
|
||||
{ item: 'REMOVED', count: 0 },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { statArray } = this.state;
|
||||
const { reportData } = this.props.location;
|
||||
onClickPieChart = value => {
|
||||
console.log(value.data.point.item);
|
||||
const chartValue = value.data.point.item;
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
|
||||
const params = {...this.state.paramsObject};
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Report</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap" style={{marginBottom: '10px'}}>
|
||||
<h3>Summary of enrollments</h3>
|
||||
<div style={{marginBottom: '10px'}}>
|
||||
<Select defaultValue="android" style={{ width: 120 , marginRight:10}}>
|
||||
<Option value="android">Android</Option>
|
||||
<Option value="ios">IOS</Option>
|
||||
<Option value="windows">Windows</Option>
|
||||
</Select>
|
||||
<Button onClick={this.onSubmitReport} style={{marginLeft:10}} type="primary">Generate Report</Button>
|
||||
</div>
|
||||
</div>
|
||||
tempParamObj.status = chartValue;
|
||||
|
||||
<div>
|
||||
<Card
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{borderRadius: 5, marginBottom: 10, height:window.innerHeight*0.5}}>
|
||||
this.setState({ paramsObject: tempParamObj });
|
||||
console.log(this.state.paramsObject);
|
||||
};
|
||||
|
||||
<PieChart onClickPieChart={this.onClickPieChart} reportData={reportData}/>
|
||||
</Card>
|
||||
</div>
|
||||
render() {
|
||||
const { reportData } = this.props.location;
|
||||
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<ReportDeviceTable paramsObject={params}/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
const params = { ...this.state.paramsObject };
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Report</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap" style={{ marginBottom: '10px' }}>
|
||||
<h3>Summary of enrollments</h3>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
<Select
|
||||
defaultValue="android"
|
||||
style={{ width: 120, marginRight: 10 }}
|
||||
>
|
||||
<Option value="android">Android</Option>
|
||||
<Option value="ios">IOS</Option>
|
||||
<Option value="windows">Windows</Option>
|
||||
</Select>
|
||||
<Button
|
||||
onClick={this.onSubmitReport}
|
||||
style={{ marginLeft: 10 }}
|
||||
type="primary"
|
||||
>
|
||||
Generate Report
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Card
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
marginBottom: 10,
|
||||
height: window.innerHeight * 0.5,
|
||||
}}
|
||||
>
|
||||
<PieChart
|
||||
onClickPieChart={this.onClickPieChart}
|
||||
reportData={reportData}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<ReportDeviceTable paramsObject={params} />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(DeviceStatusReport);
|
||||
|
||||
@ -16,118 +16,88 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
Tag,
|
||||
Radio, Select, Button, Card,
|
||||
Row, Col, message, notification
|
||||
} from "antd";
|
||||
|
||||
import {Link} from "react-router-dom";
|
||||
import PoliciesTable from "../../../components/Policies/PoliciesTable";
|
||||
import DevicesTable from "../../../components/Devices/DevicesTable";
|
||||
import DateRangePicker from "../../../components/Reports/DateRangePicker";
|
||||
import ReportDeviceTable from "../../../components/Devices/ReportDevicesTable";
|
||||
import PieChart from "../../../components/Reports/Widgets/PieChart";
|
||||
import axios from "axios";
|
||||
import CountWidget from "../../../components/Reports/Widgets/CountWidget";
|
||||
import {withConfigContext} from "../../../context/ConfigContext";
|
||||
const {Paragraph} = Typography;
|
||||
const { CheckableTag } = Tag;
|
||||
|
||||
const { Option } = Select;
|
||||
let config = null;
|
||||
import React from 'react';
|
||||
import { PageHeader, Breadcrumb, Icon, Card } from 'antd';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
import ReportDeviceTable from '../../../components/Devices/ReportDevicesTable';
|
||||
import PieChart from '../../../components/Reports/Widgets/PieChart';
|
||||
import { withConfigContext } from '../../../context/ConfigContext';
|
||||
|
||||
class EnrollmentTypeReport extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
config = this.props.context;
|
||||
const { reportData } = this.props.location;
|
||||
this.state = {
|
||||
paramsObject:{
|
||||
from:reportData.duration[0],
|
||||
to:reportData.duration[1]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
console.log(reportData.duration);
|
||||
}
|
||||
|
||||
setParam = (tempParamObj, type, value) => {
|
||||
if(type==="status"){
|
||||
tempParamObj.status = value;
|
||||
if(tempParamObj.status) {
|
||||
delete tempParamObj.status;
|
||||
}
|
||||
} else if(type=="ownership"){
|
||||
tempParamObj.ownership = value;
|
||||
if(value=="ALL" && tempParamObj.ownership) {
|
||||
delete tempParamObj.ownership;
|
||||
}
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
const { reportData } = this.props.location;
|
||||
this.state = {
|
||||
paramsObject: {
|
||||
from: reportData.duration[0],
|
||||
to: reportData.duration[1],
|
||||
},
|
||||
};
|
||||
|
||||
onClickPieChart = (value) => {
|
||||
const chartValue = value.data.point.item;
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
console.log(reportData.duration);
|
||||
}
|
||||
|
||||
console.log(chartValue)
|
||||
onClickPieChart = value => {
|
||||
const chartValue = value.data.point.item;
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
|
||||
tempParamObj.ownership = chartValue;
|
||||
|
||||
this.setState({paramsObject:tempParamObj});
|
||||
};
|
||||
console.log(chartValue);
|
||||
|
||||
render() {
|
||||
const { reportData } = this.props.location;
|
||||
tempParamObj.ownership = chartValue;
|
||||
|
||||
const params = {...this.state.paramsObject};
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Report</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap" style={{marginBottom: '10px'}}>
|
||||
<h3>Summary of enrollments</h3>
|
||||
this.setState({ paramsObject: tempParamObj });
|
||||
};
|
||||
|
||||
</div>
|
||||
render() {
|
||||
const { reportData } = this.props.location;
|
||||
|
||||
<div>
|
||||
<Card
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{borderRadius: 5, marginBottom: 10, height:window.innerHeight*0.5}}>
|
||||
const params = { ...this.state.paramsObject };
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Report</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap" style={{ marginBottom: '10px' }}>
|
||||
<h3>Summary of enrollments</h3>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Card
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
marginBottom: 10,
|
||||
height: window.innerHeight * 0.5,
|
||||
}}
|
||||
>
|
||||
<PieChart
|
||||
onClickPieChart={this.onClickPieChart}
|
||||
reportData={reportData}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<PieChart onClickPieChart={this.onClickPieChart} reportData={reportData}/>
|
||||
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<ReportDeviceTable paramsObject={params}/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<ReportDeviceTable paramsObject={params} />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(EnrollmentTypeReport);
|
||||
|
||||
@ -16,157 +16,111 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
Tag,
|
||||
Radio, Select, Button, Card,
|
||||
Row, Col, message, notification
|
||||
} from "antd";
|
||||
|
||||
import {Link, Redirect} from "react-router-dom";
|
||||
import PoliciesTable from "../../../components/Policies/PoliciesTable";
|
||||
import DevicesTable from "../../../components/Devices/DevicesTable";
|
||||
import DateRangePicker from "../../../components/Reports/DateRangePicker";
|
||||
import ReportDeviceTable from "../../../components/Devices/ReportDevicesTable";
|
||||
import PieChart from "../../../components/Reports/Widgets/PieChart";
|
||||
import axios from "axios";
|
||||
import CountWidget from "../../../components/Reports/Widgets/CountWidget";
|
||||
import {withConfigContext} from "../../../context/ConfigContext";
|
||||
const {Paragraph} = Typography;
|
||||
const { CheckableTag } = Tag;
|
||||
|
||||
const { Option } = Select;
|
||||
let config = null;
|
||||
import React from 'react';
|
||||
import { PageHeader, Breadcrumb, Icon, Card } from 'antd';
|
||||
|
||||
import { Link, Redirect } from 'react-router-dom';
|
||||
import ReportDeviceTable from '../../../components/Devices/ReportDevicesTable';
|
||||
import PieChart from '../../../components/Reports/Widgets/PieChart';
|
||||
import { withConfigContext } from '../../../context/ConfigContext';
|
||||
|
||||
class EnrollmentsVsUnenrollmentsReport extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
config = this.props.context;
|
||||
const { reportData } = this.props.location;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
const { reportData } = this.props.location;
|
||||
|
||||
this.state = {
|
||||
paramsObject:{
|
||||
from:reportData? reportData.duration[0]: "2019-01-01",
|
||||
to:reportData? reportData.duration[1]: "2019-01-01"
|
||||
},
|
||||
redirect: false
|
||||
};
|
||||
this.state = {
|
||||
paramsObject: {
|
||||
from: reportData ? reportData.duration[0] : '2019-01-01',
|
||||
to: reportData ? reportData.duration[1] : '2019-01-01',
|
||||
},
|
||||
redirect: false,
|
||||
};
|
||||
|
||||
this.redirectToHome();
|
||||
console.log(this.state.paramsObject);
|
||||
this.redirectToHome();
|
||||
console.log(this.state.paramsObject);
|
||||
}
|
||||
|
||||
redirectToHome = () => {
|
||||
return <Redirect to="/entgra" />;
|
||||
};
|
||||
|
||||
onClickPieChart = value => {
|
||||
const chartValue = value.data.point.item;
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
|
||||
console.log(chartValue);
|
||||
|
||||
if (chartValue === 'Enrollments') {
|
||||
tempParamObj.status = 'ACTIVE&status=INACTIVE';
|
||||
} else {
|
||||
tempParamObj.status = 'REMOVED';
|
||||
}
|
||||
|
||||
setParam = (tempParamObj, type, value) => {
|
||||
if(type==="status"){
|
||||
tempParamObj.status = value;
|
||||
if(tempParamObj.status) {
|
||||
delete tempParamObj.status;
|
||||
}
|
||||
} else if(type=="ownership"){
|
||||
tempParamObj.ownership = value;
|
||||
if(value=="ALL" && tempParamObj.ownership) {
|
||||
delete tempParamObj.ownership;
|
||||
}
|
||||
}
|
||||
this.setState({ paramsObject: tempParamObj });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { reportData } = this.props.location;
|
||||
|
||||
console.log('======');
|
||||
console.log(reportData);
|
||||
console.log('======');
|
||||
|
||||
let reportDataClone = {
|
||||
params: ['ACTIVE'],
|
||||
duration: ['2020-01-01', '2020-01-01'],
|
||||
};
|
||||
|
||||
redirectToHome = () => {
|
||||
return <Redirect to="/entgra" />
|
||||
};
|
||||
const params = { ...this.state.paramsObject };
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
{!reportData ? (
|
||||
<Redirect to="/entgra/reports" />
|
||||
) : (
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Report</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap" style={{ marginBottom: '10px' }}>
|
||||
<h3>Summary of enrollments</h3>
|
||||
</div>
|
||||
|
||||
setRedirect = (reportData) => {
|
||||
if(!reportData){
|
||||
this.setState({
|
||||
redirect: true
|
||||
})
|
||||
}
|
||||
};
|
||||
<div>
|
||||
<Card
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
marginBottom: 10,
|
||||
height: window.innerHeight * 0.5,
|
||||
}}
|
||||
>
|
||||
<PieChart
|
||||
onClickPieChart={this.onClickPieChart}
|
||||
reportData={reportData ? reportData : reportDataClone}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
renderRedirect = () => {
|
||||
if (this.state.redirect) {
|
||||
return <Redirect to='/entgra' />
|
||||
}
|
||||
}
|
||||
|
||||
onClickPieChart = (value) => {
|
||||
const chartValue = value.data.point.item;
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
|
||||
console.log(chartValue)
|
||||
|
||||
// tempParamObj.status = chartValue;
|
||||
|
||||
if(chartValue==="Enrollments"){
|
||||
tempParamObj.status = "ACTIVE&status=INACTIVE"
|
||||
}else{
|
||||
tempParamObj.status = "REMOVED"
|
||||
}
|
||||
|
||||
|
||||
this.setState({paramsObject:tempParamObj});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { reportData } = this.props.location;
|
||||
|
||||
console.log("======")
|
||||
console.log(reportData)
|
||||
console.log("======")
|
||||
|
||||
let reportDataClone = {
|
||||
params: ["ACTIVE"],
|
||||
duration: ["2020-01-01","2020-01-01"]
|
||||
};
|
||||
|
||||
const params = {...this.state.paramsObject};
|
||||
return (
|
||||
<div>
|
||||
|
||||
<div>{!reportData ? (
|
||||
<Redirect to='/entgra/reports' />
|
||||
) : (
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Report</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap" style={{marginBottom: '10px'}}>
|
||||
<h3>Summary of enrollments</h3>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Card
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{borderRadius: 5, marginBottom: 10, height:window.innerHeight*0.5}}>
|
||||
|
||||
|
||||
<PieChart onClickPieChart={this.onClickPieChart} reportData={reportData? reportData : reportDataClone}/>
|
||||
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<ReportDeviceTable paramsObject={params}/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
|
||||
)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<ReportDeviceTable paramsObject={params} />
|
||||
</div>
|
||||
</PageHeader>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(EnrollmentsVsUnenrollmentsReport);
|
||||
|
||||
@ -1,63 +1,47 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
import {Card, Col, Icon} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import { Card, Col } from 'antd';
|
||||
|
||||
class CountWidget extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
this.state = {
|
||||
statArray: [],
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
this.state = {
|
||||
statArray:[]
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
this.setState({ statArray: this.props.statArray });
|
||||
console.log('$$$$');
|
||||
console.log(this.props.statArray);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({statArray:this.props.statArray})
|
||||
console.log("$$$$")
|
||||
console.log(this.props.statArray)
|
||||
}
|
||||
render() {
|
||||
const { statArray } = this.state;
|
||||
|
||||
let card = statArray.map(data => (
|
||||
<Col key={data.item} span={6}>
|
||||
<Card
|
||||
key={data.item}
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{ borderRadius: 10, marginBottom: 16 }}
|
||||
>
|
||||
<div align="center">
|
||||
<h2>
|
||||
<b>{data.item}</b>
|
||||
</h2>
|
||||
<h1>{data.count}</h1>
|
||||
{/* <p>{data.duration}</p>*/}
|
||||
{/* <ReportFilterModal/>*/}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
));
|
||||
|
||||
render() {
|
||||
const countObj = [
|
||||
{item:"All",count:100},
|
||||
{item:"Enrolled",count:80},
|
||||
{item:"Unenrolled",count:20}];
|
||||
|
||||
const { statArray } = this.state;
|
||||
|
||||
let card = statArray.map((data) =>
|
||||
// <Card
|
||||
// bordered={true}
|
||||
// hoverable={true}
|
||||
// key={data.item}
|
||||
// style={{borderRadius: 5, marginBottom: 5, width:"100%"}}>
|
||||
//
|
||||
// <h3>{data.item} Devices: {data.count}</h3>
|
||||
//
|
||||
// </Card>
|
||||
<Col key={data.item} span={6}>
|
||||
<Card key={data.item} bordered={true} hoverable={true} style={{borderRadius: 10, marginBottom: 16}}>
|
||||
|
||||
<div align='center'>
|
||||
<h2><b>{data.item}</b></h2>
|
||||
<h1>{data.count}</h1>
|
||||
{/*<p>{data.duration}</p>*/}
|
||||
{/*<ReportFilterModal/>*/}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
|
||||
return(
|
||||
<div>
|
||||
{card}
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
return <div>{card}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default CountWidget;
|
||||
export default CountWidget;
|
||||
|
||||
@ -1,322 +1,342 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
import {
|
||||
G2,
|
||||
Chart,
|
||||
Geom,
|
||||
Axis,
|
||||
Tooltip,
|
||||
Coord,
|
||||
Label,
|
||||
Legend,
|
||||
View,
|
||||
Guide,
|
||||
Shape,
|
||||
Facet,
|
||||
Util
|
||||
} from "bizcharts";
|
||||
import DataSet from "@antv/data-set";
|
||||
import axios from "axios";
|
||||
import {message, notification} from "antd";
|
||||
import {withConfigContext} from "../../../context/ConfigContext";
|
||||
Chart,
|
||||
Geom,
|
||||
Axis,
|
||||
Tooltip,
|
||||
Coord,
|
||||
Label,
|
||||
Legend,
|
||||
Guide,
|
||||
} from 'bizcharts';
|
||||
import DataSet from '@antv/data-set';
|
||||
import axios from 'axios';
|
||||
import { message, notification } from 'antd';
|
||||
import { withConfigContext } from '../../../context/ConfigContext';
|
||||
|
||||
let config = null;
|
||||
|
||||
class PieChart extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
config = this.props.context;
|
||||
this.state = {
|
||||
loading: true,
|
||||
statArray: [],
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
config = this.props.context;
|
||||
this.state = {
|
||||
loading:true,
|
||||
statArray:[]
|
||||
};
|
||||
componentDidMount() {
|
||||
const { reportData } = this.props;
|
||||
let params = {
|
||||
status: reportData.params[0],
|
||||
from: reportData.duration[0],
|
||||
to: reportData.duration[1],
|
||||
};
|
||||
|
||||
const urlSet = {
|
||||
paramsList: reportData.params,
|
||||
duration: reportData.duration,
|
||||
};
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
if (reportData.params[0] === 'Enrollments') {
|
||||
this.getEnrollmentsVsUnenrollmentsCount(params, urlSet);
|
||||
} else if (reportData.params[0] === 'BYOD') {
|
||||
this.getEnrollmentTypeCount(params, urlSet);
|
||||
} else {
|
||||
this.getCount(params, urlSet);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let { statArray } = this.state;
|
||||
const { reportData } = this.props;
|
||||
let params = {
|
||||
status: reportData.params[0],
|
||||
from: reportData.duration[0],
|
||||
to: reportData.duration[1]
|
||||
};
|
||||
clicked = () => {
|
||||
console.log('Clicked...!!');
|
||||
};
|
||||
|
||||
const urlSet = {
|
||||
paramsList:reportData.params,
|
||||
duration:reportData.duration
|
||||
};
|
||||
onChartChange = data => {
|
||||
this.props.onClickPieChart(data);
|
||||
};
|
||||
|
||||
console.log(urlSet)
|
||||
statArray = [];
|
||||
|
||||
if(reportData.params[0]==="Enrollments"){
|
||||
this.getEnrollmentsVsUnenrollmentsCount(params, urlSet)
|
||||
}else if(reportData.params[0]==="BYOD"){
|
||||
this.getEnrollmentTypeCount(params, urlSet);
|
||||
}else{
|
||||
this.getCount(params, urlSet);
|
||||
// Call count APIs and get count for given parameters, then create data object to build pie chart
|
||||
getCount = (params, urlSet) => {
|
||||
this.setState({ loading: true });
|
||||
|
||||
let { statArray } = this.state;
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
const urlArray = [];
|
||||
|
||||
urlSet.paramsList.map(data => {
|
||||
const paramsObj = {
|
||||
status: data,
|
||||
from: urlSet.duration[0],
|
||||
to: urlSet.duration[1],
|
||||
};
|
||||
// console.log(paramsObj)
|
||||
const encodedExtraParams = Object.keys(paramsObj)
|
||||
.map(key => key + '=' + paramsObj[key])
|
||||
.join('&');
|
||||
const apiUrl =
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/reports/devices/count?' +
|
||||
encodedExtraParams;
|
||||
|
||||
urlArray.push(axios.get(apiUrl, data));
|
||||
});
|
||||
|
||||
console.log(urlArray);
|
||||
|
||||
axios
|
||||
.all(urlArray)
|
||||
.then(res => {
|
||||
res.map(response => {
|
||||
if (response.status === 200) {
|
||||
let countData = {
|
||||
item: response.config[0],
|
||||
// eslint-disable-next-line radix
|
||||
count: parseInt(response.data.data),
|
||||
};
|
||||
statArray.push(countData);
|
||||
}
|
||||
});
|
||||
this.setState({ statArray });
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 401) {
|
||||
// todo display a popup 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 get device count.',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
clicked = () => {
|
||||
console.log("Clicked...!!")
|
||||
// Call count APIs and get count for given parameters, then create data object to build pie chart
|
||||
getEnrollmentsVsUnenrollmentsCount = (params, urlSet) => {
|
||||
this.setState({ loading: true });
|
||||
|
||||
let { statArray } = this.state;
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
const urlArray = [];
|
||||
|
||||
urlSet.paramsList.map(data => {
|
||||
const paramsObj = {
|
||||
from: urlSet.duration[0],
|
||||
to: urlSet.duration[1],
|
||||
};
|
||||
const encodedExtraParams = Object.keys(paramsObj)
|
||||
.map(key => key + '=' + paramsObj[key])
|
||||
.join('&');
|
||||
|
||||
let apiUrl;
|
||||
if (data === 'Enrollments') {
|
||||
apiUrl =
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/reports/devices/count?status=ACTIVE&status=INACTIVE&' +
|
||||
encodedExtraParams;
|
||||
} else {
|
||||
apiUrl =
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/reports/devices/count?status=REMOVED&' +
|
||||
encodedExtraParams;
|
||||
}
|
||||
|
||||
urlArray.push(axios.get(apiUrl, data));
|
||||
});
|
||||
|
||||
console.log(urlArray);
|
||||
|
||||
axios
|
||||
.all(urlArray)
|
||||
.then(res => {
|
||||
res.map(response => {
|
||||
if (response.status === 200) {
|
||||
let countData = {
|
||||
item: response.config[0],
|
||||
// eslint-disable-next-line radix
|
||||
count: parseInt(response.data.data),
|
||||
};
|
||||
statArray.push(countData);
|
||||
}
|
||||
});
|
||||
this.setState({ statArray });
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 401) {
|
||||
// todo display a popup 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 get device count.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Call count APIs and get count for given parameters, then create data object to build pie chart
|
||||
getEnrollmentTypeCount = (params, urlSet) => {
|
||||
this.setState({ loading: true });
|
||||
|
||||
let { statArray } = this.state;
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
const urlArray = [];
|
||||
|
||||
urlSet.paramsList.map(data => {
|
||||
const paramsObj = {
|
||||
ownership: data,
|
||||
from: urlSet.duration[0],
|
||||
to: urlSet.duration[1],
|
||||
};
|
||||
const encodedExtraParams = Object.keys(paramsObj)
|
||||
.map(key => key + '=' + paramsObj[key])
|
||||
.join('&');
|
||||
const apiUrl =
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/reports/devices/count?' +
|
||||
encodedExtraParams;
|
||||
|
||||
urlArray.push(axios.get(apiUrl, data));
|
||||
});
|
||||
|
||||
console.log(urlArray);
|
||||
|
||||
axios
|
||||
.all(urlArray)
|
||||
.then(res => {
|
||||
res.map(response => {
|
||||
if (response.status === 200) {
|
||||
let countData = {
|
||||
item: response.config[0],
|
||||
// eslint-disable-next-line radix
|
||||
count: parseInt(response.data.data),
|
||||
};
|
||||
statArray.push(countData);
|
||||
}
|
||||
});
|
||||
this.setState({ statArray });
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 401) {
|
||||
// todo display a popup 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 get device count.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { DataView } = DataSet;
|
||||
const { Html } = Guide;
|
||||
const { statArray } = this.state;
|
||||
|
||||
const dv = new DataView();
|
||||
dv.source(statArray).transform({
|
||||
type: 'percent',
|
||||
field: 'count',
|
||||
dimension: 'item',
|
||||
as: 'percent',
|
||||
});
|
||||
const cols = {
|
||||
percent: {
|
||||
formatter: val => {
|
||||
val = val * 100 + '%';
|
||||
return val;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
onChartChange = (data) => {
|
||||
this.props.onClickPieChart(data);
|
||||
};
|
||||
|
||||
statArray = [];
|
||||
|
||||
//Call count APIs and get count for given parameters, then create data object to build pie chart
|
||||
getCount = (params, urlSet) => {
|
||||
|
||||
this.setState({loading: true});
|
||||
|
||||
let { statArray } = this.state;
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
const urlArray = [];
|
||||
|
||||
urlSet.paramsList.map((data) => {
|
||||
const paramsObj = {
|
||||
status:data,
|
||||
from:urlSet.duration[0],
|
||||
to:urlSet.duration[1]
|
||||
}
|
||||
// console.log(paramsObj)
|
||||
const encodedExtraParams = Object.keys(paramsObj)
|
||||
.map(key => key + '=' + paramsObj[key]).join('&');
|
||||
const apiUrl = window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/reports/devices/count?" + encodedExtraParams;
|
||||
|
||||
urlArray.push(axios.get(apiUrl, data));
|
||||
});
|
||||
|
||||
console.log(urlArray)
|
||||
|
||||
|
||||
axios.all(urlArray).then(res => {
|
||||
|
||||
res.map((response) => {
|
||||
if(response.status === 200){
|
||||
let countData = {item:response.config[0], count:parseInt(response.data.data)}
|
||||
statArray.push(countData);
|
||||
}
|
||||
})
|
||||
this.setState({statArray})
|
||||
}).catch((error) => {
|
||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
||||
//todo display a popup 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 get device count.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//Call count APIs and get count for given parameters, then create data object to build pie chart
|
||||
getEnrollmentsVsUnenrollmentsCount = (params, urlSet) => {
|
||||
|
||||
this.setState({loading: true});
|
||||
|
||||
let { statArray } = this.state;
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
const urlArray = [];
|
||||
|
||||
urlSet.paramsList.map((data) => {
|
||||
const paramsObj = {
|
||||
from:urlSet.duration[0],
|
||||
to:urlSet.duration[1]
|
||||
}
|
||||
const encodedExtraParams = Object.keys(paramsObj)
|
||||
.map(key => key + '=' + paramsObj[key]).join('&');
|
||||
|
||||
let apiUrl;
|
||||
if(data==="Enrollments"){
|
||||
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/reports/devices/count?status=ACTIVE&status=INACTIVE&" + encodedExtraParams;
|
||||
}else{
|
||||
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/reports/devices/count?status=REMOVED&" + encodedExtraParams;
|
||||
}
|
||||
|
||||
urlArray.push(axios.get(apiUrl, data));
|
||||
});
|
||||
|
||||
console.log(urlArray)
|
||||
|
||||
|
||||
axios.all(urlArray).then(res => {
|
||||
res.map((response) => {
|
||||
if(response.status === 200){
|
||||
let countData = {item:response.config[0], count:parseInt(response.data.data)}
|
||||
statArray.push(countData);
|
||||
}
|
||||
})
|
||||
this.setState({statArray})
|
||||
}).catch((error) => {
|
||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
||||
//todo display a popup 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 get device count.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//Call count APIs and get count for given parameters, then create data object to build pie chart
|
||||
getEnrollmentTypeCount = (params, urlSet) => {
|
||||
|
||||
this.setState({loading: true});
|
||||
|
||||
let { statArray } = this.state;
|
||||
|
||||
console.log(urlSet);
|
||||
|
||||
const urlArray = [];
|
||||
|
||||
urlSet.paramsList.map((data) => {
|
||||
const paramsObj = {
|
||||
ownership:data,
|
||||
from:urlSet.duration[0],
|
||||
to:urlSet.duration[1]
|
||||
}
|
||||
const encodedExtraParams = Object.keys(paramsObj)
|
||||
.map(key => key + '=' + paramsObj[key]).join('&');
|
||||
const apiUrl = window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/reports/devices/count?" + encodedExtraParams;
|
||||
|
||||
urlArray.push(axios.get(apiUrl, data));
|
||||
});
|
||||
|
||||
console.log(urlArray)
|
||||
|
||||
|
||||
axios.all(urlArray).then(res => {
|
||||
res.map((response) => {
|
||||
if(response.status === 200){
|
||||
let countData = {item:response.config[0], count:parseInt(response.data.data)}
|
||||
statArray.push(countData);
|
||||
}
|
||||
})
|
||||
this.setState({statArray})
|
||||
}).catch((error) => {
|
||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
||||
//todo display a popup 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 get device count.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { DataView } = DataSet;
|
||||
const { Html } = Guide;
|
||||
const { statArray , loading} = this.state;
|
||||
|
||||
const dv = new DataView();
|
||||
dv.source(statArray).transform({
|
||||
type: "percent",
|
||||
field: "count",
|
||||
dimension: "item",
|
||||
as: "percent"
|
||||
});
|
||||
const cols = {
|
||||
percent: {
|
||||
formatter: val => {
|
||||
val = val * 100 + "%";
|
||||
return val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Chart
|
||||
height={window.innerHeight/2}
|
||||
data={dv}
|
||||
scale={cols}
|
||||
padding={[20, 25, 20, 20]}
|
||||
forceFit
|
||||
onPlotClick={this.onChartChange}
|
||||
animate={true}
|
||||
>
|
||||
<Coord type={"theta"} radius={0.75} innerRadius={0.6} />
|
||||
<Axis name="percent" />
|
||||
<Legend
|
||||
position="right"
|
||||
offsetY={-window.innerHeight / 2 + 120}
|
||||
offsetX={-100}
|
||||
/>
|
||||
<Tooltip
|
||||
showTitle={false}
|
||||
itemTpl="<li><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}</li>"
|
||||
/>
|
||||
<Guide>
|
||||
<Html
|
||||
position={["50%", "50%"]}
|
||||
html="<div style="color:#8c8c8c;font-size:1.16em;text-align: center;width: 10em;">Total<br><span style="color:#262626;font-size:2.5em">200</span>台</div>"
|
||||
alignX="middle"
|
||||
alignY="middle"
|
||||
/>
|
||||
</Guide>
|
||||
<div onClick={this.clicked}>
|
||||
<Geom
|
||||
type="intervalStack"
|
||||
position="percent"
|
||||
color="item"
|
||||
|
||||
tooltip={[
|
||||
"item*percent",
|
||||
(item, percent) => {
|
||||
percent = percent * 100 + "%";
|
||||
return {
|
||||
name: item,
|
||||
value: percent
|
||||
};
|
||||
}
|
||||
]}
|
||||
style={{
|
||||
lineWidth: 1,
|
||||
stroke: "#fff"
|
||||
}}
|
||||
>
|
||||
<Label
|
||||
content="percent"
|
||||
formatter={(val, item) => {
|
||||
return item.point.item + ": " + val;
|
||||
}}/>
|
||||
</Geom>
|
||||
</div>
|
||||
|
||||
</Chart>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Chart
|
||||
height={window.innerHeight / 2}
|
||||
data={dv}
|
||||
scale={cols}
|
||||
padding={[20, 25, 20, 20]}
|
||||
forceFit
|
||||
onPlotClick={this.onChartChange}
|
||||
animate={true}
|
||||
>
|
||||
<Coord type={'theta'} radius={0.75} innerRadius={0.6} />
|
||||
<Axis name="percent" />
|
||||
<Legend
|
||||
position="right"
|
||||
offsetY={-window.innerHeight / 2 + 120}
|
||||
offsetX={-100}
|
||||
/>
|
||||
<Tooltip
|
||||
showTitle={false}
|
||||
itemTpl='<li><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}</li>'
|
||||
/>
|
||||
<Guide>
|
||||
<Html
|
||||
position={['50%', '50%']}
|
||||
html='<div style="color:#8c8c8c;font-size:1.16em;text-align: center;width: 10em;">Total<br><span style="color:#262626;font-size:2.5em">200</span>台</div>'
|
||||
alignX="middle"
|
||||
alignY="middle"
|
||||
/>
|
||||
</Guide>
|
||||
<div onClick={this.clicked}>
|
||||
<Geom
|
||||
type="intervalStack"
|
||||
position="percent"
|
||||
color="item"
|
||||
tooltip={[
|
||||
'item*percent',
|
||||
(item, percent) => {
|
||||
percent = percent * 100 + '%';
|
||||
return {
|
||||
name: item,
|
||||
value: percent,
|
||||
};
|
||||
},
|
||||
]}
|
||||
style={{
|
||||
lineWidth: 1,
|
||||
stroke: '#fff',
|
||||
}}
|
||||
>
|
||||
<Label
|
||||
content="percent"
|
||||
formatter={(val, item) => {
|
||||
return item.point.item + ': ' + val;
|
||||
}}
|
||||
/>
|
||||
</Geom>
|
||||
</div>
|
||||
</Chart>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(PieChart);
|
||||
export default withConfigContext(PieChart);
|
||||
|
||||
@ -1,340 +1,392 @@
|
||||
import React from 'react';
|
||||
import {Button, Form, Input, message, Modal, notification, Select, Tree} from "antd";
|
||||
import {withConfigContext} from "../../context/ConfigContext";
|
||||
import axios from "axios";
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
notification,
|
||||
Select,
|
||||
Tree,
|
||||
} from 'antd';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
import axios from 'axios';
|
||||
|
||||
const {Option} = Select;
|
||||
const {TreeNode} = Tree;
|
||||
const { Option } = Select;
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
class AddRole extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.expandKeys = [];
|
||||
this.state = {
|
||||
isAddRoleModalVisible: false,
|
||||
isAddPermissionModalVisible: false,
|
||||
roleName: '',
|
||||
users: [],
|
||||
nodeList: [],
|
||||
expandedKeys: [],
|
||||
autoExpandParent: true,
|
||||
checkedKeys: [],
|
||||
isNodeList: false,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.expandKeys = [];
|
||||
this.state = {
|
||||
openAddModal = () => {
|
||||
this.setState({
|
||||
isAddRoleModalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
onCancelHandler = e => {
|
||||
this.setState({
|
||||
isAddRoleModalVisible: false,
|
||||
isAddPermissionModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
getCheckedPermissionsList = data => {
|
||||
data.forEach(item => {
|
||||
if (item !== null) {
|
||||
this.expandKeys.push(item.resourcePath);
|
||||
this.getCheckedPermissionsList(item.nodeList);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onAddRole = e => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.onConfirmAddRole(values);
|
||||
}
|
||||
console.log(values);
|
||||
});
|
||||
};
|
||||
|
||||
onExpand = expandedKeys => {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false,
|
||||
});
|
||||
};
|
||||
|
||||
onCheck = checkedKeys => {
|
||||
this.setState({ checkedKeys });
|
||||
};
|
||||
|
||||
onConfirmAddRole = value => {
|
||||
const roleData = {
|
||||
roleName: value.roleName,
|
||||
users: value.users,
|
||||
};
|
||||
this.setState({
|
||||
roleName: value.roleName,
|
||||
});
|
||||
axios
|
||||
.post(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles',
|
||||
roleData,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 201) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isAddRoleModalVisible: false,
|
||||
isAddPermissionModalVisible: false,
|
||||
roleName: '',
|
||||
users: [],
|
||||
nodeList: [],
|
||||
expandedKeys: [],
|
||||
autoExpandParent: true,
|
||||
checkedKeys: [],
|
||||
isNodeList: false,
|
||||
isAddPermissionModalVisible: true,
|
||||
});
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully added the role.',
|
||||
});
|
||||
this.loadPermissionList();
|
||||
}
|
||||
}
|
||||
})
|
||||
.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 role.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
openAddModal = () => {
|
||||
this.setState({
|
||||
isAddRoleModalVisible: true
|
||||
});
|
||||
renderTreeNodes = data => {
|
||||
return data.map(item => {
|
||||
if (item !== null) {
|
||||
if (item.hasOwnProperty('nodeList')) {
|
||||
return (
|
||||
<TreeNode
|
||||
title={item.displayName}
|
||||
key={item.resourcePath}
|
||||
dataRef={item}
|
||||
>
|
||||
{this.renderTreeNodes(item.nodeList)}
|
||||
</TreeNode>
|
||||
);
|
||||
}
|
||||
return <TreeNode key={item.resourcePath} {...item} />;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
return <TreeNode />;
|
||||
});
|
||||
};
|
||||
|
||||
onAssignPermissions = () => {
|
||||
const roleData = {
|
||||
roleName: this.state.roleName,
|
||||
permissions: this.state.checkedKeys,
|
||||
};
|
||||
|
||||
onCancelHandler = e => {
|
||||
this.setState({
|
||||
isAddRoleModalVisible: false,
|
||||
axios
|
||||
.put(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.state.roleName,
|
||||
roleData,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully Updated the Permissions.',
|
||||
});
|
||||
this.setState({
|
||||
isAddPermissionModalVisible: 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 add permissions.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getCheckedPermissionsList = (data) =>{
|
||||
data.forEach(item => {
|
||||
if (item !== null) {
|
||||
this.expandKeys.push(item.resourcePath);
|
||||
this.getCheckedPermissionsList(item.nodeList);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
loadPermissionList = () => {
|
||||
let apiURL =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.state.roleName +
|
||||
'/permissions';
|
||||
|
||||
onAddRole = e => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.onConfirmAddRole(values);
|
||||
}
|
||||
console.log(values);
|
||||
});
|
||||
};
|
||||
axios
|
||||
.get(apiURL)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.getCheckedPermissionsList(res.data.data.nodeList);
|
||||
this.setState({
|
||||
nodeList: res.data.data.nodeList,
|
||||
isNodeList: true,
|
||||
expandedKeys: this.expandKeys,
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 permission.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onExpand = expandedKeys => {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false,
|
||||
});
|
||||
};
|
||||
loadUsersList = value => {
|
||||
let apiURL =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/users/search/usernames?filter=' +
|
||||
value +
|
||||
'&domain=Primary';
|
||||
axios
|
||||
.get(apiURL)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
let user = JSON.parse(res.data.data);
|
||||
let users = [];
|
||||
for (let i = 0; i < user.length; i++) {
|
||||
users.push(
|
||||
<Option key={user[i].username}>{user[i].username}</Option>,
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
users: users,
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 users.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onCheck = checkedKeys => {
|
||||
this.setState({checkedKeys});
|
||||
};
|
||||
|
||||
onConfirmAddRole = (value) => {
|
||||
const roleData = {
|
||||
roleName: value.roleName,
|
||||
users: value.users,
|
||||
};
|
||||
this.setState({
|
||||
roleName: value.roleName,
|
||||
});
|
||||
axios.post(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles",
|
||||
roleData,
|
||||
{headers: {'Content-Type': 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 201) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isAddRoleModalVisible: false,
|
||||
isAddPermissionModalVisible: true,
|
||||
|
||||
});
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully added the role.",
|
||||
});
|
||||
this.loadPermissionList();
|
||||
}
|
||||
}).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 role.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
renderTreeNodes = (data) => {
|
||||
return data.map(item => {
|
||||
if (item !== null) {
|
||||
if (item.hasOwnProperty("nodeList")) {
|
||||
return (
|
||||
<TreeNode title={item.displayName} key={item.resourcePath} dataRef={item}>
|
||||
{this.renderTreeNodes(item.nodeList)}
|
||||
</TreeNode>
|
||||
);
|
||||
}
|
||||
return <TreeNode key={item.resourcePath} {...item}/>;
|
||||
}
|
||||
else{
|
||||
return <TreeNode/>;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onAssignPermissions = () =>{
|
||||
const roleData = {
|
||||
roleName : this.state.roleName,
|
||||
permissions : this.state.checkedKeys
|
||||
};
|
||||
axios.put(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles/"+ this.state.roleName,
|
||||
roleData,
|
||||
{headers: {'Content-Type' : 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully Updated the Permissions.",
|
||||
});
|
||||
this.setState({
|
||||
isAddPermissionModalVisible : 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 add permissions.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
loadPermissionList = () => {
|
||||
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt + "/roles/" + this.state.roleName + "/permissions";
|
||||
|
||||
axios.get(apiURL).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.getCheckedPermissionsList(res.data.data.nodeList);
|
||||
this.setState({
|
||||
nodeList: res.data.data.nodeList,
|
||||
isNodeList: true,
|
||||
expandedKeys : this.expandKeys
|
||||
});
|
||||
|
||||
}
|
||||
}).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 permission.",
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
loadUsersList = (value) => {
|
||||
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt + "/users/search/usernames?filter=" + value + "&domain=Primary";
|
||||
axios.get(apiURL).then(res => {
|
||||
if (res.status === 200) {
|
||||
let user = JSON.parse(res.data.data);
|
||||
let users = [];
|
||||
for (let i = 0; i < user.length; i++) {
|
||||
users.push(<Option key={user[i].username}>{user[i].username}</Option>);
|
||||
}
|
||||
this.setState({
|
||||
users: users
|
||||
});
|
||||
|
||||
}
|
||||
}).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 users.",
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
render() {
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Button type="primary" icon="plus" size={"default"} onClick={this.openAddModal}
|
||||
style={{marginBottom: '10px'}}>
|
||||
Add Role
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ADD NEW ROLE"
|
||||
width="40%"
|
||||
visible={this.state.isAddRoleModalVisible}
|
||||
onOk={this.onAddRole}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onAddRole}>
|
||||
Add Role
|
||||
</Button>,
|
||||
]}>
|
||||
<div style={{alignItems: "center"}}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form
|
||||
labelCol={{span: 5}}
|
||||
wrapperCol={{span: 18}}>
|
||||
<Form.Item label="User Store Domain" style={{display: "block"}}>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue: 'PRIMARY'
|
||||
})(
|
||||
<Select>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Role Name" style={{display: "block"}}>
|
||||
{getFieldDecorator('roleName', {
|
||||
rules: [
|
||||
{
|
||||
pattern: new RegExp("^(((?!(\\@|\\/|\\s)).){3,})*$"),
|
||||
message: 'Role name should be in minimum 3 characters long and not ' +
|
||||
'include any whitespaces or @ or /',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required.',
|
||||
},
|
||||
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User List" style={{display: "block"}}>
|
||||
{getFieldDecorator('users', {})(<Select
|
||||
mode="multiple"
|
||||
style={{width: '100%'}}
|
||||
onSearch={this.loadUsersList}>
|
||||
{this.state.users}
|
||||
</Select>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="CHANGE ROLE PERMISSION"
|
||||
width="40%"
|
||||
visible={this.state.isAddPermissionModalVisible}
|
||||
onOk={this.onAssignPermissions}
|
||||
onCancel={this.onCancelHandler}
|
||||
bodyStyle={{overflowY:"scroll", maxHeight:'500px', marginLeft:'10px'}}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onAssignPermissions}>
|
||||
Assign
|
||||
</Button>,
|
||||
]}>
|
||||
<div style={{alignItems: "center"}}>
|
||||
<div>
|
||||
{(this.state.isNodeList) && (
|
||||
<Tree
|
||||
checkable
|
||||
onExpand={this.onExpand}
|
||||
expandedKeys={this.state.expandedKeys}
|
||||
autoExpandParent={this.state.autoExpandParent}
|
||||
onCheck={this.onCheck}
|
||||
checkedKeys={this.state.checkedKeys}>
|
||||
{this.renderTreeNodes(this.state.nodeList)}
|
||||
</Tree>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
size={'default'}
|
||||
onClick={this.openAddModal}
|
||||
style={{ marginBottom: '10px' }}
|
||||
>
|
||||
Add Role
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ADD NEW ROLE"
|
||||
width="40%"
|
||||
visible={this.state.isAddRoleModalVisible}
|
||||
onOk={this.onAddRole}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onAddRole}>
|
||||
Add Role
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 18 }}>
|
||||
<Form.Item
|
||||
label="User Store Domain"
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue: 'PRIMARY',
|
||||
})(
|
||||
<Select>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Role Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('roleName', {
|
||||
rules: [
|
||||
{
|
||||
pattern: new RegExp('^(((?!(\\@|\\/|\\s)).){3,})*$'),
|
||||
message:
|
||||
'Role name should be in minimum 3 characters long and not ' +
|
||||
'include any whitespaces or @ or /',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required.',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User List" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('users', {})(
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}
|
||||
onSearch={this.loadUsersList}
|
||||
>
|
||||
{this.state.users}
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="CHANGE ROLE PERMISSION"
|
||||
width="40%"
|
||||
visible={this.state.isAddPermissionModalVisible}
|
||||
onOk={this.onAssignPermissions}
|
||||
onCancel={this.onCancelHandler}
|
||||
bodyStyle={{
|
||||
overflowY: 'scroll',
|
||||
maxHeight: '500px',
|
||||
marginLeft: '10px',
|
||||
}}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
onClick={this.onAssignPermissions}
|
||||
>
|
||||
Assign
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<div>
|
||||
{this.state.isNodeList && (
|
||||
<Tree
|
||||
checkable
|
||||
onExpand={this.onExpand}
|
||||
expandedKeys={this.state.expandedKeys}
|
||||
autoExpandParent={this.state.autoExpandParent}
|
||||
onCheck={this.onCheck}
|
||||
checkedKeys={this.state.checkedKeys}
|
||||
>
|
||||
{this.renderTreeNodes(this.state.nodeList)}
|
||||
</Tree>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'add-role'})(AddRole))
|
||||
export default withConfigContext(Form.create({ name: 'add-role' })(AddRole));
|
||||
|
||||
@ -1,428 +1,489 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
Form,
|
||||
Icon,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
notification,
|
||||
Popconfirm,
|
||||
Select,
|
||||
Tooltip, Tree,
|
||||
Typography
|
||||
} from "antd";
|
||||
import axios from "axios";
|
||||
import {withConfigContext} from "../../context/ConfigContext";
|
||||
Button,
|
||||
Divider,
|
||||
Form,
|
||||
Icon,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
notification,
|
||||
Popconfirm,
|
||||
Select,
|
||||
Tooltip,
|
||||
Tree,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import axios from 'axios';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
const { Option } = Select;
|
||||
const {Text} = Typography;
|
||||
const { Text } = Typography;
|
||||
const { TreeNode } = Tree;
|
||||
|
||||
class RoleAction extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.selected = [];
|
||||
this.expandKeys = [];
|
||||
this.state = {
|
||||
roleData: [],
|
||||
nodeList : [],
|
||||
isNodeList: false,
|
||||
users : [],
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.selected = [];
|
||||
this.expandKeys = [];
|
||||
this.state = {
|
||||
roleData: [],
|
||||
nodeList: [],
|
||||
isNodeList: false,
|
||||
users: [],
|
||||
isEditRoleModalVisible: false,
|
||||
isEditPermissionModalVisible: false,
|
||||
expandedKeys: [],
|
||||
autoExpandParent: true,
|
||||
checkedKeys: [],
|
||||
};
|
||||
}
|
||||
|
||||
openEditRoleModal = () => {
|
||||
let apiUrl =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.props.data;
|
||||
|
||||
axios
|
||||
.get(apiUrl)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.setState({
|
||||
roleData: res.data.data,
|
||||
isEditRoleModalVisible: true,
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 role.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
openEditPermissionModal = () => {
|
||||
this.loadPermissionList();
|
||||
this.setState({
|
||||
isEditPermissionModalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
loadPermissionList = () => {
|
||||
let apiURL =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.props.data +
|
||||
'/permissions';
|
||||
|
||||
axios
|
||||
.get(apiURL)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.getCheckedPermissions(res.data.data.nodeList);
|
||||
this.setState({
|
||||
nodeList: res.data.data.nodeList,
|
||||
isNodeList: true,
|
||||
checkedKeys: this.selected,
|
||||
expandedKeys: this.expandKeys,
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 permission.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
getCheckedPermissions = data => {
|
||||
data.forEach(item => {
|
||||
if (item !== null) {
|
||||
this.expandKeys.push(item.resourcePath);
|
||||
if (item.isSelected) {
|
||||
this.selected.push(item.resourcePath);
|
||||
}
|
||||
this.getCheckedPermissions(item.nodeList);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onExpand = expandedKeys => {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false,
|
||||
});
|
||||
};
|
||||
|
||||
onCheck = checkedKeys => {
|
||||
this.setState({ checkedKeys });
|
||||
};
|
||||
|
||||
renderTreeNodes = data => {
|
||||
return data.map(item => {
|
||||
if (item !== null) {
|
||||
if (item.hasOwnProperty('nodeList')) {
|
||||
return (
|
||||
<TreeNode
|
||||
title={item.displayName}
|
||||
key={item.resourcePath}
|
||||
dataRef={item}
|
||||
>
|
||||
{this.renderTreeNodes(item.nodeList)}
|
||||
</TreeNode>
|
||||
);
|
||||
}
|
||||
return <TreeNode key={item.resourcePath} {...item} />;
|
||||
}
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
return <TreeNode />;
|
||||
});
|
||||
};
|
||||
|
||||
onUpdateRole = e => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.onConfirmUpdateRole(values);
|
||||
}
|
||||
console.log(values);
|
||||
});
|
||||
};
|
||||
|
||||
onCancelHandler = e => {
|
||||
this.setState({
|
||||
isEditRoleModalVisible: false,
|
||||
isEditPermissionModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
onConfirmUpdateRole = value => {
|
||||
const roleData = {
|
||||
roleName: value.roleName,
|
||||
users: value.users,
|
||||
};
|
||||
axios
|
||||
.put(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.props.data,
|
||||
roleData,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isEditRoleModalVisible: false,
|
||||
});
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully Updated the role.',
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 role.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onAssignPermission = () => {
|
||||
const roleData = {
|
||||
roleName: this.props.data,
|
||||
permissions: this.state.checkedKeys,
|
||||
};
|
||||
axios
|
||||
.put(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.props.data,
|
||||
roleData,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully Updated the Permissions.',
|
||||
});
|
||||
this.setState({
|
||||
isEditPermissionModalVisible: false,
|
||||
expandedKeys: [],
|
||||
autoExpandParent: true,
|
||||
checkedKeys: [],
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 permissions.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
openEditRoleModal = () =>{
|
||||
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles/"+ this.props.data;
|
||||
loadUsersList = value => {
|
||||
let apiURL =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/users/search/usernames?filter=' +
|
||||
value +
|
||||
'&domain=Primary';
|
||||
axios
|
||||
.get(apiURL)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
let user = JSON.parse(res.data.data);
|
||||
let users = [];
|
||||
for (let i = 0; i < user.length; i++) {
|
||||
users.push(
|
||||
<Option key={user[i].username}>{user[i].username}</Option>,
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
users: users,
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 users.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
axios.get(apiUrl).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.setState({
|
||||
roleData : res.data.data,
|
||||
isEditRoleModalVisible: true,
|
||||
});
|
||||
}
|
||||
onDeleteRole = () => {
|
||||
axios
|
||||
.delete(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
this.props.data,
|
||||
{ headers: { 'Content-Type': 'application/json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully deleted the Role.',
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 role.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
}).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 role.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
render() {
|
||||
const isAdminRole = this.props.data === 'admin';
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: isAdminRole ? 'none' : 'inline' }}>
|
||||
<Tooltip placement="top" title={'Edit Role'}>
|
||||
<a>
|
||||
<Icon type="edit" onClick={this.openEditRoleModal} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="top" title={'Edit Permissions'}>
|
||||
<a>
|
||||
<Icon type="file-add" onClick={this.openEditPermissionModal} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={'Remove Role'}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={'Are you sure?'}
|
||||
onConfirm={this.onDeleteRole}
|
||||
okText="Ok"
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<a>
|
||||
<Text type="danger">
|
||||
<Icon type="delete" />
|
||||
</Text>
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
openEditPermissionModal =()=>{
|
||||
this.loadPermissionList();
|
||||
this.setState({
|
||||
isEditPermissionModalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
loadPermissionList = () => {
|
||||
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt + "/roles/"+this.props.data+"/permissions";
|
||||
|
||||
axios.get(apiURL).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.getCheckedPermissions(res.data.data.nodeList);
|
||||
this.setState({
|
||||
nodeList : res.data.data.nodeList,
|
||||
isNodeList: true,
|
||||
checkedKeys : this.selected,
|
||||
expandedKeys : this.expandKeys
|
||||
});
|
||||
}
|
||||
}).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 permission.",
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
getCheckedPermissions = (data) =>{
|
||||
data.forEach(item => {
|
||||
if (item !== null) {
|
||||
this.expandKeys.push(item.resourcePath);
|
||||
if (item.isSelected) {
|
||||
this.selected.push(item.resourcePath);
|
||||
}
|
||||
this.getCheckedPermissions(item.nodeList);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onExpand = expandedKeys => {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false,
|
||||
});
|
||||
};
|
||||
|
||||
onCheck = checkedKeys => {
|
||||
this.setState({checkedKeys});
|
||||
};
|
||||
|
||||
renderTreeNodes = (data) => {
|
||||
return data.map(item => {
|
||||
if (item !== null) {
|
||||
if (item.hasOwnProperty("nodeList")) {
|
||||
return (
|
||||
<TreeNode title={item.displayName} key={item.resourcePath} dataRef={item}>
|
||||
{this.renderTreeNodes(item.nodeList)}
|
||||
</TreeNode>
|
||||
);
|
||||
}
|
||||
return <TreeNode key={item.resourcePath} {...item}/>;
|
||||
} else{
|
||||
return <TreeNode/>;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onUpdateRole = e => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.onConfirmUpdateRole(values);
|
||||
}
|
||||
console.log(values);
|
||||
});
|
||||
};
|
||||
|
||||
onCancelHandler = e =>{
|
||||
this.setState({
|
||||
isEditRoleModalVisible: false,
|
||||
isEditPermissionModalVisible:false,
|
||||
})
|
||||
};
|
||||
|
||||
onConfirmUpdateRole = (value) =>{
|
||||
const roleData = {
|
||||
roleName : value.roleName,
|
||||
users : value.users,
|
||||
};
|
||||
axios.put(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles/"+ this.props.data,
|
||||
roleData,
|
||||
{headers: {'Content-Type' : 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isEditRoleModalVisible: false,
|
||||
});
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully Updated the role.",
|
||||
});
|
||||
}
|
||||
}).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 role.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onAssignPermission = () =>{
|
||||
const roleData = {
|
||||
roleName : this.props.data,
|
||||
permissions : this.state.checkedKeys
|
||||
};
|
||||
axios.put(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles/"+ this.props.data,
|
||||
roleData,
|
||||
{headers: {'Content-Type' : 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully Updated the Permissions.",
|
||||
});
|
||||
this.setState({
|
||||
isEditPermissionModalVisible : 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 add permissions.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
loadUsersList = (value) => {
|
||||
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt + "/users/search/usernames?filter="+value+"&domain=Primary";
|
||||
axios.get(apiURL).then(res => {
|
||||
if (res.status === 200) {
|
||||
let user = JSON.parse(res.data.data);
|
||||
let users = [];
|
||||
for(let i=0; i<user.length; i++){
|
||||
users.push(<Option key={user[i].username}>{user[i].username}</Option>);
|
||||
}
|
||||
this.setState({
|
||||
users : users
|
||||
});
|
||||
|
||||
}
|
||||
}).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 users.",
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
onDeleteRole = () => {
|
||||
axios.delete(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles/" + this.props.data,
|
||||
{headers: {'Content-Type': 'application/json'}}
|
||||
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully deleted the Role.",
|
||||
});
|
||||
}
|
||||
}).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 role.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const isAdminRole = this.props.data ==="admin";
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div style={{display:isAdminRole ? "none" : "inline"}}>
|
||||
<Tooltip placement="top" title={"Edit Role"}>
|
||||
<a><Icon type="edit" onClick={this.openEditRoleModal}/></a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="top" title={"Edit Permissions"}>
|
||||
<a><Icon type="file-add" onClick={this.openEditPermissionModal}/></a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={"Remove Role"}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={"Are you sure?"}
|
||||
onConfirm={this.onDeleteRole}
|
||||
okText="Ok"
|
||||
cancelText="Cancel">
|
||||
<a><Text type="danger"><Icon type="delete"/></Text></a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Modal
|
||||
title="EDIT ROLE"
|
||||
width="40%"
|
||||
visible={this.state.isEditRoleModalVisible}
|
||||
onOk={this.onUpdateRole}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onUpdateRole}>
|
||||
Add Role
|
||||
</Button>,
|
||||
]}>
|
||||
<div style={{alignItems:"center"}}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 18 }}>
|
||||
<Form.Item label="User Store Domain" style={{display:"block"}}>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue : 'PRIMARY'
|
||||
})(
|
||||
<Select>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Role Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('roleName', {
|
||||
initialValue: this.state.roleData.roleName,
|
||||
rules: [
|
||||
{
|
||||
pattern : new RegExp("^(((?!(\\@|\\/|\\s)).){3,})*$"),
|
||||
message: 'Role name should be in minimum 3 characters long and not ' +
|
||||
'include any whitespaces or @ or /',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required.',
|
||||
},
|
||||
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User List" style={{display:"block"}}>
|
||||
{getFieldDecorator('users', {
|
||||
initialValue: this.state.roleData.users,
|
||||
})(<Select
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}
|
||||
onSearch={this.loadUsersList}>
|
||||
{this.state.users}
|
||||
</Select>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="CHANGE ROLE PERMISSION"
|
||||
width="40%"
|
||||
visible={this.state.isEditPermissionModalVisible}
|
||||
onOk={this.onAssignPermission}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onAssignPermission}>
|
||||
Assign
|
||||
</Button>,
|
||||
]}
|
||||
bodyStyle={{overflowY:"scroll", maxHeight:'500px', marginLeft:'10px'}}>
|
||||
<div>
|
||||
{(this.state.isNodeList) &&(
|
||||
<Tree
|
||||
checkable
|
||||
onExpand={this.onExpand}
|
||||
expandedKeys={this.state.expandedKeys}
|
||||
autoExpandParent={this.state.autoExpandParent}
|
||||
onCheck={this.onCheck}
|
||||
checkedKeys={this.state.checkedKeys}>
|
||||
{this.renderTreeNodes(this.state.nodeList)}
|
||||
</Tree>
|
||||
)}
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="EDIT ROLE"
|
||||
width="40%"
|
||||
visible={this.state.isEditRoleModalVisible}
|
||||
onOk={this.onUpdateRole}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onUpdateRole}>
|
||||
Add Role
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 18 }}>
|
||||
<Form.Item
|
||||
label="User Store Domain"
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue: 'PRIMARY',
|
||||
})(
|
||||
<Select>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Role Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('roleName', {
|
||||
initialValue: this.state.roleData.roleName,
|
||||
rules: [
|
||||
{
|
||||
pattern: new RegExp('^(((?!(\\@|\\/|\\s)).){3,})*$'),
|
||||
message:
|
||||
'Role name should be in minimum 3 characters long and not ' +
|
||||
'include any whitespaces or @ or /',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required.',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User List" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('users', {
|
||||
initialValue: this.state.roleData.users,
|
||||
})(
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}
|
||||
onSearch={this.loadUsersList}
|
||||
>
|
||||
{this.state.users}
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="CHANGE ROLE PERMISSION"
|
||||
width="40%"
|
||||
visible={this.state.isEditPermissionModalVisible}
|
||||
onOk={this.onAssignPermission}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
onClick={this.onAssignPermission}
|
||||
>
|
||||
Assign
|
||||
</Button>,
|
||||
]}
|
||||
bodyStyle={{
|
||||
overflowY: 'scroll',
|
||||
maxHeight: '500px',
|
||||
marginLeft: '10px',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
{this.state.isNodeList && (
|
||||
<Tree
|
||||
checkable
|
||||
onExpand={this.onExpand}
|
||||
expandedKeys={this.state.expandedKeys}
|
||||
autoExpandParent={this.state.autoExpandParent}
|
||||
onCheck={this.onCheck}
|
||||
checkedKeys={this.state.checkedKeys}
|
||||
>
|
||||
{this.renderTreeNodes(this.state.nodeList)}
|
||||
</Tree>
|
||||
)}
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'role-actions'})(RoleAction));
|
||||
export default withConfigContext(
|
||||
Form.create({ name: 'role-actions' })(RoleAction),
|
||||
);
|
||||
|
||||
@ -16,243 +16,251 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import axios from "axios";
|
||||
import {
|
||||
Button,
|
||||
message,
|
||||
Modal,
|
||||
notification,
|
||||
Table, List
|
||||
} from "antd";
|
||||
import TimeAgo from 'javascript-time-ago'
|
||||
import React from 'react';
|
||||
import axios from 'axios';
|
||||
import { Button, message, Modal, notification, Table, List } 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 AddRole from "./AddRole";
|
||||
import RoleAction from "./RoleAction";
|
||||
import Filter from "../Utils/Filter/Filter";
|
||||
import en from 'javascript-time-ago/locale/en';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
import AddRole from './AddRole';
|
||||
import RoleAction from './RoleAction';
|
||||
import Filter from '../Utils/Filter/Filter';
|
||||
|
||||
const searchFields = [
|
||||
{
|
||||
name: 'filter',
|
||||
placeholder: 'Name'
|
||||
}
|
||||
{
|
||||
name: 'filter',
|
||||
placeholder: 'Name',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
class RolesTable extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
TimeAgo.addLocale(en);
|
||||
this.state = {
|
||||
data: [],
|
||||
pagination: {},
|
||||
loading: false,
|
||||
selectedRows: [],
|
||||
userData: [],
|
||||
users : [],
|
||||
isEditRoleModalVisible: false,
|
||||
isUserListModalVisible :false,
|
||||
};
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
TimeAgo.addLocale(en);
|
||||
this.state = {
|
||||
data: [],
|
||||
pagination: {},
|
||||
loading: false,
|
||||
selectedRows: [],
|
||||
userData: [],
|
||||
users: [],
|
||||
isEditRoleModalVisible: false,
|
||||
isUserListModalVisible: false,
|
||||
};
|
||||
}
|
||||
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows
|
||||
})
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchUsers();
|
||||
}
|
||||
|
||||
openUserListModal = event => {
|
||||
let apiUrl =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles/' +
|
||||
event;
|
||||
|
||||
// send request to the invokerss
|
||||
axios
|
||||
.get(apiUrl)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.setState({
|
||||
userData: res.data.data.users,
|
||||
isUserListModalVisible: true,
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 users.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleOk = e => {
|
||||
this.setState({
|
||||
isUserListModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = e => {
|
||||
this.setState({
|
||||
isUserListModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
// fetch data from api
|
||||
fetchUsers = (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,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchUsers();
|
||||
}
|
||||
const encodedExtraParams = Object.keys(extraParams)
|
||||
.map(key => key + '=' + extraParams[key])
|
||||
.join('&');
|
||||
|
||||
openUserListModal = (event) => {
|
||||
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles/"+ event;
|
||||
let apiUrl =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles?' +
|
||||
encodedExtraParams;
|
||||
|
||||
//send request to the invokerss
|
||||
axios.get(apiUrl).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.setState({
|
||||
userData : res.data.data.users,
|
||||
isUserListModalVisible: true,
|
||||
});
|
||||
}
|
||||
// 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.roles,
|
||||
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 users.',
|
||||
});
|
||||
}
|
||||
|
||||
}).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 users.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
};
|
||||
|
||||
handleOk = e => {
|
||||
this.setState({
|
||||
isUserListModalVisible: 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,
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = e => {
|
||||
this.setState({
|
||||
isUserListModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
//fetch data from api
|
||||
fetchUsers = (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('&');
|
||||
|
||||
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/roles?" + 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.roles,
|
||||
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 users.",
|
||||
});
|
||||
}
|
||||
|
||||
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 columns = [
|
||||
{
|
||||
title: 'Role Name',
|
||||
dataIndex: '',
|
||||
key: "role",
|
||||
width: "60%",
|
||||
},
|
||||
{
|
||||
title: 'View',
|
||||
dataIndex: '',
|
||||
key: 'users',
|
||||
render: (id, row) =>
|
||||
<Button
|
||||
type="primary"
|
||||
size={"small"}
|
||||
icon="book"
|
||||
onClick={()=>this.openUserListModal(row)}>Users</Button>
|
||||
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: 'id',
|
||||
key: 'action',
|
||||
render: (id, row) => (
|
||||
<span>
|
||||
<RoleAction data={row} fetchUsers={this.fetchUsers}/>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
];
|
||||
return (
|
||||
render() {
|
||||
const { data, pagination, loading } = this.state;
|
||||
const columns = [
|
||||
{
|
||||
title: 'Role Name',
|
||||
dataIndex: '',
|
||||
key: 'role',
|
||||
width: '60%',
|
||||
},
|
||||
{
|
||||
title: 'View',
|
||||
dataIndex: '',
|
||||
key: 'users',
|
||||
render: (id, row) => (
|
||||
<Button
|
||||
type="primary"
|
||||
size={'small'}
|
||||
icon="book"
|
||||
onClick={() => this.openUserListModal(row)}
|
||||
>
|
||||
Users
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: 'id',
|
||||
key: 'action',
|
||||
render: (id, row) => (
|
||||
<span>
|
||||
<RoleAction data={row} fetchUsers={this.fetchUsers} />
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
return (
|
||||
<div>
|
||||
<div style={{ background: '#f0f2f5' }}>
|
||||
<AddRole fetchUsers={this.fetchUsers} />
|
||||
</div>
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<Filter fields={searchFields} callback={this.fetchUsers} />
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => record}
|
||||
dataSource={data}
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: 'small',
|
||||
// position: "top",
|
||||
showTotal: (total, range) =>
|
||||
`showing ${range[0]}-${range[1]} of ${total} groups`,
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="USERS"
|
||||
width="900px"
|
||||
visible={this.state.isUserListModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
>
|
||||
<div>
|
||||
<div style={{background: '#f0f2f5'}}>
|
||||
<AddRole fetchUsers={this.fetchUsers}/>
|
||||
</div>
|
||||
<div style={{textAlign: 'right'}}>
|
||||
<Filter fields={searchFields} callback={this.fetchUsers}/>
|
||||
</div>
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => (record)}
|
||||
dataSource={data}
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: "small",
|
||||
// position: "top",
|
||||
showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups`
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="USERS"
|
||||
width="900px"
|
||||
visible={this.state.isUserListModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel} >
|
||||
<div>
|
||||
<List
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={this.state.userData}
|
||||
renderItem={item => <List.Item>{item}</List.Item>}/>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<List
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={this.state.userData}
|
||||
renderItem={item => <List.Item>{item}</List.Item>}
|
||||
/>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(RolesTable);
|
||||
|
||||
@ -17,21 +17,28 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {Route} from 'react-router-dom';
|
||||
class RouteWithSubRoutes extends React.Component{
|
||||
props;
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.props = props;
|
||||
}
|
||||
render() {
|
||||
return(
|
||||
<Route path={this.props.path} exact={this.props.exact} render={(props) => (
|
||||
<this.props.component {...props} {...this.props} routes={this.props.routes}/>
|
||||
)}/>
|
||||
);
|
||||
}
|
||||
|
||||
import { Route } from 'react-router-dom';
|
||||
class RouteWithSubRoutes extends React.Component {
|
||||
props;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.props = props;
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Route
|
||||
path={this.props.path}
|
||||
exact={this.props.exact}
|
||||
render={props => (
|
||||
<this.props.component
|
||||
{...props}
|
||||
{...this.props}
|
||||
routes={this.props.routes}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default RouteWithSubRoutes;
|
||||
export default RouteWithSubRoutes;
|
||||
|
||||
@ -1,215 +1,245 @@
|
||||
import React from 'react';
|
||||
import {Button, Form, Select, Input, message, Modal, notification, Typography} from "antd";
|
||||
import axios from "axios";
|
||||
import {withConfigContext} from "../../context/ConfigContext";
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Select,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
notification,
|
||||
} from 'antd';
|
||||
import axios from 'axios';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
const { Option } = Select;
|
||||
const {Text} = Typography;
|
||||
|
||||
class AddUser extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.state = {
|
||||
isModalVisible: false,
|
||||
roles: [],
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.state = {
|
||||
componentDidMount() {
|
||||
this.getRole();
|
||||
}
|
||||
|
||||
openAddModal = () => {
|
||||
this.setState({
|
||||
isModalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
onSubmitHandler = e => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.onConfirmAddUser(values);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onConfirmAddUser = value => {
|
||||
const userData = {
|
||||
username: value.userStoreDomain + '/' + value.userName,
|
||||
firstname: value.firstName,
|
||||
lastname: value.lastName,
|
||||
emailAddress: value.email,
|
||||
roles: value.userRoles,
|
||||
};
|
||||
axios
|
||||
.post(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/users',
|
||||
userData,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 201) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isModalVisible: false,
|
||||
roles : []
|
||||
});
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully added the user.',
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.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 user.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.getRole();
|
||||
}
|
||||
onCancelHandler = e => {
|
||||
this.setState({
|
||||
isModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
openAddModal = () => {
|
||||
this.setState({
|
||||
isModalVisible:true
|
||||
});
|
||||
};
|
||||
getRole = () => {
|
||||
let apiURL =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles?user-store=PRIMARY&limit=100';
|
||||
|
||||
onSubmitHandler = e => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.onConfirmAddUser(values);
|
||||
}
|
||||
});
|
||||
};
|
||||
axios
|
||||
.get(apiURL)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
const roles = [];
|
||||
for (let i = 0; i < res.data.data.roles.length; i++) {
|
||||
roles.push(
|
||||
<Option key={res.data.data.roles[i]}>
|
||||
{res.data.data.roles[i]}
|
||||
</Option>,
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
roles: roles,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 401) {
|
||||
// todo display a popop with error
|
||||
|
||||
onConfirmAddUser = (value) =>{
|
||||
const userData = {
|
||||
username : value.userStoreDomain +"/"+value.userName,
|
||||
firstname : value.firstName,
|
||||
lastname : value.lastName,
|
||||
emailAddress : value.email,
|
||||
roles : value.userRoles
|
||||
};
|
||||
axios.post(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/users",
|
||||
userData,
|
||||
{headers: {'Content-Type' : 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 201) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isModalVisible: false,
|
||||
});
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully added the user.",
|
||||
});
|
||||
}
|
||||
}).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 user.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
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.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onCancelHandler = e => {
|
||||
this.setState({
|
||||
isModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
getRole = () => {
|
||||
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt + "/roles?user-store=PRIMARY&limit=100";
|
||||
|
||||
axios.get(apiURL).then(res => {
|
||||
if (res.status === 200) {
|
||||
const roles = [];
|
||||
for(let i=0; i<res.data.data.roles.length ; i++){
|
||||
roles.push(<Option key={res.data.data.roles[i]}>{res.data.data.roles[i]}</Option>);
|
||||
}
|
||||
this.setState({
|
||||
roles : 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.",
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Button type="primary" icon="plus" size={"default"} onClick={this.openAddModal} style={{marginBottom : '10px'}}>
|
||||
Add User
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ADD NEW USER"
|
||||
width="40%"
|
||||
visible={this.state.isModalVisible}
|
||||
onOk={this.onSubmitHandler}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onSubmitHandler}>
|
||||
Submit
|
||||
</Button>,
|
||||
]}>
|
||||
<div style={{alignItems:"center"}}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 18 }}>
|
||||
<Form.Item label="User Store Domain" style={{display:"block"}}>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue : 'PRIMARY'
|
||||
})(
|
||||
<Select>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('userName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required. Username should be at least 3 characters long with no white spaces.',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="First Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('firstName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Last Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('lastName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Email Address" style={{display:"block"}}>
|
||||
{getFieldDecorator('email', {
|
||||
rules: [
|
||||
{
|
||||
type: 'email',
|
||||
message: 'Invalid Email Address',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Roles" style={{display:"block"}}>
|
||||
{getFieldDecorator('userRoles', {
|
||||
})(<Select
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}>
|
||||
{this.state.roles}
|
||||
</Select>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Button
|
||||
type="primary"
|
||||
icon="plus"
|
||||
size={'default'}
|
||||
onClick={this.openAddModal}
|
||||
style={{ marginBottom: '10px' }}
|
||||
>
|
||||
Add User
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ADD NEW USER"
|
||||
width="40%"
|
||||
visible={this.state.isModalVisible}
|
||||
onOk={this.onSubmitHandler}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
onClick={this.onSubmitHandler}
|
||||
>
|
||||
Submit
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 18 }}>
|
||||
<Form.Item
|
||||
label="User Store Domain"
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue: 'PRIMARY',
|
||||
})(
|
||||
<Select>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('userName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message:
|
||||
'This field is required. Username should be at least 3 characters long with no white spaces.',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="First Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('firstName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Last Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('lastName', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Email Address" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('email', {
|
||||
rules: [
|
||||
{
|
||||
type: 'email',
|
||||
message: 'Invalid Email Address',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Roles" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('userRoles', {})(
|
||||
<Select mode="multiple" style={{ width: '100%' }}>
|
||||
{this.state.roles}
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'add-user'})(AddUser))
|
||||
export default withConfigContext(Form.create({ name: 'add-user' })(AddUser));
|
||||
|
||||
@ -1,423 +1,472 @@
|
||||
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 { Option } = Select;
|
||||
const {Text} = Typography;
|
||||
const { Text } = Typography;
|
||||
|
||||
class UserActions extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.state = {
|
||||
isEditModalVisible: false,
|
||||
isResetPasswordModalVisible: false,
|
||||
rolesData: [],
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.config = this.props.context;
|
||||
this.state = {
|
||||
isEditModalVisible: false,
|
||||
isResetPasswordModalVisible: false,
|
||||
rolesData: [],
|
||||
};
|
||||
}
|
||||
openEditModal = () => {
|
||||
this.setState({
|
||||
isEditModalVisible: true,
|
||||
});
|
||||
this.fetchRoles(this.props.data.username);
|
||||
};
|
||||
openPasswordResetModal = () => {
|
||||
this.setState({
|
||||
isResetPasswordModalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
onCancelHandler = () => {
|
||||
this.setState({
|
||||
isEditModalVisible: false,
|
||||
isResetPasswordModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
compareToFirstPassword = (rule, value, callback) => {
|
||||
if (value && value !== this.props.form.getFieldValue('password')) {
|
||||
callback("New password doesn't match the confirmation.");
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
openEditModal = () =>{
|
||||
this.setState({
|
||||
isEditModalVisible: true,
|
||||
});
|
||||
this.fetchRoles(this.props.data.username);
|
||||
};
|
||||
|
||||
};
|
||||
openPasswordResetModal = () =>{
|
||||
this.setState({
|
||||
isResetPasswordModalVisible: true,
|
||||
})
|
||||
};
|
||||
onSavePassword = () => {
|
||||
this.props.form.validateFields(
|
||||
['password', 'confirmPassword'],
|
||||
(err, values) => {
|
||||
if (!err) {
|
||||
this.onResetPassword(values);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
onCancelHandler = () =>{
|
||||
this.setState({
|
||||
isEditModalVisible: false,
|
||||
onResetPassword = value => {
|
||||
const password = {
|
||||
newPassword: value.password,
|
||||
};
|
||||
axios
|
||||
.post(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/admin/users/' +
|
||||
this.props.data.username +
|
||||
'/credentials',
|
||||
password,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isResetPasswordModalVisible: false,
|
||||
})
|
||||
};
|
||||
|
||||
compareToFirstPassword = (rule, value, callback) => {
|
||||
if (value && value !== this.props.form.getFieldValue('password')) {
|
||||
callback('New password doesn\'t match the confirmation.');
|
||||
});
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully reset the password',
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 {
|
||||
callback();
|
||||
notification.error({
|
||||
message: 'There was a problem',
|
||||
duration: 0,
|
||||
description: 'Error occurred while trying to reset password.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.getRole();
|
||||
}
|
||||
|
||||
getRole = () => {
|
||||
let apiURL =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/roles?user-store=PRIMARY&limit=100';
|
||||
|
||||
axios
|
||||
.get(apiURL)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
const roles = [];
|
||||
for (let i = 0; i < res.data.data.roles.length; i++) {
|
||||
roles.push(
|
||||
<Option key={res.data.data.roles[i]}>
|
||||
{res.data.data.roles[i]}
|
||||
</Option>,
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
roles: 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.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onConfirmDeleteUser = () => {
|
||||
axios
|
||||
.delete(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/users/' +
|
||||
this.props.data.username,
|
||||
{ headers: { 'Content-Type': 'application/json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully deleted the user.',
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 user.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
fetchRoles = username => {
|
||||
let apiUrl =
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/users/' +
|
||||
username +
|
||||
'/roles';
|
||||
|
||||
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.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleEditOk = e => {
|
||||
this.props.form.validateFields(
|
||||
[
|
||||
'userStoreDomain',
|
||||
'userName',
|
||||
'firstName',
|
||||
'lastName',
|
||||
'email',
|
||||
'userRoles',
|
||||
],
|
||||
(err, values) => {
|
||||
if (!err) {
|
||||
this.onUpdateUser(values);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
onUpdateUser = value => {
|
||||
const userData = {
|
||||
username: value.userStoreDomain + '/' + value.userName,
|
||||
firstname: value.firstName,
|
||||
lastname: value.lastName,
|
||||
emailAddress: value.email,
|
||||
roles: value.userRoles,
|
||||
};
|
||||
axios
|
||||
.put(
|
||||
window.location.origin +
|
||||
this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
'/users/' +
|
||||
this.props.data.username,
|
||||
userData,
|
||||
{ headers: { 'Content-Type': 'application-json' } },
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isEditModalVisible: false,
|
||||
});
|
||||
notification.success({
|
||||
message: 'Done',
|
||||
duration: 4,
|
||||
description: 'Successfully updated the user.',
|
||||
});
|
||||
}
|
||||
})
|
||||
.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 user.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onSavePassword = () => {
|
||||
this.props.form.validateFields((['password', 'confirmPassword']),(err, values) => {
|
||||
if (!err) {
|
||||
this.onResetPassword(values);
|
||||
}
|
||||
});
|
||||
};
|
||||
render() {
|
||||
const isAdminUser = this.props.data.username === 'admin';
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: isAdminUser ? 'none' : 'inline' }}>
|
||||
<Tooltip placement="top" title={'Edit User'}>
|
||||
<a>
|
||||
<Icon type="edit" onClick={this.openEditModal} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="top" title={'Reset Password'}>
|
||||
<a>
|
||||
<Icon type="key" onClick={this.openPasswordResetModal} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={'Remove User'}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={'Are you sure?'}
|
||||
onConfirm={this.onConfirmDeleteUser}
|
||||
okText="Ok"
|
||||
cancelText="Cancel"
|
||||
>
|
||||
<a>
|
||||
<Text type="danger">
|
||||
<Icon type="delete" />
|
||||
</Text>
|
||||
</a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
onResetPassword = (value) =>{
|
||||
const password = {
|
||||
newPassword : value.password,
|
||||
};
|
||||
axios.post(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/admin/users/"+this.props.data.username+"/credentials",
|
||||
password,
|
||||
{headers: {'Content-Type' : 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isResetPasswordModalVisible: false,
|
||||
});
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully reset the password",
|
||||
});
|
||||
}
|
||||
}).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 reset password.",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.getRole();
|
||||
}
|
||||
|
||||
getRole = () => {
|
||||
let apiURL = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt + "/roles?user-store=PRIMARY&limit=100";
|
||||
|
||||
axios.get(apiURL).then(res => {
|
||||
if (res.status === 200) {
|
||||
const roles = [];
|
||||
for(let i=0; i<res.data.data.roles.length ; i++){
|
||||
roles.push(<Option key={res.data.data.roles[i]}>{res.data.data.roles[i]}</Option>);
|
||||
}
|
||||
this.setState({
|
||||
roles : 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.",
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
onConfirmDeleteUser = () => {
|
||||
axios.delete(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/users/" + this.props.data.username,
|
||||
{headers: {'Content-Type': 'application/json'}}
|
||||
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully deleted the user.",
|
||||
});
|
||||
}
|
||||
}).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 user.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
fetchRoles = (username) => {
|
||||
let apiUrl = window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/users/" + username + "/roles";
|
||||
|
||||
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.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleEditOk = e =>{
|
||||
this.props.form.validateFields((['userStoreDomain', 'userName', 'firstName', 'lastName' , 'email', 'userRoles']),(err, values) => {
|
||||
if (!err) {
|
||||
this.onUpdateUser(values);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onUpdateUser = (value) =>{
|
||||
const userData = {
|
||||
username : value.userStoreDomain +"/"+value.userName,
|
||||
firstname : value.firstName,
|
||||
lastname : value.lastName,
|
||||
emailAddress : value.email,
|
||||
roles : value.userRoles
|
||||
};
|
||||
axios.put(
|
||||
window.location.origin + this.config.serverConfig.invoker.uri +
|
||||
this.config.serverConfig.invoker.deviceMgt +
|
||||
"/users/"+ this.props.data.username,
|
||||
userData,
|
||||
{headers: {'Content-Type' : 'application-json'}}
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.props.fetchUsers();
|
||||
this.setState({
|
||||
isEditModalVisible: false,
|
||||
});
|
||||
notification["success"]({
|
||||
message: "Done",
|
||||
duration: 4,
|
||||
description:
|
||||
"Successfully updated the user.",
|
||||
});
|
||||
}
|
||||
}).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 user.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const isAdminUser = this.props.data.username ==="admin";
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<div style={{display:isAdminUser ? "none" : "inline"}}>
|
||||
<Tooltip placement="top" title={"Edit User"}>
|
||||
<a><Icon type="edit" onClick={this.openEditModal}/></a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="top" title={"Reset Password"}>
|
||||
<a><Icon type="key" onClick={this.openPasswordResetModal}/></a>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Tooltip placement="bottom" title={"Remove User"}>
|
||||
<Popconfirm
|
||||
placement="top"
|
||||
title={"Are you sure?"}
|
||||
onConfirm={this.onConfirmDeleteUser}
|
||||
okText="Ok"
|
||||
cancelText="Cancel">
|
||||
<a><Text type="danger"><Icon type="delete"/></Text></a>
|
||||
</Popconfirm>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Modal
|
||||
title="Reset Password"
|
||||
width="40%"
|
||||
visible={this.state.isResetPasswordModalVisible}
|
||||
onCancel={this.onCancelHandler}
|
||||
onOk={this.onSavePassword}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onSavePassword} >
|
||||
Save
|
||||
</Button>,
|
||||
]}>
|
||||
<div style={{alignItems:"center"}}>
|
||||
<Form
|
||||
labelCol={{ span: 6 }}
|
||||
wrapperCol={{ span: 17 }}>
|
||||
<Form.Item label="New Password" style={{display:"block"}}>
|
||||
{getFieldDecorator(
|
||||
'password',
|
||||
{
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input.Password/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Retype New Password" style={{display:"block"}}>
|
||||
{getFieldDecorator(
|
||||
'confirmPassword',
|
||||
{
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
{
|
||||
validator: this.compareToFirstPassword,
|
||||
},
|
||||
],
|
||||
})(<Input.Password/>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Modal
|
||||
title="EDIT USER"
|
||||
width="40%"
|
||||
visible={this.state.isEditModalVisible}
|
||||
onOk={this.handleEditOk}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleEditOk}>
|
||||
Update
|
||||
</Button>,
|
||||
]}>
|
||||
<div style={{alignItems:"center"}}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form
|
||||
labelCol={{ span: 5 }}
|
||||
wrapperCol={{ span: 18 }}>
|
||||
<Form.Item label="User Store Domain" style={{display:"block"}}>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue : 'PRIMARY'
|
||||
})(
|
||||
<Select disabled={true}>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('userName', {
|
||||
initialValue: this.props.data.username,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required. Username should be at least 3 characters long with no white spaces.',
|
||||
},
|
||||
],
|
||||
})(<Input disabled={true}/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="First Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('firstName', {
|
||||
initialValue: this.props.data.firstname,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Last Name" style={{display:"block"}}>
|
||||
{getFieldDecorator('lastName', {
|
||||
initialValue: this.props.data.lastname,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Email Address" style={{display:"block"}}>
|
||||
{getFieldDecorator('email', {
|
||||
initialValue: this.props.data.emailAddress,
|
||||
rules: [
|
||||
{
|
||||
type: 'email',
|
||||
message: 'Invalid Email Address',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input/>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Roles" style={{display:"block"}}>
|
||||
{getFieldDecorator('userRoles', {
|
||||
initialValue: this.state.rolesData,
|
||||
})(<Select
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}>
|
||||
{this.state.roles}
|
||||
</Select>)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="Reset Password"
|
||||
width="40%"
|
||||
visible={this.state.isResetPasswordModalVisible}
|
||||
onCancel={this.onCancelHandler}
|
||||
onOk={this.onSavePassword}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.onSavePassword}>
|
||||
Save
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<Form labelCol={{ span: 6 }} wrapperCol={{ span: 17 }}>
|
||||
<Form.Item label="New Password" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('password', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input.Password />)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Retype New Password"
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator('confirmPassword', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
{
|
||||
validator: this.compareToFirstPassword,
|
||||
},
|
||||
],
|
||||
})(<Input.Password />)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Modal
|
||||
title="EDIT USER"
|
||||
width="40%"
|
||||
visible={this.state.isEditModalVisible}
|
||||
onOk={this.handleEditOk}
|
||||
onCancel={this.onCancelHandler}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={this.onCancelHandler}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleEditOk}>
|
||||
Update
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div style={{ alignItems: 'center' }}>
|
||||
<p>Create new user on IoT Server.</p>
|
||||
<Form labelCol={{ span: 5 }} wrapperCol={{ span: 18 }}>
|
||||
<Form.Item
|
||||
label="User Store Domain"
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
{getFieldDecorator('userStoreDomain', {
|
||||
initialValue: 'PRIMARY',
|
||||
})(
|
||||
<Select disabled={true}>
|
||||
<Option key="PRIMARY">PRIMARY</Option>
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('userName', {
|
||||
initialValue: this.props.data.username,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message:
|
||||
'This field is required. Username should be at least 3 characters long with no white spaces.',
|
||||
},
|
||||
],
|
||||
})(<Input disabled={true} />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="First Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('firstName', {
|
||||
initialValue: this.props.data.firstname,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Last Name" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('lastName', {
|
||||
initialValue: this.props.data.lastname,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Email Address" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('email', {
|
||||
initialValue: this.props.data.emailAddress,
|
||||
rules: [
|
||||
{
|
||||
type: 'email',
|
||||
message: 'Invalid Email Address',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
message: 'This field is required',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="User Roles" style={{ display: 'block' }}>
|
||||
{getFieldDecorator('userRoles', {
|
||||
initialValue: this.state.rolesData,
|
||||
})(
|
||||
<Select mode="multiple" style={{ width: '100%' }}>
|
||||
{this.state.roles}
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Form.create({name: 'user-actions'})(UserActions));
|
||||
export default withConfigContext(
|
||||
Form.create({ name: 'user-actions' })(UserActions),
|
||||
);
|
||||
|
||||
@ -16,233 +16,245 @@
|
||||
* 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 (
|
||||
<span style={{fontSize: 20, color: color, textAlign: "center"}}>
|
||||
<Icon type={icon} theme={theme}/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
// todo add filtering options
|
||||
return (
|
||||
<span style={{ fontSize: 20, color: color, textAlign: 'center' }}>
|
||||
<Icon type={icon} theme={theme} />
|
||||
</span>
|
||||
);
|
||||
},
|
||||
{
|
||||
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',
|
||||
width: 100,
|
||||
render: enrolmentInfo => enrolmentInfo.ownership,
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
dataIndex: 'enrolmentInfo',
|
||||
width: 100,
|
||||
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 <Tag color={color}>{status}</Tag>;
|
||||
},
|
||||
{
|
||||
title: 'Ownership',
|
||||
dataIndex: 'enrolmentInfo',
|
||||
key: 'ownership',
|
||||
width: 100,
|
||||
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 (
|
||||
<Tooltip title={new Date(dateOfLastUpdate).toString()}>
|
||||
{timeAgoString}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
dataIndex: 'enrolmentInfo',
|
||||
width: 100,
|
||||
key: 'status',
|
||||
render: (enrolmentInfo) => {
|
||||
const status = enrolmentInfo.status.toLowerCase();
|
||||
let color = "#f9ca24";
|
||||
switch (status) {
|
||||
case "active":
|
||||
color = "#badc58";
|
||||
break;
|
||||
case "created":
|
||||
color = "#6ab04c";
|
||||
break;
|
||||
case "removed":
|
||||
color = "#ff7979";
|
||||
break;
|
||||
case "inactive":
|
||||
color = "#f9ca24";
|
||||
break;
|
||||
case "blocked":
|
||||
color = "#636e72";
|
||||
break;
|
||||
}
|
||||
return <Tag color={color}>{status}</Tag>;
|
||||
}
|
||||
// todo add filtering options
|
||||
},
|
||||
{
|
||||
title: 'Last Updated',
|
||||
dataIndex: 'enrolmentInfo',
|
||||
key: 'dateOfLastUpdate',
|
||||
render: (data) => {
|
||||
const {dateOfLastUpdate} = data;
|
||||
const timeAgoString = getTimeAgo(dateOfLastUpdate);
|
||||
return <Tooltip title={new Date(dateOfLastUpdate).toString()}>{timeAgoString}</Tooltip>;
|
||||
}
|
||||
// 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 UsersDevices 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: [],
|
||||
};
|
||||
}
|
||||
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
// Rerender component when parameters change
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (prevProps.user !== this.props.user) {
|
||||
this.fetch();
|
||||
}
|
||||
}
|
||||
|
||||
// fetch data from api
|
||||
fetch = (params = {}) => {
|
||||
const config = this.props.context;
|
||||
this.setState({ loading: true });
|
||||
// get current page
|
||||
const currentPage = params.hasOwnProperty('page') ? params.page : 1;
|
||||
|
||||
const extraParams = {
|
||||
offset: 10 * (currentPage - 1), // calculate the offset
|
||||
limit: 10,
|
||||
user: this.props.user,
|
||||
requireDeviceInfo: true,
|
||||
};
|
||||
|
||||
const encodedExtraParams = Object.keys(extraParams)
|
||||
.map(key => key + '=' + extraParams[key])
|
||||
.join('&');
|
||||
|
||||
// send request to the invoker
|
||||
axios
|
||||
.get(
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/devices?' +
|
||||
encodedExtraParams,
|
||||
)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
const pagination = { ...this.state.pagination };
|
||||
this.setState({
|
||||
loading: false,
|
||||
selectedRows: []
|
||||
};
|
||||
}
|
||||
|
||||
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.user !== this.props.user){
|
||||
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 load devices.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//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.setState({ loading: false });
|
||||
});
|
||||
};
|
||||
|
||||
const extraParams = {
|
||||
offset: 10 * (currentPage - 1), //calculate the offset
|
||||
limit: 10,
|
||||
user: this.props.user,
|
||||
requireDeviceInfo: 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,
|
||||
});
|
||||
};
|
||||
|
||||
const encodedExtraParams = Object.keys(extraParams)
|
||||
.map(key => key + '=' + extraParams[key]).join('&');
|
||||
|
||||
//send request to the invoker
|
||||
axios.get(
|
||||
window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/devices?" + encodedExtraParams,
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
const pagination = {...this.state.pagination};
|
||||
this.setState({
|
||||
loading: false,
|
||||
data: res.data.data.devices,
|
||||
pagination
|
||||
});
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
||||
//todo display a popop with error
|
||||
message.error('You are not logged in');
|
||||
window.location.href = window.location.origin + '/entgra/login';
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: "There was a problem",
|
||||
duration: 0,
|
||||
description:
|
||||
"Error occurred while trying to load devices.",
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({loading: false});
|
||||
});
|
||||
};
|
||||
|
||||
handleTableChange = (pagination, filters, sorter) => {
|
||||
const pager = {...this.state.pagination};
|
||||
pager.current = pagination.current;
|
||||
this.setState({
|
||||
pagination: pager,
|
||||
});
|
||||
this.fetch({
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
const {data, pagination, loading, selectedRows} = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => (record.deviceIdentifier + record.enrolmentInfo.owner + record.enrolmentInfo.ownership)}
|
||||
dataSource={data}
|
||||
showHeader={false}
|
||||
size="small"
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: "small",
|
||||
// position: "top",
|
||||
showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} devices`
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data, pagination, loading } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record =>
|
||||
record.deviceIdentifier +
|
||||
record.enrolmentInfo.owner +
|
||||
record.enrolmentInfo.ownership
|
||||
}
|
||||
dataSource={data}
|
||||
showHeader={false}
|
||||
size="small"
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: 'small',
|
||||
// position: "top",
|
||||
showTotal: (total, range) =>
|
||||
`showing ${range[0]}-${range[1]} of ${total} devices`,
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(UsersDevices);
|
||||
export default withConfigContext(UsersDevices);
|
||||
|
||||
@ -16,305 +16,322 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import axios from "axios";
|
||||
import {Button, Collapse, Icon, List, message, Modal, notification, Table, Tabs, Typography} from "antd";
|
||||
import TimeAgo from 'javascript-time-ago'
|
||||
import React from 'react';
|
||||
import axios from 'axios';
|
||||
import { Button, List, message, Modal, 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 UsersDevices from "./UsersDevices";
|
||||
import AddUser from "./AddUser";
|
||||
import UserActions from "./UserActions";
|
||||
import Filter from "../Utils/Filter/Filter";
|
||||
import en from 'javascript-time-ago/locale/en';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
import UsersDevices from './UsersDevices';
|
||||
import AddUser from './AddUser';
|
||||
import UserActions from './UserActions';
|
||||
import Filter from '../Utils/Filter/Filter';
|
||||
const ButtonGroup = Button.Group;
|
||||
const {Text} = Typography;
|
||||
|
||||
let config = null;
|
||||
let apiUrl;
|
||||
|
||||
const searchFields = [
|
||||
{
|
||||
name: 'username',
|
||||
placeholder: 'Username'
|
||||
},
|
||||
{
|
||||
name: 'firstName',
|
||||
placeholder: 'First Name'
|
||||
},
|
||||
{
|
||||
name: 'lastName',
|
||||
placeholder: 'Last Name'
|
||||
},
|
||||
{
|
||||
name: 'emailAddress',
|
||||
placeholder: 'Email Address'
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
placeholder: 'Username',
|
||||
},
|
||||
{
|
||||
name: 'firstName',
|
||||
placeholder: 'First Name',
|
||||
},
|
||||
{
|
||||
name: 'lastName',
|
||||
placeholder: 'Last Name',
|
||||
},
|
||||
{
|
||||
name: 'emailAddress',
|
||||
placeholder: 'Email Address',
|
||||
},
|
||||
];
|
||||
|
||||
class UsersTable 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: [],
|
||||
rolesModalVisible: false,
|
||||
devicesModalVisible: false,
|
||||
rolesData: [],
|
||||
user: '',
|
||||
};
|
||||
}
|
||||
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchUsers();
|
||||
}
|
||||
|
||||
// fetch data from api
|
||||
fetchUsers = (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 +
|
||||
'/users/search?' +
|
||||
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: [],
|
||||
rolesModalVisible: false,
|
||||
devicesModalVisible: false,
|
||||
rolesData: [],
|
||||
user:''
|
||||
};
|
||||
}
|
||||
data: res.data.data.users,
|
||||
pagination,
|
||||
});
|
||||
|
||||
rowSelection = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.setState({
|
||||
selectedRows: selectedRows
|
||||
})
|
||||
console.log(res.data.data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 401) {
|
||||
// todo display a popop with error
|
||||
message.error('You are not logged in');
|
||||
window.location.href = window.location.origin + '/entgra/login';
|
||||
} else {
|
||||
notification.error({
|
||||
message: 'There was a problem',
|
||||
duration: 0,
|
||||
description: 'Error occurred while trying to load users.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchUsers();
|
||||
}
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
};
|
||||
|
||||
//fetch data from api
|
||||
fetchUsers = (params = {}, filters = {}) => {
|
||||
const config = this.props.context;
|
||||
this.setState({loading: true});
|
||||
fetchRoles = username => {
|
||||
const config = this.props.context;
|
||||
|
||||
// get current page
|
||||
const currentPage = (params.hasOwnProperty("page")) ? params.page : 1;
|
||||
this.setState({
|
||||
rolesModalVisible: true,
|
||||
user: username,
|
||||
});
|
||||
|
||||
const extraParams = {
|
||||
offset: 10 * (currentPage - 1), //calculate the offset
|
||||
limit: 10,
|
||||
...filters
|
||||
};
|
||||
apiUrl =
|
||||
window.location.origin +
|
||||
config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
'/users/' +
|
||||
username +
|
||||
'/roles';
|
||||
|
||||
const encodedExtraParams = Object.keys(extraParams)
|
||||
.map(key => key + '=' + extraParams[key]).join('&');
|
||||
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.',
|
||||
});
|
||||
}
|
||||
|
||||
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/users/search?" + encodedExtraParams;
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
};
|
||||
|
||||
//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.users,
|
||||
pagination,
|
||||
});
|
||||
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,
|
||||
});
|
||||
};
|
||||
|
||||
console.log(res.data.data)
|
||||
}
|
||||
handleOk = e => {
|
||||
this.setState({
|
||||
rolesModalVisible: false,
|
||||
devicesModalVisible: 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 users.",
|
||||
});
|
||||
}
|
||||
handleCancel = e => {
|
||||
this.setState({
|
||||
rolesModalVisible: false,
|
||||
devicesModalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
this.setState({loading: false});
|
||||
});
|
||||
};
|
||||
openDeviceListModal = e => {
|
||||
this.setState({
|
||||
devicesModalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
fetchRoles = (username) => {
|
||||
const config = this.props.context;
|
||||
|
||||
this.setState({
|
||||
rolesModalVisible: true,
|
||||
user: username
|
||||
});
|
||||
|
||||
apiUrl = window.location.origin + config.serverConfig.invoker.uri +
|
||||
config.serverConfig.invoker.deviceMgt +
|
||||
"/users/" + username + "/roles";
|
||||
|
||||
axios.get(apiUrl).then(res => {
|
||||
if (res.status === 200) {
|
||||
this.setState({
|
||||
rolesData: res.data.data.roles,
|
||||
});
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
||||
//todo display a popop with error
|
||||
message.error('You are not logged in');
|
||||
window.location.href = window.location.origin + '/entgra/login';
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: "There was a problem",
|
||||
duration: 0,
|
||||
description:"Error occurred while trying to load roles.",
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({loading: false});
|
||||
});
|
||||
};
|
||||
|
||||
handleTableChange = (pagination, filters, sorter) => {
|
||||
const pager = {...this.state.pagination};
|
||||
pager.current = pagination.current;
|
||||
this.setState({
|
||||
pagination: pager,
|
||||
});
|
||||
this.fetch({
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters,
|
||||
});
|
||||
};
|
||||
|
||||
handleOk = e => {
|
||||
this.setState({
|
||||
rolesModalVisible: false,
|
||||
devicesModalVisible: false
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = e => {
|
||||
this.setState({
|
||||
rolesModalVisible: false,
|
||||
devicesModalVisible: false
|
||||
});
|
||||
};
|
||||
|
||||
openDeviceListModal = e =>{
|
||||
this.setState({
|
||||
devicesModalVisible: true,
|
||||
})
|
||||
};
|
||||
|
||||
render() {
|
||||
const {data, pagination, loading, selectedRows} = this.state;
|
||||
const { Panel } = Collapse;
|
||||
const { TabPane } = Tabs;
|
||||
const columns = [
|
||||
{
|
||||
title: 'User Name',
|
||||
dataIndex: 'username',
|
||||
key: "username",
|
||||
},
|
||||
{
|
||||
title: 'First Name',
|
||||
dataIndex: 'firstname',
|
||||
key: 'firstname',
|
||||
},
|
||||
{
|
||||
title: 'Last Name',
|
||||
dataIndex: 'lastname',
|
||||
key: 'lastname',
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
dataIndex: 'emailAddress',
|
||||
key: 'emailAddress',
|
||||
},
|
||||
{
|
||||
title: 'View',
|
||||
dataIndex: 'username',
|
||||
key: 'roles',
|
||||
render: (username) =>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
type="primary"
|
||||
size={"small"}
|
||||
icon="book"
|
||||
onClick={() => this.fetchRoles(username)}>Roles</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
size={"small"}
|
||||
icon="desktop"
|
||||
onClick={this.openDeviceListModal}>Devices</Button>
|
||||
</ButtonGroup>
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: 'id',
|
||||
key: 'action',
|
||||
render: (id, row) => (
|
||||
<span>
|
||||
<UserActions data={row} fetchUsers={this.fetchUsers}/>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
];
|
||||
return (
|
||||
render() {
|
||||
const { data, pagination, loading } = this.state;
|
||||
const columns = [
|
||||
{
|
||||
title: 'User Name',
|
||||
dataIndex: 'username',
|
||||
key: 'username',
|
||||
},
|
||||
{
|
||||
title: 'First Name',
|
||||
dataIndex: 'firstname',
|
||||
key: 'firstname',
|
||||
},
|
||||
{
|
||||
title: 'Last Name',
|
||||
dataIndex: 'lastname',
|
||||
key: 'lastname',
|
||||
},
|
||||
{
|
||||
title: 'Email',
|
||||
dataIndex: 'emailAddress',
|
||||
key: 'emailAddress',
|
||||
},
|
||||
{
|
||||
title: 'View',
|
||||
dataIndex: 'username',
|
||||
key: 'roles',
|
||||
render: username => (
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
type="primary"
|
||||
size={'small'}
|
||||
icon="book"
|
||||
onClick={() => this.fetchRoles(username)}
|
||||
>
|
||||
Roles
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
size={'small'}
|
||||
icon="desktop"
|
||||
onClick={this.openDeviceListModal}
|
||||
>
|
||||
Devices
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
dataIndex: 'id',
|
||||
key: 'action',
|
||||
render: (id, row) => (
|
||||
<span>
|
||||
<UserActions data={row} fetchUsers={this.fetchUsers} />
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
return (
|
||||
<div>
|
||||
<div style={{ background: '#f0f2f5' }}>
|
||||
<AddUser fetchUsers={this.fetchUsers} />
|
||||
</div>
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<Filter fields={searchFields} callback={this.fetchUsers} />
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => record.username}
|
||||
dataSource={data}
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: 'small',
|
||||
// position: "top",
|
||||
showTotal: (total, range) =>
|
||||
`showing ${range[0]}-${range[1]} of ${total} groups`,
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ROLES"
|
||||
width="900px"
|
||||
visible={this.state.rolesModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
>
|
||||
<div>
|
||||
<div style={{background: '#f0f2f5'}}>
|
||||
<AddUser fetchUsers={this.fetchUsers}/>
|
||||
</div>
|
||||
<div style={{textAlign: 'right'}}>
|
||||
<Filter fields={searchFields} callback={this.fetchUsers}/>
|
||||
</div>
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey={record => (record.username)}
|
||||
dataSource={data}
|
||||
pagination={{
|
||||
...pagination,
|
||||
size: "small",
|
||||
// position: "top",
|
||||
showTotal: (total, range) => `showing ${range[0]}-${range[1]} of ${total} groups`
|
||||
// showQuickJumper: true
|
||||
}}
|
||||
loading={loading}
|
||||
onChange={this.handleTableChange}
|
||||
rowSelection={this.rowSelection}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Modal
|
||||
title="ROLES"
|
||||
width="900px"
|
||||
visible={this.state.rolesModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel} >
|
||||
<div>
|
||||
<List
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={this.state.rolesData}
|
||||
renderItem={item => <List.Item>{item}</List.Item>}/>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Modal
|
||||
title="DEVICES"
|
||||
width="900px"
|
||||
visible={this.state.devicesModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}>
|
||||
<div>
|
||||
<UsersDevices user={this.state.user}/>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
<List
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={this.state.rolesData}
|
||||
renderItem={item => <List.Item>{item}</List.Item>}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Modal
|
||||
title="DEVICES"
|
||||
width="900px"
|
||||
visible={this.state.devicesModalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
>
|
||||
<div>
|
||||
<UsersDevices user={this.state.user} />
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(UsersTable);
|
||||
|
||||
@ -1,41 +1,38 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
import {Form, Icon, Input, Button} from 'antd';
|
||||
|
||||
const hasErrors = (fieldsError) => {
|
||||
return Object.keys(fieldsError).some(field => fieldsError[field]);
|
||||
};
|
||||
import { Form, Input, Button } from 'antd';
|
||||
|
||||
class HorizontalLoginForm extends React.Component {
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
Object.keys(values).forEach(key => values[key] === undefined && delete values[key]);
|
||||
this.props.callback({},values);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
|
||||
|
||||
return (
|
||||
<Form layout="inline" onSubmit={this.handleSubmit}>
|
||||
{this.props.fields.map((field) => (
|
||||
<Form.Item key={field.name}>
|
||||
{getFieldDecorator(field.name)(
|
||||
<Input placeholder={field.placeholder}/>,
|
||||
)}
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button htmlType='submit' shape="circle" icon="search" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
Object.keys(values).forEach(
|
||||
key => values[key] === undefined && delete values[key],
|
||||
);
|
||||
}
|
||||
this.props.callback({}, values);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
return (
|
||||
<Form layout="inline" onSubmit={this.handleSubmit}>
|
||||
{this.props.fields.map(field => (
|
||||
<Form.Item key={field.name}>
|
||||
{getFieldDecorator(field.name)(
|
||||
<Input placeholder={field.placeholder} />,
|
||||
)}
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button htmlType="submit" shape="circle" icon="search" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Form.create({name: 'horizontal_login'})(HorizontalLoginForm);
|
||||
export default Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);
|
||||
|
||||
@ -16,19 +16,19 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
|
||||
const ConfigContext = React.createContext();
|
||||
|
||||
export const withConfigContext = Component => {
|
||||
return props => (
|
||||
<ConfigContext.Consumer>
|
||||
{context => {
|
||||
return <Component {...props} context={context}/>;
|
||||
}}
|
||||
</ConfigContext.Consumer>
|
||||
);
|
||||
// eslint-disable-next-line react/display-name
|
||||
return props => (
|
||||
<ConfigContext.Consumer>
|
||||
{context => {
|
||||
return <Component {...props} context={context} />;
|
||||
}}
|
||||
</ConfigContext.Consumer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfigContext;
|
||||
|
||||
|
||||
@ -19,119 +19,117 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
import App from "./App";
|
||||
import Login from "./pages/Login";
|
||||
import Dashboard from "./pages/Dashboard/Dashboard";
|
||||
import App from './App';
|
||||
import Login from './pages/Login';
|
||||
import Dashboard from './pages/Dashboard/Dashboard';
|
||||
import './index.css';
|
||||
import Devices from "./pages/Dashboard/Devices/Devices";
|
||||
import Reports from "./pages/Dashboard/Reports/Reports";
|
||||
import Geo from "./pages/Dashboard/Geo/Geo";
|
||||
import Groups from "./pages/Dashboard/Groups/Groups";
|
||||
import Users from "./pages/Dashboard/Users/Users";
|
||||
import Policies from "./pages/Dashboard/Policies/Policies";
|
||||
import Roles from "./pages/Dashboard/Roles/Roles";
|
||||
import DeviceTypes from "./pages/Dashboard/DeviceTypes/DeviceTypes";
|
||||
import DeviceEnroll from "./pages/Dashboard/Devices/DeviceEnroll";
|
||||
import AddNewPolicy from "./pages/Dashboard/Policies/AddNewPolicy";
|
||||
import Certificates from "./pages/Dashboard/Configurations/Certificates/Certificates";
|
||||
import ReportDurationItemList from "./pages/Dashboard/Reports/ReportDurationItemList";
|
||||
import EnrollmentsVsUnenrollmentsReport from "./components/Reports/Templates/EnrollmentsVsUnenrollmentsReport";
|
||||
import EnrollmentTypeReport from "./components/Reports/Templates/EnrollmentTypeReport";
|
||||
import Devices from './pages/Dashboard/Devices/Devices';
|
||||
import Reports from './pages/Dashboard/Reports/Reports';
|
||||
import Geo from './pages/Dashboard/Geo/Geo';
|
||||
import Groups from './pages/Dashboard/Groups/Groups';
|
||||
import Users from './pages/Dashboard/Users/Users';
|
||||
import Policies from './pages/Dashboard/Policies/Policies';
|
||||
import Roles from './pages/Dashboard/Roles/Roles';
|
||||
import DeviceTypes from './pages/Dashboard/DeviceTypes/DeviceTypes';
|
||||
import DeviceEnroll from './pages/Dashboard/Devices/DeviceEnroll';
|
||||
import AddNewPolicy from './pages/Dashboard/Policies/AddNewPolicy';
|
||||
import Certificates from './pages/Dashboard/Configurations/Certificates/Certificates';
|
||||
import ReportDurationItemList from './pages/Dashboard/Reports/ReportDurationItemList';
|
||||
import EnrollmentsVsUnenrollmentsReport from './components/Reports/Templates/EnrollmentsVsUnenrollmentsReport';
|
||||
import EnrollmentTypeReport from './components/Reports/Templates/EnrollmentTypeReport';
|
||||
import DeviceStatusReport from './components/Reports/Templates/DeviceStatusReport';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/entgra/login',
|
||||
{
|
||||
path: '/entgra/login',
|
||||
exact: true,
|
||||
component: Login,
|
||||
},
|
||||
{
|
||||
path: '/entgra',
|
||||
exact: false,
|
||||
component: Dashboard,
|
||||
routes: [
|
||||
{
|
||||
path: '/entgra/devices',
|
||||
component: Devices,
|
||||
exact: true,
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
path: '/entgra',
|
||||
exact: false,
|
||||
component: Dashboard,
|
||||
routes: [
|
||||
{
|
||||
path: '/entgra/devices',
|
||||
component: Devices,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/devices/enroll',
|
||||
component: DeviceEnroll,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/geo',
|
||||
component: Geo,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/reports',
|
||||
component: Reports,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/groups',
|
||||
component: Groups,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/users',
|
||||
component: Users,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/policies',
|
||||
component: Policies,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/policy/add',
|
||||
component: AddNewPolicy,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/roles',
|
||||
component: Roles,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/devicetypes',
|
||||
component: DeviceTypes,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/certificates',
|
||||
component: Certificates,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/reportList',
|
||||
component: ReportDurationItemList,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/enrollmentsvsunenrollments',
|
||||
component: EnrollmentsVsUnenrollmentsReport,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/enrollmenttype',
|
||||
component: EnrollmentTypeReport,
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/entgra/devicestatus',
|
||||
component: DeviceStatusReport,
|
||||
exact: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/entgra/devices/enroll',
|
||||
component: DeviceEnroll,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/geo',
|
||||
component: Geo,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/reports',
|
||||
component: Reports,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/groups',
|
||||
component: Groups,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/users',
|
||||
component: Users,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/policies',
|
||||
component: Policies,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/policy/add',
|
||||
component: AddNewPolicy,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/roles',
|
||||
component: Roles,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/devicetypes',
|
||||
component: DeviceTypes,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/certificates',
|
||||
component: Certificates,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/reportList',
|
||||
component: ReportDurationItemList,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/enrollmentsvsunenrollments',
|
||||
component: EnrollmentsVsUnenrollmentsReport,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/enrollmenttype',
|
||||
component: EnrollmentTypeReport,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
path: '/entgra/devicestatus',
|
||||
component: DeviceStatusReport,
|
||||
exact: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
ReactDOM.render(
|
||||
<App routes={routes}/>,
|
||||
document.getElementById('root'));
|
||||
ReactDOM.render(<App routes={routes} />, document.getElementById('root'));
|
||||
|
||||
// If you want your app e and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
|
||||
@ -16,52 +16,48 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import DeviceTable from "../../../../components/Devices/DevicesTable";
|
||||
import CertificateTable from "../../../../components/Configurations/Certificates/CertificateTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import CertificateTable from '../../../../components/Configurations/Certificates/CertificateTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Certificates extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Configurations</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Certificates</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Certificates</h3>
|
||||
<Paragraph>Certificate configurations</Paragraph>
|
||||
</div>
|
||||
<div style={{backgroundColor: "#ffffff", borderRadius: 5}}>
|
||||
<CertificateTable/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Configurations</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Certificates</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Certificates</h3>
|
||||
<Paragraph>Certificate configurations</Paragraph>
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<CertificateTable />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Certificates;
|
||||
|
||||
@ -16,193 +16,197 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {Layout, Menu, Icon} from 'antd';
|
||||
import {Switch, Link} from "react-router-dom";
|
||||
import RouteWithSubRoutes from "../../components/RouteWithSubRoutes"
|
||||
import {Redirect} from 'react-router'
|
||||
import "./Dashboard.css";
|
||||
import {withConfigContext} from "../../context/ConfigContext";
|
||||
import Logout from "./Logout/Logout";
|
||||
import React from 'react';
|
||||
import { Layout, Menu, Icon } from 'antd';
|
||||
import { Switch, Link } from 'react-router-dom';
|
||||
import RouteWithSubRoutes from '../../components/RouteWithSubRoutes';
|
||||
import { Redirect } from 'react-router';
|
||||
import './Dashboard.css';
|
||||
import { withConfigContext } from '../../context/ConfigContext';
|
||||
import Logout from './Logout/Logout';
|
||||
|
||||
const {Header, Content, Footer, Sider} = Layout;
|
||||
const {SubMenu} = Menu;
|
||||
const { Header, Content, Footer } = Layout;
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
class Dashboard extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const mobileWidth = (window.innerWidth<=768 ? '0' : '80');
|
||||
const mobileWidth = window.innerWidth <= 768 ? '0' : '80';
|
||||
|
||||
this.state = {
|
||||
routes: props.routes,
|
||||
selectedKeys: [],
|
||||
deviceTypes: [],
|
||||
isNavBarCollapsed: false,
|
||||
mobileWidth
|
||||
};
|
||||
this.logo = this.props.context.theme.logo;
|
||||
this.config = this.props.context;
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
console.log(this.config)
|
||||
this.setState({
|
||||
isNavBarCollapsed: !this.state.isNavBarCollapsed,
|
||||
});
|
||||
this.state = {
|
||||
routes: props.routes,
|
||||
selectedKeys: [],
|
||||
deviceTypes: [],
|
||||
isNavBarCollapsed: false,
|
||||
mobileWidth,
|
||||
};
|
||||
this.logo = this.props.context.theme.logo;
|
||||
this.config = this.props.context;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Layout className="layout" >
|
||||
<Layout>
|
||||
<Header style={{background: '#fff', padding: 0}}>
|
||||
<div className="logo-image">
|
||||
<Link to="/entgra/devices"><img alt="logo" src={this.logo}/></Link>
|
||||
</div>
|
||||
toggle = () => {
|
||||
console.log(this.config);
|
||||
this.setState({
|
||||
isNavBarCollapsed: !this.state.isNavBarCollapsed,
|
||||
});
|
||||
};
|
||||
|
||||
<Menu
|
||||
theme="light"
|
||||
mode="horizontal"
|
||||
style={{
|
||||
lineHeight: '64px',
|
||||
marginRight: 110
|
||||
}}
|
||||
>
|
||||
<SubMenu
|
||||
key="devices"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="appstore"/>
|
||||
<span>Devices</span>
|
||||
</span>}
|
||||
>
|
||||
<Menu.Item key="devices">
|
||||
<Link to="/entgra/devices">
|
||||
<span>View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="deviceEnroll">
|
||||
<Link to="/entgra/devices/enroll">
|
||||
<span>Enroll</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu
|
||||
key="geo"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="environment"/>
|
||||
<span>Geo</span>
|
||||
</span>}
|
||||
>
|
||||
<Menu.Item key="singleDevice">
|
||||
<Link to="/entgra/geo">
|
||||
<span>Single Device View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="deviceGroup">
|
||||
<Link to="#">
|
||||
<span>Device Group View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="reports">
|
||||
<Link to="/entgra/reports">
|
||||
<Icon type="bar-chart"/>
|
||||
<span>Reports</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="groups">
|
||||
<Link to="/entgra/groups">
|
||||
<Icon type="deployment-unit"/>
|
||||
<span>Groups</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="users">
|
||||
<Link to="/entgra/users">
|
||||
<Icon type="user"/>
|
||||
<span>Users</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<SubMenu
|
||||
key="policies"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="audit"/>
|
||||
<span>Policies</span>
|
||||
</span>}
|
||||
>
|
||||
<Menu.Item key="policiesList">
|
||||
<Link to="/entgra/policies">
|
||||
<span>View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="addPolicy">
|
||||
<Link to="/entgra/policy/add">
|
||||
<span>Add New Policy</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="roles">
|
||||
<Link to="/entgra/roles">
|
||||
<Icon type="book"/>
|
||||
<span>Roles</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="devicetypes">
|
||||
<Link to="/entgra/devicetypes">
|
||||
<Icon type="desktop"/>
|
||||
<span>Device Types</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<SubMenu
|
||||
key="configurations"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="setting"/>
|
||||
<span>Configurations</span>
|
||||
</span>}
|
||||
>
|
||||
<Menu.Item key="certificates">
|
||||
<Link to="/entgra/certificates">
|
||||
<span>Certificates</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="trigger">
|
||||
</Menu.Item>
|
||||
<SubMenu className="profile"
|
||||
title={
|
||||
<span className="submenu-title-wrapper">
|
||||
<Icon type="user"/>
|
||||
{this.config.user}
|
||||
</span> }>
|
||||
<Logout/>
|
||||
</SubMenu>
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Layout className="layout">
|
||||
<Layout>
|
||||
<Header style={{ background: '#fff', padding: 0 }}>
|
||||
<div className="logo-image">
|
||||
<Link to="/entgra/devices">
|
||||
<img alt="logo" src={this.logo} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</Menu>
|
||||
</Header>
|
||||
<Menu
|
||||
theme="light"
|
||||
mode="horizontal"
|
||||
style={{
|
||||
lineHeight: '64px',
|
||||
marginRight: 110,
|
||||
}}
|
||||
>
|
||||
<SubMenu
|
||||
key="devices"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="appstore" />
|
||||
<span>Devices</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="devices">
|
||||
<Link to="/entgra/devices">
|
||||
<span>View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="deviceEnroll">
|
||||
<Link to="/entgra/devices/enroll">
|
||||
<span>Enroll</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<SubMenu
|
||||
key="geo"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="environment" />
|
||||
<span>Geo</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="singleDevice">
|
||||
<Link to="/entgra/geo">
|
||||
<span>Single Device View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="deviceGroup">
|
||||
<Link to="#">
|
||||
<span>Device Group View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="reports">
|
||||
<Link to="/entgra/reports">
|
||||
<Icon type="bar-chart" />
|
||||
<span>Reports</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="groups">
|
||||
<Link to="/entgra/groups">
|
||||
<Icon type="deployment-unit" />
|
||||
<span>Groups</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="users">
|
||||
<Link to="/entgra/users">
|
||||
<Icon type="user" />
|
||||
<span>Users</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<SubMenu
|
||||
key="policies"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="audit" />
|
||||
<span>Policies</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="policiesList">
|
||||
<Link to="/entgra/policies">
|
||||
<span>View</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="addPolicy">
|
||||
<Link to="/entgra/policy/add">
|
||||
<span>Add New Policy</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="roles">
|
||||
<Link to="/entgra/roles">
|
||||
<Icon type="book" />
|
||||
<span>Roles</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="devicetypes">
|
||||
<Link to="/entgra/devicetypes">
|
||||
<Icon type="desktop" />
|
||||
<span>Device Types</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<SubMenu
|
||||
key="configurations"
|
||||
title={
|
||||
<span>
|
||||
<Icon type="setting" />
|
||||
<span>Configurations</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item key="certificates">
|
||||
<Link to="/entgra/certificates">
|
||||
<span>Certificates</span>
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
<Menu.Item key="trigger"></Menu.Item>
|
||||
<SubMenu
|
||||
className="profile"
|
||||
title={
|
||||
<span className="submenu-title-wrapper">
|
||||
<Icon type="user" />
|
||||
{this.config.user}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Logout />
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</Header>
|
||||
|
||||
<Content style={{marginTop: 10}}>
|
||||
<Switch>
|
||||
<Redirect exact from="/entgra" to="/entgra/devices"/>
|
||||
{this.state.routes.map((route) => (
|
||||
<RouteWithSubRoutes key={route.path} {...route} />
|
||||
))}
|
||||
</Switch>
|
||||
</Content>
|
||||
<Content style={{ marginTop: 10 }}>
|
||||
<Switch>
|
||||
<Redirect exact from="/entgra" to="/entgra/devices" />
|
||||
{this.state.routes.map(route => (
|
||||
<RouteWithSubRoutes key={route.path} {...route} />
|
||||
))}
|
||||
</Switch>
|
||||
</Content>
|
||||
|
||||
<Footer style={{textAlign: 'center'}}>
|
||||
©2019 entgra.io
|
||||
</Footer>
|
||||
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<Footer style={{ textAlign: 'center' }}>©2019 entgra.io</Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Dashboard);
|
||||
|
||||
@ -16,50 +16,47 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import DeviceTypesTable from "../../../components/DeviceTypes/DeviceTypesTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import DeviceTypesTable from '../../../components/DeviceTypes/DeviceTypesTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class DeviceTypes extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Device Types</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Device Types</h3>
|
||||
<Paragraph>All device types for device management.</Paragraph>
|
||||
</div>
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<DeviceTypesTable/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Device Types</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Device Types</h3>
|
||||
<Paragraph>All device types for device management.</Paragraph>
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<DeviceTypesTable />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DeviceTypes;
|
||||
|
||||
@ -1,50 +1,47 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
Button, Select
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import AddDevice from "../../../components/Devices/AddDevice";
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import AddDevice from '../../../components/Devices/AddDevice';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class DeviceEnroll extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item><Link to="/entgra/devices">Devices</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Enroll Device</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Devices</h3>
|
||||
<Paragraph>All enrolled devices</Paragraph>
|
||||
</div>
|
||||
<div style={{borderRadius: 5}}>
|
||||
<AddDevice/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices">Devices</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Enroll Device</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Devices</h3>
|
||||
<Paragraph>All enrolled devices</Paragraph>
|
||||
</div>
|
||||
<div style={{ borderRadius: 5 }}>
|
||||
<AddDevice />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DeviceEnroll;
|
||||
export default DeviceEnroll;
|
||||
|
||||
@ -16,51 +16,47 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
Button, Select
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import DeviceTable from "../../../components/Devices/DevicesTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import DeviceTable from '../../../components/Devices/DevicesTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Devices extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Devices</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Devices</h3>
|
||||
<Paragraph>All enrolled devices</Paragraph>
|
||||
</div>
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<DeviceTable/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra/devices">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Devices</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Devices</h3>
|
||||
<Paragraph>All enrolled devices</Paragraph>
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<DeviceTable />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Devices;
|
||||
|
||||
@ -16,49 +16,51 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon,
|
||||
Card
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import GeoDashboard from "../../../components/Geo/geo-dashboard/GeoDashboard";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import GeoDashboard from '../../../components/Geo/geo-dashboard/GeoDashboard';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Geo extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Geo</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Geo</h3>
|
||||
<Paragraph>Geo Location Service</Paragraph>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720, alignItems: "center"}}>
|
||||
<GeoDashboard/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Geo</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Geo</h3>
|
||||
<Paragraph>Geo Location Service</Paragraph>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{
|
||||
background: '#f0f2f5',
|
||||
padding: 24,
|
||||
minHeight: 720,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<GeoDashboard />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Geo;
|
||||
|
||||
@ -16,47 +16,44 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import GroupsTable from "../../../components/Groups/GroupsTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import GroupsTable from '../../../components/Groups/GroupsTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Groups extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Groups</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Groups</h3>
|
||||
<Paragraph>All device groups.</Paragraph>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
<GroupsTable/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Groups</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Groups</h3>
|
||||
<Paragraph>All device groups.</Paragraph>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}>
|
||||
<GroupsTable />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Groups;
|
||||
|
||||
@ -16,65 +16,66 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {notification, Menu, Icon} from 'antd';
|
||||
import React from 'react';
|
||||
import { notification, Menu, Icon } from 'antd';
|
||||
import axios from 'axios';
|
||||
import {withConfigContext} from "../../../context/ConfigContext";
|
||||
import { withConfigContext } from '../../../context/ConfigContext';
|
||||
|
||||
/*
|
||||
This class for call the logout api by sending request
|
||||
*/
|
||||
class Logout extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inValid: false,
|
||||
loading: false
|
||||
};
|
||||
}
|
||||
/*
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inValid: false,
|
||||
loading: false,
|
||||
};
|
||||
}
|
||||
/*
|
||||
This function call the logout api when the request is success
|
||||
*/
|
||||
handleSubmit = () => {
|
||||
handleSubmit = () => {
|
||||
const thisForm = this;
|
||||
const config = this.props.context;
|
||||
|
||||
const thisForm = this;
|
||||
const config = this.props.context;
|
||||
thisForm.setState({
|
||||
inValid: false,
|
||||
});
|
||||
|
||||
thisForm.setState({
|
||||
inValid: false
|
||||
});
|
||||
axios
|
||||
.post(window.location.origin + config.serverConfig.logoutUri)
|
||||
.then(res => {
|
||||
// if the api call status is correct then user will logout and then it goes to login page
|
||||
if (res.status === 200) {
|
||||
window.location = window.location.origin + '/entgra/login';
|
||||
}
|
||||
})
|
||||
.catch(function(error) {
|
||||
if (error.hasOwnProperty('response') && error.response.status === 400) {
|
||||
thisForm.setState({
|
||||
inValid: true,
|
||||
});
|
||||
} else {
|
||||
notification.error({
|
||||
message: 'There was a problem',
|
||||
duration: 0,
|
||||
description: 'Error occurred while trying to logout.',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
axios.post(window.location.origin + config.serverConfig.logoutUri
|
||||
).then(res => {
|
||||
//if the api call status is correct then user will logout and then it goes to login page
|
||||
if (res.status === 200) {
|
||||
window.location = window.location.origin + "/entgra/login";
|
||||
}
|
||||
}).catch(function (error) {
|
||||
|
||||
if (error.hasOwnProperty("response") && error.response.status === 400) {
|
||||
thisForm.setState({
|
||||
inValid: true
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: "There was a problem",
|
||||
duration: 0,
|
||||
description:
|
||||
"Error occurred while trying to logout.",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Item key="1" onClick={this.handleSubmit}><Icon type="logout"/>Logout</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Item key="1" onClick={this.handleSubmit}>
|
||||
<Icon type="logout" />
|
||||
Logout
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withConfigContext(Logout);
|
||||
|
||||
@ -16,50 +16,47 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import AddPolicy from "../../../components/Policies/AddPolicy";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import AddPolicy from '../../../components/Policies/AddPolicy';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class AddNewPolicy extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Policies</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Policies</h3>
|
||||
<Paragraph>Create new policy on IoT Server.</Paragraph>
|
||||
</div>
|
||||
<div style={{ borderRadius: 5}}>
|
||||
<AddPolicy/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Policies</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Policies</h3>
|
||||
<Paragraph>Create new policy on IoT Server.</Paragraph>
|
||||
</div>
|
||||
<div style={{ borderRadius: 5 }}>
|
||||
<AddPolicy />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AddNewPolicy;
|
||||
|
||||
@ -16,50 +16,47 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import PoliciesTable from "../../../components/Policies/PoliciesTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import PoliciesTable from '../../../components/Policies/PoliciesTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Policies extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Policies</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Policies</h3>
|
||||
<Paragraph>All policies for device management</Paragraph>
|
||||
</div>
|
||||
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||
<PoliciesTable/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Policies</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Policies</h3>
|
||||
<Paragraph>All policies for device management</Paragraph>
|
||||
</div>
|
||||
<div style={{ backgroundColor: '#ffffff', borderRadius: 5 }}>
|
||||
<PoliciesTable />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Policies;
|
||||
|
||||
@ -16,137 +16,181 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
Icon,
|
||||
Col,
|
||||
Row, Select,
|
||||
Radio, Card,
|
||||
Button
|
||||
} from "antd";
|
||||
import React from 'react';
|
||||
import { Icon, Col, Row, Card } from 'antd';
|
||||
|
||||
import {Link} from "react-router-dom";
|
||||
import moment from "moment";
|
||||
|
||||
|
||||
const { Option } = Select;
|
||||
import { Link } from 'react-router-dom';
|
||||
import moment from 'moment';
|
||||
|
||||
class ReportDurationItemList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
reportParams: ['ACTIVE', 'INACTIVE', 'REMOVED'],
|
||||
enrollmentsVsUnenrollmentsParams: ['Enrollments', 'Unenrollments'],
|
||||
enrollmentTypeParams: ['BYOD', 'COPE'],
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
reportParams:["ACTIVE","INACTIVE","REMOVED"],
|
||||
enrollmentsVsUnenrollmentsParams:["Enrollments", "Unenrollments"],
|
||||
enrollmentTypeParams:["BYOD", "COPE"]
|
||||
}
|
||||
}
|
||||
durationItemArray = [
|
||||
{
|
||||
name: 'Daily Report',
|
||||
description: 'Enrollments of today',
|
||||
duration: [
|
||||
moment().format('YYYY-MM-DD'),
|
||||
moment()
|
||||
.add(1, 'days')
|
||||
.format('YYYY-MM-DD'),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Weekly Report',
|
||||
description: 'Enrollments of last 7 days',
|
||||
duration: [
|
||||
moment()
|
||||
.subtract(6, 'days')
|
||||
.format('YYYY-MM-DD'),
|
||||
moment()
|
||||
.add(1, 'days')
|
||||
.format('YYYY-MM-DD'),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Monthly Report',
|
||||
description: 'Enrollments of last month',
|
||||
duration: [
|
||||
moment()
|
||||
.subtract(29, 'days')
|
||||
.format('YYYY-MM-DD'),
|
||||
moment()
|
||||
.add(1, 'days')
|
||||
.format('YYYY-MM-DD'),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
durationItemArray = [
|
||||
{name:"Daily Report", description:"Enrollments of today", duration:[moment().format('YYYY-MM-DD'), moment().add(1, 'days').format('YYYY-MM-DD')]},
|
||||
{name:"Weekly Report", description:"Enrollments of last 7 days", duration:[moment().subtract(6, 'days').format('YYYY-MM-DD'), moment().add(1, 'days').format('YYYY-MM-DD')]},
|
||||
{name:"Monthly Report", description:"Enrollments of last month", duration:[moment().subtract(29, 'days').format('YYYY-MM-DD'), moment().add(1, 'days').format('YYYY-MM-DD')]}]
|
||||
|
||||
|
||||
render(){
|
||||
|
||||
let itemStatus = this.durationItemArray.map((data) =>
|
||||
<Col key={data.name} span={6}>
|
||||
<Link
|
||||
to={{
|
||||
//Path to respective report page
|
||||
pathname: "/entgra/devicestatus",
|
||||
reportData: {
|
||||
duration: data.duration,
|
||||
reportType: data.reportType,
|
||||
params: this.state.reportParams,
|
||||
paramsType: data.paramsType
|
||||
}
|
||||
}}>
|
||||
<Card key={data.name} bordered={true} hoverable={true} style={{borderRadius: 10, marginBottom: 16}}>
|
||||
|
||||
<div align='center'>
|
||||
<Icon type="desktop" style={{ fontSize: '25px', color: '#08c' }}/>
|
||||
<h2><b>{data.name}</b></h2>
|
||||
<p>{data.description}</p>
|
||||
{/*<p>{data.duration}</p>*/}
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
);
|
||||
|
||||
let itemEnrollmentsVsUnenrollments = this.durationItemArray.map((data) =>
|
||||
<Col key={data.name} span={6}>
|
||||
<Link
|
||||
to={{
|
||||
//Path to respective report page
|
||||
pathname: "/entgra/enrollmentsvsunenrollments",
|
||||
reportData: {
|
||||
duration: data.duration,
|
||||
reportType: data.reportType,
|
||||
params: this.state.enrollmentsVsUnenrollmentsParams,
|
||||
paramsType: data.paramsType
|
||||
}
|
||||
}}>
|
||||
<Card key={data.name} bordered={true} hoverable={true} style={{borderRadius: 10, marginBottom: 16}}>
|
||||
|
||||
<div align='center'>
|
||||
<Icon type="desktop" style={{ fontSize: '25px', color: '#08c' }}/>
|
||||
<h2><b>{data.name}</b></h2>
|
||||
<p>{data.description}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
);
|
||||
|
||||
let itemEnrollmentType = this.durationItemArray.map((data) =>
|
||||
<Col key={data.name} span={6}>
|
||||
<Link
|
||||
to={{
|
||||
//Path to respective report page
|
||||
pathname: "/entgra/enrollmenttype",
|
||||
reportData: {
|
||||
duration: data.duration,
|
||||
reportType: data.reportType,
|
||||
params: this.state.enrollmentTypeParams,
|
||||
paramsType: data.paramsType
|
||||
}
|
||||
}}>
|
||||
<Card key={data.name} bordered={true} hoverable={true} style={{borderRadius: 10, marginBottom: 16}}>
|
||||
|
||||
<div align='center'>
|
||||
<Icon type="desktop" style={{ fontSize: '25px', color: '#08c' }}/>
|
||||
<h2><b>{data.name}</b></h2>
|
||||
<p>{data.description}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
);
|
||||
return(
|
||||
<div>
|
||||
<div style={{borderRadius: 5}}>
|
||||
<Row gutter={16} >
|
||||
{itemStatus}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div style={{borderRadius: 5}}>
|
||||
<Row gutter={16} >
|
||||
{itemEnrollmentsVsUnenrollments}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div style={{borderRadius: 5}}>
|
||||
<Row gutter={16} >
|
||||
{itemEnrollmentType}
|
||||
</Row>
|
||||
</div>
|
||||
render() {
|
||||
let itemStatus = this.durationItemArray.map(data => (
|
||||
<Col key={data.name} span={6}>
|
||||
<Link
|
||||
to={{
|
||||
// Path to respective report page
|
||||
pathname: '/entgra/devicestatus',
|
||||
reportData: {
|
||||
duration: data.duration,
|
||||
reportType: data.reportType,
|
||||
params: this.state.reportParams,
|
||||
paramsType: data.paramsType,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
key={data.name}
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{ borderRadius: 10, marginBottom: 16 }}
|
||||
>
|
||||
<div align="center">
|
||||
<Icon
|
||||
type="desktop"
|
||||
style={{ fontSize: '25px', color: '#08c' }}
|
||||
/>
|
||||
<h2>
|
||||
<b>{data.name}</b>
|
||||
</h2>
|
||||
<p>{data.description}</p>
|
||||
{/* <p>{data.duration}</p>*/}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
));
|
||||
|
||||
let itemEnrollmentsVsUnenrollments = this.durationItemArray.map(data => (
|
||||
<Col key={data.name} span={6}>
|
||||
<Link
|
||||
to={{
|
||||
// Path to respective report page
|
||||
pathname: '/entgra/enrollmentsvsunenrollments',
|
||||
reportData: {
|
||||
duration: data.duration,
|
||||
reportType: data.reportType,
|
||||
params: this.state.enrollmentsVsUnenrollmentsParams,
|
||||
paramsType: data.paramsType,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
key={data.name}
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{ borderRadius: 10, marginBottom: 16 }}
|
||||
>
|
||||
<div align="center">
|
||||
<Icon
|
||||
type="desktop"
|
||||
style={{ fontSize: '25px', color: '#08c' }}
|
||||
/>
|
||||
<h2>
|
||||
<b>{data.name}</b>
|
||||
</h2>
|
||||
<p>{data.description}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
));
|
||||
|
||||
let itemEnrollmentType = this.durationItemArray.map(data => (
|
||||
<Col key={data.name} span={6}>
|
||||
<Link
|
||||
to={{
|
||||
// Path to respective report page
|
||||
pathname: '/entgra/enrollmenttype',
|
||||
reportData: {
|
||||
duration: data.duration,
|
||||
reportType: data.reportType,
|
||||
params: this.state.enrollmentTypeParams,
|
||||
paramsType: data.paramsType,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
key={data.name}
|
||||
bordered={true}
|
||||
hoverable={true}
|
||||
style={{ borderRadius: 10, marginBottom: 16 }}
|
||||
>
|
||||
<div align="center">
|
||||
<Icon
|
||||
type="desktop"
|
||||
style={{ fontSize: '25px', color: '#08c' }}
|
||||
/>
|
||||
<h2>
|
||||
<b>{data.name}</b>
|
||||
</h2>
|
||||
<p>{data.description}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
<div style={{ borderRadius: 5 }}>
|
||||
<Row gutter={16}>{itemStatus}</Row>
|
||||
</div>
|
||||
|
||||
<div style={{ borderRadius: 5 }}>
|
||||
<Row gutter={16}>{itemEnrollmentsVsUnenrollments}</Row>
|
||||
</div>
|
||||
|
||||
<div style={{ borderRadius: 5 }}>
|
||||
<Row gutter={16}>{itemEnrollmentType}</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ReportDurationItemList;
|
||||
export default ReportDurationItemList;
|
||||
|
||||
@ -16,80 +16,69 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import ReportDurationItemList from "./ReportDurationItemList";
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
import React from 'react';
|
||||
import { PageHeader, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import ReportDurationItemList from './ReportDurationItemList';
|
||||
|
||||
class Reports extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
this.state = {
|
||||
paramsObject:{},
|
||||
}
|
||||
}
|
||||
//Get modified value from datepicker and set it to paramsObject
|
||||
updateDurationValue = (modifiedFromDate,modifiedToDate) => {
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
tempParamObj.from = modifiedFromDate;
|
||||
tempParamObj.to = modifiedToDate;
|
||||
this.setState({paramsObject:tempParamObj});
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
this.state = {
|
||||
paramsObject: {},
|
||||
};
|
||||
}
|
||||
// Get modified value from datepicker and set it to paramsObject
|
||||
updateDurationValue = (modifiedFromDate, modifiedToDate) => {
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
tempParamObj.from = modifiedFromDate;
|
||||
tempParamObj.to = modifiedToDate;
|
||||
this.setState({ paramsObject: tempParamObj });
|
||||
};
|
||||
|
||||
//Get modified value from filters and set it to paramsObject
|
||||
updateFiltersValue = (modifiedValue,filterType) => {
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
if(filterType=="Device Status"){
|
||||
tempParamObj.status = modifiedValue;
|
||||
if(modifiedValue=="ALL" && tempParamObj.status){
|
||||
delete tempParamObj.status;
|
||||
}
|
||||
}else{
|
||||
tempParamObj.ownership = modifiedValue;
|
||||
if(modifiedValue=="ALL" && tempParamObj.ownership){
|
||||
delete tempParamObj.ownership;
|
||||
}
|
||||
}
|
||||
this.setState({paramsObject:tempParamObj});
|
||||
};
|
||||
|
||||
render() {
|
||||
//Arrays for filters
|
||||
const statusObj = ['ALL','ACTIVE','INACTIVE','REMOVED'];
|
||||
const ownershipObj = ['ALL','BYOD','COPE'];
|
||||
|
||||
const params = {...this.state.paramsObject};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Reports</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Reports</h3>
|
||||
<ReportDurationItemList/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
// Get modified value from filters and set it to paramsObject
|
||||
updateFiltersValue = (modifiedValue, filterType) => {
|
||||
let tempParamObj = this.state.paramsObject;
|
||||
if (filterType == 'Device Status') {
|
||||
tempParamObj.status = modifiedValue;
|
||||
if (modifiedValue == 'ALL' && tempParamObj.status) {
|
||||
delete tempParamObj.status;
|
||||
}
|
||||
} else {
|
||||
tempParamObj.ownership = modifiedValue;
|
||||
if (modifiedValue == 'ALL' && tempParamObj.ownership) {
|
||||
delete tempParamObj.ownership;
|
||||
}
|
||||
}
|
||||
this.setState({ paramsObject: tempParamObj });
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Reports</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Reports</h3>
|
||||
<ReportDurationItemList />
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Reports;
|
||||
|
||||
@ -16,47 +16,44 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import RolesTable from "../../../components/Roles/RolesTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import RolesTable from '../../../components/Roles/RolesTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Roles extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Roles</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Roles</h3>
|
||||
<Paragraph>All user roles</Paragraph>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
<RolesTable/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Roles</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Roles</h3>
|
||||
<Paragraph>All user roles</Paragraph>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}>
|
||||
<RolesTable />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Roles;
|
||||
|
||||
@ -16,48 +16,45 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
PageHeader,
|
||||
Typography,
|
||||
Breadcrumb,
|
||||
Icon
|
||||
} from "antd";
|
||||
import {Link} from "react-router-dom";
|
||||
import UsersTable from "../../../components/Users/UsersTable";
|
||||
import React from 'react';
|
||||
import { PageHeader, Typography, Breadcrumb, Icon } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import UsersTable from '../../../components/Users/UsersTable';
|
||||
|
||||
const {Paragraph} = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
|
||||
class Users extends React.Component {
|
||||
routes;
|
||||
routes;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{paddingTop: 0}}>
|
||||
<Breadcrumb style={{paddingBottom: 16}}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Users</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Users</h3>
|
||||
<Paragraph>All users for device management.</Paragraph>
|
||||
</div>
|
||||
<UsersTable/>
|
||||
</PageHeader>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader style={{ paddingTop: 0 }}>
|
||||
<Breadcrumb style={{ paddingBottom: 16 }}>
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/entgra">
|
||||
<Icon type="home" /> Home
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Users</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="wrap">
|
||||
<h3>Users</h3>
|
||||
<Paragraph>All users for device management.</Paragraph>
|
||||
</div>
|
||||
<UsersTable />
|
||||
</PageHeader>
|
||||
<div
|
||||
style={{ background: '#f0f2f5', padding: 24, minHeight: 720 }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Users;
|
||||
|
||||
@ -16,161 +16,180 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {Typography, Row, Col, Form, Icon, Input, Button, Checkbox} from 'antd';
|
||||
import React from 'react';
|
||||
import {
|
||||
Typography,
|
||||
Row,
|
||||
Col,
|
||||
Form,
|
||||
Icon,
|
||||
Input,
|
||||
Button,
|
||||
Checkbox,
|
||||
} from 'antd';
|
||||
import './Login.css';
|
||||
import axios from 'axios';
|
||||
import {withConfigContext} from "../context/ConfigContext";
|
||||
import { withConfigContext } from '../context/ConfigContext';
|
||||
|
||||
const {Title} = Typography;
|
||||
const {Text} = Typography;
|
||||
const { Title } = Typography;
|
||||
const { Text } = Typography;
|
||||
|
||||
class Login extends React.Component {
|
||||
render() {
|
||||
const config = this.props.context;
|
||||
return (
|
||||
<div>
|
||||
<div className="background">
|
||||
</div>
|
||||
<div className="content">
|
||||
<Row>
|
||||
<Col xs={3} sm={3} md={10}>
|
||||
|
||||
</Col>
|
||||
<Col xs={18} sm={18} md={4}>
|
||||
<Row style={{marginBottom: 20}}>
|
||||
<Col style={{textAlign: "center"}}>
|
||||
<img style={
|
||||
{
|
||||
marginTop: 36,
|
||||
height: 60
|
||||
}
|
||||
}
|
||||
src={config.theme.logo}/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Title level={2}>Login</Title>
|
||||
<WrappedNormalLoginForm/>
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={4} offset={10}>
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const config = this.props.context;
|
||||
return (
|
||||
<div>
|
||||
<div className="background"></div>
|
||||
<div className="content">
|
||||
<Row>
|
||||
<Col xs={3} sm={3} md={10}></Col>
|
||||
<Col xs={18} sm={18} md={4}>
|
||||
<Row style={{ marginBottom: 20 }}>
|
||||
<Col style={{ textAlign: 'center' }}>
|
||||
<img
|
||||
style={{
|
||||
marginTop: 36,
|
||||
height: 60,
|
||||
}}
|
||||
src={config.theme.logo}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Title level={2}>Login</Title>
|
||||
<WrappedNormalLoginForm />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={4} offset={10}></Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NormalLoginForm extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inValid: false,
|
||||
loading: false
|
||||
};
|
||||
}
|
||||
|
||||
handleSubmit = (e) => {
|
||||
const thisForm = this;
|
||||
const config = this.props.context;
|
||||
console.log(config);
|
||||
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
thisForm.setState({
|
||||
inValid: false
|
||||
});
|
||||
if (!err) {
|
||||
thisForm.setState({
|
||||
loading: true
|
||||
});
|
||||
const parameters = {
|
||||
username: values.username,
|
||||
password: values.password,
|
||||
platform: "entgra"
|
||||
};
|
||||
|
||||
const request = Object.keys(parameters).map(key => key + '=' + parameters[key]).join('&');
|
||||
|
||||
axios.post(window.location.origin+ config.serverConfig.loginUri, request
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
let redirectUrl = window.location.origin + "/entgra";
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
if (searchParams.has("redirect")) {
|
||||
redirectUrl = searchParams.get("redirect");
|
||||
}
|
||||
window.location = redirectUrl;
|
||||
}
|
||||
}).catch(function (error) {
|
||||
if (error.response.status === 400) {
|
||||
thisForm.setState({
|
||||
inValid: true,
|
||||
loading: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inValid: false,
|
||||
loading: false,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
let errorMsg = "";
|
||||
if (this.state.inValid) {
|
||||
errorMsg = <Text type="danger">Invalid Login Details</Text>;
|
||||
}
|
||||
let loading = "";
|
||||
if (this.state.loading) {
|
||||
loading = <Text type="secondary">Loading..</Text>;
|
||||
}
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit} className="login-form">
|
||||
<Form.Item>
|
||||
{getFieldDecorator('username', {
|
||||
rules: [{required: true, message: 'Please input your username!'}],
|
||||
})(
|
||||
<Input name="username" style={{height: 32}}
|
||||
prefix={<Icon type="user" style={{color: 'rgba(0,0,0,.25)'}}/>}
|
||||
placeholder="Username"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('password', {
|
||||
rules: [{required: true, message: 'Please input your Password!'}],
|
||||
})(
|
||||
<Input name="password" style={{height: 32}}
|
||||
prefix={<Icon type="lock" style={{color: 'rgba(0,0,0,.25)'}}/>} type="password"
|
||||
placeholder="Password"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
{loading}
|
||||
{errorMsg}
|
||||
<Form.Item>
|
||||
{getFieldDecorator('remember', {
|
||||
valuePropName: 'checked',
|
||||
initialValue: true,
|
||||
})(
|
||||
<Checkbox>Remember me</Checkbox>
|
||||
)}
|
||||
<br/>
|
||||
<a className="login-form-forgot" href="">Forgot password</a>
|
||||
<Button loading={this.state.loading} block type="primary" htmlType="submit" className="login-form-button">
|
||||
Log in
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
handleSubmit = e => {
|
||||
const thisForm = this;
|
||||
const config = this.props.context;
|
||||
console.log(config);
|
||||
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err, values) => {
|
||||
thisForm.setState({
|
||||
inValid: false,
|
||||
});
|
||||
if (!err) {
|
||||
thisForm.setState({
|
||||
loading: true,
|
||||
});
|
||||
const parameters = {
|
||||
username: values.username,
|
||||
password: values.password,
|
||||
platform: 'entgra',
|
||||
};
|
||||
|
||||
const request = Object.keys(parameters)
|
||||
.map(key => key + '=' + parameters[key])
|
||||
.join('&');
|
||||
|
||||
axios
|
||||
.post(window.location.origin + config.serverConfig.loginUri, request)
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
let redirectUrl = window.location.origin + '/entgra';
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
if (searchParams.has('redirect')) {
|
||||
redirectUrl = searchParams.get('redirect');
|
||||
}
|
||||
window.location = redirectUrl;
|
||||
}
|
||||
})
|
||||
.catch(function(error) {
|
||||
if (error.response.status === 400) {
|
||||
thisForm.setState({
|
||||
inValid: true,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
let errorMsg = '';
|
||||
if (this.state.inValid) {
|
||||
errorMsg = <Text type="danger">Invalid Login Details</Text>;
|
||||
}
|
||||
let loading = '';
|
||||
if (this.state.loading) {
|
||||
loading = <Text type="secondary">Loading..</Text>;
|
||||
}
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit} className="login-form">
|
||||
<Form.Item>
|
||||
{getFieldDecorator('username', {
|
||||
rules: [{ required: true, message: 'Please input your username!' }],
|
||||
})(
|
||||
<Input
|
||||
name="username"
|
||||
style={{ height: 32 }}
|
||||
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
|
||||
placeholder="Username"
|
||||
/>,
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('password', {
|
||||
rules: [{ required: true, message: 'Please input your Password!' }],
|
||||
})(
|
||||
<Input
|
||||
name="password"
|
||||
style={{ height: 32 }}
|
||||
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/>,
|
||||
)}
|
||||
</Form.Item>
|
||||
{loading}
|
||||
{errorMsg}
|
||||
<Form.Item>
|
||||
{getFieldDecorator('remember', {
|
||||
valuePropName: 'checked',
|
||||
initialValue: true,
|
||||
})(<Checkbox>Remember me</Checkbox>)}
|
||||
<br />
|
||||
<a className="login-form-forgot" href="">
|
||||
Forgot password
|
||||
</a>
|
||||
<Button
|
||||
loading={this.state.loading}
|
||||
block
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
className="login-form-button"
|
||||
>
|
||||
Log in
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const WrappedNormalLoginForm = withConfigContext(Form.create({name: 'normal_login'})(NormalLoginForm));
|
||||
const WrappedNormalLoginForm = withConfigContext(
|
||||
Form.create({ name: 'normal_login' })(NormalLoginForm),
|
||||
);
|
||||
|
||||
export default withConfigContext(Login);
|
||||
|
||||
@ -34,8 +34,8 @@ const isLocalhost = Boolean(
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
|
||||
),
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
@ -61,7 +61,7 @@ export function register(config) {
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA',
|
||||
);
|
||||
});
|
||||
} else {
|
||||
@ -89,7 +89,7 @@ function registerValidSW(swUrl, config) {
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.',
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
@ -139,7 +139,7 @@ function checkValidServiceWorker(swUrl, config) {
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
'No internet connection found. App is running in offline mode.',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -16,119 +16,119 @@
|
||||
* under the License.
|
||||
*/
|
||||
var path = require('path');
|
||||
const HtmlWebPackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const configurations = require("./public/conf/config.json");
|
||||
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const configurations = require('./public/conf/config.json');
|
||||
|
||||
const config = {
|
||||
devtool: "source-map",
|
||||
output: {
|
||||
publicPath: '/entgra/'
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
publicPath: '/entgra/',
|
||||
},
|
||||
watch: false,
|
||||
resolve: {
|
||||
alias: {
|
||||
AppData: path.resolve(__dirname, 'source/src/app/common/'),
|
||||
AppComponents: path.resolve(__dirname, 'source/src/app/components/'),
|
||||
},
|
||||
watch: false,
|
||||
resolve: {
|
||||
alias: {
|
||||
AppData: path.resolve(__dirname, 'source/src/app/common/'),
|
||||
AppComponents: path.resolve(__dirname, 'source/src/app/components/')
|
||||
},
|
||||
extensions: ['.jsx', '.js', '.ttf', '.woff', '.woff2', '.svg']
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader'
|
||||
}
|
||||
]
|
||||
extensions: ['.jsx', '.js', '.ttf', '.woff', '.woff2', '.svg'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'html-loader',
|
||||
options: { minimize: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: ['style-loader', 'scss-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'style-loader',
|
||||
},
|
||||
{
|
||||
loader: 'css-loader',
|
||||
},
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: {
|
||||
modifyVars: {
|
||||
'primary-color': configurations.theme.primaryColor,
|
||||
'link-color': configurations.theme.primaryColor,
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: [
|
||||
{
|
||||
loader: "html-loader",
|
||||
options: { minimize: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|eot|ttf|svg)$/,
|
||||
loader: 'url-loader?limit=100000',
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g)/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
name: './img/[name].[ext]',
|
||||
limit: 10000,
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [MiniCssExtractPlugin.loader, "css-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
"css-loader",
|
||||
"postcss-loader",
|
||||
"sass-loader"
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [ 'style-loader', 'scss-loader' ]
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
{
|
||||
loader: "style-loader"
|
||||
},
|
||||
{
|
||||
loader: "css-loader",
|
||||
},
|
||||
{
|
||||
loader: "less-loader",
|
||||
options: {
|
||||
modifyVars: {
|
||||
'primary-color': configurations.theme.primaryColor,
|
||||
'link-color': configurations.theme.primaryColor,
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|eot|ttf|svg)$/,
|
||||
loader: 'url-loader?limit=100000',
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g)/i,
|
||||
use: [
|
||||
{
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
name: "./img/[name].[ext]",
|
||||
limit: 10000
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: "img-loader"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebPackPlugin({
|
||||
template: "./src/index.html",
|
||||
filename: "./index.html"
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "[name].css",
|
||||
chunkFilename: "[id].css"
|
||||
})
|
||||
},
|
||||
{
|
||||
loader: 'img-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
externals: {
|
||||
'Config': JSON.stringify(require('./public/conf/config.json'))
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebPackPlugin({
|
||||
template: './src/index.html',
|
||||
filename: './index.html',
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
}),
|
||||
],
|
||||
externals: {
|
||||
Config: JSON.stringify(require('./public/conf/config.json')),
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
config.watch = true;
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
config.watch = true;
|
||||
}
|
||||
|
||||
module.exports = config;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user