From b58c4e4c179ef8eca1db307f31ed51cd69e25462 Mon Sep 17 00:00:00 2001 From: Misha Date: Fri, 4 Dec 2015 15:39:56 +0200 Subject: [PATCH] Merging with main fork --- .../libreplan/business/common/Registry.java | 14 + .../common/entities/Configuration.java | 8 + .../common/entities/EntityNameEnum.java | 11 +- .../business/logs/daos/IIssueLogDAO.java | 40 ++ .../business/logs/daos/IProjectLogDAO.java | 49 ++ .../business/logs/daos/IRiskLogDAO.java | 36 ++ .../business/logs/daos/IssueLogDAO.java | 46 ++ .../business/logs/daos/ProjectLogDAO.java | 54 +++ .../business/logs/daos/RiskLogDAO.java | 46 ++ .../business/logs/entities/IssueLog.java | 158 +++++++ .../logs/entities/IssueStatusEnum.java | 26 ++ .../business/logs/entities/IssueTypeEnum.java | 28 ++ .../logs/entities/LowMediumHighEnum.java | 47 ++ .../business/logs/entities/ProjectLog.java | 54 +++ .../business/logs/entities/RiskLog.java | 172 +++++++ .../logs/entities/RiskScoreStatesEnum.java | 26 ++ .../libreplan-business-spring-config.xml | 3 + .../business/logs/entities/Logs.hbm.xml | 107 +++++ .../web/common/CustomMenuController.java | 13 + .../libreplan/web/logs/IIssueLogModel.java | 119 +++++ .../org/libreplan/web/logs/IRiskLogModel.java | 119 +++++ .../web/logs/IssueLogCRUDController.java | 420 ++++++++++++++++++ .../org/libreplan/web/logs/IssueLogModel.java | 183 ++++++++ .../libreplan/web/logs/LogsController.java | 119 +++++ .../web/logs/RiskLogCRUDController.java | 366 +++++++++++++++ .../org/libreplan/web/logs/RiskLogModel.java | 183 ++++++++ .../web/planner/tabs/LogsTabCreator.java | 160 +++++++ .../tabs/MultipleTabsPlannerController.java | 46 +- .../services/CustomTargetUrlResolver.java | 119 +++++ .../main/webapp/common/css/libreplan_zk.css | 13 + .../src/main/webapp/common/img/cabecera.jpg | Bin 0 -> 4808 bytes .../webapp/common/img/ico_logs-global.png | Bin 0 -> 2781 bytes .../main/webapp/common/img/ico_logs-order.png | Bin 0 -> 3228 bytes .../src/main/webapp/common/img/logo.gif | Bin 0 -> 9569 bytes .../src/main/webapp/common/img/logo2.gif | Bin 0 -> 7248 bytes .../src/main/webapp/logs/_editIssueLog.zul | 169 +++++++ .../src/main/webapp/logs/_editRiskLog.zul | 153 +++++++ .../src/main/webapp/logs/_listIssueLog.zul | 42 ++ .../src/main/webapp/logs/_listRiskLog.zul | 44 ++ .../src/main/webapp/logs/_logs.zul | 62 +++ .../src/main/webapp/logs/_logsFilter.zul | 28 ++ .../src/main/webapp/logs/issue_log.zul | 33 ++ .../src/main/webapp/logs/risk_log.zul | 33 ++ 43 files changed, 3346 insertions(+), 3 deletions(-) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/daos/IIssueLogDAO.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/daos/IProjectLogDAO.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/daos/IRiskLogDAO.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/daos/IssueLogDAO.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/daos/ProjectLogDAO.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/daos/RiskLogDAO.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueLog.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueStatusEnum.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueTypeEnum.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/LowMediumHighEnum.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/ProjectLog.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskLog.java create mode 100644 libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskScoreStatesEnum.java create mode 100644 libreplan-business/src/main/resources/org/libreplan/business/logs/entities/Logs.hbm.xml create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/IIssueLogModel.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/IRiskLogModel.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogCRUDController.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogModel.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/LogsController.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogCRUDController.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogModel.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/LogsTabCreator.java create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/users/services/CustomTargetUrlResolver.java create mode 100644 libreplan-webapp/src/main/webapp/common/img/cabecera.jpg create mode 100644 libreplan-webapp/src/main/webapp/common/img/ico_logs-global.png create mode 100644 libreplan-webapp/src/main/webapp/common/img/ico_logs-order.png create mode 100644 libreplan-webapp/src/main/webapp/common/img/logo.gif create mode 100644 libreplan-webapp/src/main/webapp/common/img/logo2.gif create mode 100644 libreplan-webapp/src/main/webapp/logs/_editIssueLog.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/_editRiskLog.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/_listIssueLog.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/_listRiskLog.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/_logs.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/_logsFilter.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/issue_log.zul create mode 100644 libreplan-webapp/src/main/webapp/logs/risk_log.zul diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/Registry.java b/libreplan-business/src/main/java/org/libreplan/business/common/Registry.java index 441e6d264..0d50523e7 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/common/Registry.java +++ b/libreplan-business/src/main/java/org/libreplan/business/common/Registry.java @@ -40,6 +40,8 @@ import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO; import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO; import org.libreplan.business.labels.daos.ILabelDAO; import org.libreplan.business.labels.daos.ILabelTypeDAO; +import org.libreplan.business.logs.daos.IIssueLogDAO; +import org.libreplan.business.logs.daos.IRiskLogDAO; import org.libreplan.business.materials.daos.IMaterialCategoryDAO; import org.libreplan.business.materials.daos.IMaterialDAO; import org.libreplan.business.materials.daos.IUnitTypeDAO; @@ -200,6 +202,12 @@ public class Registry { @Autowired private IExpenseSheetDAO expenseSheetDAO; + @Autowired + private IIssueLogDAO issueLogDAO; + + @Autowired + private IRiskLogDAO riskLogDAO; + @Autowired private IExpenseSheetLineDAO expenseSheetLineDAO; @@ -383,6 +391,12 @@ public class Registry { return getInstance().expenseSheetDAO; } + public static IIssueLogDAO getIssueLogDAO() { + return getInstance().issueLogDAO; + } + + public static IRiskLogDAO getRiskLogDAO() {return getInstance().riskLogDAO;} + public static IExpenseSheetLineDAO getExpenseSheetLineDAO() { return getInstance().expenseSheetLineDAO; } diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/entities/Configuration.java b/libreplan-business/src/main/java/org/libreplan/business/common/entities/Configuration.java index c56edd8ff..e6a811070 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/common/entities/Configuration.java +++ b/libreplan-business/src/main/java/org/libreplan/business/common/entities/Configuration.java @@ -48,6 +48,8 @@ public class Configuration extends BaseEntity { private String companyCode; + private Boolean generateCodeForProjectLog = true; + private Boolean generateCodeForCriterion = true; private Boolean generateCodeForLabel = true; @@ -202,6 +204,12 @@ public class Configuration extends BaseEntity { return true; } + //TODO 2 added methods follow below + public void setGeneratedCodeForProjectLog(Boolean generateCodeForProjectLog) { + this.generateCodeForProjectLog = generateCodeForProjectLog; + } + public Boolean getGenerateCodeForProjectLog(){ return generateCodeForProjectLog;} + public void setGenerateCodeForCriterion(Boolean generateCodeForCriterion) { this.generateCodeForCriterion = generateCodeForCriterion; } diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/entities/EntityNameEnum.java b/libreplan-business/src/main/java/org/libreplan/business/common/entities/EntityNameEnum.java index 25e25f062..f8f127d53 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/common/entities/EntityNameEnum.java +++ b/libreplan-business/src/main/java/org/libreplan/business/common/entities/EntityNameEnum.java @@ -31,6 +31,8 @@ import org.libreplan.business.costcategories.entities.ResourcesCostCategoryAssig import org.libreplan.business.costcategories.entities.TypeOfWorkHours; import org.libreplan.business.expensesheet.entities.ExpenseSheet; import org.libreplan.business.labels.entities.LabelType; +import org.libreplan.business.logs.entities.IssueLog; +import org.libreplan.business.logs.entities.RiskLog; import org.libreplan.business.materials.entities.MaterialCategory; import org.libreplan.business.materials.entities.UnitType; import org.libreplan.business.orders.entities.Order; @@ -56,7 +58,7 @@ public enum EntityNameEnum { "Calendar exception day", true), COST_CATEGORY("Cost category", true), RESOURCE_CALENDAR("Resource calendar", true), CRITERION_SATISFACTION( "Criterion satisfaction", true), RESOURCE_COST_CATEGORY_ASSIGNMENT( - "Resource cost category assignment", true), EXPENSE_SHEET("Expense sheet", true); + "Resource cost category assignment", true), EXPENSE_SHEET("Expense sheet", true), ISSUE_LOG("Issue log", true), RISK_LOG("Risk log", true); private String description; @@ -121,6 +123,13 @@ public enum EntityNameEnum { .getResourcesCostCategoryAssignmentDAO(); case EXPENSE_SHEET: return (IIntegrationEntityDAO) Registry.getExpenseSheetDAO(); + + case ISSUE_LOG: + return (IIntegrationEntityDAO) Registry.getIssueLogDAO(); + + case RISK_LOG: + return (IIntegrationEntityDAO) Registry.getRiskLogDAO(); + default: throw new RuntimeException("can't handle the code sequence of the " + description); diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IIssueLogDAO.java b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IIssueLogDAO.java new file mode 100644 index 000000000..95966063d --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IIssueLogDAO.java @@ -0,0 +1,40 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IIntegrationEntityDAO; +import org.libreplan.business.logs.entities.IssueLog; + +/** + * Contract for {@link IssueLogDAO} + * + * @author Miciele Ghiorghis + */ +public interface IIssueLogDAO extends IIntegrationEntityDAO { + + /** + * Gets all the issue-logs + * + * @return a list of {@link IssueLog} objects + */ + List getIssueLogs(); +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IProjectLogDAO.java b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IProjectLogDAO.java new file mode 100644 index 000000000..cbe212ade --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IProjectLogDAO.java @@ -0,0 +1,49 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IIntegrationEntityDAO; +import org.libreplan.business.logs.entities.IssueLog; +import org.libreplan.business.logs.entities.ProjectLog; +import org.libreplan.business.logs.entities.RiskLog; + +/** + * Contract for {@link ProjectLogDAO} + * + * @author Miciele Ghiorghis + */ +public interface IProjectLogDAO extends IIntegrationEntityDAO { + + /** + * Gets all the issue-logs + * + * @return a list of {@link IssueLog} objects + */ + List getIssueLogs(); + + /** + * Gets all the risk logs + * + * @return a list of {@link RiskLog} objects + */ + List getRiskLogs(); +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IRiskLogDAO.java b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IRiskLogDAO.java new file mode 100644 index 000000000..bcc20a7f6 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IRiskLogDAO.java @@ -0,0 +1,36 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IIntegrationEntityDAO; +import org.libreplan.business.logs.entities.RiskLog; + +public interface IRiskLogDAO extends IIntegrationEntityDAO { + + /** + * Gets all the risk-logs + * + * @return a list of {@link RiskLog} objects + */ + List getRiskLogs(); + +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IssueLogDAO.java b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IssueLogDAO.java new file mode 100644 index 000000000..0bdcd9e37 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/IssueLogDAO.java @@ -0,0 +1,46 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IntegrationEntityDAO; +import org.libreplan.business.logs.entities.IssueLog; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +/** + * DAO for {@link IssueLog} + * + * @author Miciele Ghiorghis + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class IssueLogDAO extends IntegrationEntityDAO implements + IIssueLogDAO { + + @Override + public List getIssueLogs() { + return list(IssueLog.class); + } + + +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/daos/ProjectLogDAO.java b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/ProjectLogDAO.java new file mode 100644 index 000000000..ec161e9ba --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/ProjectLogDAO.java @@ -0,0 +1,54 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IntegrationEntityDAO; +import org.libreplan.business.logs.entities.IssueLog; +import org.libreplan.business.logs.entities.ProjectLog; +import org.libreplan.business.logs.entities.RiskLog; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * DAO for {@link ProjectLog} + * + * @author Miciele Ghiorghis + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +@Transactional +public class ProjectLogDAO extends IntegrationEntityDAO implements + IProjectLogDAO { + + @Override + public List getIssueLogs() { + return list(IssueLog.class); + } + + @Override + public List getRiskLogs() { + return list(RiskLog.class); + } + +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/daos/RiskLogDAO.java b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/RiskLogDAO.java new file mode 100644 index 000000000..2bce9a40b --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/daos/RiskLogDAO.java @@ -0,0 +1,46 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IntegrationEntityDAO; +import org.libreplan.business.logs.entities.RiskLog; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +/** + * DAO for {@link RiskLog} + * + * @author Miciele Ghiorghis + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class RiskLogDAO extends IntegrationEntityDAO implements + IRiskLogDAO { + + + @Override + public List getRiskLogs() { + return list(RiskLog.class); + } + +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueLog.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueLog.java new file mode 100644 index 000000000..fc08ba3cf --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueLog.java @@ -0,0 +1,158 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.entities; +import javax.validation.constraints.NotNull; +import java.util.Date; + +import org.libreplan.business.common.IntegrationEntity; +import org.libreplan.business.common.Registry; +import org.libreplan.business.common.daos.IIntegrationEntityDAO; +import org.libreplan.business.users.entities.User; + +/** + * IssueLog entity, represents parameters to be able to administrate issues that + * come up in the project + * + * @author Misha Gozhda + */ +public class IssueLog extends ProjectLog { + + private IssueTypeEnum type = IssueTypeEnum.getDefault(); + private IssueStatusEnum status = IssueStatusEnum.getDefault(); + private LowMediumHighEnum priority = LowMediumHighEnum.getDefault(); + private LowMediumHighEnum severity = LowMediumHighEnum.getDefault(); + private Date dateRaised; + private User createdBy; + private String assignedTo; + private Date dateResolved; + private Date deadline; + private String notes; + + + public static IssueLog create() { + return create(new IssueLog(new Date())); + } + + /** + * Constructor for Hibernate. Do not use! + */ + protected IssueLog() { + + } + + private IssueLog(Date date) { + this.dateRaised = date; + } + + public IssueTypeEnum getType() { + return type; + } + + public void setType(IssueTypeEnum type) { + this.type = type; + } + + public IssueStatusEnum getStatus() { + return status; + } + + public void setStatus(IssueStatusEnum status) { + this.status = status; + } + + @NotNull(message = "priority is not specified") + public LowMediumHighEnum getPriority() { + return priority; + } + + public void setPriority(LowMediumHighEnum priority) { + this.priority = priority; + } + + public LowMediumHighEnum getSeverity() { + return severity; + } + + public void setSeverity(LowMediumHighEnum severity) { + this.severity = severity; + } + + @NotNull(message = "date raised is not specified") + public Date getDateRaised() { + return dateRaised; + } + + public void setDateRaised(Date dateEntered) { + this.dateRaised = dateEntered; + } + + public User getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(User user) { + this.createdBy = user; + } + + public String getAssignedTo() { + return assignedTo; + } + + public void setAssignedTo(String assignedTo) { + this.assignedTo = assignedTo; + } + + public Date getDateResolved() { + return dateResolved; + } + + public void setDateResolved(Date dateResolved) { + this.dateResolved = dateResolved; + } + + + public Date getDeadline() { + return deadline; + } + + public void setDeadline(Date decisionDate) { + this.deadline = decisionDate; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + + @Override + public String getHumanId() { + return getCode(); + } + + @Override + protected IIntegrationEntityDAO getIntegrationEntityDAO() { + return (IIntegrationEntityDAO) Registry + .getIssueLogDAO(); + } +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueStatusEnum.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueStatusEnum.java new file mode 100644 index 000000000..2b79a8daa --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueStatusEnum.java @@ -0,0 +1,26 @@ +package org.libreplan.business.logs.entities; +import static org.libreplan.business.i18n.I18nHelper._; +/** + * Defines INVESTIGATING, ESCALATED, RESOLVED enums + * to be used as data type in + * {@link IssueLog} + * + * @author Misha Gozhda + */ +public enum IssueStatusEnum { + INVESTIGATING(_("INVESTIGATING")), ESCALATED(_("ESCALATED")), RESOLVED(_("RESOLVED")); + + private final String issueStatusEnum; + + IssueStatusEnum(String issueStatusEnum) { + this.issueStatusEnum = issueStatusEnum; + } + + public String getDisplayName() { + return issueStatusEnum; + } + + public static IssueStatusEnum getDefault() { + return IssueStatusEnum.INVESTIGATING; + } +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueTypeEnum.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueTypeEnum.java new file mode 100644 index 000000000..93cdf37a3 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/IssueTypeEnum.java @@ -0,0 +1,28 @@ +package org.libreplan.business.logs.entities; + +import static org.libreplan.business.i18n.I18nHelper._; + +/** + * Defines PROBLEM_OR_CONCERN, REQUEST_FOR_CHANGE, OFF_SPECIFICATION enums + * to be used as data type in + * {@link IssueLog} + * + * @author Misha Gozhda + */ +public enum IssueTypeEnum { + PROBLEM_OR_CONCERN(_("PROBLEM OR CONCERN")), REQUEST_FOR_CHANGE(_("REQUEST FOR CHANGE")), OFF_SPECIFICATION(_("OFF SPECIFICATON")); + + private final String issueTypeEnum; + + IssueTypeEnum(String issueTypeEnum) { + this.issueTypeEnum = issueTypeEnum; + } + + public String getDisplayName() { + return issueTypeEnum; + } + + public static IssueTypeEnum getDefault() { + return IssueTypeEnum.OFF_SPECIFICATION; + } +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/LowMediumHighEnum.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/LowMediumHighEnum.java new file mode 100644 index 000000000..883fab6a2 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/LowMediumHighEnum.java @@ -0,0 +1,47 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.libreplan.business.logs.entities; + +import static org.libreplan.business.i18n.I18nHelper._; + + +/** + * Defines the low, medium and high enums to be used as data type in + * {@link IssueLog} and {@link RiskLog} + * + * @author Misha Gozhda + */ +public enum LowMediumHighEnum { + + LOW(_("LOW")), MEDIUM(_("MEDIUM")), HIGH(_("HIGH")); + + private final String lowMediumHighEnum; + + LowMediumHighEnum(String lowMediumHighEnum) { + this.lowMediumHighEnum = lowMediumHighEnum; + } + + public String getDisplayName() { + return lowMediumHighEnum; + } + + public static LowMediumHighEnum getDefault() { + return LowMediumHighEnum.LOW; + } +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/ProjectLog.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/ProjectLog.java new file mode 100644 index 000000000..c9a810700 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/ProjectLog.java @@ -0,0 +1,54 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.entities; + +import org.libreplan.business.common.IHumanIdentifiable; +import org.libreplan.business.common.IntegrationEntity; +import org.libreplan.business.common.Registry; +import org.libreplan.business.common.daos.IIntegrationEntityDAO; +import org.libreplan.business.orders.entities.Order; + +/** + * This class is the base class for all logs like issue-log, risk-log etc. + * + * @author Misha Gozhda + */ +public abstract class ProjectLog extends IntegrationEntity implements + IHumanIdentifiable { + + protected Order project; + protected String description; + + public Order getOrder() { + return project; + } + + public void setOrder(Order order) { + this.project = order; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskLog.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskLog.java new file mode 100644 index 000000000..2aa98d8de --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskLog.java @@ -0,0 +1,172 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.logs.entities; + +import org.libreplan.business.common.IntegrationEntity; +import org.libreplan.business.common.Registry; +import org.libreplan.business.common.daos.IIntegrationEntityDAO; +import org.libreplan.business.users.entities.User; + +import java.util.Date; + +/** + * RiskLog entity, represents parameters to be able to administrate risks that + * come up in the project + * + * @author Misha Gozhda + */ +public class RiskLog extends ProjectLog { + + private String projectName; + private String status; + private LowMediumHighEnum probability = LowMediumHighEnum.getDefault(); + private LowMediumHighEnum impact = LowMediumHighEnum.getDefault(); + private Date dateCreated; + private User createdBy; + private String counterMeasures; + private String contingency; + private String responsible; + private Date actionWhen; + private String notes; + private RiskScoreStatesEnum score = RiskScoreStatesEnum.getDefault(); + + public static RiskLog create() { + return create(new RiskLog()); + } + + /** + * Constructor for Hibernate. Do not use! + */ + protected RiskLog() { + + } + + public String getProjectName() { + return projectName; + } + + public void setProjectName (String projectName) { + this.projectName = projectName; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public LowMediumHighEnum getProbability() { + return probability; + } + + public void setProbability(LowMediumHighEnum probability) { + this.probability = probability; + } + + public LowMediumHighEnum getImpact() { + return impact; + } + + public void setImpact(LowMediumHighEnum impact) { + this.impact = impact; + } + + public Date getDateCreated() { + return dateCreated; + } + + public void setDateCreated(Date dateCreated) { + this.dateCreated = dateCreated; + } + + public User getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(User createdBy) { + this.createdBy = createdBy; + } + + public String getCounterMeasures() { + return counterMeasures; + } + + public void setCounterMeasures(String counterMeasures) { + this.counterMeasures = counterMeasures; + } + + public String getContingency() { + return contingency; + } + + public void setContingency(String contingency) { + this.contingency = contingency; + } + + public void setResponsible(String responsible) { + this.responsible = responsible; + } + + public String getResponsible() { + return responsible; + } + + public Date getActionWhen() { + return actionWhen; + } + + public void setActionWhen(Date actionWhen) { + this.actionWhen = actionWhen; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public void setScoreAfterCM(RiskScoreStatesEnum scoreAfterCM) { + this.score = scoreAfterCM; + } + + public RiskScoreStatesEnum getScoreAfterCM() { + return score; + } + + public int getRiskScore() { + return (probability.ordinal() + 1) * (impact.ordinal() + 1); + } + + @Override + public String getHumanId() { + return getCode(); + } + + @Override + protected IIntegrationEntityDAO getIntegrationEntityDAO() { + return (IIntegrationEntityDAO) Registry + .getRiskLogDAO(); + } + +} diff --git a/libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskScoreStatesEnum.java b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskScoreStatesEnum.java new file mode 100644 index 000000000..26f3e4bc7 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/logs/entities/RiskScoreStatesEnum.java @@ -0,0 +1,26 @@ +package org.libreplan.business.logs.entities; +import static org.libreplan.business.i18n.I18nHelper._; +/** + * Defines ZERO, ONE, TWO, THREE, FOUR, SIX, NINE + * to be used as data type in + * {@link RiskLog} + * + * @author Misha Gozhda + */ +public enum RiskScoreStatesEnum { + ZERO(_("0")), ONE(_("1")), TWO(_("2")), THREE(_("3")), FOUR(_("4")), SIX(_("6")), NINE(_("9")) ; + + private final String riskScoreStateEnum; + + RiskScoreStatesEnum(String riskScoreStateEnum) { + this.riskScoreStateEnum = riskScoreStateEnum; + } + + public String getDisplayName() { + return riskScoreStateEnum; + } + + public static RiskScoreStatesEnum getDefault() { + return RiskScoreStatesEnum.ZERO; + } +} diff --git a/libreplan-business/src/main/resources/libreplan-business-spring-config.xml b/libreplan-business/src/main/resources/libreplan-business-spring-config.xml index c7e391a87..4f00767e4 100644 --- a/libreplan-business/src/main/resources/libreplan-business-spring-config.xml +++ b/libreplan-business/src/main/resources/libreplan-business-spring-config.xml @@ -97,6 +97,9 @@ org/libreplan/business/email/entities/Email.hbm.xml + + org/libreplan/business/logs/entities/Logs.hbm.xml + diff --git a/libreplan-business/src/main/resources/org/libreplan/business/logs/entities/Logs.hbm.xml b/libreplan-business/src/main/resources/org/libreplan/business/logs/entities/Logs.hbm.xml new file mode 100644 index 000000000..eab2e621a --- /dev/null +++ b/libreplan-business/src/main/resources/org/libreplan/business/logs/entities/Logs.hbm.xml @@ -0,0 +1,107 @@ + + + + + + + 100 + + + + + + + + + + + + org.libreplan.business.logs.entities.IssueTypeEnum + + + + + + + + org.libreplan.business.logs.entities.LowMediumHighEnum + + + + + + org.libreplan.business.logs.entities.LowMediumHighEnum + + + + + + + + + + + + + + + + + + + + + + + + 100 + + + + + + + + + + + + org.libreplan.business.logs.entities.LowMediumHighEnum + + + + + + org.libreplan.business.logs.entities.LowMediumHighEnum + + + + + + + + + + + + + + + + + + + + + + + + + + org.libreplan.business.logs.entities.RiskScoreStatesEnum + + + + + + diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java index c62280ee5..bbd5b3225 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java @@ -275,6 +275,12 @@ public class CustomMenuController extends Div implements IMenuItemsRegister { } }, "01-introducion.html#id2")); } +/* planningItems.add(subItem(_("RiskLog"), new ICapture() { + @Override + public void capture() { + globalView.g + } + }*/ if (SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_PLANNING)) { planningItems.add(subItem(_("Resources Load"), new ICapture() { @Override @@ -298,6 +304,13 @@ public class CustomMenuController extends Div implements IMenuItemsRegister { planningItems.add(subItem(_("Import project"), "/orders/imports/projectImport.zul", "")); } + + if (SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_CRITERIA)) { + planningItems.add(subItem(_("RiskLog"), + "/logs/issue_log.zul", + "02-criterios.html#id1")); + } + if (!planningItems.isEmpty()) { topItem(_("Planning"), "/planner/index.zul", "", planningItems); } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/IIssueLogModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IIssueLogModel.java new file mode 100644 index 000000000..813365aa4 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IIssueLogModel.java @@ -0,0 +1,119 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import java.util.List; + +import org.libreplan.business.common.exceptions.ValidationException; +import org.libreplan.business.logs.entities.IssueLog; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.users.entities.User; + +/** + * Contract for {@link IssueLogModel} + * + * @author Miciele Ghiorghis + */ +public interface IIssueLogModel { + + /** + * Returns a list of all {@link IssueLog} + */ + List getIssueLogs(); + + /** + * Returns a list of all {@link Order} + */ + List getOrders(); + + /** + * Returns current {@link Order} + */ + Order getOrder(); + + /** + * Sets the order + * + * @param order + * the order to be set + */ + void setOrder(Order order); + + /** + * Returns a list of all {@link User} + */ + List getUsers(); + + /** + * Returns the {@link User} + */ + User getCreatedBy(); + + /** + * Sets the user + * + * @param user + * the user to be set + */ + void setCreatedBy(User user); + + /** + * Prepares for create a new {@link IssueLog}. + */ + void initCreate(); + + /** + * Prepares for edit {@link IssueLog} + * + * @param issueLog + * an object to be edited + */ + void initEdit(IssueLog issueLog); + + /** + * Gets the current {@link IssueLog}. + * + * @return A {@link IssueLog} + */ + IssueLog getIssueLog(); + + /** + * Saves the current {@link IssueLog} + * + * @throws ValidationException + * if validation fails + */ + void confirmSave() throws ValidationException; + + /** + * Cancels the current {@link IssueLog} + */ + void cancel(); + + /** + * Removes the current {@link IssueLog} + * + * @param issueLog + * an object to be removed + */ + void remove(IssueLog issueLog); + + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/IRiskLogModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IRiskLogModel.java new file mode 100644 index 000000000..63893aec7 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IRiskLogModel.java @@ -0,0 +1,119 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import java.util.List; + +import org.libreplan.business.common.exceptions.ValidationException; +import org.libreplan.business.logs.entities.RiskLog; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.users.entities.User; + +/** + * Contract for {@link RiskLogModel} + * + * @author Miciele Ghiorghis + */ +public interface IRiskLogModel { + + /** + * Returns a list of all {@link RiskLog} + */ + List getRiskLogs(); + + /** + * Returns a list of all {@link Order} + */ + List getOrders(); + + /** + * Returns current {@link Order} + */ + Order getOrder(); + + /** + * Sets the order + * + * @param order + * the order to set + */ + void setOrder(Order order); + + /** + * Returns a list of all {@link User} + */ + List getUsers(); + + /** + * Returns {@link User} + */ + User getCreatedBy(); + + /** + * Sets the user + * + * @param user + * the user to be set + */ + void setCreatedBy(User user); + + /** + * Prepares for create a new {@link RiskLog}. + */ + void initCreate(); + + /** + * Prepares for edit {@link RiskLog} + * + * @param riskLog + * an object to be edited + */ + void initEdit(RiskLog riskLog); + + /** + * Gets the current {@link RiskLog}. + * + * @return A {@link RiskLog} + */ + RiskLog getRiskLog(); + + /** + * Saves the current {@link RiskLog} + * + * @throws ValidationException + * if validation fails + */ + void confirmSave() throws ValidationException; + + /** + * Cancels the current {@link RiskLog} + */ + void cancel(); + + /** + * Removes the current {@link RiskLog} + * + * @param riskLog + * an object to be removed + */ + void remove(RiskLog riskLog); + + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogCRUDController.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogCRUDController.java new file mode 100644 index 000000000..4cd526f60 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogCRUDController.java @@ -0,0 +1,420 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import static org.libreplan.web.I18nHelper._; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.common.exceptions.ValidationException; +import org.libreplan.business.logs.entities.IssueLog; +import org.libreplan.business.logs.entities.IssueStatusEnum; +import org.libreplan.business.logs.entities.IssueTypeEnum; +import org.libreplan.business.logs.entities.LowMediumHighEnum; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.users.entities.User; +import org.libreplan.web.common.BaseCRUDController; +import org.libreplan.web.common.Util; +import org.libreplan.web.common.components.bandboxsearch.BandboxSearch; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.WrongValueException; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zul.*; +import org.zkoss.zk.ui.Executions; + +import javax.swing.*; + +/** + * Controller for IssueLog CRUD actions + * + * @author Misha Gozhda + */ +@SuppressWarnings("serial") +@org.springframework.stereotype.Component +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class IssueLogCRUDController extends BaseCRUDController { + + private static final org.apache.commons.logging.Log LOG = LogFactory + .getLog(IssueLogCRUDController.class); + + @Autowired + private IIssueLogModel issueLogModel; + + private BandboxSearch bdProjectIssueLog; + + private BandboxSearch bdUserIssueLog; + + @Override + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + comp.setVariable("issueLogController", this, true); + showListWindow(); + initializeOrderComponent(); + initializeUserComponent(); + + } + + /** + * Initializes order component + */ + private void initializeOrderComponent() { + bdProjectIssueLog = (BandboxSearch) editWindow + .getFellow("bdProjectIssueLog"); + Util.createBindingsFor(bdProjectIssueLog); + bdProjectIssueLog.setListboxEventListener(Events.ON_SELECT, + new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdProjectIssueLog + .getSelectedElement(); + issueLogModel.setOrder((Order) object); + } + }); + bdProjectIssueLog.setListboxEventListener(Events.ON_OK, + new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdProjectIssueLog + .getSelectedElement(); + issueLogModel.setOrder((Order) object); + bdProjectIssueLog.close(); + } + }); + } + + /** + * Initializes user component + */ + private void initializeUserComponent() { + bdUserIssueLog = (BandboxSearch) editWindow.getFellow("bdUserIssueLog"); + Util.createBindingsFor(bdUserIssueLog); + + bdUserIssueLog.setListboxEventListener(Events.ON_SELECT, new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdUserIssueLog.getSelectedElement(); + issueLogModel.setCreatedBy((User) object); + } + }); + bdUserIssueLog.setListboxEventListener(Events.ON_OK, new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdUserIssueLog.getSelectedElement(); + issueLogModel.setCreatedBy((User) object); + bdUserIssueLog.close(); + } + }); + } + + /** + * Enumerations rendering + */ + public static ListitemRenderer issueTypeRenderer = new ListitemRenderer() { + @Override + public void render(org.zkoss.zul.Listitem item, Object data) + throws Exception { + IssueTypeEnum issueTypeEnum = (IssueTypeEnum) data; + String displayName = issueTypeEnum.getDisplayName(); + item.setLabel(displayName); + } + }; + public static ListitemRenderer issueStatusRenderer = new ListitemRenderer() { + @Override + public void render(org.zkoss.zul.Listitem item, Object data) + throws Exception { + IssueStatusEnum issueStatusEnum = (IssueStatusEnum) data; + String displayName = issueStatusEnum.getDisplayName(); + item.setLabel(displayName); + } + }; + + public static ListitemRenderer lowMediumHighEnumRenderer = new ListitemRenderer() { + @Override + public void render(org.zkoss.zul.Listitem item, Object data) + throws Exception { + LowMediumHighEnum lowMediumHighEnum = (LowMediumHighEnum) data; + String displayName = lowMediumHighEnum.getDisplayName(); + item.setLabel(displayName); + } + }; + + /** + * Renders issue logs + * + * @return {@link RowRenderer} + */ + public RowRenderer getIssueLogsRowRenderer() { + return new RowRenderer() { + + @Override + public void render(Row row, Object data) throws Exception { + final IssueLog issueLog = (IssueLog) data; + row.setValue(issueLog); + appendObject(row, issueLog.getCode()); + appendLabel(row, issueLog.getOrder().getName()); + appendObject(row, issueLog.getType()); + appendObject(row, issueLog.getStatus()); + appendLabel(row, issueLog.getDescription()); + appendObject(row, issueLog.getPriority()); + appendObject(row, issueLog.getSeverity()); + appendDate(row, issueLog.getDateRaised()); + appendLabel(row, issueLog.getCreatedBy().getLoginName()); + appendLabel(row, issueLog.getAssignedTo()); + appendDate(row, issueLog.getDeadline()); + appendDate(row, issueLog.getDateResolved()); + appendLabel(row, issueLog.getNotes()); + appendOperations(row, issueLog); + } + }; + } + + /** + * Appends the specified object to the specified + * row + * + * @param row + * @param object + */ + private void appendObject(final Row row, Object object) { + String text = new String(""); + if (object != null) { + text = object.toString(); + } + appendLabel(row, text); + } + + /** + * Creates {@link Label} bases on the specified value and + * appends to the specified row + * + * @param row + * @param value + */ + private void appendLabel(final Row row, String value) { + Label label = new Label(value); + row.appendChild(label); + } + + /** + * Appends the specified date to the specified row + * @param row + * @param date*/ + private void appendDate(final Row row, Date date) { + String labelDate = new String(""); + if (date != null) { + labelDate = Util.formatDate(date); + } + appendLabel(row, labelDate); + } + + /** + * Appends operation(edit and remove) to the specified row + * + * @param row + * @param issueLog + */ + private void appendOperations(final Row row, final IssueLog issueLog) { + Hbox hbox = new Hbox(); + hbox.appendChild(Util.createEditButton(new EventListener() { + @Override + public void onEvent(Event event) { + goToEditForm(issueLog); + } + })); + hbox.appendChild(Util.createRemoveButton(new EventListener() { + @Override + public void onEvent(Event event) { + confirmDelete(issueLog); + } + })); + row.appendChild(hbox); + } + + /** + * Returns {@link LowMediumHighEnum} values + */ + public LowMediumHighEnum[] getLowMediumHighEnum() { + return LowMediumHighEnum.values(); + } + + /** + * Returns {@link IssueTypeEnum} values + */ + public IssueTypeEnum[] getIssueTypeEnum() { + return IssueTypeEnum.values(); + } + + /** + * Returns {@link IssueStatusEnum} values + */ + public IssueStatusEnum[] getIssueStatusEnum() { + return IssueStatusEnum.values(); + } + + /** + * Returns a list of {@link Order} objects + */ + public List getOrders() { + return issueLogModel.getOrders(); + } + + + /** + * Returns a list of {@link User} objects + */ + public List getUsers() { + return issueLogModel.getUsers(); + } + + /** + * Returns date entered + */ + public Date getDateRaised() { + if (issueLogModel.getIssueLog() == null) { + return null; + } + return (issueLogModel.getIssueLog().getDateRaised() != null) ? issueLogModel + .getIssueLog().getDateRaised() + : null; + } + + /** + * Sets the date entered + * + * @param date + * date eneted + */ + public void setDateRaised(Date date) { + issueLogModel.getIssueLog().setDateRaised(date); + } + + /** + * Returns date resolved + */ + public Date getDateResolved() { + if (issueLogModel.getIssueLog() == null) { + return null; + } + return (issueLogModel.getIssueLog().getDateResolved() != null) ? issueLogModel + .getIssueLog().getDateResolved() + : null; + } + /** + * Sets the date resolved + * + * @param date + * the date resolved + */ + public void setDateResolved(Date date) { + issueLogModel.getIssueLog().setDateResolved(date); + } + + public Date getDeadline() { + if (issueLogModel.getIssueLog() == null) { + return null; + } + return (issueLogModel.getIssueLog().getDeadline() != null) ? issueLogModel + .getIssueLog().getDeadline() // this is a getIntegrationEntityDAO method + : null; + } + + public void setDeadline(Date date) { + issueLogModel.getIssueLog().setDeadline(date); + } + + /** + * Returns the {@link IssueLog} object + */ + public IssueLog getIssueLog() { + return issueLogModel.getIssueLog(); + } + + /** + * Returns a list of {@link IssueLog} objects + */ + public List getIssueLogs() { + if (LogsController.getProjectNameVisibility() == true) + return issueLogModel.getIssueLogs(); + else{ + List issueLogs = new ArrayList(); + Order order = LogsController.getOrder(); + for (IssueLog issueLog : issueLogModel.getIssueLogs()) { + if (issueLog.getOrder().equals(order)) + issueLogs.add(issueLog); + } + return issueLogs; + } + } + + @Override + protected String getEntityType() { + return _("issuelog-number"); + } + + @Override + protected String getPluralEntityType() { + return _("Issue logs"); + } + + @Override + protected void initCreate() { + issueLogModel.initCreate(); + } + + @Override + protected void initEdit(IssueLog entity) { + issueLogModel.initEdit(entity); + } + + @Override + protected void save() throws ValidationException { + if (getIssueLog().getOrder() == null) { + throw new WrongValueException(bdProjectIssueLog, + _("please select a project")); + } + + if (getIssueLog().getCreatedBy() == null) { + throw new WrongValueException(bdUserIssueLog, + _("please select an author")); + } + issueLogModel.confirmSave(); + } + + @Override + protected IssueLog getEntityBeingEdited() { + return issueLogModel.getIssueLog(); + } + + @Override + protected void delete(IssueLog entity) throws InstanceNotFoundException { + issueLogModel.remove(entity); + } + + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogModel.java new file mode 100644 index 000000000..d23bceae3 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/IssueLogModel.java @@ -0,0 +1,183 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.libreplan.business.common.IntegrationEntity; +import org.libreplan.business.common.daos.IConfigurationDAO; +import org.libreplan.business.common.entities.EntityNameEnum; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.common.exceptions.ValidationException; +import org.libreplan.business.logs.daos.IIssueLogDAO; +import org.libreplan.business.logs.daos.IProjectLogDAO; +import org.libreplan.business.logs.entities.IssueLog; +import org.libreplan.business.orders.daos.IOrderDAO; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.scenarios.IScenarioManager; +import org.libreplan.business.users.daos.IUserDAO; +import org.libreplan.business.users.entities.User; +import org.libreplan.web.common.IntegrationEntityModel; +import org.libreplan.web.common.concurrentdetection.OnConcurrentModification; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Model for UI operations related to {@link IssueLog} + * + * @author Miciele Ghiorghis + */ +@Service +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +@OnConcurrentModification(goToPage = "/logs/_logs.zul") +public class IssueLogModel extends IntegrationEntityModel implements + IIssueLogModel { + + private IssueLog issueLog; + + @Autowired + private IIssueLogDAO issueLogDAO; + + @Autowired + private IProjectLogDAO projectLogDAO; + + @Autowired + private IUserDAO userDAO; + + @Autowired + private IOrderDAO orderDAO; + + @Autowired + private IScenarioManager scenarioManager; + + @Autowired + private IConfigurationDAO configurationDAO; + + @Override + @Transactional(readOnly = true) + public List getIssueLogs() { + return projectLogDAO.getIssueLogs(); + } + + @Override + @Transactional(readOnly = true) + public List getOrders() { + return orderDAO.getOrders(); + } + + @Override + @Transactional(readOnly = true) + public List getUsers() { + List users = new ArrayList(); + users.addAll(userDAO.findAll()); + return users; + } + + @Override + @Transactional(readOnly = true) + public void initCreate() { + boolean codeGenerated = configurationDAO.getConfiguration() + .getGenerateCodeForProjectLog(); + this.issueLog = IssueLog.create(); + if (codeGenerated) { + issueLog.setCodeAutogenerated(codeGenerated); + setDefaultCode(); + } + } + + @Override + public void initEdit(IssueLog issueLog) { + this.issueLog = issueLog; + } + + @Override + public IssueLog getIssueLog() { + return this.issueLog; + } + + @Override + @Transactional + public void confirmSave() throws ValidationException { + issueLogDAO.save(issueLog); + } + + @Override + public void cancel() { + issueLog = null; + } + + @Override + @Transactional + public void remove(IssueLog issueLog) { + try { + issueLogDAO.remove(issueLog.getId()); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public EntityNameEnum getEntityName() { + return EntityNameEnum.ISSUE_LOG; + } + + @Override + public IntegrationEntity getCurrentEntity() { + return this.issueLog; + } + + @Override + protected Set getChildren() { + return new HashSet(); + } + + @Override + public Order getOrder() { + return issueLog.getOrder(); + } + + @Override + public void setOrder(Order order) { + if (this.issueLog != null) { + IssueLog issueLog = getIssueLog(); + issueLog.setOrder(order); + } + } + + @Override + public User getCreatedBy() { + return issueLog.getCreatedBy(); + } + + @Override + public void setCreatedBy(User user) { + if (this.issueLog != null) { + IssueLog issueLog = getIssueLog(); + issueLog.setCreatedBy(user); + } + } + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/LogsController.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/LogsController.java new file mode 100644 index 000000000..9d5483194 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/LogsController.java @@ -0,0 +1,119 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import java.util.HashMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.web.common.Util; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.util.GenericForwardComposer; +import org.zkoss.zul.api.Hbox; +import org.zkoss.zul.api.Window; + +/** + * Controller for Logs(issue and risk logs) + * + * @author Misha Gozhda + */ +@org.springframework.stereotype.Component +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class LogsController extends GenericForwardComposer { + + private static final Log LOG = LogFactory.getLog(LogsController.class); + + private Window issueLogWindow; + private Window riskLogWindow; + private Window logWindow; + + private Hbox logsFilter; + + private IssueLogCRUDController issueLogController; + private RiskLogCRUDController riskLogController; + private static boolean projectNameVisibility = true; + private static Order order = null; + + @Override + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + comp.setVariable("logsController", this, true); + Component filterComponent = Executions.createComponents( + "/logs/_logsFilter.zul", logsFilter, + new HashMap()); + filterComponent.setVariable("logsFilterController", this, true); + logsFilter.setVisible(true); + logWindow = (Window) comp.getFellowIfAny("logWindow"); + Util.createBindingsFor(logWindow); + setupIssueLogController(); + } + + public void onApplyFilter() { + } + + public void setupIssueLogController() { + issueLogWindow = (Window) self.getFellowIfAny("issueLogWindow"); + + if (issueLogController == null) { + issueLogController = new IssueLogCRUDController(); + } + try { + issueLogController.doAfterCompose(issueLogWindow); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public void setupRiskLogController() { + riskLogWindow = (Window) self.getFellowIfAny("riskLogWindow"); + + if (riskLogController == null) { + riskLogController = new RiskLogCRUDController(); + } + try { + riskLogController.doAfterCompose(riskLogWindow); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void goToOrderMode(Order order) { + LogsController.projectNameVisibility =false; + LogsController.order = order; + } + + public static void goToGlobalMode(){ + projectNameVisibility = true; + order = null; + } + + public static boolean getProjectNameVisibility() { + return projectNameVisibility; + } + + public static Order getOrder() { + return order; + } +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogCRUDController.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogCRUDController.java new file mode 100644 index 000000000..62cf1050d --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogCRUDController.java @@ -0,0 +1,366 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import static org.libreplan.web.I18nHelper._; + +import java.util.Date; +import java.util.List; + +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.common.exceptions.ValidationException; +import org.libreplan.business.logs.entities.LowMediumHighEnum; +import org.libreplan.business.logs.entities.RiskLog; +import org.libreplan.business.logs.entities.RiskScoreStatesEnum; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.users.entities.User; +import org.libreplan.web.common.BaseCRUDController; +import org.libreplan.web.common.Util; +import org.libreplan.web.common.components.bandboxsearch.BandboxSearch; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.WrongValueException; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zul.*; + +/** + * Controller for RiskLog CRUD actions + * + * @author Misha Gozhda + */ +@SuppressWarnings("serial") +@org.springframework.stereotype.Component +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class RiskLogCRUDController extends BaseCRUDController { + + private static final org.apache.commons.logging.Log LOG = LogFactory + .getLog(RiskLogCRUDController.class); + + @Autowired + private IRiskLogModel riskLogModel; + + private BandboxSearch bdProjectRiskLog; + + private BandboxSearch bdUserRiskLog; + + @Override + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + comp.setVariable("riskLogController", this, true); + showListWindow(); + initializeOrderComponent(); + initializeUserComponent(); + } + + /** + * Initializes order component + */ + private void initializeOrderComponent() { + bdProjectRiskLog = (BandboxSearch) editWindow + .getFellow("bdProjectRiskLog"); + Util.createBindingsFor(bdProjectRiskLog); + bdProjectRiskLog.setListboxEventListener(Events.ON_SELECT, + new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdProjectRiskLog.getSelectedElement(); + riskLogModel.setOrder((Order) object); + } + }); + bdProjectRiskLog.setListboxEventListener(Events.ON_OK, new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdProjectRiskLog.getSelectedElement(); + riskLogModel.setOrder((Order) object); + bdProjectRiskLog.close(); + } + }); + } + + /** + * Initializes user component + */ + private void initializeUserComponent() { + bdUserRiskLog = (BandboxSearch) editWindow.getFellow("bdUserRiskLog"); + Util.createBindingsFor(bdUserRiskLog); + bdUserRiskLog.setListboxEventListener(Events.ON_SELECT, + new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdUserRiskLog + .getSelectedElement(); + riskLogModel.setCreatedBy((User) object); + } + }); + bdUserRiskLog.setListboxEventListener(Events.ON_OK, + new EventListener() { + @Override + public void onEvent(Event event) { + final Object object = bdUserRiskLog + .getSelectedElement(); + riskLogModel.setCreatedBy((User) object); + bdUserRiskLog.close(); + } + }); + } + + /** + * Renders risk logs + * + * @return {@link RowRenderer} + */ + public RowRenderer getRiskLogsRowRenderer() { + return new RowRenderer() { + + @Override + public void render(Row row, Object data) throws Exception { + final RiskLog riskLog = (RiskLog) data; + row.setValue(riskLog); + appendObject(row, riskLog.getCode()); + appendLabel(row, riskLog.getOrder().getName()); + appendObject(row, riskLog.getProbability()); + appendObject(row, riskLog.getImpact()); + appendObject(row, riskLog.getRiskScore()); + appendLabel(row, riskLog.getStatus()); + appendLabel(row, riskLog.getDescription()); + appendDate(row, riskLog.getDateCreated()); + appendLabel(row, riskLog.getCreatedBy().getFullName() + riskLog.getCreatedBy().getLoginName()); + appendLabel(row, riskLog.getCounterMeasures()); + appendLabel(row, "4"); + appendLabel(row, riskLog.getContingency()); + appendLabel(row, riskLog.getResponsible()); + appendDate(row, riskLog.getActionWhen()); + appendLabel(row, riskLog.getNotes()); + appendOperations(row, riskLog); + } + }; + } + + public static ListitemRenderer lowMediumHighEnumRenderer = new ListitemRenderer() { + @Override + public void render(org.zkoss.zul.Listitem item, Object data) + throws Exception { + LowMediumHighEnum lowMediumHighEnum = (LowMediumHighEnum) data; + String displayName = lowMediumHighEnum.getDisplayName(); + item.setLabel(displayName); + } + }; + public static ListitemRenderer riskScoreStatesEnumRenderer = new ListitemRenderer() { + @Override + public void render(org.zkoss.zul.Listitem item, Object data) + throws Exception { + RiskScoreStatesEnum riskScoreStatesEnum = (RiskScoreStatesEnum) data; + String displayName = riskScoreStatesEnum.getDisplayName(); + item.setLabel(displayName); + } + }; + + /** + * Appends the specified object to the specified + * row + * + * @param row + * @param object + */ + private void appendObject(final Row row, Object object) { + String text = new String(""); + if (object != null) { + text = object.toString(); + } + appendLabel(row, text); + } + + /** + * Creates {@link Label} bases on the specified value and + * appends to the specified row + * + * @param row + * @param value + */ + private void appendLabel(final Row row, String value) { + Label label = new Label(value); + row.appendChild(label); + } + + /** + * Appends the specified date to the specified row + * + * @param row + * @param date + */ + private void appendDate(final Row row, Date date) { + String labelDate = new String(""); + if (date != null) { + labelDate = Util.formatDate(date); + } + appendLabel(row, labelDate); + } + + /** + * Appends operation(edit and remove) to the specified row + * + * @param row + * @param riskLog + */ + private void appendOperations(final Row row, final RiskLog riskLog) { + Hbox hbox = new Hbox(); + hbox.appendChild(Util.createEditButton(new EventListener() { + @Override + public void onEvent(Event event) { + goToEditForm(riskLog); + } + })); + hbox.appendChild(Util.createRemoveButton(new EventListener() { + @Override + public void onEvent(Event event) { + confirmDelete(riskLog); + } + })); + row.appendChild(hbox); + } + + /** + * Returns {@link LowMediumHighEnum} values + */ + public LowMediumHighEnum[] getLowMediumHighEnums() { + return LowMediumHighEnum.values(); + } + /** + * Returns {@link org.libreplan.business.logs.entities.RiskScoreStatesEnum} values + */ + public RiskScoreStatesEnum[] getRiskScoreStatesEnums() { + return RiskScoreStatesEnum.values(); + } + + /** + * Returns a list of {@link Order} objects + */ + public List getOrders() { + return riskLogModel.getOrders(); + } + + /** + * Returns a list of {@link User} objects + */ + public List getUsers() { + return riskLogModel.getUsers(); + } + + /** + * Returns registration date + */ + public Date getDateCreated() { + if (riskLogModel.getRiskLog() == null) { + return null; + } + return (riskLogModel.getRiskLog().getDateCreated() != null) ? riskLogModel + .getRiskLog().getDateCreated() + : null; + } + + /** + * Sets the registration date + * + * @param date + * registration date + */ + public void setDateCreated(Date date) { + riskLogModel.getRiskLog().setDateCreated(date); + } + + public void setActionWhen(Date date) { + riskLogModel.getRiskLog().setActionWhen(date); + } + + public Date getActionWhen() { + if (riskLogModel.getRiskLog() == null) { + return null; + } + return (riskLogModel.getRiskLog().getActionWhen() != null) ? riskLogModel + .getRiskLog().getActionWhen() + : null; + } + + /** + * Returns the {@link RiskLog} object + */ + public RiskLog getRiskLog() { + return riskLogModel.getRiskLog(); + } + + /** + * Returns a list of {@link RiskLog} objects + */ + public List getRiskLogs() { + return riskLogModel.getRiskLogs(); + } + + @Override + protected String getEntityType() { + return _("Issue log"); + } + + @Override + protected String getPluralEntityType() { + return _("Issue logs"); + } + + @Override + protected void initCreate() { + riskLogModel.initCreate(); + } + + @Override + protected void initEdit(RiskLog entity) { + riskLogModel.initEdit(entity); + } + + @Override + protected void save() throws ValidationException { + if (getRiskLog().getOrder() == null) { + throw new WrongValueException(bdProjectRiskLog, + _("please select a project")); + } + + if (getRiskLog().getCreatedBy() == null) { + throw new WrongValueException(bdUserRiskLog, + _("please select an author")); + } + + riskLogModel.confirmSave(); + } + + @Override + protected RiskLog getEntityBeingEdited() { + return riskLogModel.getRiskLog(); + } + + @Override + protected void delete(RiskLog entity) throws InstanceNotFoundException { + riskLogModel.remove(entity); + + } + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogModel.java new file mode 100644 index 000000000..c18ce3bb5 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/logs/RiskLogModel.java @@ -0,0 +1,183 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.logs; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.libreplan.business.common.IntegrationEntity; +import org.libreplan.business.common.daos.IConfigurationDAO; +import org.libreplan.business.common.entities.EntityNameEnum; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.common.exceptions.ValidationException; +import org.libreplan.business.logs.daos.IProjectLogDAO; +import org.libreplan.business.logs.daos.IRiskLogDAO; +import org.libreplan.business.logs.entities.RiskLog; +import org.libreplan.business.orders.daos.IOrderDAO; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.scenarios.IScenarioManager; +import org.libreplan.business.users.daos.IUserDAO; +import org.libreplan.business.users.entities.User; +import org.libreplan.web.common.IntegrationEntityModel; +import org.libreplan.web.common.concurrentdetection.OnConcurrentModification; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Model for UI operations related to {@link RiskLog} + * + * @author Miciele Ghiorghis + */ +@Service +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +@OnConcurrentModification(goToPage = "/logs/_logs.zul") +public class RiskLogModel extends IntegrationEntityModel implements + IRiskLogModel { + + private RiskLog riskLog; + + @Autowired + private IRiskLogDAO riskLogDAO; + + @Autowired + private IProjectLogDAO projectLogDAO; + + @Autowired + private IUserDAO userDAO; + + @Autowired + private IOrderDAO orderDAO; + + @Autowired + private IScenarioManager scenarioManager; + + @Autowired + private IConfigurationDAO configurationDAO; + + @Override + @Transactional(readOnly = true) + public List getRiskLogs() { + return projectLogDAO.getRiskLogs(); + } + + @Override + @Transactional(readOnly = true) + public List getOrders() { + return orderDAO.getOrders(); + } + + @Override + @Transactional(readOnly = true) + public List getUsers() { + List users = new ArrayList(); + users.addAll(userDAO.findAll()); + return users; + } + + @Override + @Transactional(readOnly = true) + public void initCreate() { + boolean codeGenerated = configurationDAO.getConfiguration() + .getGenerateCodeForProjectLog(); + this.riskLog = RiskLog.create(); + if (codeGenerated) { + riskLog.setCodeAutogenerated(codeGenerated); + setDefaultCode(); + } + } + + @Override + public void initEdit(RiskLog riskLog) { + this.riskLog = riskLog; + } + + @Override + public RiskLog getRiskLog() { + return this.riskLog; + } + + @Override + @Transactional + public void confirmSave() throws ValidationException { + riskLogDAO.save(riskLog); + } + + @Override + public void cancel() { + riskLog = null; + } + + @Override + @Transactional + public void remove(RiskLog riskLog) { + try { + riskLogDAO.remove(riskLog.getId()); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public EntityNameEnum getEntityName() { + return EntityNameEnum.RISK_LOG; + } + + @Override + public IntegrationEntity getCurrentEntity() { + return this.riskLog; + } + + @Override + protected Set getChildren() { + return new HashSet(); + } + + @Override + public Order getOrder() { + return riskLog.getOrder(); + } + + @Override + public void setOrder(Order order) { + if (this.riskLog != null) { + RiskLog riskLog = getRiskLog(); + riskLog.setOrder(order); + } + } + + @Override + public User getCreatedBy() { + return riskLog.getCreatedBy(); + } + + @Override + public void setCreatedBy(User user) { + if (this.riskLog != null) { + RiskLog riskLog = getRiskLog(); + riskLog.setCreatedBy(user); + } + } + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/LogsTabCreator.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/LogsTabCreator.java new file mode 100644 index 000000000..58ef47721 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/LogsTabCreator.java @@ -0,0 +1,160 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.libreplan.web.planner.tabs; + +import static org.libreplan.web.I18nHelper._; +import static org.libreplan.web.planner.tabs.MultipleTabsPlannerController.BREADCRUMBS_SEPARATOR; +import static org.libreplan.web.planner.tabs.MultipleTabsPlannerController.getSchedulingLabel; + +import java.util.HashMap; +import java.util.Map; + +import org.libreplan.business.users.entities.UserRole; +import org.libreplan.web.common.Util; +import org.libreplan.web.logs.LogsController; +import org.libreplan.web.planner.order.IOrderPlanningGate; +import org.libreplan.web.planner.tabs.CreatedOnDemandTab.IComponentCreator; +import org.libreplan.web.security.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.zkoss.ganttz.extensions.ITab; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zul.Image; +import org.zkoss.zul.Label; + +import javax.swing.*; + +/** + * Creates global Tab for Logs(issue and risk logs) + * + * @author Misha Gozhda + */ +public class LogsTabCreator { + + public static ITab create(Mode mode, LogsController logsController, LogsController logsControllerGlobal, + Component breadcrumbs, IOrderPlanningGate orderPlanningGate, + Map parameters) { + return new LogsTabCreator(mode, logsController, logsControllerGlobal, breadcrumbs, + orderPlanningGate, parameters) + .build(); + } + + private final Mode mode; + + private final LogsController logsControllerGlobal; + + private final LogsController logsController; + + private final Component breadcrumbs; + + private final IOrderPlanningGate orderPlanningGate; + + private LogsTabCreator(Mode mode, LogsController logsController, LogsController logsControllerGlobal, + Component breadcrumbs, IOrderPlanningGate orderPlanningGate, + Map parameters) { + this.mode = mode; + this.logsController = logsController; + this.logsControllerGlobal = logsControllerGlobal; + this.breadcrumbs = breadcrumbs; + this.orderPlanningGate = orderPlanningGate; + } + + private ITab build() { + return TabOnModeType.forMode(mode) + .forType(ModeType.GLOBAL, createGlobalLogsTab()) + .forType(ModeType.ORDER, createOrderLogsTab()) + .create(); + } + + + private ITab createGlobalLogsTab() { + IComponentCreator componentCreator = new IComponentCreator() { + + @Override + public org.zkoss.zk.ui.Component create( + org.zkoss.zk.ui.Component parent) { + Map arguments = new HashMap(); + arguments.put("logsController", logsControllerGlobal); + return Executions.createComponents("/logs/_logs.zul", + parent, arguments); + } + + }; + return new CreatedOnDemandTab(_("Logs"), "logs-global", + componentCreator) { + @Override + protected void beforeShowAction() { + if (!SecurityUtils + .isSuperuserOrUserInRoles(UserRole.ROLE_PLANNING)) { + Util.sendForbiddenStatusCodeInHttpServletResponse(); + } + } + + @Override + protected void afterShowAction() { + if (breadcrumbs.getChildren() != null) { + breadcrumbs.getChildren().clear(); + } + breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR)); + breadcrumbs.appendChild(new Label(getSchedulingLabel())); + breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR)); + breadcrumbs.appendChild(new Label(_("Logs"))); + } + }; + } + + private ITab createOrderLogsTab() { + IComponentCreator componentCreator = new IComponentCreator() { + + @Override + public org.zkoss.zk.ui.Component create( + org.zkoss.zk.ui.Component parent) { + Map arguments = new HashMap(); + arguments.put("logsController", logsController); + return Executions.createComponents("/logs/_logs.zul", + parent, arguments); + } + + }; + return new CreatedOnDemandTab(_("Logs"), "logs-order", + componentCreator) { + @Override + protected void beforeShowAction() { + if (!SecurityUtils + .isSuperuserOrUserInRoles(UserRole.ROLE_PLANNING)) { + Util.sendForbiddenStatusCodeInHttpServletResponse(); + } + } + + @Override + protected void afterShowAction() { + if (breadcrumbs.getChildren() != null) { + breadcrumbs.getChildren().clear(); + } + breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR)); + breadcrumbs.appendChild(new Label(getSchedulingLabel())); + breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR)); + breadcrumbs.appendChild(new Label(_("Logs"))); + breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR)); + breadcrumbs.appendChild(new Label(mode.getOrder().getName())); + } + }; + } + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java index 7b5db901a..de295afd9 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java @@ -42,6 +42,7 @@ import org.libreplan.web.common.entrypoints.URLHandlerRegistry; import org.libreplan.web.dashboard.DashboardController; import org.libreplan.web.dashboard.DashboardControllerGlobal; import org.libreplan.web.limitingresources.LimitingResourcesController; +import org.libreplan.web.logs.LogsController; import org.libreplan.web.montecarlo.MonteCarloController; import org.libreplan.web.orders.OrderCRUDController; import org.libreplan.web.planner.allocation.AdvancedAllocationController.IBack; @@ -75,6 +76,8 @@ import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.util.Composer; +import javax.swing.*; + /** * Creates and handles several tabs * @@ -83,7 +86,8 @@ import org.zkoss.zk.ui.util.Composer; */ @Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) -public class MultipleTabsPlannerController implements Composer, +public class + MultipleTabsPlannerController implements Composer, IGlobalViewEntryPoints { public static String WELCOME_URL = "-- no URL provided --"; @@ -164,6 +168,8 @@ public class MultipleTabsPlannerController implements Composer, private ITab dashboardTab; + private ITab logsTab; + private TabSwitcher tabsSwitcher; @Autowired @@ -190,6 +196,12 @@ public class MultipleTabsPlannerController implements Composer, @Autowired private DashboardControllerGlobal dashboardControllerGlobal; + @Autowired + private LogsController logsController; + + @Autowired + private LogsController logsControllerGlobal; + private org.zkoss.zk.ui.Component breadcrumbs; @Autowired @@ -254,7 +266,7 @@ public class MultipleTabsPlannerController implements Composer, @Override public void goToTaskResourceAllocation(Order order, - TaskElement task) { + TaskElement task) { orderPlanningController.setShowedTask(task); orderPlanningController.setCurrentControllerToShow(orderPlanningController.getEditTaskController()); getTabsRegistry() @@ -303,6 +315,32 @@ public class MultipleTabsPlannerController implements Composer, dashboardController, dashboardControllerGlobal, orderPlanningController, breadcrumbs, resourcesSearcher); + logsTab = LogsTabCreator.create(mode, logsController, logsControllerGlobal, breadcrumbs, new IOrderPlanningGate() { + + @Override + public void goToScheduleOf(Order order) { + getTabsRegistry() + .show(planningTab, changeModeTo(order)); + } + + @Override + public void goToOrderDetails(Order order) { + getTabsRegistry().show(ordersTab, changeModeTo(order)); + } + + @Override + public void goToTaskResourceAllocation(Order order, + TaskElement task) { + // do nothing + } + + @Override + public void goToDashboard(Order order) { + // do nothing + } + + }, parameters); + final boolean isMontecarloVisible = isMonteCarloVisible(); if (isMontecarloVisible) { monteCarloTab = MonteCarloTabCreator.create(mode, @@ -334,6 +372,8 @@ public class MultipleTabsPlannerController implements Composer, tabsConfiguration.add(visibleOnlyAtOrderMode(monteCarloTab)); } + tabsConfiguration.add(tabWithNameReloading(logsTab, typeChanged)); + return tabsConfiguration; } @@ -467,6 +507,7 @@ public class MultipleTabsPlannerController implements Composer, @Override public void goToCompanyScheduling() { + LogsController.goToGlobalMode(); getTabsRegistry().show(planningTab); } @@ -541,6 +582,7 @@ public class MultipleTabsPlannerController implements Composer, } private IBeforeShowAction changeModeTo(final Order order) { + logsController.goToOrderMode(order); return new IBeforeShowAction() { @Override public void doAction() { diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/users/services/CustomTargetUrlResolver.java b/libreplan-webapp/src/main/java/org/libreplan/web/users/services/CustomTargetUrlResolver.java new file mode 100644 index 000000000..6174f5900 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/users/services/CustomTargetUrlResolver.java @@ -0,0 +1,119 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2012 Igalia, S.L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + *//* + + +package org.libreplan.web.users.services; + +import javax.servlet.http.HttpServletRequest; + +import org.libreplan.business.common.IAdHocTransactionService; +import org.libreplan.business.common.IOnTransaction; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.users.daos.IOrderAuthorizationDAO; +import org.libreplan.business.users.daos.IUserDAO; +import org.libreplan.business.users.entities.User; +import org.libreplan.business.users.entities.UserRole; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.Authentication; +import org.springframework.security.ui.TargetUrlResolverImpl; +import org.springframework.security.ui.savedrequest.SavedRequest; +import org.springframework.security.userdetails.UserDetails; + +*/ +/** + * Determines the URL for authenticated users depending on if user is bound or + * not to any resource.
+ * + * If the user is bound to a resource then the target URL will be the user + * dashboard. + * + * @author Manuel Rego Casasnovas + *//* + +public class CustomTargetUrlResolver extends TargetUrlResolverImpl { + + public final static String USER_DASHBOARD_URL = "/myaccount/userDashboard.zul"; + + public static final String PLANNING_URL = "/planner/index.zul"; + + public static final String SETTINGS_URL = "/myaccount/settings.zul"; + + @Autowired + private IUserDAO userDAO; + + @Autowired + private IOrderAuthorizationDAO orderAuthorizationDAO; + + @Autowired + private IAdHocTransactionService transactionServiceDAO; + + @Override + public String determineTargetUrl(SavedRequest savedRequest, + HttpServletRequest currentRequest, final Authentication auth) { + if (isUserInRole(auth, UserRole.ROLE_SUPERUSER.name())) { + return super.determineTargetUrl(savedRequest, currentRequest, auth); + } + + if (isUserInRole(auth, UserRole.ROLE_BOUND_USER.name())) { + return USER_DASHBOARD_URL; + } + + if (isUserInRole(auth, UserRole.ROLE_PLANNING.name())) { + return PLANNING_URL; + } + + boolean userOrItsProfilesHaveAnyAuthorization = transactionServiceDAO + .runOnReadOnlyTransaction(new IOnTransaction() { + @Override + public Boolean execute() { + try { + UserDetails userDetails = (UserDetails) auth.getPrincipal(); + User user = userDAO.findByLoginName(userDetails.getUsername()); + user.getProfiles().size(); + return orderAuthorizationDAO + .userOrItsProfilesHaveAnyAuthorization(user); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + + } + }); + if (userOrItsProfilesHaveAnyAuthorization) { + return PLANNING_URL; + } + + return SETTINGS_URL; + } + + private boolean isUserInRole(Authentication auth, String role) { + if ((auth == null) || (auth.getPrincipal() == null) + || (auth.getAuthorities() == null)) { + return false; + } + + for (int i = 0; i < auth.getAuthorities().length; i++) { + if (role.equals(auth.getAuthorities()[i].getAuthority())) { + return true; + } + } + + return false; + } +} +*/ diff --git a/libreplan-webapp/src/main/webapp/common/css/libreplan_zk.css b/libreplan-webapp/src/main/webapp/common/css/libreplan_zk.css index 838b699f6..1354fa15a 100644 --- a/libreplan-webapp/src/main/webapp/common/css/libreplan_zk.css +++ b/libreplan-webapp/src/main/webapp/common/css/libreplan_zk.css @@ -1077,6 +1077,19 @@ span.perspective, span.perspective-active { margin-top: 5px; } +.perspective.logs-global .z-button-cm { + background-image: url(../img/ico_logs-global.png); +} +.perspective-active.logs-global .z-button-cm { + background-image: url(../img/ico_logs-global.png); +} + +.perspective.logs-order .z-button-cm { + background-image: url(../img/ico_logs-order.png); +} +.perspective-active.logs-order .z-button-cm { + background-image: url(../img/ico_logs-order.png); +} .perspectives-column { display:none; diff --git a/libreplan-webapp/src/main/webapp/common/img/cabecera.jpg b/libreplan-webapp/src/main/webapp/common/img/cabecera.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94ea1aa32eb53cc4002960dcc2e18eae2e853ba4 GIT binary patch literal 4808 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 LdLt>PiLw6!F-x2a literal 0 HcmV?d00001 diff --git a/libreplan-webapp/src/main/webapp/common/img/ico_logs-global.png b/libreplan-webapp/src/main/webapp/common/img/ico_logs-global.png new file mode 100644 index 0000000000000000000000000000000000000000..90cdafaa4cc40a5b884564af29ad744c0b2a68d8 GIT binary patch literal 2781 zcmV<33L^E1P)myxuQG_bW7R3jxeW)@1K|*axsE<&C zA)+QWMvO5g4K|HtQ&S5OF*Q+3(*`ISEn4XMz=BA?<*_V}S$1}Ic4zM6{QAc{cJ9pX z>@KWnJjqSwp1t?n@9%ehkMHkyR_#0-6TZbG05JcudR#p|3mOPpUi&j=ySfO4!ziV2 zU6+%`I+%a$Lhil$r}U50w>~-Aoe`iX1)d&Nsp1C#MYy5@?Rlha7sqjlMnZ@vwAQ$eQ~F+R{XihENY8bL zSl>T7x(6~l5Us8#>jS0%z3~Jmk9QCXg^5(x5Q$de4fBrHHp&1I7p+~CVIdj}6M|-7 z*!9nReF|k51cN~uXEx$`<+bnFc1D1+N$|>;kZCGnJt?}n`++1C@f3}-X5ctd#+np% zTH`tzuOD<7A2UrwcRWp3Pd|yCI5qY4L@uH1`aTo-&g42oWCZh87>2_0G$MlII3qsq zI1WzQ#tH??qYwe5FiaEAbpVyMp7JJi`g~tz2WCgrhz}PAN&wsTM)7QrzC;?wNubKv za}KP|FQ4_N^5b+a3VoA90AXkanWl+pnkDnD>y9!i$~P~-P@p}}qti7w(QmLfp@?DP zqOe?HnyI-uVlu^oOG27pAb{(-<@3O}X*->!r?nM#-#)^tRuOse#S*{R6;rG`S4VG` zg-RE`tnyYPBAFZ#(mXl0m!C8Up63nk#5c^SVXUdew(XL+-la=%Km0I%AAR>-?3NY) ze)GP|KZDgI`zydHFn;a#WdK74e+xpbrDvH&6`lb zvc_&MMPavR@#2!e(lPUU+__!hMZy?f1$h48lGk|F+x<(bTm%3CjpA4Tp3L?oXP6NU zWWO(iLF-~hYV&3&$_o~-^5MVW0cL$IxD?oUHuUE-t_!tJW@ie(7c$+IA5>u(Mp00| zh@le+5-V5wwI2?%>Av4`a==1@A!I;hw>=9yYv*~b%ODx_0hg>7h@eDJXu8s2{(4N0 zUldBNU0cFP8{%=cZQPI29!6C(3tFKHcc3utcb_A@|3jqbG-fbNXu)k5)%6+RSYK0Kvxm;4!zm*Io{O?VD4j72DW(r7>LtmR zTY6dVPGsj7pvA-c@5e+IEX$`qDcmN}?2nsh?GBodWmy+=4HTJ7 z5kU&P`+|KS@z6tl+IIWxP+QB^ty{VL_-UHvG~-n_viqam9Q2|j921m*QU-<l*2@s!!z?8CKGB} z3jMl7^SRKpXo{PMKISkg$t0AZs6ZfJf#H zFn40;!V;OiYZq>NyN~NfUwSEjKb!zcDXN}%#-FJ-|A~da?;zIaVn!l_<}CtykY6aD z<}=^AGMZx5T+bKw$0R`SJ@@z>ckyC^%a#p-D&kbNwYB-*l@C9RIcHA(qd!=?i_?7? zqcTG1%Im?C!GKf5wKOmT8Z{P0AxBxXfb_~Crfq)NmC=@Df2Wk_gEKmVN8QIj7#jY~^Q$!Il zT>|DPyVFBv+*FF*<;(pKH#cK7H4VF%>$-GycGA?;#P;pmOTwz_y1ewGsr>z5FGqSj z4uAF$wWp3y7e7m-mm=Kp6;&J7Qy&d6dx8msM{IDZorhzx|-yLl%!> zZQod=2!NMA?gnk6oD|A287jRh1sgw)jA%k7PAnqCTU-54ghB*YtQb|c4uwK=bac?x z*2WcAT)~0`3yR&G9y@>-28cuU6r{9K1h@{QJqVd&5MbchXZ`&hrKtbni_%`cNG3B& zVGl49v!~S7vVQGa#Pg73645&UjJ7PMhthl%HxSeEt*HtqgouE6sBK%}?w^lN03C~w zT)(~qY;5-Ip{ezSbf$p^Tkc?W%NmSOB{7Gf0QE+e;fIl;00000NkvXXu0mjf|I;(5 literal 0 HcmV?d00001 diff --git a/libreplan-webapp/src/main/webapp/common/img/ico_logs-order.png b/libreplan-webapp/src/main/webapp/common/img/ico_logs-order.png new file mode 100644 index 0000000000000000000000000000000000000000..8c5a475b6246f6857717a8678cf149dfd6101266 GIT binary patch literal 3228 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 O0000aHI+0-NobTxrFvs*6`Il_OAQGvYAgw< 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 literal 0 HcmV?d00001 diff --git a/libreplan-webapp/src/main/webapp/common/img/logo2.gif b/libreplan-webapp/src/main/webapp/common/img/logo2.gif new file mode 100644 index 0000000000000000000000000000000000000000..79b37add3a11ed384cf375dd5b123c88cade94aa GIT binary patch literal 7248 zcmXAMdo+~$_y7BO=9&9EV+Oga8TXtpt_i0zxusH#E>hHINbWL(IF)AHBN|hd#%0pe(kmQTKl!u>yN#5ou}ifz;@saz5@Uv z8WtAj@7=riV)Dz>)RbrGo&uhA*%d7{ZkKZbyZ@v5Wb8gr5?)k+Zm!FPKOn-Yk`e9-5I}o(gz538R{Bdz% zeuL;=gX7H+H+#yvMs-sDS(4szpy6$B&8z3{6+t(;cT_zY`!aK&@zs|fb8W+l^aq0= zv1xdCcy4Z1{^fgGtBi2??)3CD!oPRu&e)G1Kg{x4S*JT+D`r4)(~-vEAB*#!=6-0T z{d1;6UMhWCS64T`uyEtXjW2UE-@kufTv#0Z_zfif6MsvtRL*Lrw+bH)J)QU}`#e2A zKNovz1jOCv)eoSDn#}Va8|6Q~EBoks^#zE%&AHs2ba&$W&w0ILEx(`Z=>PcbK;y)f z?r{)%Cq&#czc@QLzhHf`RVB44p?;LOzX2rNIU;%UXTvB+ZTYddAQ_sxH894j9|eac z-+ufgCESAq?errL>iQ-Z7v^?X5AbgF&MwTq{y4Qq+;`|sFGy+oF+V%^bKbG=$@6zp zL06xCnfn=AD|fvptsav6OTIgHsBv^=aY6BY7VN)M&^C@segN~E58itR zr%Lp5+x@Rdd*4rE4@+K6egj9FlJ2}6`0%Ch;aj_+4v_jlsZ?6!KRnp*_Q9Lan4|4b zY72(nHaIzz-}VklYyP|U-S>srgAHTYghu|o5oTs9lK2l2_s`^q$v_+|0 z{Lg+ZQZ6VL|G)pL7ycjgb5Z##`9=S)*24TR^uPZ6FK9veb6)uiRn9Le=atI2#l^(N zfuBErzWy++lG4%N-+!=PjuEtylOGV18_iEVz0s>^d_Df;-RG63n*FN#X-SRDj3>g* z(TmTdW2<}BoYK79Mb$c~FUb6Eyjs87y ztmev-bB-%r(`Jrq-zwfxT<{p`9EuSZV2rXB}DdaEV*@I zZFFqSj9SU9uori%Uo{q9dv%+~^lZ6e;18BO6}ei>uF$QG?5nd@WZH)fwq(<7|IOT} zdpop;Gizpq%QH$oxs-TSiluK`(p~ZTHO{tXqI=cF-)ns>D(Ht|e3$#gg*Cxu4apzR z`DElf)V#dE+xaKu*3`(7V*8O~w4%W95O3L~itHb`n%B7hi0oQ(_2MvR1EaaIUnZKiRLEa$z)*CpDvNo$DaeHqzu^3NmfP5I7o z4V}zAj)AG{@tUyUAgQpG;?l;R%5_Rrgq3GIy`SBX;#N^0U|Z==T=usvc30Kn(r#vI zI(KOeTQYjX49)cKluM4&CD$JlBj;wi4Eqhj|k%?`Rgl#kV!e;oZ~QysRuD-is<**S>Tsh?il}!~*<8+#yq20{c}*|1rLfDcH`}7SUE#f>PYc<&irpIcul=A` z?FR=EQofGW=V*vo`R=jEwe#&`E*r4JhFuMD@dr???kWzdIVfUbjVN9PS!6Sj3|;w> z+nwjI$riY?4qpo{957>~dg<*xq}FA>#m;u4@qWWD2a9;=QyscpwhByLg}%}a=G&}Wekz^`Q)$-6zk16prfGl7R|_$2dYxQ8NzBTQV5L!A z%_Qct;uEU~a^lr&UK}U@KFw4+Q;j$z7ZWgcG5ui-x=0>^f)vbP>t_Eb8hMW=IfvSf_Kt|l+ z)dIo`Acy)XiYj2J*=VIxqL|0F01;lu&r}cK=8X{`U@LJAAK#Z7ErUSI*{r4CvQ<_x z$0h5n8U6t>L-WQZ5=PY8Jk@ zgvR)}Q4S`xyv;$B7b9Jo$uZm(XXHmdrA|(%1et8EINx3z2%PzksEGjMqO}+LEy>eP zT}IKZXhLK7O{RRFio-Nm7A^rDFANHd&S!0}7h;;4?i9o*i8j}5%MKk2CFMDwfKWO7lvBl!Wytk3$ih7az&r=fuM@9{FzLk zSuMe=>~GR|BlghK^T}D}Z3ue%A8xrAc*2<%6w7dD8<@oMw|KL4yZFaRXPK$C_nOXN zp~ntOv6Z?ew5(I=k2DGykF;k3;f>16 zMr)|hI$Meejv0qA6J8$b?sCZXw2XMYHnY1rFx6xQ&~P0U8n|j?l2~f0X{;QqJ1?~= z$3XpvBEv*P*Gc8L5gzh@>3RWf1*O|GsljdM>vGut10VNp7Qq2wDwk&ndaC%pl}J*f zxMjLFTu(heACmR97HmDk16mZ4)k3M&-2DNVz^Jl0!`Kj zik8-h2CdHDUOc7hT-ro56rRxxmF-OWT_wH5F9vl@&FfnqeEUvwI+D&57^l0!OC9%V zUVt1Tc`X_iel4_!De|_e^1{G&w!MUr7UEujt?hSb7)gUwR+K4KOt?E7a*%9W?_vF1 zZkB6SR>thpBK!KPX8o7aJSaVoertENN|-!@8+YqZgpAw13ojB^E`BMf#yh0>%q# zL=TK;TMD6pD8ZN-p%23ubFlQ5Yo9X1nk0C(*tSDJ?`w&!lQ71szKKHalu={yFe;g| z6pUnTeKZ%>?X)~~%L}#&cMbyWK4_@=40=O(29|p6ejj!|_~tq_D3Apx)=+OGc^aNwle3`|#!179>HFmw0j0s9&C!E)p=_JK zc<=?XJb$H>hhKZvO`~BMn=BO{XKrH{v-}XM7fUdV2~v&m!sz|Mq?1Atp?UjY%8~$&}_NbaSszU(LdY3XfzP zQ%hNhftVGgz#m{Gzn1JcC0a&(jCuiqF4r_yI9d`UnwgXaELf1 z>PlABOt25wW6X1oPsAC~RG+b6B`fK+A88*p-xpxB_=uN;`hk!9#UmURLp>ZSb|80+ zgyJbC1#-6IB$Tsa6*o{|b_~gqk+w_oXOSRmf%+Rh?lOb8RY5dVDv00tgt!WID+qH8 zK&wn>B@)b00Bz6U-n~gU%)$i)lB=z=Y&fX11fMJ3w2zAp5$I!bjIk6yTc4F!d17b` zGUdR3Gt_#Tb!@oNjBO`OX(XgQB)$)378Wg**F=SRS39LK8Asq`<$&zB21zcBg(1~LBix75UlQ|Ni8NhY2B5JD~ zFl8EV*gNfosWa*PbzR2ntGLY!4HCeuVBs&b$^R5{FY<_?(vuX)3aJR)!dR=Nz;6;o z_5&-mSb8varSb*Y*3G-0r{OV%xlb!LH%23ynZ0;x+u;o!`LpV=q&&0<}pBu_h3F7fUQJ8_i-*ifdoF-0wALR`no4XI1#FETz`lX9ijsntl zF~*aPpJCw-@-gSdHpdds0Zy*(S~TM;@^V!`RAzOnJ>UKe##o&BQc9Ronqd57@DK}5 z?7z8jtadK!pn!(m3(%>Ps>mY@S4uE;rtxLi{S2g&1GVszPZt>(Uq?G7IF5w6L`JD# zl22_5fA*DP!p745jNV8+VC z8pu%=3o+35LGS^d?qN3eFbg3AlCA{hip)d^{RMZaq2kQ$9Yy1g&{D8JjEEay5qdeR zx3*v@jOr^2!ql;tp}7l*jlr$L!j&(G(J~jJuX(2g4im!1X=tJp7sMe3k5K-VQ*Z#c ziv`7S@q@FJSPquT2iNCrHwxiDqz4dX89EY7?9T-rY=Vo7;KU%F6yJAZsJPN7ym}#oH%7^fk5a3;2h%H%~!rnB{fqfF!=d=d63ERa% zU3zSAXiHZ8k})ktN8l1nA;i6#zQOz_Y{~ ztIJod=8{6BO>=~OoI>g+Y5trpn#>_)4c1`_I!~K-LJaJt6&AY&Q5^^BYnDUMfd|+0 z9AP_@q_~Ytp%54NNeSi*$6eu9>kT?JDquOsW{Bl5#4;~1j*hl7+bnoKs;og}eAMUE zsvefZa|MbI042Hn+Hu3H=5Lr@!Y-DBG1YKtXN1OhhQV<9-Jm#kt9H~ zyYIZbu$P@oDp&s>-4fSC`K`>nL(tomx+Kg)t@evr`bo`W`|5D=y=Zw`m8#nLw`zZW zp_sw42_At63 zcRwXd$oDwg;NnDE|32`!Ci$$8>g}8PCSfZ> zk7~{Z#FL3R{AKIeyT2Eq0ivxv68H)a7D(G2_KExe6;lQfr39(xAnSw(kux+Z0z@|A z%|VDfhzMYRF}7Ze9g8NfW3BRFy!pC&2w|%|5h5Ne+S~JBos@z|-oQ1#z5ys8Rz~C? zN`2X=5Rva5lD($1vk`yA8`(zS&Zj)#P!XXF%176MArFQe5dqT+vQfrRy=3@Q8hry4 z@l4_WKOt%KHuBH|Hz>j8b=y1{#pZ~}9U|&A1q^Ohb_lQ}$?qCmQqEw=5eCdwQ2cnR ziwi(SjMWzceHx4^03w1=8ievGC=bh2K_zpq>qO zupzh%=yTuEl{|>fA7k<$gg-{-Q`gbp+#zV40xaW_HKl;W8;cvFj5FTR0j$D<+8JZf zo4`&mt^&qK8NcSq%S2E;8`;SQxo}M~TAEI~c%23X1n2un^m>fJzqutW-cm8vF!|ov;M$Vk|6r z(|n)iTBd%^fTkviJMnP(p@)It}{v7YN)uc`Bb$uoQOZlHc!tm$wvR zGC=vz_^-?KS;Nbuka-N5yXiZ|=esQW4Jv}@Y`HgUEFfi$f8mRY6w={S88jHP8R+vV zIzpf>g&^f5w8vbPK5bHC(aRsuamR^1q69T`^*4NnSl`8FTL+)yajWvC0VZ*Z!ZLER zL-O-1)L_A9rWEp!efO3i>lBc`62M3Ilc`FuxM}jip6^8$uyy;%0hW_=HnM~9RbNV3 zvKb7&UL2>v>v(f={Rw?QV?^0Y72y006@9aK$rV1FK|rGD%r7#xbfli`&hBHZ%U+=w zwd5H8xT{9I`d@YpUzlsssfd9@U2!wpqI6Zlr?-z!?X>gnyS7u@-BIYUyqi}N275fW zT4PnQX_T?Oz{!}?9L$}mesv4fAMa=Go!n^`;{0!HuxcQ4Z9Ky%K8eOWc7sYR31^#r zZ5lMvuQz(!1uAindc2vdyKEDQQlyKzp1 z%P#K)cZlZw$3S+u{Y>9A^~3N8l9_RCT!P$ zb0j9m?!xn;><|J6G+|DeDN;k&4a-|B#7r)^RNYHjXklpx^bN$}V=!rTL!<|3`pf4u z{91!lm}Y=HuRz3sa5}KLx1seM0nl{)J0STZqn!5Vf6)BwI8NpVBOVrppRM^@H%h1M zVWC#4ldHa3xkh5xeL6@JF`!Y^b!Y+w$Ah%Nj4; zF=u=S!qs5^bmO&VnTU$tSmzL zT{FAF&)ur)+H~=9{HvIA8~b;L{evEq$1Jz>3o!3KIaWN;P&G!}ltYr|~q1jpIECp4l0aV23Tfmhzl*X2EZnQeW)VSR?}cCF#CQ%~)-l%0DzQQ~=) ziA8saWJ-@SyPghu2&)`L6{EY~FN|imX@rdsLxN@f;q|W)e?~WqT(Qx`sB`4nUQzvf zAu}_&`<_#m-|OsHBjTsx=ys4s)veLQ`Pg>Dqy8l!b;X_^Lk|Na6`QG*s_GFT2Zg%= z1*1YH^=L4ttteprn_^saB=KeF0~?)iUZx5EXM0t%V0)M2=yB#fv!SzgKZ@6+`}U5V z3OFBGl=A2M^YtnR&fm;2ilToz)M7Pv26=S91eYV9RIOSX*v^u6Q4^`fJTbAlfy zwIfn4x#&hF<^NG~t7kdr6MOFZa%#m7V~*gI;o=Fk0GrBEz;q{-J6OdZ3YGYEvDka#fQCoc|AP CVp$~s literal 0 HcmV?d00001 diff --git a/libreplan-webapp/src/main/webapp/logs/_editIssueLog.zul b/libreplan-webapp/src/main/webapp/logs/_editIssueLog.zul new file mode 100644 index 000000000..a30f87db5 --- /dev/null +++ b/libreplan-webapp/src/main/webapp/logs/_editIssueLog.zul @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +