diff --git a/rest/taskana-rest-spring-example/src/test/java/pro/taskana/doc/api/TaskControllerRestDocumentation.java b/rest/taskana-rest-spring-example/src/test/java/pro/taskana/doc/api/TaskControllerRestDocumentation.java index 1172a5e57..10bb36cba 100644 --- a/rest/taskana-rest-spring-example/src/test/java/pro/taskana/doc/api/TaskControllerRestDocumentation.java +++ b/rest/taskana-rest-spring-example/src/test/java/pro/taskana/doc/api/TaskControllerRestDocumentation.java @@ -94,6 +94,7 @@ public class TaskControllerRestDocumentation { taskFieldDescriptionsMap.put("primaryObjRef.type", "The type of the reference (contract, claim, policy, customer, ...)"); taskFieldDescriptionsMap.put("primaryObjRef.value", "The value of the primary object reference"); taskFieldDescriptionsMap.put("customAttributes", "A container for all additional information on the task in JSON representation"); + taskFieldDescriptionsMap.put("callbackInfo", "A container for all callback information of the task in JSON representation"); taskFieldDescriptionsMap.put("attachments", ""); taskFieldDescriptionsMap.put("custom1", "A custom property with name \"1\""); taskFieldDescriptionsMap.put("custom2", "A custom property with name \"2\""); @@ -152,6 +153,7 @@ public class TaskControllerRestDocumentation { fieldWithPath("read").description(taskFieldDescriptionsMap.get("read")), fieldWithPath("transferred").description(taskFieldDescriptionsMap.get("transferred")), fieldWithPath("customAttributes").description(taskFieldDescriptionsMap.get("customAttributes")), + fieldWithPath("callbackInfo").description(taskFieldDescriptionsMap.get("callbackInfo")), fieldWithPath("attachments").description(taskFieldDescriptionsMap.get("attachments")), fieldWithPath("custom1").description(taskFieldDescriptionsMap.get("custom1")).type("String"), fieldWithPath("custom2").description(taskFieldDescriptionsMap.get("custom2")).type("String"), @@ -201,6 +203,7 @@ public class TaskControllerRestDocumentation { fieldWithPath("read").description(taskFieldDescriptionsMap.get("read")), fieldWithPath("transferred").description(taskFieldDescriptionsMap.get("transferred")), fieldWithPath("customAttributes").ignored(), + fieldWithPath("callbackInfo").ignored(), fieldWithPath("attachments").description(taskFieldDescriptionsMap.get("attachments")), fieldWithPath("custom1").description(taskFieldDescriptionsMap.get("custom1")), fieldWithPath("custom2").description(taskFieldDescriptionsMap.get("custom2")), @@ -247,6 +250,7 @@ public class TaskControllerRestDocumentation { fieldWithPath("owner").description(taskFieldDescriptionsMap.get("owner")).type("String").optional(), fieldWithPath("primaryObjRef.id").description(taskFieldDescriptionsMap.get("primaryObjRef.id")).type("String").optional(), fieldWithPath("customAttributes").description(taskFieldDescriptionsMap.get("customAttributes")).type("Object").optional(), + fieldWithPath("callbackInfo").description(taskFieldDescriptionsMap.get("callbackInfo")).type("Object").optional(), fieldWithPath("attachments").description(taskFieldDescriptionsMap.get("attachments")).type("Array").optional(), fieldWithPath("custom1").description(taskFieldDescriptionsMap.get("custom1")).type("String").optional(), fieldWithPath("custom2").description(taskFieldDescriptionsMap.get("custom2")).type("String").optional(), @@ -313,20 +317,19 @@ public class TaskControllerRestDocumentation { BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream())); String inputLine; - StringBuffer content = new StringBuffer(); + StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close(); con.disconnect(); String originalTask = content.toString(); - String modifiedTask = new String(originalTask.toString()); - + this.mockMvc.perform(RestDocumentationRequestBuilders .put("http://127.0.0.1:" + port + "/v1/tasks/TKI:100000000000000000000000000000000000") .header("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x") .contentType("application/json") - .content(modifiedTask)) + .content(originalTask)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcRestDocumentation.document("UpdateTaskDocTest", requestFields(taskFieldDescriptors), diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java index 286e4be87..164b7196b 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java @@ -46,7 +46,7 @@ import pro.taskana.rest.resource.WorkbasketSummaryResource; import pro.taskana.rest.resource.assembler.DistributionTargetListAssembler; import pro.taskana.rest.resource.assembler.WorkbasketAccessItemAssembler; import pro.taskana.rest.resource.assembler.WorkbasketAccessItemListAssembler; -import pro.taskana.rest.resource.assembler.WorkbasketAssembler; +import pro.taskana.rest.resource.assembler.WorkbasketResourceAssembler; import pro.taskana.rest.resource.assembler.WorkbasketSummaryResourcesAssembler; /** @@ -80,7 +80,7 @@ public class WorkbasketController extends AbstractPagingController { private WorkbasketService workbasketService; @Autowired - private WorkbasketAssembler workbasketAssembler; + private WorkbasketResourceAssembler workbasketResourceAssembler; @Autowired private DistributionTargetListAssembler distributionTargetListAssembler; @@ -133,7 +133,7 @@ public class WorkbasketController extends AbstractPagingController { throws WorkbasketNotFoundException, NotAuthorizedException { ResponseEntity result; Workbasket workbasket = workbasketService.getWorkbasket(workbasketId); - result = new ResponseEntity<>(workbasketAssembler.toResource(workbasket), HttpStatus.OK); + result = new ResponseEntity<>(workbasketResourceAssembler.toResource(workbasket), HttpStatus.OK); return result; } @@ -151,9 +151,9 @@ public class WorkbasketController extends AbstractPagingController { public ResponseEntity createWorkbasket(@RequestBody WorkbasketResource workbasketResource) throws InvalidWorkbasketException, NotAuthorizedException, WorkbasketAlreadyExistException, WorkbasketNotFoundException, DomainNotFoundException { - Workbasket workbasket = workbasketAssembler.toModel(workbasketResource); + Workbasket workbasket = workbasketResourceAssembler.toModel(workbasketResource); workbasket = workbasketService.createWorkbasket(workbasket); - return new ResponseEntity<>(workbasketAssembler.toResource(workbasket), HttpStatus.CREATED); + return new ResponseEntity<>(workbasketResourceAssembler.toResource(workbasket), HttpStatus.CREATED); } @PutMapping(path = "/{workbasketId}") @@ -164,9 +164,9 @@ public class WorkbasketController extends AbstractPagingController { throws InvalidWorkbasketException, WorkbasketNotFoundException, NotAuthorizedException { ResponseEntity result; if (workbasketId.equals(workbasketResource.workbasketId)) { - Workbasket workbasket = workbasketAssembler.toModel(workbasketResource); + Workbasket workbasket = workbasketResourceAssembler.toModel(workbasketResource); workbasket = workbasketService.updateWorkbasket(workbasket); - result = ResponseEntity.ok(workbasketAssembler.toResource(workbasket)); + result = ResponseEntity.ok(workbasketResourceAssembler.toResource(workbasket)); } else { throw new InvalidWorkbasketException( "Target-WB-ID('" + workbasketId diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java index dcd53685d..bc2438101 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java @@ -28,7 +28,7 @@ import pro.taskana.rest.resource.WorkbasketDefinition; import pro.taskana.rest.resource.WorkbasketResource; import pro.taskana.rest.resource.assembler.WorkbasketAccessItemAssembler; import pro.taskana.rest.resource.assembler.WorkbasketDefinitionAssembler; -import pro.taskana.rest.resource.assembler.WorkbasketAssembler; +import pro.taskana.rest.resource.assembler.WorkbasketResourceAssembler; import java.util.ArrayList; import java.util.HashMap; @@ -50,7 +50,7 @@ public class WorkbasketDefinitionController { private WorkbasketDefinitionAssembler workbasketDefinitionAssembler; @Autowired - private WorkbasketAssembler workbasketAssembler; + private WorkbasketResourceAssembler workbasketResourceAssembler; @Autowired private WorkbasketAccessItemAssembler workbasketAccessItemAssembler; @@ -110,11 +110,11 @@ public class WorkbasketDefinitionController { if (systemIds.containsKey(logicalId(res))) { res.workbasketId = systemIds.get(logicalId(res)); workbasket = workbasketService.updateWorkbasket( - workbasketAssembler.toModel(res)); + workbasketResourceAssembler.toModel(res)); } else { res.workbasketId = null; workbasket = workbasketService.createWorkbasket( - workbasketAssembler.toModel(res)); + workbasketResourceAssembler.toModel(res)); } res.workbasketId = oldId; diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/TaskResource.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/TaskResource.java index 08c6f0054..43fe5ea88 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/TaskResource.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/TaskResource.java @@ -38,6 +38,7 @@ public class TaskResource extends ResourceSupport { private boolean isTransferred; // All objects have to be serializable private Map customAttributes = Collections.emptyMap(); + private Map callbackInfo = Collections.emptyMap(); private List attachments = new ArrayList<>(); private String custom1; private String custom2; @@ -232,6 +233,14 @@ public class TaskResource extends ResourceSupport { this.customAttributes = customAttributes; } + public Map getCallbackInfo() { + return callbackInfo; + } + + public void setCallbackInfo(Map callbackInfo) { + this.callbackInfo = callbackInfo; + } + public List getAttachments() { return attachments; } diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetListAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetListAssembler.java index ce13ebd8b..ad8177c54 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetListAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetListAssembler.java @@ -24,13 +24,13 @@ import pro.taskana.rest.resource.DistributionTargetResource; public class DistributionTargetListAssembler { @Autowired - private DistributionTargetAssembler distributionTargetAssembler; + private DistributionTargetResourceAssembler distributionTargetResourceAssembler; public Resources toResource(String workbasketId, Collection distributionTargets) throws WorkbasketNotFoundException, NotAuthorizedException { List resourceList = new ArrayList<>(); for (WorkbasketSummary wb : distributionTargets) { - resourceList.add(distributionTargetAssembler.toResource(wb)); + resourceList.add(distributionTargetResourceAssembler.toResource(wb)); } Resources distributionTargetListResource = new Resources<>(resourceList); diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetResourceAssembler.java similarity index 96% rename from rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetAssembler.java rename to rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetResourceAssembler.java index 299cd17d8..83105a7e9 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/DistributionTargetResourceAssembler.java @@ -16,7 +16,7 @@ import pro.taskana.rest.resource.DistributionTargetResource; * Transforms WorkbasketSummary to its resource counterpart DistributionTargerResource and vice versa. */ @Component -public class DistributionTargetAssembler { +public class DistributionTargetResourceAssembler { public DistributionTargetResource toResource(WorkbasketSummary summary) throws WorkbasketNotFoundException, NotAuthorizedException { diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketDefinitionAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketDefinitionAssembler.java index 7a7131a37..8821f8319 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketDefinitionAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketDefinitionAssembler.java @@ -33,7 +33,7 @@ public class WorkbasketDefinitionAssembler { private WorkbasketService workbasketService; @Autowired - private WorkbasketAssembler workbasketAssembler; + private WorkbasketResourceAssembler workbasketResourceAssembler; @Autowired private WorkbasketAccessItemAssembler workbasketAccessItemAssembler; @@ -60,7 +60,7 @@ public class WorkbasketDefinitionAssembler { .stream() .map(WorkbasketSummary::getId) .collect(Collectors.toSet()); - WorkbasketDefinition resource = new WorkbasketDefinition(workbasketAssembler.toResource(basket), distroTargets, + WorkbasketDefinition resource = new WorkbasketDefinition(workbasketResourceAssembler.toResource(basket), distroTargets, authorizations); return addLinks(resource, basket); } diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketResourceAssembler.java similarity index 98% rename from rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketAssembler.java rename to rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketResourceAssembler.java index bf25cbaee..b36ce235b 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketResourceAssembler.java @@ -21,7 +21,7 @@ import pro.taskana.rest.resource.WorkbasketResource; * Transforms {@link Workbasket} to its resource counterpart {@link WorkbasketResource} and vice versa. */ @Component -public class WorkbasketAssembler { +public class WorkbasketResourceAssembler { @Autowired private WorkbasketService workbasketService; diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssembler.java deleted file mode 100644 index cc1721af6..000000000 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssembler.java +++ /dev/null @@ -1,36 +0,0 @@ -package pro.taskana.rest.resource.assembler; - -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; -import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; - -import org.springframework.beans.BeanUtils; -import org.springframework.stereotype.Component; - -import pro.taskana.WorkbasketSummary; -import pro.taskana.exceptions.NotAuthorizedException; -import pro.taskana.exceptions.WorkbasketNotFoundException; -import pro.taskana.rest.WorkbasketController; -import pro.taskana.rest.resource.WorkbasketSummaryResource; - -/** - * Transforms {@link WorkbasketSummary} to its resource counterpart {@link WorkbasketSummaryResource} and vice versa. - */ -@Component -public class WorkbasketSummaryAssembler { - - public WorkbasketSummaryResource toResource(WorkbasketSummary summary) - throws WorkbasketNotFoundException, NotAuthorizedException { - WorkbasketSummaryResource resource = new WorkbasketSummaryResource(); - BeanUtils.copyProperties(summary, resource); - // named different so needs to be set by hand - resource.setWorkbasketId(summary.getId()); - - return addLinks(resource, summary); - } - - private WorkbasketSummaryResource addLinks(WorkbasketSummaryResource resource, WorkbasketSummary summary) - throws WorkbasketNotFoundException, NotAuthorizedException { - resource.add(linkTo(methodOn(WorkbasketController.class).getWorkbasket(summary.getId())).withSelfRel()); - return resource; - } -} diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketAssemblerTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketResourceAssemblerTest.java similarity index 93% rename from rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketAssemblerTest.java rename to rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketResourceAssemblerTest.java index 5376c168e..2df00192b 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketAssemblerTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketResourceAssemblerTest.java @@ -20,17 +20,17 @@ import pro.taskana.rest.TestConfiguration; import pro.taskana.rest.resource.WorkbasketResource; /** - * Test for {@link WorkbasketAssembler}. + * Test for {@link WorkbasketResourceAssembler}. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {TestConfiguration.class}) @WebAppConfiguration -public class WorkbasketAssemblerTest { +public class WorkbasketResourceAssemblerTest { @Autowired WorkbasketService workbasketService; @Autowired - WorkbasketAssembler workbasketAssembler; + WorkbasketResourceAssembler workbasketResourceAssembler; @Test public void workbasketToResource() throws NotAuthorizedException, WorkbasketNotFoundException { @@ -52,7 +52,7 @@ public class WorkbasketAssemblerTest { ((WorkbasketImpl) workbasket).setCreated(Instant.parse("2010-01-01T12:00:00Z")); ((WorkbasketImpl) workbasket).setModified(Instant.parse("2010-01-01T12:00:00Z")); // when - WorkbasketResource workbasketResource = workbasketAssembler.toResource(workbasket); + WorkbasketResource workbasketResource = workbasketResourceAssembler.toResource(workbasket); // then testEquality(workbasket, workbasketResource); } @@ -79,7 +79,7 @@ public class WorkbasketAssemblerTest { workbasketResource.setOwner("Lars"); workbasketResource.setType(WorkbasketType.PERSONAL); // when - Workbasket workbasket = workbasketAssembler.toModel(workbasketResource); + Workbasket workbasket = workbasketResourceAssembler.toModel(workbasketResource); // then testEquality(workbasket, workbasketResource); } diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssemblerTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssemblerTest.java index fea290c85..228ab711d 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssemblerTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/assembler/WorkbasketSummaryAssemblerTest.java @@ -10,14 +10,12 @@ import org.springframework.test.context.web.WebAppConfiguration; import pro.taskana.WorkbasketService; import pro.taskana.WorkbasketType; -import pro.taskana.exceptions.NotAuthorizedException; -import pro.taskana.exceptions.WorkbasketNotFoundException; import pro.taskana.impl.WorkbasketSummaryImpl; import pro.taskana.rest.TestConfiguration; import pro.taskana.rest.resource.WorkbasketSummaryResource; /** - * Test for {@link WorkbasketSummaryAssembler}. + * Test for {@link WorkbasketSummaryResourceAssembler}. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {TestConfiguration.class}) @@ -25,12 +23,12 @@ import pro.taskana.rest.resource.WorkbasketSummaryResource; public class WorkbasketSummaryAssemblerTest { @Autowired - WorkbasketSummaryAssembler workbasketSummaryAssembler; + WorkbasketSummaryResourceAssembler workbasketSummaryAssembler; @Autowired WorkbasketService workbasketService; @Test - public void workbasketSummaryToResource() throws WorkbasketNotFoundException, NotAuthorizedException { + public void workbasketSummaryToResource() { // given WorkbasketSummaryImpl workbasketSummary = (WorkbasketSummaryImpl) workbasketService.newWorkbasket("1", "DOMAIN_A").asSummary(); diff --git a/web/src/app/administration/workbasket/details/workbasket-details.component.html b/web/src/app/administration/workbasket/details/workbasket-details.component.html index dc6fd4a51..591218b39 100644 --- a/web/src/app/administration/workbasket/details/workbasket-details.component.html +++ b/web/src/app/administration/workbasket/details/workbasket-details.component.html @@ -6,7 +6,7 @@ Back -
  • Information
  • @@ -35,4 +35,4 @@ - \ No newline at end of file + diff --git a/web/src/app/administration/workbasket/details/workbasket-details.component.scss b/web/src/app/administration/workbasket/details/workbasket-details.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/web/src/app/administration/workbasket/details/workbasket-details.component.ts b/web/src/app/administration/workbasket/details/workbasket-details.component.ts index 8eb7991d6..2738a887f 100644 --- a/web/src/app/administration/workbasket/details/workbasket-details.component.ts +++ b/web/src/app/administration/workbasket/details/workbasket-details.component.ts @@ -14,8 +14,7 @@ import { ErrorModalService } from '../../../services/errorModal/error-modal.serv @Component({ selector: 'taskana-workbasket-details', - templateUrl: './workbasket-details.component.html', - styleUrls: ['./workbasket-details.component.scss'] + templateUrl: './workbasket-details.component.html' }) export class WorkbasketDetailsComponent implements OnInit, OnDestroy { diff --git a/web/src/app/monitor/tasks/tasks.component.ts b/web/src/app/monitor/tasks/tasks.component.ts index 478b28289..1a699e798 100644 --- a/web/src/app/monitor/tasks/tasks.component.ts +++ b/web/src/app/monitor/tasks/tasks.component.ts @@ -11,7 +11,7 @@ import { ReportData } from 'app/monitor/models/report-data'; export class TasksComponent implements OnInit { - pieChartLabels: string[] = ['Ready', 'Claimed', 'Completed']; + pieChartLabels: string[]; pieChartData: number[] = []; pieChartType = 'pie'; reportData: ReportData @@ -23,6 +23,7 @@ export class TasksComponent implements OnInit { ngOnInit() { this.restConnectorService.getTaskStatusReport().subscribe((data: ReportData) => { this.reportData = data; + this.pieChartLabels = Object.keys(data.sumRow.cells); Object.keys(data.sumRow.cells).forEach(key => { this.pieChartData.push(data.sumRow.cells[key]); }) diff --git a/web/src/app/workplace/models/task.ts b/web/src/app/workplace/models/task.ts index a0a799fbb..4710ab405 100644 --- a/web/src/app/workplace/models/task.ts +++ b/web/src/app/workplace/models/task.ts @@ -22,6 +22,8 @@ export class Task { public priority: number, public classificationSummaryResource: Classification, public workbasketSummaryResource: Workbasket, + public customAttributes: Object, + public callbackInfo: Object, public custom1: string, public custom2: string, public custom3: string, @@ -40,3 +42,25 @@ export class Task { public custom16: string) { } } + +export class CustomAttribute { + key: string; + value: string; +} + +export function convertToCustomAttributes(callbackInfo: boolean = false): CustomAttribute[] { + return Object.keys(callbackInfo ? this.callbackInfo : this.customAttributes) + .map(k => ({ key: k, value: (callbackInfo ? this.callbackInfo : this.customAttributes)[k] })); +} + +export function saveCustomAttributes(attributes: CustomAttribute[], callbackInfo: boolean = false): void { + const att: Object = attributes.filter(attr => attr.key).reduce((acc, obj) => { + acc[obj.key] = obj.value; + return acc; + }, {}); + if (callbackInfo) { + this.callbackInfo = att; + } else { + this.customAttributes = att; + } +} diff --git a/web/src/app/workplace/services/task.service.ts b/web/src/app/workplace/services/task.service.ts index bd2c9aa18..851e313da 100644 --- a/web/src/app/workplace/services/task.service.ts +++ b/web/src/app/workplace/services/task.service.ts @@ -17,14 +17,14 @@ export class TaskService { STATE = 'state'; url = `${environment.taskanaRestUrl}/v1/tasks`; - - private taskSelected = new Subject(); - taskChangedSource = new Subject(); taskChangedStream = this.taskChangedSource.asObservable(); - taskDeletedSource = new Subject(); taskDeletedStream = this.taskDeletedSource.asObservable(); + private taskSelected = new Subject(); + + constructor(private httpClient: HttpClient) { + } publishUpdatedTask(task: Task) { this.taskChangedSource.next(task); @@ -42,9 +42,6 @@ export class TaskService { return this.taskSelected.asObservable(); } - constructor(private httpClient: HttpClient) { - } - /** * @param {string} basketId * @param {string} sortBy name of field, that the tasks should be sorted by, default is priority diff --git a/web/src/app/workplace/taskdetails/attribute/attribute.component.html b/web/src/app/workplace/taskdetails/attribute/attribute.component.html new file mode 100644 index 000000000..75eaf11e2 --- /dev/null +++ b/web/src/app/workplace/taskdetails/attribute/attribute.component.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + +
    AttributeProperty
    + + + + + +
    + +
    diff --git a/web/src/app/workplace/taskdetails/attribute/attribute.component.scss b/web/src/app/workplace/taskdetails/attribute/attribute.component.scss new file mode 100644 index 000000000..5a5e6c4cd --- /dev/null +++ b/web/src/app/workplace/taskdetails/attribute/attribute.component.scss @@ -0,0 +1,3 @@ +.table__remove-col { + width: 57px; +} diff --git a/web/src/app/workplace/taskdetails/attribute/attribute.component.spec.ts b/web/src/app/workplace/taskdetails/attribute/attribute.component.spec.ts new file mode 100644 index 000000000..7a5cd5186 --- /dev/null +++ b/web/src/app/workplace/taskdetails/attribute/attribute.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TaskdetailsAttributeComponent } from './attribute.component'; + +describe('AttributeComponent', () => { + let component: TaskdetailsAttributeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TaskdetailsAttributeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TaskdetailsAttributeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/web/src/app/workplace/taskdetails/attribute/attribute.component.ts b/web/src/app/workplace/taskdetails/attribute/attribute.component.ts new file mode 100644 index 000000000..f0380e21d --- /dev/null +++ b/web/src/app/workplace/taskdetails/attribute/attribute.component.ts @@ -0,0 +1,35 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { convertToCustomAttributes, CustomAttribute, Task } from 'app/workplace/models/task'; + +@Component({ + selector: 'taskana-task-details-attributes', + templateUrl: './attribute.component.html', + styleUrls: ['./attribute.component.scss'] +}) +export class TaskdetailsAttributeComponent implements OnInit { + + @Input() task: Task; + @Input() callbackInfo = false; + attributes: CustomAttribute[] = []; + + @Output() notify: EventEmitter = new EventEmitter(); + + constructor() { + } + + ngOnInit() { + if (this.task) { + this.attributes = convertToCustomAttributes.bind(this.task)(this.callbackInfo); + this.notify.emit(this.attributes); + } + } + + addAttribute(): void { + this.attributes.push({ key: '', value: '' }); + } + + removeAttribute(idx: number): void { + this.attributes.splice(idx, 1); + } + +} diff --git a/web/src/app/workplace/taskdetails/custom/custom-fields.component.html b/web/src/app/workplace/taskdetails/custom/custom-fields.component.html new file mode 100644 index 000000000..08d254ead --- /dev/null +++ b/web/src/app/workplace/taskdetails/custom/custom-fields.component.html @@ -0,0 +1,102 @@ + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    diff --git a/web/src/app/workplace/taskdetails/custom/custom-fields.component.spec.ts b/web/src/app/workplace/taskdetails/custom/custom-fields.component.spec.ts new file mode 100644 index 000000000..0f517bf14 --- /dev/null +++ b/web/src/app/workplace/taskdetails/custom/custom-fields.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TaskdetailsCustomFieldsComponent } from './custom-fields.component'; + +describe('CustomComponent', () => { + let component: TaskdetailsCustomFieldsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TaskdetailsCustomFieldsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TaskdetailsCustomFieldsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/web/src/app/workplace/taskdetails/custom/custom-fields.component.ts b/web/src/app/workplace/taskdetails/custom/custom-fields.component.ts new file mode 100644 index 000000000..334435be5 --- /dev/null +++ b/web/src/app/workplace/taskdetails/custom/custom-fields.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Task } from 'app/workplace/models/task'; + +@Component({ + selector: 'taskana-task-details-custom-fields', + templateUrl: './custom-fields.component.html' +}) +export class TaskdetailsCustomFieldsComponent implements OnInit { + + @Input() task: Task; + + constructor() { + } + + ngOnInit() { + } + +} diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.html b/web/src/app/workplace/taskdetails/general/general-fields.component.html new file mode 100644 index 000000000..5f6440d11 --- /dev/null +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.html @@ -0,0 +1,113 @@ + +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts b/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts new file mode 100644 index 000000000..53b7b1ebd --- /dev/null +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TaskdetailsGeneralFieldsComponent } from './general-fields.component'; + +describe('GeneralComponent', () => { + let component: TaskdetailsGeneralFieldsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TaskdetailsGeneralFieldsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TaskdetailsGeneralFieldsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.ts b/web/src/app/workplace/taskdetails/general/general-fields.component.ts new file mode 100644 index 000000000..d4bddf221 --- /dev/null +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Task } from 'app/workplace/models/task'; + +@Component({ + selector: 'taskana-task-details-general-fields', + templateUrl: './general-fields.component.html' +}) +export class TaskdetailsGeneralFieldsComponent implements OnInit { + + @Input() task: Task; + + constructor() { + } + + ngOnInit() { + } + +} diff --git a/web/src/app/workplace/taskdetails/taskdetails.component.html b/web/src/app/workplace/taskdetails/taskdetails.component.html index 659084b40..490599bfa 100644 --- a/web/src/app/workplace/taskdetails/taskdetails.component.html +++ b/web/src/app/workplace/taskdetails/taskdetails.component.html @@ -1,4 +1,33 @@ + +
    @@ -16,208 +45,23 @@

    {{task?.name}}

    -
    +
    -
    -
    - - +
    +
    +
    -
    - - + +
    +
    -
    - - +
    +
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - +
    +
    diff --git a/web/src/app/workplace/taskdetails/taskdetails.component.scss b/web/src/app/workplace/taskdetails/taskdetails.component.scss index f702654d2..e69de29bb 100644 --- a/web/src/app/workplace/taskdetails/taskdetails.component.scss +++ b/web/src/app/workplace/taskdetails/taskdetails.component.scss @@ -1,6 +0,0 @@ -.list-group { - max-height: 85vh; - margin-bottom: 10px; - overflow: hidden; - overflow-y: scroll; -} diff --git a/web/src/app/workplace/taskdetails/taskdetails.component.ts b/web/src/app/workplace/taskdetails/taskdetails.component.ts index 7aa55e7e6..53c41e4b2 100644 --- a/web/src/app/workplace/taskdetails/taskdetails.component.ts +++ b/web/src/app/workplace/taskdetails/taskdetails.component.ts @@ -5,7 +5,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { TaskService } from 'app/workplace/services/task.service'; import { RemoveConfirmationService } from 'app/services/remove-confirmation/remove-confirmation.service'; -import { Task } from 'app/workplace/models/task'; +import {convertToCustomAttributes, saveCustomAttributes, CustomAttribute, Task} from 'app/workplace/models/task'; import {ErrorModel} from '../../models/modal-error'; import {ErrorModalService} from '../../services/errorModal/error-modal.service'; @@ -16,7 +16,10 @@ import {ErrorModalService} from '../../services/errorModal/error-modal.service'; }) export class TaskdetailsComponent implements OnInit, OnDestroy { task: Task = null; + customAttributes: CustomAttribute[] = []; + callbackInfo: CustomAttribute[] = []; requestInProgress = false; + tabSelected = 'general'; private routeSubscription: Subscription; @@ -49,6 +52,8 @@ export class TaskdetailsComponent implements OnInit, OnDestroy { updateTask() { this.requestInProgress = true; + saveCustomAttributes.bind(this.task)(this.customAttributes); + saveCustomAttributes.bind(this.task)(this.callbackInfo, true); this.taskService.updateTask(this.task).subscribe(task => { this.requestInProgress = false; this.task = task; @@ -69,13 +74,33 @@ export class TaskdetailsComponent implements OnInit, OnDestroy { `You are going to delete Task: ${this.task.taskId}. Can you confirm this action?`); } + deleteTaskConfirmation(): void { this.taskService.deleteTask(this.task).subscribe(); this.taskService.publishDeletedTask(this.task); this.task = null; + this.customAttributes = []; this.router.navigate([`/workplace/tasks`]); } + selectTab(tab: string): void { + this.tabSelected = tab; + } + + backClicked(): void { + this.task = undefined; + this.taskService.selectTask(this.task); + this.router.navigate(['./'], { relativeTo: this.route.parent }); + } + + linkAttributes(attr: CustomAttribute[], callbackInfo: boolean = false): void { + if (callbackInfo) { + this.callbackInfo = attr; + } else { + this.customAttributes = attr; + } + } + ngOnDestroy(): void { if (this.routeSubscription) { this.routeSubscription.unsubscribe(); diff --git a/web/src/app/workplace/tasklist/tasklist.component.ts b/web/src/app/workplace/tasklist/tasklist.component.ts index 1bd7644fd..90a08d013 100644 --- a/web/src/app/workplace/tasklist/tasklist.component.ts +++ b/web/src/app/workplace/tasklist/tasklist.component.ts @@ -60,6 +60,9 @@ export class TasklistComponent implements OnInit, OnDestroy { this.currentBasket = task.workbasketSummaryResource; this.getTasks(); } + if (!task) { + this.selectedId = undefined; + } }); } diff --git a/web/src/app/workplace/workplace.module.ts b/web/src/app/workplace/workplace.module.ts index 346545df1..30238a25b 100644 --- a/web/src/app/workplace/workplace.module.ts +++ b/web/src/app/workplace/workplace.module.ts @@ -9,6 +9,9 @@ import {AlertModule, TypeaheadModule} from 'ngx-bootstrap'; import {TaskListToolbarComponent} from './tasklist/tasklist-toolbar/tasklist-toolbar.component'; import {TasklistComponent} from './tasklist/tasklist.component'; import {TaskdetailsComponent} from './taskdetails/taskdetails.component'; +import {TaskdetailsGeneralFieldsComponent} from './taskdetails/general/general-fields.component'; +import {TaskdetailsCustomFieldsComponent} from './taskdetails/custom/custom-fields.component'; +import {TaskdetailsAttributeComponent} from './taskdetails/attribute/attribute.component'; import {TaskComponent} from './task/task.component'; import {CodeComponent} from './components/code/code.component'; @@ -36,6 +39,9 @@ const DECLARATIONS = [ TaskListToolbarComponent, TasklistComponent, TaskdetailsComponent, + TaskdetailsGeneralFieldsComponent, + TaskdetailsCustomFieldsComponent, + TaskdetailsAttributeComponent, TaskComponent, CodeComponent, OrderTasksByPipe diff --git a/web/src/assets/_site.scss b/web/src/assets/_site.scss index c8d587786..ec1dd1a6c 100644 --- a/web/src/assets/_site.scss +++ b/web/src/assets/_site.scss @@ -279,7 +279,7 @@ body{ } } -taskana-workbasket-information, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-monitor-tasks, +taskana-workbasket-information,taskana-task-details, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-access-items-management, taskana-classification-details,taskana-workbasket-details { & .panel{ border: none; @@ -302,7 +302,7 @@ taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classificati } } -li.list-group-item.active:hover, { +li.list-group-item.active:hover { color: #fff; background-color: $green; border-color: $green; @@ -311,7 +311,7 @@ li.list-group-item.active:hover, { .list-group-item.active{ background-color: $green; } -li.list-group-item:hover, { +li.list-group-item:hover { color: #555; text-decoration: none; background-color: #f5f5f5; @@ -342,7 +342,43 @@ li.list-group-item:hover, { } .align-center { - text-align: center; + text-align: center; +} + .nav.nav-tabs { + & > li { + & > a { + min-height: 52px; + padding-top: 15px; + border-radius: 0; + margin-right: 0; + &.has-changes { + border-bottom: solid #f0ad4e; + } + cursor: pointer; + } + + &:first-child > a { + border-left: none; + } + } + + & > li.active > a { + border-top: 3px solid #479ea9; + padding-top: 13px; + background-color: #f5f5f5; + } + + & > p { + margin: 0px; + } + + & > li.disabled { + cursor: not-allowed; + } + + & > li.disabled > a { + pointer-events: none; + } } .btn.rounded {