diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/RouteStepDto.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/RouteStepDto.java index 1550b259..edeb50c4 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/RouteStepDto.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/RouteStepDto.java @@ -1,6 +1,10 @@ package com.sismics.docs.core.dao.jpa.dto; import com.sismics.docs.core.constant.RouteStepType; +import com.sismics.util.JsonUtil; + +import javax.json.Json; +import javax.json.JsonObjectBuilder; /** * Route step DTO. @@ -147,4 +151,23 @@ public class RouteStepDto { this.validatorUserName = validatorUserName; return this; } + + /** + * Transform in JSON. + * + * @return JSON object builder + */ + public JsonObjectBuilder toJson() { + return Json.createObjectBuilder() + .add("name", getName()) + .add("type", getType().name()) + .add("comment", JsonUtil.nullable(getComment())) + .add("end_date", JsonUtil.nullable(getEndDateTimestamp())) + .add("validator_username", JsonUtil.nullable(getValidatorUserName())) + .add("target", Json.createObjectBuilder() + .add("id", getTargetId()) + .add("name", JsonUtil.nullable(getTargetName())) + .add("type", getTargetType())) + .add("transition", JsonUtil.nullable(getTransition())); + } } diff --git a/docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java b/docs-core/src/main/java/com/sismics/util/JsonUtil.java similarity index 97% rename from docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java rename to docs-core/src/main/java/com/sismics/util/JsonUtil.java index d3504e71..945c1b74 100644 --- a/docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java +++ b/docs-core/src/main/java/com/sismics/util/JsonUtil.java @@ -1,4 +1,4 @@ -package com.sismics.rest.util; +package com.sismics.util; import javax.json.Json; import javax.json.JsonValue; diff --git a/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java b/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java index 74e73012..e3d5f662 100644 --- a/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java +++ b/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java @@ -4,6 +4,7 @@ import com.sismics.docs.core.constant.AclType; import com.sismics.docs.core.constant.PermType; import com.sismics.docs.core.dao.jpa.AclDao; import com.sismics.docs.core.dao.jpa.dto.AclDto; +import com.sismics.util.JsonUtil; import javax.json.Json; import javax.json.JsonArrayBuilder; diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/AuditLogResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/AuditLogResource.java index 7aa1002e..4a08fe84 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/AuditLogResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/AuditLogResource.java @@ -10,7 +10,7 @@ import com.sismics.docs.core.util.jpa.PaginatedList; import com.sismics.docs.core.util.jpa.PaginatedLists; import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.rest.exception.ForbiddenClientException; -import com.sismics.rest.util.JsonUtil; +import com.sismics.util.JsonUtil; import javax.json.Json; import javax.json.JsonArrayBuilder; diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java index 2e5e4669..480b2786 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java @@ -25,8 +25,8 @@ import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; import com.sismics.rest.util.AclUtil; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; +import com.sismics.util.JsonUtil; import com.sismics.util.context.ThreadLocalContext; import com.sismics.util.mime.MimeType; import org.joda.time.DateTime; @@ -216,10 +216,9 @@ public class DocumentResource extends BaseResource { // Add current route step RouteStepDto routeStepDto = new RouteStepDao().getCurrentStep(documentId); if (routeStepDto != null && !principal.isAnonymous()) { - document.add("route_step", Json.createObjectBuilder() - .add("name", routeStepDto.getName()) - .add("type", routeStepDto.getType().name()) - .add("transitionable", getTargetIdList(null).contains(routeStepDto.getTargetId()))); + JsonObjectBuilder step = routeStepDto.toJson(); + step.add("transitionable", getTargetIdList(null).contains(routeStepDto.getTargetId())); + document.add("route_step", step); } return Response.ok().entity(document.build()).build(); diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index 56096aaa..9ea3b51e 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -22,9 +22,9 @@ import com.sismics.docs.core.util.PdfUtil; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; import com.sismics.util.HttpUtil; +import com.sismics.util.JsonUtil; import com.sismics.util.context.ThreadLocalContext; import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeTypeUtil; diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/GroupResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/GroupResource.java index 13d6915f..a8b42baa 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/GroupResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/GroupResource.java @@ -14,8 +14,8 @@ import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.docs.rest.constant.BaseFunction; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; +import com.sismics.util.JsonUtil; import javax.json.Json; import javax.json.JsonArrayBuilder; diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/RouteResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/RouteResource.java index 2749a20b..96634dbf 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/RouteResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/RouteResource.java @@ -18,7 +18,6 @@ import com.sismics.docs.core.util.SecurityUtil; import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; import javax.json.*; @@ -44,6 +43,7 @@ public class RouteResource extends BaseResource { * @apiParam {String} documentId Document ID * @apiSuccess {String} status Status OK * @apiError (client) InvalidRouteModel Invalid route model + * @apiError (client) RunningRoute A running route already exists on this document * @apiError (client) ForbiddenError Access denied * @apiError (client) NotFound Route model or document not found * @apiPermission user @@ -72,6 +72,12 @@ public class RouteResource extends BaseResource { throw new NotFoundException(); } + // Avoid creating 2 running routes on the same document + RouteStepDao routeStepDao = new RouteStepDao(); + if (routeStepDao.getCurrentStep(documentId) != null) { + throw new ClientException("RunningRoute", "A running route already exists on this document"); + } + // Create the route Route route = new Route() .setDocumentId(documentId) @@ -80,7 +86,6 @@ public class RouteResource extends BaseResource { routeDao.create(route, principal.getId()); // Create the steps - RouteStepDao routeStepDao = new RouteStepDao(); try (JsonReader reader = Json.createReader(new StringReader(routeModel.getSteps()))) { JsonArray stepsJson = reader.readArray(); for (int order = 0; order < stepsJson.size(); order++) { @@ -108,9 +113,8 @@ public class RouteResource extends BaseResource { RouteStepDto routeStep = routeStepDao.getCurrentStep(documentId); RoutingUtil.updateAcl(documentId, routeStep, null, principal.getId()); - // Always return OK JsonObjectBuilder response = Json.createObjectBuilder() - .add("status", "ok"); + .add("route_step", routeStep.toJson()); return Response.ok().entity(response.build()).build(); } @@ -173,10 +177,13 @@ public class RouteResource extends BaseResource { RoutingUtil.updateAcl(documentId, newRouteStep, routeStep, principal.getId()); // TODO Send an email to the new route step - // Always return OK - // TODO Return if the document is still readable and return the new current step if any JsonObjectBuilder response = Json.createObjectBuilder() - .add("status", "ok"); + .add("readable", aclDao.checkPermission(documentId, PermType.READ, getTargetIdList(null))); + if (newRouteStep != null) { + JsonObjectBuilder step = newRouteStep.toJson(); + step.add("transitionable", getTargetIdList(null).contains(newRouteStep.getTargetId())); + response.add("route_step", step); + } return Response.ok().entity(response.build()).build(); } @@ -232,17 +239,7 @@ public class RouteResource extends BaseResource { JsonArrayBuilder steps = Json.createArrayBuilder(); for (RouteStepDto routeStepDto : routeStepDtoList) { - steps.add(Json.createObjectBuilder() - .add("name", routeStepDto.getName()) - .add("type", routeStepDto.getType().name()) - .add("comment", JsonUtil.nullable(routeStepDto.getComment())) - .add("end_date", JsonUtil.nullable(routeStepDto.getEndDateTimestamp())) - .add("validator_username", JsonUtil.nullable(routeStepDto.getValidatorUserName())) - .add("target", Json.createObjectBuilder() - .add("id", routeStepDto.getTargetId()) - .add("name", JsonUtil.nullable(routeStepDto.getTargetName())) - .add("type", routeStepDto.getTargetType())) - .add("transition", JsonUtil.nullable(routeStepDto.getTransition()))); + steps.add(routeStepDto.toJson()); } routes.add(Json.createObjectBuilder() @@ -253,7 +250,8 @@ public class RouteResource extends BaseResource { JsonObjectBuilder json = Json.createObjectBuilder() .add("routes", routes); - return Response.ok().entity(json.build()).build(); } + + // TODO Workflow cancellation } diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java index ea38e25d..f54fce72 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java @@ -10,8 +10,8 @@ import com.sismics.docs.core.model.jpa.Acl; import com.sismics.docs.core.model.jpa.Share; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; +import com.sismics.util.JsonUtil; import javax.json.Json; import javax.json.JsonObjectBuilder; diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java index 423432ff..430787ea 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java @@ -10,9 +10,9 @@ import com.sismics.docs.rest.constant.BaseFunction; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; import com.sismics.util.HttpUtil; +import com.sismics.util.JsonUtil; import com.sismics.util.css.Selector; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataParam; diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java index 0fb3b225..01d643b5 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java @@ -21,9 +21,9 @@ import com.sismics.docs.rest.constant.BaseFunction; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; -import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; import com.sismics.security.UserPrincipal; +import com.sismics.util.JsonUtil; import com.sismics.util.context.ThreadLocalContext; import com.sismics.util.filter.TokenBasedSecurityFilter; import com.sismics.util.totp.GoogleAuthenticator; diff --git a/docs-web/src/main/webapp/src/app/docs/app.js b/docs-web/src/main/webapp/src/app/docs/app.js index bf4c8ebb..2c644506 100644 --- a/docs-web/src/main/webapp/src/app/docs/app.js +++ b/docs-web/src/main/webapp/src/app/docs/app.js @@ -285,6 +285,15 @@ angular.module('docs', } } }) + .state('document.view.workflow', { + url: '/workflow', + views: { + 'tab': { + templateUrl: 'partial/docs/document.view.workflow.html', + controller: 'DocumentViewWorkflow' + } + } + }) .state('document.view.content.file', { url: '/file/:fileId', views: { diff --git a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentView.js b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentView.js index 73368b92..895d6bfe 100644 --- a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentView.js +++ b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentView.js @@ -5,16 +5,16 @@ */ angular.module('docs').controller('DocumentView', function ($scope, $state, $stateParams, $location, $dialog, $uibModal, Restangular, $translate) { // Load document data from server - Restangular.one('document', $stateParams.id).get().then(function(data) { + Restangular.one('document', $stateParams.id).get().then(function (data) { $scope.document = data; - }, function(response) { + }, function (response) { $scope.error = response; }); // Load comments from server - Restangular.one('comment', $stateParams.id).get().then(function(data) { + Restangular.one('comment', $stateParams.id).get().then(function (data) { $scope.comments = data.comments; - }, function(response) { + }, function (response) { $scope.commentsError = response; }); @@ -22,7 +22,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta * Add a comment. */ $scope.comment = ''; - $scope.addComment = function() { + $scope.addComment = function () { if ($scope.comment.length === 0) { return; } @@ -30,7 +30,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta Restangular.one('comment').put({ id: $stateParams.id, content: $scope.comment - }).then(function(data) { + }).then(function (data) { $scope.comment = ''; $scope.comments.push(data); }); @@ -39,7 +39,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta /** * Delete a comment. */ - $scope.deleteComment = function(comment) { + $scope.deleteComment = function (comment) { var title = $translate.instant('document.view.delete_comment_title'); var msg = $translate.instant('document.view.delete_comment_message'); var btns = [ @@ -49,7 +49,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta $dialog.messageBox(title, msg, btns, function (result) { if (result === 'ok') { - Restangular.one('comment', comment.id).remove().then(function() { + Restangular.one('comment', comment.id).remove().then(function () { $scope.comments.splice($scope.comments.indexOf(comment), 1); }); } @@ -69,7 +69,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta $dialog.messageBox(title, msg, btns, function (result) { if (result === 'ok') { - Restangular.one('document', document.id).remove().then(function() { + Restangular.one('document', document.id).remove().then(function () { $scope.loadDocuments(); $state.go('document.default'); }); @@ -105,7 +105,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta /** * Display a share. */ - $scope.showShare = function(share) { + $scope.showShare = function (share) { // Show the link var link = $location.absUrl().replace($location.path(), '').replace('#', '') + 'share.html#/share/' + $stateParams.id + '/' + share.id; var title = $translate.instant('document.view.shared_document_title'); @@ -119,7 +119,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta if (result === 'unshare') { // Unshare this document and update the local shares Restangular.one('share', share.id).remove().then(function () { - $scope.document.acls = _.reject($scope.document.acls, function(s) { + $scope.document.acls = _.reject($scope.document.acls, function (s) { return share.id === s.id; }); }); @@ -130,7 +130,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta /** * Export the current document to PDF. */ - $scope.exportPdf = function() { + $scope.exportPdf = function () { $uibModal.open({ templateUrl: 'partial/docs/document.pdf.html', controller: 'DocumentModalPdf' @@ -138,4 +138,22 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta return false; }; + + /** + * Validate the workflow. + */ + $scope.validateWorkflow = function (transition) { + Restangular.one('route').post('validate', { + documentId: $stateParams.id, + transition: transition, + comment: $scope.workflowComment + }).then(function (data) { + $scope.workflowComment = ''; + if (data.readable) { + $scope.document.route_step = data.route_step; + } else { + $state.go('document.default'); + } + }); + }; }); \ No newline at end of file diff --git a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewWorkflow.js b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewWorkflow.js new file mode 100644 index 00000000..6b3f7709 --- /dev/null +++ b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewWorkflow.js @@ -0,0 +1,33 @@ +'use strict'; + +/** + * Document view workflow controller. + */ +angular.module('docs').controller('DocumentViewWorkflow', function ($scope, $stateParams, Restangular) { + $scope.loadRoutes = function () { + Restangular.one('route').get({ + documentId: $stateParams.id + }).then(function(data) { + $scope.routes = data.routes; + }); + }; + + // Load route models + Restangular.one('routemodel').get().then(function(data) { + $scope.routemodels = data.routemodels; + }); + + // Start the selected workflow + $scope.startWorkflow = function () { + Restangular.one('route').post('start', { + routeModelId: $scope.routemodel, + documentId: $stateParams.id + }).then(function (data) { + $scope.document.route_step = data.route_step; + $scope.loadRoutes(); + }); + }; + + // Load routes + $scope.loadRoutes(); +}); \ No newline at end of file diff --git a/docs-web/src/main/webapp/src/index.html b/docs-web/src/main/webapp/src/index.html index f7d2d9f6..08f8b1b7 100644 --- a/docs-web/src/main/webapp/src/index.html +++ b/docs-web/src/main/webapp/src/index.html @@ -58,6 +58,7 @@ + diff --git a/docs-web/src/main/webapp/src/locale/en.json b/docs-web/src/main/webapp/src/locale/en.json index 4dc084df..6455cec0 100644 --- a/docs-web/src/main/webapp/src/locale/en.json +++ b/docs-web/src/main/webapp/src/locale/en.json @@ -92,6 +92,8 @@ "no_comments": "No comments on this document yet", "add_comment": "Add a comment", "error_loading_comments": "Error loading comments", + "workflow_current": "Current workflow step", + "workflow_comment": "Add a workflow comment", "content": { "content": "Content", "delete_file_title": "Delete file", @@ -103,6 +105,14 @@ "drop_zone": "Drag & drop files here to upload", "add_files": "Add files" }, + "workflow": { + "workflow": "Workflow", + "message": "Verify or validate your documents with people of your organization using workflows.", + "workflow_start_label": "Which workflow to start?", + "add_more_workflow": "Add more workflows", + "start_workflow_submit": "Start workflow", + "full_name": "{{ name }} started on {{ create_date | date }}" + }, "permissions": { "permissions": "Permissions", "message": "Permissions can be applied directly to this document, or can come from tags.", @@ -428,6 +438,15 @@ "GROUP": "Group", "SHARE": "Shared" }, + "workflow_type": { + "VALIDATE": "Validation", + "APPROVE": "Approbation" + }, + "workflow_transition": { + "APPROVED": "Approved", + "REJECTED": "Rejected", + "VALIDATED": "Validated" + }, "validation": { "required": "Required", "too_short": "Too short", diff --git a/docs-web/src/main/webapp/src/partial/docs/document.view.html b/docs-web/src/main/webapp/src/partial/docs/document.view.html index 0fe0e794..e5875fdf 100644 --- a/docs-web/src/main/webapp/src/partial/docs/document.view.html +++ b/docs-web/src/main/webapp/src/partial/docs/document.view.html @@ -72,6 +72,11 @@ {{ 'document.view.content' | translate }} +
  • + + {{ 'document.view.workflow' | translate }} + +
  • {{ 'document.view.permissions' | translate }} @@ -86,7 +91,43 @@
    -
    + + +
    +

    {{ document.route_step.name }}

    +

    + + + {{ 'workflow_type.' + document.route_step.type | translate }} + +

    +

    + + + {{ 'workflow_transition.VALIDATED' | translate }} + + + {{ 'workflow_transition.APPROVED' | translate }} + + + {{ 'workflow_transition.REJECTED' | translate }} + +

    +
    +
    + + diff --git a/docs-web/src/main/webapp/src/partial/docs/document.view.workflow.html b/docs-web/src/main/webapp/src/partial/docs/document.view.workflow.html new file mode 100644 index 00000000..972cbcc8 --- /dev/null +++ b/docs-web/src/main/webapp/src/partial/docs/document.view.workflow.html @@ -0,0 +1,72 @@ +

    {{ 'document.view.workflow.message' | translate }}

    + +
    + + +
    +
    + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + +
    TypeNameForValidation
    + + + {{ 'workflow_type.' + step.type | translate }} + {{ step.name }} + + + + {{ 'workflow_transition.' + step.transition | translate }} + {{ step.end_date | timeAgo: dateTimeFormat }} + by + {{ step.validator_username }} + +
    + {{ step.comment }} +
    +
    +
    \ No newline at end of file diff --git a/docs-web/src/main/webapp/src/style/main.less b/docs-web/src/main/webapp/src/style/main.less index 7fe6872f..aee9a1c8 100644 --- a/docs-web/src/main/webapp/src/style/main.less +++ b/docs-web/src/main/webapp/src/style/main.less @@ -237,7 +237,7 @@ input[readonly].share-link { } // Comments -.page-header-comments { +.page-header-side { margin: 14px 0 20px; } @@ -449,4 +449,22 @@ input[readonly].share-link { .mb-10 { margin-bottom: 10px; +} + +// Buttons +.btn { + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; + font-weight: 400; + border-radius: 4px; +} + +// Cards +.card { + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0,0,0,.125); + border-radius: .25em; + padding: 1.25em; } \ No newline at end of file diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestRouteResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestRouteResource.java index 8fd5dedb..9209411d 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestRouteResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestRouteResource.java @@ -52,11 +52,13 @@ public class TestRouteResource extends BaseJerseyTest { String document1Id = json.getString("id"); // Start the default route on document 1 - target().path("/route/start").request() + json = target().path("/route/start").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, route1Token) .post(Entity.form(new Form() .param("documentId", document1Id) .param("routeModelId", routeModels.getJsonObject(0).getString("id"))), JsonObject.class); + JsonObject step = json.getJsonObject("route_step"); + Assert.assertEquals("Check the document's metadata", step.getString("name")); // Get the route on document 1 json = target().path("/route") @@ -71,7 +73,7 @@ public class TestRouteResource extends BaseJerseyTest { Assert.assertNotNull(route.getJsonNumber("create_date")); JsonArray steps = route.getJsonArray("steps"); Assert.assertEquals(3, steps.size()); - JsonObject step = steps.getJsonObject(0); + step = steps.getJsonObject(0); Assert.assertEquals("Check the document's metadata", step.getString("name")); Assert.assertEquals("VALIDATE", step.getString("type")); Assert.assertTrue(step.isNull("comment")); @@ -102,11 +104,14 @@ public class TestRouteResource extends BaseJerseyTest { Assert.assertEquals("Check the document's metadata", routeStep.getString("name")); // Validate the current step with admin - target().path("/route/validate").request() + json = target().path("/route/validate").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("documentId", document1Id) .param("transition", "VALIDATED")), JsonObject.class); + step = json.getJsonObject("route_step"); + Assert.assertEquals("Add relevant files to the document", step.getString("name")); + Assert.assertTrue(json.getBoolean("readable")); // Get the route on document 1 json = target().path("/route") @@ -136,12 +141,15 @@ public class TestRouteResource extends BaseJerseyTest { Assert.assertEquals("Add relevant files to the document", routeStep.getString("name")); // Validate the current step with admin - target().path("/route/validate").request() + json = target().path("/route/validate").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("documentId", document1Id) .param("transition", "VALIDATED") .param("comment", "OK")), JsonObject.class); + step = json.getJsonObject("route_step"); + Assert.assertEquals("Approve the document", step.getString("name")); + Assert.assertTrue(json.getBoolean("readable")); // Get the route on document 1 json = target().path("/route") @@ -171,11 +179,13 @@ public class TestRouteResource extends BaseJerseyTest { Assert.assertEquals("Approve the document", routeStep.getString("name")); // Validate the current step with admin - target().path("/route/validate").request() + json = target().path("/route/validate").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken) .post(Entity.form(new Form() .param("documentId", document1Id) .param("transition", "APPROVED")), JsonObject.class); + Assert.assertFalse(json.containsKey("route_step")); + Assert.assertFalse(json.getBoolean("readable")); // Get the route on document 1 json = target().path("/route")