Commit 7f66a623 authored by Prayas Jain's avatar Prayas Jain

Added Edit Feature in On Behalf Of functionality , Updated Utilization chart...

Added Edit Feature in On Behalf Of functionality , Updated Utilization chart Functionality and Updated Edit feature for bench resource
parent 33b8a8f7
......@@ -199,6 +199,18 @@ public class EmployeeController {
return new ResponseEntity<ResponseDetails>(getRespDetails, HttpStatus.OK);
}
@RequestMapping(value = "/employees/getAllEmployees", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getAllEmployees(HttpServletRequest request) {
List<Employee> employeeList = empService.getAllEmployees();
ResponseDetails getRespDetails = new ResponseDetails(new Date(), 905, "Retrieved Employees successfully",
"Employees list by status", employeeList, request.getRequestURI(), "Employee Details: Status", null);
return new ResponseEntity<ResponseDetails>(getRespDetails, HttpStatus.OK);
}
@RequestMapping(value = "/employee/searchCriteria", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
......@@ -297,5 +309,4 @@ public class EmployeeController {
}
}
\ No newline at end of file
package com.nisum.myteam.controller;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.nisum.myteam.exception.handler.ResponseDetails;
import com.nisum.myteam.service.impl.FunctionalGroupService;
@RestController
@RequestMapping("/functionalGroups")
public class FunctionalGroupController {
@Autowired
FunctionalGroupService functionalGroupService;
@RequestMapping(value = "/getAllFunctionalGroups", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getAllFunctionalGroups(HttpServletRequest request) {
List<String> functionalGroupsList = functionalGroupService.getAllFunctionalGroups().stream().
filter(f -> !Arrays.asList("IT","Recruiter","Admin","HR","Accounts").contains(f.getName())).map(f -> f.getName()).collect(Collectors.toList());
ResponseDetails getRespDetails = new ResponseDetails(new Date(), 905, "Retrieved FunctionalGroups successfully",
"FunctionalGroups list", functionalGroupsList, request.getRequestURI(), "FunctionalGroups Details: Status", null);
return new ResponseEntity<ResponseDetails>(getRespDetails, HttpStatus.OK);
}
}
......@@ -274,55 +274,7 @@ public class ReportsController {
return new ResponseEntity<>(empList, HttpStatus.OK);
}
// @RequestMapping(value = "/fetchEmployeeDetailsByAccountBillability",
// method = RequestMethod.GET,
// produces = MediaType.APPLICATION_JSON_VALUE)
// public ResponseEntity<List<ResourceVO>> fetchEmployeeDetailsByAccountBillability(
// @RequestParam("account") String account,
// @RequestParam("billabilityStatus") String billabilityStatus)
// throws MyTeamException {
// List<ResourceVO> resourcesList = new ArrayList<>();
// if (account != null && !account.isEmpty()) {
// resourcesList = resourceService.getAllResourcesVO();
//
// }
// return new ResponseEntity<>(resourcesList, HttpStatus.OK);
// }
// @RequestMapping(value = "/fetchEmployeeDetailsByDateBillability",
// method = RequestMethod.GET,
// produces = MediaType.APPLICATION_JSON_VALUE)
// public ResponseEntity<List<Resource>> fetchEmployeeDetailsByDateBillability(
// @RequestParam("billabilityStatus") String billabilityStatus,
// @RequestParam("reportDate") String reportDateString)
// throws MyTeamException {
// List<Resource> empList = new ArrayList<>();
// if (reportDateString != null && !reportDateString.isEmpty()) {
// String pattern = "MM-dd-yyyy";
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
// Date reportDateValue = new Date();
// try {
// reportDateValue = simpleDateFormat.parse(reportDateString);
// } catch (ParseException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// Criteria status = Criteria.where("billableStatus")
// .is(billabilityStatus);
// Criteria criteriaV1 = Criteria.where("billingStartDate")
// .lt(reportDateValue);
// Criteria criteriaV21 = Criteria.where("billingEndDate").is(null);
// Criteria criteriaV22 = Criteria.where("billingEndDate")
// .gt(reportDateValue);
// Criteria criteriaV221 = status.andOperator(
// criteriaV1.orOperator(criteriaV21, criteriaV22));
// Query query = new Query();
// query.addCriteria(criteriaV221);
// empList = mongoTemplate.find(query, Resource.class);
// }
// return new ResponseEntity<>(empList, HttpStatus.OK);
// }
@RequestMapping(value = "/getBarChartReport",
method = RequestMethod.GET,
......
......@@ -132,17 +132,6 @@ public class ResourceController {
"List of Resources for a project", null, request.getRequestURI(), "Resource details", null);
return new ResponseEntity<ResponseDetails>(responseDetails, HttpStatus.OK);
}
@RequestMapping(value = "/resources/openPool/active", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getResourcesForOpenPool(HttpServletRequest request)
throws MyTeamException {
List<ResourceVO> resourcesList = resourceService.getResourcesForOpenPool(MyTeamUtils.BENCH_PROJECT_ID, MyTeamUtils.ACTIVE).stream()
.sorted((o1, o2) -> o1.getEmployeeName().trim().compareTo(o2.getEmployeeName().trim()))
.collect(Collectors.toList());
ResponseDetails responseDetails = new ResponseDetails(new Date(), 602, "Resources have been retrieved successfully",
"List of Resources for a project", resourcesList, request.getRequestURI(), "Resource details", null);
return new ResponseEntity<ResponseDetails>(responseDetails, HttpStatus.OK);
}
@RequestMapping(value = "/resources/getMyProjectAllocations", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getMyProjectAllocations(
......
......@@ -71,9 +71,6 @@ public interface IResourceService {
Resource getCurrentAllocation(String employeeId);
List<ResourceVO> getResourcesForOpenPool(String projectId, String statusFlag);
// List<Resource> getAllResourcesForProject(String projectId, String status);
// List<Resource> getResourcesForEmployee(String empId);
......
......@@ -22,7 +22,7 @@ import java.util.stream.Collectors;
public class ReportService implements IReportService {
private static final String Shadow = "Shadow";
private static final String Reserved = "Reserved";
@Autowired
......@@ -43,7 +43,7 @@ public class ReportService implements IReportService {
public ReportVo getBarChartReport(String byType) throws MyTeamException {
ReportVo reportVo = new ReportVo();
if(byType.equals("FunctionalGroup")) {
if(byType.equals("AllFunctionalGroup")) {
functionalGroupService.getAllFunctionalGroups().stream().
filter(f -> !Arrays.asList("IT","Recruiter","Admin","HR","Accounts").contains(f.getName())).
forEach(f -> reportVo.getCategoriesList().add(f.getName()));
......@@ -71,13 +71,14 @@ public class ReportService implements IReportService {
float billper;
float nonBillPer;
List<Employee> employeeList = new ArrayList<>();
if(byType.equals("FunctionalGroup")) {
if(byType.equals("AllFunctionalGroup")) {
employeeList = getEmployeesByFunctionalGroup(category);
} else {
} else if(byType.equals("Account")){
employeeList = getEmployeeByAccounts(category);
}
// .getAllEmployees().stream().
// filter(e -> e.getFunctionalGroup().equals(functionalGroup)).collect(Collectors.toList());
else {
employeeList = getEmployeesByAccAndFG(category,byType);
}
for(Employee employee:employeeList){
Resource resource = resourceService.getCurrentAllocationIfNotReturnNull(employee.getEmployeeId());//getCurrentAllocation(employee.getEmployeeId());
if(resource!=null && resource.getBillableStatus().equals("Billable")){
......@@ -111,7 +112,13 @@ public class ReportService implements IReportService {
return reportVo;
}
private List<Employee> getEmployeesByFunctionalGroup(String functionalGroup){
private List<Employee> getEmployeesByAccAndFG(String account, String functionalGroup) {
List<Employee> empList = new ArrayList<Employee>();
empList = getEmployeeByAccounts(account).stream().filter(e -> e.getFunctionalGroup().equals(functionalGroup)).collect(Collectors.toList());
return empList;
}
private List<Employee> getEmployeesByFunctionalGroup(String functionalGroup){
return employeeService.getEmployeesByFunctionalGrp(functionalGroup);
}
......@@ -124,8 +131,9 @@ public class ReportService implements IReportService {
Employee employee= employeeService.findByEmployeeIdAndEmpStatus(MyTeamUtils.ACTIVE,r.getEmployeeId());
if(employee!=null)
employeeList.add(employeeService.getEmployeeById(r.getEmployeeId()));
});
});
});
return employeeList;
}
......
......@@ -145,7 +145,7 @@ public class ResourceService implements IResourceService {
Resource resource = resourceRepo.findById(resourceReq.getId());
if (resource != null) {
if(!resource.getStatus().equalsIgnoreCase(MyTeamUtils.STATUS_RELEASED)){
if(!resource.getStatus().equalsIgnoreCase(MyTeamUtils.STATUS_RELEASED) || resourceReq.getProjectId().equalsIgnoreCase(MyTeamUtils.BENCH_PROJECT_ID)){
if(resource.getStatus().equals(MyTeamUtils.STATUS_PROPOSED) && resourceReq.getStatus().equals(MyTeamUtils.STATUS_ENGAGED)){
if(validateResourceForProposedToEngage(resourceReq)){
......@@ -579,7 +579,8 @@ public class ResourceService implements IResourceService {
resourcesList.addAll(prepareProjectTeamMembersList(resource.getProjectId()));
}
}
return resourcesList;
return resourcesList.stream().sorted((o1, o2) -> o1.getEmployeeName().trim().compareTo(o2.getEmployeeName().trim()))
.collect(Collectors.toList());
}
......@@ -611,9 +612,12 @@ public class ResourceService implements IResourceService {
} else {
resourceVO.setResourceStatus(ResourceStatus.IN_ACTIVE.getStatus());
}
finalResourcesList.add(resourceVO);
if(projectId.equalsIgnoreCase(MyTeamUtils.BENCH_PROJECT_ID) && employee.getEmpStatus().equalsIgnoreCase(MyTeamUtils.ACTIVE)) {
finalResourcesList.add(resourceVO);
}
else if(!projectId.equalsIgnoreCase(MyTeamUtils.BENCH_PROJECT_ID)){
finalResourcesList.add(resourceVO);
}
}
return finalResourcesList;
}
......@@ -665,8 +669,14 @@ public class ResourceService implements IResourceService {
if (statusFlag.equals(ResourceStatus.ACTIVE.getStatus()) &&
(resource.getStatus().equals(MyTeamUtils.STATUS_ENGAGED) ||
(resource.getProjectId().equalsIgnoreCase(MyTeamUtils.BENCH_PROJECT_ID)))) {
resourceVO.setResourceStatus(ResourceStatus.ACTIVE.getStatus());
resourcesList.add(resourceVO);
resourceVO.setResourceStatus(ResourceStatus.ACTIVE.getStatus());
if(resource.getProjectId().equalsIgnoreCase(MyTeamUtils.BENCH_PROJECT_ID) &&
employee.getEmpStatus().equalsIgnoreCase(MyTeamUtils.ACTIVE) && (resource.getBillingEndDate().compareTo(new Date())>0)) {
resourcesList.add(resourceVO);
}
else if(!resource.getProjectId().equalsIgnoreCase(MyTeamUtils.BENCH_PROJECT_ID)) {
resourcesList.add(resourceVO);
}
} else if (statusFlag.equals(ResourceStatus.IN_ACTIVE.getStatus()) && resource.getStatus().equals(MyTeamUtils.STATUS_RELEASED)) {
resourceVO.setResourceStatus(ResourceStatus.IN_ACTIVE.getStatus());
resourcesList.add(resourceVO);
......@@ -679,40 +689,10 @@ public class ResourceService implements IResourceService {
}
}
return resourcesList;
return resourcesList.stream().sorted((o1, o2) -> o1.getEmployeeName().trim().compareTo(o2.getEmployeeName().trim()))
.collect(Collectors.toList());
}
@Override
public List<ResourceVO> getResourcesForOpenPool(String projectId, String statusFlag) {
List<ResourceVO> resourcesList = new ArrayList<>();
for (Resource resource : resourceRepo.findByProjectId(projectId)) {
Date billingEndDate = resource.getBillingEndDate();
Date todayDate = new Date();
if (billingEndDate != null) {
Employee employee = employeeService.getEmployeeById(resource.getEmployeeId());
if(employee.getEmpStatus().equalsIgnoreCase(MyTeamUtils.ACTIVE) && billingEndDate.compareTo(todayDate)>0) {
ResourceVO resourceVO = new ResourceVO();
resourceVO.setId(resource.getId());
resourceVO.setProjectId(resource.getProjectId());
resourceVO.setProjectName(projectService.getProjectByProjectId(resource.getProjectId()).getProjectName());
resourceVO.setResourceRole(resource.getResourceRole());
resourceVO.setBillingStartDate(resource.getBillingStartDate());
resourceVO.setBillingEndDate(resource.getBillingEndDate());
resourceVO.setBillableStatus(resource.getBillableStatus());
resourceVO.setEmployeeId(resource.getEmployeeId());
resourceVO.setStatus(resource.getStatus());
resourceVO.setOnBehalfOf(resource.getOnBehalfOf()!=null?employeeService.getEmployeeById(resource.getOnBehalfOf()).getEmployeeName():"");
resourceVO.setEmailId(employee.getEmailId());
resourceVO.setEmployeeName(employee.getEmployeeName());
resourceVO.setDesignation(employee.getDesignation());
resourcesList.add(resourceVO);
}
}
}
return resourcesList;
}
@Override
......
......@@ -4,19 +4,21 @@ myApp.directive('hcPieChart', function () {
restrict: 'E',
template: '<div></div>',
link: function (scope, element) {
getEmployeeDetails(scope,element[0].baseURI+'reports/getBarChartReport?byType=FunctionalGroup','column',element,"Billability By Functional Group");
getEmployeeDetails(scope,element[0].baseURI+'reports/getBarChartReport?byType=AllFunctionalGroup','column',element,"Billability For All Functional Group");
//getEmployeeDetails(scope,element[0].baseURI+'reports/billabilityByFunctionalGroup','column',element,"Billability By Functional Group");
//getEmployeeDetails(scope,element[0].baseURI+'reports/getBillabilityDetailsByAccount','column',element,"Billability By Account");
scope.clickMe= function() {
scope.gridOptions.data = [];
scope.clickMe= function(reportType) {
scope.gridOptions.data = [];
scope.gridOptions.enablePaginationControls = false;
if(scope.reportId == 1){
getEmployeeDetails(scope,element[0].baseURI+'reports/getBarChartReport?byType=FunctionalGroup','column',element,"Billability By Functional Group");
}else if(scope.reportId == 2){
getEmployeeDetails(scope,element[0].baseURI+'reports/getBarChartReport?byType=Account','column',element,"Billability By Account");
}else if(scope.reportId == 3){
getEmployeeDetails(scope,element[0].baseURI+'reports/getBillabilityDetailsByMonth','line',element," Billability Monthly Trends");
}
if(reportType!=null ) {
if(reportType == "Monthly Trends"){
getEmployeeDetails(scope,element[0].baseURI+'reports/getBillabilityDetailsByMonth','line',element," Billability Monthly Trends");
}
else {
reportTypeApiFormat = reportType == "All Functional Group" ? reportType.replace(/\s/g, "") : reportType;
getEmployeeDetails(scope,element[0].baseURI+'reports/getBarChartReport?byType='+reportTypeApiFormat,'column',element,"Billability For "+reportType);
}
}
}
}
};
......@@ -25,11 +27,19 @@ myApp.directive('hcPieChart', function () {
$scope.name = [];
$scope.records = [];
$scope.empSearchId = "";
$scope.reportId = "1"
$scope.reports = $scope.reportId;
$scope.reports=[{Name:"Billability By Functional Group",Id:"1"},{Name:"Billability By Account",Id:"2"},{Name:"Billability Monthly Trends",Id:"3"}];
$scope.reportType = "All Functional Group"
$scope.reportTypeList = ["All Functional Group", "Account", "Monthly Trends"];
$scope.getAllOptions = function() {
$http({
method: "GET",
url: appConfig.appUri + "functionalGroups/getAllFunctionalGroups"
}).then(function mySuccess(response) {
$scope.reportTypeList = $scope.reportTypeList.concat(response.data.records);
}, function myError(response) {
showAlert("Something went wrong while fetching data!!!");
$scope.gridOptions.data = [];
});
}
$scope.employees = [];
$scope.projects = [];
$scope.gridOptions = {
......@@ -94,8 +104,8 @@ myApp.directive('hcPieChart', function () {
$scope.gridOptions.enablePaginationControls = false;
$scope.getMyTeamDetails = function(seriesName, category, optionName,title){
if(title.trim() == 'Billability By Functional Group'){
console.log(title)
if(title.trim() == 'Billability For All Functional Group'){
if(category=='I&A'){
category = 'I%26A';
}
......@@ -114,7 +124,7 @@ myApp.directive('hcPieChart', function () {
showAlert("Something went wrong while fetching data!!!");
$scope.gridOptions.data = [];
});
}else if(title.trim() == 'Billability By Account'){
}else if(title.trim() == 'Billability For Account'){
$http({
method : "GET",
url : appConfig.appUri + "reports/fetchEmployeeDetailsByAccountBillability?account="+category+"&billabilityStatus="+seriesName
......@@ -210,6 +220,15 @@ myApp.directive('hcPieChart', function () {
}
}
},
column: {
dataLabels: {
enabled: true,
formatter: function () {
return this.point.y;
}
}
},
series:{
events:{
......
myApp.controller("openPoolController", function($scope, $http, myFactory, $mdDialog, appConfig, exportUiGridService) {
myApp.controller("openPoolController", function($scope, $http, myFactory, $mdDialog, appConfig, exportUiGridService, $timeout) {
$scope.records = [];
var today = new Date();
var getCellTemplate = '<p class="col-lg-12"><i ng-show="!row.entity.editrow" class="fa fa-pencil-square-o fa-2x" data-placement="center" title="Edit" onmouseenter="$(this).tooltip(\'show\')" aria-hidden="true" style="font-size:1.5em;margin-top:3px;cursor:pointer;" ng-click="grid.appScope.onEdit(row)"></i>'+
......@@ -76,7 +76,7 @@ myApp.controller("openPoolController", function($scope, $http, myFactory, $mdDia
}
$http({
method : "GET",
url : appConfig.appUri + 'resources/openPool/active'
url : appConfig.appUri + 'resources/project/Nisum0000?status=Active'
}).then(function mySuccess(response) {
$mdDialog.hide();
$scope.gridOptions.data = response.data.records;
......
......@@ -36,7 +36,7 @@ myApp.controller("projectController", function ($scope,uiGridConstants, myFactor
var getCellTemplate = '<p class="col-lg-12"><i class="fa fa-users fa-2x" aria-hidden="true" style="font-size:1.4em;margin-top:3px;cursor:pointer;" ng-class="{ \'my-css-class\': grid.appScope.rowFormatter( row ) }" data-placement="center" title="View" onmouseenter="$(this).tooltip(\'show\')" ng-click="grid.appScope.getRowData(row,\'View\')" ></i>' +
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i ng-show="row.entity.status == \'Active\'" class="fa fa-pencil-square-o fa-2x" aria-hidden="true" style="font-size:1.5em;margin-top:3px;cursor:pointer;" data-placement="center" title="Edit" onmouseenter="$(this).tooltip(\'show\')" ng-click="grid.appScope.getRowData(row,\'Update\')"></i></p>' ;
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i ng-show="row.entity.status == \'Active\' || row.entity.status == \'Proposed\'" class="fa fa-pencil-square-o fa-2x" aria-hidden="true" style="font-size:1.5em;margin-top:3px;cursor:pointer;" data-placement="center" title="Edit" onmouseenter="$(this).tooltip(\'show\')" ng-click="grid.appScope.getRowData(row,\'Update\')"></i></p>' ;
// '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i class="fa fa-minus-circle fa-2x" aria-hidden="true" style="font-size:1.5em;margin-top:3px;cursor:pointer;" data-placement="left" title="Delete" onmouseenter="$(this).tooltip(\'show\')" ng-click="grid.appScope.getRowData(row,\'Delete\')"></i></p>'
......@@ -559,6 +559,16 @@ myApp.controller("projectController", function ($scope,uiGridConstants, myFactor
});
};
$scope.getAllEmployees = function(){
$http({
method : "GET",
url : appConfig.appUri + "employees/getAllEmployees"
}).then(function mySuccess(response) {
$scope.allEmployeesList =response.data.records;
}, function myError(response) {
showAlert("Something went wrong while fetching data!!!");
});
};
function setDomain(action) {
$scope.domains.forEach(function(domain){
if(domain.domainId == dataToPass.domainId){
......@@ -639,8 +649,8 @@ myApp.controller("projectController", function ($scope,uiGridConstants, myFactor
'<span class="glyphicon glyphicon-remove close-mdselect" ng-click="grid.appScope.closeSelectBox()"></span>'+
'</md-select-header>'+
'<md-optgroup label="Employee" class="optionScroll">'+
'<md-option value= "" ng-click="grid.appScope.getEmp(null)">None</md-option>'+
'<md-option ng-value="employee.employeeName" ng-repeat="employee in grid.appScope.employeeList | filter:grid.appScope.searchFilter" ng-click="grid.appScope.getEmp(employee)">{{employee.employeeName}}</md-option>'+
'<md-option value= "">None</md-option>'+
'<md-option value="{{employee.employeeName}}" ng-repeat="employee in grid.appScope.allEmployeesList | filter:grid.appScope.searchFilter">{{employee.employeeName}}</md-option>'+
'</md-optgroup>'+
'</md-select></div>';
......@@ -1541,7 +1551,7 @@ myApp.controller("projectController", function ($scope,uiGridConstants, myFactor
}
$scope.getOnBehalfOfEmpId = function(onBehalfOfEmpName){
return $scope.employeeList.filter(function (employee) {
return $scope.allEmployeesList.filter(function (employee) {
return employee.employeeName == onBehalfOfEmpName;
});
}
......
......@@ -693,4 +693,7 @@ cursor: pointer;
}
.substatus-report-grid {
height: calc(85vh - 150px) !important;
}
.manage-open-pool {
height: calc(100vh - 239px) !important;
}
\ No newline at end of file
......@@ -2,10 +2,12 @@
<body>
<div class="md-padding"
id="popupContainer" ng-controller="chartsController">
id="popupContainer" ng-controller="chartsController" ng-init="getAllOptions()">
<div class="text-right">
Report Type:<select ng-model="reportId" #ref ng-change="clickMe()" ng-options="report.Id as report.Name for report in reports"></select>
Report Type: <select ng-model="reportType" #ref ng-change="clickMe(reportType)">
<option ng-value="reportType" ng-repeat="reportType in reportTypeList" >Billability : {{reportType}}</option>
</select>
</div>
<hc-pie-chart title="Browser usage" data="pieData" options="chartOptions">Placeholder for pie chart</hc-pie-chart>
......
<md-dialog aria-label="Team Details" style="height:auto;" class="viewTeamDetails md-dialog-custom-height" ng-init="getEmployeeDetails()" id="projectTeamDetails" >
<md-dialog aria-label="Team Details" style="height:auto;" class="viewTeamDetails md-dialog-custom-height" ng-init="getEmployeeDetails(); getAllEmployees();" id="projectTeamDetails" >
<form ng-cloak name="myForm ">
<md-toolbar>
<div class="md-toolbar-tools " style="background: cadetblue; ">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment