From ba8024aae761b2cbdd3acf725462e845a536b7c5 Mon Sep 17 00:00:00 2001 From: miciele Ghiorghis Date: Thu, 21 Mar 2013 15:23:13 +0100 Subject: [PATCH] jira and tim-connector: new job for Jira order element synchronizer and some improvement - New Job implementation for Jira order element synchronizer - Some imporvements to manage/display errors --- .../common/entities/JobClassNameEnum.java | 7 +- .../importers/ExportTimesheetToTimJob.java | 10 +- .../importers/ExportTimesheetsToTim.java | 18 ++- .../importers/IExportTimesheetsToTim.java | 15 ++- .../importers/IImportRosterFromTim.java | 6 +- .../IJiraOrderElementSynchronizer.java | 14 ++ .../importers/ImportRosterFromTim.java | 13 +- .../importers/ImportRosterFromTimJob.java | 9 +- .../JiraOrderElementSynchronizer.java | 126 ++++++++++++++++-- .../JiraOrderElementSynchronizerJob.java | 63 +++++++++ .../web/common/IJobSchedulerModel.java | 4 +- .../web/common/JobSchedulerController.java | 60 +++++++-- .../web/common/JobSchedulerModel.java | 23 +++- .../webapp/orders/_synchronizationInfo.zul | 26 ++++ 14 files changed, 343 insertions(+), 51 deletions(-) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizerJob.java create mode 100644 libreplan-webapp/src/main/webapp/orders/_synchronizationInfo.zul diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobClassNameEnum.java b/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobClassNameEnum.java index a7f2f3a77..038d7c413 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobClassNameEnum.java +++ b/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobClassNameEnum.java @@ -28,10 +28,9 @@ package org.libreplan.business.common.entities; */ public enum JobClassNameEnum { - IMPORT_ROSTER_FROM_TIM_JOB("org.libreplan.importers", - "ImportRosterFromTimJob"), EXPORT_TIMESHEET_TO_TIM_JOB( - "org.libreplan.importers", - "ExportTimesheetToTimJob"); + IMPORT_ROSTER_FROM_TIM_JOB("org.libreplan.importers", "ImportRosterFromTimJob"), + EXPORT_TIMESHEET_TO_TIM_JOB("org.libreplan.importers","ExportTimesheetToTimJob"), + SYNC_ORDERELEMENTS_WITH_JIRA_ISSUES_JOB("org.libreplan.importers","JiraOrderElementSynchronizerJob"); private String packageName; private String name; diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java index 5c8575edc..b5add4f97 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java @@ -19,6 +19,8 @@ package org.libreplan.importers; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.libreplan.business.common.entities.ConnectorException; @@ -46,10 +48,12 @@ public class ExportTimesheetToTimJob extends QuartzJobBean { .getBean("exportTimesheetsToTim"); try { - exportTimesheetsToTim.exportTimesheets(); + List syncInfos = exportTimesheetsToTim + .exportTimesheets(); + LOG.info("Export scuccessful: " - + exportTimesheetsToTim.getSynchronizationInfo() - .isSuccessful()); + + (syncInfos == null || syncInfos.isEmpty())); + } catch (ConnectorException e) { LOG.error("Export timesheet to Tim failed", e); } diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java index fd86d9052..695c58092 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java @@ -86,7 +86,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim { @Override @Transactional(readOnly = true) - public void exportTimesheets() throws ConnectorException { + public List exportTimesheets() throws ConnectorException { Connector connector = getTimConnector(); if (connector == null) { throw new ConnectorException(_("Tim connector not found")); @@ -98,18 +98,25 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim { synchronizationInfo = new SynchronizationInfo(_("Export")); + List syncInfos = new ArrayList(); + List orderSyncInfos = orderSyncInfoDAO.findByConnectorId(PredefinedConnectors.TIM.getName()); if (orderSyncInfos == null || orderSyncInfos.isEmpty()) { LOG.warn("No items found in 'OrderSyncInfo' to export to Tim"); synchronizationInfo.addFailedReason(_("No items found in 'OrderSyncInfo' to export to Tim")); - return; + syncInfos.add(synchronizationInfo); + return syncInfos; } for (OrderSyncInfo orderSyncInfo : orderSyncInfos) { LOG.info("Exporting '" + orderSyncInfo.getOrder().getName() + "'"); exportTimesheets(orderSyncInfo.getKey(), orderSyncInfo.getOrder(), connector); + if (!synchronizationInfo.isSuccessful()) { + syncInfos.add(synchronizationInfo); + } } + return syncInfos; } @Override @@ -133,8 +140,6 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim { _("Connection values of Tim connector are invalid")); } - synchronizationInfo = new SynchronizationInfo(_("Export")); - exportTimesheets(productCode, order, connector); } @@ -152,6 +157,11 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim { */ private void exportTimesheets(String productCode, Order order, Connector connector) { + + synchronizationInfo = new SynchronizationInfo(_( + "Export product code {0}, project {1}", productCode, + order.getName())); + Map properties = connector.getPropertiesAsMap(); String url = properties.get(PredefinedConnectorProperties.SERVER_URL); diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java index 75730a689..15945e12d 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java @@ -19,6 +19,8 @@ package org.libreplan.importers; +import java.util.List; + import org.libreplan.business.common.entities.Connector; import org.libreplan.business.common.entities.ConnectorException; import org.libreplan.business.orders.entities.Order; @@ -50,14 +52,19 @@ public interface IExportTimesheetsToTim { void exportTimesheets(String productCode, Order order) throws ConnectorException; /** - * Loops through all existing {@link Order}s and searches for last - * synchronized order. if found, start exporting the time sheets of that - * order to Tim SOAP server. if not found write info to the log file. + * Exporting the time sheets to Tim SOAP server, if they are already + * exported using + * {@link IExportTimesheetsToTim#exportTimesheets(String, Order)}. + * + * It gets then an already exported time sheets from {@link OrderSyncInfo} + * and re-exporting them. + * + * @return a list of {@link SynchronizationInfo} * * @throws ConnectorException * if connector is not valid */ - void exportTimesheets() throws ConnectorException; + List exportTimesheets() throws ConnectorException; /** * Gets the most recent synchronized time sheet info diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java index 2d421e38e..82aabbf69 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java @@ -19,6 +19,8 @@ package org.libreplan.importers; +import java.util.List; + import org.libreplan.business.calendars.entities.CalendarException; import org.libreplan.business.common.entities.Connector; import org.libreplan.business.common.entities.ConnectorException; @@ -40,10 +42,12 @@ public interface IImportRosterFromTim { * If worker calendar exception already exists it will be removed and added * new one, in other cases a new calendar exception will be created * + * @return a list of {@link SynchronizationInfo} + * * @throws ConnectorException * if connector is not valid */ - void importRosters() throws ConnectorException; + List importRosters() throws ConnectorException; /** * Returns synchronization info, success of fail info diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/IJiraOrderElementSynchronizer.java b/libreplan-webapp/src/main/java/org/libreplan/importers/IJiraOrderElementSynchronizer.java index 2fbdff736..04a7b5711 100755 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/IJiraOrderElementSynchronizer.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/IJiraOrderElementSynchronizer.java @@ -112,4 +112,18 @@ public interface IJiraOrderElementSynchronizer { */ SynchronizationInfo getSynchronizationInfo(); + /** + * Synchronize order elements with JIRA issues if they already synchronized + * using + * {@link IJiraOrderElementSynchronizer#syncOrderElementsWithJiraIssues(List, Order) + * + * It gets then an already synchronized orders from the + * {@link OrderSyncInfo} and re-synchronize them + * + * @return a list of {@link SynchronizationInfo} + * + * @throws ConnectorException + * if connector not found or contains invalid connection values + */ + List syncOrderElementsWithJiraIssues() throws ConnectorException; } diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java index b44bb0f45..54987566e 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java @@ -117,7 +117,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim { @Override @Transactional - public void importRosters() throws ConnectorException { + public List importRosters() throws ConnectorException { Connector connector = connectorDAO .findUniqueByName(PredefinedConnectors.TIM.getName()); if (connector == null) { @@ -156,10 +156,14 @@ public class ImportRosterFromTim implements IImportRosterFromTim { String[] departmentIdsArray = StringUtils.stripAll(StringUtils.split( departmentIds, ",")); - synchronizationInfo = new SynchronizationInfo(_("Import")); + List syncInfos = new ArrayList(); for (String department : departmentIdsArray) { LOG.info("Department: " + department); + + synchronizationInfo = new SynchronizationInfo(_( + "Import roster for department {0}", department)); + RosterRequestDTO rosterRequestDTO = createRosterRequest(department, nrDaysRosterFromTim); RosterResponseDTO rosterResponseDTO = TimSoapClient @@ -169,13 +173,18 @@ public class ImportRosterFromTim implements IImportRosterFromTim { if (rosterResponseDTO != null) { updateWorkersCalendarException(rosterResponseDTO, productivityFactor); + if (!synchronizationInfo.isSuccessful()) { + syncInfos.add(synchronizationInfo); + } } else { LOG.error("No valid response for department " + department); synchronizationInfo.addFailedReason(_( "No valid response for department \"{0}\"", department)); + syncInfos.add(synchronizationInfo); } } + return syncInfos; } /** diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java index 22e0a2dc3..b4e928eaa 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java @@ -19,6 +19,8 @@ package org.libreplan.importers; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.libreplan.business.common.entities.ConnectorException; @@ -51,9 +53,12 @@ public class ImportRosterFromTimJob extends QuartzJobBean { .getBean("importRosterFromTim"); try { - importRosterFromTim.importRosters(); + List syncInfos = importRosterFromTim + .importRosters(); + LOG.info("Import scuccessful: " - + importRosterFromTim.getSynchronizationInfo().isSuccessful()); + + (syncInfos == null || syncInfos.isEmpty())); + } catch (ConnectorException e) { LOG.error("Import roster from Tim failed", e); } diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizer.java b/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizer.java index 3575f9691..e1ad94ba8 100755 --- a/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizer.java +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizer.java @@ -33,6 +33,8 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.joda.time.LocalDate; import org.libreplan.business.advance.bootstrap.PredefinedAdvancedTypes; import org.libreplan.business.advance.entities.AdvanceMeasurement; @@ -40,6 +42,8 @@ import org.libreplan.business.advance.entities.AdvanceType; import org.libreplan.business.advance.entities.DirectAdvanceAssignment; import org.libreplan.business.advance.exceptions.DuplicateAdvanceAssignmentForOrderElementException; import org.libreplan.business.advance.exceptions.DuplicateValueTrueReportGlobalAdvanceException; +import org.libreplan.business.common.IAdHocTransactionService; +import org.libreplan.business.common.IOnTransaction; import org.libreplan.business.common.daos.IConnectorDAO; import org.libreplan.business.common.entities.Connector; import org.libreplan.business.common.entities.ConnectorException; @@ -57,6 +61,7 @@ import org.libreplan.importers.jira.StatusDTO; import org.libreplan.importers.jira.TimeTrackingDTO; import org.libreplan.importers.jira.WorkLogDTO; import org.libreplan.importers.jira.WorkLogItemDTO; +import org.libreplan.web.orders.IOrderModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; @@ -72,13 +77,25 @@ import org.springframework.transaction.annotation.Transactional; @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchronizer { + private static final Log LOG = LogFactory + .getLog(JiraOrderElementSynchronizer.class); + private SynchronizationInfo synchronizationInfo; @Autowired private IConnectorDAO connectorDAO; @Autowired - IOrderSyncInfoDAO orderSyncInfoDAO; + private IOrderSyncInfoDAO orderSyncInfoDAO; + + @Autowired + private IAdHocTransactionService adHocTransactionService; + + @Autowired + private IOrderModel orderModel; + + @Autowired + private IJiraTimesheetSynchronizer jiraTimesheetSynchronizer; @Override @Transactional(readOnly = true) @@ -115,6 +132,19 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz _("Connection values of JIRA connector are invalid")); } + return getJiraIssues(label, connector); + } + + /** + * Gets all jira issues for the specified label + * + * @param label + * the search criteria + * @param connector + * where to read the configuration parameters + * @return a list of {@link IssueDTO} + */ + private List getJiraIssues(String label, Connector connector) { Map properties = connector.getPropertiesAsMap(); String url = properties.get(PredefinedConnectorProperties.SERVER_URL); @@ -137,7 +167,8 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz @Transactional(readOnly = true) public void syncOrderElementsWithJiraIssues(List issues, Order order) { - synchronizationInfo = new SynchronizationInfo(_("Synchronization")); + synchronizationInfo = new SynchronizationInfo(_( + "Synchronization order {0}", order.getName())); for (IssueDTO issue : issues) { String code = PredefinedConnectorProperties.JIRA_CODE_PREFIX @@ -440,18 +471,26 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz @Override @Transactional - public void saveSyncInfo(String key, Order order) { - OrderSyncInfo orderSyncInfo = orderSyncInfoDAO - .findByKeyOrderAndConnectorId(key, order, - PredefinedConnectors.JIRA.getName()); - if (orderSyncInfo == null) { - orderSyncInfo = OrderSyncInfo.create(key, order, - PredefinedConnectors.JIRA.getName()); - } - orderSyncInfo.setLastSyncDate(new Date()); - orderSyncInfoDAO.save(orderSyncInfo); + public void saveSyncInfo(final String key, final Order order) { + adHocTransactionService + .runOnAnotherTransaction(new IOnTransaction() { + @Override + public Void execute() { + OrderSyncInfo orderSyncInfo = orderSyncInfoDAO + .findByKeyOrderAndConnectorId(key, order, + PredefinedConnectors.JIRA.getName()); + if (orderSyncInfo == null) { + orderSyncInfo = OrderSyncInfo.create(key, order, + PredefinedConnectors.JIRA.getName()); + } + orderSyncInfo.setLastSyncDate(new Date()); + orderSyncInfoDAO.save(orderSyncInfo); + return null; + } + }); } + @Override @Transactional(readOnly = true) public OrderSyncInfo getOrderLastSyncInfo(Order order) { @@ -460,4 +499,67 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz } + @Override + @Transactional + public List syncOrderElementsWithJiraIssues() throws ConnectorException { + Connector connector = getJiraConnector(); + if (connector == null) { + throw new ConnectorException(_("JIRA connector not found")); + } + if (!connector.areConnectionValuesValid()) { + throw new ConnectorException( + _("Connection values of JIRA connector are invalid")); + } + + List orderSyncInfos = orderSyncInfoDAO + .findByConnectorId(PredefinedConnectors.JIRA.getName()); + + synchronizationInfo = new SynchronizationInfo(_("Synchronization")); + + List syncInfos = new ArrayList(); + + if (orderSyncInfos == null || orderSyncInfos.isEmpty()) { + LOG.warn("No items found in 'OrderSyncInfo' to synchronize with JIRA issues"); + synchronizationInfo + .addFailedReason(_("No items found in 'OrderSyncInfo' to synchronize with JIRA issues")); + syncInfos.add(synchronizationInfo); + return syncInfos; + } + + for (OrderSyncInfo orderSyncInfo : orderSyncInfos) { + Order order = orderSyncInfo.getOrder(); + LOG.info("Synchronizing '" + order.getName() + "'"); + synchronizationInfo = new SynchronizationInfo(_( + "Synchronization order {0}", order.getName())); + + List issueDTOs = getJiraIssues(orderSyncInfo.getKey(), + connector); + if (issueDTOs == null || issueDTOs.isEmpty()) { + LOG.warn("No JIRA issues found for '" + orderSyncInfo.getKey() + + "'"); + synchronizationInfo.addFailedReason(_( + "No JIRA issues found for key {0}", + orderSyncInfo.getKey())); + syncInfos.add(synchronizationInfo); + continue; + } + + orderModel.initEdit(order, null); + syncOrderElementsWithJiraIssues(issueDTOs, order); + if (!synchronizationInfo.isSuccessful()) { + syncInfos.add(synchronizationInfo); + continue; + } + orderModel.save(false); + + saveSyncInfo(orderSyncInfo.getKey(), order); + + jiraTimesheetSynchronizer.syncJiraTimesheetWithJiraIssues( + issueDTOs, order); + if (!synchronizationInfo.isSuccessful()) { + syncInfos.add(synchronizationInfo); + } + } + return syncInfos; + } } diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizerJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizerJob.java new file mode 100644 index 000000000..0b2a43520 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/JiraOrderElementSynchronizerJob.java @@ -0,0 +1,63 @@ +/* + * 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.importers; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.entities.ConnectorException; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.quartz.QuartzJobBean; + +/** + * A job that synchronizes order elements and time sheets with JIRA issues + * + * @author Miciele Ghiorghis + */ +public class JiraOrderElementSynchronizerJob extends QuartzJobBean { + + private static final Log LOG = LogFactory + .getLog(JiraOrderElementSynchronizerJob.class); + + @Override + protected void executeInternal(JobExecutionContext context) + throws JobExecutionException { + ApplicationContext applicationContext = (ApplicationContext) context + .getJobDetail().getJobDataMap().get("applicationContext"); + + IJiraOrderElementSynchronizer jiraOrderElementSynchronizer = (IJiraOrderElementSynchronizer) applicationContext + .getBean("jiraOrderElementSynchronizer"); + + try { + List syncInfos = jiraOrderElementSynchronizer + .syncOrderElementsWithJiraIssues(); + + LOG.info("Synchronization scuccessful: " + + (syncInfos == null || syncInfos.isEmpty())); + + } catch (ConnectorException e) { + LOG.error("Synchronize order elements failed", e); + } + } + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/IJobSchedulerModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/IJobSchedulerModel.java index fd7327275..c8043e533 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/common/IJobSchedulerModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/IJobSchedulerModel.java @@ -64,9 +64,9 @@ public interface IJobSchedulerModel { throws ConnectorException; /** - * Returns synchronization info. Failure or success info + * Returns synchronization infos. Failures or successes info */ - SynchronizationInfo getSynchronizationInfo(); + List getSynchronizationInfos(); /** * Prepares for create a new {@link JobSchedulerConfiguration}. diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java index 38efce86c..51145628e 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java @@ -47,12 +47,15 @@ import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zul.Button; import org.zkoss.zul.Grid; +import org.zkoss.zul.Groupbox; import org.zkoss.zul.Hbox; import org.zkoss.zul.Label; +import org.zkoss.zul.Listbox; import org.zkoss.zul.Popup; import org.zkoss.zul.Row; import org.zkoss.zul.RowRenderer; import org.zkoss.zul.SimpleListModel; +import org.zkoss.zul.api.Caption; import org.zkoss.zul.api.Textbox; import org.zkoss.zul.api.Window; @@ -184,7 +187,7 @@ public class JobSchedulerController extends public void onEvent(Event event) throws Exception { try { jobSchedulerModel.doManual(jobSchedulerConfiguration); - shwoImpExpInfo(); + shwoSynchronizationInfo(); } catch (ConnectorException e) { messagesForUser.showMessage(Level.ERROR, e.getMessage()); @@ -209,20 +212,57 @@ public class JobSchedulerController extends }; } - private void shwoImpExpInfo() { + public RowRenderer getSynchronizationInfoRenderer() { + return new RowRenderer() { + + @Override + public void render(Row row, Object data) { + final SynchronizationInfo synchronizationInfo = (SynchronizationInfo) data; + row.setValue(data); + + Groupbox groupbox = new Groupbox(); + groupbox.setClosable(true); + Caption caption = new org.zkoss.zul.Caption(); + caption.setLabel(synchronizationInfo.getAction()); + groupbox.appendChild(caption); + row.appendChild(groupbox); + + if (synchronizationInfo.isSuccessful()) { + groupbox.appendChild(new Label(_("Completed"))); + } else { + + Listbox listbox = new Listbox(); + + listbox.setModel(new SimpleListModel(synchronizationInfo + .getFailedReasons())); + groupbox.appendChild(listbox); + } + } + }; + } + + + public List getSynchronizationInfos() { + return jobSchedulerModel.getSynchronizationInfos(); + } + + + private void shwoSynchronizationInfo() { Map args = new HashMap(); - SynchronizationInfo synchronizationInfo = jobSchedulerModel.getSynchronizationInfo(); - args.put("action", synchronizationInfo.getAction()); - args.put("showSuccess", synchronizationInfo.isSuccessful()); - args.put("failedReasons", - new SimpleListModel(synchronizationInfo.getFailedReasons())); + Window win = (Window) Executions.createComponents( + "/orders/_synchronizationInfo.zul", null, args); - Window timImpExpInfoWindow = (Window) Executions.createComponents( - "/orders/_timImpExpInfo.zul", null, args); + Window syncInfoWin = (Window) win.getFellowIfAny("syncInfoWin"); + + Grid syncInfoGrid = (Grid) syncInfoWin.getFellowIfAny("syncInfoGrid"); + + syncInfoGrid.setModel(new SimpleListModel(getSynchronizationInfos())); + + syncInfoGrid.setRowRenderer(getSynchronizationInfoRenderer()); try { - timImpExpInfoWindow.doModal(); + win.doModal(); } catch (SuspendNotAllowedException e) { throw new RuntimeException(e); } catch (InterruptedException e) { diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerModel.java index 32f2536cc..5601cd3cb 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerModel.java @@ -31,6 +31,7 @@ import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.common.exceptions.ValidationException; import org.libreplan.importers.IExportTimesheetsToTim; import org.libreplan.importers.IImportRosterFromTim; +import org.libreplan.importers.IJiraOrderElementSynchronizer; import org.libreplan.importers.ISchedulerManager; import org.libreplan.importers.SynchronizationInfo; import org.libreplan.web.common.concurrentdetection.OnConcurrentModification; @@ -69,7 +70,10 @@ public class JobSchedulerModel implements IJobSchedulerModel { @Autowired private IExportTimesheetsToTim exportTimesheetsToTim; - private SynchronizationInfo synchronizationInfo; + @Autowired + private IJiraOrderElementSynchronizer jiraOrderElementSynchronizer; + + private List synchronizationInfos; @Override @Transactional(readOnly = true) @@ -88,20 +92,25 @@ public class JobSchedulerModel implements IJobSchedulerModel { throws ConnectorException { String name = jobSchedulerConfiguration.getJobClassName().getName(); if (name.equals(JobClassNameEnum.IMPORT_ROSTER_FROM_TIM_JOB.getName())) { - importRosterFromTim.importRosters(); - synchronizationInfo = importRosterFromTim.getSynchronizationInfo(); + synchronizationInfos = importRosterFromTim.importRosters(); return; } if (name.equals(JobClassNameEnum.EXPORT_TIMESHEET_TO_TIM_JOB.getName())) { - exportTimesheetsToTim.exportTimesheets(); - synchronizationInfo = exportTimesheetsToTim.getSynchronizationInfo(); + synchronizationInfos = exportTimesheetsToTim.exportTimesheets(); return; } + if (name.equals(JobClassNameEnum.SYNC_ORDERELEMENTS_WITH_JIRA_ISSUES_JOB + .getName())) { + synchronizationInfos = jiraOrderElementSynchronizer + .syncOrderElementsWithJiraIssues(); + return; + } + throw new RuntimeException("Unknown action"); } @Override - public SynchronizationInfo getSynchronizationInfo() { - return synchronizationInfo; + public List getSynchronizationInfos() { + return synchronizationInfos; } @Override diff --git a/libreplan-webapp/src/main/webapp/orders/_synchronizationInfo.zul b/libreplan-webapp/src/main/webapp/orders/_synchronizationInfo.zul new file mode 100644 index 000000000..a7a0d53d7 --- /dev/null +++ b/libreplan-webapp/src/main/webapp/orders/_synchronizationInfo.zul @@ -0,0 +1,26 @@ + + + + + +