diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json index dece5f9363..dbba25e052 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json @@ -39,7 +39,8 @@ "redux-thunk": "^2.3.0", "shade-blend-color": "^1.0.0", "storm-react-diagrams": "^5.2.1", - "typescript": "^3.6.4" + "typescript": "^3.6.4", + "lodash.debounce": "latest" }, "devDependencies": { "@babel/core": "^7.5.0", diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/detailed-rating/DetailedRating.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/detailed-rating/DetailedRating.js index 2ef88827be..dba024f2ed 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/detailed-rating/DetailedRating.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/detailed-rating/DetailedRating.js @@ -61,7 +61,7 @@ class DetailedRating extends React.Component{ } }).catch(function (error) { - handleApiError(error, "Error occurred while trying to load rating for the release."); + handleApiError(error, "Error occurred while trying to load rating for the release.", true); }); }; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js index fc54ab399b..7eaea07d32 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js @@ -136,7 +136,7 @@ class AppDetailsDrawer extends React.Component { } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load app details."); + handleApiError(error, "Error occurred while trying to load categories.", true); this.setState({ loading: false }); @@ -509,8 +509,8 @@ class AppDetailsDrawer extends React.Component { title="Published" style={{ backgroundColor: '#52c41a', - borderRadius:"50%", - color:"white" + borderRadius: "50%", + color: "white" }} count={ - {/*display add new release only if app type is enterprise*/} {(app.type === "ENTERPRISE") && (
+
Add new release for the application diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/Filters.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/Filters.js index e042def20d..14c76e24a7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/Filters.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/Filters.js @@ -30,7 +30,7 @@ import { Form, message, Radio, - notification + notification, Alert } from "antd"; import axios from "axios"; import {withConfigContext} from "../../../context/ConfigContext"; @@ -46,7 +46,12 @@ class FiltersForm extends React.Component { this.state = { categories: [], tags: [], - deviceTypes: [] + deviceTypes: [], + forbiddenErrors: { + categories: false, + tags: false, + deviceTypes: false + } }; } @@ -59,11 +64,11 @@ class FiltersForm extends React.Component { } } - if(values.hasOwnProperty("deviceType") && values.deviceType==="ALL"){ + if (values.hasOwnProperty("deviceType") && values.deviceType === "ALL") { delete values["deviceType"]; } - if(values.hasOwnProperty("appType") && values.appType==="ALL"){ + if (values.hasOwnProperty("appType") && values.appType === "ALL") { delete values["appType"]; } @@ -73,16 +78,17 @@ class FiltersForm extends React.Component { componentDidMount() { this.getCategories(); + this.getTags(); + this.getDeviceTypes(); } getCategories = () => { const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories" + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories" ).then(res => { if (res.status === 200) { let categories = JSON.parse(res.data.data); - this.getTags(); this.setState({ categories: categories, loading: false @@ -90,21 +96,29 @@ class FiltersForm extends React.Component { } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load categories."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load categories.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.categories = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; getTags = () => { const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags" + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags" ).then(res => { if (res.status === 200) { let tags = JSON.parse(res.data.data); - this.getDeviceTypes(); this.setState({ tags: tags, loading: false, @@ -112,10 +126,19 @@ class FiltersForm extends React.Component { } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load tags."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load tags.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.tags = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; @@ -123,7 +146,7 @@ class FiltersForm extends React.Component { getDeviceTypes = () => { const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt + "/device-types" + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt + "/device-types" ).then(res => { if (res.status === 200) { const deviceTypes = JSON.parse(res.data.data); @@ -134,15 +157,24 @@ class FiltersForm extends React.Component { } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load device types."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load device types.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.deviceTypes = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; render() { - const {categories, tags, deviceTypes} = this.state; + const {categories, tags, deviceTypes, forbiddenErrors} = this.state; const {getFieldDecorator} = this.props.form; return ( @@ -170,7 +202,13 @@ class FiltersForm extends React.Component { - + {(forbiddenErrors.categories) && ( + + )} {getFieldDecorator('categories', { rules: [{ @@ -182,8 +220,7 @@ class FiltersForm extends React.Component { mode="multiple" style={{width: '100%'}} placeholder="Select a Category" - onChange={this.handleCategoryChange} - > + onChange={this.handleCategoryChange}> { categories.map(category => { return ( @@ -198,7 +235,13 @@ class FiltersForm extends React.Component { )} - + {(forbiddenErrors.deviceTypes) && ( + + )} {getFieldDecorator('deviceType', { rules: [{ @@ -208,8 +251,7 @@ class FiltersForm extends React.Component { })( )} - + {(forbiddenErrors.tags) && ( + + )} {getFieldDecorator('tags', { rules: [{ diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js index d008cf5609..01d6c8c159 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js @@ -17,7 +17,7 @@ */ import React from "react"; -import {Avatar, Table, Tag, Icon, message, notification, Col, Badge} from "antd"; +import {Avatar, Table, Tag, Icon, message, notification, Col, Badge, Alert} from "antd"; import axios from "axios"; import pSBC from 'shade-blend-color'; import "./AppsTable.css"; @@ -58,7 +58,7 @@ const columns = [ avatar = (hasPublishedRelease) ? ( @@ -74,7 +74,6 @@ const columns = [ ) : ( { - handleApiError(error, "Error occurred while trying to load apps."); + handleApiError(error, "Error occurred while trying to load apps.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + this.setState({ + isForbiddenErrorVisible: true + }) + } this.setState({loading: false}); }); }; @@ -256,29 +261,37 @@ class AppsTable extends React.Component { render() { const {isDrawerVisible, loading} = this.state; return ( -
- record.id} - dataSource={this.state.apps} - columns={columns} - pagination={this.state.pagination} - onChange={this.handleTableChange} - rowClassName="app-row" - loading={loading} - onRow={(record, rowIndex) => { - return { - onClick: event => { - this.showDrawer(record, rowIndex); - }, - }; - }}/> - +
+ {(this.state.isForbiddenErrorVisible) && ( + + )} +
+
record.id} + dataSource={this.state.apps} + columns={columns} + pagination={this.state.pagination} + onChange={this.handleTableChange} + rowClassName="app-row" + loading={loading} + onRow={(record, rowIndex) => { + return { + onClick: event => { + this.showDrawer(record, rowIndex); + }, + }; + }}/> + + - ); } } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js index 0c208c776b..6ea67eee20 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js @@ -24,6 +24,7 @@ import "../../../App.css"; import DetailedRating from "../detailed-rating/DetailedRating"; import EditRelease from "./edit-release/EditRelease"; import {withConfigContext} from "../../../context/ConfigContext"; +import NewAppUploadForm from "../../new-app/subForms/NewAppUploadForm"; const {Title, Text, Paragraph} = Typography; @@ -97,6 +98,7 @@ class ReleaseView extends React.Component { Version : {release.version}
{(config.deviceTypes.mobileTypes.includes(deviceType)) && ( - - {getFieldDecorator('supportedOS')( -
- - -
- - {getFieldDecorator('lowerOsVersion', { - rules: [{ - required: true, - message: 'Please select Value' - }], - })( - - )} - - - -

-

- - - - {getFieldDecorator('upperOsVersion', { - rules: [{ - required: true, - message: 'Please select Value' - }], - })( - - )} - - - - - - +
+ {(this.props.forbiddenErrors.supportedOsVersions) && ( + )} - + + {getFieldDecorator('supportedOS')( +
+ + +
+ + {getFieldDecorator('lowerOsVersion', { + rules: [{ + required: true, + message: 'Please select Value' + }], + })( + + )} + + + +

-

+ + + + {getFieldDecorator('upperOsVersion', { + rules: [{ + required: true, + message: 'Please select Value' + }], + })( + + )} + + + + + + + )} + + )} {getFieldDecorator('meta', { diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/review/Reviews.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/review/Reviews.js index 0e75a3d663..53aa43d298 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/review/Reviews.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/review/Reviews.js @@ -17,7 +17,7 @@ */ import React from "react"; -import {List, message, Avatar, Spin, Button, notification} from 'antd'; +import {List, message, Avatar, Spin, Button, notification, Alert} from 'antd'; import "./Reviews.css"; import InfiniteScroll from 'react-infinite-scroller'; @@ -33,7 +33,10 @@ class Reviews extends React.Component { data: [], loading: false, hasMore: false, - loadMore: false + loadMore: false, + forbiddenErrors: { + reviews: false + } }; @@ -49,17 +52,34 @@ class Reviews extends React.Component { const config = this.props.context; const {uuid, type} = this.props; - + this.setState({ + loading: true + }); axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/reviews/" + type + "/" + uuid + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.publisher + + "/admin/reviews/" + type + "/" + uuid ).then(res => { if (res.status === 200) { let reviews = res.data.data.data; callback(reviews); } - }).catch(function (error) { - handleApiError(error, "Error occurred while trying to load reviews."); + }).catch((error) => { + handleApiError(error, "Error occurred while trying to load reviews.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.reviews = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; @@ -101,32 +121,39 @@ class Reviews extends React.Component { render() { return ( -
- - ( - - - - )} - > - {this.state.loading && this.state.hasMore && ( -
- -
- )} -
-
- {!this.state.loadMore && (this.state.data.length >= limit) && (
- -
)} +
+ {(this.state.forbiddenErrors.reviews) && ( + + )} +
+ + ( + + + + )}> + {this.state.loading && this.state.hasMore && ( +
+ +
+ )} +
+
+ {!this.state.loadMore && (this.state.data.length >= limit) && (
+ +
)} +
); } diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageCategories.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageCategories.js index 984cd5d67d..a4de159263 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageCategories.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageCategories.js @@ -32,7 +32,7 @@ import { Modal, Row, Col, - Typography + Typography, Alert } from "antd"; import axios from "axios"; import {TweenOneGroup} from 'rc-tween-one'; @@ -53,13 +53,16 @@ class ManageCategories extends React.Component { isAddNewVisible: false, isEditModalVisible: false, currentlyEditingId: null, - editingValue: null + editingValue: null, + forbiddenErrors: { + categories: false + } }; componentDidMount() { const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories", + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories", ).then(res => { if (res.status === 200) { let categories = JSON.parse(res.data.data); @@ -70,10 +73,19 @@ class ManageCategories extends React.Component { } }).catch((error) => { - handleApiError(error, "Error occured while trying to load categories"); - this.setState({ - loading: false - }); + handleApiError(error, "Error occured while trying to load categories", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.categories = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); } @@ -90,7 +102,7 @@ class ManageCategories extends React.Component { loading: true }); axios.delete( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/categories/" + id, + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/categories/" + id, ).then(res => { if (res.status === 200) { notification["success"]({ @@ -125,8 +137,7 @@ class ManageCategories extends React.Component { const tagElem = ( + style={{marginTop: 8}}> {categoryName} @@ -150,8 +161,7 @@ class ManageCategories extends React.Component { } }} okText="Yes" - cancelText="No" - > + cancelText="No"> @@ -168,7 +178,7 @@ class ManageCategories extends React.Component { const config = this.props.context; const tagElem = ( { e.preventDefault(); @@ -229,7 +239,7 @@ class ManageCategories extends React.Component { const data = tempElements.map(category => category.categoryName); axios.post( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/categories", + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/categories", data, ).then(res => { if (res.status === 200) { @@ -287,7 +297,7 @@ class ManageCategories extends React.Component { }); axios.put( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/categories/rename?from=" + currentlyEditingId + "&to=" + editingValue, + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/categories/rename?from=" + currentlyEditingId + "&to=" + editingValue, {}, ).then(res => { if (res.status === 200) { @@ -324,11 +334,18 @@ class ManageCategories extends React.Component { }; render() { - const {categories, inputVisible, inputValue, tempElements, isAddNewVisible} = this.state; + const {categories, inputVisible, inputValue, tempElements, isAddNewVisible, forbiddenErrors} = this.state; const categoriesElements = categories.map(this.renderElement); const temporaryElements = tempElements.map(this.renderTempElement); return (
+ {(forbiddenErrors.categories) && ( + + )} diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageTags.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageTags.js index 69c269bc17..8b9ed800b1 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageTags.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/manage/categories/ManageTags.js @@ -31,7 +31,7 @@ import { Popconfirm, Modal, Row, Col, - Typography + Typography, Alert } from "antd"; import axios from "axios"; import {TweenOneGroup} from 'rc-tween-one'; @@ -51,13 +51,16 @@ class ManageTags extends React.Component { isAddNewVisible: false, isEditModalVisible: false, currentlyEditingId: null, - editingValue: null + editingValue: null, + forbiddenErrors: { + tags: false + } }; componentDidMount() { const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags", + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags", ).then(res => { if (res.status === 200) { let tags = JSON.parse(res.data.data); @@ -68,10 +71,19 @@ class ManageTags extends React.Component { } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load tags."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load tags.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.tags = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); } @@ -90,7 +102,7 @@ class ManageTags extends React.Component { }); axios.delete( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/tags/" + id + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/admin/applications/tags/" + id ).then(res => { if (res.status === 200) { notification["success"]({ @@ -124,7 +136,7 @@ class ManageTags extends React.Component { const tagElem = ( {tagName} @@ -167,7 +179,7 @@ class ManageTags extends React.Component { const {tempElements} = this.state; const tagElem = ( { e.preventDefault(); @@ -226,7 +238,7 @@ class ManageTags extends React.Component { const data = tempElements.map(tag => tag.tagName); - axios.post(window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags", + axios.post(window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags", data, ).then(res => { if (res.status === 200) { @@ -284,7 +296,7 @@ class ManageTags extends React.Component { }); axios.put( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags/rename?from=" + currentlyEditingId + "&to=" + editingValue, + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags/rename?from=" + currentlyEditingId + "&to=" + editingValue, {}, ).then(res => { if (res.status === 200) { @@ -321,11 +333,18 @@ class ManageTags extends React.Component { }; render() { - const {tags, inputVisible, inputValue, tempElements, isAddNewVisible} = this.state; + const {tags, inputVisible, inputValue, tempElements, isAddNewVisible, forbiddenErrors} = this.state; const tagsElements = tags.map(this.renderElement); const temporaryElements = tempElements.map(this.renderTempElement); return (
+ {(forbiddenErrors.tags) && ( + + )} @@ -365,8 +384,7 @@ class ManageTags extends React.Component { }, }} leave={{opacity: 0, width: 0, scale: 0, duration: 200}} - appear={false} - > + appear={false}> {temporaryElements} {inputVisible && ( diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/AddNewAppForm.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/AddNewAppForm.js index 340d28aa93..39dc99ddb1 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/AddNewAppForm.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/AddNewAppForm.js @@ -55,7 +55,10 @@ class AddNewAppFormComponent extends React.Component { isError: false, deviceType: null, supportedOsVersions: [], - errorText: "" + errorText: "", + forbiddenErrors: { + supportedOsVersions: false + } }; } @@ -143,15 +146,24 @@ class AddNewAppFormComponent extends React.Component { }); } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load supported OS versions."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load supported OS versions.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.supportedOsVersions = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; render() { - const {loading, current, isError, supportedOsVersions, errorText} = this.state; + const {loading, current, isError, supportedOsVersions, errorText, forbiddenErrors} = this.state; const {formConfig} = this.props; return (
@@ -171,6 +183,7 @@ class AddNewAppFormComponent extends React.Component {
{ e.preventDefault(); const {formConfig} = this.props; @@ -58,13 +68,17 @@ class NewAppDetailsForm extends React.Component { this.setState({ loading: true }); - const {name, description, categories, tags, price, isSharedWithAllTenants, binaryFile, icon, screenshots, releaseDescription, releaseType} = values; + const {name, description, categories, tags, unrestrictedRoles} = values; + const unrestrictedRolesData = []; + unrestrictedRoles.map(val => { + unrestrictedRolesData.push(val.key); + }); const application = { name, description, categories, tags, - unrestrictedRoles: [], + unrestrictedRoles: unrestrictedRolesData, }; if (formConfig.installationType !== "WEB_CLIP") { @@ -81,6 +95,8 @@ class NewAppDetailsForm extends React.Component { componentDidMount() { this.getCategories(); + this.getTags(); + this.getDeviceTypes(); } getCategories = () => { @@ -95,13 +111,20 @@ class NewAppDetailsForm extends React.Component { loading: false }); } - this.getTags(); - }).catch((error) => { - handleApiError(error, "Error occurred while trying to load categories."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load categories.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.categories = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; @@ -117,13 +140,20 @@ class NewAppDetailsForm extends React.Component { loading: false, }); } - this.getDeviceTypes(); - }).catch((error) => { - handleApiError(error, "Error occurred while trying to load tags."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load tags.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.tags = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } }); }; @@ -141,15 +171,15 @@ class NewAppDetailsForm extends React.Component { const allowedDeviceTypes = []; // exclude mobile device types if installation type is custom - if(installationType==="CUSTOM"){ - allDeviceTypes.forEach(deviceType=>{ - if(!mobileDeviceTypes.includes(deviceType.name)){ + if (installationType === "CUSTOM") { + allDeviceTypes.forEach(deviceType => { + if (!mobileDeviceTypes.includes(deviceType.name)) { allowedDeviceTypes.push(deviceType); } }); - }else{ - allDeviceTypes.forEach(deviceType=>{ - if(mobileDeviceTypes.includes(deviceType.name)){ + } else { + allDeviceTypes.forEach(deviceType => { + if (mobileDeviceTypes.includes(deviceType.name)) { allowedDeviceTypes.push(deviceType); } }); @@ -161,16 +191,76 @@ class NewAppDetailsForm extends React.Component { }); } }).catch((error) => { - handleApiError(error, "Error occurred while trying to load device types."); - this.setState({ - loading: false - }); + handleApiError(error, "Error occurred while trying to load device types.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.deviceTypes = true; + this.setState({ + forbiddenErrors, + loading: false + }) + } else { + this.setState({ + loading: false + }); + } + }); + }; + + fetchRoles = value => { + const config = this.props.context; + this.lastFetchId += 1; + const fetchId = this.lastFetchId; + this.setState({data: [], fetching: true}); + + axios.get( + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt + "/roles?filter=" + value, + ).then(res => { + if (res.status === 200) { + if (fetchId !== this.lastFetchId) { + // for fetch callback order + return; + } + + const data = res.data.data.roles.map(role => ({ + text: role, + value: role, + })); + + this.setState({ + unrestrictedRoles: data, + fetching: false + }); + } + + }).catch((error) => { + handleApiError(error, "Error occurred while trying to load roles.", true); + if (error.hasOwnProperty("response") && error.response.status === 403) { + const {forbiddenErrors} = this.state; + forbiddenErrors.roles = true; + this.setState({ + forbiddenErrors, + fetching: false + }) + } else { + this.setState({ + fetching: false + }); + } + }); + }; + + handleRoleSearch = roleSearchValue => { + this.setState({ + roleSearchValue, + unrestrictedRoles: [], + fetching: false, }); }; render() { const {formConfig} = this.props; - const {categories, tags, deviceTypes} = this.state; + const {categories, tags, deviceTypes, fetching, roleSearchValue, unrestrictedRoles, forbiddenErrors} = this.state; const {getFieldDecorator} = this.props.form; return ( @@ -185,34 +275,41 @@ class NewAppDetailsForm extends React.Component { layout="horizontal" onSubmit={this.handleSubmit}> {formConfig.installationType !== "WEB_CLIP" && ( - - {getFieldDecorator('deviceType', { - rules: [ +
+ {(forbiddenErrors.deviceTypes) && ( + + )} + + {getFieldDecorator('deviceType', { + rules: [ + { + required: true, + message: 'Please select device type' + } + ], + } + )( + - { - deviceTypes.map(deviceType => { - return ( - - ) - }) - } - - )} - + + )} + +
)} {/*app name*/} @@ -238,6 +335,43 @@ class NewAppDetailsForm extends React.Component {