@Override public void addCommand(FilterInteraction interaction, IUserCommand command) { if (interaction == FilterInteraction.UPDATE) { interactionMap.put(interaction, command); data.stream().forEach(this::notifyUpdateCommand); } else { interactionMap.put(interaction, command); } }
@Override public void handle(ActionEvent event) { if (event.getSource() instanceof CheckBox) { for (Entry<String, CheckBox> entry : propertiesCb.entrySet()) { CheckBox cb = entry.getValue(); String propertyName = entry.getKey(); if (cb.isSelected()) { propertiesTf.get(propertyName).setDisable(false); } else { propertiesTf.get(propertyName).setDisable(true); } } } }
/** * Sets up the remove button, which is used to remove filters from the table view and the graph. * * @param tableView The table view needed to get the currently selected filter. * @return The fully configured remove button. */ private Button setRemoveButton(TableView tableView) { final Button removeButton = new ImageButton("remove.png"); removeButton.setOnAction( actionEvent -> { final FilterInput filterInput = (FilterInput) tableView.getSelectionModel().getSelectedItem(); if (!data.isEmpty() && filterInput != null) { // Update model final IUserCommand updateGraphFilterCommand = interactionMap.get(FilterInteraction.REMOVE); if (updateGraphFilterCommand != null) { filterInput.setDeleted(); updateGraphFilterCommand.setSelection(filterInput); notifyListeners(updateGraphFilterCommand); logger.debug( "Removed FilterInput: " + filterInput.getName() + " from table view and database."); } else { logger.warn("no remove command mapped"); } } }); removeButton.setScaleX(0.5); removeButton.setScaleY(0.5); return removeButton; }
public void newFile() { infoTa.setText(""); selectProviderCb.setValue(providers.get(0).getName()); weightTf.setText("0.0"); for (Entry<String, TextField> entry : propertiesTf.entrySet()) { String propertyName = entry.getKey(); TextField tf = entry.getValue(); CheckBox cb = propertiesCb.get(propertyName); tf.setText("0.0"); tf.setDisable(true); cb.setSelected(false); } file = null; mainStage.setTitle("unknown"); }
public void notifyUpdateCommand(FilterInput filterInput) { final IUserCommand command = interactionMap.get(FilterInteraction.UPDATE); if (command != null) { logger.debug("update command of filterinput"); command.setSelection(filterInput); notifyListeners(command); } }
/** Set the Labels */ protected void setLabels() { mLabels = new HashMap<String, Label>(); mValues = new HashMap<String, Label>(); for (String name : mLabelNames) { Label newLabel1 = new Label(name); Label newLabel2 = new Label(); newLabel1.setFont(new Font("Arial", 20)); newLabel2.setFont(new Font("Arial", 20)); mLabels.put(name, newLabel1); mValues.put(name, newLabel2); } Label upgradeLabel = new Label(mUpgradeName); upgradeLabel.setFont(new Font("Arial", 25)); upgradeLabel.setWrapText(true); mLabels.put(mUpgradeName, upgradeLabel); update(); }
public void open(File f) { Properties open = new Properties(); InputStream input = null; try { input = new FileInputStream(f); open.load(input); selectProviderCb.setValue(open.getProperty("provider")); selectGrainCb.setValue(open.getProperty("grain")); weightTf.setText(open.getProperty("weight")); infoTa.setText(open.getProperty("info")); for (Entry<String, TextField> entry : propertiesTf.entrySet()) { String propertyName = entry.getKey(); TextField tf = entry.getValue(); CheckBox cb = propertiesCb.get(propertyName); tf.setText(open.getProperty(propertyName)); if (open.getProperty(propertyName + "_ENABLED").equals("ON")) { tf.setDisable(false); cb.setSelected(true); } else { tf.setDisable(true); cb.setSelected(false); } } mainStage.setTitle(f.getName()); } catch (Exception ex) { infoTa.setText("Не могу открыть файл"); } finally { if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } }
public void save(File f) { Properties save = new Properties(); OutputStream output = null; try { save.setProperty("provider", selectProviderCb.getValue()); save.setProperty("grain", selectGrainCb.getValue()); save.setProperty("weight", weightTf.getText()); save.setProperty("info", infoTa.getText()); for (Entry<String, TextField> entry : propertiesTf.entrySet()) { TextField tf = entry.getValue(); String propertyName = entry.getKey(); save.setProperty(propertyName, tf.getText()); if (tf.isDisable()) { save.setProperty(propertyName + "_ENABLED", "OFF"); } else { save.setProperty(propertyName + "_ENABLED", "ON"); } } output = new FileOutputStream(f); save.store(output, null); mainStage.setTitle(f.getName()); } catch (Exception ex) { infoTa.setText("Не могу сохранить в файл"); } finally { if (output != null) { try { output.close(); } catch (IOException e) { e.printStackTrace(); } } } }
/** Updater */ protected void update() { mValues .get("Plants in Operation") .setText("" + mModel.getEnergyManager().getFossil().getAmount()); mValues .get("Supply Provided") .setText(String.format(FORMAT, mModel.getEnergyManager().getFossil().getPower())); mValues .get("Cost") .setText(String.format(FORMAT, mModel.getEnergyManager().getFossil().getCostBuild())); mValues .get("Public Approval") .setText(String.format(FORMAT, mModel.getEnergyManager().getFossil().getApproval())); mValues .get("Emissions") .setText(String.format(FORMAT, mModel.getEnergyManager().getFossil().getEmissions())); mValues .get("Security") .setText(String.format(FORMAT, mModel.getEnergyManager().getFossil().getSecurity())); mValues .get("Profit") .setText(String.format(FORMAT, mModel.getEnergyManager().getFossil().getProfit())); }
public void HandlerCalcPriceButton(ActionEvent event) { try { grain = getGrain(selectGrainCb.getValue()); System.out.println("> " + grain.getName()); try { grain.setWeight(Double.parseDouble(weightTf.getText())); } catch (NumberFormatException e) { weightTf.requestFocus(); throw new NumberFormatException("Вес партии зерна"); } for (Entry<String, TextField> entry : propertiesTf.entrySet()) { TextField tf = entry.getValue(); String propertyName = entry.getKey(); System.out.println("\t> " + propertyName); if (!tf.isDisable()) { try { grain.getProperty(propertyName).setValue(Double.parseDouble(tf.getText())); } catch (NumberFormatException e) { tf.requestFocus(); throw new NumberFormatException(grain.getProperty(propertyName).getDescription()); } grain.getProperty(propertyName).setEnabled(true); } else { grain.getProperty(propertyName).setEnabled(false); } } System.out.println("> before calculator"); PriceCalculator calculator = new PriceCalculator(grain, dao); calculator.calculatePrice(); infoTa.setText(calculator.toString()); Supply supply = new Supply(); supply.setProvider(selectProviderCb.getValue()); supply.setDate(new Date(Calendar.getInstance().getTimeInMillis())); // supply.setGrain(grain.getName()); supply.setGrain(grain.getDescription()); supply.setWeight(grain.getWeight()); supply.setPrice(calculator.getPrice()); dao.saveSupply(supply); } catch (RestrictiveConditionException e) { Utils.showErrorDialog("Ограшичительные кондиции!", e); infoTa.clear(); } catch (DataBaseException e) { Utils.showErrorDialog("Обшибка базы данных!", e); infoTa.clear(); } catch (NumberFormatException e) { Utils.showErrorDialog("Неверный ввод!", e); infoTa.clear(); } catch (Exception ex) { Utils.showErrorDialog("Ошибка!", ex); infoTa.clear(); } }
public void initProperties(Grain g) { int currentGridRow = FIRST_PROPERTY_ROW; propertiesGp.getChildren().remove(FIRST_PROPERTY_ROW + 1, propertiesGp.getChildren().size()); propertiesCb.clear(); propertiesTf.clear(); for (Entry<String, Property> entry : g.getProperties().entrySet()) { Property property = entry.getValue(); String propertyName = entry.getKey(); propertiesCb.put(propertyName, new CheckBox(property.getDescription())); propertiesCb.get(propertyName).setOnAction(eh); GridPane.setConstraints(propertiesCb.get(propertyName), 0, currentGridRow); propertiesGp.getChildren().add(propertiesCb.get(propertyName)); propertiesTf.put(propertyName, new TextField(Double.toString(property.getValue()))); GridPane.setConstraints(propertiesTf.get(propertyName), 1, currentGridRow); propertiesGp.getChildren().add(propertiesTf.get(propertyName)); if (property.isEnabled()) { propertiesCb.get(propertyName).setSelected(true); } else { propertiesTf.get(propertyName).setDisable(true); } currentGridRow++; } }
/** Setup of the Pane */ protected void setup() { setLabels(); add(getTitleLabel(), 0, 0, 7, 1); add(mApply, 0, 3, 7, 1); add(mFossilUpgrades, 1, 12, 1, 1); add(mUp, 5, 1, 1, 1); add(mDown, 5, 2, 1, 1); add(mLabels.get("Plants in Operation"), 1, 1, 4, 2); add(mLabels.get("Supply Provided"), 1, 4, 3, 1); add(mLabels.get("Cost"), 1, 5, 3, 1); add(mLabels.get("Public Approval"), 1, 6, 3, 1); add(mLabels.get("Emissions"), 1, 8, 3, 1); add(mLabels.get("Security"), 1, 9, 3, 1); add(mLabels.get("Profit"), 1, 10, 3, 1); add(mLabels.get(mUpgradeName), 3, 12, 3, 1); add(mValues.get("Plants in Operation"), 4, 1, 1, 2); add(mValues.get("Supply Provided"), 5, 4, 1, 1); add(mValues.get("Cost"), 5, 5, 1, 1); add(mValues.get("Public Approval"), 5, 6, 1, 1); add(mValues.get("Emissions"), 5, 8, 1, 1); add(mValues.get("Security"), 5, 9, 1, 1); add(mValues.get("Profit"), 5, 10, 1, 1); }
public void addTab(Path path, Runnable... runnables) { ObservableList<String> recentFiles = controller.getRecentFilesList(); if (Files.notExists(path)) { recentFiles.remove(path.toString()); return; } ObservableList<Tab> tabs = controller.getTabPane().getTabs(); for (Tab tab : tabs) { MyTab myTab = (MyTab) tab; Path currentPath = myTab.getPath(); if (Objects.nonNull(currentPath)) if (currentPath.equals(path)) { myTab.select(); // Select already added tab return; } } AnchorPane anchorPane = new AnchorPane(); EditorPane editorPane = webviewService.createWebView(); MyTab tab = createTab(); tab.setEditorPane(editorPane); tab.setTabText(path.getFileName().toString()); editorPane.confirmHandler( param -> { if ("command:ready".equals(param)) { JSObject window = editorPane.getWindow(); window.setMember("afx", controller); window.call("updateOptions", new Object[] {}); Map<String, String> shortCuts = controller.getShortCuts(); Set<String> keySet = shortCuts.keySet(); for (String key : keySet) { window.call("addNewCommand", new Object[] {key, shortCuts.get(key)}); } if (Objects.isNull(path)) return true; threadService.runTaskLater( () -> { String content = IOHelper.readFile(path); threadService.runActionLater( () -> { window.call("changeEditorMode", path.toUri().toString()); window.call("setInitialized"); window.call("setEditorValue", new Object[] {content}); for (Runnable runnable : runnables) { runnable.run(); } }); }); } return false; }); threadService.runActionLater( () -> { TabPane tabPane = controller.getTabPane(); tabPane.getTabs().add(tab); tab.select(); }); Node editorVBox = editorService.createEditorVBox(editorPane, tab); controller.fitToParent(editorVBox); anchorPane.getChildren().add(editorVBox); tab.setContent(anchorPane); tab.setPath(path); Tooltip tip = new Tooltip(path.toString()); Tooltip.install(tab.getGraphic(), tip); recentFiles.remove(path.toString()); recentFiles.add(0, path.toString()); editorPane.focus(); }
private void updateStatisticsData(List<TaskWithWorklogs> displayResult) { if (!SettingsUtil.loadSettings().isShowStatistics()) { return; } statisticsView.getChildren().clear(); WorklogStatistics statistics = new WorklogStatistics(); // generic statistics displayResult.forEach( taskWithWorklogs -> { statistics.getTotalTimeSpent().addAndGet(taskWithWorklogs.getTotalInMinutes()); for (WorklogItem worklogItem : taskWithWorklogs.getWorklogItemList()) { String employee = worklogItem.getUserDisplayname(); // employee total time spent AtomicLong totalTimeSpent = statistics.getEmployeeToTotaltimeSpent().get(employee); if (totalTimeSpent == null) { totalTimeSpent = new AtomicLong(0); statistics.getEmployeeToTotaltimeSpent().put(employee, totalTimeSpent); } totalTimeSpent.addAndGet(worklogItem.getDurationInMinutes()); // distinct tasks per employee Set<String> totalDistinctTasks = statistics.getEmployeeToTotalDistinctTasks().get(employee); if (totalDistinctTasks == null) { totalDistinctTasks = new HashSet<>(); statistics.getEmployeeToTotalDistinctTasks().put(employee, totalDistinctTasks); } totalDistinctTasks.add(taskWithWorklogs.getIssue()); // distinct tasks per employee per project Map<String, Set<String>> projectToDistinctTasks = statistics.getEmployeeToProjectToDistinctTasks().get(employee); if (projectToDistinctTasks == null) { projectToDistinctTasks = new HashMap<>(); statistics .getEmployeeToProjectToDistinctTasks() .put(employee, projectToDistinctTasks); } Set<String> distinctTasks = projectToDistinctTasks.get(taskWithWorklogs.getProject()); if (distinctTasks == null) { distinctTasks = new HashSet<>(); projectToDistinctTasks.put(taskWithWorklogs.getProject(), distinctTasks); } distinctTasks.add(taskWithWorklogs.getIssue()); // time spent per project Map<String, AtomicLong> projectToTimespent = statistics.getEmployeeToProjectToWorktime().get(employee); if (projectToTimespent == null) { projectToTimespent = new HashMap<>(); statistics.getEmployeeToProjectToWorktime().put(employee, projectToTimespent); } AtomicLong timespentOnProject = projectToTimespent.get(taskWithWorklogs.getProject()); if (timespentOnProject == null) { timespentOnProject = new AtomicLong(0); projectToTimespent.put(taskWithWorklogs.getProject(), timespentOnProject); } timespentOnProject.addAndGet(worklogItem.getDurationInMinutes()); } }); // render grid and bar graph final AtomicInteger currentGridRow = new AtomicInteger(0); GridPane employeeProjectSummaryGrid = new GridPane(); employeeProjectSummaryGrid.setHgap(5); employeeProjectSummaryGrid.setVgap(5); NumberAxis projectEmployeeXAxis = new NumberAxis(); projectEmployeeXAxis.setLabel(FormattingUtil.getFormatted("view.statistics.timespentinhours")); projectEmployeeXAxis.setTickLabelRotation(90); NumberAxis employeeProjectXAxis = new NumberAxis(); employeeProjectXAxis.setLabel(FormattingUtil.getFormatted("view.statistics.timespentinhours")); employeeProjectXAxis.setTickLabelRotation(90); CategoryAxis projectEmployeeYAxis = new CategoryAxis(); CategoryAxis employeeProjectYAxis = new CategoryAxis(); StackedBarChart<Number, String> projectEmployeeBargraph = new StackedBarChart<>(projectEmployeeXAxis, projectEmployeeYAxis); StackedBarChart<Number, String> employeeProjectBargraph = new StackedBarChart<>(employeeProjectXAxis, employeeProjectYAxis); projectEmployeeBargraph.setTitle( FormattingUtil.getFormatted("view.statistics.byprojectandemployee")); employeeProjectBargraph.setTitle( FormattingUtil.getFormatted("view.statistics.byemployeeandproject")); Set<String> projectsToDisplay = new HashSet<>(); displayResult.forEach( taskWithWorklogs -> { projectsToDisplay.add(taskWithWorklogs.getProject()); }); int projectEmployeeBargraphPreferedHeight = HEIGHT_PER_Y_AXIS_ELEMENT * projectsToDisplay.size() + HEIGHT_PER_X_AXIS_ELEMENT * statistics.getEmployeeToTotaltimeSpent().keySet().size() + ADDITIONAL_HEIGHT; projectEmployeeBargraph.setPrefHeight(projectEmployeeBargraphPreferedHeight); VBox.setVgrow(projectEmployeeBargraph, Priority.ALWAYS); int employeeProjectBargraphPreferedHeight = HEIGHT_PER_Y_AXIS_ELEMENT * statistics.getEmployeeToProjectToWorktime().keySet().size() + HEIGHT_PER_X_AXIS_ELEMENT * projectsToDisplay.size() + ADDITIONAL_HEIGHT; employeeProjectBargraph.setPrefHeight(employeeProjectBargraphPreferedHeight); VBox.setVgrow(employeeProjectBargraph, Priority.ALWAYS); Map<String, XYChart.Series<Number, String>> projectNameToSeries = Maps.newHashMap(); statistics .getEmployeeToProjectToWorktime() .keySet() .stream() .sorted(COLLATOR::compare) .forEach( employee -> { // employee headline label Set<String> totalDistinctTasksOfEmployee = statistics.getEmployeeToTotalDistinctTasks().get(employee); Label employeeLabel = getBoldLabel( FormattingUtil.getFormatted( "view.statistics.somethingtoamountoftickets", employee, totalDistinctTasksOfEmployee.size())); employeeLabel.setPadding(new Insets(20, 0, 0, 0)); GridPane.setConstraints(employeeLabel, 0, currentGridRow.getAndIncrement()); GridPane.setColumnSpan(employeeLabel, 4); employeeProjectSummaryGrid.getChildren().addAll(employeeLabel); // bar graph data container XYChart.Series<Number, String> projectEmployeeSeries = new XYChart.Series<>(); projectEmployeeSeries.setName(employee); projectEmployeeBargraph.getData().add(projectEmployeeSeries); // time spent per project Map<String, AtomicLong> projectToWorktime = statistics.getEmployeeToProjectToWorktime().get(employee); Map<String, Label> projectToPercentageLabel = Maps.newHashMap(); projectToWorktime .keySet() .stream() .sorted(COLLATOR::compare) .forEach( projectName -> { XYChart.Series<Number, String> employeeProjectSeries = projectNameToSeries.get(projectName); if (employeeProjectSeries == null) { employeeProjectSeries = new XYChart.Series<>(); employeeProjectSeries.setName(projectName); employeeProjectBargraph.getData().add(employeeProjectSeries); projectNameToSeries.put(projectName, employeeProjectSeries); } // percentage label Label percentageLabel = getBoldLabel("PLACEHOLDER"); percentageLabel.setAlignment(Pos.CENTER_RIGHT); percentageLabel.setPadding(new Insets(0, 0, 0, 20)); GridPane.setConstraints(percentageLabel, 1, currentGridRow.get()); GridPane.setHalignment(percentageLabel, HPos.RIGHT); projectToPercentageLabel.put(projectName, percentageLabel); // project label Set<String> distinctTasksPerProject = statistics .getEmployeeToProjectToDistinctTasks() .get(employee) .get(projectName); Label projectLabel = getBoldLabel( FormattingUtil.getFormatted( "view.statistics.somethingtoamountoftickets", projectName, distinctTasksPerProject.size())); GridPane.setConstraints(projectLabel, 2, currentGridRow.get()); // time spent for project label long timespentInMinutes = projectToWorktime.get(projectName).longValue(); Label timespentLabel = new Label(FormattingUtil.formatMinutes(timespentInMinutes, true)); GridPane.setConstraints(timespentLabel, 3, currentGridRow.get()); GridPane.setHgrow(timespentLabel, Priority.ALWAYS); GridPane.setHalignment(timespentLabel, HPos.RIGHT); employeeProjectSummaryGrid .getChildren() .addAll(percentageLabel, projectLabel, timespentLabel); currentGridRow.incrementAndGet(); // bargraph data projectEmployeeSeries .getData() .add(new XYChart.Data<>(timespentInMinutes / 60d, projectName)); employeeProjectSeries .getData() .addAll(new XYChart.Data<>(timespentInMinutes / 60d, employee)); }); // total time spent Label totalLabel = getBoldLabel(FormattingUtil.getFormatted("view.statistics.totaltimespent")); GridPane.setConstraints(totalLabel, 0, currentGridRow.get()); GridPane.setColumnSpan(totalLabel, 4); Label timespentLabel = new Label( FormattingUtil.formatMinutes( statistics.getEmployeeToTotaltimeSpent().get(employee).get(), true)); GridPane.setConstraints(timespentLabel, 3, currentGridRow.get()); GridPane.setHgrow(timespentLabel, Priority.ALWAYS); GridPane.setHalignment(timespentLabel, HPos.RIGHT); employeeProjectSummaryGrid.getChildren().addAll(totalLabel, timespentLabel); // set label now that we can calculate the percentage projectToWorktime .keySet() .forEach( projectName -> { Label percentageLabel = projectToPercentageLabel.get(projectName); double totalSpentTime = statistics.getEmployeeToTotaltimeSpent().get(employee).doubleValue(); double spentTimeOnProject = projectToWorktime.get(projectName).doubleValue(); double percentage = spentTimeOnProject / totalSpentTime; String percentageFormatted = FormattingUtil.formatPercentage(percentage); percentageLabel.setText(percentageFormatted); }); currentGridRow.incrementAndGet(); }); // employeeProjectBargraph statisticsView .getChildren() .addAll(employeeProjectSummaryGrid, projectEmployeeBargraph, employeeProjectBargraph); // custom view statistics addAdditionalStatistics(statisticsView, statistics, displayResult); }
private void processWithGrouping(List<TaskWithWorklogs> tasks, DisplayData displayData) { LOGGER.debug("Processing with grouping"); List<String> distinctGroupByCriteria = tasks .stream() .map(TaskWithWorklogs::getDistinctGroupByCriteriaValues) .flatMap(Collection::stream) .distinct() .sorted(COLLATOR) .collect(Collectors.toList()); distinctGroupByCriteria.forEach( groupByCriteria -> { LOGGER.debug("Gathering data for group criteria value {}", groupByCriteria); DisplayRow groupCaptionRow = new DisplayRow(); groupCaptionRow.setIsGroupContainer(true); groupCaptionRow.setLabel(groupByCriteria); TreeItem<DisplayRow> groupRow = new TreeItem<>(groupCaptionRow); groupRow.setExpanded(true); Map<String, DisplayRow> ticketIdToDisplayRow = Maps.newHashMap(); // add sub rows to groupRow tasks .stream() .filter( taskWithWorklogs -> taskWithWorklogs.getDistinctGroupByCriteriaValues().contains(groupByCriteria)) .sorted((o1, o2) -> COLLATOR.compare(o1.getIssue(), o2.getIssue())) .forEach( taskWithWorklogs -> { // this task with worklogs contains at least one workitem // having the group by criteria DisplayRow ticketRowWithinThisGroup = ticketIdToDisplayRow.get(taskWithWorklogs.getIssue()); if (ticketRowWithinThisGroup == null) { ticketRowWithinThisGroup = new DisplayRow(); ticketRowWithinThisGroup.setLabel(taskWithWorklogs.getSummary()); ticketRowWithinThisGroup.setIssueId(taskWithWorklogs.getIssue()); ticketRowWithinThisGroup.setResolvedDate(taskWithWorklogs.getResolved()); groupRow.getChildren().add(new TreeItem<>(ticketRowWithinThisGroup)); ticketIdToDisplayRow.put( taskWithWorklogs.getIssue(), ticketRowWithinThisGroup); } DisplayRow ticketRowWithinThisGroupAsFinal = ticketRowWithinThisGroup; taskWithWorklogs .getWorklogItemList() .stream() .filter( worklogItem -> StringUtils.equals(worklogItem.getGroup(), groupByCriteria)) .sorted((o1, o2) -> o1.getDate().compareTo(o2.getDate())) .forEach( worklogItem -> { // this worklog item matches the critera // add workday entry to current row LocalDate date = worklogItem.getDate(); DisplayDayEntry workdayEntry = ticketRowWithinThisGroupAsFinal .getWorkdayEntry(date) .orElseGet( () -> { DisplayDayEntry displayDayEntry = new DisplayDayEntry(); displayDayEntry.setDate(date); ticketRowWithinThisGroupAsFinal.addDisplayDayEntry( displayDayEntry); return displayDayEntry; }); workdayEntry .getSpentTime() .addAndGet(worklogItem.getDurationInMinutes()); // also add up the spent time in the group header per group workdayEntry = groupCaptionRow .getWorkdayEntry(date) .orElseGet( () -> { DisplayDayEntry newWorkdayEntry = new DisplayDayEntry(); newWorkdayEntry.setDate(date); groupCaptionRow.addDisplayDayEntry(newWorkdayEntry); return newWorkdayEntry; }); workdayEntry .getSpentTime() .addAndGet(worklogItem.getDurationInMinutes()); }); }); // add groupRow to result displayData.addRow(groupRow); }); }