Merge branch 'application-mgt-new' into 'application-mgt-new'

Add Login Redirection

See merge request entgra/carbon-device-mgt!77
feature/appm-store/pbac
Dharmakeerthi Lasantha 6 years ago
commit 4482245971

@ -16,10 +16,11 @@
"react": "^16.8.4", "react": "^16.8.4",
"react-dom": "^16.8.4", "react-dom": "^16.8.4",
"react-highlight-words": "^0.16.0", "react-highlight-words": "^0.16.0",
"react-router": "latest",
"react-router-config": "^5.0.0", "react-router-config": "^5.0.0",
"react-router-dom": "latest", "react-router-dom": "latest",
"react-scripts": "2.1.8", "react-scripts": "2.1.8",
"react-router": "latest" "redux-thunk": "^2.3.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.0.0", "@babel/core": "^7.0.0",
@ -37,6 +38,7 @@
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"img-loader": "^3.0.1", "img-loader": "^3.0.1",
"json-loader": "^0.5.7",
"less": "^3.9.0", "less": "^3.9.0",
"less-loader": "^4.1.0", "less-loader": "^4.1.0",
"mini-css-extract-plugin": "^0.5.0", "mini-css-extract-plugin": "^0.5.0",

@ -3,10 +3,16 @@
"type": "default", "type": "default",
"value": "lightBaseTheme" "value": "lightBaseTheme"
}, },
"config": { "serverConfig": {
"hostname": "localhost", "hostname": "localhost",
"httpsPort": "9443", "httpsPort": "9443",
"apiPort": "8243" "invokerUri": "/api/application-mgt-handler/v1.0/invoke",
"loginUri": "/api/application-mgt-handler/v1.0/login"
}, },
"serverUrl" : "https://localhost:9443" "serverUrl" : "https://localhost:9443",
"defaultPlatformIcons": {
"default": "http://www.newdesignfile.com/postpic/2015/08/square-app-icon-blue_77131.png",
"android": "data:image/png;base64,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",
"ios" : "data:image/png;base64,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"
}
} }

@ -3,27 +3,33 @@ import "antd/dist/antd.css";
import RouteWithSubRoutes from "./components/RouteWithSubRoutes"; import RouteWithSubRoutes from "./components/RouteWithSubRoutes";
import { import {
BrowserRouter as Router, BrowserRouter as Router,
Link, Link, Redirect, Switch,
} from 'react-router-dom'; } from 'react-router-dom';
class App extends React.Component { class App extends React.Component {
routes; routes;
constructor(props) { constructor(props) {
super(props); super(props);
this.routes = props.routes; this.routes = props.routes;
} }
render() {
return (
<Router>
<div>
{this.routes.map((route) => (
<RouteWithSubRoutes key={route.path} {...route} />
))}
</div>
</Router>
); render() {
} console.log(this.routes);
return (
<Router>
<div>
<Switch>
<Redirect exact from="/publisher" to="/publisher/apps"/>
{this.routes.map((route) => (
<RouteWithSubRoutes key={route.path} {...route} />
))}
</Switch>
</div>
</Router>
);
}
} }
export default App; export default App;

@ -0,0 +1,47 @@
import {
Skeleton, Switch, Card, Icon, Avatar, Typography
} from 'antd';
import React from "react";
import config from "../../public/conf/config.json";
const { Meta } = Card;
const { Text } = Typography;
class AppCard extends React.Component {
constructor(props){
super(props);
}
render() {
const defaultPlatformIcons = config.defaultPlatformIcons;
let icon = defaultPlatformIcons.default;
if(defaultPlatformIcons.hasOwnProperty(this.props.platform)){
icon = defaultPlatformIcons[this.props.platform];
}
let descriptionText = this.props.description;
if(descriptionText.length>50){
descriptionText = descriptionText.substring(0,50)+"...";
}
const description = (
<div>
<p>{descriptionText}</p>
<Text code>{this.props.type}</Text>
<Text> {this.props.subType}</Text>
</div>
);
return (
<Card style={{marginTop: 16 }} actions={[<Icon type="edit" />, <Icon type="close" />, <Icon type="ellipsis" />]}>
<Meta
avatar={<Avatar src={icon} />}
title={this.props.name}
description={description}
/>
</Card>
);
}
}
export default AppCard;

@ -0,0 +1,41 @@
import React from "react";
import AppCard from "./AppCard";
import {Col, Row} from "antd";
import {connect} from "react-redux";
import {getApps} from "../js/actions";
// connecting state.articles with the component
const mapStateToProps= state => {
return {apps : state.apps}
};
class ConnectedAppList extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.getApps();
}
render() {
return (
<Row gutter={16}>
{this.props.apps.map(app => (
<Col key={app.id} xs={24} sm={12} md={6} lg={6}>
<AppCard key={app.id}
name={app.name}
platform={app.deviceType}
type={app.type}
subType={app.subType}
description={app.description}/>
</Col>
))}
</Row>
);
}
}
const AppList = connect(mapStateToProps,{getApps})(ConnectedAppList);
export default AppList;

@ -8,7 +8,7 @@ class RouteWithSubRoutes extends React.Component{
} }
render() { render() {
return( return(
<Route path={this.props.path} render={(props) => ( <Route path={this.props.path} exact={this.props.exact} render={(props) => (
<this.props.component {...props} routes={this.props.routes}/> <this.props.component {...props} routes={this.props.routes}/>
)}/> )}/>
); );

@ -14,19 +14,23 @@ import {Provider} from "react-redux";
const routes = [ const routes = [
{ {
path: '/publisher/login', path: '/publisher/login',
exact: true,
component: Login component: Login
}, },
{ {
path: '/publisher', path: '/publisher/apps',
exact: false,
component: Dashboard, component: Dashboard,
routes: [ routes: [
{ {
path: '/publisher/apps', path: '/publisher/apps',
component: Apps component: Apps,
exact: true
}, },
{ {
path: '/publisher/new-app', path: '/publisher/apps/new-app',
component: AddNewApp component: AddNewApp,
exact: true
} }
] ]
} }
@ -35,7 +39,7 @@ const routes = [
ReactDOM.render( ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<App routes={routes}/> <App routes={routes}/>
</Provider>, </Provider>,
document.getElementById('root')); document.getElementById('root'));

@ -0,0 +1,31 @@
import axios from "axios";
import {GET_APPS} from "../constants/action-types";
import config from "../../../public/conf/config.json";
export function getApps() {
return (dispatch) => {
const request = "method=post&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/applications";
return axios.post('https://'+config.serverConfig.hostname+':'+config.serverConfig.httpsPort+config.serverConfig.invokerUri, request
).then(res => {
if (res.status === 200) {
let apps = [];
if(res.data.data.hasOwnProperty("applications")){
apps = res.data.data.applications;
}
console.log(res.data);
dispatch({type: GET_APPS, payload: apps});
}
}).catch(function (error) {
if (error.response.status === 401) {
window.location.href = 'https://localhost:9443/publisher/login';
}
});
};
}

@ -1 +1,3 @@
export const LOGIN = "LOGIN"; export const LOGIN = "LOGIN";
export const GET_APPS = "GET_APPS";

@ -1,8 +1,16 @@
import {GET_APPS} from "../constants/action-types";
const initialState = { const initialState = {
apps: []
}; };
function rootReducer(state = initialState, action) { function rootReducer(state = initialState, action) {
if (action.type === GET_APPS) {
console.log(11);
return Object.assign({}, state, {
apps: action.payload
});
}
return state; return state;
} }

@ -1,4 +1,5 @@
import { createStore } from "redux"; import { createStore, applyMiddleware } from "redux";
import rootReducer from "../reducers/index"; import rootReducer from "../reducers/index";
const store = createStore(rootReducer); import thunk from "redux-thunk";
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store; export default store;

@ -2,6 +2,7 @@ import React from "react";
import {Typography, Row, Col, Form, Icon, Input, Button, Checkbox} from 'antd'; import {Typography, Row, Col, Form, Icon, Input, Button, Checkbox} from 'antd';
import styles from './Login.less'; import styles from './Login.less';
import axios from 'axios'; import axios from 'axios';
import config from "../../public/conf/config.json";
const {Title} = Typography; const {Title} = Typography;
const {Text} = Typography; const {Text} = Typography;
@ -58,7 +59,7 @@ class NormalLoginForm extends React.Component {
}); });
console.log('Received values of form: ', values); console.log('Received values of form: ', values);
let data = "username=" + values.username + "&password=" + values.password + "&platform=publisher"; let data = "username=" + values.username + "&password=" + values.password + "&platform=publisher";
axios.post('https://localhost:9443/api/application-mgt-handler/v1.0/login', data axios.post('https://'+config.serverConfig.hostname+':'+config.serverConfig.httpsPort+config.serverConfig.loginUri, data
).then(res => { ).then(res => {
if (res.status === 200) { if (res.status === 200) {
window.location = res.data.url; window.location = res.data.url;

@ -31,14 +31,14 @@ class Dashboard extends React.Component {
defaultSelectedKeys={['2']} defaultSelectedKeys={['2']}
style={{lineHeight: '64px'}} style={{lineHeight: '64px'}}
> >
<Menu.Item key="1"><Link to="apps"><Icon type="appstore"/>Apps</Link></Menu.Item> <Menu.Item key="1"><Link to="/publisher/apps"><Icon type="appstore"/>Apps</Link></Menu.Item>
<Menu.Item key="2"><Link to="apps"><Icon type="line-chart"/>Apps</Link></Menu.Item> <Menu.Item key="2"><Link to="/publisher/apps"><Icon type="line-chart"/>Apps</Link></Menu.Item>
<Menu.Item key="3"><Link to="new-app"><Icon type="upload"/>Add New App</Link></Menu.Item> <Menu.Item key="3"><Link to="/publisher/apps/new-app"><Icon type="upload"/>Add New App</Link></Menu.Item>
</Menu> </Menu>
</Header> </Header>
<Content style={{padding: '0 0'}}> <Content style={{padding: '0 0'}}>
<Switch> <Switch>
<Redirect exact from="/publisher" to="/publisher/apps"/> <Redirect exact from="/publisher/dashboard" to="/publisher/dashboard/apps"/>
{this.state.routes.map((route) => ( {this.state.routes.map((route) => (
<RouteWithSubRoutes key={route.path} {...route} /> <RouteWithSubRoutes key={route.path} {...route} />
))} ))}

@ -1,9 +1,8 @@
import React from "react"; import React from "react";
import "antd/dist/antd.css"; import "antd/dist/antd.css";
import {Table, Divider, Tag, Card, PageHeader, Typography, Avatar,Input, Button, Icon, Row, Col} from "antd"; import {PageHeader, Typography,Input, Button, Row, Col} from "antd";
import Highlighter from 'react-highlight-words'; import AppList from "../../../components/AppList";
const Paragraph = Typography;
const Search = Input.Search; const Search = Input.Search;
const routes = [ const routes = [
@ -22,188 +21,32 @@ const routes = [
]; ];
const data = [{
key: '1',
icon: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',
name: 'John Brown',
platform: 'android',
type: 'Enterprise',
status: 'published',
version: '13.0.0.1',
updated_at: '27-03-2019 08:27'
},{
key: '2',
icon: 'http://aztechbeat.com/wp-content/uploads/2014/04/confide-app-icon.png',
name: 'Lorem Ipsum',
platform: 'ios',
type: 'Enterprise',
status: 'published',
version: '2.3.1.2',
updated_at: '27-03-2019 09:45'
},{
key: '3',
icon: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRx2Xx1-hnH16EGZHUlT06nOcfGODPoboA2TXKaBVtODto4lJtK',
name: 'Lorem Ipsum',
platform: 'ios',
type: 'Enterprise',
status: 'removed',
version: '4.1.1.0',
updated_at: '27-03-2019 09:46'
}];
class Apps extends React.Component { class Apps extends React.Component {
routes; routes;
state = {
searchText: '',
};
constructor(props) { constructor(props) {
super(props); super(props);
this.routes = props.routes; this.routes = props.routes;
}
getColumnSearchProps = (dataIndex) => ({
filterDropdown: ({
setSelectedKeys, selectedKeys, confirm, clearFilters,
}) => (
<div style={{ padding: 8 }}>
<Input
ref={node => { this.searchInput = node; }}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
style={{ width: 188, marginBottom: 8, display: 'block' }}
/>
<Button
type="primary"
onClick={() => this.handleSearch(selectedKeys, confirm)}
icon="search"
size="small"
style={{ width: 90, marginRight: 8 }}
>
Search
</Button>
<Button
onClick={() => this.handleReset(clearFilters)}
size="small"
style={{ width: 90 }}
>
Reset
</Button>
</div>
),
filterIcon: filtered => <Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} />,
onFilter: (value, record) => record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()),
onFilterDropdownVisibleChange: (visible) => {
if (visible) {
setTimeout(() => this.searchInput.select());
}
},
render: (text) => (
<Highlighter
highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
searchWords={[this.state.searchText]}
autoEscape
textToHighlight={text.toString()}
/>
),
})
handleSearch = (selectedKeys, confirm) => {
confirm();
this.setState({ searchText: selectedKeys[0] });
}
handleReset = (clearFilters) => {
clearFilters();
this.setState({ searchText: '' });
} }
render() { render() {
const columns = [{
title: '',
dataIndex: 'icon',
key: 'icon',
render: text => <Avatar size="large" src={text}/>,
}, {
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a href="javascript:;">{text}</a>,
...this.getColumnSearchProps('name'),
}, {
title: 'Platform',
dataIndex: 'platform',
key: 'platform',
}, {
title: 'Type',
dataIndex: 'type',
key: 'type',
}, {
title: 'Status',
key: 'status',
dataIndex: 'status',
render: tag => {
let color;
switch (tag) {
case 'published':
color = 'green';
break;
case 'removed':
color = 'red'
break;
case 'default':
color = 'blue'
}
return <Tag color={color} key={tag}>{tag.toUpperCase()}</Tag>;
},
}, {
title: 'Published Version',
dataIndex: 'version',
key: 'version',
}, {
title: 'Last Updated',
dataIndex: 'updated_at',
key: 'updated_at',
},{
title: 'Action',
key: 'action',
render: () => (
<span>
<a href="javascript:;">Edit</a>
<Divider type="vertical" />
<a href="javascript:;">Manage</a>
</span>
),
}];
return ( return (
<div> <div>
<PageHeader <PageHeader
breadcrumb={{routes}} breadcrumb={{routes}}
/> />
<div style={{background: '#f0f2f5', padding: 24, minHeight: 780}}> <div style={{background: '#f0f2f5', padding: 24, minHeight: 780}}>
<Row style={{padding:10}}>
<Card> <Col span={6} offset={18}>
<Row style={{padding:10}}> <Search
<Col span={6} offset={18}> placeholder="search"
<Search onSearch={value => console.log(value)}
placeholder="search" style={{ width: 200}}
onSearch={value => console.log(value)} />
style={{ width: 200}} <Button style={{margin:5}}>Advanced Search</Button>
/> </Col>
<Button style={{margin:5}}>Advanced Search</Button> </Row>
</Col> <AppList/>
</Row>
<Table columns={columns} dataSource={data}/>
</Card>
</div> </div>
</div> </div>

@ -0,0 +1,226 @@
import React from "react";
import "antd/dist/antd.css";
import {Table, Divider, Tag, Card, PageHeader, Typography, Avatar,Input, Button, Icon, Row, Col} from "antd";
import Highlighter from 'react-highlight-words';
import axios from "axios";
const Paragraph = Typography;
const Search = Input.Search;
const routes = [
{
path: 'index',
breadcrumbName: 'Publisher',
},
{
path: 'first',
breadcrumbName: 'Dashboard',
},
{
path: 'second',
breadcrumbName: 'OldApps',
},
];
class OldApps extends React.Component {
routes;
state = {
searchText: '',
};
constructor(props) {
super(props);
this.routes = props.routes;
this.state = {
data: []
};
this.loadData = this.loadData.bind(this);
}
loadData(){
const thisComponent = this;
const request = "method=post&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/applications";
axios.post('https://localhost:9443/api/application-mgt-handler/v1.0/invoke', request
).then(res => {
if(res.status === 200){
console.log(res.status);
let apps = [];
res.data['data']['applications'].forEach(function (app) {
apps.push({
key: app.id,
icon: app["applicationReleases"][0]["iconPath"],
name: app.name,
platform: 'undefined',
type: app.type,
status: 'undefined',
version: 'undefined',
updated_at: 'undefined'
});
});
thisComponent.setState({
data : apps
})
}
}).catch(function (error) {
if(error.response.status === 401){
window.location.href = 'https://localhost:9443/publisher/login';
}
});
}
componentDidMount() {
this.loadData();
}
getColumnSearchProps = (dataIndex) => ({
filterDropdown: ({
setSelectedKeys, selectedKeys, confirm, clearFilters,
}) => (
<div style={{ padding: 8 }}>
<Input
ref={node => { this.searchInput = node; }}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
style={{ width: 188, marginBottom: 8, display: 'block' }}
/>
<Button
type="primary"
onClick={() => this.handleSearch(selectedKeys, confirm)}
icon="search"
size="small"
style={{ width: 90, marginRight: 8 }}
>
Search
</Button>
<Button
onClick={() => this.handleReset(clearFilters)}
size="small"
style={{ width: 90 }}
>
Reset
</Button>
</div>
),
filterIcon: filtered => <Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} />,
onFilter: (value, record) => record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()),
onFilterDropdownVisibleChange: (visible) => {
if (visible) {
setTimeout(() => this.searchInput.select());
}
},
render: (text) => (
<Highlighter
highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
searchWords={[this.state.searchText]}
autoEscape
textToHighlight={text.toString()}
/>
),
});
handleSearch = (selectedKeys, confirm) => {
confirm();
this.setState({ searchText: selectedKeys[0] });
};
handleReset = (clearFilters) => {
clearFilters();
this.setState({ searchText: '' });
};
render() {
const columns = [{
title: '',
dataIndex: 'icon',
key: 'icon',
render: text => <Avatar size="large" src={text}/>,
}, {
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a href="javascript:;">{text}</a>,
...this.getColumnSearchProps('name'),
}, {
title: 'Platform',
dataIndex: 'platform',
key: 'platform',
}, {
title: 'Type',
dataIndex: 'type',
key: 'type',
}, {
title: 'Status',
key: 'status',
dataIndex: 'status',
render: tag => {
let color;
switch (tag) {
case 'published':
color = 'green';
break;
case 'removed':
color = 'red';
break;
case 'default':
color = 'blue';
}
return <Tag color={color} key={tag}>{tag.toUpperCase()}</Tag>;
},
}, {
title: 'Published Version',
dataIndex: 'version',
key: 'version',
}, {
title: 'Last Updated',
dataIndex: 'updated_at',
key: 'updated_at',
},{
title: 'Action',
key: 'action',
render: () => (
<span>
<a href="javascript:;">Edit</a>
<Divider type="vertical" />
<a href="javascript:;">Manage</a>
</span>
),
}];
return (
<div>
<PageHeader
breadcrumb={{routes}}
/>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 780}}>
<Card>
<Row style={{padding:10}}>
<Col span={6} offset={18}>
<Search
placeholder="search"
onSearch={value => console.log(value)}
style={{ width: 200}}
/>
<Button style={{margin:5}}>Advanced Search</Button>
</Col>
</Row>
<Table columns={columns} dataSource={this.state.data}/>
</Card>
</div>
</div>
);
}
}
export default OldApps;
Loading…
Cancel
Save