mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Merge branch 'wso2-application-mgt' into application-mgt
# Conflicts: # .gitignore
This commit is contained in:
commit
f01f150a37
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,8 +26,9 @@ target
|
|||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/node_modules/
|
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/node_modules/
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/build/
|
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/build/
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/public/dist/
|
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/package-lock.json
|
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/package-lock.json
|
||||||
|
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/npm-debug.log
|
||||||
|
components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/src/main/resources/publisher/public/dist/
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.store.ui/src/main/resources/store/node_modules/
|
components/application-mgt/org.wso2.carbon.device.application.mgt.store.ui/src/main/resources/store/node_modules/
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.store.ui/src/main/resources/store/public/dist/
|
components/application-mgt/org.wso2.carbon.device.application.mgt.store.ui/src/main/resources/store/public/dist/
|
||||||
components/application-mgt/org.wso2.carbon.device.application.mgt.store.ui/src/main/resources/store/package-lock.json
|
components/application-mgt/org.wso2.carbon.device.application.mgt.store.ui/src/main/resources/store/package-lock.json
|
||||||
|
|||||||
@ -22,14 +22,13 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
import org.wso2.carbon.device.application.mgt.api.beans.ErrorResponse;
|
import org.wso2.carbon.device.application.mgt.api.beans.ErrorResponse;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationReleaseManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationReleaseManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
||||||
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
@ -47,6 +46,7 @@ public class APIUtil {
|
|||||||
private static ApplicationReleaseManager applicationReleaseManager;
|
private static ApplicationReleaseManager applicationReleaseManager;
|
||||||
private static ApplicationStorageManager applicationStorageManager;
|
private static ApplicationStorageManager applicationStorageManager;
|
||||||
private static SubscriptionManager subscriptionManager;
|
private static SubscriptionManager subscriptionManager;
|
||||||
|
private static PlatformStorageManager platformStorageManager;
|
||||||
|
|
||||||
public static ApplicationManager getApplicationManager() {
|
public static ApplicationManager getApplicationManager() {
|
||||||
if (applicationManager == null) {
|
if (applicationManager == null) {
|
||||||
@ -147,7 +147,31 @@ public class APIUtil {
|
|||||||
}
|
}
|
||||||
return applicationStorageManager;
|
return applicationStorageManager;
|
||||||
}
|
}
|
||||||
public static Response getResponse(ApplicationManagementException ex, Response.Status status) {
|
|
||||||
|
/**
|
||||||
|
* To get the Platform Storage Manager from the osgi context.
|
||||||
|
*
|
||||||
|
* @return PlatformStoreManager instance in the current osgi context.
|
||||||
|
*/
|
||||||
|
public static PlatformStorageManager getPlatformStorageManager() {
|
||||||
|
if (platformStorageManager == null) {
|
||||||
|
synchronized (APIUtil.class) {
|
||||||
|
if (platformStorageManager == null) {
|
||||||
|
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||||
|
platformStorageManager = (PlatformStorageManager) ctx
|
||||||
|
.getOSGiService(PlatformStorageManager.class, null);
|
||||||
|
if (platformStorageManager == null) {
|
||||||
|
String msg = "Platform Storage Manager service has not initialized.";
|
||||||
|
log.error(msg);
|
||||||
|
throw new IllegalStateException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return platformStorageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response getResponse(Exception ex, Response.Status status) {
|
||||||
return getResponse(ex.getMessage(), status);
|
return getResponse(ex.getMessage(), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,8 +28,11 @@ import io.swagger.annotations.ExtensionProperty;
|
|||||||
import io.swagger.annotations.Info;
|
import io.swagger.annotations.Info;
|
||||||
import io.swagger.annotations.SwaggerDefinition;
|
import io.swagger.annotations.SwaggerDefinition;
|
||||||
import io.swagger.annotations.Tag;
|
import io.swagger.annotations.Tag;
|
||||||
|
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
|
||||||
|
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
|
||||||
import org.wso2.carbon.apimgt.annotations.api.Scopes;
|
import org.wso2.carbon.apimgt.annotations.api.Scopes;
|
||||||
import org.wso2.carbon.device.application.mgt.api.beans.ErrorResponse;
|
import org.wso2.carbon.device.application.mgt.api.beans.ErrorResponse;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.ApplicationRelease;
|
||||||
import org.wso2.carbon.device.application.mgt.common.Platform;
|
import org.wso2.carbon.device.application.mgt.common.Platform;
|
||||||
|
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
@ -96,7 +99,6 @@ import javax.ws.rs.core.Response;
|
|||||||
"such as get all the available platform for a tenant, etc.")
|
"such as get all the available platform for a tenant, etc.")
|
||||||
@Path("/platforms")
|
@Path("/platforms")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public interface PlatformManagementAPI {
|
public interface PlatformManagementAPI {
|
||||||
String SCOPE = "scope";
|
String SCOPE = "scope";
|
||||||
|
|
||||||
@ -181,9 +183,9 @@ public interface PlatformManagementAPI {
|
|||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
consumes = MediaType.APPLICATION_JSON,
|
consumes = MediaType.MULTIPART_FORM_DATA,
|
||||||
produces = MediaType.APPLICATION_JSON,
|
produces = MediaType.APPLICATION_JSON,
|
||||||
httpMethod = "POST",
|
httpMethod = "POST",
|
||||||
value = "Add Platform",
|
value = "Add Platform",
|
||||||
@ -209,11 +211,8 @@ public interface PlatformManagementAPI {
|
|||||||
response = ErrorResponse.class)
|
response = ErrorResponse.class)
|
||||||
})
|
})
|
||||||
Response addPlatform(
|
Response addPlatform(
|
||||||
@ApiParam(
|
@Multipart(value = "Platform", type = "application/json" ) Platform platform,
|
||||||
name = "platform",
|
@Multipart(value = "icon", required = false) Attachment iconFile
|
||||||
value = "The payload of the platform",
|
|
||||||
required = true)
|
|
||||||
Platform platform
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@ -343,7 +342,7 @@ public interface PlatformManagementAPI {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("tags")
|
@Path("tags/{name}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ApiOperation(
|
@ApiOperation(
|
||||||
@ -374,6 +373,46 @@ public interface PlatformManagementAPI {
|
|||||||
Response getPlatformTags(
|
Response getPlatformTags(
|
||||||
@ApiParam(name = "name", value ="The initial part of the name of platform tags that we need to retrieve",
|
@ApiParam(name = "name", value ="The initial part of the name of platform tags that we need to retrieve",
|
||||||
required = true)
|
required = true)
|
||||||
@QueryParam("name") @Size(min = 3) String name
|
@PathParam("name") @Size(min = 3) String name
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{identifier}/icon")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
@ApiOperation(
|
||||||
|
consumes = MediaType.MULTIPART_FORM_DATA,
|
||||||
|
produces = MediaType.APPLICATION_JSON,
|
||||||
|
httpMethod = "POST",
|
||||||
|
value = "Update Platform icon",
|
||||||
|
notes = "This will update the platform icon",
|
||||||
|
tags = "Platform Management",
|
||||||
|
extensions = {
|
||||||
|
@Extension(properties = {
|
||||||
|
@ExtensionProperty(name = SCOPE, value = "perm:platform:update")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiResponses(
|
||||||
|
value = {
|
||||||
|
@ApiResponse(
|
||||||
|
code = 200,
|
||||||
|
message = "OK. \n Successfully updated the platform icon"),
|
||||||
|
@ApiResponse(
|
||||||
|
code = 400,
|
||||||
|
message = "Bad Request. \n Invalid request parameters passed."),
|
||||||
|
@ApiResponse(
|
||||||
|
code = 500,
|
||||||
|
message = "Internal Server Error. \n Error occurred while updating the platform icon.",
|
||||||
|
response = ErrorResponse.class)
|
||||||
|
})
|
||||||
|
Response updatePlatformIcon(
|
||||||
|
@ApiParam(
|
||||||
|
name = "identifier",
|
||||||
|
required = true)
|
||||||
|
@PathParam("identifier")
|
||||||
|
@Size(max = 45)
|
||||||
|
String identifier,
|
||||||
|
@Multipart(value = "icon") Attachment iconFile
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import org.wso2.carbon.device.application.mgt.common.Filter;
|
|||||||
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationReleaseManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationReleaseManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager;
|
||||||
@ -97,6 +98,9 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
String msg = "Error occurred while getting the application list";
|
String msg = "Error occurred while getting the application list";
|
||||||
log.error(msg, e);
|
log.error(msg, e);
|
||||||
return Response.status(Response.Status.BAD_REQUEST).build();
|
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||||
|
} catch (ApplicationStorageManagementException e) {
|
||||||
|
log.error("Error occurred while getting the image artifacts of the application", e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +136,9 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
} catch (ApplicationManagementException e) {
|
} catch (ApplicationManagementException e) {
|
||||||
log.error("Error occurred while getting application with the uuid " + uuid, e);
|
log.error("Error occurred while getting application with the uuid " + uuid, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (ApplicationStorageManagementException e) {
|
||||||
|
log.error("Error occurred while getting the image artifacts of the application with the uuid " + uuid, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +259,10 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
return APIUtil.getResponse(new ApplicationManagementException(
|
return APIUtil.getResponse(new ApplicationManagementException(
|
||||||
"Exception while trying to read icon, " + "banner files for the application " +
|
"Exception while trying to read icon, " + "banner files for the application " +
|
||||||
applicationUUID, e), Response.Status.BAD_REQUEST);
|
applicationUUID, e), Response.Status.BAD_REQUEST);
|
||||||
|
} catch (ResourceManagementException e) {
|
||||||
|
log.error("Error occurred while uploading the image artifacts of the application with the uuid "
|
||||||
|
+ applicationUUID, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,8 +270,8 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
@PUT
|
@PUT
|
||||||
@Path("/upload-image-artifacts/{uuid}")
|
@Path("/upload-image-artifacts/{uuid}")
|
||||||
public Response updateApplicationArtifacts(@PathParam("uuid") String applicationUUID,
|
public Response updateApplicationArtifacts(@PathParam("uuid") String applicationUUID,
|
||||||
@Multipart("icon") Attachment iconFile, @Multipart("banner") Attachment bannerFile, @Multipart
|
@Multipart("icon") Attachment iconFile, @Multipart("banner") Attachment bannerFile,
|
||||||
("screenshot") List<Attachment> attachmentList) {
|
@Multipart("screenshot") List<Attachment> attachmentList) {
|
||||||
ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager();
|
ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager();
|
||||||
try {
|
try {
|
||||||
InputStream iconFileStream = null;
|
InputStream iconFileStream = null;
|
||||||
@ -282,15 +293,15 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
.uploadImageArtifacts(applicationUUID, iconFileStream, bannerFileStream, attachments);
|
.uploadImageArtifacts(applicationUUID, iconFileStream, bannerFileStream, attachments);
|
||||||
return Response.status(Response.Status.OK)
|
return Response.status(Response.Status.OK)
|
||||||
.entity("Successfully updated artifacts for the application " + applicationUUID).build();
|
.entity("Successfully updated artifacts for the application " + applicationUUID).build();
|
||||||
} catch (ApplicationManagementException e) {
|
|
||||||
String msg = "Error occurred while updating the artifact for the application " + applicationUUID;
|
|
||||||
log.error(msg, e);
|
|
||||||
return APIUtil.getResponse(e, Response.Status.BAD_REQUEST);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Exception while trying to read icon, banner files for the application " + applicationUUID);
|
log.error("Exception while trying to read icon, banner files for the application " + applicationUUID);
|
||||||
return APIUtil.getResponse(new ApplicationManagementException(
|
return APIUtil.getResponse(new ApplicationManagementException(
|
||||||
"Exception while trying to read icon, banner files for the application " +
|
"Exception while trying to read icon, banner files for the application " +
|
||||||
applicationUUID, e), Response.Status.BAD_REQUEST);
|
applicationUUID, e), Response.Status.BAD_REQUEST);
|
||||||
|
} catch (ResourceManagementException e) {
|
||||||
|
log.error("Error occurred while uploading the image artifacts of the application with the uuid "
|
||||||
|
+ applicationUUID, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +339,9 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
String msg = "Error occurred while deleting the application: " + uuid;
|
String msg = "Error occurred while deleting the application: " + uuid;
|
||||||
log.error(msg, e);
|
log.error(msg, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (ApplicationStorageManagementException e) {
|
||||||
|
log.error("Error occurred while deleteing the image artifacts of the application with the uuid " + uuid, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +372,10 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
log.error(errorMessage, e);
|
log.error(errorMessage, e);
|
||||||
return APIUtil.getResponse(new ApplicationManagementException(errorMessage, e),
|
return APIUtil.getResponse(new ApplicationManagementException(errorMessage, e),
|
||||||
Response.Status.INTERNAL_SERVER_ERROR);
|
Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (ResourceManagementException e) {
|
||||||
|
log.error("Error occurred while uploading the releases artifacts of the application with the uuid "
|
||||||
|
+ applicationUUID + " for the release " + applicationRelease.getVersionName(), e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,6 +412,10 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
return APIUtil.getResponse(new ApplicationManagementException(
|
return APIUtil.getResponse(new ApplicationManagementException(
|
||||||
"Error while updating the release artifacts of the application with UUID "
|
"Error while updating the release artifacts of the application with UUID "
|
||||||
+ applicationUUID), Response.Status.INTERNAL_SERVER_ERROR);
|
+ applicationUUID), Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (ResourceManagementException e) {
|
||||||
|
log.error("Error occurred while updating the releases artifacts of the application with the uuid "
|
||||||
|
+ applicationUUID + " for the release " + applicationRelease.getVersionName(), e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,6 +492,10 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
|
|||||||
} catch (ApplicationManagementException e) {
|
} catch (ApplicationManagementException e) {
|
||||||
log.error("Error while deleting application release with the application UUID " + applicationUUID, e);
|
log.error("Error while deleting application release with the application UUID " + applicationUUID, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (ApplicationStorageManagementException e) {
|
||||||
|
log.error("Error occurred while deleting the releases artifacts of the application with the uuid "
|
||||||
|
+ applicationUUID + " for the release " + version, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,13 +19,21 @@ package org.wso2.carbon.device.application.mgt.api.services.impl;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
|
||||||
|
import org.apache.cxf.jaxrs.ext.multipart.Multipart;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
import org.wso2.carbon.device.application.mgt.api.APIUtil;
|
import org.wso2.carbon.device.application.mgt.api.APIUtil;
|
||||||
import org.wso2.carbon.device.application.mgt.api.services.PlatformManagementAPI;
|
import org.wso2.carbon.device.application.mgt.api.services.PlatformManagementAPI;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
||||||
import org.wso2.carbon.device.application.mgt.common.Platform;
|
import org.wso2.carbon.device.application.mgt.common.Platform;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.PlatformManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.PlatformManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.PlatformStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.core.exception.PlatformManagementDAOException;
|
import org.wso2.carbon.device.application.mgt.core.exception.PlatformManagementDAOException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
@ -54,6 +62,7 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
@Override
|
@Override
|
||||||
public Response getPlatforms(@QueryParam("status") String status, @QueryParam("tag") String tag) {
|
public Response getPlatforms(@QueryParam("status") String status, @QueryParam("tag") String tag) {
|
||||||
int tenantID = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
int tenantID = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
|
PlatformStorageManager platformStorageManager = APIUtil.getPlatformStorageManager();
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("API request received for getting the platforms with the status " + status);
|
log.debug("API request received for getting the platforms with the status " + status);
|
||||||
@ -85,25 +94,25 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
} else {
|
} else {
|
||||||
results = platforms;
|
results = platforms;
|
||||||
}
|
}
|
||||||
|
if (results != null) {
|
||||||
if (tag != null) {
|
for (Platform platform : results) {
|
||||||
if (results != null) {
|
if (tag == null || tag.isEmpty() || (platform.getTags() != null && platform.getTags()
|
||||||
for (Platform platform : results) {
|
.contains(tag))) {
|
||||||
if (platform.getTags() != null && platform.getTags().contains(tag)) {
|
platform.setIcon(platformStorageManager.getIcon(platform.getIdentifier()));
|
||||||
filteredPlatforms.add(platform);
|
filteredPlatforms.add(platform);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (log.isDebugEnabled()) {
|
||||||
filteredPlatforms = results;
|
log.debug("Number of platforms with the status " + status + " : " + results.size());
|
||||||
}
|
}
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Number of platforms with the status " + status + " : " + results.size());
|
|
||||||
}
|
}
|
||||||
return Response.status(Response.Status.OK).entity(filteredPlatforms).build();
|
return Response.status(Response.Status.OK).entity(filteredPlatforms).build();
|
||||||
} catch (PlatformManagementException e) {
|
} catch (PlatformManagementException e) {
|
||||||
log.error("Error while getting the platforms for tenant - " + tenantID, e);
|
log.error("Error while getting the platforms for tenant - " + tenantID, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (PlatformStorageManagementException e) {
|
||||||
|
log.error("Error while getting platform icons for the tenant : " + tenantID, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +127,10 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
if (platform == null) {
|
if (platform == null) {
|
||||||
return Response.status(Response.Status.NOT_FOUND).entity("Platform not found").build();
|
return Response.status(Response.Status.NOT_FOUND).entity("Platform not found").build();
|
||||||
}
|
}
|
||||||
|
ImageArtifact icon = APIUtil.getPlatformStorageManager().getIcon(id);
|
||||||
|
if (icon != null) {
|
||||||
|
platform.setIcon(icon);
|
||||||
|
}
|
||||||
return Response.status(Response.Status.OK).entity(platform).build();
|
return Response.status(Response.Status.OK).entity(platform).build();
|
||||||
} catch (PlatformManagementDAOException e) {
|
} catch (PlatformManagementDAOException e) {
|
||||||
log.error("Error while trying the get the platform with the identifier : " + id + " for the tenant :"
|
log.error("Error while trying the get the platform with the identifier : " + id + " for the tenant :"
|
||||||
@ -127,17 +140,26 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
log.error("Error while trying the get the platform with the identifier : " + id + " for the tenant :"
|
log.error("Error while trying the get the platform with the identifier : " + id + " for the tenant :"
|
||||||
+ tenantId, e);
|
+ tenantId, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.NOT_FOUND);
|
return APIUtil.getResponse(e, Response.Status.NOT_FOUND);
|
||||||
|
} catch (PlatformStorageManagementException e) {
|
||||||
|
log.error("Platform Storage Management Exception while trying to get the icon for the platform : " + id
|
||||||
|
+ " for the tenant : " + tenantId, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.NOT_FOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Override
|
@Override
|
||||||
public Response addPlatform(Platform platform) {
|
public Response addPlatform(@Multipart("platform") Platform platform, @Multipart("icon")Attachment icon) {
|
||||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
try {
|
try {
|
||||||
if (platform != null) {
|
if (platform != null) {
|
||||||
if (platform.validate()) {
|
if (platform.validate()) {
|
||||||
APIUtil.getPlatformManager().register(tenantId, platform);
|
APIUtil.getPlatformManager().register(tenantId, platform);
|
||||||
|
|
||||||
|
if (icon != null) {
|
||||||
|
InputStream iconFileStream = icon.getDataHandler().getInputStream();
|
||||||
|
APIUtil.getPlatformStorageManager().uploadIcon(platform.getIdentifier(), iconFileStream);
|
||||||
|
}
|
||||||
return Response.status(Response.Status.CREATED).build();
|
return Response.status(Response.Status.CREATED).build();
|
||||||
} else {
|
} else {
|
||||||
return APIUtil
|
return APIUtil
|
||||||
@ -152,6 +174,14 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
log.error("Platform Management Exception while trying to add the platform with identifier : " + platform
|
log.error("Platform Management Exception while trying to add the platform with identifier : " + platform
|
||||||
.getIdentifier() + " for the tenant : " + tenantId, e);
|
.getIdentifier() + " for the tenant : " + tenantId, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("IO Exception while trying to save platform icon for the platform : " + platform.getIdentifier(),
|
||||||
|
e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (ResourceManagementException e) {
|
||||||
|
log.error("Storage Exception while trying to save platform icon for the platform : " + platform
|
||||||
|
.getIdentifier(), e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,11 +205,17 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
public Response removePlatform(@PathParam("identifier") @Size(max = 45) String id) {
|
public Response removePlatform(@PathParam("identifier") @Size(max = 45) String id) {
|
||||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
try {
|
try {
|
||||||
|
APIUtil.getPlatformStorageManager().deleteIcon(id);
|
||||||
APIUtil.getPlatformManager().unregister(tenantId, id, false);
|
APIUtil.getPlatformManager().unregister(tenantId, id, false);
|
||||||
return Response.status(Response.Status.OK).build();
|
return Response.status(Response.Status.OK).build();
|
||||||
} catch (PlatformManagementException e) {
|
} catch (PlatformManagementException e) {
|
||||||
log.error("Platform Management Exception while trying to un-register the platform with the identifier : "
|
log.error(
|
||||||
+ id + " for the tenant : " + tenantId, e);
|
"Platform Management Exception while trying to un-register the platform with the identifier : " + id
|
||||||
|
+ " for the tenant : " + tenantId, e);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (PlatformStorageManagementException e) {
|
||||||
|
log.error("Platform Storage Management Exception while trying to delete the icon of the platform with "
|
||||||
|
+ "identifier for the tenant :" + tenantId, e);
|
||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,9 +241,9 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("tags")
|
@Path("tags/{name}")
|
||||||
@Override
|
@Override
|
||||||
public Response getPlatformTags(@QueryParam("name") String name) {
|
public Response getPlatformTags(@PathParam("name") String name) {
|
||||||
if (name == null || name.isEmpty() || name.length() < 3) {
|
if (name == null || name.isEmpty() || name.length() < 3) {
|
||||||
return APIUtil.getResponse("In order to get platform tags, it is required to pass the first 3 "
|
return APIUtil.getResponse("In order to get platform tags, it is required to pass the first 3 "
|
||||||
+ "characters of the platform tag name", Response.Status.INTERNAL_SERVER_ERROR);
|
+ "characters of the platform tag name", Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
@ -221,4 +257,28 @@ public class PlatformManagementAPIImpl implements PlatformManagementAPI {
|
|||||||
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("{identifier}/icon")
|
||||||
|
@Override
|
||||||
|
public Response updatePlatformIcon(@PathParam("identifier") String identifier, @Multipart("icon") Attachment
|
||||||
|
icon) {
|
||||||
|
try {
|
||||||
|
if (icon != null) {
|
||||||
|
InputStream iconFileStream = icon.getDataHandler().getInputStream();
|
||||||
|
APIUtil.getPlatformStorageManager().uploadIcon(identifier, iconFileStream);
|
||||||
|
return Response.status(Response.Status.OK)
|
||||||
|
.entity("Icon file is successfully updated for the platform :" + identifier).build();
|
||||||
|
} else {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).entity("Icon file is not provided to update")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
} catch (ResourceManagementException e) {
|
||||||
|
log.error("Resource Management exception while trying to update the icon for the platform " + identifier);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("IO exception while trying to update the icon for the platform " + identifier);
|
||||||
|
return APIUtil.getResponse(e, Response.Status.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,29 @@ package org.wso2.carbon.device.application.mgt.auth.handler.util;
|
|||||||
public class Constants {
|
public class Constants {
|
||||||
public static final String SCOPES = "perm:application:get perm:application:create perm:application:update " +
|
public static final String SCOPES = "perm:application:get perm:application:create perm:application:update " +
|
||||||
"perm:application-mgt:login perm:application:delete perm:platform:add perm:platform:remove " +
|
"perm:application-mgt:login perm:application:delete perm:platform:add perm:platform:remove " +
|
||||||
"perm:roles:view perm:devices:view perm:platform:get";
|
"perm:roles:view perm:devices:view perm:platform:get perm:admin:devices:view perm:roles:add " +
|
||||||
|
"perm:roles:add-users perm:roles:update perm:roles:permissions perm:roles:details perm:roles:view" +
|
||||||
|
" perm:roles:create-combined-role perm:roles:delete perm:dashboard:vulnerabilities " +
|
||||||
|
"perm:dashboard:non-compliant-count perm:dashboard:non-compliant perm:dashboard:by-groups " +
|
||||||
|
"perm:dashboard:device-counts perm:dashboard:feature-non-compliant perm:dashboard:count-overview " +
|
||||||
|
"perm:dashboard:filtered-count perm:dashboard:details perm:get-activity perm:devices:delete " +
|
||||||
|
"perm:devices:applications perm:devices:effective-policy perm:devices:compliance-data " +
|
||||||
|
"perm:devices:features perm:devices:operations perm:devices:search perm:devices:details " +
|
||||||
|
"perm:devices:update perm:devices:view perm:view-configuration perm:manage-configuration " +
|
||||||
|
"perm:policies:remove perm:policies:priorities perm:policies:deactivate perm:policies:get-policy-details" +
|
||||||
|
" perm:policies:manage perm:policies:activate perm:policies:update perm:policies:changes " +
|
||||||
|
"perm:policies:get-details perm:users:add perm:users:details perm:users:count perm:users:delete " +
|
||||||
|
"perm:users:roles perm:users:user-details perm:users:credentials perm:users:search perm:users:is-exist " +
|
||||||
|
"perm:users:update perm:users:send-invitation perm:admin-users:view perm:groups:devices perm:groups:update " +
|
||||||
|
"perm:groups:add perm:groups:device perm:groups:devices-count perm:groups:remove perm:groups:groups " +
|
||||||
|
"perm:groups:groups-view perm:groups:share perm:groups:count perm:groups:roles perm:groups:devices-remove " +
|
||||||
|
"perm:groups:devices-add perm:groups:assign perm:device-types:features perm:device-types:types " +
|
||||||
|
"perm:applications:install perm:applications:uninstall perm:admin-groups:count perm:admin-groups:view" +
|
||||||
|
" perm:notifications:mark-checked perm:notifications:view perm:admin:certificates:delete " +
|
||||||
|
"perm:admin:certificates:details perm:admin:certificates:view perm:admin:certificates:add " +
|
||||||
|
"perm:admin:certificates:verify perm:admin perm:devicetype:deployment perm:device-types:events " +
|
||||||
|
"perm:device-types:events:view perm:admin:device-type perm:device:enroll perm:geo-service:analytics-view " +
|
||||||
|
"perm:geo-service:alerts-manage";
|
||||||
|
|
||||||
public static final String[] TAGS = {"device_management"};
|
public static final String[] TAGS = {"device_management"};
|
||||||
public static final String USER_NAME = "userName";
|
public static final String USER_NAME = "userName";
|
||||||
|
|||||||
@ -60,6 +60,8 @@ public class Platform {
|
|||||||
|
|
||||||
private boolean defaultTenantMapping;
|
private boolean defaultTenantMapping;
|
||||||
|
|
||||||
|
private ImageArtifact icon;
|
||||||
|
|
||||||
public Platform(Platform platform) {
|
public Platform(Platform platform) {
|
||||||
this.id = platform.getId();
|
this.id = platform.getId();
|
||||||
this.name = platform.getName();
|
this.name = platform.getName();
|
||||||
@ -180,6 +182,10 @@ public class Platform {
|
|||||||
return !(name == null || identifier == null);
|
return !(name == null || identifier == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIcon(ImageArtifact icon) {
|
||||||
|
this.icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a property of a {@link Platform}.
|
* Represents a property of a {@link Platform}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -22,7 +22,7 @@ package org.wso2.carbon.device.application.mgt.common.exception;
|
|||||||
/**
|
/**
|
||||||
* Represents the exception thrown during storing and retrieving the artifacts.
|
* Represents the exception thrown during storing and retrieving the artifacts.
|
||||||
*/
|
*/
|
||||||
public class ApplicationStorageManagementException extends ApplicationManagementException {
|
public class ApplicationStorageManagementException extends ResourceManagementException {
|
||||||
public ApplicationStorageManagementException(String message, Throwable ex) {
|
public ApplicationStorageManagementException(String message, Throwable ex) {
|
||||||
super(message, ex);
|
super(message, ex);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.wso2.carbon.device.application.mgt.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the exception thrown during storing and retrieving those artifacts.
|
||||||
|
*/
|
||||||
|
public class PlatformStorageManagementException extends ResourceManagementException {
|
||||||
|
public PlatformStorageManagementException(String message, Throwable ex) {
|
||||||
|
super(message, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlatformStorageManagementException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.wso2.carbon.device.application.mgt.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the exception that will be thrown when there is an issue while managing the resources.
|
||||||
|
*/
|
||||||
|
public class ResourceManagementException extends Exception {
|
||||||
|
ResourceManagementException(String message, Throwable ex) {
|
||||||
|
super(message, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceManagementException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,6 +21,7 @@ package org.wso2.carbon.device.application.mgt.common.services;
|
|||||||
|
|
||||||
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -38,7 +39,7 @@ public interface ApplicationStorageManager {
|
|||||||
* @throws ApplicationStorageManagementException Application Storage Management Exception.
|
* @throws ApplicationStorageManagementException Application Storage Management Exception.
|
||||||
*/
|
*/
|
||||||
public void uploadImageArtifacts(String applicationUUID, InputStream iconFile, InputStream bannerFile,
|
public void uploadImageArtifacts(String applicationUUID, InputStream iconFile, InputStream bannerFile,
|
||||||
List<InputStream> screenshots) throws ApplicationStorageManagementException;
|
List<InputStream> screenshots) throws ResourceManagementException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To upload release artifacts for an Application.
|
* To upload release artifacts for an Application.
|
||||||
@ -47,8 +48,8 @@ public interface ApplicationStorageManager {
|
|||||||
* @param binaryFile Binary File for the release.
|
* @param binaryFile Binary File for the release.
|
||||||
* @throws ApplicationStorageManagementException Application Storage Management Exception.
|
* @throws ApplicationStorageManagementException Application Storage Management Exception.
|
||||||
*/
|
*/
|
||||||
public void uploadReleaseArtifacts(String applicationUUID, String versionName, InputStream binaryFile) throws
|
public void uploadReleaseArtifacts(String applicationUUID, String versionName, InputStream binaryFile)
|
||||||
ApplicationStorageManagementException;
|
throws ResourceManagementException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To get released artifacts for the particular version of the application.
|
* To get released artifacts for the particular version of the application.
|
||||||
|
|||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.wso2.carbon.device.application.mgt.common.services;
|
||||||
|
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.PlatformStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages all the storage related requirements of Platform.
|
||||||
|
*/
|
||||||
|
public interface PlatformStorageManager {
|
||||||
|
/**
|
||||||
|
* To upload image artifacts related with an Application.
|
||||||
|
*
|
||||||
|
* @param platformIdentifier Identifier of the platform
|
||||||
|
* @param iconFile Icon File input stream
|
||||||
|
* @throws PlatformStorageManagementException Platform Storage Management Exception.
|
||||||
|
*/
|
||||||
|
public void uploadIcon(String platformIdentifier, InputStream iconFile) throws ResourceManagementException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get the icon for a particular platform.
|
||||||
|
*
|
||||||
|
* @param platformIdentifier Identifier of the platform.
|
||||||
|
* @return the icon for the given platform.
|
||||||
|
*/
|
||||||
|
public ImageArtifact getIcon(String platformIdentifier) throws PlatformStorageManagementException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To delete the icon of a particular platform
|
||||||
|
*
|
||||||
|
* @param platformIdentifier Identifier of the platform to which delete icon.
|
||||||
|
* @throws PlatformStorageManagementException PlatformStorageManagement Exception.
|
||||||
|
*/
|
||||||
|
public void deleteIcon(String platformIdentifier) throws PlatformStorageManagementException;
|
||||||
|
}
|
||||||
@ -77,7 +77,8 @@
|
|||||||
org.wso2.carbon.ndatasource.core,
|
org.wso2.carbon.ndatasource.core,
|
||||||
org.wso2.carbon,
|
org.wso2.carbon,
|
||||||
org.apache.commons.io,
|
org.apache.commons.io,
|
||||||
org.apache.commons.codec.binary;version="${commons-codec.wso2.osgi.version.range}"
|
org.apache.commons.codec.binary;version="${commons-codec.wso2.osgi.version.range}",
|
||||||
|
org.wso2.carbon.base
|
||||||
</Import-Package>
|
</Import-Package>
|
||||||
<Export-Package>
|
<Export-Package>
|
||||||
!org.wso2.carbon.device.application.mgt.core.internal.*,
|
!org.wso2.carbon.device.application.mgt.core.internal.*,
|
||||||
|
|||||||
@ -87,7 +87,8 @@ public class Extension {
|
|||||||
VisibilityTypeManager,
|
VisibilityTypeManager,
|
||||||
SubscriptionManager,
|
SubscriptionManager,
|
||||||
VisibilityManager,
|
VisibilityManager,
|
||||||
ApplicationStorageManager
|
ApplicationStorageManager,
|
||||||
|
PlatformStorageManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
package org.wso2.carbon.device.application.mgt.core.impl;
|
package org.wso2.carbon.device.application.mgt.core.impl;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
@ -30,6 +28,7 @@ import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
|||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException;
|
import org.wso2.carbon.device.application.mgt.common.exception.DBConnectionException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.TransactionManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.TransactionManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager;
|
import org.wso2.carbon.device.application.mgt.common.services.ApplicationStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.core.dao.common.DAOFactory;
|
import org.wso2.carbon.device.application.mgt.core.dao.common.DAOFactory;
|
||||||
@ -37,18 +36,18 @@ import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManageme
|
|||||||
import org.wso2.carbon.device.application.mgt.core.internal.DataHolder;
|
import org.wso2.carbon.device.application.mgt.core.internal.DataHolder;
|
||||||
import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil;
|
import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil;
|
||||||
import org.wso2.carbon.device.application.mgt.core.util.Constants;
|
import org.wso2.carbon.device.application.mgt.core.util.Constants;
|
||||||
|
import org.wso2.carbon.device.application.mgt.core.util.StorageManagementUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.wso2.carbon.device.application.mgt.core.util.StorageManagementUtil.saveFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains the default concrete implementation of ApplicationStorage Management.
|
* This class contains the default concrete implementation of ApplicationStorage Management.
|
||||||
*/
|
*/
|
||||||
@ -70,7 +69,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadImageArtifacts(String applicationUUID, InputStream iconFileStream, InputStream bannerFileStream,
|
public void uploadImageArtifacts(String applicationUUID, InputStream iconFileStream, InputStream bannerFileStream,
|
||||||
List<InputStream> screenShotStreams) throws ApplicationStorageManagementException {
|
List<InputStream> screenShotStreams) throws ResourceManagementException {
|
||||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
Application application = validateApplication(applicationUUID);
|
Application application = validateApplication(applicationUUID);
|
||||||
String artifactDirectoryPath = storagePath + application.getId();
|
String artifactDirectoryPath = storagePath + application.getId();
|
||||||
@ -78,7 +77,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
log.debug("Artifact Directory Path for saving the artifacts related with application " + applicationUUID
|
log.debug("Artifact Directory Path for saving the artifacts related with application " + applicationUUID
|
||||||
+ " is " + artifactDirectoryPath);
|
+ " is " + artifactDirectoryPath);
|
||||||
}
|
}
|
||||||
createArtifactDirectory(artifactDirectoryPath);
|
StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
|
||||||
if (iconFileStream != null) {
|
if (iconFileStream != null) {
|
||||||
try {
|
try {
|
||||||
saveFile(iconFileStream, artifactDirectoryPath + File.separator + Constants.IMAGE_ARTIFACTS[0]);
|
saveFile(iconFileStream, artifactDirectoryPath + File.separator + Constants.IMAGE_ARTIFACTS[0]);
|
||||||
@ -155,15 +154,14 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadReleaseArtifacts(String applicationUUID, String versionName, InputStream binaryFile)
|
public void uploadReleaseArtifacts(String applicationUUID, String versionName, InputStream binaryFile)
|
||||||
throws ApplicationStorageManagementException {
|
throws ResourceManagementException {
|
||||||
Application application = validateApplication(applicationUUID);
|
Application application = validateApplication(applicationUUID);
|
||||||
String artifactDirectoryPath = storagePath + application.getId();
|
String artifactDirectoryPath = storagePath + application.getId();
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled())
|
||||||
log.debug("Artifact Directory Path for saving the application release related artifacts related with "
|
log.debug("Artifact Directory Path for saving the application release related artifacts related with "
|
||||||
+ "application " + applicationUUID + " is " + artifactDirectoryPath);
|
+ "application " + applicationUUID + " is " + artifactDirectoryPath);
|
||||||
}
|
|
||||||
|
|
||||||
createArtifactDirectory(artifactDirectoryPath);
|
StorageManagementUtil.createArtifactDirectory(artifactDirectoryPath);
|
||||||
if (binaryFile != null) {
|
if (binaryFile != null) {
|
||||||
try {
|
try {
|
||||||
saveFile(binaryFile, artifactDirectoryPath + File.separator + versionName);
|
saveFile(binaryFile, artifactDirectoryPath + File.separator + versionName);
|
||||||
@ -207,7 +205,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
File artifactDirectory = new File(artifactDirectoryPath);
|
File artifactDirectory = new File(artifactDirectoryPath);
|
||||||
|
|
||||||
if (artifactDirectory.exists()) {
|
if (artifactDirectory.exists()) {
|
||||||
deleteDir(artifactDirectory);
|
StorageManagementUtil.deleteDir(artifactDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,14 +217,14 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
File artifact = new File(artifactPath);
|
File artifact = new File(artifactPath);
|
||||||
|
|
||||||
if (artifact.exists()) {
|
if (artifact.exists()) {
|
||||||
deleteDir(artifact);
|
StorageManagementUtil.deleteDir(artifact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteAllApplicationReleaseArtifacts(String applicationUUID) throws
|
public void deleteAllApplicationReleaseArtifacts(String applicationUUID) throws
|
||||||
ApplicationStorageManagementException {
|
ApplicationStorageManagementException {
|
||||||
Application application = validateApplication(applicationUUID);
|
validateApplication(applicationUUID);
|
||||||
try {
|
try {
|
||||||
List<ApplicationRelease> applicationReleases = DataHolder.getInstance().getReleaseManager()
|
List<ApplicationRelease> applicationReleases = DataHolder.getInstance().getReleaseManager()
|
||||||
.getReleases(applicationUUID);
|
.getReleases(applicationUUID);
|
||||||
@ -256,12 +254,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
"Image artifact " + name + " does not exist for the " + "application with UUID " + applicationUUID);
|
"Image artifact " + name + " does not exist for the " + "application with UUID " + applicationUUID);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ImageArtifact imageArtifact = new ImageArtifact();
|
return StorageManagementUtil.createImageArtifact(imageFile, imageArtifactPath);
|
||||||
imageArtifact.setName(imageFile.getName());
|
|
||||||
imageArtifact.setType(Files.probeContentType(imageFile.toPath()));
|
|
||||||
byte[] imageBytes = IOUtils.toByteArray(new FileInputStream(imageArtifactPath));
|
|
||||||
imageArtifact.setEncodedImage(Base64.encodeBase64URLSafeString(imageBytes));
|
|
||||||
return imageArtifact;
|
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
throw new ApplicationStorageManagementException(
|
throw new ApplicationStorageManagementException(
|
||||||
"File not found exception while trying to get the image artifact " + name + " for the "
|
"File not found exception while trying to get the image artifact " + name + " for the "
|
||||||
@ -273,61 +266,6 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* To save a file in a given location.
|
|
||||||
*
|
|
||||||
* @param inputStream Stream of the file.
|
|
||||||
* @param path Path the file need to be saved in.
|
|
||||||
*/
|
|
||||||
private void saveFile(InputStream inputStream, String path) throws IOException {
|
|
||||||
OutputStream outStream = null;
|
|
||||||
try {
|
|
||||||
byte[] buffer = new byte[inputStream.available()];
|
|
||||||
inputStream.read(buffer);
|
|
||||||
outStream = new FileOutputStream(new File(path));
|
|
||||||
outStream.write(buffer);
|
|
||||||
} finally {
|
|
||||||
if (inputStream != null) {
|
|
||||||
inputStream.close();
|
|
||||||
}
|
|
||||||
if (outStream != null) {
|
|
||||||
outStream.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is responsible for creating artifact parent directories in the given path.
|
|
||||||
*
|
|
||||||
* @param artifactDirectoryPath Path for the artifact directory.
|
|
||||||
* @throws ApplicationStorageManagementException Application Storage Management Exception.
|
|
||||||
*/
|
|
||||||
private void createArtifactDirectory(String artifactDirectoryPath) throws ApplicationStorageManagementException {
|
|
||||||
File artifactDirectory = new File(artifactDirectoryPath);
|
|
||||||
|
|
||||||
if (!artifactDirectory.exists()) {
|
|
||||||
if (!artifactDirectory.mkdirs()) {
|
|
||||||
throw new ApplicationStorageManagementException(
|
|
||||||
"Cannot create directories in the path to save the application related artifacts");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To delete a directory recursively
|
|
||||||
*
|
|
||||||
* @param artifactDirectory Artifact Directory that need to be deleted.
|
|
||||||
*/
|
|
||||||
private void deleteDir(File artifactDirectory) {
|
|
||||||
File[] contents = artifactDirectory.listFiles();
|
|
||||||
if (contents != null) {
|
|
||||||
for (File file : contents) {
|
|
||||||
deleteDir(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
artifactDirectory.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To validate the image artifact names.
|
* To validate the image artifact names.
|
||||||
* @param name Name of the image artifact.
|
* @param name Name of the image artifact.
|
||||||
@ -354,7 +292,7 @@ public class ApplicationStorageManagerImpl implements ApplicationStorageManager
|
|||||||
* could not be found.
|
* could not be found.
|
||||||
*/
|
*/
|
||||||
private Application validateApplication(String uuid) throws ApplicationStorageManagementException {
|
private Application validateApplication(String uuid) throws ApplicationStorageManagementException {
|
||||||
Application application = null;
|
Application application;
|
||||||
try {
|
try {
|
||||||
application = DataHolder.getInstance().getApplicationManager().getApplication(uuid);
|
application = DataHolder.getInstance().getApplicationManager().getApplication(uuid);
|
||||||
} catch (ApplicationManagementException e) {
|
} catch (ApplicationManagementException e) {
|
||||||
|
|||||||
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.wso2.carbon.device.application.mgt.core.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.base.MultitenantConstants;
|
||||||
|
import org.wso2.carbon.context.CarbonContext;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.Platform;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.PlatformManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.PlatformStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformStorageManager;
|
||||||
|
import org.wso2.carbon.device.application.mgt.core.internal.DataHolder;
|
||||||
|
import org.wso2.carbon.device.application.mgt.core.util.Constants;
|
||||||
|
import org.wso2.carbon.device.application.mgt.core.util.StorageManagementUtil;
|
||||||
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static org.wso2.carbon.device.application.mgt.core.util.StorageManagementUtil.saveFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the concrete implementation of {@link PlatformStorageManager}
|
||||||
|
*/
|
||||||
|
public class PlatformStorageManagerImpl implements PlatformStorageManager {
|
||||||
|
private static final Log log = LogFactory.getLog(ApplicationStorageManagerImpl.class);
|
||||||
|
private String storagePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This creates a new instance of PlatformStorageManager.
|
||||||
|
* @param storagePath Storage path to store the artifacts related with platform.
|
||||||
|
*/
|
||||||
|
public PlatformStorageManagerImpl(String storagePath) {
|
||||||
|
this.storagePath = storagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadIcon(String platformIdentifier, InputStream iconFileStream) throws ResourceManagementException {
|
||||||
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
|
Platform platform = validatePlatform(tenantId, platformIdentifier);
|
||||||
|
|
||||||
|
if (platform.isFileBased()) {
|
||||||
|
throw new ApplicationStorageManagementException("Icons for the file based platforms need to be added "
|
||||||
|
+ "directly to the deployment location inside icon folder");
|
||||||
|
}
|
||||||
|
if (platform.isShared() && tenantId != MultitenantConstants.SUPER_TENANT_ID) {
|
||||||
|
throw new PlatformStorageManagementException("Platform " + platformIdentifier
|
||||||
|
+ " is a shared platform from super-tenant. Only the super-tenant users can modify it");
|
||||||
|
}
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Artifact Directory Path for saving the artifacts related with application " + platformIdentifier
|
||||||
|
+ " is " + storagePath);
|
||||||
|
}
|
||||||
|
StorageManagementUtil.createArtifactDirectory(storagePath);
|
||||||
|
if (iconFileStream != null) {
|
||||||
|
try {
|
||||||
|
saveFile(iconFileStream, storagePath + File.separator + platform.getId());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ApplicationStorageManagementException(
|
||||||
|
"IO Exception while saving the icon file in the server for the platform " + platformIdentifier,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageArtifact getIcon(String platformIdentifier) throws PlatformStorageManagementException {
|
||||||
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
|
Platform platform = validatePlatform(tenantId, platformIdentifier);
|
||||||
|
String imageArtifactPath = storagePath + platform.getId();
|
||||||
|
File imageFile = null;
|
||||||
|
|
||||||
|
if (platform.isFileBased()) {
|
||||||
|
imageFile = new File(MultitenantUtils.getAxis2RepositoryPath(CarbonContext.getThreadLocalCarbonContext().
|
||||||
|
getTenantId()) + Constants.PLATFORMS_DEPLOYMENT_DIR_NAME + File.separator
|
||||||
|
+ Constants.IMAGE_ARTIFACTS[0] + File.separator + platformIdentifier);
|
||||||
|
} else {
|
||||||
|
imageFile = new File(imageArtifactPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!imageFile.exists()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return StorageManagementUtil.createImageArtifact(imageFile, imageArtifactPath);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new PlatformStorageManagementException(
|
||||||
|
"File not found exception while trying to get the icon for the " + "platform "
|
||||||
|
+ platformIdentifier, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PlatformStorageManagementException(
|
||||||
|
"IO Exception while trying to detect the file type of the platform icon of "
|
||||||
|
+ platformIdentifier, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteIcon(String platformIdentifier) throws PlatformStorageManagementException {
|
||||||
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
|
Platform platform = validatePlatform(tenantId, platformIdentifier);
|
||||||
|
String imageArtifactPath = storagePath + platform.getId();
|
||||||
|
|
||||||
|
if (platform.isShared() && tenantId != MultitenantConstants.SUPER_TENANT_ID) {
|
||||||
|
throw new PlatformStorageManagementException("Platform " + platformIdentifier + " is a shared platform "
|
||||||
|
+ "from super-tenant. Only the super-tenant users can modify it");
|
||||||
|
}
|
||||||
|
if (platform.isFileBased()) {
|
||||||
|
throw new PlatformStorageManagementException("Platform " + platformIdentifier + " is a file based one. "
|
||||||
|
+ "Please remove the relevant icon file directly from file system.");
|
||||||
|
}
|
||||||
|
|
||||||
|
File imageFile = new File(imageArtifactPath);
|
||||||
|
if (imageFile.exists()) {
|
||||||
|
imageFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To validate the platform, whether the given identifier has a valid platform.
|
||||||
|
*
|
||||||
|
* @param tenantId ID of the tenant
|
||||||
|
* @param identifier Identifier of the platform
|
||||||
|
* @return Platform related with the particular identifier.
|
||||||
|
*/
|
||||||
|
private Platform validatePlatform(int tenantId, String identifier) throws PlatformStorageManagementException {
|
||||||
|
Platform platform;
|
||||||
|
try {
|
||||||
|
PlatformManager platformManager = DataHolder.getInstance().getPlatformManager();
|
||||||
|
platform = platformManager.getPlatform(tenantId, identifier);
|
||||||
|
} catch (PlatformManagementException e) {
|
||||||
|
throw new PlatformStorageManagementException(
|
||||||
|
"Platform Management Exception while getting the platform " + "related with the identifier "
|
||||||
|
+ identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform == null) {
|
||||||
|
throw new PlatformStorageManagementException("Platform does not exist with the identifier " + identifier);
|
||||||
|
}
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,7 +19,6 @@ package org.wso2.carbon.device.application.mgt.core.impl;
|
|||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
|
||||||
import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier;
|
import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier;
|
||||||
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
||||||
@ -41,7 +40,6 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the default implementation for the Subscription Manager.
|
* This is the default implementation for the Subscription Manager.
|
||||||
@ -63,13 +61,9 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
|
|||||||
org.wso2.carbon.device.mgt.common.DeviceIdentifier deviceIdentifier = new org.wso2.carbon.device.mgt
|
org.wso2.carbon.device.mgt.common.DeviceIdentifier deviceIdentifier = new org.wso2.carbon.device.mgt
|
||||||
.common.DeviceIdentifier(device.getId(), device.getType());
|
.common.DeviceIdentifier(device.getId(), device.getType());
|
||||||
try {
|
try {
|
||||||
DeviceManagementDAOFactory.openConnection();
|
DeviceManagementProviderService dmpService = DataHolder.getInstance().getDeviceManagementService();
|
||||||
// todo: replace this with boolean:deviceExsits(deviceId) operation
|
if (!dmpService.isEnrolled(deviceIdentifier)) {
|
||||||
Map<Integer, Device> currentDevices = DeviceManagementDAOFactory.getDeviceDAO().getDevice(deviceIdentifier);
|
log.error("Device with ID: " + device.getId() + " is not enrolled to install the application.");
|
||||||
DeviceManagementDAOFactory.closeConnection();
|
|
||||||
|
|
||||||
if (currentDevices.isEmpty()) {
|
|
||||||
log.error("Device with ID: " + device.getId() + " not found to install the application.");
|
|
||||||
} else {
|
} else {
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Installing application to : " + device.getId());
|
log.debug("Installing application to : " + device.getId());
|
||||||
@ -96,10 +90,8 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
|
|||||||
// DAOFactory.getSubscriptionDAO().addDeviceApplicationMapping(device.getId(), applicationUUID, false);
|
// DAOFactory.getSubscriptionDAO().addDeviceApplicationMapping(device.getId(), applicationUUID, false);
|
||||||
failedDeviceList.remove(device);
|
failedDeviceList.remove(device);
|
||||||
}
|
}
|
||||||
} catch (DeviceManagementException | DeviceManagementDAOException | OperationManagementException | InvalidDeviceException | SQLException e) {
|
} catch (DeviceManagementException | OperationManagementException | InvalidDeviceException e) {
|
||||||
throw new ApplicationManagementException("Failed to install application " + applicationUUID + " on device " + deviceIdentifier, e);
|
throw new ApplicationManagementException("Failed to install application " + applicationUUID + " on device " + deviceIdentifier, e);
|
||||||
} finally {
|
|
||||||
DeviceManagementDAOFactory.closeConnection();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return failedDeviceList;
|
return failedDeviceList;
|
||||||
@ -110,15 +102,14 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
|
|||||||
throws ApplicationManagementException {
|
throws ApplicationManagementException {
|
||||||
log.info("Install application: " + applicationUUID + " to: " + userList.size() + " users.");
|
log.info("Install application: " + applicationUUID + " to: " + userList.size() + " users.");
|
||||||
List<DeviceIdentifier> deviceList = new ArrayList<>();
|
List<DeviceIdentifier> deviceList = new ArrayList<>();
|
||||||
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
|
||||||
for (String user : userList) {
|
for (String user : userList) {
|
||||||
try {
|
try {
|
||||||
List<Device> devicesOfUser = DeviceManagementDAOFactory.getDeviceDAO().getDevicesOfUser(user, tenantId);
|
List<Device> devicesOfUser = DataHolder.getInstance().getDeviceManagementService().getDevicesOfUser(user);
|
||||||
for (Device device : devicesOfUser) {
|
for (Device device : devicesOfUser) {
|
||||||
deviceList.add(new DeviceIdentifier(device
|
deviceList.add(new DeviceIdentifier(device
|
||||||
.getDeviceIdentifier(), device.getType()));
|
.getDeviceIdentifier(), device.getType()));
|
||||||
}
|
}
|
||||||
} catch (DeviceManagementDAOException e) {
|
} catch (DeviceManagementException e) {
|
||||||
log.error("Error when extracting the device list from user[" + user + "].", e);
|
log.error("Error when extracting the device list from user[" + user + "].", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import org.wso2.carbon.device.application.mgt.common.services.CategoryManager;
|
|||||||
import org.wso2.carbon.device.application.mgt.common.services.CommentsManager;
|
import org.wso2.carbon.device.application.mgt.common.services.CommentsManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.VisibilityManager;
|
import org.wso2.carbon.device.application.mgt.common.services.VisibilityManager;
|
||||||
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
||||||
@ -57,6 +58,8 @@ public class DataHolder {
|
|||||||
|
|
||||||
private ApplicationStorageManager applicationStorageManager;
|
private ApplicationStorageManager applicationStorageManager;
|
||||||
|
|
||||||
|
private PlatformStorageManager platformStorageManager;
|
||||||
|
|
||||||
private static final DataHolder applicationMgtDataHolder = new DataHolder();
|
private static final DataHolder applicationMgtDataHolder = new DataHolder();
|
||||||
|
|
||||||
private DataHolder() {
|
private DataHolder() {
|
||||||
@ -154,4 +157,12 @@ public class DataHolder {
|
|||||||
public ApplicationStorageManager getApplicationStorageManager() {
|
public ApplicationStorageManager getApplicationStorageManager() {
|
||||||
return applicationStorageManager;
|
return applicationStorageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPlatformStorageManager(PlatformStorageManager platformStorageManager) {
|
||||||
|
this.platformStorageManager = platformStorageManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlatformStorageManager getPlatformStorageManager() {
|
||||||
|
return platformStorageManager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,13 +30,13 @@ import org.wso2.carbon.device.application.mgt.common.services.CategoryManager;
|
|||||||
import org.wso2.carbon.device.application.mgt.common.services.CommentsManager;
|
import org.wso2.carbon.device.application.mgt.common.services.CommentsManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.VisibilityManager;
|
import org.wso2.carbon.device.application.mgt.common.services.VisibilityManager;
|
||||||
import org.wso2.carbon.device.application.mgt.core.config.ConfigurationManager;
|
import org.wso2.carbon.device.application.mgt.core.config.ConfigurationManager;
|
||||||
import org.wso2.carbon.device.application.mgt.core.dao.common.DAOFactory;
|
import org.wso2.carbon.device.application.mgt.core.dao.common.DAOFactory;
|
||||||
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
|
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
|
||||||
import org.wso2.carbon.device.application.mgt.core.util.ApplicationManagementUtil;
|
import org.wso2.carbon.device.application.mgt.core.util.ApplicationManagementUtil;
|
||||||
import org.wso2.carbon.device.application.mgt.core.util.Constants;
|
|
||||||
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
||||||
import org.wso2.carbon.ndatasource.core.DataSourceService;
|
import org.wso2.carbon.ndatasource.core.DataSourceService;
|
||||||
import org.wso2.carbon.user.core.service.RealmService;
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
@ -115,6 +115,11 @@ public class ServiceComponent {
|
|||||||
DataHolder.getInstance().setApplicationStorageManager(applicationStorageManager);
|
DataHolder.getInstance().setApplicationStorageManager(applicationStorageManager);
|
||||||
bundleContext.registerService(ApplicationStorageManager.class.getName(), applicationStorageManager, null);
|
bundleContext.registerService(ApplicationStorageManager.class.getName(), applicationStorageManager, null);
|
||||||
|
|
||||||
|
PlatformStorageManager platformStorageManager = ApplicationManagementUtil
|
||||||
|
.getPlatformStorageManagerInstance();
|
||||||
|
DataHolder.getInstance().setPlatformStorageManager(platformStorageManager);
|
||||||
|
bundleContext.registerService(PlatformStorageManager.class.getName(), platformStorageManager, null);
|
||||||
|
|
||||||
bundleContext.registerService(Axis2ConfigurationContextObserver.class.getName(),
|
bundleContext.registerService(Axis2ConfigurationContextObserver.class.getName(),
|
||||||
new PlatformManagementAxis2ConfigurationObserverImpl(), null);
|
new PlatformManagementAxis2ConfigurationObserverImpl(), null);
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import org.wso2.carbon.device.application.mgt.common.services.CategoryManager;
|
|||||||
import org.wso2.carbon.device.application.mgt.common.services.CommentsManager;
|
import org.wso2.carbon.device.application.mgt.common.services.CommentsManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
import org.wso2.carbon.device.application.mgt.common.services.LifecycleStateManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformManager;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.services.PlatformStorageManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
|
||||||
import org.wso2.carbon.device.application.mgt.common.services.VisibilityManager;
|
import org.wso2.carbon.device.application.mgt.common.services.VisibilityManager;
|
||||||
import org.wso2.carbon.device.application.mgt.core.config.ConfigurationManager;
|
import org.wso2.carbon.device.application.mgt.core.config.ConfigurationManager;
|
||||||
@ -99,6 +100,14 @@ public class ApplicationManagementUtil {
|
|||||||
return getInstance(extension, ApplicationStorageManager.class);
|
return getInstance(extension, ApplicationStorageManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PlatformStorageManager getPlatformStorageManagerInstance() throws
|
||||||
|
InvalidConfigurationException {
|
||||||
|
ConfigurationManager configurationManager = ConfigurationManager.getInstance();
|
||||||
|
Extension extension = configurationManager.getExtension(Extension.Name.PlatformStorageManager);
|
||||||
|
return getInstance(extension, PlatformStorageManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static <T> T getInstance(Extension extension, Class<T> cls) throws InvalidConfigurationException {
|
private static <T> T getInstance(Extension extension, Class<T> cls) throws InvalidConfigurationException {
|
||||||
try {
|
try {
|
||||||
Class theClass = Class.forName(extension.getClassName());
|
Class theClass = Class.forName(extension.getClassName());
|
||||||
|
|||||||
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.wso2.carbon.device.application.mgt.core.util;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.ImageArtifact;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationStorageManagementException;
|
||||||
|
import org.wso2.carbon.device.application.mgt.common.exception.ResourceManagementException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
public class StorageManagementUtil {
|
||||||
|
/**
|
||||||
|
* This method is responsible for creating artifact parent directories in the given path.
|
||||||
|
*
|
||||||
|
* @param artifactDirectoryPath Path for the artifact directory.
|
||||||
|
* @throws ApplicationStorageManagementException Application Storage Management Exception.
|
||||||
|
*/
|
||||||
|
public static void createArtifactDirectory(String artifactDirectoryPath) throws ResourceManagementException {
|
||||||
|
File artifactDirectory = new File(artifactDirectoryPath);
|
||||||
|
|
||||||
|
if (!artifactDirectory.exists()) {
|
||||||
|
if (!artifactDirectory.mkdirs()) {
|
||||||
|
throw new ResourceManagementException(
|
||||||
|
"Cannot create directories in the path to save the application related artifacts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To delete a directory recursively
|
||||||
|
*
|
||||||
|
* @param artifactDirectory Artifact Directory that need to be deleted.
|
||||||
|
*/
|
||||||
|
public static void deleteDir(File artifactDirectory) {
|
||||||
|
File[] contents = artifactDirectory.listFiles();
|
||||||
|
if (contents != null) {
|
||||||
|
for (File file : contents) {
|
||||||
|
deleteDir(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
artifactDirectory.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To save a file in a given location.
|
||||||
|
*
|
||||||
|
* @param inputStream Stream of the file.
|
||||||
|
* @param path Path the file need to be saved in.
|
||||||
|
*/
|
||||||
|
public static void saveFile(InputStream inputStream, String path) throws IOException {
|
||||||
|
OutputStream outStream = null;
|
||||||
|
try {
|
||||||
|
byte[] buffer = new byte[inputStream.available()];
|
||||||
|
inputStream.read(buffer);
|
||||||
|
outStream = new FileOutputStream(new File(path));
|
||||||
|
outStream.write(buffer);
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
if (outStream != null) {
|
||||||
|
outStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To create {@link ImageArtifact}.
|
||||||
|
*
|
||||||
|
* @param imageFile Image File.
|
||||||
|
* @param imageArtifactPath Path of the image artifact file.
|
||||||
|
* @return Image Artifact.
|
||||||
|
* @throws IOException IO Exception.
|
||||||
|
*/
|
||||||
|
public static ImageArtifact createImageArtifact(File imageFile, String imageArtifactPath) throws IOException {
|
||||||
|
ImageArtifact imageArtifact = new ImageArtifact();
|
||||||
|
imageArtifact.setName(imageFile.getName());
|
||||||
|
imageArtifact.setType(Files.probeContentType(imageFile.toPath()));
|
||||||
|
byte[] imageBytes = IOUtils.toByteArray(new FileInputStream(imageArtifactPath));
|
||||||
|
imageArtifact.setEncodedImage(Base64.encodeBase64URLSafeString(imageBytes));
|
||||||
|
return imageArtifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -58,4 +58,4 @@
|
|||||||
</Extension>
|
</Extension>
|
||||||
</Extensions>
|
</Extensions>
|
||||||
|
|
||||||
</ApplicationManagementConfiguration>
|
</ApplicationManagementConfiguration>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -10,18 +10,18 @@
|
|||||||
"license": "Apache License 2.0",
|
"license": "Apache License 2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.16.2",
|
"axios": "^0.16.2",
|
||||||
"bootstrap": "^4.0.0-alpha.6",
|
"bootstrap": "^4.0.0-beta",
|
||||||
"flux": "^3.1.3",
|
"flux": "^3.1.3",
|
||||||
"history": "^4.7.2",
|
"history": "^4.7.2",
|
||||||
"latest-version": "^3.1.0",
|
"latest-version": "^3.1.0",
|
||||||
"material-ui": "^0.19.1",
|
"material-ui": "^0.19.3",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.6.0",
|
||||||
"qs": "^6.5.0",
|
"qs": "^6.5.1",
|
||||||
"react": "^15.6.1",
|
"react": "^15.6.2",
|
||||||
"react-addons-css-transition-group": "^15.6.0",
|
"react-addons-css-transition-group": "^15.6.2",
|
||||||
"react-addons-transition-group": "^15.6.0",
|
"react-addons-transition-group": "^15.6.2",
|
||||||
"react-dom": "^15.6.1",
|
"react-dom": "^15.6.2",
|
||||||
"react-dropzone": "^4.1.2",
|
"react-dropzone": "^4.1.3",
|
||||||
"react-images-uploader": "^1.1.0",
|
"react-images-uploader": "^1.1.0",
|
||||||
"react-material-ui-form-validator": "^0.5.1",
|
"react-material-ui-form-validator": "^0.5.1",
|
||||||
"react-modal": "^2.3.2",
|
"react-modal": "^2.3.2",
|
||||||
@ -43,8 +43,8 @@
|
|||||||
"css-loader": "^0.28.7",
|
"css-loader": "^0.28.7",
|
||||||
"less": "^2.7.2",
|
"less": "^2.7.2",
|
||||||
"less-loader": "^4.0.4",
|
"less-loader": "^4.0.4",
|
||||||
"mocha": "^3.4.1",
|
"mocha": "^3.5.3",
|
||||||
"mock-local-storage": "^1.0.2",
|
"mock-local-storage": "^1.0.5",
|
||||||
"node-sass": "^4.5.3",
|
"node-sass": "^4.5.3",
|
||||||
"react-intl": "^2.4.0",
|
"react-intl": "^2.4.0",
|
||||||
"sass-loader": "^6.0.6",
|
"sass-loader": "^6.0.6",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@ -23,6 +23,7 @@
|
|||||||
<meta name="theme-color" content="#000000">
|
<meta name="theme-color" content="#000000">
|
||||||
<link rel="stylesheet" type="text/css" href="/publisher/css/font-wso2.css">
|
<link rel="stylesheet" type="text/css" href="/publisher/css/font-wso2.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/publisher/themes/default/default-theme.css">
|
<link rel="stylesheet" type="text/css" href="/publisher/themes/default/default-theme.css">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is added to the
|
manifest.json provides metadata used when your web app is added to the
|
||||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Title" : "Title",
|
"Title" : "Title",
|
||||||
"Description" : "Description",
|
"Description" : "Description",
|
||||||
|
"ShortDescription" : "Short Description",
|
||||||
"Category" : "Category",
|
"Category" : "Category",
|
||||||
"Visibility" : "Visibility",
|
"Visibility" : "Visibility",
|
||||||
"Devices" : "Devices",
|
"Devices" : "Devices",
|
||||||
@ -8,22 +9,26 @@
|
|||||||
"Groups" : "Groups",
|
"Groups" : "Groups",
|
||||||
"Tags" : "Tags",
|
"Tags" : "Tags",
|
||||||
"Platform" : "Platform",
|
"Platform" : "Platform",
|
||||||
"Platforms" : "Platfomrs",
|
"Platforms" : "Platforms",
|
||||||
|
"Applications": "Applications",
|
||||||
"No.Platform" : "No Platforms",
|
"No.Platform" : "No Platforms",
|
||||||
"Screenshots" : "Screenshots",
|
"Screenshots" : "Screenshots",
|
||||||
"Icon" : "Icon",
|
"Icon" : "Icon",
|
||||||
|
"Info" : "Info",
|
||||||
"Banner" : "Banner",
|
"Banner" : "Banner",
|
||||||
"Create.Application" : "Create Application",
|
"Create.Application" : "Create Application",
|
||||||
"Back" : "Back",
|
"Back" : "Back",
|
||||||
"Cancel" : "Cancel",
|
"Cancel" : "Cancel",
|
||||||
"Finish" : "Finish",
|
"Finish" : "Finish",
|
||||||
"Continue" : "Continue",
|
"Continue" : "Continue",
|
||||||
|
"Name" : "Name",
|
||||||
"Application.Name" : "Application Name",
|
"Application.Name" : "Application Name",
|
||||||
"General" : "General",
|
"General" : "General",
|
||||||
"App.Releases" : "Application Releases",
|
"App.Releases" : "Application Releases",
|
||||||
"Package.Manager" : "Package Manager",
|
"Package.Manager" : "Package Manager",
|
||||||
"Save" : "Save",
|
"Save" : "Save",
|
||||||
"Create.Release" : "Create Release",
|
"Create.Release" : "Create Release",
|
||||||
|
"Release.Channel" : "Release Channel",
|
||||||
"Release" : "Release",
|
"Release" : "Release",
|
||||||
"New.Release.For" : "New Release for",
|
"New.Release.For" : "New Release for",
|
||||||
"Upload.Package.File" : "Upload Package File",
|
"Upload.Package.File" : "Upload Package File",
|
||||||
@ -37,5 +42,20 @@
|
|||||||
"Alpha.Releases" : "Alpha Releases",
|
"Alpha.Releases" : "Alpha Releases",
|
||||||
"Version" : "Version",
|
"Version" : "Version",
|
||||||
"Status" : "Status",
|
"Status" : "Status",
|
||||||
"App.Publisher" : "Application Publisher"
|
"App.Publisher" : "Application Publisher",
|
||||||
|
"Search.Apps" : "Search for Applications",
|
||||||
|
"View.In.Store" : "View in Store",
|
||||||
|
"Last.Updated" : "Last updated on",
|
||||||
|
"Installs" : "Installs",
|
||||||
|
"General.Info" : "General Info",
|
||||||
|
"Select.Platform": "Select Platform",
|
||||||
|
"Add.Release" : "Add Release to Application",
|
||||||
|
"Share.With.Tenants" : "Share with Tenants",
|
||||||
|
"Disable" : "Disable",
|
||||||
|
"File.Based" : "File Based",
|
||||||
|
"Activate" : "Activate",
|
||||||
|
"Yes" : "Yes",
|
||||||
|
"No" : "No",
|
||||||
|
"No.Platform.Tags" : "No Platform Tags",
|
||||||
|
"Create.Platform" : "Create Platform"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.chip {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 25px;
|
|
||||||
height: 50px;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 50px;
|
|
||||||
border-radius: 25px;
|
|
||||||
background-color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chip img {
|
|
||||||
float: left;
|
|
||||||
margin: 0 10px 0 -25px;
|
|
||||||
height: 50px;
|
|
||||||
width: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
padding-left: 10px;
|
|
||||||
color: #888;
|
|
||||||
font-weight: bold;
|
|
||||||
float: right;
|
|
||||||
font-size: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn:hover {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
@ -16,10 +16,131 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Roboto-Medium";
|
||||||
|
src: url('../../fonts/Roboto-Medium.woff');
|
||||||
|
src: local("Roboto-Medium"), url("../../fonts/Roboto-Medium.ttf") format("ttf");
|
||||||
|
src: local("Roboto-Medium"), url("../../fonts/Roboto-Medium.woff") format("woff");
|
||||||
|
src: local("Roboto-Medium"), url("../../fonts/Roboto-Medium.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Roboto-Regular";
|
||||||
|
src: url("../../fonts/Roboto-Regular.woff");
|
||||||
|
src: local("Roboto-Regular"), url("../../fonts/Roboto-Regular.ttf") format("ttf");
|
||||||
|
src: local("Roboto-Regular"), url("../../fonts/Roboto-Regular.woff") format("woff");
|
||||||
|
src: local("Roboto-Regular"), url("../../fonts/Roboto-Regular.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Colors*/
|
||||||
|
.primary {
|
||||||
|
color: white;
|
||||||
|
background-color: #2196f3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-flat {
|
||||||
|
color: #2196F3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger {
|
||||||
|
color: white;
|
||||||
|
background-color: #e91e63 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-flat {
|
||||||
|
color: #e91e63 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grey {
|
||||||
|
color: #b3b3b3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================================================================== */
|
||||||
|
/* Custom button styles based on material design specs. */
|
||||||
|
|
||||||
|
.custom-raised {
|
||||||
|
font-family: Roboto-Medium;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
padding-left: 16px !important;
|
||||||
|
border-radius: 2px !important;
|
||||||
|
padding-right: 16px !important;
|
||||||
|
height: 36px !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-raised:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08) !important;
|
||||||
|
-webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08) !important;
|
||||||
|
background-color: #1976D2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-raised:focus {
|
||||||
|
box-shadow: none !important;
|
||||||
|
-webkit-box-shadow: none !important;
|
||||||
|
background-color: #1976D2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-flat {
|
||||||
|
font-family: Roboto-Medium;
|
||||||
|
height: 36px !important;
|
||||||
|
border-radius: 2px !important;
|
||||||
|
margin-left: 8px !important;
|
||||||
|
margin-right: 8px !important;
|
||||||
|
padding-left: 8px !important;
|
||||||
|
padding-right: 8px !important;
|
||||||
|
background-color: transparent !important;
|
||||||
|
text-transform: uppercase;
|
||||||
|
outline: none !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-flat:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: rgba(0, 0, 0, 0.12) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-flat:focus {
|
||||||
|
outline: none !important;
|
||||||
|
border: none !important;
|
||||||
|
-webkit-box-shadow: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
background-color: rgba(0, 0, 0, 0.40) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-button {
|
||||||
|
border-radius: 100% !important;
|
||||||
|
height: 36px !important;
|
||||||
|
width: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==================================================================== */
|
||||||
|
|
||||||
/* Body Styling */
|
/* Body Styling */
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: Roboto sans-serif;
|
font-family: "Roboto-Regular" !important;
|
||||||
|
background-color: #e8e8e8 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-manager-title {
|
||||||
|
font-family: "Roboto-Medium";
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-manager-sub-title {
|
||||||
|
font-family: "Roboto-Regular";
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app-mgt-footer {
|
||||||
|
clear: both;
|
||||||
|
position: relative;
|
||||||
|
height: 50px;
|
||||||
|
width: 100%;
|
||||||
|
color: white;
|
||||||
|
background-color: #334d88;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Login page styles*/
|
/* Login page styles*/
|
||||||
@ -31,35 +152,55 @@ body {
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-btn {
|
.login-btn {
|
||||||
border-radius: 0;
|
float: right;
|
||||||
background-color: navy;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-container {
|
.login-header {
|
||||||
width: 50%;
|
background-color: #3f50b5;
|
||||||
margin: 0 auto
|
color: white;
|
||||||
|
height: 128px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-card {
|
#login-card {
|
||||||
|
width: 25%;
|
||||||
|
height: 50%;
|
||||||
|
margin: 10% auto;
|
||||||
|
font-family: Roboto-Regular;
|
||||||
|
font-size: 14px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
background-color: #BaBaBa;
|
background-color: #ffffff;
|
||||||
|
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header-title {
|
||||||
|
font-family: Roboto-Medium;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header-logo {
|
||||||
|
height: 70px;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base layout container */
|
/* Base layout container */
|
||||||
#container {
|
|
||||||
background-color: #ffffff;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Base layout header content*/
|
/* Base layout header content*/
|
||||||
#header-content {
|
.header-content {
|
||||||
height: 125px;
|
height: 128px !important;
|
||||||
width: 100%;
|
width: 100% !important;
|
||||||
margin: 0 10px 0 0;
|
margin: 0 10px 0 0;
|
||||||
background-color: #3b33bd;
|
background-color: #3f50b5 !important;
|
||||||
position: fixed; /* Set the navbar to fixed position */
|
position: fixed; /* Set the navbar to fixed position */
|
||||||
top: 0; /* Position the navbar at the top of the page */
|
top: 0; /* Position the navbar at the top of the page */
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
@ -67,22 +208,59 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Contains the header styles.*/
|
/* Contains the header styles.*/
|
||||||
#header {
|
.header {
|
||||||
margin: 16px 16px 20px 16px;
|
padding: 24px 24px 10px 24px;
|
||||||
height: 100%;
|
/*margin: 16px 16px 20px 16px;*/
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header-text {
|
#header-text {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 25px;
|
font-size: 20px;
|
||||||
|
font-family: Roboto-Medium;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The buttons in the header (User and Notification)*/
|
/* The buttons in the header (User and Notification)*/
|
||||||
#header-btn-container {
|
.header-button-container {
|
||||||
float: right;
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-user-name {
|
||||||
|
font-family: Roboto-Medium;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-top: 15px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-image {
|
||||||
|
height: 43px;
|
||||||
|
width: 100px;
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-button {
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
margin-right: 10px;
|
||||||
|
position: relative;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-button:hover {
|
||||||
|
background-color: #4353bd;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-button i {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 19px;
|
||||||
|
left: 17px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-header {
|
.btn-header {
|
||||||
@ -91,21 +269,25 @@ body {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search box styles */
|
#sub-title {
|
||||||
.search-icon {
|
font-family: Roboto-Regular;
|
||||||
position: absolute;
|
font-size: 18px;
|
||||||
top: 5px;
|
font-weight: 600;
|
||||||
left: 5px;
|
padding-top: 5px;
|
||||||
|
padding-left: 18px;
|
||||||
|
color: RGBA(0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-box {
|
/* Search box styles */
|
||||||
|
.search-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
color: #a8a8a8;
|
|
||||||
position: relative;
|
|
||||||
float: right;
|
float: right;
|
||||||
top: 75px;
|
}
|
||||||
left: 80px;
|
|
||||||
margin-right: 16px;
|
.search-box i {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
color: #BaBaBa;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search {
|
#search {
|
||||||
@ -123,38 +305,114 @@ body {
|
|||||||
/* Application Add button */
|
/* Application Add button */
|
||||||
#add-btn-container {
|
#add-btn-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 12%;
|
top: 98px;
|
||||||
top: 100px;
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
background-color: #ff5722;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn:hover {
|
||||||
|
background-color: #E64A19;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app-main-content {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sub-title-container {
|
||||||
|
height: 100px;
|
||||||
|
padding: 50px 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-container {
|
||||||
|
padding: 0 !important;
|
||||||
|
min-height: 100% !important;
|
||||||
|
margin-top: 128px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Holds the app publisher pages. */
|
/* Holds the app publisher pages. */
|
||||||
#application-content {
|
#application-content {
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 80%;
|
background-color: white;
|
||||||
margin: 150px auto;
|
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: 10px 10px 10px 10px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stepper-header {
|
.stepper-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-bottom: solid 1px cornflowerblue;
|
color: #BaBaBa;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
margin-bottom: 10px;
|
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;
|
||||||
margin-right: 20px;
|
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.platform-link-placeholder i {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
#application-list {
|
#application-list {
|
||||||
margin-top: 20px;
|
|
||||||
transition: margin-right .5s;
|
transition: margin-right .5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#batch-content {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-list-icon {
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 50px;
|
||||||
|
width: 50px
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-table-row {
|
||||||
|
height: 62px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding-top: 6px;
|
||||||
|
font-family: "Roboto-Regular";
|
||||||
|
font-size: medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-table-row:hover {
|
||||||
|
color: white;
|
||||||
|
background-color: #3f50b5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-list-table-header {
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-family: "Roboto-Medium";
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-view-image {
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app-visibility-default {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#app-image-screenshot {
|
#app-image-screenshot {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
@ -170,12 +428,15 @@ body {
|
|||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#form-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
.application-create-banner-dropzone {
|
.application-create-banner-dropzone {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
border-radius: 5%;
|
border-radius: 5%;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: rgba(157, 159, 157, 0.53);
|
|
||||||
border: dashed #888888 2px;
|
border: dashed #888888 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +452,6 @@ body {
|
|||||||
margin: 0 5px 0 5px;
|
margin: 0 5px 0 5px;
|
||||||
border-radius: 10%;
|
border-radius: 10%;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: rgba(157, 159, 157, 0.53);
|
|
||||||
border: dashed #888888 2px;
|
border: dashed #888888 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +466,6 @@ body {
|
|||||||
height: 150px;
|
height: 150px;
|
||||||
border-radius: 10%;
|
border-radius: 10%;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: rgba(157, 159, 157, 0.53);
|
|
||||||
border: dashed #888888 2px;
|
border: dashed #888888 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +476,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#screenshot-container {
|
#screenshot-container {
|
||||||
|
max-width: 600px;
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
@ -232,6 +492,13 @@ body {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.step-index {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
background-color: #2196F3;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
#img-btn-screenshot {
|
#img-btn-screenshot {
|
||||||
margin: 0 5px 0 5px;
|
margin: 0 5px 0 5px;
|
||||||
}
|
}
|
||||||
@ -239,6 +506,7 @@ body {
|
|||||||
#app-create-modal {
|
#app-create-modal {
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
border-radius: 0% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#store {
|
#store {
|
||||||
@ -276,12 +544,13 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Application View */
|
/* Application View */
|
||||||
|
|
||||||
#application-view-content {
|
#application-view-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#application-view-row {
|
#application-view-row {
|
||||||
margin: 10px 10px 20px 20px;
|
margin: 10px 10px 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app-icon {
|
#app-icon {
|
||||||
@ -293,7 +562,6 @@ body {
|
|||||||
|
|
||||||
.app-updated-date {
|
.app-updated-date {
|
||||||
color: #888888;
|
color: #888888;
|
||||||
font-style: italic;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-install-count {
|
.app-install-count {
|
||||||
@ -315,12 +583,13 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Application Edit Base Layout */
|
/* Application Edit Base Layout */
|
||||||
|
|
||||||
#application-edit-header {
|
#application-edit-header {
|
||||||
height: 50px;
|
height: 40px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin-top: 20px;
|
||||||
font-size: 20px;
|
margin-bottom: 20px;
|
||||||
border-bottom: solid 1px #d8d8d8;
|
font-size: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.application-header-text {
|
.application-header-text {
|
||||||
@ -348,6 +617,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*Tab styling*/
|
/*Tab styling*/
|
||||||
|
|
||||||
div.tab {
|
div.tab {
|
||||||
float: left;
|
float: left;
|
||||||
border-right: 1px solid #d8d8d8;
|
border-right: 1px solid #d8d8d8;
|
||||||
@ -355,6 +625,7 @@ div.tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Style the tab buttons */
|
/* Style the tab buttons */
|
||||||
|
|
||||||
div.tab button {
|
div.tab button {
|
||||||
display: block;
|
display: block;
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
@ -369,30 +640,25 @@ div.tab button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Change background color of buttons on hover */
|
/* Change background color of buttons on hover */
|
||||||
|
|
||||||
div.tab button:hover {
|
div.tab button:hover {
|
||||||
background-color: #ddd6d7;
|
background-color: #ddd6d7;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create an active/current "tab button" class */
|
/* Create an active/current "tab button" class */
|
||||||
|
|
||||||
div.tab button.active {
|
div.tab button.active {
|
||||||
background-color: #1b3bcc;
|
background-color: #1b3bcc;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#application-edit-main-container {
|
#application-edit-main-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#application-edit-outer-content {
|
#application-edit-outer-content {
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#application-edit-content {
|
|
||||||
margin: 5px 10px 5px 10px;
|
|
||||||
width: 90%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#app-edit-content {
|
#app-edit-content {
|
||||||
@ -402,13 +668,13 @@ div.tab button.active {
|
|||||||
|
|
||||||
.back-to-app {
|
.back-to-app {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 40px;
|
height: 50px;
|
||||||
width: 40px;
|
width: 50px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-app i {
|
.back-to-app i {
|
||||||
padding: 10px 10px 10px 10px;
|
padding: 12px 10px 10px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-to-app:hover {
|
.back-to-app:hover {
|
||||||
@ -418,6 +684,7 @@ div.tab button.active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create Release and Release management */
|
/* Create Release and Release management */
|
||||||
|
|
||||||
.release-header {
|
.release-header {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
@ -472,6 +739,7 @@ div.tab button.active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Application Edit General Info */
|
/* Application Edit General Info */
|
||||||
|
|
||||||
.app-edit-general-info {
|
.app-edit-general-info {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@ -481,3 +749,92 @@ div.tab button.active {
|
|||||||
float: right;
|
float: right;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-view-field {
|
||||||
|
font-family: Roboto-Medium;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-view-text {
|
||||||
|
font-family: Roboto-Regular;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Platform Specific Styles. */
|
||||||
|
#platform-listing {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-platform i {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#platform-list {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content {
|
||||||
|
margin: 10px;
|
||||||
|
padding-top: 16px;
|
||||||
|
box-shadow: 2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content .row {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content .col {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content-basic {
|
||||||
|
padding: 0 16px 0 16px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content-more-outer {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content-more {
|
||||||
|
padding: 16px 16px 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content-footer {
|
||||||
|
display: flex;
|
||||||
|
padding: 8px 8px 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-text-container {
|
||||||
|
padding: 8px 16px 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-icon-letter {
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-family: Roboto-Medium;
|
||||||
|
font-size: 70px;
|
||||||
|
color: white;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-icon-container {
|
||||||
|
height: 120px;
|
||||||
|
width: 120px;
|
||||||
|
background-color: #01579B;
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08) !important;
|
||||||
|
-webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-content:hover {
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-table-row-cell {
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
|||||||
@ -35,8 +35,8 @@ export default class ApplicationMgtApi {
|
|||||||
*
|
*
|
||||||
* From applicationData, the proper application object will be created and send it to the api.
|
* From applicationData, the proper application object will be created and send it to the api.
|
||||||
* */
|
* */
|
||||||
static createApplication(applicationData) {
|
static createApplication(generalInfo, platform, screenshots, release) {
|
||||||
let {application, images} = Helper.buildApplication(applicationData);
|
let {application, images} = Helper.buildApplication(generalInfo, platform, screenshots, release);
|
||||||
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
console.log(application);
|
console.log(application);
|
||||||
console.log(images);
|
console.log(images);
|
||||||
|
|||||||
@ -25,26 +25,22 @@ export default class Helper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate application object from form data passed.
|
* Generate application object from form data passed.
|
||||||
* @param appData: Application data from the application creation form.
|
* @param generalInfo: Application data from the application creation form.
|
||||||
|
* @param platform
|
||||||
|
* @param screenshots
|
||||||
|
* @param release
|
||||||
* @return {Object, Object}: The application object and the set of images related to the application.
|
* @return {Object, Object}: The application object and the set of images related to the application.
|
||||||
* */
|
* */
|
||||||
static buildApplication(appData) {
|
static buildApplication(generalInfo, platform, screenshots, release) {
|
||||||
|
|
||||||
let application = {};
|
let images = screenshots;
|
||||||
let images = {};
|
let application = Object.assign({}, generalInfo, platform);
|
||||||
|
for (let prop in application) {
|
||||||
for (let step in appData) {
|
if (prop === 'tags') {
|
||||||
let tmpData = appData[step].data.step;
|
application[prop] = Helper.stringifyTags(generalInfo[prop]);
|
||||||
for (let prop in tmpData) {
|
|
||||||
if (prop === 'banner' || prop === 'screenshots' || prop === 'icon') {
|
|
||||||
images[prop] = tmpData[prop];
|
|
||||||
} else if(prop === 'tags') {
|
|
||||||
application[prop] = Helper.stringifyTags(tmpData[prop]);
|
|
||||||
} else {
|
|
||||||
application[prop] = tmpData[prop];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log(application);
|
||||||
return {application, images};
|
return {application, images};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,24 +15,24 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React, {Component} from 'react';
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform view component.
|
* This Utility class will contain basic methods for form validation.
|
||||||
* */
|
* */
|
||||||
class PlatformView extends Component {
|
export const validateURL = (value) => {
|
||||||
|
|
||||||
constructor() {
|
};
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
export const validateNull = (value) => {
|
||||||
return (
|
return !value;
|
||||||
<div>
|
};
|
||||||
Platform View
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PlatformView;
|
export const validateEmpty = (array) => {
|
||||||
|
return array.length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const validateEmptyObject = (object) => {
|
||||||
|
return Object.keys(object).length > 0;
|
||||||
|
};
|
||||||
@ -20,10 +20,11 @@ import PropTypes from 'prop-types';
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {withRouter} from 'react-router-dom';
|
import {withRouter} from 'react-router-dom';
|
||||||
import AuthHandler from "../../api/authHandler";
|
import AuthHandler from "../../api/authHandler";
|
||||||
|
import {Button, Col, Container, Input, Row,} from 'reactstrap';
|
||||||
import ApplicationCreate from '../Application/Create/ApplicationCreate';
|
import ApplicationCreate from '../Application/Create/ApplicationCreate';
|
||||||
import {Col, Container, Input, Row,} from 'reactstrap';
|
|
||||||
import FloatingButton from "../UIComponents/FloatingButton/FloatingButton";
|
import FloatingButton from "../UIComponents/FloatingButton/FloatingButton";
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
import Logo from "../UIComponents/Logo/Logo";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Layout:
|
* Base Layout:
|
||||||
@ -35,13 +36,21 @@ class BaseLayout extends Component {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
|
||||||
notifications: 0,
|
|
||||||
user: 'Admin',
|
|
||||||
openModal: false
|
|
||||||
};
|
|
||||||
this.logout = this.logout.bind(this);
|
this.logout = this.logout.bind(this);
|
||||||
this.closeModal = this.closeModal.bind(this);
|
this.closeModal = this.closeModal.bind(this);
|
||||||
|
this.onClickPlatforms = this.onClickPlatforms.bind(this);
|
||||||
|
this.onClickApplications = this.onClickApplications.bind(this);
|
||||||
|
this.state = {
|
||||||
|
notifications: 0,
|
||||||
|
user: '',
|
||||||
|
openModal: false,
|
||||||
|
currentPage: "",
|
||||||
|
logo: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.setState({user: this.props.user});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleApplicationClick() {
|
handleApplicationClick() {
|
||||||
@ -70,45 +79,112 @@ class BaseLayout extends Component {
|
|||||||
this.setState({openModal: false});
|
this.setState({openModal: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickPlatforms() {
|
||||||
|
window.location.href = "/publisher/assets/platforms";
|
||||||
|
this.setState({currentPage: "Platforms"})
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickApplications() {
|
||||||
|
window.location.href = "/publisher/assets/apps";
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentPageTitle() {
|
||||||
|
let href = window.location.href;
|
||||||
|
|
||||||
|
if (href.indexOf("apps") !== -1) {
|
||||||
|
return "Applications";
|
||||||
|
} else if (href.indexOf("platforms") !== -1) {
|
||||||
|
return "Platforms";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const userName = this.state.user._userName[0];
|
||||||
return (
|
return (
|
||||||
<Container noGutters fluid id="container">
|
<div>
|
||||||
<div id="header-content">
|
<div className="header-content">
|
||||||
<div id="header">
|
<div className="header">
|
||||||
<span id="header-text">
|
<Row>
|
||||||
WSO2 IoT <FormattedMessage id="App.Publisher" defaultMessage="Application Publisher"/>
|
<Col md="6">
|
||||||
</span>
|
<span id="header-text">
|
||||||
<div id="header-btn-container">
|
<Logo className="header-image" image_name="logo.png"/>
|
||||||
<i className="fw fw-notification btn-header"></i>
|
IoT <FormattedMessage id="App.Publisher" defaultMessage="Application Publisher"/>
|
||||||
<i className="fw fw-user btn-header"></i>
|
</span>
|
||||||
</div>
|
</Col>
|
||||||
<div id="search-box">
|
<Col>
|
||||||
<i className="fw fw-search search-icon">
|
<div className="header-button-container">
|
||||||
</i>
|
<Button id="header-button">
|
||||||
<Input
|
<i className="fw fw-notification btn-header"></i></Button>
|
||||||
id="search"
|
<span className="header-user-name">
|
||||||
name="search"
|
{userName.charAt(0).toUpperCase() + userName.slice(1)}
|
||||||
placeholder={'Search for Applications'}
|
</span>
|
||||||
onChange={(event) => console.log(event.target.value)} //TODO: Remove this
|
<Button id="header-button">
|
||||||
|
<i className="fw fw-user btn-header"></i></Button>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div className="search-box">
|
||||||
|
<i className="fw fw-search"></i>
|
||||||
|
<Input
|
||||||
|
id="search"
|
||||||
|
name="search"
|
||||||
|
placeholder={'Search for Applications'}
|
||||||
|
onChange={(event) => console.log(event.target.value)} //TODO: Remove this
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<Container>
|
||||||
|
<div id="add-btn-container">
|
||||||
|
<FloatingButton
|
||||||
|
className="add-btn small"
|
||||||
|
onClick={this.handleApplicationCreateClick.bind(this)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Container>
|
||||||
<div id="add-btn-container">
|
|
||||||
<FloatingButton
|
|
||||||
className="add-btn small"
|
|
||||||
onClick={this.handleApplicationCreateClick.bind(this)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="application-content" style={this.state.style}>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
{this.props.children}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</div>
|
</div>
|
||||||
|
<Container className="application-container">
|
||||||
|
<div id="app-main-content">
|
||||||
|
<Row id="sub-title-container">
|
||||||
|
<Col>
|
||||||
|
<div id="sub-title">
|
||||||
|
{/*TODO: Add the current page title*/}
|
||||||
|
{this.getCurrentPageTitle()}
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<div className="platform-link-placeholder">
|
||||||
|
{this.getCurrentPageTitle() === "Applications" ?
|
||||||
|
<Button className="custom-flat grey" onClick={this.onClickPlatforms}>
|
||||||
|
<i className="fw fw-settings"></i>
|
||||||
|
<FormattedMessage id="Platforms" defaultMessage="Platforms"/>
|
||||||
|
</Button> :
|
||||||
|
<Button className="custom-flat grey" onClick={this.onClickApplications}>
|
||||||
|
<i className="fw fw-application"></i>
|
||||||
|
<FormattedMessage id="Applications" defaultMessage="Applications"/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<div id="application-content">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
{this.props.children}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
<ApplicationCreate open={this.state.openModal} close={this.closeModal}/>
|
<ApplicationCreate open={this.state.openModal} close={this.closeModal}/>
|
||||||
</Container>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {withRouter} from 'react-router-dom';
|
import {withRouter} from 'react-router-dom';
|
||||||
import {Button, Col, Row, Table} from 'reactstrap';
|
import {Button, Col, Row} from 'reactstrap';
|
||||||
import Drawer from '../UIComponents/Drawer/Drawer';
|
import Drawer from '../UIComponents/Drawer/Drawer';
|
||||||
import ApplicationView from './View/ApplicationView';
|
import ApplicationView from './View/ApplicationView';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import ApplicationMgtApi from "../../api/applicationMgtApi";
|
||||||
|
import AuthHandler from "../../api/authHandler";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The App Create Component.
|
* The App Create Component.
|
||||||
@ -32,14 +33,15 @@ import {FormattedMessage} from 'react-intl';
|
|||||||
* When the wizard is completed, data will be arranged and sent to the api.
|
* When the wizard is completed, data will be arranged and sent to the api.
|
||||||
* */
|
* */
|
||||||
class ApplicationListing extends Component {
|
class ApplicationListing extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.searchApplications = this.searchApplications.bind(this);
|
this.searchApplications = this.searchApplications.bind(this);
|
||||||
this.onRowClick = this.onRowClick.bind(this);
|
this.onRowClick = this.onRowClick.bind(this);
|
||||||
this.setData = this.setData.bind(this);
|
|
||||||
this.sortData = this.sortData.bind(this);
|
this.sortData = this.sortData.bind(this);
|
||||||
this.compare = this.compare.bind(this);
|
this.compare = this.compare.bind(this);
|
||||||
this.handleButtonClick = this.handleButtonClick.bind(this);
|
this.onAppEditClick = this.onAppEditClick.bind(this);
|
||||||
|
this.getSelectedApplication = this.getSelectedApplication.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
searchedApplications: [],
|
searchedApplications: [],
|
||||||
applications: [],
|
applications: [],
|
||||||
@ -57,7 +59,6 @@ class ApplicationListing extends Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
applications = [
|
applications = [
|
||||||
{
|
{
|
||||||
id: "3242342ffww3423",
|
id: "3242342ffww3423",
|
||||||
@ -84,35 +85,59 @@ class ApplicationListing extends Component {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
headers = [
|
||||||
|
{
|
||||||
|
data_id: "image",
|
||||||
|
data_type: "image",
|
||||||
|
sortable: false,
|
||||||
|
label: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "applicationName",
|
||||||
|
data_type: "string",
|
||||||
|
sortable: true,
|
||||||
|
locale: "Application.name",
|
||||||
|
label: "Application Name",
|
||||||
|
sort: this.sortData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "platform",
|
||||||
|
data_type: "image_array",
|
||||||
|
sortable: false,
|
||||||
|
locale: "Platform",
|
||||||
|
label: "Platform"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "category",
|
||||||
|
data_type: "string",
|
||||||
|
sortable: false,
|
||||||
|
locale: "Category",
|
||||||
|
label: "Category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "status",
|
||||||
|
data_type: "string",
|
||||||
|
sortable: false,
|
||||||
|
locale: "Status",
|
||||||
|
label: "Status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "edit",
|
||||||
|
data_type: "button",
|
||||||
|
sortable: false,
|
||||||
|
label: ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
|
||||||
// let getApps = ApplicationMgtApi.getApplications();
|
let getApps = ApplicationMgtApi.getApplications();
|
||||||
// getApps.then(response => {
|
getApps.then(response => {
|
||||||
// let apps = this.setData(response.data.applications);
|
console.log(response);
|
||||||
// console.log(apps); //TODO: Remove this.
|
this.setState({searchedApplications: response.data.applications});
|
||||||
// this.setState({searchedApplications: apps});
|
}).catch(err => {
|
||||||
// // console.log(this.setState({data: response.data}), console.log(this.state));
|
AuthHandler.unauthorizedErrorHandler(err);
|
||||||
// }).catch(err => {
|
});
|
||||||
// AuthHandler.unauthorizedErrorHandler(err);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract application from application list and update the state.
|
|
||||||
* */
|
|
||||||
setData(applications) {
|
|
||||||
let apps = [];
|
|
||||||
for (let app in applications) {
|
|
||||||
let application = {};
|
|
||||||
application.id = applications[app].uuid;
|
|
||||||
application.applicationName = applications[app].name;
|
|
||||||
application.platform = applications[app].platform.name;
|
|
||||||
application.category = applications[app].category.id;
|
|
||||||
application.status = applications[app].currentLifecycle.lifecycleState.name;
|
|
||||||
apps.push(application);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({searchedApplications: apps});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,34 +179,22 @@ class ApplicationListing extends Component {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
onRowClick() {
|
onRowClick(uuid) {
|
||||||
|
let selectedApp = this.getSelectedApplication(uuid);
|
||||||
let style = {
|
let style = {
|
||||||
width: '500px',
|
width: '550px',
|
||||||
marginLeft: '500px'
|
marginLeft: '550px'
|
||||||
};
|
};
|
||||||
|
|
||||||
let appListStyle = {
|
let appListStyle = {
|
||||||
marginRight: '500px',
|
marginRight: '550px',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setState({drawer: style, appListStyle: appListStyle});
|
this.setState({drawer: style, appListStyle: appListStyle, application: selectedApp[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleButtonClick() {
|
onAppEditClick(uuid) {
|
||||||
console.log("Application Listing");
|
this.props.history.push("apps/edit/" + uuid);
|
||||||
this.props.history.push("apps/edit/fdsfdsf343");
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(imageId) {
|
|
||||||
let tmp = this.state.image;
|
|
||||||
|
|
||||||
console.log(imageId);
|
|
||||||
|
|
||||||
let rem = tmp.filter((image) => {
|
|
||||||
return image.id !== imageId
|
|
||||||
|
|
||||||
});
|
|
||||||
this.setState({image: rem});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closeDrawer() {
|
closeDrawer() {
|
||||||
@ -196,70 +209,56 @@ class ApplicationListing extends Component {
|
|||||||
this.setState({drawer: style, appListStyle: appListStyle});
|
this.setState({drawer: style, appListStyle: appListStyle});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
getSelectedApplication(uuid) {
|
||||||
return (
|
return this.state.searchedApplications.filter(application => {
|
||||||
|
return application.uuid === uuid;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
//TODO: Move this to a data table component.
|
||||||
|
return (
|
||||||
<div id="application-list" style={this.state.appListStyle}>
|
<div id="application-list" style={this.state.appListStyle}>
|
||||||
<Row>
|
<Row className="app-list-table-header">
|
||||||
<Col xs="3 offset-9">
|
{this.headers.map(header => {
|
||||||
<div className="platform-link-placeholder">
|
if (header.data_id === "applicationName") {
|
||||||
<Button><i className="fw fw-settings"></i>
|
return (
|
||||||
<FormattedMessage id="Platforms" defaultMessage="Platforms"/>
|
<Col xs="5">{header.label}</Col>)
|
||||||
</Button>
|
} else if (header.data_id === "image") {
|
||||||
</div>
|
return (<Col xs="1">{header.label}</Col>)
|
||||||
</Col>
|
}
|
||||||
</Row>
|
return (<Col>{header.label}</Col>)
|
||||||
<Row>
|
})}
|
||||||
<Col>
|
|
||||||
<Table striped hover>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
{/* TODO: Remove console.log and add sort method. */}
|
|
||||||
<th onClick={() => {
|
|
||||||
console.log("sort")
|
|
||||||
}}>
|
|
||||||
<FormattedMessage id="Application.Name" defaultMessage="Application Name"/>
|
|
||||||
</th>
|
|
||||||
<th><FormattedMessage id="Category" defaultMessage="Category"/></th>
|
|
||||||
<th><FormattedMessage id="Platform" defaultMessage="Platform"/></th>
|
|
||||||
<th><FormattedMessage id="Status" defaultMessage="Status"/></th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{this.applications.map(
|
|
||||||
(application) => {
|
|
||||||
return (
|
|
||||||
<tr key={application.id} onClick={this.onRowClick}>
|
|
||||||
<td>
|
|
||||||
{/* TODO: Move this styles to css. */}
|
|
||||||
<img
|
|
||||||
src={application.icon}
|
|
||||||
height='50px'
|
|
||||||
width='50px'
|
|
||||||
style={{border: 'solid 1px black', borderRadius: "100%"}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td>{application.applicationName}</td>
|
|
||||||
<td>{application.category}</td>
|
|
||||||
<td>{application.platform}</td>
|
|
||||||
<td>{application.status}</td>
|
|
||||||
<td>
|
|
||||||
<Button onClick={this.handleButtonClick}>
|
|
||||||
<i className="fw fw-edit"></i>
|
|
||||||
</Button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
|
<hr/>
|
||||||
|
{this.state.searchedApplications.map(application => {
|
||||||
|
return (
|
||||||
|
<Row className="app-table-row" onClick={() => {
|
||||||
|
this.onRowClick(application.uuid)
|
||||||
|
}}>
|
||||||
|
<Col xs="1">
|
||||||
|
<img
|
||||||
|
className="app-list-icon"
|
||||||
|
src={application.icon}
|
||||||
|
/>
|
||||||
|
</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
|
||||||
|
className="data-table-row-cell">{application.currentLifecycle.lifecycleState.name}
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Button className="custom-flat grey rounded"
|
||||||
|
onClick={() => this.onAppEditClick(application.uuid)}>
|
||||||
|
<i className="fw fw-edit"></i>
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
})}
|
||||||
<Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}>
|
<Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}>
|
||||||
<ApplicationView/>
|
<ApplicationView application={this.state.application}/>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -21,9 +21,10 @@ 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 {Button, Col, Modal, ModalBody, ModalFooter, ModalHeader, Row} from 'reactstrap';
|
import {Col, Modal, ModalBody, ModalHeader, Row} from 'reactstrap';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The App Create Component.
|
* The App Create Component.
|
||||||
*
|
*
|
||||||
@ -49,7 +50,11 @@ class ApplicationCreate extends Component {
|
|||||||
finished: false,
|
finished: false,
|
||||||
stepIndex: 0,
|
stepIndex: 0,
|
||||||
stepData: [],
|
stepData: [],
|
||||||
isDialogOpen: false
|
isDialogOpen: false,
|
||||||
|
generalInfo: {},
|
||||||
|
platform: {},
|
||||||
|
screenshots: {},
|
||||||
|
release: {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,17 +66,18 @@ class ApplicationCreate extends Component {
|
|||||||
this.setState({open: this.props.open});
|
this.setState({open: this.props.open});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the form and closes the modal.
|
||||||
|
* */
|
||||||
onClose() {
|
onClose() {
|
||||||
this.setState({stepIndex: 0}, this.props.close());
|
this.setState({stepIndex: 0, generalInfo: {}, platform: {}, screenshots: {}, release: {}}, this.props.close());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles next button click event.
|
* Handles next button click event.
|
||||||
* */
|
* */
|
||||||
onNextClick() {
|
onNextClick() {
|
||||||
console.log("Handle Next"); //TODO: Remove this
|
console.log(this.state.stepIndex); //TODO: Remove this
|
||||||
const {stepIndex} = this.state;
|
const {stepIndex} = this.state;
|
||||||
this.setState({
|
this.setState({
|
||||||
stepIndex: stepIndex + 1,
|
stepIndex: stepIndex + 1,
|
||||||
@ -83,8 +89,8 @@ class ApplicationCreate extends Component {
|
|||||||
* Handles form submit.
|
* Handles form submit.
|
||||||
* */
|
* */
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
let stepData = this.state.stepData;
|
let {generalInfo, platform, screenshots, release} = this.state;
|
||||||
let applicationCreationPromise = ApplicationMgtApi.createApplication(stepData);
|
let applicationCreationPromise = ApplicationMgtApi.createApplication(generalInfo, platform, screenshots, release);
|
||||||
applicationCreationPromise.then(response => {
|
applicationCreationPromise.then(response => {
|
||||||
this.handleYes();
|
this.handleYes();
|
||||||
}
|
}
|
||||||
@ -108,10 +114,10 @@ class ApplicationCreate extends Component {
|
|||||||
* This clears the data in the current step and returns to the previous step.
|
* This clears the data in the current step and returns to the previous step.
|
||||||
* */
|
* */
|
||||||
onPrevClick() {
|
onPrevClick() {
|
||||||
|
console.log(this.state.stepIndex);
|
||||||
const {stepIndex} = this.state;
|
const {stepIndex} = this.state;
|
||||||
if (stepIndex > 0) {
|
if (stepIndex > 0) {
|
||||||
this.removeStepData();
|
this.setState({stepIndex: stepIndex - 1, finished: false});
|
||||||
this.setState({stepIndex: stepIndex - 1});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,11 +127,25 @@ class ApplicationCreate extends Component {
|
|||||||
* @param data: The form data of the step.
|
* @param data: The form data of the step.
|
||||||
* */
|
* */
|
||||||
setStepData(step, data) {
|
setStepData(step, data) {
|
||||||
console.log(step, data, this.state.stepData); //TODO: Remove this
|
console.log(step, data, this.state); //TODO: Remove this
|
||||||
let tmpStepData = this.state.stepData;
|
switch (step) {
|
||||||
tmpStepData.push({step: step, data: data});
|
case "generalInfo": {
|
||||||
|
this.setState({generalInfo: data}, this.onNextClick());
|
||||||
this.setState({stepData: tmpStepData}, this.onNextClick())
|
break;
|
||||||
|
}
|
||||||
|
case "platform": {
|
||||||
|
this.setState({platform: data}, this.onNextClick());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "screenshots": {
|
||||||
|
this.setState({screenshots: data}, this.onNextClick());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "release": {
|
||||||
|
this.setState({release: data}, this.onNextClick());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,9 +154,10 @@ class ApplicationCreate extends Component {
|
|||||||
removeStepData() {
|
removeStepData() {
|
||||||
let tempData = this.state.stepData;
|
let tempData = this.state.stepData;
|
||||||
tempData.pop();
|
tempData.pop();
|
||||||
this.setState({stepData: tempData});
|
this.setState({stepData: tempData, stepIndex: 0});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ----------------- Deprecated ----------------- */
|
||||||
/**
|
/**
|
||||||
* Handles the Yes button in app creation cancellation dialog.
|
* Handles the Yes button in app creation cancellation dialog.
|
||||||
* Clears all the form data and reset the wizard.
|
* Clears all the form data and reset the wizard.
|
||||||
@ -153,6 +174,8 @@ class ApplicationCreate extends Component {
|
|||||||
this.setState({isDialogOpen: false});
|
this.setState({isDialogOpen: false});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines all the Steps in the stepper. (Wizard)
|
* Defines all the Steps in the stepper. (Wizard)
|
||||||
*
|
*
|
||||||
@ -167,35 +190,36 @@ class ApplicationCreate extends Component {
|
|||||||
case 0:
|
case 0:
|
||||||
return (
|
return (
|
||||||
<Step1
|
<Step1
|
||||||
handleNext={this.onNextClick}
|
defaultData={this.state.generalInfo}
|
||||||
setData={this.setStepData}
|
setStepData={this.setStepData}
|
||||||
removeData={this.removeStepData}
|
close={this.onClose}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 1:
|
case 1:
|
||||||
return (
|
return (
|
||||||
<Step2
|
<Step2
|
||||||
handleNext={this.onNextClick}
|
defaultData={this.state.platform}
|
||||||
handlePrev={this.onPrevClick}
|
handlePrev={this.onPrevClick}
|
||||||
setData={this.setStepData}
|
setStepData={this.setStepData}
|
||||||
removeData={this.removeStepData}
|
close={this.onClose}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 2:
|
case 2:
|
||||||
return (
|
return (
|
||||||
<Step3
|
<Step3
|
||||||
handleFinish={this.onNextClick}
|
defaultData={this.state.screenshots}
|
||||||
handlePrev={this.onPrevClick}
|
handlePrev={this.onPrevClick}
|
||||||
setData={this.setStepData}
|
setStepData={this.setStepData}
|
||||||
removeData={this.removeStepData}
|
close={this.onClose}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 3: {
|
case 3: {
|
||||||
return (
|
return (
|
||||||
<Step4
|
<Step4
|
||||||
handleNext={this.onNextClick}
|
defaultData={this.state.release}
|
||||||
setData={this.setStepData}
|
handlePrev={this.onPrevClick}
|
||||||
removeData={this.removeStepData}
|
onSubmit={this.onSubmit}
|
||||||
|
close={this.onClose}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -204,6 +228,10 @@ class ApplicationCreate extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setStepHeader(stepIndex) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {finished, stepIndex} = this.state;
|
const {finished, stepIndex} = this.state;
|
||||||
|
|
||||||
@ -218,7 +246,35 @@ class ApplicationCreate extends Component {
|
|||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<div className="stepper-header">
|
<div className="stepper-header">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div className="stepper-header-content">
|
||||||
|
<div className="step-index">1</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>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
@ -228,22 +284,6 @@ class ApplicationCreate extends Component {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
|
||||||
{stepIndex === 0 ? <div/> :
|
|
||||||
<Button color="primary" onClick={this.onPrevClick}>
|
|
||||||
<FormattedMessage id="Back" defaultMessage="Back"/>
|
|
||||||
</Button>}
|
|
||||||
<Button color="secondary" onClick={this.onClose}>
|
|
||||||
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
|
|
||||||
</Button>
|
|
||||||
{finished ?
|
|
||||||
<Button color="primary" onClick={this.onSubmit}>
|
|
||||||
<FormattedMessage id="Finish" defaultMessage="Finish" />
|
|
||||||
</Button> :
|
|
||||||
<Button color="primary" onClick={this.onNextClick}>
|
|
||||||
<FormattedMessage id="Continue" defaultMessage="Continue"/>
|
|
||||||
</Button>}
|
|
||||||
</ModalFooter>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,10 @@
|
|||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Badge, FormGroup, Input, Label} from 'reactstrap';
|
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
import {Button, Form, FormFeedback, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
|
||||||
|
import * as validator from '../../../../common/validator';
|
||||||
|
import Chip from "../../../UIComponents/Chip/Chip";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Second step of application create wizard.
|
* The Second step of application create wizard.
|
||||||
@ -42,22 +44,34 @@ import {FormattedMessage} from 'react-intl';
|
|||||||
class Step1 extends Component {
|
class Step1 extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this.onTextFieldChange = this.onTextFieldChange.bind(this);
|
||||||
|
this.setStepData = this.setStepData.bind(this);
|
||||||
|
this.onCancelClick = this.onCancelClick.bind(this);
|
||||||
|
this.onVisibilityChange = this.onVisibilityChange.bind(this);
|
||||||
|
this.onVisibilityItemSelect = this.onVisibilityItemSelect.bind(this);
|
||||||
|
this.handleRequestDelete = this.handleRequestDelete.bind(this);
|
||||||
|
this.validate = this.validate.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
tags: [],
|
tags: [],
|
||||||
icon: [],
|
name: "",
|
||||||
title: "",
|
|
||||||
errors: {},
|
errors: {},
|
||||||
banner: [],
|
|
||||||
defValue: "",
|
defValue: "",
|
||||||
category: 0,
|
category: {},
|
||||||
visibility: 0,
|
visibility: {type: "PUBLIC", allowedList: []},
|
||||||
description: "",
|
description: "",
|
||||||
screenshots: [],
|
|
||||||
identifier: "",
|
|
||||||
shortDescription: ""
|
shortDescription: ""
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
const defaultVals = this.props.defaultData;
|
||||||
|
|
||||||
|
if (defaultVals) {
|
||||||
|
this.setState(defaultVals);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a tag on Enter key press and set it to the state.
|
* Create a tag on Enter key press and set it to the state.
|
||||||
* Clears the tags text field.
|
* Clears the tags text field.
|
||||||
@ -85,81 +99,222 @@ class Step1 extends Component {
|
|||||||
* Handles Chip delete function.
|
* Handles Chip delete function.
|
||||||
* Removes the tag from state.tags
|
* Removes the tag from state.tags
|
||||||
* */
|
* */
|
||||||
handleRequestDelete(event) {
|
handleRequestDelete(key) {
|
||||||
this.chipData = this.state.tags;
|
let chipData = this.state.tags;
|
||||||
console.log(event.target);
|
const chipToDelete = chipData.map((chip) => chip.key).indexOf(key);
|
||||||
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
|
chipData.splice(chipToDelete, 1);
|
||||||
this.chipData.splice(chipToDelete, 1);
|
this.setState({tags: chipData});
|
||||||
this.setState({tags: this.chipData});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an object with the current step data and persist in the parent.
|
* Creates an object with the current step data and persist in the parent.
|
||||||
* */
|
* */
|
||||||
setStepData() {
|
setStepData() {
|
||||||
let stepData = {};
|
const {name, description, tags, visibility, shortDescription} = this.state;
|
||||||
this.props.setData("step1", {step: stepData});
|
let stepData = {
|
||||||
|
name: name,
|
||||||
|
description: description,
|
||||||
|
tags: tags,
|
||||||
|
visibility: visibility,
|
||||||
|
shortDescription: shortDescription,
|
||||||
|
category: {id: 1, name: "business"}
|
||||||
|
};
|
||||||
|
|
||||||
|
let {errorCount, errors} = this.validate();
|
||||||
|
|
||||||
|
if (errorCount !== 0) {
|
||||||
|
this.setState({errors: errors});
|
||||||
|
} else {
|
||||||
|
this.props.setStepData("generalInfo", stepData);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onCancelClick() {
|
||||||
|
this.props.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the form fields.
|
||||||
|
* */
|
||||||
|
validate() {
|
||||||
|
const {name, description, tags, shortDescription} = this.state;
|
||||||
|
let errorCount = 0;
|
||||||
|
let errors = {};
|
||||||
|
if (validator.validateNull(name)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.name = "Application Title is Required!";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validator.validateNull(description)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.description = "Description is Required!"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validator.validateNull(shortDescription)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.shortDescription = "Short Description is Required!"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validator.validateEmpty(tags)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.tags = "You need to enter at least one tag!"
|
||||||
|
}
|
||||||
|
return {errorCount, errors};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set text field values to state.
|
* Set text field values to state.
|
||||||
* */
|
* */
|
||||||
onTextFieldChange(event, value) {
|
onTextFieldChange(event) {
|
||||||
let field = event.target.id;
|
let field = event.target.name;
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case "name": {
|
case "appName": {
|
||||||
this.setState({name: value});
|
this.setState({name: event.target.value});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "shortDescription": {
|
case "appDescription": {
|
||||||
this.setState({shortDescription: value});
|
this.setState({description: event.target.value});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "description": {
|
case "appShortDescription": {
|
||||||
this.setState({description: value});
|
this.setState({shortDescription: event.target.value});
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "identifier": {
|
|
||||||
this.setState({identifier: value});
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onVisibilityChange(event) {
|
||||||
|
console.log(event.target.value);
|
||||||
|
this.setState({visibility: event.target.value});
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibilityItemSelect(event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
|
const {visibility} = this.state;
|
||||||
|
|
||||||
|
let visibilityItem = () => {
|
||||||
|
switch (visibility) {
|
||||||
|
case("public"): {
|
||||||
|
return <div/>
|
||||||
|
}
|
||||||
|
case("roles"): {
|
||||||
|
return <FormGroup>
|
||||||
|
<Input
|
||||||
|
type="select"
|
||||||
|
name="visibility-item"
|
||||||
|
id="app-visibility-item"
|
||||||
|
onChange={this.onVisibilityItemSelect}
|
||||||
|
>
|
||||||
|
<option id="app-visibility-default" disabled selected>Select the Roles.</option>
|
||||||
|
<option><Input type="checkbox"/>Role1</option>
|
||||||
|
<option>Role2</option>
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
}
|
||||||
|
case ("groups"): {
|
||||||
|
return <FormGroup>
|
||||||
|
<Input
|
||||||
|
type="select"
|
||||||
|
name="visibility-item"
|
||||||
|
id="app-visibility-item"
|
||||||
|
onChange={this.onVisibilityItemSelect}
|
||||||
|
>
|
||||||
|
<option id="app-visibility-default" disabled selected>Select the Groups.</option>
|
||||||
|
<option>Group1</option>
|
||||||
|
<option>Group2</option>
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return <div/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="createStep2Content">
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Label for="app-title">
|
<Label for="app-title">
|
||||||
<FormattedMessage id='Title' defaultMessage='Title'/>*
|
<FormattedMessage id='Title' defaultMessage='Title'/>*
|
||||||
</Label>
|
</Label>
|
||||||
<Input required type="text" name="appName" id="app-title"/>
|
<Input
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
name="appName"
|
||||||
|
id="app-title"
|
||||||
|
value={this.state.name}
|
||||||
|
onChange={this.onTextFieldChange}
|
||||||
|
/>
|
||||||
|
<FormFeedback id="form-error">{this.state.errors.name}</FormFeedback>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="app-short-description">
|
||||||
|
<FormattedMessage id="shortDescription" defaultMessage="shortDescription"/>*
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
required
|
||||||
|
type="textarea"
|
||||||
|
name="appShortDescription"
|
||||||
|
id="app-short-description"
|
||||||
|
value={this.state.shortDescription}
|
||||||
|
onChange={this.onTextFieldChange}
|
||||||
|
/>
|
||||||
|
<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 required type="textarea" name="appDescription" id="app-description"/>
|
<Input
|
||||||
|
required
|
||||||
|
type="textarea"
|
||||||
|
name="appDescription"
|
||||||
|
id="app-description"
|
||||||
|
value={this.state.description}
|
||||||
|
onChange={this.onTextFieldChange}
|
||||||
|
/>
|
||||||
|
<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 type="select" name="category" id="app-category">
|
<Input
|
||||||
<option>Business</option>
|
type="select"
|
||||||
|
name="category"
|
||||||
|
id="app-category"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
<Input type="select" name="visibility" id="app-visibility">
|
<Form inline>
|
||||||
<option><FormattedMessage id='Devices' defaultMessage='Devices'/></option>
|
<FormGroup>
|
||||||
<option><FormattedMessage id='Roles' defaultMessage='Roles'/></option>
|
<Input
|
||||||
<option><FormattedMessage id='Groups' defaultMessage='Groups'/></option>
|
type="select"
|
||||||
</Input>
|
name="visibility"
|
||||||
|
id="app-visibility"
|
||||||
|
onChange={this.onVisibilityChange}
|
||||||
|
>
|
||||||
|
<option id="app-visibility-default" disabled selected>Select the App Visibility
|
||||||
|
Option.
|
||||||
|
</option>
|
||||||
|
<option key={1}><FormattedMessage id='Devices' defaultMessage='Devices'/>
|
||||||
|
</option>
|
||||||
|
<option key={2}><FormattedMessage id='Roles' defaultMessage='Roles'/></option>
|
||||||
|
<option key={3}><FormattedMessage id='Groups' defaultMessage='Groups'/></option>
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
{visibilityItem()}
|
||||||
|
</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>
|
||||||
@ -172,23 +327,31 @@ class Step1 extends Component {
|
|||||||
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 (
|
||||||
<Badge
|
<Chip
|
||||||
style={{margin: '0 2px 0 2px'}}
|
key={tag.key}
|
||||||
value={tag.value}
|
content={tag}
|
||||||
onClick={this.handleRequestDelete.bind(this)}
|
onDelete={this.handleRequestDelete}
|
||||||
>
|
/>
|
||||||
{tag.value}
|
|
||||||
</Badge>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<FormFeedback id="form-error">{this.state.errors.tags}</FormFeedback>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -197,8 +360,7 @@ class Step1 extends Component {
|
|||||||
Step1.prototypes = {
|
Step1.prototypes = {
|
||||||
handleNext: PropTypes.func,
|
handleNext: PropTypes.func,
|
||||||
handlePrev: PropTypes.func,
|
handlePrev: PropTypes.func,
|
||||||
setData: PropTypes.func,
|
setData: PropTypes.func
|
||||||
removeData: PropTypes.func
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Step1;
|
export default Step1;
|
||||||
|
|||||||
@ -20,8 +20,9 @@ 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 {FormGroup, Input, Label} from 'reactstrap';
|
import {Button, FormFeedback, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
import * as validator from '../../../../common/validator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first step of the application creation wizard.
|
* The first step of the application creation wizard.
|
||||||
@ -41,24 +42,30 @@ class Step2 extends Component {
|
|||||||
super();
|
super();
|
||||||
this.setPlatforms = this.setPlatforms.bind(this);
|
this.setPlatforms = this.setPlatforms.bind(this);
|
||||||
this.setStepData = this.setStepData.bind(this);
|
this.setStepData = this.setStepData.bind(this);
|
||||||
|
this.onCancelClick = this.onCancelClick.bind(this);
|
||||||
|
this.onBackClick = this.onBackClick.bind(this);
|
||||||
|
this.validate = this.validate.bind(this);
|
||||||
this.platforms = [];
|
this.platforms = [];
|
||||||
this.state = {
|
this.state = {
|
||||||
finished: false,
|
errors: {},
|
||||||
stepIndex: 0,
|
|
||||||
store: 1,
|
store: 1,
|
||||||
platformSelectedIndex: 0,
|
platformSelectedIndex: 0,
|
||||||
platform: "",
|
platform: {},
|
||||||
platforms: [],
|
platforms: []
|
||||||
stepData: [],
|
|
||||||
title: "",
|
|
||||||
titleError: ""
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
const {defaultData} = this.props;
|
||||||
|
|
||||||
|
if (defaultData) {
|
||||||
|
this.setState(defaultData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
//Get the list of available platforms and set to the state.
|
//Get the list of available platforms and set to the state.
|
||||||
PlatformMgtApi.getPlatforms().then(response => {
|
PlatformMgtApi.getPlatforms().then(response => {
|
||||||
console.log(response);
|
|
||||||
this.setPlatforms(response.data);
|
this.setPlatforms(response.data);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
AuthHandler.unauthorizedErrorHandler(err);
|
AuthHandler.unauthorizedErrorHandler(err);
|
||||||
@ -76,25 +83,51 @@ class Step2 extends Component {
|
|||||||
platform = platforms[index];
|
platform = platforms[index];
|
||||||
tmpPlatforms.push(platform);
|
tmpPlatforms.push(platform);
|
||||||
}
|
}
|
||||||
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name})
|
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persist the current form data to the state.
|
* Persist the current form data to the state.
|
||||||
* */
|
* */
|
||||||
setStepData() {
|
setStepData() {
|
||||||
let step = {
|
const {store, platform} = this.state;
|
||||||
store: this.state.store,
|
let data = {
|
||||||
platform: this.state.platforms[this.state.platformSelectedIndex]
|
store: store,
|
||||||
|
platform: platform[0]
|
||||||
};
|
};
|
||||||
this.props.setData("step2", {step: step});
|
|
||||||
|
const {errorCount, errors} = this.validate();
|
||||||
|
|
||||||
|
if (errorCount > 0) {
|
||||||
|
this.setState({errors: errors})
|
||||||
|
} else {
|
||||||
|
this.props.setStepData("platform", data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancelClick() {
|
||||||
|
this.props.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackClick() {
|
||||||
|
this.props.handlePrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
const {store, platform} = this.state;
|
||||||
|
let errors = {};
|
||||||
|
let errorCount = 0;
|
||||||
|
if (!validator.validateEmptyObject(platform)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.platform = "You must select an application platform!"
|
||||||
|
}
|
||||||
|
return {errorCount, errors};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers when changing the Platform selection.
|
* Triggers when changing the Platform selection.
|
||||||
* */
|
* */
|
||||||
onChangePlatform(event) {
|
onChangePlatform(event) {
|
||||||
console.log(event.target.value, this.state.platforms);
|
|
||||||
let id = event.target.value;
|
let id = event.target.value;
|
||||||
let selectedPlatform = this.state.platforms.filter((platform) => {
|
let selectedPlatform = this.state.platforms.filter((platform) => {
|
||||||
return platform.identifier === id;
|
return platform.identifier === id;
|
||||||
@ -122,16 +155,34 @@ class Step2 extends Component {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Label for="store"><FormattedMessage id='Platform' defaultMessage='Platform'/></Label>
|
<Label for="store"><FormattedMessage id='Platform' defaultMessage='Platform'/></Label>
|
||||||
<Input type="select" name="store" onChange={this.onChangePlatform.bind(this)}>
|
<Input
|
||||||
|
required
|
||||||
|
type="select"
|
||||||
|
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 => {
|
{this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
|
||||||
return (
|
return (
|
||||||
<option value={platform.identifier}>
|
<option value={platform.identifier} key={platform.identifier}>
|
||||||
{platform.name}
|
{platform.name}
|
||||||
</option>
|
</option>
|
||||||
)
|
)
|
||||||
}) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>}
|
}) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>}
|
||||||
</Input>
|
</Input>
|
||||||
|
<FormFeedback id="form-error">{this.state.errors.platform}</FormFeedback>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
import PropTypes from 'prop-types';
|
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 {FormGroup, Label} from 'reactstrap';
|
import * as validator from '../../../../common/validator';
|
||||||
|
import {Button, FormFeedback, FormGroup, Label, 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';
|
||||||
|
|
||||||
@ -40,47 +41,77 @@ import {FormattedMessage} from 'react-intl';
|
|||||||
class Step3 extends Component {
|
class Step3 extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this.setStepData = this.setStepData.bind(this);
|
||||||
|
this.onBackClick = this.onBackClick.bind(this);
|
||||||
|
this.validate = this.validate.bind(this);
|
||||||
|
this.onCancelClick = this.onCancelClick.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
tags: [],
|
|
||||||
icon: [],
|
icon: [],
|
||||||
title: "",
|
|
||||||
errors: {},
|
errors: {},
|
||||||
banner: [],
|
banner: [],
|
||||||
defValue: "",
|
|
||||||
category: 0,
|
|
||||||
visibility: 0,
|
|
||||||
description: "",
|
|
||||||
screenshots: [],
|
screenshots: [],
|
||||||
identifier: "",
|
|
||||||
shortDescription: ""
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
componentWillMount() {
|
||||||
* Handles Chip delete function.
|
const {defaultData} = this.props;
|
||||||
* Removes the tag from state.tags
|
|
||||||
* */
|
this.setState(defaultData);
|
||||||
handleRequestDelete(event) {
|
}
|
||||||
this.chipData = this.state.tags;
|
|
||||||
console.log(event.target); //TODO: Remove Console log.
|
|
||||||
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
|
|
||||||
this.chipData.splice(chipToDelete, 1);
|
|
||||||
this.setState({tags: this.chipData});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an object with the current step data and persist in the parent.
|
* Creates an object with the current step data and persist in the parent.
|
||||||
* */
|
* */
|
||||||
setStepData() {
|
setStepData() {
|
||||||
|
|
||||||
|
const {icon, banner, screenshots} = this.state;
|
||||||
|
|
||||||
let stepData = {
|
let stepData = {
|
||||||
icon: this.state.icon,
|
icon: icon,
|
||||||
banner: this.state.banner,
|
banner: banner,
|
||||||
screenshots: this.state.screenshots
|
screenshots: screenshots
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.setData("step2", {step: stepData});
|
const {errorCount, errors} = this.validate();
|
||||||
|
|
||||||
|
if (errorCount > 0) {
|
||||||
|
this.setState({errors: errors})
|
||||||
|
} else {
|
||||||
|
this.props.setStepData("screenshots", stepData);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onCancelClick() {
|
||||||
|
this.props.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackClick() {
|
||||||
|
this.props.handlePrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
const {icon, banner, screenshots} = this.state;
|
||||||
|
let errors = {}, errorCount = 0;
|
||||||
|
|
||||||
|
if (!validator.validateEmpty(icon)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.icon = "You must upload an icon image!"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validator.validateEmpty(banner)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.banner = "You must upload a banner image!"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validator.validateEmpty(screenshots)) {
|
||||||
|
errorCount++;
|
||||||
|
errors.screenshots = "You must upload at least one screenshot image!"
|
||||||
|
}
|
||||||
|
|
||||||
|
return {errorCount, errors};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removed user uploaded banner.
|
* Removed user uploaded banner.
|
||||||
* */
|
* */
|
||||||
@ -126,7 +157,6 @@ class Step3 extends Component {
|
|||||||
onDrop={(screenshots, rejected) => {
|
onDrop={(screenshots, rejected) => {
|
||||||
let tmpScreenshots = this.state.screenshots;
|
let tmpScreenshots = this.state.screenshots;
|
||||||
tmpScreenshots.push(screenshots);
|
tmpScreenshots.push(screenshots);
|
||||||
console.log(screenshots); //TODO: Remove this
|
|
||||||
this.setState({
|
this.setState({
|
||||||
screenshots: tmpScreenshots
|
screenshots: tmpScreenshots
|
||||||
});
|
});
|
||||||
@ -135,6 +165,7 @@ class Step3 extends Component {
|
|||||||
<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.screenshots}</FormFeedback>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: 'flex'}}>
|
<div style={{display: 'flex'}}>
|
||||||
@ -162,6 +193,7 @@ class Step3 extends Component {
|
|||||||
<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>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</div>
|
||||||
<div style={{marginLeft: '15px'}}>
|
<div style={{marginLeft: '15px'}}>
|
||||||
@ -188,9 +220,21 @@ class Step3 extends Component {
|
|||||||
</Dropzone> : <div/>
|
</Dropzone> : <div/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
<FormFeedback id="form-error">{this.state.errors.banner}</FormFeedback>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,9 @@
|
|||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Collapse, FormGroup, Input, Label, FormText} from 'reactstrap';
|
import {Button, Collapse, FormGroup, FormText, Input, Label, ModalFooter} from 'reactstrap';
|
||||||
import Switch from '../../../UIComponents/Switch/Switch'
|
import Switch from '../../../UIComponents/Switch/Switch'
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Third step of application create wizard. {Application Release Step}
|
* The Third step of application create wizard. {Application Release Step}
|
||||||
@ -47,9 +48,10 @@ class Step4 extends Component {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.handleToggle = this.handleToggle.bind(this);
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
this.handlePrev = this.handlePrev.bind(this);
|
this.onCancelClick = this.onCancelClick.bind(this);
|
||||||
this.handleToggle = this.handleToggle.bind(this);
|
this.onBackClick = this.onBackClick.bind(this);
|
||||||
this.handleFinish = this.handleFinish.bind(this);
|
this.handleFinish = this.handleFinish.bind(this);
|
||||||
|
this.onSubmit = this.onSubmit.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
showForm: false,
|
showForm: false,
|
||||||
releaseChannel: 1,
|
releaseChannel: 1,
|
||||||
@ -66,13 +68,18 @@ class Step4 extends Component {
|
|||||||
this.props.handleFinish();
|
this.props.handleFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
onCancelClick() {
|
||||||
* Invokes Prev button click.
|
this.props.close();
|
||||||
* */
|
}
|
||||||
handlePrev() {
|
|
||||||
|
onBackClick() {
|
||||||
this.props.handlePrev();
|
this.props.handlePrev();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.props.onSubmit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles release application selection.
|
* Handles release application selection.
|
||||||
* */
|
* */
|
||||||
@ -90,7 +97,7 @@ class Step4 extends Component {
|
|||||||
<div id="app-release-switch-label">
|
<div id="app-release-switch-label">
|
||||||
<Label for="app-release-switch">
|
<Label for="app-release-switch">
|
||||||
<strong>
|
<strong>
|
||||||
Add Release to Application
|
<FormattedMessage id="Add.Release" defaultMessage="Add.Release"/>
|
||||||
</strong>
|
</strong>
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
@ -104,17 +111,19 @@ class Step4 extends Component {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
<br/>
|
<br/>
|
||||||
<div>
|
<div>
|
||||||
<FormText color="muted">
|
<FormText color="muted">
|
||||||
<i>Info: </i>
|
<i><FormattedMessage id="Info" defaultMessage="Info"/> </i>
|
||||||
Enabling this will create a release for the current Application.
|
Enabling this will create a release for the current Application.
|
||||||
To upload the Application, please visit to the Release management section of
|
To upload the Application, please visit to the Release management section of
|
||||||
Application Edit View.
|
Application Edit View.
|
||||||
</FormText>
|
</FormText>
|
||||||
</div>
|
</div>
|
||||||
{/*If toggle is true, the release form will be shown.*/}
|
{/*If toggle is true, the release form will be shown.*/}
|
||||||
<Collapse isOpen={this.state.showForm}>
|
<Collapse isOpen={this.state.showForm}>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Label for="release-channel">Release Channel</Label>
|
<Label for="release-channel">
|
||||||
|
<FormattedMessage id="Release.Channel" defaultMessage="Release.Channel"/>
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
type="select"
|
type="select"
|
||||||
id="release-channel"
|
id="release-channel"
|
||||||
@ -130,7 +139,9 @@ class Step4 extends Component {
|
|||||||
</Input>
|
</Input>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Label for="version">Version*</Label>
|
<Label for="version">
|
||||||
|
<FormattedMessage id="Version" defaultMessage="Version"/>*
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
id="version input-custom"
|
id="version input-custom"
|
||||||
@ -140,6 +151,17 @@ class Step4 extends Component {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</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.onSubmit}>
|
||||||
|
<FormattedMessage id="Finish" defaultMessage="Finish"/>
|
||||||
|
</Button>
|
||||||
|
</ModalFooter>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -149,7 +171,7 @@ Step4.propTypes = {
|
|||||||
handleFinish: PropTypes.func,
|
handleFinish: PropTypes.func,
|
||||||
handlePrev: PropTypes.func,
|
handlePrev: PropTypes.func,
|
||||||
setData: PropTypes.func,
|
setData: PropTypes.func,
|
||||||
removeData: PropTypes.func
|
onSubmit: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Step4;
|
export default Step4;
|
||||||
|
|||||||
@ -89,6 +89,7 @@ class ApplicationEdit extends Component {
|
|||||||
<FormattedMessage id="Application.Name" defaultMessage="Application Name"/>
|
<FormattedMessage id="Application.Name" defaultMessage="Application Name"/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<hr/>
|
||||||
<Row id="application-edit-main-container">
|
<Row id="application-edit-main-container">
|
||||||
<Col xs="3">
|
<Col xs="3">
|
||||||
<div className="tab">
|
<div className="tab">
|
||||||
@ -104,17 +105,9 @@ class ApplicationEdit extends Component {
|
|||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs="9">
|
<Col xs="9">
|
||||||
<div id="app-edit-content">
|
{/* Application edit content */}
|
||||||
<Row>
|
<div id="application-edit-content">
|
||||||
<Col xs="12">
|
{this.getTabContent(this.state.activeTab)}
|
||||||
<div id="application-edit-outer-content">
|
|
||||||
{/* Application edit content */}
|
|
||||||
<div id="application-edit-content">
|
|
||||||
{this.getTabContent(this.state.activeTab)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@ -17,16 +17,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Badge, Button, FormGroup, Input, Label, Row} from 'reactstrap';
|
import {Button, FormGroup, Input, Label, Row} from 'reactstrap';
|
||||||
import Dropzone from 'react-dropzone';
|
import Dropzone from 'react-dropzone';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
import Chip from "../../../UIComponents/Chip/Chip";
|
||||||
|
|
||||||
class GeneralInfo extends Component {
|
class GeneralInfo extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this.onTextFieldChange = this.onTextFieldChange.bind(this);
|
||||||
|
this.addTags = this.addTags.bind(this);
|
||||||
|
this.handleRequestDelete = this.handleRequestDelete.bind(this);
|
||||||
|
this.handleTagChange = this.handleTagChange.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
defValue: "",
|
defValue: "",
|
||||||
|
title: "",
|
||||||
|
description: "",
|
||||||
|
shortDescription: "",
|
||||||
tags: [],
|
tags: [],
|
||||||
screenshots: [],
|
screenshots: [],
|
||||||
icon: [],
|
icon: [],
|
||||||
@ -34,6 +42,62 @@ class GeneralInfo extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text field values to state.
|
||||||
|
* */
|
||||||
|
onTextFieldChange(event) {
|
||||||
|
let field = event.target.name;
|
||||||
|
console.log(event.target.value);
|
||||||
|
switch (field) {
|
||||||
|
case "appName": {
|
||||||
|
this.setState({name: event.target.value});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "appDescription": {
|
||||||
|
this.setState({description: event.target.value});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "appShortDescription": {
|
||||||
|
this.setState({shortDescription: event.target.value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a tag on Enter key press and set it to the state.
|
||||||
|
* Clears the tags text field.
|
||||||
|
* Chip gets two parameters: Key and value.
|
||||||
|
* */
|
||||||
|
addTags(event) {
|
||||||
|
let tags = this.state.tags;
|
||||||
|
if (event.charCode === 13) {
|
||||||
|
event.preventDefault();
|
||||||
|
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
|
||||||
|
this.setState({tags, defValue: ""}, console.log(tags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value for tag.
|
||||||
|
* */
|
||||||
|
handleTagChange(event) {
|
||||||
|
let defaultValue = this.state.defValue;
|
||||||
|
defaultValue = event.target.value;
|
||||||
|
this.setState({defValue: defaultValue})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Chip delete function.
|
||||||
|
* Removes the tag from state.tags
|
||||||
|
* */
|
||||||
|
handleRequestDelete(key) {
|
||||||
|
let chipData = this.state.tags;
|
||||||
|
const chipToDelete = chipData.map((chip) => chip.key).indexOf(key);
|
||||||
|
chipData.splice(chipToDelete, 1);
|
||||||
|
this.setState({tags: chipData});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//TODO: Remove Console logs.
|
//TODO: Remove Console logs.
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@ -44,18 +108,31 @@ class GeneralInfo extends Component {
|
|||||||
<Label for="app-title">
|
<Label for="app-title">
|
||||||
<FormattedMessage id="Title" defaultMessage="Title"/>*
|
<FormattedMessage id="Title" defaultMessage="Title"/>*
|
||||||
</Label>
|
</Label>
|
||||||
|
<Input required type="text" name="appName" id="app-title"
|
||||||
|
onChange={this.onTextFieldChange}/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="app-short-description">
|
||||||
|
<FormattedMessage id="shortDescription" defaultMessage="shortDescription"/>*
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
required
|
required
|
||||||
type="text"
|
type="textarea"
|
||||||
name="appName"
|
name="appShortDescription"
|
||||||
id="app-title"
|
id="app-short-description"
|
||||||
|
onChange={this.onTextFieldChange}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Label for="app-title">
|
<Label for="app-title">
|
||||||
<FormattedMessage id="Description" defaultMessage="Description"/>*
|
<FormattedMessage id="Description" defaultMessage="Description"/>*
|
||||||
</Label>
|
</Label>
|
||||||
<Input required type="textarea" multiline name="appName" id="app-title"/>
|
<Input
|
||||||
|
required
|
||||||
|
type="textarea"
|
||||||
|
name="appDescription"
|
||||||
|
id="app-description"
|
||||||
|
onChange={this.onTextFieldChange}/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<Label for="app-category">
|
<Label for="app-category">
|
||||||
@ -79,16 +156,23 @@ class GeneralInfo extends Component {
|
|||||||
<Label for="app-tags">
|
<Label for="app-tags">
|
||||||
<FormattedMessage id="Tags" defaultMessage="Tags"/>*
|
<FormattedMessage id="Tags" defaultMessage="Tags"/>*
|
||||||
</Label>
|
</Label>
|
||||||
<Input required type="text" value={this.state.defValue} name="app-tags" id="app-tags"/>
|
<Input
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
value={this.state.defValue}
|
||||||
|
name="app-tags"
|
||||||
|
id="app-tags"
|
||||||
|
onChange={this.handleTagChange.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 (
|
||||||
<Badge
|
<Chip
|
||||||
style={{margin: '0 2px 0 2px'}}
|
key={tag.key}
|
||||||
value={tag.value}
|
content={tag}
|
||||||
>
|
onDelete={this.handleRequestDelete}
|
||||||
{tag.value}
|
/>
|
||||||
</Badge>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
@ -102,12 +186,14 @@ class GeneralInfo extends Component {
|
|||||||
<span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
|
<span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
|
||||||
<div id="screenshot-container">
|
<div id="screenshot-container">
|
||||||
{this.state.screenshots.map((tile) => (
|
{this.state.screenshots.map((tile) => (
|
||||||
<button id="img-btn-screenshot" style={{height: '210px', width: '410px'}}
|
<button id="img-btn-screenshot"
|
||||||
|
style={{height: '210px', width: '410px'}}
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
console.log("Mouse Entered")
|
console.log("Mouse Entered")
|
||||||
}}>
|
}}>
|
||||||
{console.log(tile[0].preview)}
|
{console.log(tile[0].preview)}
|
||||||
<img style={{height: '200px', width: '400px'}} src={tile[0].preview}/>
|
<img style={{height: '200px', width: '400px'}}
|
||||||
|
src={tile[0].preview}/>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
{this.state.screenshots.length < 3 ?
|
{this.state.screenshots.length < 3 ?
|
||||||
@ -140,7 +226,8 @@ class GeneralInfo extends Component {
|
|||||||
<button onMouseEnter={() => {
|
<button onMouseEnter={() => {
|
||||||
console.log("Mouse Entered")
|
console.log("Mouse Entered")
|
||||||
}}>
|
}}>
|
||||||
<img style={{height: '200px', width: '200px'}} src={tile.preview}/>
|
<img style={{height: '200px', width: '200px'}}
|
||||||
|
src={tile.preview}/>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
{this.state.icon.length === 0 ?
|
{this.state.icon.length === 0 ?
|
||||||
@ -167,7 +254,8 @@ class GeneralInfo extends Component {
|
|||||||
<button onMouseEnter={() => {
|
<button onMouseEnter={() => {
|
||||||
console.log("Mouse Entered")
|
console.log("Mouse Entered")
|
||||||
}}>
|
}}>
|
||||||
<img style={{height: '200px', width: '400px'}} src={tile.preview}/>
|
<img style={{height: '200px', width: '400px'}}
|
||||||
|
src={tile.preview}/>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
{this.state.banner.length === 0 ?
|
{this.state.banner.length === 0 ?
|
||||||
@ -186,9 +274,8 @@ class GeneralInfo extends Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="save-info">
|
<div className="save-info">
|
||||||
<Button>
|
<Button className="custom-flat danger-flat">Cancel</Button>
|
||||||
<FormattedMessage id="Save" defaultMessage="Save"/>
|
<Button className="custom-raised primary">Save</Button>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
|
|
||||||
class PackageManager extends Component {
|
class PackageManager extends Component {
|
||||||
@ -26,7 +25,7 @@ class PackageManager extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return(
|
return (
|
||||||
<div id="package-mgt-content">
|
<div id="package-mgt-content">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -92,7 +92,9 @@ class CreateRelease extends Component {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button id="create-release-btn" onClick={this.showUploadArtifacts}>Create a {channel} Release</Button>
|
<Button id="create-release-btn" onClick={this.showUploadArtifacts}>Create
|
||||||
|
a {channel}
|
||||||
|
Release</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@ -41,7 +41,8 @@ class UploadPackage extends Component {
|
|||||||
<a onClick={this.handleBack}>{"<-"}</a>
|
<a onClick={this.handleBack}>{"<-"}</a>
|
||||||
<span id="create-release-header">
|
<span id="create-release-header">
|
||||||
<strong>
|
<strong>
|
||||||
<FormattedMessage id="New.Release.For" defaultMessage="New Release For"/> {selectedChannel}
|
<FormattedMessage id="New.Release.For"
|
||||||
|
defaultMessage="New Release For"/> {selectedChannel}
|
||||||
</strong>
|
</strong>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -47,91 +47,108 @@ class ApplicationView extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const platform = this.state.application;
|
if (this.state.application.length === 0) {
|
||||||
console.log(platform);
|
return <div/>
|
||||||
|
} else {
|
||||||
|
const app = this.state.application;
|
||||||
|
console.log(app);
|
||||||
|
return (
|
||||||
|
<div id="application-view-content">
|
||||||
|
<div id="application-view-row">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div id="app-icon">
|
||||||
|
{/*TODO: Remove this*/}
|
||||||
|
<img
|
||||||
|
className="app-view-image"
|
||||||
|
src={app.icon}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Row>
|
||||||
|
<p className="app-view-field">{app.name}</p>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<span className="app-updated-date app-view-text">
|
||||||
|
<FormattedMessage id="Last.Updated"
|
||||||
|
defaultMessage="Last.Updated"/> {app.modifiedAt}</span>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<div id="application-view-row">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<span className="app-install-count app-view-text">
|
||||||
|
2k <FormattedMessage id="Installs" defaultMessage="Installs"/>
|
||||||
|
</span>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<i className="fw fw-star"></i>
|
||||||
|
<i className="fw fw-star"></i>
|
||||||
|
<i className="fw fw-star"></i>
|
||||||
|
<i className="fw fw-star"></i>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">
|
||||||
|
<a href="#">
|
||||||
|
<FormattedMessage id="View.In.Store" defaultMessage="View.In.Store"/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div id="application-view-row">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-field">
|
||||||
|
<FormattedMessage id="Description" defaultMessage="Description"/>:
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">{app.description}</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-field">
|
||||||
|
<FormattedMessage id="Tags" defaultMessage="Tags"/>:
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">[list of tags...]</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-field">
|
||||||
|
<FormattedMessage id="Release" defaultMessage="Release"/>:
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">Production</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-field">
|
||||||
|
<FormattedMessage id="Version" defaultMessage="Version"/>:
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">v1.0</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
return (
|
);
|
||||||
<div id="application-view-content">
|
|
||||||
<div id="application-view-row">
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<div id="app-icon">
|
|
||||||
|
|
||||||
</div>
|
}
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Row>
|
|
||||||
<span><strong>Facebook</strong></span>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<span className="app-updated-date">Last updated on 2017-09-23</span>
|
|
||||||
</Row>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
<div id="application-view-row">
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<span className="app-install-count">2k Installs</span>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<i className="fw fw-star"></i>
|
|
||||||
<i className="fw fw-star"></i>
|
|
||||||
<i className="fw fw-star"></i>
|
|
||||||
<i className="fw fw-star"></i>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<a href="#">View in Store</a>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
<div id="application-view-row">
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<span><strong>
|
|
||||||
<FormattedMessage id="Description" defaultMessage="Description"/>:
|
|
||||||
</strong></span>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<p>sdfjlkdsjfsjdfjsdf sfjdslkjfdsflkjdsfslkdjfl j</p>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<span><strong>
|
|
||||||
<FormattedMessage id="Tags" defaultMessage="Tags"/>:
|
|
||||||
</strong></span>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<p>[list of tags...]</p>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<span><strong>
|
|
||||||
<FormattedMessage id="Release" defaultMessage="Release"/>:
|
|
||||||
</strong></span>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<p>Production</p>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<span><strong>
|
|
||||||
<FormattedMessage id="Version" defaultMessage="Version"/>:
|
|
||||||
</strong></span>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<p>v1.0</p>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* 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 React, {Component} from 'react';
|
||||||
|
import {Button, Col, Collapse, Row} from "reactstrap";
|
||||||
|
import {FormattedMessage} from "react-intl";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform component.
|
||||||
|
* In Platform listing, this component will be displayed as cards.
|
||||||
|
* */
|
||||||
|
class Platform extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.unFold = this.unFold.bind(this);
|
||||||
|
this.state = {
|
||||||
|
isOpen: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unFold() {
|
||||||
|
let isOpen = this.state.isOpen;
|
||||||
|
this.setState({isOpen: !isOpen})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {platform} = this.props;
|
||||||
|
return (
|
||||||
|
<div className="platform-content">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div className="platform-text-container">
|
||||||
|
<p className="app-view-field">{platform.name}</p>
|
||||||
|
<p className="app-view-text">{platform.enabled ? "Active" : "Disabled"}</p>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<div className="platform-icon-container">
|
||||||
|
<p className="platform-icon-letter">{platform.name.charAt(0)}</p>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<div className="platform-content-footer">
|
||||||
|
<Button className="custom-flat grey">{platform.enabled ?
|
||||||
|
<FormattedMessage id="Disable" defaultMessage="Disable"/> :
|
||||||
|
<FormattedMessage id="Activate" defaultMessage="Activate"/>}
|
||||||
|
</Button>
|
||||||
|
<Button className="custom-flat grey">
|
||||||
|
<FormattedMessage id="Share.With.Tenants" defaultMessage="Share.With.Tenants"/>
|
||||||
|
</Button>
|
||||||
|
<Button className="custom-flat grey circle-button" onClick={this.unFold}>
|
||||||
|
{this.state.isOpen ? <i className="fw fw-up"></i> : <i className="fw fw-down"></i>}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
<div className="platform-content-more-outer">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Collapse isOpen={this.state.isOpen}>
|
||||||
|
<div className="platform-content-more">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-field">
|
||||||
|
<FormattedMessage id="Description" defaultMessage="Description"/>
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
<Col><p className="app-view-text">{platform.description}</p></Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-field">
|
||||||
|
<FormattedMessage id="File.Based" defaultMessage="File.Based"/>
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">{platform.fileBased ?
|
||||||
|
<FormattedMessage id="Yes" defaultMessage="Yes"/>
|
||||||
|
: <FormattedMessage id="No" defaultMessage="No"/>}</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col><p className="app-view-field">
|
||||||
|
<FormattedMessage id="Tags" defaultMessage="Tags"/>
|
||||||
|
</p></Col>
|
||||||
|
<Col>
|
||||||
|
<p className="app-view-text">
|
||||||
|
{platform.tags.length > 0 ?
|
||||||
|
platform.tags :
|
||||||
|
<FormattedMessage
|
||||||
|
id="No.Platform.Tags"
|
||||||
|
defaultMessage="No.Platform.Tags"/>
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Platform;
|
||||||
@ -15,416 +15,69 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Chip from 'material-ui/Chip';
|
|
||||||
import Dropzone from 'react-dropzone';
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Toggle from 'material-ui/Toggle';
|
import {Button, FormGroup, Input, Label, Modal, ModalBody, ModalFooter, ModalHeader} from "reactstrap";
|
||||||
import MenuItem from 'material-ui/MenuItem';
|
import {FormattedMessage} from "react-intl";
|
||||||
import TextField from 'material-ui/TextField';
|
|
||||||
import FlatButton from 'material-ui/FlatButton';
|
|
||||||
import IconButton from 'material-ui/IconButton';
|
|
||||||
import SelectField from 'material-ui/SelectField';
|
|
||||||
import RaisedButton from 'material-ui/RaisedButton';
|
|
||||||
import PlatformMgtApi from '../../api/platformMgtApi';
|
|
||||||
import Clear from 'material-ui/svg-icons/content/clear';
|
|
||||||
import {GridList, GridTile} from 'material-ui/GridList';
|
|
||||||
import Close from 'material-ui/svg-icons/navigation/close';
|
|
||||||
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
|
||||||
import AddCircleOutline from 'material-ui/svg-icons/content/add-circle-outline';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform Create component.
|
* Platform view component.
|
||||||
* Contains following components:
|
|
||||||
* * Platform Name
|
|
||||||
* * Platform Description
|
|
||||||
* * Platform Icon
|
|
||||||
* * Whether the platform needs an app to be installed.
|
|
||||||
* * Whether the platform is enabled by default.
|
|
||||||
* * Whether the platform is shared with tenants.
|
|
||||||
* */
|
* */
|
||||||
class PlatformCreate extends Component {
|
class PlatformCreate extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.onCreatePlatform = this.onCreatePlatform.bind(this);
|
this.onCancelClick = this.onCancelClick.bind(this);
|
||||||
this.handleToggle = this.handleToggle.bind(this);
|
|
||||||
this.addProperty = this.addProperty.bind(this);
|
|
||||||
this.addTags = this.addTags.bind(this);
|
|
||||||
this.clearForm = this.clearForm.bind(this);
|
|
||||||
this.onPropertySelect = this.onPropertySelect.bind(this);
|
|
||||||
this.handleTagChange = this.handleTagChange.bind(this);
|
|
||||||
this.removeIcon = this.removeIcon.bind(this);
|
|
||||||
this.onTextChange = this.onTextChange.bind(this);
|
|
||||||
this.renderChip = this.renderChip.bind(this);
|
|
||||||
this.removeProperty = this.removeProperty.bind(this);
|
|
||||||
this.state = {
|
this.state = {
|
||||||
tags: [],
|
open: false
|
||||||
defValue: "",
|
|
||||||
enabled: true,
|
|
||||||
allTenants: false,
|
|
||||||
files: [],
|
|
||||||
platformProperties: [],
|
|
||||||
selectedProperty: 0,
|
|
||||||
name: "",
|
|
||||||
description: "",
|
|
||||||
property: "",
|
|
||||||
icon: [],
|
|
||||||
identifier: "",
|
|
||||||
propertyTypes: [
|
|
||||||
{key: 0, value: 'String'},
|
|
||||||
{key: 1, value: 'Number'},
|
|
||||||
{key: 2, value: 'Boolean'},
|
|
||||||
{key: 3, value: 'File'}]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles toggle button actions.
|
|
||||||
* One method is used for all the toggle buttons and, each toggle is identified by the id.
|
|
||||||
* */
|
|
||||||
handleToggle(event) {
|
|
||||||
switch (event.target.id) {
|
|
||||||
case "enabled" : {
|
|
||||||
let enabled = this.state.enabled;
|
|
||||||
this.setState({enabled: !enabled});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "tenant" : {
|
|
||||||
let allTenants = this.state.allTenants;
|
|
||||||
this.setState({allTenants: !allTenants});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggers the onChange action on property type selection.
|
componentWillReceiveProps(props, nextprops) {
|
||||||
* */
|
this.setState({open: props.open})
|
||||||
onPropertySelect(event, index, value) {
|
|
||||||
console.log(this.state.propertyTypes[value]);
|
|
||||||
this.setState({selectedProperty: value});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
componentWillMount() {
|
||||||
* Handles Chip delete function.
|
this.setState({open: this.props.open});
|
||||||
* Removes the tag from state.tags
|
|
||||||
* */
|
|
||||||
handleTagDelete(key) {
|
|
||||||
this.chipData = this.state.tags;
|
|
||||||
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key);
|
|
||||||
this.chipData.splice(chipToDelete, 1);
|
|
||||||
this.setState({tags: this.chipData});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
onCancelClick() {
|
||||||
* Create a tag on Enter key press and set it to the state.
|
this.setState({open: false})
|
||||||
* Clears the tags text field.
|
|
||||||
* Chip gets two parameters: Key and value.
|
|
||||||
* */
|
|
||||||
addTags(event) {
|
|
||||||
let tags = this.state.tags;
|
|
||||||
if (event.charCode === 13) {
|
|
||||||
event.preventDefault();
|
|
||||||
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
|
|
||||||
this.setState({tags, defValue: ""});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates Chip array from state.tags.
|
|
||||||
* */
|
|
||||||
renderChip(data) {
|
|
||||||
return (
|
|
||||||
<Chip
|
|
||||||
key={data.key}
|
|
||||||
onRequestDelete={() => this.handleTagDelete(data.key)}
|
|
||||||
style={this.styles.chip}
|
|
||||||
>
|
|
||||||
{data.value}
|
|
||||||
</Chip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the value for tag.
|
|
||||||
* */
|
|
||||||
handleTagChange(event) {
|
|
||||||
let defaultValue = this.state.defValue;
|
|
||||||
defaultValue = event.target.value;
|
|
||||||
this.setState({defValue: defaultValue})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the selected property from the property list.
|
|
||||||
* */
|
|
||||||
removeProperty(property) {
|
|
||||||
let properties = this.state.platformProperties;
|
|
||||||
properties.splice(properties.indexOf(property), 1);
|
|
||||||
this.setState({platformProperties: properties});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new platform property.
|
|
||||||
* */
|
|
||||||
addProperty() {
|
|
||||||
let property = this.state.property;
|
|
||||||
let selected = this.state.selectedProperty;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
platformProperties:
|
|
||||||
this.state.platformProperties.concat([
|
|
||||||
{
|
|
||||||
key: property,
|
|
||||||
value: this.state.propertyTypes[selected].value
|
|
||||||
}]),
|
|
||||||
property: "",
|
|
||||||
selectedProperty: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggers in onChange event of text fields.
|
|
||||||
* Text fields are identified by their ids and the value will be persisted in the component state.
|
|
||||||
* */
|
|
||||||
onTextChange(event, value) {
|
|
||||||
let property = this.state.property;
|
|
||||||
let name = this.state.name;
|
|
||||||
let description = this.state.description;
|
|
||||||
let identifier = this.state.identifier;
|
|
||||||
|
|
||||||
switch (event.target.id) {
|
|
||||||
case "name": {
|
|
||||||
name = value;
|
|
||||||
this.setState({name: name});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "description": {
|
|
||||||
description = value;
|
|
||||||
this.setState({description: description});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "property": {
|
|
||||||
property = value;
|
|
||||||
this.setState({property: property});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "identifier": {
|
|
||||||
identifier = value;
|
|
||||||
this.setState({identifier: identifier});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create platform object and call the create platform api.
|
|
||||||
* */
|
|
||||||
onCreatePlatform(event) {
|
|
||||||
//Call the platform create api.
|
|
||||||
event.preventDefault();
|
|
||||||
let platform = {};
|
|
||||||
platform.identifier = this.state.identifier;
|
|
||||||
platform.name = this.state.name;
|
|
||||||
platform.description = this.state.description;
|
|
||||||
platform.tags = this.state.tags;
|
|
||||||
platform.properties = this.state.platformProperties;
|
|
||||||
platform.icon = this.state.icon;
|
|
||||||
platform.enabled = this.state.enabled;
|
|
||||||
platform.allTenants = this.state.allTenants;
|
|
||||||
platform.defaultTenantMapping = true;
|
|
||||||
|
|
||||||
PlatformMgtApi.createPlatform(platform);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the uploaded icon.
|
|
||||||
* */
|
|
||||||
removeIcon(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.setState({icon: []});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the user entered values in the form.
|
|
||||||
* */
|
|
||||||
clearForm(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.setState({
|
|
||||||
enabled: true,
|
|
||||||
allTenants: false,
|
|
||||||
files: [],
|
|
||||||
platformProperties: [],
|
|
||||||
selectedProperty: 0,
|
|
||||||
name: "",
|
|
||||||
description: "",
|
|
||||||
property: "",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
|
||||||
platformProperties,
|
|
||||||
allTenants,
|
|
||||||
enabled,
|
|
||||||
selectedProperty,
|
|
||||||
propertyTypes,
|
|
||||||
name,
|
|
||||||
tags,
|
|
||||||
defValue,
|
|
||||||
description,
|
|
||||||
identifier,
|
|
||||||
property
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="middle createplatformmiddle">
|
<div>
|
||||||
<Card>
|
<Modal isOpen={this.state.open} toggle={this.toggle} id="platform-create-modal" backdrop={'static'}>
|
||||||
<CardTitle title="Create Platform"/>
|
<ModalHeader>
|
||||||
<CardActions>
|
<FormattedMessage id="Create.Platform" defaultMessage="Create.Platform"/>
|
||||||
<div className="createplatformcardaction">
|
</ModalHeader>
|
||||||
<form>
|
<ModalBody>
|
||||||
<TextField
|
<FormGroup>
|
||||||
hintText="Unique Identifier for Platform."
|
<Label for="platform-name">
|
||||||
id="identifier"
|
<FormattedMessage id="Name" defaultMessage="Name"/>*
|
||||||
floatingLabelText="Identifier*"
|
</Label>
|
||||||
floatingLabelFixed={true}
|
<Input required type="text" name="appName" id="platform-name"/>
|
||||||
value={identifier}
|
</FormGroup>
|
||||||
onChange={this.onTextChange}
|
<FormGroup>
|
||||||
/>
|
<Label for="platform-description">
|
||||||
<br/>
|
<FormattedMessage id="Description" defaultMessage="Description"/>*
|
||||||
<TextField
|
</Label>
|
||||||
hintText="Enter the Platform Name."
|
<Input required type="textarea" name="appName" id="platform-description"/>
|
||||||
id="name"
|
</FormGroup>
|
||||||
floatingLabelText="Name*"
|
</ModalBody>
|
||||||
floatingLabelFixed={true}
|
<ModalFooter>
|
||||||
value={name}
|
<Button className="custom-flat danger-flat" onClick={this.onCancelClick}>
|
||||||
onChange={this.onTextChange}
|
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
|
||||||
/>
|
</Button>
|
||||||
<br/>
|
<Button className="custom-raised primary">
|
||||||
<TextField
|
<FormattedMessage id="Create" defaultMessage="Create"/>
|
||||||
id="description"
|
</Button>
|
||||||
hintText="Enter the Platform Description."
|
</ModalFooter>
|
||||||
floatingLabelText="Description*"
|
</Modal>
|
||||||
floatingLabelFixed={true}
|
|
||||||
multiLine={true}
|
|
||||||
rows={2}
|
|
||||||
value={description}
|
|
||||||
onChange={this.onTextChange}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<Toggle
|
|
||||||
id="tenant"
|
|
||||||
label="Shared with all Tenants"
|
|
||||||
labelPosition="right"
|
|
||||||
onToggle={this.handleToggle}
|
|
||||||
toggled={allTenants}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<Toggle
|
|
||||||
id="enabled"
|
|
||||||
label="Enabled"
|
|
||||||
labelPosition="right"
|
|
||||||
onToggle={this.handleToggle}
|
|
||||||
toggled={enabled}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<TextField
|
|
||||||
id="tags"
|
|
||||||
hintText="Enter Platform tags.."
|
|
||||||
floatingLabelText="Tags*"
|
|
||||||
floatingLabelFixed={true}
|
|
||||||
value={defValue}
|
|
||||||
onChange={this.handleTagChange}
|
|
||||||
onKeyPress={this.addTags}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<div className="createPlatformTagWrapper">
|
|
||||||
{tags.map(this.renderChip, this)}
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<div>
|
|
||||||
<p className="createplatformproperties">Platform Properties</p>
|
|
||||||
<div id="property-container">
|
|
||||||
{platformProperties.map((p) => {
|
|
||||||
return <div key={p.key}>{p.key} : {p.value}
|
|
||||||
<IconButton onClick={this.removeProperty.bind(this, p)}>
|
|
||||||
<Close className="createplatformpropertyclose"/>
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div className="createplatformproperty">
|
|
||||||
<TextField
|
|
||||||
id="property"
|
|
||||||
hintText="Property Name"
|
|
||||||
floatingLabelText="Platform Property*"
|
|
||||||
floatingLabelFixed={true}
|
|
||||||
value={this.state.property}
|
|
||||||
onChange={this.onTextChange}
|
|
||||||
/> <em/>
|
|
||||||
<SelectField
|
|
||||||
className="createplatformpropertyselect"
|
|
||||||
floatingLabelText="Property Type"
|
|
||||||
value={selectedProperty}
|
|
||||||
floatingLabelFixed={true}
|
|
||||||
onChange={this.onPropertySelect}>
|
|
||||||
{propertyTypes.map((type) => {
|
|
||||||
return <MenuItem key={type.key}
|
|
||||||
value={type.key}
|
|
||||||
primaryText={type.value}/>
|
|
||||||
})}
|
|
||||||
</SelectField>
|
|
||||||
<IconButton onClick={this.addProperty}>
|
|
||||||
<AddCircleOutline/>
|
|
||||||
</IconButton>
|
|
||||||
<br/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="createplatformiconp">Platform Icon*:</p>
|
|
||||||
<GridList className="createplatformicon" cols={1.1}>
|
|
||||||
{this.state.icon.map((tile) => (
|
|
||||||
<GridTile
|
|
||||||
key={Math.floor(Math.random() * 1000)}
|
|
||||||
title={tile.name}
|
|
||||||
actionIcon={
|
|
||||||
<IconButton onClick={this.removeIcon}>
|
|
||||||
<Clear/>
|
|
||||||
</IconButton>}>
|
|
||||||
<img src={tile.preview}/>
|
|
||||||
</GridTile>
|
|
||||||
))}
|
|
||||||
{this.state.icon.length === 0 ?
|
|
||||||
<Dropzone
|
|
||||||
className="createplatformdropzone"
|
|
||||||
accept="image/jpeg, image/png"
|
|
||||||
onDrop={(icon, rejected) => {
|
|
||||||
this.setState({icon, rejected})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<p className="createplatformdropzonep">+</p>
|
|
||||||
</Dropzone> : <div/>}
|
|
||||||
</GridList>
|
|
||||||
</div>
|
|
||||||
<br/>
|
|
||||||
<RaisedButton
|
|
||||||
primary={true} label="Create"
|
|
||||||
onClick={this.onCreatePlatform}/>
|
|
||||||
<FlatButton label="Cancel" onClick={this.clearForm}/>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</CardActions>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformCreate.prototypes = {};
|
|
||||||
|
|
||||||
export default PlatformCreate;
|
export default PlatformCreate;
|
||||||
|
|||||||
@ -15,145 +15,63 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {withRouter} from 'react-router-dom';
|
import {Button, Col, Row} from "reactstrap";
|
||||||
import TextField from 'material-ui/TextField';
|
import Platform from "./Platform";
|
||||||
import AuthHandler from "../../api/authHandler";
|
|
||||||
import DataTable from '../UIComponents/DataTable/DataTable';
|
|
||||||
import PlatformMgtApi from "../../api/platformMgtApi";
|
import PlatformMgtApi from "../../api/platformMgtApi";
|
||||||
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
import AuthHandler from "../../api/authHandler";
|
||||||
|
import PlatformCreate from "./PlatformCreate";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The App Create Component.
|
* Platform view component.
|
||||||
*
|
|
||||||
* Application creation is handled through a Wizard. (We use Material UI Stepper.)
|
|
||||||
*
|
|
||||||
* In each step, data will be set to the state separately.
|
|
||||||
* When the wizard is completed, data will be arranged and sent to the api.
|
|
||||||
* */
|
* */
|
||||||
class PlatformListing extends Component {
|
class PlatformListing extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.setPlatforms = this.setPlatforms.bind(this);
|
this.onPlatformCreateClick = this.onPlatformCreateClick.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
platforms: [],
|
platforms: [],
|
||||||
asc: true
|
openModal: false
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
headers = [
|
|
||||||
{
|
|
||||||
data_id: "image",
|
|
||||||
data_type: "image",
|
|
||||||
sortable: false,
|
|
||||||
label: ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data_id: "platformName",
|
|
||||||
data_type: String,
|
|
||||||
sortable: true,
|
|
||||||
label: "Platform Name",
|
|
||||||
sort: this.sortData
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data_id: "enabled",
|
|
||||||
data_type: String,
|
|
||||||
sortable: false,
|
|
||||||
label: "Enabled"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
data_id: "fileBased",
|
|
||||||
data_type: String,
|
|
||||||
sortable: false,
|
|
||||||
label: "File Based"
|
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
let platformsPromise = PlatformMgtApi.getPlatforms();
|
|
||||||
platformsPromise.then(
|
|
||||||
response => {
|
|
||||||
let platforms = this.setPlatforms(response.data);
|
|
||||||
this.setState({platforms: platforms});
|
|
||||||
}
|
|
||||||
).catch(
|
|
||||||
err => {
|
|
||||||
AuthHandler.unauthorizedErrorHandler(err);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
componentWillMount() {
|
||||||
* Create platform objects from the response which can be displayed in the table.
|
PlatformMgtApi.getPlatforms().then(response => {
|
||||||
* */
|
console.log(response);
|
||||||
setPlatforms(platforms) {
|
this.setState({platforms: response.data});
|
||||||
let tmpPlatforms = [];
|
}).catch(err => {
|
||||||
|
AuthHandler.unauthorizedErrorHandler(err);
|
||||||
for (let index in platforms) {
|
})
|
||||||
let platform = {};
|
|
||||||
platform.id = platforms[index].identifier;
|
|
||||||
platform.platformName = platforms[index].name;
|
|
||||||
platform.enabled = platforms[index].enabled.toString();
|
|
||||||
platform.fileBased = platforms[index].fileBased.toString();
|
|
||||||
tmpPlatforms.push(platform)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmpPlatforms;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
onPlatformCreateClick() {
|
||||||
* Handles the search action.
|
this.setState({openModal: true});
|
||||||
* When typing in the search bar, this method will be invoked.
|
|
||||||
* */
|
|
||||||
searchApplications(word) {
|
|
||||||
let searchedData = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles sort data function and toggles the asc state.
|
|
||||||
* asc: true : sort in ascending order.
|
|
||||||
* */
|
|
||||||
sortData() {
|
|
||||||
let isAsc = this.state.asc;
|
|
||||||
let datas = isAsc ? this.data.sort(this.compare) : this.data.reverse();
|
|
||||||
this.setState({data: datas, asc: !isAsc});
|
|
||||||
}
|
|
||||||
|
|
||||||
compare(a, b) {
|
|
||||||
if (a.applicationName < b.applicationName)
|
|
||||||
return -1;
|
|
||||||
if (a.applicationName > b.applicationName)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowClick(id) {
|
|
||||||
//TODO: Remove this
|
|
||||||
console.log(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className='middle listingplatformmiddle'>
|
<div id="platform-listing">
|
||||||
<Card className='listingplatformcard'>
|
<Row>
|
||||||
<TextField hintText="Search" onChange={this.searchApplications.bind(this)}
|
<div className="create-platform">
|
||||||
className='listingplatformsearch'/>
|
<Button className="custom-flat grey" onClick={this.onPlatformCreateClick}>
|
||||||
<CardTitle title="Platforms" className='listingplatformTitle'/>
|
<i className="fw fw-add"></i>Create Platform
|
||||||
<CardActions>
|
</Button>
|
||||||
|
</div>
|
||||||
</CardActions>
|
</Row>
|
||||||
<DataTable
|
<Row>
|
||||||
headers={this.headers}
|
<div id="platform-list">
|
||||||
data={this.state.platforms}
|
{this.state.platforms.map(platform => {
|
||||||
handleRowClick={this.onRowClick.bind(this)}
|
return (
|
||||||
noDataMessage={{type: 'button', text: 'Create Platform'}}/>
|
<Platform key={platform.identifier} platform={platform}/>
|
||||||
</Card>
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
<PlatformCreate open={this.state.openModal}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformListing.propTypes = {};
|
export default PlatformListing;
|
||||||
|
|
||||||
export default withRouter(PlatformListing);
|
|
||||||
|
|||||||
@ -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 Theme from '../../../theme';
|
import './appImage.css';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component for holding uploaded image.
|
* Component for holding uploaded image.
|
||||||
@ -29,18 +29,6 @@ class AppImage extends Component {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.removeImage = this.removeImage.bind(this);
|
this.removeImage = this.removeImage.bind(this);
|
||||||
this.scriptId = "appImage";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +44,7 @@ class AppImage extends Component {
|
|||||||
const {image, imageId} = this.props;
|
const {image, imageId} = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="image-container" style={this.props.imageStyles}>
|
<div className="image-container" style={this.props.imageStyles}>
|
||||||
<img src={image} className="image" id={imageId}/>
|
<img src={image} style={{width: '100%'}} className="image" id={imageId}/>
|
||||||
<div className="btn-content">
|
<div className="btn-content">
|
||||||
<i className="close-btn" id={imageId} onClick={this.removeImage}>X</i>
|
<i className="close-btn" id={imageId} onClick={this.removeImage}>X</i>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -31,7 +31,6 @@
|
|||||||
height: auto;
|
height: auto;
|
||||||
transition: .5s ease;
|
transition: .5s ease;
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-content {
|
.btn-content {
|
||||||
@ -16,35 +16,38 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Theme from '../../../theme';
|
import './chip.css';
|
||||||
|
|
||||||
class Chip extends Component {
|
class Chip extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.scriptId = "chip";
|
this.onDeleteClick = this.onDeleteClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
onDeleteClick() {
|
||||||
/**
|
this.props.onDelete(this.props.content.key);
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="chip">
|
<div className="chip">
|
||||||
{this.props.image?<img src={this.props.image} alt="Person" width="96" height="96" />:<div/>}
|
<div className="chip-content">
|
||||||
{this.props.text}
|
<div className="chip-text">{this.props.content.value}</div>
|
||||||
<span className="close-btn" >×</span>
|
<div className="chip-close-btn" onClick={this.onDeleteClick}>
|
||||||
|
<i className="fw fw-error"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Chip.propTypes = {
|
||||||
|
onDelete: PropTypes.func,
|
||||||
|
content: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
export default Chip;
|
export default Chip;
|
||||||
|
|||||||
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chip component with the material design specs.
|
||||||
|
* Chip with a close button.
|
||||||
|
* (-12px-{text (Roboto-Regular 13px)}-4px-{close button}-4px-)
|
||||||
|
*/
|
||||||
|
.chip {
|
||||||
|
margin-right: 5px;
|
||||||
|
height: 32px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-content {
|
||||||
|
display: flex;
|
||||||
|
margin: 4px 4px 4px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-text {
|
||||||
|
height: 24px;
|
||||||
|
font-family: "Roboto-Regular";
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
line-height: 20px;
|
||||||
|
padding-top: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
user-select: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-close-btn {
|
||||||
|
align-content: center;
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-top: 1px;
|
||||||
|
display: inline-block;
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
user-select: none;
|
||||||
|
transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-close-btn i {
|
||||||
|
color: #a9a9a9;
|
||||||
|
color: rgba(0, 0, 0, 0.258824);
|
||||||
|
fill: rgba(0, 0, 0, 0.258824);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-close-btn i:hover {
|
||||||
|
color: #959595;
|
||||||
|
}
|
||||||
@ -16,13 +16,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Theme from '../../../theme';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import DataTableRow from './DataTableRow';
|
|
||||||
import DataTableHeader from './DataTableHeader';
|
|
||||||
import RaisedButton from 'material-ui/RaisedButton';
|
|
||||||
import {Table, TableBody, TableHeader, TableRow} from 'material-ui/Table';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Custom Table Component.
|
* The Custom Table Component.
|
||||||
@ -53,8 +47,6 @@ class DataTable extends Component {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.handleRowClick = this.handleRowClick.bind(this);
|
|
||||||
this.handleBtnClick = this.handleBtnClick.bind(this);
|
|
||||||
this.state = {
|
this.state = {
|
||||||
data: [],
|
data: [],
|
||||||
headers: [],
|
headers: [],
|
||||||
@ -62,92 +54,21 @@ class DataTable extends Component {
|
|||||||
this.scriptId = "data-table"
|
this.scriptId = "data-table"
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
console.log("Will mount", this.props.data); //TODO: Remove this
|
|
||||||
this.setState({data: this.props.data, headers: this.props.headers}, Theme.insertThemingScripts(this.scriptId));
|
|
||||||
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
|
||||||
if (!nextProps.data) {
|
|
||||||
this.setState({data: nextState.data});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
this.setState({data: nextProps.data});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers when user click on table row.
|
* Triggers when user click on table row.
|
||||||
* This method invokes the parent method handleRowClick, which is passed via props.
|
* This method invokes the parent method handleRowClick, which is passed via props.
|
||||||
* */
|
* */
|
||||||
handleRowClick(id) {
|
|
||||||
this.props.handleRowClick(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleBtnClick(id) {
|
|
||||||
this.props.handleButtonClick(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {data, headers} = this.state;
|
return (
|
||||||
|
<div className="data-table">
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
//TODO: Remove this
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
let noDataContent = null;
|
|
||||||
|
|
||||||
if (this.props.noDataMessage.type === 'button') {
|
|
||||||
noDataContent = <div><RaisedButton label={this.props.noDataMessage.text}/></div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
return (<Table
|
|
||||||
selectable={false}>
|
|
||||||
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
|
|
||||||
<TableRow>
|
|
||||||
{headers.map((header) => {
|
|
||||||
return (
|
|
||||||
<DataTableHeader
|
|
||||||
key={header.data_id}
|
|
||||||
className="datatableRowColumn"
|
|
||||||
header={header}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
)}
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{data.map((dataItem) => {
|
|
||||||
return (
|
|
||||||
<DataTableRow
|
|
||||||
key={dataItem.id}
|
|
||||||
dataItem={dataItem}
|
|
||||||
handleButtonClick={this.handleBtnClick}
|
|
||||||
handleClick={this.handleRowClick}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>)
|
|
||||||
}
|
|
||||||
return (<div>{noDataContent}</div>);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataTable.prototypes = {
|
DataTable.prototypes = {};
|
||||||
data: PropTypes.arrayOf(Object),
|
|
||||||
headers: PropTypes.arrayOf(Object),
|
|
||||||
sortData: PropTypes.func,
|
|
||||||
handleRowClick: PropTypes.func,
|
|
||||||
noDataMessage: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DataTable;
|
export default DataTable;
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import PropTypes from 'prop-types';
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import FlatButton from 'material-ui/FlatButton';
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
import {TableHeaderColumn} from 'material-ui/Table';
|
import {TableHeaderColumn} from 'material-ui/Table';
|
||||||
|
import {Col, Row} from "reactstrap";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data Table header component.
|
* Data Table header component.
|
||||||
@ -55,33 +56,25 @@ class DataTableHeader extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let headerCell = null;
|
/*margin-top: 30px
|
||||||
|
* margin-bottom: 10px
|
||||||
/**
|
* */
|
||||||
* If the header is sortable, create a button with onClick handler.
|
|
||||||
* else create a span element with label as the table header.
|
|
||||||
* */
|
|
||||||
if (this.props.header.sortable) {
|
|
||||||
headerCell =
|
|
||||||
<FlatButton
|
|
||||||
label={this.props.header.label}
|
|
||||||
onClick={this.tableHeaderClick}
|
|
||||||
className="sortableHeaderCell"
|
|
||||||
/>
|
|
||||||
} else {
|
|
||||||
headerCell = <span className="notsortableHeaderCell">{this.props.header.label}</span>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableHeaderColumn key={this.props.header.id} className="datatableHeaderColumn">
|
<Row className="data-table-header">
|
||||||
{headerCell}
|
{this.props.headers.map(header => {
|
||||||
</TableHeaderColumn>
|
|
||||||
|
let headerStyle = header.size;
|
||||||
|
|
||||||
|
return <Col className={headerStyle}>{header.label}</Col>
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DataTableHeader.prototypes = {
|
DataTableHeader.prototypes = {
|
||||||
header: PropTypes.object
|
headers: PropTypes.array
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DataTableHeader;
|
export default DataTableHeader;
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import IconButton from 'material-ui/IconButton';
|
|||||||
import Create from 'material-ui/svg-icons/content/create'
|
import Create from 'material-ui/svg-icons/content/create'
|
||||||
import {TableRow, TableRowColumn} from 'material-ui/Table';
|
import {TableRow, TableRowColumn} from 'material-ui/Table';
|
||||||
import Avatar from 'material-ui/Avatar';
|
import Avatar from 'material-ui/Avatar';
|
||||||
|
import {Row} from "reactstrap";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,43 +64,17 @@ class DataTableRow extends Component {
|
|||||||
handleBtnClick(event) {
|
handleBtnClick(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
console.log(event.target['id'])
|
console.log(event.target['id'])
|
||||||
this.props.handleButtonClick(event.target['id']);
|
this.props.onAppEditClick(event.target['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {dataItem} = this.state;
|
const {dataItem} = this.state;
|
||||||
return (
|
|
||||||
<TableRow
|
|
||||||
key={this.props.key}
|
|
||||||
onClick={this.handleClick.bind(this)}
|
|
||||||
>
|
|
||||||
<TableRowColumn
|
|
||||||
className="datatableRowColumn"
|
|
||||||
key={Math.random()}
|
|
||||||
>
|
|
||||||
<Avatar>{dataItem.name}</Avatar>
|
|
||||||
</TableRowColumn>
|
|
||||||
{Object.keys(dataItem).map((key) => {
|
|
||||||
if (key !== 'id') {
|
|
||||||
return (
|
|
||||||
<TableRowColumn
|
|
||||||
className="datatableRowColumn"
|
|
||||||
key={key}
|
|
||||||
>
|
|
||||||
{dataItem[key]}
|
|
||||||
</TableRowColumn>)
|
|
||||||
}
|
|
||||||
|
|
||||||
})}
|
//height: 62px
|
||||||
<TableRowColumn
|
return (
|
||||||
className="datatableRowColumn"
|
<Row className="data-table-row">
|
||||||
key={dataItem.id}
|
|
||||||
>
|
</Row>
|
||||||
<IconButton id={dataItem.id} onClick={this.handleBtnClick.bind(this)}>
|
|
||||||
<Create id={dataItem.id}/>
|
|
||||||
</IconButton>
|
|
||||||
</TableRowColumn>
|
|
||||||
</TableRow>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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 Theme from '../../../theme';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
|
import {TableHeaderColumn} from 'material-ui/Table';
|
||||||
|
import {Col, Row} from "reactstrap";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data Table header component.
|
||||||
|
* This component creates the header elements of the table.
|
||||||
|
* */
|
||||||
|
class HeaderCell extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.tableHeaderClick = this.tableHeaderClick.bind(this);
|
||||||
|
this.scriptId = "data-table";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The onClick function of the table header.
|
||||||
|
* Invokes the function passed in the header object.
|
||||||
|
* */
|
||||||
|
tableHeaderClick() {
|
||||||
|
this.props.header.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
/*margin-top: 30px
|
||||||
|
* margin-bottom: 10px
|
||||||
|
* */
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row className="data-table-header">
|
||||||
|
{this.props.headers.map(header => {
|
||||||
|
|
||||||
|
let headerStyle = header.size;
|
||||||
|
|
||||||
|
return <Col className={headerStyle}>{header.label}</Col>
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTableHeader.prototypes = {
|
||||||
|
headers: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeaderCell;
|
||||||
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Theme from '../../../theme'
|
import './drawer.css';
|
||||||
|
import {Row} from "reactstrap";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom React component for Application View.
|
* Custom React component for Application View.
|
||||||
@ -28,18 +29,6 @@ class Drawer extends Component {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.closeDrawer = this.closeDrawer.bind(this);
|
this.closeDrawer = this.closeDrawer.bind(this);
|
||||||
this.scriptId = "drawer";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -25,21 +25,19 @@
|
|||||||
right: 0%;
|
right: 0%;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
overflow-x: hidden; /* Disable horizontal scroll */
|
overflow-x: hidden; /* Disable horizontal scroll */
|
||||||
padding-top: 60px; /* Place content 60px from the top */
|
padding: 60px 0px 0 5px; /* Place content 60px from the top */
|
||||||
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
|
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-view-drawer a {
|
.drawer-close-btn {
|
||||||
padding: 8px 8px 8px 32px;
|
padding: 8px 8px 8px 32px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 25px;
|
|
||||||
color: #818181;
|
color: #818181;
|
||||||
display: block;
|
display: block;
|
||||||
transition: 0.3s
|
transition: 0.3s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Position and style the close button (top right corner) */
|
/* Position and style the close button (top right corner) */
|
||||||
.app-view-drawer .closebtn {
|
.app-view-drawer .closebtn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -49,9 +47,8 @@
|
|||||||
margin-left: 50px;
|
margin-left: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-close-btn {
|
.drawer-close-btn i {
|
||||||
height: 40px;
|
font-size: 14px;
|
||||||
width: 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-close-btn:hover {
|
.drawer-close-btn:hover {
|
||||||
@ -67,7 +64,8 @@
|
|||||||
|
|
||||||
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
|
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
|
||||||
@media screen and (max-height: 450px) {
|
@media screen and (max-height: 450px) {
|
||||||
.sidenav {padding-top: 15px;}
|
.sidenav {
|
||||||
.sidenav a {font-size: 18px;}
|
padding-top: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,29 +18,13 @@
|
|||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Theme from '../../../theme';
|
import './floatingButton.css';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Floating Action button.
|
* Floating Action button.
|
||||||
* */
|
* */
|
||||||
class FloatingButton extends Component {
|
class FloatingButton extends Component {
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.scriptId = "floatingButton";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick(event) {
|
handleClick(event) {
|
||||||
this.props.onClick(event);
|
this.props.onClick(event);
|
||||||
}
|
}
|
||||||
@ -49,7 +33,9 @@ class FloatingButton extends Component {
|
|||||||
let classes = 'btn-circle ' + this.props.className;
|
let classes = 'btn-circle ' + this.props.className;
|
||||||
return (
|
return (
|
||||||
<div className={classes} onClick={this.handleClick.bind(this)}>
|
<div className={classes} onClick={this.handleClick.bind(this)}>
|
||||||
|
<div className={classes + " btn-shade"}>
|
||||||
<i className="fw fw-add"></i>
|
<i className="fw fw-add"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,35 +16,39 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Material design based Floating button.
|
||||||
|
*/
|
||||||
.btn-circle {
|
.btn-circle {
|
||||||
color: white;
|
color: white;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #e65100;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
text-align: center;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.156863) 0px 3px 10px, rgba(0, 0, 0, 0.227451) 0px 3px 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-circle:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-shade:focus {
|
||||||
|
background-color: rgba(0, 0, 0, .12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-circle i {
|
.btn-circle i {
|
||||||
position: absolute;
|
height: 24px;
|
||||||
margin-top: 37%;
|
width: 24px;
|
||||||
margin-left: 37%;
|
font-size: 18px;
|
||||||
|
padding: 3px;
|
||||||
|
margin-top: 16px
|
||||||
}
|
}
|
||||||
|
|
||||||
.small {
|
.small {
|
||||||
height: 50px;
|
height: 56px;
|
||||||
width: 50px;
|
width: 56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.medium {
|
.medium {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-circle:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: rgb(255, 93, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary {
|
|
||||||
background-color: blue;
|
|
||||||
}
|
|
||||||
@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
|
import './imageUploader.css';
|
||||||
import Dropzone from "react-dropzone";
|
import Dropzone from "react-dropzone";
|
||||||
import {Row} from "reactstrap";
|
import {Row} from "reactstrap";
|
||||||
import Theme from '../../../theme';
|
|
||||||
|
|
||||||
|
|
||||||
class ImageUploader extends Component {
|
class ImageUploader extends Component {
|
||||||
@ -29,19 +29,7 @@ class ImageUploader extends Component {
|
|||||||
this.setImages = this.setImages.bind(this);
|
this.setImages = this.setImages.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
images: []
|
images: []
|
||||||
};
|
}
|
||||||
this.scriptId = "imageUploader";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setImages(images) {
|
setImages(images) {
|
||||||
|
|||||||
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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 Axios from 'axios';
|
||||||
|
|
||||||
|
const imageLocation = "/images/";
|
||||||
|
|
||||||
|
class Logo extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
image: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
let url = imageLocation + this.props.image_name;
|
||||||
|
Axios.get(url, {responseType: 'arraybuffer'}).then(
|
||||||
|
response => {
|
||||||
|
let image = "data:image/jpeg;base64," + new Buffer(response.data, 'binary').toString('base64');
|
||||||
|
this.setState({image: image});
|
||||||
|
}
|
||||||
|
).catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<img className={this.props.className} src={this.state.image} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Logo.prototypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
image_name: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Logo;
|
||||||
@ -18,23 +18,11 @@
|
|||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Col, Row} from "reactstrap";
|
import {Col, Row} from "reactstrap";
|
||||||
import Theme from '../../../theme'
|
import './notification.css';
|
||||||
|
|
||||||
class NotificationItem extends Component {
|
class NotificationItem extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.scriptId = "notification";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -19,23 +19,10 @@
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Col, Row} from "reactstrap";
|
import {Col, Row} from "reactstrap";
|
||||||
import './notification.css';
|
import './notification.css';
|
||||||
import Theme from '../../../theme'
|
|
||||||
|
|
||||||
class NotificationView extends Component {
|
class NotificationView extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.scriptId = "notification";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@ -17,26 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Theme from '../../../theme';
|
import './switch.css';
|
||||||
|
|
||||||
class Switch extends Component {
|
class Switch extends Component {
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.scriptId = "switch";
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
/**
|
|
||||||
*Loading the theme files based on the the user-preference.
|
|
||||||
*/
|
|
||||||
Theme.insertThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
Theme.removeThemingScripts(this.scriptId);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {height, width} = this.props;
|
const {height, width} = this.props;
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -20,7 +20,8 @@ import qs from 'qs';
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {Redirect, Switch} from 'react-router-dom';
|
import {Redirect, Switch} from 'react-router-dom';
|
||||||
import AuthHandler from '../../../api/authHandler';
|
import AuthHandler from '../../../api/authHandler';
|
||||||
import {Button, Card, CardBlock, CardTitle, Col, Form, FormGroup, Input, Label} from 'reactstrap';
|
import {Button, Col, Form, FormGroup, Input, Label, Row} from 'reactstrap';
|
||||||
|
import Logo from "../../UIComponents/Logo/Logo";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Login Component.
|
* The Login Component.
|
||||||
@ -39,7 +40,8 @@ class Login extends Component {
|
|||||||
userName: "",
|
userName: "",
|
||||||
password: "",
|
password: "",
|
||||||
rememberMe: true,
|
rememberMe: true,
|
||||||
errors: {}
|
errors: {},
|
||||||
|
loginError: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +122,12 @@ class Login extends Component {
|
|||||||
loginPromis.then(response => {
|
loginPromis.then(response => {
|
||||||
console.log(AuthHandler.getUser());
|
console.log(AuthHandler.getUser());
|
||||||
this.setState({isLoggedIn: AuthHandler.getUser()});
|
this.setState({isLoggedIn: AuthHandler.getUser()});
|
||||||
})
|
}).catch(
|
||||||
|
err => {
|
||||||
|
console.log(err);
|
||||||
|
this.setState({loginError: err});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,33 +137,51 @@ class Login extends Component {
|
|||||||
return (
|
return (
|
||||||
<div id="login-container">
|
<div id="login-container">
|
||||||
{/*TODO: Style the components.*/}
|
{/*TODO: Style the components.*/}
|
||||||
<Card id="login-card">
|
<div id="login-card">
|
||||||
<CardBlock>
|
<div id="login-card-content">
|
||||||
<CardTitle>WSO2 IoT APP Publisher</CardTitle>
|
<Row className="login-header">
|
||||||
<Form onSubmit={this.handleLogin.bind(this)}>
|
<Col>
|
||||||
<FormGroup row>
|
<Logo className="login-header-logo" image_name="logo.png"/>
|
||||||
<Label for="userName" sm={2}>User Name:</Label>
|
</Col>
|
||||||
<Col sm={10}>
|
<Col>
|
||||||
<Input type="text" name="userName" id="userName" placeholder="User Name"
|
<p className="login-header-title">IoT APP Publisher</p>
|
||||||
onChange={this.onUserNameChange.bind(this)}/>
|
</Col>
|
||||||
</Col>
|
</Row>
|
||||||
|
<Row className="login-form">
|
||||||
</FormGroup>
|
<Col>
|
||||||
<FormGroup row>
|
<Form onSubmit={this.handleLogin.bind(this)}>
|
||||||
<Label for="password" sm={2}>Password:</Label>
|
<FormGroup>
|
||||||
<Col sm={10}>
|
<Label for="userName">User Name:</Label>
|
||||||
<Input type="password" name="text" id="password" placeholder="Password"
|
<Input
|
||||||
onChange={this.onPasswordChange.bind(this)}/>
|
type="text"
|
||||||
</Col>
|
name="userName"
|
||||||
</FormGroup>
|
id="userName"
|
||||||
<FormGroup check row>
|
placeholder="User Name"
|
||||||
<Col sm={{size: 10, offset: 2}}>
|
onChange={this.onUserNameChange.bind(this)}/>
|
||||||
<Button type="submit" id="login-btn">Login</Button>
|
</FormGroup>
|
||||||
</Col>
|
<FormGroup>
|
||||||
</FormGroup>
|
<Label for="password">Password:</Label>
|
||||||
</Form>
|
<Input
|
||||||
</CardBlock>
|
valid={false}
|
||||||
</Card>
|
type="password"
|
||||||
|
name="text"
|
||||||
|
id="password"
|
||||||
|
placeholder="Password"
|
||||||
|
onChange={this.onPasswordChange.bind(this)}/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="custom-raised login-btn primary"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>);
|
</div>);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import Publisher from './App';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import 'bootstrap/dist/css/bootstrap.css';
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
import registerServiceWorker from './registerServiceWorker';
|
import registerServiceWorker from './registerServiceWorker';
|
||||||
import {IntlProvider, addLocaleData, defineMessages} from 'react-intl';
|
import {addLocaleData, defineMessages, IntlProvider} from 'react-intl';
|
||||||
import Axios from 'axios';
|
import Axios from 'axios';
|
||||||
import Constants from './common/constants';
|
import Constants from './common/constants';
|
||||||
import Configuration from './common/configuration';
|
import Configuration from './common/configuration';
|
||||||
@ -45,7 +45,7 @@ function loadPublisher() {
|
|||||||
registerServiceWorker();
|
registerServiceWorker();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
addLocaleData(require('react-intl/locale-data/en'));
|
addLocaleData(require('react-intl/locale-data/en'));
|
||||||
let defaultLocale = axios.create({
|
let defaultLocale = Axios.create({
|
||||||
baseURL: Configuration.hostConstants.baseURL + "/" + Configuration.hostConstants.appContext + "/locales"
|
baseURL: Configuration.hostConstants.baseURL + "/" + Configuration.hostConstants.appContext + "/locales"
|
||||||
+ Constants.defaultLocale + ".json"
|
+ Constants.defaultLocale + ".json"
|
||||||
}).get();
|
}).get();
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
* 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: {
|
||||||
|
|||||||
@ -46,9 +46,6 @@
|
|||||||
<Extension name="VisibilityManager">
|
<Extension name="VisibilityManager">
|
||||||
<ClassName>org.wso2.carbon.device.application.mgt.core.impl.VisibilityManagerImpl</ClassName>
|
<ClassName>org.wso2.carbon.device.application.mgt.core.impl.VisibilityManagerImpl</ClassName>
|
||||||
</Extension>
|
</Extension>
|
||||||
<Extension name="VisibilityTypeManager">
|
|
||||||
<ClassName>org.wso2.carbon.device.application.mgt.core.impl.VisibilityTypeManagerImpl</ClassName>
|
|
||||||
</Extension>
|
|
||||||
<Extension name="ApplicationStorageManager">
|
<Extension name="ApplicationStorageManager">
|
||||||
<ClassName>org.wso2.carbon.device.application.mgt.core.impl.ApplicationStorageManagerImpl</ClassName>
|
<ClassName>org.wso2.carbon.device.application.mgt.core.impl.ApplicationStorageManagerImpl</ClassName>
|
||||||
<Parameters>
|
<Parameters>
|
||||||
@ -56,5 +53,11 @@
|
|||||||
<Parameter name="MaxScreenShotCount">6</Parameter>
|
<Parameter name="MaxScreenShotCount">6</Parameter>
|
||||||
</Parameters>
|
</Parameters>
|
||||||
</Extension>
|
</Extension>
|
||||||
|
<Extension name="PlatformStorageManager">
|
||||||
|
<ClassName>org.wso2.carbon.device.application.mgt.core.impl.PlatformStorageManagerImpl</ClassName>
|
||||||
|
<Parameters>
|
||||||
|
<Parameter name="StoragePath">repository/resources/platforms</Parameter>
|
||||||
|
</Parameters>
|
||||||
|
</Extension>
|
||||||
</Extensions>
|
</Extensions>
|
||||||
</ApplicationManagementConfiguration>
|
</ApplicationManagementConfiguration>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user