Merge branch 'master' into 'master'

Add View to Enroll New Device and Change left menu to top

See merge request entgra/carbon-device-mgt!395
feature/appm-store/pbac
Dharmakeerthi Lasantha 5 years ago
commit 28e3aaf91e

@ -0,0 +1,66 @@
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;
class AddDevice extends React.Component {
constructor(props) {
super(props);
this.config = this.props.context;
this.state = {
isAddDeviceModalVisible: false,
current : 0,
}
};
onClickType = () =>{
this.setState({
current: 1,
})
};
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={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>
);
}
}
export default withConfigContext(Form.create({name: 'add-device'})(AddDevice));

@ -0,0 +1,148 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from "react";
import axios from "axios";
import {Card, Col, Icon, message, notification, Row, 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";
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: {},
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});
// 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>
);
}
}
export default withConfigContext(DeviceType);

@ -0,0 +1,87 @@
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;
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();
};
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.",
});
}
});
};
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>
);
}
}
export default withConfigContext(EnrollAgent);

@ -31,6 +31,7 @@ import Users from "./pages/Dashboard/Users/Users";
import Policies from "./pages/Dashboard/Policies/Policies"; import Policies from "./pages/Dashboard/Policies/Policies";
import Roles from "./pages/Dashboard/Roles/Roles"; import Roles from "./pages/Dashboard/Roles/Roles";
import DeviceTypes from "./pages/Dashboard/DeviceTypes/DeviceTypes"; import DeviceTypes from "./pages/Dashboard/DeviceTypes/DeviceTypes";
import DeviceEnroll from "./pages/Dashboard/Devices/DeviceEnroll";
const routes = [ const routes = [
{ {
@ -48,6 +49,11 @@ const routes = [
component: Devices, component: Devices,
exact: true exact: true
}, },
{
path: '/entgra/devices/enroll',
component: DeviceEnroll,
exact: true
},
{ {
path: '/entgra/geo', path: '/entgra/geo',
component: Geo, component: Geo,

@ -35,13 +35,7 @@
} }
.layout .logo-image { .layout .logo-image {
position: relative; float: left;
height: 64px;
padding-left: 8px;
overflow: hidden;
line-height: 64px;
background: #001529;
transition: all .3s;
} }
.layout .brand{ .layout .brand{
@ -54,7 +48,7 @@
} }
.layout .logo-image img { .layout .logo-image img {
height: 55px; height: 45px;
margin-top: 5px; margin-top: 5px;
margin-left: 16px; margin-left: 16px;
margin-right: 16px; margin-right: 16px;

@ -56,24 +56,36 @@ class Dashboard extends React.Component {
return ( return (
<div> <div>
<Layout className="layout" > <Layout className="layout" >
<Layout>
<Sider <Header style={{background: '#fff', padding: 0}}>
trigger={null}
collapsible
collapsed={this.state.isNavBarCollapsed}
collapsedWidth={this.state.mobileWidth}
>
<div className="logo-image"> <div className="logo-image">
<Link to="/entgra/devices"><img alt="logo" src={this.logo}/></Link> <Link to="/entgra/devices"><img alt="logo" src={this.logo}/></Link>
</div> </div>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['devices']}>
<Menu.Item key="devices"> <Menu
<Link to="/entgra/devices"> theme="light"
mode="horizontal"
style={{lineHeight: '64px'}}
>
<SubMenu
key="devices"
title={
<span>
<Icon type="appstore"/> <Icon type="appstore"/>
<span>Devices</span> <span>Devices</span>
</span>}
>
<Menu.Item key="devices">
<Link to="/entgra/devices">
<span>View</span>
</Link> </Link>
</Menu.Item> </Menu.Item>
<Menu.Item key="deviceEnroll">
<Link to="/entgra/devices/enroll">
<span>Enroll</span>
</Link>
</Menu.Item>
</SubMenu>
<SubMenu <SubMenu
key="geo" key="geo"
title={ title={
@ -129,24 +141,6 @@ class Dashboard extends React.Component {
<span>Device Types</span> <span>Device Types</span>
</Link> </Link>
</Menu.Item> </Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{background: '#fff', padding: 0}}>
<div className="trigger">
<Icon
type={this.state.isNavBarCollapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</div>
<Menu
theme="light"
mode="horizontal"
style={{lineHeight: '64px'}}
>
<Menu.Item key="trigger"> <Menu.Item key="trigger">
</Menu.Item> </Menu.Item>
<SubMenu className="profile" <SubMenu className="profile"
@ -161,7 +155,7 @@ class Dashboard extends React.Component {
</Menu> </Menu>
</Header> </Header>
<Content style={{marginTop: 2}}> <Content style={{marginTop: 10}}>
<Switch> <Switch>
<Redirect exact from="/entgra" to="/entgra/devices"/> <Redirect exact from="/entgra" to="/entgra/devices"/>
{this.state.routes.map((route) => ( {this.state.routes.map((route) => (

@ -0,0 +1,50 @@
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";
const {Paragraph} = Typography;
class DeviceEnroll extends React.Component {
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>
);
}
}
export default DeviceEnroll;
Loading…
Cancel
Save