From cb285cbfddfc0b633d6b8cdb4dc0d2bd2b8b51ef Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 05 Jan 2012 17:34:05 -0500
Subject: [PATCH] Fixed bug in receive hook for repositories in subfolders

---
 src/com/gitblit/client/FeedsPanel.java |  238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 217 insertions(+), 21 deletions(-)

diff --git a/src/com/gitblit/client/FeedsPanel.java b/src/com/gitblit/client/FeedsPanel.java
index c6b464d..97f37c0 100644
--- a/src/com/gitblit/client/FeedsPanel.java
+++ b/src/com/gitblit/client/FeedsPanel.java
@@ -18,23 +18,33 @@
 import java.awt.BorderLayout;
 import java.awt.FlowLayout;
 import java.awt.Insets;
+import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
+import javax.swing.DefaultComboBoxModel;
 import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
+import javax.swing.RowFilter;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableRowSorter;
 
-import com.gitblit.Constants.RpcRequest;
+import com.gitblit.models.FeedEntryModel;
 import com.gitblit.models.FeedModel;
-import com.gitblit.models.SyndicatedEntryModel;
+import com.gitblit.utils.StringUtils;
 
 /**
  * RSS Feeds Panel displays recent entries and launches the browser to view the
@@ -49,11 +59,29 @@
 
 	private final GitblitClient gitblit;
 
-	private SyndicatedEntryTableModel tableModel;
+	private final String ALL = "*";
+
+	private FeedEntryTableModel tableModel;
+
+	private TableRowSorter<FeedEntryTableModel> defaultSorter;
 
 	private HeaderPanel header;
 
 	private JTable table;
+
+	private DefaultComboBoxModel repositoryChoices;
+
+	private JComboBox repositorySelector;
+
+	private DefaultComboBoxModel authorChoices;
+
+	private JComboBox authorSelector;
+
+	private int page;
+
+	private JButton prev;
+
+	private JButton next;
 
 	public FeedsPanel(GitblitClient gitblit) {
 		super();
@@ -62,10 +90,29 @@
 	}
 
 	private void initialize() {
+
+		prev = new JButton("<");
+		prev.setToolTipText(Translation.get("gb.pagePrevious"));
+		prev.setEnabled(false);
+		prev.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				refreshFeeds(--page);
+			}
+		});
+
+		next = new JButton(">");
+		next.setToolTipText(Translation.get("gb.pageNext"));
+		next.setEnabled(false);
+		next.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				refreshFeeds(++page);
+			}
+		});
+
 		JButton refreshFeeds = new JButton(Translation.get("gb.refresh"));
 		refreshFeeds.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
-				refreshFeeds();
+				refreshFeeds(0);
 			}
 		});
 
@@ -108,17 +155,21 @@
 		controls.add(viewTree);
 
 		NameRenderer nameRenderer = new NameRenderer();
-		tableModel = new SyndicatedEntryTableModel();
-		header = new HeaderPanel(Translation.get("gb.timeline"), "feed_16x16.png");
+		tableModel = new FeedEntryTableModel();
+		header = new HeaderPanel(Translation.get("gb.activity"), "feed_16x16.png");
 		table = Utils.newTable(tableModel, Utils.DATE_FORMAT);
-		String name = table.getColumnName(SyndicatedEntryTableModel.Columns.Author.ordinal());
+		defaultSorter = new TableRowSorter<FeedEntryTableModel>(tableModel);
+		String name = table.getColumnName(FeedEntryTableModel.Columns.Author.ordinal());
 		table.setRowHeight(nameRenderer.getFont().getSize() + 8);
 		table.getColumn(name).setCellRenderer(nameRenderer);
-		name = table.getColumnName(SyndicatedEntryTableModel.Columns.Repository.ordinal());
+		name = table.getColumnName(FeedEntryTableModel.Columns.Repository.ordinal());
 		table.getColumn(name).setCellRenderer(nameRenderer);
 
-		name = table.getColumnName(SyndicatedEntryTableModel.Columns.Branch.ordinal());
+		name = table.getColumnName(FeedEntryTableModel.Columns.Branch.ordinal());
 		table.getColumn(name).setCellRenderer(new BranchRenderer());
+
+		name = table.getColumnName(FeedEntryTableModel.Columns.Message.ordinal());
+		table.getColumn(name).setCellRenderer(new MessageRenderer(gitblit));
 
 		table.addMouseListener(new MouseAdapter() {
 			public void mouseClicked(MouseEvent e) {
@@ -145,8 +196,50 @@
 			}
 		});
 
+		repositoryChoices = new DefaultComboBoxModel();
+		repositorySelector = new JComboBox(repositoryChoices);
+		repositorySelector.setRenderer(nameRenderer);
+		repositorySelector.setForeground(nameRenderer.getForeground());
+		repositorySelector.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+				// repopulate the author list based on repository selection
+				// preserve author selection, if possible
+				String selectedAuthor = null;
+				if (authorSelector.getSelectedIndex() > -1) {
+					selectedAuthor = authorSelector.getSelectedItem().toString();
+				}
+				updateAuthors();
+				if (selectedAuthor != null) {
+					if (authorChoices.getIndexOf(selectedAuthor) > -1) {
+						authorChoices.setSelectedItem(selectedAuthor);
+					}
+				}
+				filterFeeds();
+			}
+		});
+		authorChoices = new DefaultComboBoxModel();
+		authorSelector = new JComboBox(authorChoices);
+		authorSelector.setRenderer(nameRenderer);
+		authorSelector.setForeground(nameRenderer.getForeground());
+		authorSelector.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+				filterFeeds();
+			}
+		});
+		JPanel northControls = new JPanel(new FlowLayout(FlowLayout.LEFT, Utils.MARGIN, 0));
+		northControls.add(new JLabel(Translation.get("gb.repository")));
+		northControls.add(repositorySelector);
+		northControls.add(new JLabel(Translation.get("gb.author")));
+		northControls.add(authorSelector);
+//		northControls.add(prev);
+//		northControls.add(next);
+
+		JPanel northPanel = new JPanel(new BorderLayout(0, Utils.MARGIN));
+		northPanel.add(header, BorderLayout.NORTH);
+		northPanel.add(northControls, BorderLayout.CENTER);
+
 		setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
-		add(header, BorderLayout.NORTH);
+		add(northPanel, BorderLayout.NORTH);
 		add(new JScrollPane(table), BorderLayout.CENTER);
 		add(controls, BorderLayout.SOUTH);
 	}
@@ -156,12 +249,12 @@
 		return Utils.INSETS;
 	}
 
-	protected void refreshFeeds() {
-		// TODO change request type here
-		GitblitWorker worker = new GitblitWorker(FeedsPanel.this, RpcRequest.LIST_USERS) {
+	protected void refreshFeeds(final int page) {
+		this.page = page;
+		GitblitWorker worker = new GitblitWorker(FeedsPanel.this, null) {
 			@Override
 			protected Boolean doRequest() throws IOException {
-				gitblit.refreshSubscribedFeeds();
+				gitblit.refreshSubscribedFeeds(page);
 				return true;
 			}
 
@@ -179,32 +272,135 @@
 		tableModel.entries.clear();
 		tableModel.entries.addAll(gitblit.getSyndicatedEntries());
 		tableModel.fireTableDataChanged();
-		header.setText(Translation.get("gb.timeline") + " ("
-				+ gitblit.getSyndicatedEntries().size() + ")");
+		header.setText(Translation.get("gb.activity") + " ("
+				+ gitblit.getSyndicatedEntries().size() + (page > 0 ? (", pg " + (page + 1)) : "")
+				+ ")");
 		if (pack) {
 			Utils.packColumns(table, Utils.MARGIN);
 		}
+		table.scrollRectToVisible(new Rectangle(table.getCellRect(0, 0, true)));
+
+		if (page == 0) {
+			// determine unique repositories
+			Set<String> uniqueRepositories = new HashSet<String>();
+			for (FeedEntryModel entry : tableModel.entries) {
+				uniqueRepositories.add(entry.repository);
+			}
+
+			// repositories
+			List<String> sortedRespositories = new ArrayList<String>(uniqueRepositories);
+			StringUtils.sortRepositorynames(sortedRespositories);
+			repositoryChoices.removeAllElements();
+			repositoryChoices.addElement(ALL);
+			for (String repo : sortedRespositories) {
+				repositoryChoices.addElement(repo);
+			}
+		}
+
+		// update pagination buttons
+		next.setEnabled(tableModel.entries.size() > 0);
+		prev.setEnabled(page > 0);
 	}
 
-	protected SyndicatedEntryModel getSelectedSyndicatedEntry() {
+	private void updateAuthors() {
+		String repository = ALL;
+		if (repositorySelector.getSelectedIndex() > -1) {
+			repository = repositorySelector.getSelectedItem().toString();
+		}
+
+		// determine unique repositories and authors
+		Set<String> uniqueAuthors = new HashSet<String>();
+		for (FeedEntryModel entry : tableModel.entries) {
+			if (repository.equals(ALL) || entry.repository.equalsIgnoreCase(repository)) {
+				uniqueAuthors.add(entry.author);
+			}
+		}
+		// authors
+		List<String> sortedAuthors = new ArrayList<String>(uniqueAuthors);
+		Collections.sort(sortedAuthors);
+		authorChoices.removeAllElements();
+		authorChoices.addElement(ALL);
+		for (String author : sortedAuthors) {
+			authorChoices.addElement(author);
+		}
+	}
+
+	protected FeedEntryModel getSelectedSyndicatedEntry() {
 		int viewRow = table.getSelectedRow();
 		int modelRow = table.convertRowIndexToModel(viewRow);
-		SyndicatedEntryModel entry = tableModel.get(modelRow);
+		FeedEntryModel entry = tableModel.get(modelRow);
 		return entry;
 	}
 
 	protected void viewCommit() {
-		SyndicatedEntryModel entry = getSelectedSyndicatedEntry();
+		FeedEntryModel entry = getSelectedSyndicatedEntry();
 		Utils.browse(entry.link);
 	}
 
 	protected void viewCommitDiff() {
-		SyndicatedEntryModel entry = getSelectedSyndicatedEntry();
+		FeedEntryModel entry = getSelectedSyndicatedEntry();
 		Utils.browse(entry.link.replace("/commit/", "/commitdiff/"));
 	}
 
 	protected void viewTree() {
-		SyndicatedEntryModel entry = getSelectedSyndicatedEntry();
+		FeedEntryModel entry = getSelectedSyndicatedEntry();
 		Utils.browse(entry.link.replace("/commit/", "/tree/"));
 	}
+
+	protected void filterFeeds() {
+		final String repository;
+		if (repositorySelector.getSelectedIndex() > -1) {
+			repository = repositorySelector.getSelectedItem().toString();
+		} else {
+			repository = ALL;
+		}
+
+		final String author;
+		if (authorSelector.getSelectedIndex() > -1) {
+			author = authorSelector.getSelectedItem().toString();
+		} else {
+			author = ALL;
+		}
+
+		if (repository.equals(ALL) && author.equals(ALL)) {
+			table.setRowSorter(defaultSorter);
+			return;
+		}
+		final int repositoryIndex = FeedEntryTableModel.Columns.Repository.ordinal();
+		final int authorIndex = FeedEntryTableModel.Columns.Author.ordinal();
+		RowFilter<FeedEntryTableModel, Object> containsFilter;
+		if (repository.equals(ALL)) {
+			// author filter
+			containsFilter = new RowFilter<FeedEntryTableModel, Object>() {
+				public boolean include(
+						Entry<? extends FeedEntryTableModel, ? extends Object> entry) {
+					return entry.getStringValue(authorIndex).equalsIgnoreCase(author);
+				}
+			};
+		} else if (author.equals(ALL)) {
+			// repository filter
+			containsFilter = new RowFilter<FeedEntryTableModel, Object>() {
+				public boolean include(
+						Entry<? extends FeedEntryTableModel, ? extends Object> entry) {
+					return entry.getStringValue(repositoryIndex).equalsIgnoreCase(repository);
+				}
+			};
+		} else {
+			// repository-author filter
+			containsFilter = new RowFilter<FeedEntryTableModel, Object>() {
+				public boolean include(
+						Entry<? extends FeedEntryTableModel, ? extends Object> entry) {
+					boolean authorMatch = entry.getStringValue(authorIndex)
+							.equalsIgnoreCase(author);
+					boolean repositoryMatch = entry.getStringValue(repositoryIndex)
+							.equalsIgnoreCase(repository);
+					return authorMatch && repositoryMatch;
+				}
+			};
+		}
+		TableRowSorter<FeedEntryTableModel> sorter = new TableRowSorter<FeedEntryTableModel>(
+				tableModel);
+		sorter.setRowFilter(containsFilter);
+		table.setRowSorter(sorter);
+	}
 }

--
Gitblit v1.9.1