Merge branch 'wso2-application-mgt' into application-mgt

feature/appm-store/pbac
sinthuja 7 years ago
commit 251fba7830

@ -57,5 +57,6 @@
"Yes" : "Yes", "Yes" : "Yes",
"No" : "No", "No" : "No",
"No.Platform.Tags" : "No Platform Tags", "No.Platform.Tags" : "No Platform Tags",
"Create.Platform" : "Create Platform" "Create.Platform" : "Create Platform",
"Optional": "Optional"
} }

@ -316,10 +316,6 @@ body {
background-color: #E64A19; background-color: #E64A19;
} }
#app-main-content {
margin: 0 auto;
}
#sub-title-container { #sub-title-container {
height: 100px; height: 100px;
padding: 50px 0 20px 0; padding: 50px 0 20px 0;
@ -332,32 +328,13 @@ body {
} }
/* Holds the app publisher pages. */ /* Holds the app publisher pages. */
#application-content { .publisher-card {
height: auto; height: auto;
background-color: white; background-color: white;
width: 100%;
box-shadow: 2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); box-shadow: 2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
padding: 24px; padding: 24px;
} }
.stepper-header {
width: 100%;
color: #BaBaBa;
padding-bottom: 5px;
margin-bottom: 10px;
}
#application-tag {
margin: 0 2px 0 2px;
background-color: blue;
height: 20px;
}
#application-tag:hover {
cursor: pointer;
background-color: #007bff;
}
.platform-link-placeholder { .platform-link-placeholder {
color: #888888; color: #888888;
float: right; float: right;
@ -368,7 +345,7 @@ body {
margin-right: 4px; margin-right: 4px;
} }
#application-list { .application-list {
transition: margin-right .5s; transition: margin-right .5s;
} }
@ -489,14 +466,18 @@ body {
#modal-body-content { #modal-body-content {
max-height: 700px; max-height: 700px;
padding-left: 24px;
overflow-y: auto; overflow-y: auto;
} }
.step-index { .custom-footer {
height: 20px; justify-content: inherit !important;
width: 20px; margin: 0 !important;
background-color: #2196F3; }
border-radius: 50%;
.footer-main-btn {
display: flex;
justify-content: flex-end;
} }
#img-btn-screenshot { #img-btn-screenshot {
@ -504,11 +485,20 @@ body {
} }
#app-create-modal { #app-create-modal {
max-width: 700px; max-width: 850px;
overflow-x: auto;
border-radius: 0% !important; border-radius: 0% !important;
} }
.app-create-modal-header {
background-color: #4353bd;
color: white;
padding: 24px !important;
}
.app-create-modal-content {
padding: 0 !important;
}
#store { #store {
border: none; border: none;
border-bottom: solid #BDBDBD 1px; border-bottom: solid #BDBDBD 1px;
@ -532,7 +522,7 @@ body {
float: left; float: left;
} }
#app-release-switch-switch { #app-release-switch {
position: absolute; position: absolute;
right: 10px; right: 10px;
} }
@ -838,3 +828,39 @@ div.tab button.active {
.data-table-row-cell { .data-table-row-cell {
padding-top: 14px; padding-top: 14px;
} }
.error-code {
text-align: center;
font-family: Roboto-Medium;
font-weight: 800;
font-size: 15em;
color: #BaBaBa;
}
.error-code p {
}
.error-text {
text-align: center;
font-family: Roboto-Regular;
font-size: 14px;
font-weight: 500;
color: #9e9e9e;
}
/**
If you need to change the color of active steps in stepper,
uncomment the following and set the background color and font color as needed.
*/
/*
.stepper-active-index {
background-color: #0a6eff !important;
color: white !important;
}
.stepper-passed-index {
background-color: #0a6eff !important;
color: green !important;
}
*/

@ -78,7 +78,7 @@ class Base extends Component {
<Route exact path={"/assets/platforms"} component={PlatformListing}/> <Route exact path={"/assets/platforms"} component={PlatformListing}/>
<Route exact path={"/assets/platforms/create"} component={PlatformCreate}/> <Route exact path={"/assets/platforms/create"} component={PlatformCreate}/>
{/*<Route exact path={"/assets/apps/:app"}/>*/} {/*<Route exact path={"/assets/apps/:app"}/>*/}
<Route exact path={"/assets/apps/edit/:app"} component={ApplicationEdit}/> <Route exact path={"/assets/apps/:app/edit"} component={ApplicationEdit}/>
<Route exact path={"/assets/platforms/:platform"}/> <Route exact path={"/assets/platforms/:platform"}/>
<Route exact path={"/assets/platforms/:platform/edit"}/> <Route exact path={"/assets/platforms/:platform/edit"}/>
<Route exact path={"/assets/reviews"}/> <Route exact path={"/assets/reviews"}/>

@ -61,8 +61,12 @@ export default class ApplicationMgtApi {
/** /**
* Method to handle application release process. * Method to handle application release process.
* */ * */
static releaseApplication(appId) { static releaseApplication(appId, applicationRelease, file) {
let release = new FormData();
release.append('applicationRelease', applicationRelease);
release.append('binaryFile', file);
const headers = AuthHandler.createAuthenticationHeaders("multipart/form-data");
return Axios.post(Constants.appManagerEndpoints.APP_RELEASE + appId, release, {headers: headers});
} }
/** /**
@ -73,7 +77,8 @@ export default class ApplicationMgtApi {
* URL Pattern : /application/1.0/ * URL Pattern : /application/1.0/
* */ * */
static updateLifeCycleState(appId, nextState) { static updateLifeCycleState(appId, nextState) {
const headers = AuthHandler.createAuthenticationHeaders("application/json");
return Axios.put(Constants.appManagerEndpoints.GET_ALL_APPS + appId + "/lifecycle?state=" + nextState, {headers: headers});
} }
/** /**
@ -81,6 +86,8 @@ export default class ApplicationMgtApi {
* @param appId: The application uuid. * @param appId: The application uuid.
*/ */
static getNextLifeCycleState(appId) { static getNextLifeCycleState(appId) {
const headers = AuthHandler.createAuthenticationHeaders("application/json");
return Axios.get(Constants.appManagerEndpoints.GET_ALL_APPS + appId + "/lifecycle", {headers: headers});
} }

@ -32,20 +32,29 @@ class Constants {
} }
load() { load() {
let applicationApiContext = '/api/application-mgt/v1.0/applications/1.0.0/';
let platformApiContext = '/api/application-mgt/v1.0/platforms/1.0.0';
let apiBaseUrl = 'https://' + Configuration.serverConfig.hostname + ':' + Configuration.serverConfig.apiPort; let apiBaseUrl = 'https://' + Configuration.serverConfig.hostname + ':' + Configuration.serverConfig.apiPort;
let httpBaseUrl = 'https://' + Configuration.serverConfig.hostname + ':' + Configuration.serverConfig.httpsPort; let httpBaseUrl = 'https://' + Configuration.serverConfig.hostname + ':' + Configuration.serverConfig.httpsPort;
this.appManagerEndpoints = { this.appManagerEndpoints = {
GET_ALL_APPS: apiBaseUrl + '/api/application-mgt/v1.0/applications/1.0.0/', GET_ALL_APPS: apiBaseUrl + applicationApiContext,
CREATE_APP: apiBaseUrl + '/api/application-mgt/v1.0/applications/1.0.0/', CREATE_APP: apiBaseUrl + applicationApiContext,
UPLOAD_IMAGE_ARTIFACTS: apiBaseUrl + '/api/application-mgt/v1.0/applications/1.0.0/upload-image-artifacts/', //+appId UPLOAD_IMAGE_ARTIFACTS: apiBaseUrl + applicationApiContext + 'upload-image-artifacts/', //+appId
GET_IMAGE_ARTIFACTS: apiBaseUrl + '/api/application-mgt/v1.0/applications/1.0.0/image-artifacts/' GET_IMAGE_ARTIFACTS: apiBaseUrl + applicationApiContext + 'image-artifacts/',
APP_RELEASE: apiBaseUrl + applicationApiContext + "release/", //+uuid
GET_APP_RELEASE_ARTIFACTS: apiBaseUrl + applicationApiContext + "/release-artifacts/", //+AppId/version
GET_NEXT_LIFECYCLE_STATE: apiBaseUrl + applicationApiContext //+ [uuid]/lifecycle
}; };
this.platformManagerEndpoints = { this.platformManagerEndpoints = {
CREATE_PLATFORM: apiBaseUrl + '/api/application-mgt/v1.0/platforms/1.0.0', CREATE_PLATFORM: apiBaseUrl + platformApiContext,
GET_ENABLED_PLATFORMS: apiBaseUrl + '/api/application-mgt/v1.0/platforms/1.0.0?status=ENABLED', GET_ENABLED_PLATFORMS: apiBaseUrl + platformApiContext + '?status=ENABLED',
GET_PLATFORM: apiBaseUrl + '/api/application-mgt/v1.0/platforms/1.0.0/' GET_PLATFORM: apiBaseUrl + platformApiContext, //+platformId
GET_PLATFORMS: apiBaseUrl + platformApiContext,
UPDATE_STATUS: apiBaseUrl + platformApiContext + "update-status/", // + platformId + ?status=
EDIT_PLATFORM: apiBaseUrl + platformApiContext //+platformId
}; };
this.userConstants = { this.userConstants = {

@ -182,19 +182,18 @@ class ApplicationListing extends Component {
onRowClick(uuid) { onRowClick(uuid) {
let selectedApp = this.getSelectedApplication(uuid); let selectedApp = this.getSelectedApplication(uuid);
let style = { let style = {
width: '550px', width: '35%'
marginLeft: '550px'
}; };
let appListStyle = { let appListStyle = {
marginRight: '550px', marginRight: '35%',
}; };
this.setState({drawer: style, appListStyle: appListStyle, application: selectedApp[0]}); this.setState({drawer: style, appListStyle: appListStyle, application: selectedApp[0]});
} }
onAppEditClick(uuid) { onAppEditClick(uuid) {
this.props.history.push("apps/edit/" + uuid); this.props.history.push("apps/" + uuid + "/edit");
} }
closeDrawer() { closeDrawer() {
@ -217,38 +216,53 @@ class ApplicationListing extends Component {
render() { render() {
//TODO: Move this to a data table component. //TODO: Move this to a data table component.
console.log(this.state.appListStyle);
return ( return (
<div id="application-list" style={this.state.appListStyle}> <div className="publisher-card application-list" style={this.state.appListStyle}>
<Row className="app-list-table-header"> <Row className="app-list-table-header">
{this.headers.map(header => { {this.headers.map(header => {
if (header.data_id === "applicationName") { if (header.data_id === "applicationName") {
return ( return (
<Col xs="5">{header.label}</Col>) <Col key={Math.random()} xs="4">{header.label}</Col>)
} else if (header.data_id === "image") { } else if (header.data_id === "image") {
return (<Col xs="1">{header.label}</Col>) return (<Col key={Math.random()} xs="1">{header.label}</Col>)
} else if (header.data_id === "edit") {
return <Col key={Math.random()} xs="1"></Col>
} }
return (<Col>{header.label}</Col>) return (<Col key={Math.random()}>{header.label}</Col>)
})} })}
</Row> </Row>
<hr/> <hr/>
{this.state.searchedApplications.map(application => { {this.state.searchedApplications.map(application => {
return ( return (
<Row className="app-table-row" onClick={() => { <Row key={application.uuid} className="app-table-row" onClick={() => {
this.onRowClick(application.uuid) this.onRowClick(application.uuid)
}}> }}>
<Col xs="1"> <Col key={Math.random()} xs="1">
<img <img
className="app-list-icon" className="app-list-icon"
src={application.icon} src={application.icon}
/> />
</Col> </Col>
<Col xs="5" className="data-table-row-cell"><strong>{application.name}</strong></Col>
<Col className="data-table-row-cell">{application.platform.name}</Col>
<Col className="data-table-row-cell">{application.category.name}</Col>
<Col <Col
className="data-table-row-cell">{application.currentLifecycle.lifecycleState.name} key={Math.random()}
xs="4"
className="data-table-row-cell"
>
<strong>{application.name}</strong>
</Col> </Col>
<Col> <Col key={Math.random()} className="data-table-row-cell">{application.platform.name}</Col>
<Col key={Math.random()} className="data-table-row-cell">{application.category.name}</Col>
<Col
key={Math.random()}
className="data-table-row-cell"
>
{application.currentLifecycle.lifecycleState.name}
</Col>
<Col
xs="1"
key={Math.random()}
>
<Button className="custom-flat grey rounded" <Button className="custom-flat grey rounded"
onClick={() => this.onAppEditClick(application.uuid)}> onClick={() => this.onAppEditClick(application.uuid)}>
<i className="fw fw-edit"></i> <i className="fw fw-edit"></i>

@ -21,8 +21,9 @@ import {withRouter} from 'react-router-dom';
import AuthHandler from "../../../api/authHandler"; import AuthHandler from "../../../api/authHandler";
import {Step1, Step2, Step3, Step4} from './CreateSteps/index'; import {Step1, Step2, Step3, Step4} from './CreateSteps/index';
import ApplicationMgtApi from '../../../api/applicationMgtApi'; import ApplicationMgtApi from '../../../api/applicationMgtApi';
import {Col, Modal, ModalBody, ModalHeader, Row} from 'reactstrap'; import {Modal, ModalHeader} from 'reactstrap';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import Stepper from "../../UIComponents/StepprHeader/Stepper";
/** /**
@ -148,6 +149,18 @@ class ApplicationCreate extends Component {
} }
}; };
/**
* Defines the application creation stepper.
* */
getStepperHeaders() {
return [
{index: 1, text: <FormattedMessage id="General.Info" defaultMessage="General.Info"/>},
{index: 2, text: <FormattedMessage id="Select.Platform" defaultMessage="Select.Platform"/>},
{index: 3, text: <FormattedMessage id="Screenshots" defaultMessage="Screenshots"/>},
{index: 4, text: <FormattedMessage id="Release" defaultMessage="Release"/>, optional: true}
];
}
/** /**
* Remove the last data point * Remove the last data point
* */ * */
@ -239,51 +252,17 @@ class ApplicationCreate extends Component {
<div id="create-application-modal"> <div id="create-application-modal">
<Modal isOpen={this.state.open} toggle={this.toggle} id="app-create-modal" <Modal isOpen={this.state.open} toggle={this.toggle} id="app-create-modal"
backdrop={'static'}> backdrop={'static'}>
<ModalHeader toggle={this.toggle}> <ModalHeader toggle={this.toggle} className="app-create-modal-header">
<FormattedMessage id="Create.Application" defaultMessage="Create Application"/> <FormattedMessage id="Create.Application" defaultMessage="Create Application"/>
</ModalHeader> </ModalHeader>
<ModalBody id="modal-body-content"> <div className="container app-create-modal-content">
<Row> <Stepper
<Col> activeStep={stepIndex + 1}
<div className="stepper-header"> previousStep={stepIndex}
<Row> stepContent={this.getStepperHeaders()}
<Col> />
<div className="stepper-header-content"> {this.getStepContent(stepIndex)}
<div className="step-index">1</div> </div>
<div className="step-header">
<FormattedMessage id="General.Info" defaultMessage="General.Info"/>
</div>
</div>
</Col>
<Col>
<span className="step-index">2</span>
<span className="step-header">
<FormattedMessage id="Select.Platform"
defaultMessage="Select.Platform"/>
</span>
</Col>
<Col>
<span className="step-index">3</span>
<span className="step-header">
<FormattedMessage id="Screenshots" defaultMessage="Screenshots"/>
</span>
</Col>
<Col>
<span className="step-index">4</span>
<span className="step-header">
<FormattedMessage id="Release" defaultMessage="Release"/>
</span>
</Col>
</Row>
</div>
</Col>
</Row>
<Row>
<Col>
{this.getStepContent(stepIndex)}
</Col>
</Row>
</ModalBody>
</Modal> </Modal>
</div>); </div>);
} }

@ -19,7 +19,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {Button, Form, FormFeedback, FormGroup, Input, Label, ModalFooter} from 'reactstrap'; import {Button, Form, FormFeedback, FormGroup, Input, Label, ModalBody, ModalFooter} from 'reactstrap';
import * as validator from '../../../../common/validator'; import * as validator from '../../../../common/validator';
import Chip from "../../../UIComponents/Chip/Chip"; import Chip from "../../../UIComponents/Chip/Chip";
@ -236,121 +236,121 @@ class Step1 extends Component {
return ( return (
<div> <div>
<div> <ModalBody id="modal-body-content">
<div> <FormGroup>
<FormGroup> <Label for="app-title">
<Label for="app-title"> <FormattedMessage id='Title' defaultMessage='Title'/>*
<FormattedMessage id='Title' defaultMessage='Title'/>* </Label>
</Label> <Input
<Input required
required type="text"
type="text" name="appName"
name="appName" id="app-title"
id="app-title" value={this.state.name}
value={this.state.name} onChange={this.onTextFieldChange}
onChange={this.onTextFieldChange} />
/> <FormFeedback id="form-error">{this.state.errors.name}</FormFeedback>
<FormFeedback id="form-error">{this.state.errors.name}</FormFeedback> </FormGroup>
</FormGroup> <FormGroup>
<FormGroup> <Label for="app-short-description">
<Label for="app-short-description"> <FormattedMessage id="ShortDescription" defaultMessage="ShortDescription"/>*
<FormattedMessage id="shortDescription" defaultMessage="shortDescription"/>* </Label>
</Label> <Input
<Input required
required type="textarea"
type="textarea" name="appShortDescription"
name="appShortDescription" id="app-short-description"
id="app-short-description" value={this.state.shortDescription}
value={this.state.shortDescription} onChange={this.onTextFieldChange}
onChange={this.onTextFieldChange} />
/> <FormFeedback id="form-error">{this.state.errors.shortDescription}</FormFeedback>
<FormFeedback id="form-error">{this.state.errors.shortDescription}</FormFeedback> </FormGroup>
</FormGroup> <FormGroup>
<FormGroup> <Label for="app-description">
<Label for="app-description"> <FormattedMessage id='Description' defaultMessage='Description'/>*
<FormattedMessage id='Description' defaultMessage='Description'/>* </Label>
</Label> <Input
<Input required
required type="textarea"
type="textarea" name="appDescription"
name="appDescription" id="app-description"
id="app-description" value={this.state.description}
value={this.state.description} onChange={this.onTextFieldChange}
onChange={this.onTextFieldChange} />
/> <FormFeedback id="form-error">{this.state.errors.description}</FormFeedback>
<FormFeedback id="form-error">{this.state.errors.description}</FormFeedback> </FormGroup>
</FormGroup> <FormGroup>
<FormGroup> <Label for="app-category">
<Label for="app-category"> <FormattedMessage id='Category' defaultMessage='Category'/>
<FormattedMessage id='Category' defaultMessage='Category'/> </Label>
</Label> <Input
<Input type="select"
type="select" name="category"
name="category" id="app-category"
id="app-category" >
> <option key={0} value={{id: 0, name: "business"}}>Business</option>
<option key={0} value={{id: 0, name: "business"}}>Business</option> </Input>
</Input> </FormGroup>
</FormGroup> <FormGroup>
<FormGroup> <Label for="app-visibility">
<Label for="app-visibility"> <FormattedMessage id='Visibility' defaultMessage='Visibility'/>
<FormattedMessage id='Visibility' defaultMessage='Visibility'/> </Label>
</Label> <Form inline>
<Form inline> <FormGroup>
<FormGroup> <Input
<Input type="select"
type="select" name="visibility"
name="visibility" id="app-visibility"
id="app-visibility" onChange={this.onVisibilityChange}
onChange={this.onVisibilityChange} >
> <option id="app-visibility-default" disabled selected>Select the App Visibility
<option id="app-visibility-default" disabled selected>Select the App Visibility Option.
Option. </option>
</option> <option key={1}><FormattedMessage id='Devices' defaultMessage='Devices'/>
<option key={1}><FormattedMessage id='Devices' defaultMessage='Devices'/> </option>
</option> <option key={2}><FormattedMessage id='Roles' defaultMessage='Roles'/></option>
<option key={2}><FormattedMessage id='Roles' defaultMessage='Roles'/></option> <option key={3}><FormattedMessage id='Groups' defaultMessage='Groups'/></option>
<option key={3}><FormattedMessage id='Groups' defaultMessage='Groups'/></option> </Input>
</Input> </FormGroup>
</FormGroup> {visibilityItem()}
{visibilityItem()} </Form>
</Form> </FormGroup>
</FormGroup> <FormGroup>
<FormGroup> <Label for="app-tags"><FormattedMessage id='Tags' defaultMessage='Tags'/>*</Label>
<Label for="app-tags"><FormattedMessage id='Tags' defaultMessage='Tags'/>*</Label> <Input
<Input required
required type="text"
type="text" value={this.state.defValue}
value={this.state.defValue} name="app-tags"
name="app-tags" id="app-tags"
id="app-tags" onChange={this.handleTagChange.bind(this)}
onChange={this.handleTagChange.bind(this)} onKeyPress={this.addTags.bind(this)}
onKeyPress={this.addTags.bind(this)} />
/>
<div id="batch-content"> <div id="batch-content">
{this.state.tags.map(tag => { {this.state.tags.map(tag => {
return ( return (
<Chip <Chip
key={tag.key} key={tag.key}
content={tag} content={tag}
onDelete={this.handleRequestDelete} onDelete={this.handleRequestDelete}
/> />
) )
} }
)} )}
</div> </div>
<FormFeedback id="form-error">{this.state.errors.tags}</FormFeedback> <FormFeedback id="form-error">{this.state.errors.tags}</FormFeedback>
</FormGroup> </FormGroup>
</ModalBody>
<ModalFooter className="custom-footer row">
<div className="footer-main-btn col">
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button>
<Button className="custom-flat primary-flat" onClick={this.setStepData}>
<FormattedMessage id="Continue" defaultMessage="Continue"/>
</Button>
</div> </div>
</div>
<ModalFooter>
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button>
<Button className="custom-raised primary" onClick={this.setStepData}>
<FormattedMessage id="Continue" defaultMessage="Continue"/>
</Button>
</ModalFooter> </ModalFooter>
</div> </div>
); );

@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AuthHandler from "../../../../api/authHandler"; import AuthHandler from "../../../../api/authHandler";
import PlatformMgtApi from "../../../../api/platformMgtApi"; import PlatformMgtApi from "../../../../api/platformMgtApi";
import {Button, FormFeedback, FormGroup, Input, Label, ModalFooter} from 'reactstrap'; import {Button, FormFeedback, FormGroup, Input, Label, ModalBody, ModalFooter} from 'reactstrap';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import * as validator from '../../../../common/validator'; import * as validator from '../../../../common/validator';
@ -145,43 +145,50 @@ class Step2 extends Component {
render() { render() {
return ( return (
<div> <div>
<ModalBody id="modal-body-content">
<FormGroup> <FormGroup>
<Label for="store">Store Type</Label> <Label for="store">Store Type</Label>
<Input type="select" name="store" className="input-custom" onChange={this.onChangeStore.bind(this)}> <Input type="select" name="store" className="input-custom"
<option>Enterprise</option> onChange={this.onChangeStore.bind(this)}>
<option>Public</option> <option>Enterprise</option>
</Input> <option>Public</option>
</FormGroup> </Input>
<FormGroup> </FormGroup>
<Label for="store"><FormattedMessage id='Platform' defaultMessage='Platform'/></Label> <FormGroup>
<Input <Label for="store"><FormattedMessage id='Platform' defaultMessage='Platform'/></Label>
required <Input
type="select" required
name="store" type="select"
onChange={this.onChangePlatform.bind(this)} name="store"
> onChange={this.onChangePlatform.bind(this)}
<option id="app-visibility-default" disabled selected>Select the Application Platform</option> >
{this.state.platforms.length > 0 ? this.state.platforms.map(platform => { <option id="app-visibility-default" disabled selected>Select the Application Platform
return ( </option>
<option value={platform.identifier} key={platform.identifier}> {this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
{platform.name} return (
</option> <option value={platform.identifier} key={platform.identifier}>
) {platform.name}
}) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>} </option>
</Input> )
<FormFeedback id="form-error">{this.state.errors.platform}</FormFeedback> }) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>}
</FormGroup> </Input>
<ModalFooter> <FormFeedback id="form-error">{this.state.errors.platform}</FormFeedback>
<Button className="custom-flat primary-flat" onClick={this.onBackClick}> </FormGroup>
<FormattedMessage id="Back" defaultMessage="Back"/> </ModalBody>
</Button> <ModalFooter className="custom-footer row">
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}> <div className="footer-back-btn col">
<FormattedMessage id="Cancel" defaultMessage="Cancel"/> <Button className="custom-flat primary-flat" onClick={this.onBackClick}>
</Button> <FormattedMessage id="Back" defaultMessage="Back"/>
<Button className="custom-raised primary" onClick={this.setStepData}> </Button>
<FormattedMessage id="Continue" defaultMessage="Continue"/> </div>
</Button> <div className="footer-main-btn col">
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button>
<Button className="custom-flat primary-flat" onClick={this.setStepData}>
<FormattedMessage id="Continue" defaultMessage="Continue"/>
</Button>
</div>
</ModalFooter> </ModalFooter>
</div> </div>
); );

@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
import React, {Component} from 'react'; import React, {Component} from 'react';
import * as validator from '../../../../common/validator'; import * as validator from '../../../../common/validator';
import {Button, FormFeedback, FormGroup, Label, ModalFooter} from 'reactstrap'; import {Button, FormFeedback, FormGroup, Label, ModalBody, ModalFooter} from 'reactstrap';
import AppImage from "../../../UIComponents/AppImage/AppImage"; import AppImage from "../../../UIComponents/AppImage/AppImage";
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
@ -138,102 +138,108 @@ class Step3 extends Component {
render() { render() {
return ( return (
<div className="createStep2Content"> <div className="createStep2Content">
<div> <ModalBody id="modal-body-content">
<FormGroup> <div>
<Label for="app-screenshots">
<FormattedMessage id='Screenshots' defaultMessage='Screenshots'/>*
</Label>
<span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
<div id="screenshot-container">
{this.state.screenshots.map((tile) => (
<div id="app-image-screenshot">
<AppImage image={tile[0].preview}/>
</div>
))}
{this.state.screenshots.length < 3 ?
<Dropzone
className="application-create-screenshot-dropzone"
accept="image/jpeg, image/png"
onDrop={(screenshots, rejected) => {
let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots);
this.setState({
screenshots: tmpScreenshots
});
}}
>
<i className="fw fw-add"></i>
</Dropzone> : <div/>}
</div>
<FormFeedback id="form-error">{this.state.errors.screenshots}</FormFeedback>
</FormGroup>
</div>
<div style={{display: 'flex'}}>
<div style={{float: 'left', marginRight: '15px'}}>
<FormGroup> <FormGroup>
<Label for="app-icon"> <Label for="app-screenshots">
<FormattedMessage id='Screenshots' defaultMessage='Screenshots'/>* <FormattedMessage id='Screenshots' defaultMessage='Screenshots'/>*
</Label> </Label>
<span className="image-sub-title"> (512 X 512 32 bit PNG)</span> <span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
<div id="app-icon-container"> <div id="screenshot-container">
{this.state.icon.map((tile) => ( {this.state.screenshots.map((tile) => (
<div id="app-image-icon"> <div id="app-image-screenshot">
<AppImage image={tile.preview}/> <AppImage image={tile[0].preview}/>
</div> </div>
))} ))}
{this.state.screenshots.length < 3 ?
{this.state.icon.length === 0 ?
<Dropzone <Dropzone
className="application-create-icon-dropzone" className="application-create-screenshot-dropzone"
accept="image/jpeg, image/png" accept="image/jpeg, image/png"
onDrop={(icon, rejected) => { onDrop={(screenshots, rejected) => {
this.setState({icon, rejected}); let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots);
this.setState({
screenshots: tmpScreenshots
});
}} }}
> >
<i className="fw fw-add"></i> <i className="fw fw-add"></i>
</Dropzone> : <div/>} </Dropzone> : <div/>}
</div> </div>
<FormFeedback id="form-error">{this.state.errors.icon}</FormFeedback> <FormFeedback id="form-error">{this.state.errors.screenshots}</FormFeedback>
</FormGroup> </FormGroup>
</div> </div>
<div style={{marginLeft: '15px'}}> <div style={{display: 'flex'}}>
<FormGroup> <div style={{float: 'left', marginRight: '15px'}}>
<Label for="app-banner"> <FormGroup>
<FormattedMessage id='Icon' defaultMessage='Icon'/>* <Label for="app-icon">
</Label> <FormattedMessage id='Screenshots' defaultMessage='Screenshots'/>*
<span className="image-sub-title"> (1000 X 400 32 bit PNG)</span> </Label>
<div id="app-banner-container"> <span className="image-sub-title"> (512 X 512 32 bit PNG)</span>
{this.state.banner.map((tile) => ( <div id="app-icon-container">
<div id="app-image-banner"> {this.state.icon.map((tile) => (
<AppImage image={tile.preview}/> <div id="app-image-icon">
</div> <AppImage image={tile.preview}/>
))} </div>
{this.state.banner.length === 0 ? ))}
<Dropzone
className="application-create-banner-dropzone" {this.state.icon.length === 0 ?
accept="image/jpeg, image/png" <Dropzone
onDrop={(banner, rejected) => { className="application-create-icon-dropzone"
this.setState({banner, rejected}); accept="image/jpeg, image/png"
}} onDrop={(icon, rejected) => {
> this.setState({icon, rejected});
<i className="fw fw-add"></i> }}
</Dropzone> : <div/> >
} <i className="fw fw-add"></i>
</div> </Dropzone> : <div/>}
<FormFeedback id="form-error">{this.state.errors.banner}</FormFeedback> </div>
</FormGroup> <FormFeedback id="form-error">{this.state.errors.icon}</FormFeedback>
</FormGroup>
</div>
<div style={{marginLeft: '15px'}}>
<FormGroup>
<Label for="app-banner">
<FormattedMessage id='Icon' defaultMessage='Icon'/>*
</Label>
<span className="image-sub-title"> (1000 X 400 32 bit PNG)</span>
<div id="app-banner-container">
{this.state.banner.map((tile) => (
<div id="app-image-banner">
<AppImage image={tile.preview}/>
</div>
))}
{this.state.banner.length === 0 ?
<Dropzone
className="application-create-banner-dropzone"
accept="image/jpeg, image/png"
onDrop={(banner, rejected) => {
this.setState({banner, rejected});
}}
>
<i className="fw fw-add"></i>
</Dropzone> : <div/>
}
</div>
<FormFeedback id="form-error">{this.state.errors.banner}</FormFeedback>
</FormGroup>
</div>
</div>
</ModalBody>
<ModalFooter className="custom-footer row">
<div className="footer-back-btn col">
<Button className="custom-flat primary-flat" onClick={this.onBackClick}>
<FormattedMessage id="Back" defaultMessage="Back"/>
</Button>
</div>
<div className="footer-main-btn col">
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button>
<Button className="custom-flat primary-flat" onClick={this.setStepData}>
<FormattedMessage id="Continue" defaultMessage="Continue"/>
</Button>
</div> </div>
</div>
<ModalFooter>
<Button className="custom-flat primary-flat" onClick={this.onBackClick}>
<FormattedMessage id="Back" defaultMessage="Back"/>
</Button>
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button>
<Button className="custom-raised primary" onClick={this.setStepData}>
<FormattedMessage id="Continue" defaultMessage="Continue"/>
</Button>
</ModalFooter> </ModalFooter>
</div> </div>
); );

@ -18,7 +18,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Button, Collapse, FormGroup, FormText, Input, Label, ModalFooter} from 'reactstrap'; import {Button, Collapse, FormGroup, FormText, Input, Label, ModalBody, ModalFooter} from 'reactstrap';
import Switch from '../../../UIComponents/Switch/Switch' import Switch from '../../../UIComponents/Switch/Switch'
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
@ -91,7 +91,7 @@ class Step4 extends Component {
render() { render() {
return ( return (
<div className="applicationCreateStepMiddle"> <div className="applicationCreateStepMiddle">
<div> <ModalBody id="modal-body-content">
<FormGroup> <FormGroup>
<div id="app-release-switch-content"> <div id="app-release-switch-content">
<div id="app-release-switch-label"> <div id="app-release-switch-label">
@ -150,17 +150,21 @@ class Step4 extends Component {
/> />
</FormGroup> </FormGroup>
</Collapse> </Collapse>
</div> </ModalBody>
<ModalFooter> <ModalFooter className="custom-footer row">
<Button className="custom-flat primary-flat" onClick={this.onBackClick}> <div className="footer-back-btn col">
<FormattedMessage id="Back" defaultMessage="Back"/> <Button className="custom-flat primary-flat" onClick={this.onBackClick}>
</Button> <FormattedMessage id="Back" defaultMessage="Back"/>
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}> </Button>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/> </div>
</Button> <div className="footer-main-btn col">
<Button className="custom-raised primary" onClick={this.onSubmit}> <Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
<FormattedMessage id="Finish" defaultMessage="Finish"/> <FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button> </Button>
<Button className="custom-flat primary-flat" onClick={this.onSubmit}>
<FormattedMessage id="Finish" defaultMessage="Finish"/>
</Button>
</div>
</ModalFooter> </ModalFooter>
</div> </div>
); );

@ -21,6 +21,7 @@ import React, {Component} from 'react';
import GeneralInfo from "../GenenralInfo/GeneralInfo"; import GeneralInfo from "../GenenralInfo/GeneralInfo";
import ReleaseManager from '../../Release/ReleaseMgtBase/ReleaseManager'; import ReleaseManager from '../../Release/ReleaseMgtBase/ReleaseManager';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import ApplicationMgtApi from "../../../../api/applicationMgtApi";
class ApplicationEdit extends Component { class ApplicationEdit extends Component {
@ -28,6 +29,7 @@ class ApplicationEdit extends Component {
super(); super();
this.getTabContent = this.getTabContent.bind(this); this.getTabContent = this.getTabContent.bind(this);
this.state = { this.state = {
application: {},
general: "active", general: "active",
release: "", release: "",
pkgmgt: "", pkgmgt: "",
@ -35,6 +37,22 @@ class ApplicationEdit extends Component {
} }
} }
componentWillMount() {
let appId = window.location.pathname.split("/")[4];
let response = ApplicationMgtApi.getApplication(appId);
response.then(res => {
let data = res.data.applications;
let application = data.filter(app => {
return app.uuid === appId;
});
this.setState({application: application[0]});
})
}
handleTabClick(event) { handleTabClick(event) {
event.stopPropagation(); event.stopPropagation();
const key = event.target.value; const key = event.target.value;
@ -61,7 +79,10 @@ class ApplicationEdit extends Component {
getTabContent(tab) { getTabContent(tab) {
switch (tab) { switch (tab) {
case 1: { case 1: {
return <GeneralInfo/> {
console.log(this.state.application)
}
return <GeneralInfo application={this.state.application}/>
} }
case 2: { case 2: {
return <ReleaseManager/> return <ReleaseManager/>
@ -78,7 +99,7 @@ class ApplicationEdit extends Component {
render() { render() {
return ( return (
<div id="application-edit-base"> <div className="publisher-card">
<Row id="application-edit-header"> <Row id="application-edit-header">
<Col xs="3"> <Col xs="3">
<a className="back-to-app" onClick={this.handleOnBackClick.bind(this)}> <a className="back-to-app" onClick={this.handleOnBackClick.bind(this)}>
@ -86,7 +107,7 @@ class ApplicationEdit extends Component {
</a> </a>
</Col> </Col>
<Col> <Col>
<FormattedMessage id="Application.Name" defaultMessage="Application Name"/> {this.state.application.name}
</Col> </Col>
</Row> </Row>
<hr/> <hr/>

@ -16,6 +16,7 @@
* under the License. * under the License.
*/ */
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Col, Row} from "reactstrap";
/** /**
* Error page. * Error page.
@ -28,8 +29,22 @@ class Error extends Component {
render() { render() {
return ( return (
<div> <div className="error-page">
404 not found <Row>
<Col>
<div className="error-code">
<p>404</p>
</div>
</Col>
</Row>
<Row>
<Col>
<div className="error-text">
<p>The page you are looking for doesn't exist or error occurred.</p>
<p>Please click <a href="/publisher">here</a> to go to App publisher home page.</p>
</div>
</Col>
</Row>
</div> </div>
); );
} }

@ -58,11 +58,14 @@ class Platform extends Component {
</Row> </Row>
<Row> <Row>
<div className="platform-content-footer"> <div className="platform-content-footer">
<Button className="custom-flat grey">{platform.enabled ? {platform.enabled ?
<FormattedMessage id="Disable" defaultMessage="Disable"/> : <Button className="custom-flat danger-flat">
<FormattedMessage id="Activate" defaultMessage="Activate"/>} <FormattedMessage id="Disable" defaultMessage="Disable"/>
</Button> </Button> :
<Button className="custom-flat grey"> <Button className="custom-flat primary-flat">
<FormattedMessage id="Activate" defaultMessage="Activate"/>
</Button>}
<Button className="custom-flat primary-flat">
<FormattedMessage id="Share.With.Tenants" defaultMessage="Share.With.Tenants"/> <FormattedMessage id="Share.With.Tenants" defaultMessage="Share.With.Tenants"/>
</Button> </Button>
<Button className="custom-flat grey circle-button" onClick={this.unFold}> <Button className="custom-flat grey circle-button" onClick={this.unFold}>

@ -51,7 +51,7 @@ class PlatformListing extends Component {
render() { render() {
return ( return (
<div id="platform-listing"> <div className="publisher-card">
<Row> <Row>
<div className="create-platform"> <div className="create-platform">
<Button className="custom-flat grey" onClick={this.onPlatformCreateClick}> <Button className="custom-flat grey" onClick={this.onPlatformCreateClick}>

@ -0,0 +1,72 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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 PropTypes from 'prop-types';
import React, {Component} from 'react';
import './stepper.css';
import {FormattedMessage} from "react-intl";
class Step extends Component {
render() {
const {index, text, active, passed, finalStep, optional} = this.props;
let activeStep = active ? "stepper-active-index" : "stepper-inactive-index";
let activeStepText = active ? " stepper-active-step-text" : "";
let stepPassed = index === passed || index < passed ? " stepper-passed-index" : "";
let stepPassedText = index === passed || index < passed ? " stepper-passed-step-text" : "";
let indexClassNames = "step-index " + activeStep + stepPassed;
let indexTextClassNames = "step-text " + activeStepText + stepPassedText;
let stepIndexContent = index === passed || index < passed ? <i className="fw fw-check"></i> : index;
return (
<div className="step col-3">
<div className="step-content">
<div className={indexClassNames}>
<span>
{stepIndexContent}
</span>
</div>
<div className={indexTextClassNames}>
<div>
{text}
</div>
{optional ?
<div className="stepper-optional-text">
(<FormattedMessage id="Optional" defaultMessage="Optional"/>)
</div> : <div/>}
</div>
{!finalStep ? <i className="stepper-next-arrow fw fw-right-arrow"></i> : <i/>}
</div>
</div>
)
}
}
Step.propTypes = {
index: PropTypes.number,
text: PropTypes.node,
active: PropTypes.bool,
passed: PropTypes.number,
finalStep: PropTypes.bool,
optional: PropTypes.bool
}
export default Step;

@ -0,0 +1,52 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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 PropTypes from 'prop-types';
import React, {Component} from 'react';
import './stepper.css';
import Step from "./Step";
class Stepper extends Component {
render() {
const {stepContent, activeStep, previousStep} = this.props;
return (
<div className="stepper-header row">
{stepContent.map(content => {
return (
<Step
passed={previousStep}
text={content.text}
index={content.index}
optional={content.optional}
active={activeStep === content.index}
finalStep={content.index === stepContent.length}
/>
)
})}
</div>
)
}
}
Stepper.propTypes = {
stepContent: PropTypes.array,
activeStep: PropTypes.number
};
export default Stepper;

@ -0,0 +1,95 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.
*/
.stepper-header {
width: 100%;
padding: 24px;
height: 72px;
color: rgba(0, 0, 0, 0.38);
box-shadow: 1px 0px 1px 0 rgba(0, 0, 0, 0.2), 0 0px 20px 0 rgba(0, 0, 0, 0.19);
margin: 0 !important;
}
.step {
display: table-cell;
flex-direction: row;
align-items: baseline;
}
.step-content {
display: flex;
width: auto;
}
.step-index {
padding-top: 3px;
height: 24px;
width: 24px;
font-size: 12px;
border-radius: 50%;
text-align: center;
margin-right: 8px;
}
.stepper-inactive-index {
background-color: rgba(0, 0, 0, 0.38);
}
.stepper-active-index {
background-color: #0a6eff;
color: white;
}
.stepper-passed-index {
background-color: #0a6eff;
color: white;
}
.step-text {
/*padding-top: 3px;*/
font-family: Roboto-Regular;
font-size: 14px;
}
.inactive-text {
color: rgba(0, 0, 0, 0.54);
}
.stepper-active-step-text {
font-family: Roboto-Medium;
font-size: 14px;
color: rgba(0, 0, 0, 0.87);
font-weight: 300;
}
.stepper-passed-step-text {
font-family: Roboto-Medium;
color: rgba(0, 0, 0, 0.87);
}
.stepper-next-arrow {
padding-top: 3px;
margin-left: 15px;
}
.stepper-optional-text {
font-family: Roboto-Regular;
font-size: 12px;
color: rgba(0, 0, 0, 0.39)
}

@ -16,7 +16,6 @@
* under the License. * under the License.
*/ */
var path = require('path'); var path = require('path');
import '!!style-loader!css-loader!src/css/font-wso2.css';
const config = { const config = {
entry: { entry: {

Loading…
Cancel
Save