forked from community/device-mgt-core
Further integrate app management component with device mgtfeature/appm-store/pbac
parent
157641498b
commit
e0f2d1e16a
@ -0,0 +1,407 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {Card, Tag, message, Icon, Input, notification, Divider, Button, Spin, Tooltip, Popconfirm, Modal} from "antd";
|
||||||
|
import axios from "axios";
|
||||||
|
import config from "../../../../public/conf/config.json";
|
||||||
|
import {TweenOneGroup} from 'rc-tween-one';
|
||||||
|
|
||||||
|
|
||||||
|
class ManageCategories extends React.Component {
|
||||||
|
state = {
|
||||||
|
loading: false,
|
||||||
|
searchText: '',
|
||||||
|
categories: [],
|
||||||
|
tempElements: [],
|
||||||
|
inputVisible: false,
|
||||||
|
inputValue: '',
|
||||||
|
isAddNewVisible: false,
|
||||||
|
isEditModalVisible: false,
|
||||||
|
currentlyEditingId: null,
|
||||||
|
editingValue: null
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const request = "method=get&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/applications/categories";
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
let categories = JSON.parse(res.data.data);
|
||||||
|
this.setState({
|
||||||
|
categories: categories,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.status === 401) {
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCloseButton = () => {
|
||||||
|
this.setState({
|
||||||
|
tempElements: [],
|
||||||
|
isAddNewVisible: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteCategory = (id) => {
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
const request = "method=delete&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/admin/applications/categories/" + id;
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
notification["success"]({
|
||||||
|
message: "Done!",
|
||||||
|
description:
|
||||||
|
"Category Removed Successfully!",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
// this.setState({
|
||||||
|
// categories: [...categories, ...tempElements],
|
||||||
|
// tempElements: [],
|
||||||
|
// inputVisible: false,
|
||||||
|
// inputValue: '',
|
||||||
|
// loading: false,
|
||||||
|
// isAddNewVisible: false
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.hasOwnProperty("status") && error.response.status === 401) {
|
||||||
|
message.error('You are not logged in');
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderElement = (category) => {
|
||||||
|
const categoryName = category.categoryName;
|
||||||
|
const tagElem = (
|
||||||
|
<Tag
|
||||||
|
color="blue"
|
||||||
|
>
|
||||||
|
{categoryName}
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<Tooltip title="edit">
|
||||||
|
<Icon onClick={() => {
|
||||||
|
this.openEditModal(categoryName)
|
||||||
|
}} style={{color: 'rgba(0,0,0,0.45)'}} type="edit"/>
|
||||||
|
</Tooltip>
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<Tooltip title="delete">
|
||||||
|
<Popconfirm
|
||||||
|
title="Are you sure delete this category?"
|
||||||
|
onConfirm={() => {
|
||||||
|
if (category.isCategoryDeletable) {
|
||||||
|
this.deleteCategory(categoryName);
|
||||||
|
} else {
|
||||||
|
notification["error"]({
|
||||||
|
message: 'Cannot delete "' + categoryName + '"',
|
||||||
|
description:
|
||||||
|
"This category is currently used. Please unassign the category from apps.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
>
|
||||||
|
<Icon style={{color: 'rgba(0,0,0,0.45)'}} type="delete"/>
|
||||||
|
</Popconfirm>
|
||||||
|
</Tooltip>
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<span key={category.categoryName} style={{display: 'inline-block'}}>
|
||||||
|
{tagElem}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderTempElement = (category) => {
|
||||||
|
const {tempElements} = this.state;
|
||||||
|
const tagElem = (
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const remainingElements = tempElements.filter(function (value) {
|
||||||
|
|
||||||
|
return value.categoryName !== category.categoryName;
|
||||||
|
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
tempElements: remainingElements
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{category.categoryName}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<span key={category.categoryName} style={{display: 'inline-block'}}>
|
||||||
|
{tagElem}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
showInput = () => {
|
||||||
|
this.setState({inputVisible: true}, () => this.input.focus());
|
||||||
|
};
|
||||||
|
|
||||||
|
handleInputChange = e => {
|
||||||
|
this.setState({inputValue: e.target.value});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleInputConfirm = () => {
|
||||||
|
const {inputValue, categories} = this.state;
|
||||||
|
let {tempElements} = this.state;
|
||||||
|
if (inputValue) {
|
||||||
|
if ((categories.findIndex(i => i.categoryName === inputValue) === -1) && (tempElements.findIndex(i => i.categoryName === inputValue) === -1)) {
|
||||||
|
tempElements = [...tempElements, {categoryName: inputValue, isCategoryDeletable: true}];
|
||||||
|
} else {
|
||||||
|
message.warning('Category already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
tempElements,
|
||||||
|
inputVisible: false,
|
||||||
|
inputValue: '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSave = () => {
|
||||||
|
const {tempElements, categories} = this.state;
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataArray = JSON.stringify(tempElements.map(category => category.categoryName));
|
||||||
|
|
||||||
|
const request = "method=post&content-type=application/json&payload=" + dataArray + "&api-endpoint=/application-mgt-publisher/v1.0/admin/applications/categories";
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
notification["success"]({
|
||||||
|
message: "Done!",
|
||||||
|
description:
|
||||||
|
"New Categories were added successfully",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
categories: [...categories, ...tempElements],
|
||||||
|
tempElements: [],
|
||||||
|
inputVisible: false,
|
||||||
|
inputValue: '',
|
||||||
|
loading: false,
|
||||||
|
isAddNewVisible: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.hasOwnProperty("status") && error.response.status === 401) {
|
||||||
|
message.error('You are not logged in');
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
saveInputRef = input => (this.input = input);
|
||||||
|
|
||||||
|
closeEditModal = e => {
|
||||||
|
console.log(e);
|
||||||
|
this.setState({
|
||||||
|
isEditModalVisible: false,
|
||||||
|
currentlyEditingId: null
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
openEditModal = (id) => {
|
||||||
|
this.setState({
|
||||||
|
isEditModalVisible: true,
|
||||||
|
currentlyEditingId: id,
|
||||||
|
editingValue: id
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
editItem = () => {
|
||||||
|
|
||||||
|
const {editingValue, currentlyEditingId, categories} = this.state;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: true,
|
||||||
|
isEditModalVisible: false,
|
||||||
|
});
|
||||||
|
const request = "method=put&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/admin/applications/categories?from="+currentlyEditingId+"%26to="+editingValue;
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
notification["success"]({
|
||||||
|
message: "Done!",
|
||||||
|
description:
|
||||||
|
"Category was edited successfully",
|
||||||
|
});
|
||||||
|
|
||||||
|
categories[categories.findIndex(i => i.categoryName === currentlyEditingId)].categoryName = editingValue;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
categories: categories,
|
||||||
|
loading: false,
|
||||||
|
editingValue: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.hasOwnProperty("status") && error.response.status === 401) {
|
||||||
|
message.error('You are not logged in');
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
editingValue: null
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
handleEditInputChange = (e) => {
|
||||||
|
this.setState({
|
||||||
|
editingValue: e.target.value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {categories, inputVisible, inputValue, tempElements, isAddNewVisible} = this.state;
|
||||||
|
const categoriesElements = categories.map(this.renderElement);
|
||||||
|
const temporaryElements = tempElements.map(this.renderTempElement);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Card title="Categories">
|
||||||
|
<Spin tip="Working on it..." spinning={this.state.loading}>
|
||||||
|
{!isAddNewVisible &&
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({
|
||||||
|
isAddNewVisible: true,
|
||||||
|
inputVisible: true
|
||||||
|
}, () => this.input.focus())
|
||||||
|
}} htmlType="button">Add Categories
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
{isAddNewVisible &&
|
||||||
|
<div>
|
||||||
|
<div style={{marginBottom: 16}}>
|
||||||
|
<TweenOneGroup
|
||||||
|
enter={{
|
||||||
|
scale: 0.8,
|
||||||
|
opacity: 0,
|
||||||
|
type: 'from',
|
||||||
|
duration: 100,
|
||||||
|
onComplete: e => {
|
||||||
|
e.target.style = '';
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
leave={{opacity: 0, width: 0, scale: 0, duration: 200}}
|
||||||
|
appear={false}
|
||||||
|
>
|
||||||
|
{temporaryElements}
|
||||||
|
|
||||||
|
{inputVisible && (
|
||||||
|
<Input
|
||||||
|
ref={this.saveInputRef}
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
style={{width: 120}}
|
||||||
|
value={inputValue}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
onBlur={this.handleInputConfirm}
|
||||||
|
onPressEnter={this.handleInputConfirm}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!inputVisible && (
|
||||||
|
<Tag onClick={this.showInput}
|
||||||
|
style={{background: '#fff', borderStyle: 'dashed'}}>
|
||||||
|
<Icon type="plus"/> New Category
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</TweenOneGroup>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
onClick={this.handleSave}
|
||||||
|
htmlType="button" type="primary"
|
||||||
|
size="small"
|
||||||
|
disabled={tempElements.length === 0}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<Button
|
||||||
|
onClick={this.handleCloseButton}
|
||||||
|
size="small">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<Divider dashed="true"/>
|
||||||
|
<div style={{marginTop: 16}}>
|
||||||
|
<TweenOneGroup
|
||||||
|
enter={{
|
||||||
|
scale: 0.8,
|
||||||
|
opacity: 0,
|
||||||
|
type: 'from',
|
||||||
|
duration: 100,
|
||||||
|
onComplete: e => {
|
||||||
|
e.target.style = '';
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
leave={{opacity: 0, width: 0, scale: 0, duration: 200}}
|
||||||
|
appear={false}
|
||||||
|
>
|
||||||
|
{categoriesElements}
|
||||||
|
</TweenOneGroup>
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
</Card>
|
||||||
|
<Modal
|
||||||
|
title="Edit"
|
||||||
|
visible={this.state.isEditModalVisible}
|
||||||
|
onCancel={this.closeEditModal}
|
||||||
|
onOk={this.editItem}
|
||||||
|
>
|
||||||
|
<Input value={this.state.editingValue} ref={(input) => this.editingInput = input} onChange={this.handleEditInputChange}/>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ManageCategories;
|
@ -0,0 +1,407 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {Card, Tag, message, Icon, Input, notification, Divider, Button, Spin, Tooltip, Popconfirm, Modal} from "antd";
|
||||||
|
import axios from "axios";
|
||||||
|
import config from "../../../../public/conf/config.json";
|
||||||
|
import {TweenOneGroup} from 'rc-tween-one';
|
||||||
|
|
||||||
|
|
||||||
|
class ManageTags extends React.Component {
|
||||||
|
state = {
|
||||||
|
loading: false,
|
||||||
|
searchText: '',
|
||||||
|
categories: [],
|
||||||
|
tempElements: [],
|
||||||
|
inputVisible: false,
|
||||||
|
inputValue: '',
|
||||||
|
isAddNewVisible: false,
|
||||||
|
isEditModalVisible: false,
|
||||||
|
currentlyEditingId: null,
|
||||||
|
editingValue: null
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const request = "method=get&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/applications/tags";
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
let categories = JSON.parse(res.data.data);
|
||||||
|
this.setState({
|
||||||
|
categories: categories,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.status === 401) {
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCloseButton = () => {
|
||||||
|
this.setState({
|
||||||
|
tempElements: [],
|
||||||
|
isAddNewVisible: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteCategory = (id) => {
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
const request = "method=delete&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/admin/applications/categories/" + id;
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
notification["success"]({
|
||||||
|
message: "Done!",
|
||||||
|
description:
|
||||||
|
"Category Removed Successfully!",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
// this.setState({
|
||||||
|
// categories: [...categories, ...tempElements],
|
||||||
|
// tempElements: [],
|
||||||
|
// inputVisible: false,
|
||||||
|
// inputValue: '',
|
||||||
|
// loading: false,
|
||||||
|
// isAddNewVisible: false
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.hasOwnProperty("status") && error.response.status === 401) {
|
||||||
|
message.error('You are not logged in');
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderElement = (category) => {
|
||||||
|
const categoryName = category.tagName;
|
||||||
|
const tagElem = (
|
||||||
|
<Tag
|
||||||
|
color="gold"
|
||||||
|
>
|
||||||
|
{categoryName}
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<Tooltip title="edit">
|
||||||
|
<Icon onClick={() => {
|
||||||
|
this.openEditModal(categoryName)
|
||||||
|
}} style={{color: 'rgba(0,0,0,0.45)'}} type="edit"/>
|
||||||
|
</Tooltip>
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<Tooltip title="delete">
|
||||||
|
<Popconfirm
|
||||||
|
title="Are you sure delete this category?"
|
||||||
|
onConfirm={() => {
|
||||||
|
if (category.isTagDeletable) {
|
||||||
|
this.deleteCategory(categoryName);
|
||||||
|
} else {
|
||||||
|
notification["error"]({
|
||||||
|
message: 'Cannot delete "' + categoryName + '"',
|
||||||
|
description:
|
||||||
|
"This category is currently used. Please unassign the category from apps.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
>
|
||||||
|
<Icon style={{color: 'rgba(0,0,0,0.45)'}} type="delete"/>
|
||||||
|
</Popconfirm>
|
||||||
|
</Tooltip>
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<span key={category.tagName} style={{display: 'inline-block'}}>
|
||||||
|
{tagElem}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderTempElement = (category) => {
|
||||||
|
const {tempElements} = this.state;
|
||||||
|
const tagElem = (
|
||||||
|
<Tag
|
||||||
|
closable
|
||||||
|
onClose={e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const remainingElements = tempElements.filter(function (value) {
|
||||||
|
|
||||||
|
return value.categoryName !== category.categoryName;
|
||||||
|
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
tempElements: remainingElements
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{category.categoryName}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<span key={category.categoryName} style={{display: 'inline-block'}}>
|
||||||
|
{tagElem}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
showInput = () => {
|
||||||
|
this.setState({inputVisible: true}, () => this.input.focus());
|
||||||
|
};
|
||||||
|
|
||||||
|
handleInputChange = e => {
|
||||||
|
this.setState({inputValue: e.target.value});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleInputConfirm = () => {
|
||||||
|
const {inputValue, categories} = this.state;
|
||||||
|
let {tempElements} = this.state;
|
||||||
|
if (inputValue) {
|
||||||
|
if ((categories.findIndex(i => i.categoryName === inputValue) === -1) && (tempElements.findIndex(i => i.categoryName === inputValue) === -1)) {
|
||||||
|
tempElements = [...tempElements, {categoryName: inputValue, isTagDeletable: true}];
|
||||||
|
} else {
|
||||||
|
message.warning('Category already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
tempElements,
|
||||||
|
inputVisible: false,
|
||||||
|
inputValue: '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSave = () => {
|
||||||
|
const {tempElements, categories} = this.state;
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataArray = JSON.stringify(tempElements.map(category => category.categoryName));
|
||||||
|
|
||||||
|
const request = "method=post&content-type=application/json&payload=" + dataArray + "&api-endpoint=/application-mgt-publisher/v1.0/admin/applications/categories";
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
notification["success"]({
|
||||||
|
message: "Done!",
|
||||||
|
description:
|
||||||
|
"New Categories were added successfully",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
categories: [...categories, ...tempElements],
|
||||||
|
tempElements: [],
|
||||||
|
inputVisible: false,
|
||||||
|
inputValue: '',
|
||||||
|
loading: false,
|
||||||
|
isAddNewVisible: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.hasOwnProperty("status") && error.response.status === 401) {
|
||||||
|
message.error('You are not logged in');
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
saveInputRef = input => (this.input = input);
|
||||||
|
|
||||||
|
closeEditModal = e => {
|
||||||
|
console.log(e);
|
||||||
|
this.setState({
|
||||||
|
isEditModalVisible: false,
|
||||||
|
currentlyEditingId: null
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
openEditModal = (id) => {
|
||||||
|
this.setState({
|
||||||
|
isEditModalVisible: true,
|
||||||
|
currentlyEditingId: id,
|
||||||
|
editingValue: id
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
editItem = () => {
|
||||||
|
|
||||||
|
const {editingValue, currentlyEditingId, categories} = this.state;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: true,
|
||||||
|
isEditModalVisible: false,
|
||||||
|
});
|
||||||
|
const request = "method=put&content-type=application/json&payload={}&api-endpoint=/application-mgt-publisher/v1.0/admin/applications/categories?from="+currentlyEditingId+"%26to="+editingValue;
|
||||||
|
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||||
|
).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
notification["success"]({
|
||||||
|
message: "Done!",
|
||||||
|
description:
|
||||||
|
"Category was edited successfully",
|
||||||
|
});
|
||||||
|
|
||||||
|
categories[categories.findIndex(i => i.categoryName === currentlyEditingId)].categoryName = editingValue;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
categories: categories,
|
||||||
|
loading: false,
|
||||||
|
editingValue: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response.hasOwnProperty("status") && error.response.status === 401) {
|
||||||
|
message.error('You are not logged in');
|
||||||
|
window.location.href = 'https://localhost:9443/publisher/login';
|
||||||
|
} else {
|
||||||
|
message.warning('Something went wrong');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
editingValue: null
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
handleEditInputChange = (e) => {
|
||||||
|
this.setState({
|
||||||
|
editingValue: e.target.value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {categories, inputVisible, inputValue, tempElements, isAddNewVisible} = this.state;
|
||||||
|
const categoriesElements = categories.map(this.renderElement);
|
||||||
|
const temporaryElements = tempElements.map(this.renderTempElement);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Card title="Tags">
|
||||||
|
<Spin tip="Working on it..." spinning={this.state.loading}>
|
||||||
|
{!isAddNewVisible &&
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({
|
||||||
|
isAddNewVisible: true,
|
||||||
|
inputVisible: true
|
||||||
|
}, () => this.input.focus())
|
||||||
|
}} htmlType="button">Add Tags
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
{isAddNewVisible &&
|
||||||
|
<div>
|
||||||
|
<div style={{marginBottom: 16}}>
|
||||||
|
<TweenOneGroup
|
||||||
|
enter={{
|
||||||
|
scale: 0.8,
|
||||||
|
opacity: 0,
|
||||||
|
type: 'from',
|
||||||
|
duration: 100,
|
||||||
|
onComplete: e => {
|
||||||
|
e.target.style = '';
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
leave={{opacity: 0, width: 0, scale: 0, duration: 200}}
|
||||||
|
appear={false}
|
||||||
|
>
|
||||||
|
{temporaryElements}
|
||||||
|
|
||||||
|
{inputVisible && (
|
||||||
|
<Input
|
||||||
|
ref={this.saveInputRef}
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
style={{width: 120}}
|
||||||
|
value={inputValue}
|
||||||
|
onChange={this.handleInputChange}
|
||||||
|
onBlur={this.handleInputConfirm}
|
||||||
|
onPressEnter={this.handleInputConfirm}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!inputVisible && (
|
||||||
|
<Tag onClick={this.showInput}
|
||||||
|
style={{background: '#fff', borderStyle: 'dashed'}}>
|
||||||
|
<Icon type="plus"/> New Category
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</TweenOneGroup>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
onClick={this.handleSave}
|
||||||
|
htmlType="button" type="primary"
|
||||||
|
size="small"
|
||||||
|
disabled={tempElements.length === 0}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<Button
|
||||||
|
onClick={this.handleCloseButton}
|
||||||
|
size="small">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<Divider dashed="true"/>
|
||||||
|
<div style={{marginTop: 16}}>
|
||||||
|
<TweenOneGroup
|
||||||
|
enter={{
|
||||||
|
scale: 0.8,
|
||||||
|
opacity: 0,
|
||||||
|
type: 'from',
|
||||||
|
duration: 100,
|
||||||
|
onComplete: e => {
|
||||||
|
e.target.style = '';
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
leave={{opacity: 0, width: 0, scale: 0, duration: 200}}
|
||||||
|
appear={false}
|
||||||
|
>
|
||||||
|
{categoriesElements}
|
||||||
|
</TweenOneGroup>
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
</Card>
|
||||||
|
<Modal
|
||||||
|
title="Edit"
|
||||||
|
visible={this.state.isEditModalVisible}
|
||||||
|
onCancel={this.closeEditModal}
|
||||||
|
onOk={this.editItem}
|
||||||
|
>
|
||||||
|
<Input value={this.state.editingValue} ref={(input) => this.editingInput = input} onChange={this.handleEditInputChange}/>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ManageTags;
|
@ -1,226 +0,0 @@
|
|||||||
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;
|
|
@ -0,0 +1,62 @@
|
|||||||
|
import React from "react";
|
||||||
|
import "antd/dist/antd.css";
|
||||||
|
import {PageHeader, Typography, Input, Button, Row, Col} from "antd";
|
||||||
|
import ManageCategories from "../../../components/manage/categories/ManageCategories";
|
||||||
|
import ManageTags from "../../../components/manage/categories/ManageTags";
|
||||||
|
|
||||||
|
const {Paragraph} = Typography;
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
breadcrumbName: 'Publisher',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'first',
|
||||||
|
breadcrumbName: 'Dashboard',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'second',
|
||||||
|
breadcrumbName: 'Manage',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
class Manage extends React.Component {
|
||||||
|
routes;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.routes = props.routes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PageHeader
|
||||||
|
breadcrumb={{routes}}
|
||||||
|
title = "Manage"
|
||||||
|
>
|
||||||
|
<div className="wrap">
|
||||||
|
<div className="content">
|
||||||
|
<Paragraph>
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempo.
|
||||||
|
</Paragraph>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PageHeader>
|
||||||
|
<div style={{background: '#f0f2f5', padding: 24, minHeight: 780}}>
|
||||||
|
<ManageCategories/>
|
||||||
|
<br/>
|
||||||
|
<ManageTags/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Manage;
|
Loading…
Reference in new issue