]> source.dussan.org Git - gitblit.git/commitdiff
Refactored monolithic GitblitPanel into pieces. Revised feed generation.
authorJames Moger <james.moger@gitblit.com>
Tue, 1 Nov 2011 21:21:09 +0000 (17:21 -0400)
committerJames Moger <james.moger@gitblit.com>
Tue, 1 Nov 2011 21:21:09 +0000 (17:21 -0400)
15 files changed:
src/com/gitblit/SyndicationServlet.java
src/com/gitblit/client/EditRepositoryDialog.java
src/com/gitblit/client/FeedsPanel.java [new file with mode: 0644]
src/com/gitblit/client/FeedsTableModel.java
src/com/gitblit/client/GitblitClient.java
src/com/gitblit/client/GitblitManager.java
src/com/gitblit/client/GitblitPanel.java
src/com/gitblit/client/RepositoriesPanel.java [new file with mode: 0644]
src/com/gitblit/client/SettingsPanel.java [new file with mode: 0644]
src/com/gitblit/client/StatusPanel.java
src/com/gitblit/client/UsersPanel.java [new file with mode: 0644]
src/com/gitblit/client/Utils.java
src/com/gitblit/models/FeedModel.java
src/com/gitblit/utils/SyndicationUtils.java
tests/com/gitblit/tests/SyndicationUtilsTest.java

index f1c474ff50235293683d6d4c29b248e604f9abee..694b9ccce0439d530bb4d28e6549a926e942eff9 100644 (file)
@@ -16,6 +16,7 @@
 package com.gitblit;\r
 \r
 import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
 import java.util.List;\r
 \r
 import javax.servlet.http.HttpServlet;\r
@@ -26,10 +27,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;\r
 \r
 import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.SyndicatedEntryModel;\r
 import com.gitblit.utils.HttpUtils;\r
 import com.gitblit.utils.JGitUtils;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.utils.SyndicationUtils;\r
+import com.sun.syndication.feed.synd.SyndContent;\r
+import com.sun.syndication.feed.synd.SyndContentImpl;\r
 \r
 /**\r
  * SyndicationServlet generates RSS 2.0 feeds and feed links.\r
@@ -139,9 +143,26 @@ public class SyndicationServlet extends HttpServlet {
                Repository repository = GitBlit.self().getRepository(repositoryName);\r
                RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);\r
                List<RevCommit> commits = JGitUtils.getRevLog(repository, objectId, 0, length);\r
+               List<SyndicatedEntryModel> entries = new ArrayList<SyndicatedEntryModel>();\r
+\r
+               String gitblitUrl = HttpUtils.getGitblitURL(request);\r
+               // convert RevCommit to SyndicatedEntryModel\r
+               for (RevCommit commit : commits) {\r
+                       SyndicatedEntryModel entry = new SyndicatedEntryModel();\r
+                       entry.title = commit.getShortMessage();\r
+                       entry.author = commit.getAuthorIdent().getName();\r
+                       entry.link = MessageFormat.format("{0}/commit/{1}/{2}", gitblitUrl,\r
+                                       StringUtils.encodeURL(model.name), commit.getName());\r
+                       entry.published = commit.getCommitterIdent().getWhen();\r
+                       entry.contentType = "text/plain";\r
+                       entry.content = commit.getFullMessage();\r
+                       entry.repository = model.name;\r
+                       entry.branch = objectId;\r
+                       entries.add(entry);\r
+               }\r
                try {\r
-                       SyndicationUtils.toRSS(HttpUtils.getGitblitURL(request), getTitle(model.name, objectId), model.description,\r
-                                       model.name, commits, response.getOutputStream());\r
+                       SyndicationUtils.toRSS(gitblitUrl, getTitle(model.name, objectId), model.description,\r
+                                       model.name, entries, response.getOutputStream());\r
                } catch (Exception e) {\r
                        logger.error("An error occurred during feed generation", e);\r
                }\r
index 55f5268e1facfeac46caa06d92a1777b8056e984..ef0f58ac7393a434d46018634a7b0176d30ddc2c 100644 (file)
@@ -246,6 +246,7 @@ public class EditRepositoryDialog extends JDialog {
                getContentPane().setLayout(new BorderLayout(5, 5));\r
                getContentPane().add(centerPanel, BorderLayout.CENTER);\r
                pack();\r
+               nameField.requestFocus();\r
        }\r
 \r
        private JPanel newFieldPanel(String label, JComponent comp) {\r
diff --git a/src/com/gitblit/client/FeedsPanel.java b/src/com/gitblit/client/FeedsPanel.java
new file mode 100644 (file)
index 0000000..e2b8527
--- /dev/null
@@ -0,0 +1,210 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.FlowLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+\r
+import com.gitblit.Constants.RpcRequest;\r
+import com.gitblit.models.FeedModel;\r
+import com.gitblit.models.SyndicatedEntryModel;\r
+\r
+/**\r
+ * RSS Feeds Panel displays recent entries and launches the browser to view the\r
+ * commit. commitdiff, or tree of a commit.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public abstract class FeedsPanel extends JPanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final GitblitClient gitblit;\r
+\r
+       private SyndicatedEntryTableModel tableModel;\r
+\r
+       private HeaderPanel header;\r
+\r
+       private JTable table;\r
+\r
+       public FeedsPanel(GitblitClient gitblit) {\r
+               super();\r
+               this.gitblit = gitblit;\r
+               initialize();\r
+       }\r
+\r
+       private void initialize() {\r
+               JButton refreshFeeds = new JButton(Translation.get("gb.refresh"));\r
+               refreshFeeds.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               refreshFeeds();\r
+                       }\r
+               });\r
+\r
+               final JButton viewCommit = new JButton(Translation.get("gb.view"));\r
+               viewCommit.setEnabled(false);\r
+               viewCommit.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               viewCommit();\r
+                       }\r
+               });\r
+\r
+               final JButton viewCommitDiff = new JButton(Translation.get("gb.commitdiff"));\r
+               viewCommitDiff.setEnabled(false);\r
+               viewCommitDiff.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               viewCommitDiff();\r
+                       }\r
+               });\r
+\r
+               final JButton viewTree = new JButton(Translation.get("gb.tree"));\r
+               viewTree.setEnabled(false);\r
+               viewTree.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               viewTree();\r
+                       }\r
+               });\r
+\r
+               JButton subscribeFeeds = new JButton(Translation.get("gb.subscribe") + "...");\r
+               subscribeFeeds.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               subscribeFeeds(gitblit.getAvailableFeeds());\r
+                       }\r
+               });\r
+\r
+               JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0));\r
+               controls.add(refreshFeeds);\r
+               controls.add(subscribeFeeds);\r
+               controls.add(viewCommit);\r
+               controls.add(viewCommitDiff);\r
+               controls.add(viewTree);\r
+\r
+               NameRenderer nameRenderer = new NameRenderer();\r
+               tableModel = new SyndicatedEntryTableModel();\r
+               header = new HeaderPanel(Translation.get("gb.recentActivity"), "feed_16x16.png");\r
+               table = Utils.newTable(tableModel, Utils.DATE_FORMAT);\r
+               String name = table.getColumnName(SyndicatedEntryTableModel.Columns.Author.ordinal());\r
+               table.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+               table.getColumn(name).setCellRenderer(nameRenderer);\r
+               name = table.getColumnName(SyndicatedEntryTableModel.Columns.Repository.ordinal());\r
+               table.getColumn(name).setCellRenderer(nameRenderer);\r
+\r
+               name = table.getColumnName(SyndicatedEntryTableModel.Columns.Branch.ordinal());\r
+               table.getColumn(name).setCellRenderer(nameRenderer);\r
+\r
+               table.addMouseListener(new MouseAdapter() {\r
+                       public void mouseClicked(MouseEvent e) {\r
+                               if (e.getClickCount() == 2) {\r
+                                       if (e.isControlDown()) {\r
+                                               viewCommitDiff();\r
+                                       } else {\r
+                                               viewCommit();\r
+                                       }\r
+                               }\r
+                       }\r
+               });\r
+\r
+               table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+                       @Override\r
+                       public void valueChanged(ListSelectionEvent e) {\r
+                               if (e.getValueIsAdjusting()) {\r
+                                       return;\r
+                               }\r
+                               boolean singleSelection = table.getSelectedRowCount() == 1;\r
+                               viewCommit.setEnabled(singleSelection);\r
+                               viewCommitDiff.setEnabled(singleSelection);\r
+                               viewTree.setEnabled(singleSelection);\r
+                       }\r
+               });\r
+\r
+               setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               add(header, BorderLayout.NORTH);\r
+               add(new JScrollPane(table), BorderLayout.CENTER);\r
+               add(controls, BorderLayout.SOUTH);\r
+       }\r
+\r
+       @Override\r
+       public Insets getInsets() {\r
+               return Utils.INSETS;\r
+       }\r
+\r
+       protected void refreshFeeds() {\r
+               // TODO change request type here\r
+               GitblitWorker worker = new GitblitWorker(FeedsPanel.this, RpcRequest.LIST_USERS) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               gitblit.refreshSubscribedFeeds();\r
+                               return true;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       protected abstract void subscribeFeeds(List<FeedModel> feeds);\r
+\r
+       protected void updateTable(boolean pack) {\r
+               tableModel.entries.clear();\r
+               tableModel.entries.addAll(gitblit.getSyndicatedEntries());\r
+               tableModel.fireTableDataChanged();\r
+               header.setText(Translation.get("gb.recentActivity") + " ("\r
+                               + gitblit.getSyndicatedEntries().size() + ")");\r
+               if (pack) {\r
+                       Utils.packColumns(table, Utils.MARGIN);\r
+               }\r
+       }\r
+\r
+       protected SyndicatedEntryModel getSelectedSyndicatedEntry() {\r
+               int viewRow = table.getSelectedRow();\r
+               int modelRow = table.convertRowIndexToModel(viewRow);\r
+               SyndicatedEntryModel entry = tableModel.get(modelRow);\r
+               return entry;\r
+       }\r
+\r
+       protected void viewCommit() {\r
+               SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
+               Utils.browse(entry.link);\r
+       }\r
+\r
+       protected void viewCommitDiff() {\r
+               SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
+               Utils.browse(entry.link.replace("/commit/", "/commitdiff/"));\r
+       }\r
+\r
+       protected void viewTree() {\r
+               SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
+               Utils.browse(entry.link.replace("/commit/", "/tree/"));\r
+       }\r
+}\r
index a628fc8274e62b889d02f83bb22b3bb5ac458c6c..0979a4c93da831a49125895d59407a76a6d357a8 100644 (file)
@@ -36,7 +36,7 @@ public class FeedsTableModel extends AbstractTableModel {
        List<FeedModel> list;\r
 \r
        enum Columns {\r
-               Subscribed, Repository, Branch, Max_Length;\r
+               Subscribed, Repository, Branch;\r
 \r
                @Override\r
                public String toString() {\r
@@ -87,8 +87,6 @@ public class FeedsTableModel extends AbstractTableModel {
                switch (col) {\r
                case Subscribed:\r
                        return Boolean.class;\r
-               case Max_Length:\r
-                       return Integer.class;\r
                }\r
                return String.class;\r
        }\r
@@ -112,8 +110,6 @@ public class FeedsTableModel extends AbstractTableModel {
                        return model.repository;\r
                case Branch:\r
                        return model.branch;\r
-               case Max_Length:\r
-                       return model.maxRetrieval;\r
                case Subscribed:\r
                        return model.subscribed;\r
                }\r
index 74e0e08de5760f948f04317542b1d29373d2ba73..a432c1301b5f682882a36a6836fc9811cc8936be 100644 (file)
@@ -290,7 +290,7 @@ public class GitblitClient implements Serializable {
        public boolean createRepository(RepositoryModel repository, List<String> permittedUsers)\r
                        throws IOException {\r
                boolean success = true;\r
-               success &= RpcUtils.createRepository(repository, url, account, password);\r
+               success &= RpcUtils.createRepository(repository, url, account, password);               \r
                if (permittedUsers.size() > 0) {\r
                        // if new repository has named members, set them\r
                        success &= RpcUtils.setRepositoryMembers(repository, permittedUsers, url, account,\r
index d9c2dccf429daed022379562183d99c9fa533ac9..f4ca7c5c0194836a9e83106e43353936f9e1c480 100644 (file)
@@ -56,12 +56,12 @@ import javax.swing.UIManager;
 import org.eclipse.jgit.errors.ConfigInvalidException;\r
 import org.eclipse.jgit.lib.StoredConfig;\r
 import org.eclipse.jgit.storage.file.FileBasedConfig;\r
-import org.eclipse.jgit.util.Base64;\r
 import org.eclipse.jgit.util.FS;\r
 \r
 import com.gitblit.Constants;\r
 import com.gitblit.GitBlitException.ForbiddenException;\r
 import com.gitblit.models.FeedModel;\r
+import com.gitblit.utils.Base64;\r
 import com.gitblit.utils.StringUtils;\r
 \r
 /**\r
index 64e85eaff604b1c88d49b15d82457f478539f8ea..6c65328b0a43ca28e6422c1fe32d00bd3acb5580 100644 (file)
 package com.gitblit.client;\r
 \r
 import java.awt.BorderLayout;\r
-import java.awt.Color;\r
 import java.awt.Component;\r
-import java.awt.Desktop;\r
-import java.awt.Dimension;\r
-import java.awt.FlowLayout;\r
-import java.awt.GridLayout;\r
 import java.awt.Insets;\r
-import java.awt.event.ActionEvent;\r
-import java.awt.event.ActionListener;\r
-import java.awt.event.KeyAdapter;\r
-import java.awt.event.KeyEvent;\r
-import java.awt.event.MouseAdapter;\r
-import java.awt.event.MouseEvent;\r
 import java.io.IOException;\r
-import java.net.URI;\r
-import java.text.MessageFormat;\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
 import java.util.List;\r
-import java.util.Map;\r
 \r
-import javax.swing.ImageIcon;\r
-import javax.swing.JButton;\r
-import javax.swing.JLabel;\r
-import javax.swing.JOptionPane;\r
 import javax.swing.JPanel;\r
-import javax.swing.JScrollPane;\r
 import javax.swing.JTabbedPane;\r
-import javax.swing.JTable;\r
-import javax.swing.JTextField;\r
-import javax.swing.RowFilter;\r
-import javax.swing.SwingConstants;\r
-import javax.swing.event.ListSelectionEvent;\r
-import javax.swing.event.ListSelectionListener;\r
-import javax.swing.table.DefaultTableCellRenderer;\r
-import javax.swing.table.TableCellRenderer;\r
-import javax.swing.table.TableRowSorter;\r
+import javax.swing.event.ChangeEvent;\r
+import javax.swing.event.ChangeListener;\r
 \r
-import com.gitblit.Constants.RpcRequest;\r
 import com.gitblit.client.ClosableTabComponent.CloseTabListener;\r
 import com.gitblit.models.FeedModel;\r
-import com.gitblit.models.RepositoryModel;\r
-import com.gitblit.models.SettingModel;\r
-import com.gitblit.models.SyndicatedEntryModel;\r
-import com.gitblit.models.UserModel;\r
-import com.gitblit.utils.StringUtils;\r
 \r
 /**\r
  * GitblitPanel performs the login, all business logic, and contains all widgets\r
@@ -74,54 +40,22 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
 \r
        private static final long serialVersionUID = 1L;\r
 \r
-       private final int margin = 5;\r
-\r
-       private final Insets insets = new Insets(margin, margin, margin, margin);\r
-\r
        private final RegistrationsDialog.RegistrationListener listener;\r
 \r
        private GitblitClient gitblit;\r
 \r
        private JTabbedPane tabs;\r
 \r
-       private JTable repositoriesTable;\r
-\r
-       private RepositoriesTableModel repositoriesModel;\r
-\r
-       private JTable usersTable;\r
-\r
-       private UsersTableModel usersModel;\r
-\r
-       private JTable settingsTable;\r
-\r
-       private SettingsTableModel settingsModel;\r
-\r
-       private JButton createRepository;\r
-\r
-       private JButton delRepository;\r
-\r
-       private TableRowSorter<RepositoriesTableModel> defaultRepositoriesSorter;\r
-\r
-       private TableRowSorter<UsersTableModel> defaultUsersSorter;\r
+       private RepositoriesPanel repositoriesPanel;\r
 \r
-       private TableRowSorter<SettingsTableModel> defaultSettingsSorter;\r
+       private FeedsPanel feedsPanel;\r
 \r
-       private JButton editRepository;\r
+       private UsersPanel usersPanel;\r
 \r
-       private HeaderPanel repositoriesHeader;\r
-\r
-       private HeaderPanel usersHeader;\r
-\r
-       private HeaderPanel settingsHeader;\r
+       private SettingsPanel settingsPanel;\r
 \r
        private StatusPanel statusPanel;\r
 \r
-       private SyndicatedEntryTableModel syndicationModel;\r
-\r
-       private HeaderPanel feedsHeader;\r
-\r
-       private JTable syndicationEntriesTable;\r
-\r
        public GitblitPanel(GitblitRegistration reg, RegistrationsDialog.RegistrationListener listener) {\r
                this.gitblit = new GitblitClient(reg);\r
                this.listener = listener;\r
@@ -132,510 +66,74 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                tabs.addTab(Translation.get("gb.users"), createUsersPanel());\r
                tabs.addTab(Translation.get("gb.settings"), createSettingsPanel());\r
                tabs.addTab(Translation.get("gb.status"), createStatusPanel());\r
+               tabs.addChangeListener(new ChangeListener() {\r
+                       public void stateChanged(ChangeEvent e) {\r
+                               tabs.getSelectedComponent().requestFocus();                             \r
+                       }\r
+               });             \r
 \r
                setLayout(new BorderLayout());\r
                add(tabs, BorderLayout.CENTER);\r
        }\r
 \r
        private JPanel createRepositoriesPanel() {\r
-               final JButton browseRepository = new JButton(Translation.get("gb.browse"));\r
-               browseRepository.setEnabled(false);\r
-               browseRepository.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               RepositoryModel model = getSelectedRepositories().get(0);\r
-                               String u = MessageFormat.format("{0}/summary/{1}", gitblit.url,\r
-                                               StringUtils.encodeURL(model.name));\r
-                               try {\r
-                                       Desktop.getDesktop().browse(new URI(u));\r
-                               } catch (Exception x) {\r
-                                       x.printStackTrace();\r
-                               }\r
-                       }\r
-               });\r
-\r
-               JButton refreshRepositories = new JButton(Translation.get("gb.refresh"));\r
-               refreshRepositories.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               refreshRepositories();\r
-                       }\r
-               });\r
+               repositoriesPanel = new RepositoriesPanel(gitblit) {\r
 \r
-               createRepository = new JButton(Translation.get("gb.create"));\r
-               createRepository.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               createRepository();\r
-                       }\r
-               });\r
-\r
-               editRepository = new JButton(Translation.get("gb.edit"));\r
-               editRepository.setEnabled(false);\r
-               editRepository.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               editRepository(getSelectedRepositories().get(0));\r
-                       }\r
-               });\r
-\r
-               delRepository = new JButton(Translation.get("gb.delete"));\r
-               delRepository.setEnabled(false);\r
-               delRepository.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               deleteRepositories(getSelectedRepositories());\r
-                       }\r
-               });\r
-\r
-               final JButton subscribeRepository = new JButton(Translation.get("gb.subscribe") + "...");\r
-               subscribeRepository.setEnabled(false);\r
-               subscribeRepository.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               List<FeedModel> feeds = gitblit.getAvailableFeeds(getSelectedRepositories().get(0));\r
-                               subscribeFeeds(feeds);\r
-                       }\r
-               });\r
-\r
-               SubscribedRepositoryRenderer nameRenderer = new SubscribedRepositoryRenderer(gitblit);\r
-               IndicatorsRenderer typeRenderer = new IndicatorsRenderer();\r
-\r
-               DefaultTableCellRenderer sizeRenderer = new DefaultTableCellRenderer();\r
-               sizeRenderer.setHorizontalAlignment(SwingConstants.RIGHT);\r
-               sizeRenderer.setForeground(new Color(0, 0x80, 0));\r
-\r
-               DefaultTableCellRenderer ownerRenderer = new DefaultTableCellRenderer();\r
-               ownerRenderer.setForeground(Color.gray);\r
-               ownerRenderer.setHorizontalAlignment(SwingConstants.CENTER);\r
-\r
-               repositoriesModel = new RepositoriesTableModel();\r
-               defaultRepositoriesSorter = new TableRowSorter<RepositoriesTableModel>(repositoriesModel);\r
-               repositoriesTable = Utils.newTable(repositoriesModel, Utils.DATE_FORMAT);\r
-               repositoriesTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
-               repositoriesTable.setRowSorter(defaultRepositoriesSorter);\r
-               repositoriesTable.getRowSorter().toggleSortOrder(\r
-                               RepositoriesTableModel.Columns.Name.ordinal());\r
-\r
-               setRepositoryRenderer(RepositoriesTableModel.Columns.Name, nameRenderer, -1);\r
-               setRepositoryRenderer(RepositoriesTableModel.Columns.Indicators, typeRenderer, 100);\r
-               setRepositoryRenderer(RepositoriesTableModel.Columns.Owner, ownerRenderer, -1);\r
-               setRepositoryRenderer(RepositoriesTableModel.Columns.Size, sizeRenderer, 60);\r
+                       private static final long serialVersionUID = 1L;\r
 \r
-               repositoriesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
                        @Override\r
-                       public void valueChanged(ListSelectionEvent e) {\r
-                               if (e.getValueIsAdjusting()) {\r
-                                       return;\r
-                               }\r
-                               boolean singleSelection = repositoriesTable.getSelectedRowCount() == 1;\r
-                               boolean selected = repositoriesTable.getSelectedRow() > -1;\r
-                               browseRepository.setEnabled(singleSelection);\r
-                               delRepository.setEnabled(selected);\r
-                               subscribeRepository.setEnabled(singleSelection);\r
-                               if (selected) {\r
-                                       int viewRow = repositoriesTable.getSelectedRow();\r
-                                       int modelRow = repositoriesTable.convertRowIndexToModel(viewRow);\r
-                                       RepositoryModel model = ((RepositoriesTableModel) repositoriesTable.getModel()).list\r
-                                                       .get(modelRow);\r
-                                       editRepository.setEnabled(singleSelection\r
-                                                       && (gitblit.allowManagement() || gitblit.isOwner(model)));\r
-                               } else {\r
-                                       editRepository.setEnabled(false);\r
-                               }\r
+                       protected void subscribeFeeds(List<FeedModel> feeds) {\r
+                               GitblitPanel.this.subscribeFeeds(feeds);\r
                        }\r
-               });\r
 \r
-               repositoriesTable.addMouseListener(new MouseAdapter() {\r
-                       public void mouseClicked(MouseEvent e) {\r
-                               if (e.getClickCount() == 2 && gitblit.allowManagement()) {\r
-                                       editRepository(getSelectedRepositories().get(0));\r
-                               }\r
-                       }\r
-               });\r
-\r
-               final JTextField repositoryFilter = new JTextField();\r
-               repositoryFilter.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               filterRepositories(repositoryFilter.getText());\r
-                       }\r
-               });\r
-               repositoryFilter.addKeyListener(new KeyAdapter() {\r
-                       public void keyReleased(KeyEvent e) {\r
-                               filterRepositories(repositoryFilter.getText());\r
+                       @Override\r
+                       protected void updateUsersTable() {\r
+                               usersPanel.updateTable(false);\r
                        }\r
-               });\r
 \r
-               JPanel repositoryFilterPanel = new JPanel(new BorderLayout(margin, margin));\r
-               repositoryFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);\r
-               repositoryFilterPanel.add(repositoryFilter, BorderLayout.CENTER);\r
-\r
-               JPanel repositoryTablePanel = new JPanel(new BorderLayout(margin, margin));\r
-               repositoryTablePanel.add(repositoryFilterPanel, BorderLayout.NORTH);\r
-               repositoryTablePanel.add(new JScrollPane(repositoriesTable), BorderLayout.CENTER);\r
-\r
-               JPanel repositoryControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
-               repositoryControls.add(refreshRepositories);\r
-               repositoryControls.add(browseRepository);\r
-               repositoryControls.add(createRepository);\r
-               repositoryControls.add(editRepository);\r
-               repositoryControls.add(delRepository);\r
-               repositoryControls.add(subscribeRepository);\r
-\r
-               JPanel repositoriesPanel = new JPanel(new BorderLayout(margin, margin)) {\r
-\r
-                       private static final long serialVersionUID = 1L;\r
-\r
-                       public Insets getInsets() {\r
-                               return insets;\r
-                       }\r
                };\r
-               repositoriesHeader = new HeaderPanel(Translation.get("gb.repositories"),\r
-                               "gitweb-favicon.png");\r
-               repositoriesPanel.add(repositoriesHeader, BorderLayout.NORTH);\r
-               repositoriesPanel.add(repositoryTablePanel, BorderLayout.CENTER);\r
-               repositoriesPanel.add(repositoryControls, BorderLayout.SOUTH);\r
-\r
                return repositoriesPanel;\r
        }\r
 \r
-       private void setRepositoryRenderer(RepositoriesTableModel.Columns col,\r
-                       TableCellRenderer renderer, int maxWidth) {\r
-               String name = repositoriesTable.getColumnName(col.ordinal());\r
-               repositoriesTable.getColumn(name).setCellRenderer(renderer);\r
-               if (maxWidth > 0) {\r
-                       repositoriesTable.getColumn(name).setMinWidth(maxWidth);\r
-                       repositoriesTable.getColumn(name).setMaxWidth(maxWidth);\r
-               }\r
-       }\r
-\r
        private JPanel createFeedsPanel() {\r
-               JButton refreshFeeds = new JButton(Translation.get("gb.refresh"));\r
-               refreshFeeds.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               refreshFeeds();\r
-                       }\r
-               });\r
-\r
-               final JButton viewCommit = new JButton(Translation.get("gb.view"));\r
-               viewCommit.setEnabled(false);\r
-               viewCommit.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               viewCommit();\r
-                       }\r
-               });\r
-\r
-               final JButton viewCommitDiff = new JButton(Translation.get("gb.commitdiff"));\r
-               viewCommitDiff.setEnabled(false);\r
-               viewCommitDiff.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               viewCommitDiff();\r
-                       }\r
-               });\r
-\r
-               final JButton viewTree = new JButton(Translation.get("gb.tree"));\r
-               viewTree.setEnabled(false);\r
-               viewTree.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               viewTree();\r
-                       }\r
-               });\r
-\r
-               JButton subscribeFeeds = new JButton(Translation.get("gb.subscribe") + "...");\r
-               subscribeFeeds.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               subscribeFeeds(gitblit.getAvailableFeeds());\r
-                       }\r
-               });\r
-\r
-               JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
-               controls.add(refreshFeeds);\r
-               controls.add(subscribeFeeds);\r
-               controls.add(viewCommit);\r
-               controls.add(viewCommitDiff);\r
-               controls.add(viewTree);\r
-\r
-               NameRenderer nameRenderer = new NameRenderer();\r
-               syndicationModel = new SyndicatedEntryTableModel();\r
-               feedsHeader = new HeaderPanel(Translation.get("gb.recentActivity"), "feed_16x16.png");\r
-               syndicationEntriesTable = Utils.newTable(syndicationModel, Utils.DATE_FORMAT);\r
-               String name = syndicationEntriesTable\r
-                               .getColumnName(SyndicatedEntryTableModel.Columns.Author.ordinal());\r
-               syndicationEntriesTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
-               syndicationEntriesTable.getColumn(name).setCellRenderer(nameRenderer);\r
-               name = syndicationEntriesTable.getColumnName(SyndicatedEntryTableModel.Columns.Repository\r
-                               .ordinal());\r
-               syndicationEntriesTable.getColumn(name).setCellRenderer(nameRenderer);\r
-\r
-               name = syndicationEntriesTable.getColumnName(SyndicatedEntryTableModel.Columns.Branch\r
-                               .ordinal());\r
-               syndicationEntriesTable.getColumn(name).setCellRenderer(nameRenderer);\r
-\r
-               syndicationEntriesTable.addMouseListener(new MouseAdapter() {\r
-                       public void mouseClicked(MouseEvent e) {\r
-                               if (e.getClickCount() == 2) {\r
-                                       if (e.isControlDown()) {\r
-                                               viewCommitDiff();\r
-                                       } else {\r
-                                               viewCommit();\r
-                                       }\r
-                               }\r
-                       }\r
-               });\r
-\r
-               syndicationEntriesTable.getSelectionModel().addListSelectionListener(\r
-                               new ListSelectionListener() {\r
-                                       @Override\r
-                                       public void valueChanged(ListSelectionEvent e) {\r
-                                               if (e.getValueIsAdjusting()) {\r
-                                                       return;\r
-                                               }\r
-                                               boolean singleSelection = syndicationEntriesTable.getSelectedRowCount() == 1;\r
-                                               viewCommit.setEnabled(singleSelection);\r
-                                               viewCommitDiff.setEnabled(singleSelection);\r
-                                               viewTree.setEnabled(singleSelection);\r
-                                       }\r
-                               });\r
-\r
-               JPanel panel = new JPanel(new BorderLayout(5, 5)) {\r
-\r
+               feedsPanel = new FeedsPanel(gitblit) {\r
                        private static final long serialVersionUID = 1L;\r
 \r
                        @Override\r
-                       public Insets getInsets() {\r
-                               return insets;\r
+                       protected void subscribeFeeds(List<FeedModel> feeds) {\r
+                               GitblitPanel.this.subscribeFeeds(feeds);\r
                        }\r
                };\r
-               panel.add(feedsHeader, BorderLayout.NORTH);\r
-               panel.add(new JScrollPane(syndicationEntriesTable), BorderLayout.CENTER);\r
-               panel.add(controls, BorderLayout.SOUTH);\r
-               return panel;\r
+               return feedsPanel;\r
        }\r
 \r
        private JPanel createUsersPanel() {\r
-               JButton refreshUsers = new JButton(Translation.get("gb.refresh"));\r
-               refreshUsers.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               refreshUsers();\r
-                       }\r
-               });\r
-\r
-               JButton createUser = new JButton(Translation.get("gb.create"));\r
-               createUser.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               createUser();\r
-                       }\r
-               });\r
-\r
-               final JButton editUser = new JButton(Translation.get("gb.edit"));\r
-               editUser.setEnabled(false);\r
-               editUser.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               editUser(getSelectedUsers().get(0));\r
-                       }\r
-               });\r
-\r
-               final JButton delUser = new JButton(Translation.get("gb.delete"));\r
-               delUser.setEnabled(false);\r
-               delUser.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               deleteUsers(getSelectedUsers());\r
-                       }\r
-               });\r
-\r
-               NameRenderer nameRenderer = new NameRenderer();\r
-               usersModel = new UsersTableModel();\r
-               defaultUsersSorter = new TableRowSorter<UsersTableModel>(usersModel);\r
-               usersTable = Utils.newTable(usersModel, Utils.DATE_FORMAT);\r
-               String name = usersTable.getColumnName(UsersTableModel.Columns.Name.ordinal());\r
-               usersTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
-               usersTable.getColumn(name).setCellRenderer(nameRenderer);\r
-               usersTable.setRowSorter(defaultUsersSorter);\r
-               usersTable.getRowSorter().toggleSortOrder(UsersTableModel.Columns.Name.ordinal());\r
-               usersTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
-\r
-                       @Override\r
-                       public void valueChanged(ListSelectionEvent e) {\r
-                               if (e.getValueIsAdjusting()) {\r
-                                       return;\r
-                               }\r
-                               boolean selected = usersTable.getSelectedRow() > -1;\r
-                               boolean singleSelection = usersTable.getSelectedRows().length == 1;\r
-                               editUser.setEnabled(singleSelection && selected);\r
-                               delUser.setEnabled(selected);\r
-                       }\r
-               });\r
-\r
-               usersTable.addMouseListener(new MouseAdapter() {\r
-                       public void mouseClicked(MouseEvent e) {\r
-                               if (e.getClickCount() == 2) {\r
-                                       editUser(getSelectedUsers().get(0));\r
-                               }\r
-                       }\r
-               });\r
-\r
-               final JTextField userFilter = new JTextField();\r
-               userFilter.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               filterUsers(userFilter.getText());\r
-                       }\r
-               });\r
-               userFilter.addKeyListener(new KeyAdapter() {\r
-                       public void keyReleased(KeyEvent e) {\r
-                               filterUsers(userFilter.getText());\r
-                       }\r
-               });\r
-\r
-               JPanel userFilterPanel = new JPanel(new BorderLayout(margin, margin));\r
-               userFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);\r
-               userFilterPanel.add(userFilter, BorderLayout.CENTER);\r
-\r
-               JPanel userTablePanel = new JPanel(new BorderLayout(margin, margin));\r
-               userTablePanel.add(userFilterPanel, BorderLayout.NORTH);\r
-               userTablePanel.add(new JScrollPane(usersTable), BorderLayout.CENTER);\r
-\r
-               JPanel userControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
-               userControls.add(refreshUsers);\r
-               userControls.add(createUser);\r
-               userControls.add(editUser);\r
-               userControls.add(delUser);\r
-\r
-               JPanel usersPanel = new JPanel(new BorderLayout(margin, margin)) {\r
-\r
-                       private static final long serialVersionUID = 1L;\r
-\r
-                       public Insets getInsets() {\r
-                               return insets;\r
-                       }\r
-               };\r
-               usersHeader = new HeaderPanel(Translation.get("gb.users"), "user_16x16.png");\r
-               usersPanel.add(usersHeader, BorderLayout.NORTH);\r
-               usersPanel.add(userTablePanel, BorderLayout.CENTER);\r
-               usersPanel.add(userControls, BorderLayout.SOUTH);\r
-\r
+               usersPanel = new UsersPanel(gitblit);\r
                return usersPanel;\r
        }\r
 \r
        private JPanel createSettingsPanel() {\r
-               JButton refreshSettings = new JButton(Translation.get("gb.refresh"));\r
-               refreshSettings.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               refreshSettings();\r
-                       }\r
-               });\r
-\r
-               final JButton editSetting = new JButton(Translation.get("gb.edit"));\r
-               editSetting.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               int viewRow = settingsTable.getSelectedRow();\r
-                               int modelRow = settingsTable.convertRowIndexToModel(viewRow);\r
-                               String key = settingsModel.keys.get(modelRow);\r
-                               SettingModel setting = settingsModel.settings.get(key);\r
-                               editSetting(setting);\r
-                       }\r
-               });\r
-\r
-               NameRenderer nameRenderer = new NameRenderer();\r
-               final SettingPanel settingPanel = new SettingPanel();\r
-               settingsModel = new SettingsTableModel();\r
-               defaultSettingsSorter = new TableRowSorter<SettingsTableModel>(settingsModel);\r
-               settingsTable = Utils.newTable(settingsModel, Utils.DATE_FORMAT);\r
-               settingsTable.setDefaultRenderer(SettingModel.class, new SettingCellRenderer());\r
-               String name = settingsTable.getColumnName(UsersTableModel.Columns.Name.ordinal());\r
-               settingsTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
-               settingsTable.getColumn(name).setCellRenderer(nameRenderer);\r
-               settingsTable.setRowSorter(defaultSettingsSorter);\r
-               settingsTable.getRowSorter().toggleSortOrder(SettingsTableModel.Columns.Name.ordinal());\r
-               settingsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
-\r
-                       @Override\r
-                       public void valueChanged(ListSelectionEvent e) {\r
-                               if (e.getValueIsAdjusting()) {\r
-                                       return;\r
-                               }\r
-                               boolean singleSelection = settingsTable.getSelectedRows().length == 1;\r
-                               editSetting.setEnabled(singleSelection);\r
-                               if (singleSelection) {\r
-                                       int viewRow = settingsTable.getSelectedRow();\r
-                                       int modelRow = settingsTable.convertRowIndexToModel(viewRow);\r
-                                       SettingModel setting = settingsModel.get(modelRow);\r
-                                       settingPanel.setSetting(setting);\r
-                               } else {\r
-                                       settingPanel.clear();\r
-                               }\r
-                       }\r
-               });\r
-\r
-               final JTextField settingFilter = new JTextField();\r
-               settingFilter.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               filterSettings(settingFilter.getText());\r
-                       }\r
-               });\r
-               settingFilter.addKeyListener(new KeyAdapter() {\r
-                       public void keyReleased(KeyEvent e) {\r
-                               filterSettings(settingFilter.getText());\r
-                       }\r
-               });\r
-\r
-               JPanel settingFilterPanel = new JPanel(new BorderLayout(margin, margin));\r
-               settingFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);\r
-               settingFilterPanel.add(settingFilter, BorderLayout.CENTER);\r
-\r
-               JPanel settingsTablePanel = new JPanel(new BorderLayout(margin, margin));\r
-               settingsTablePanel.add(settingFilterPanel, BorderLayout.NORTH);\r
-               settingsTablePanel.add(new JScrollPane(settingsTable), BorderLayout.CENTER);\r
-               settingsTablePanel.add(settingPanel, BorderLayout.SOUTH);\r
-\r
-               JPanel settingsControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
-               settingsControls.add(refreshSettings);\r
-               settingsControls.add(editSetting);\r
-\r
-               JPanel settingsPanel = new JPanel(new BorderLayout(margin, margin)) {\r
-\r
-                       private static final long serialVersionUID = 1L;\r
-\r
-                       public Insets getInsets() {\r
-                               return insets;\r
-                       }\r
-               };\r
-               settingsHeader = new HeaderPanel(Translation.get("gb.settings"), "settings_16x16.png");\r
-               settingsPanel.add(settingsHeader, BorderLayout.NORTH);\r
-               settingsPanel.add(settingsTablePanel, BorderLayout.CENTER);\r
-               settingsPanel.add(settingsControls, BorderLayout.SOUTH);\r
-\r
+               settingsPanel = new SettingsPanel(gitblit);\r
                return settingsPanel;\r
        }\r
 \r
        private JPanel createStatusPanel() {\r
-               JButton refreshStatus = new JButton(Translation.get("gb.refresh"));\r
-               refreshStatus.addActionListener(new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               refreshStatus();\r
-                       }\r
-               });\r
-\r
-               JPanel controls = new JPanel();\r
-               controls.add(refreshStatus);\r
-\r
-               JPanel panel = new JPanel(new BorderLayout());\r
-               statusPanel = new StatusPanel();\r
-               panel.add(statusPanel, BorderLayout.CENTER);\r
-               panel.add(controls, BorderLayout.SOUTH);\r
-               return panel;\r
+               statusPanel = new StatusPanel(gitblit);\r
+               return statusPanel;\r
        }\r
 \r
        public void login() throws IOException {\r
                gitblit.login();\r
 \r
-               updateRepositoriesTable();\r
-               Utils.packColumns(repositoriesTable, 5);\r
-\r
-               updateFeedsTable();\r
-               Utils.packColumns(syndicationEntriesTable, 5);\r
+               repositoriesPanel.updateTable(true);\r
+               feedsPanel.updateTable(true);\r
 \r
                if (gitblit.allowManagement()) {\r
-                       updateUsersTable();\r
+                       usersPanel.updateTable(false);\r
                } else {\r
                        // user does not have administrator privileges\r
                        // hide admin repository buttons\r
-                       createRepository.setVisible(false);\r
-                       editRepository.setVisible(false);\r
-                       delRepository.setVisible(false);\r
+                       repositoriesPanel.disableManagement();\r
 \r
                        while (tabs.getTabCount() > 2) {\r
                                // remove all management/administration tabs\r
@@ -644,9 +142,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                }\r
 \r
                if (gitblit.allowAdministration()) {\r
-                       updateSettingsTable();\r
-                       updateStatusPanel();\r
-                       Utils.packColumns(settingsTable, 5);\r
+                       settingsPanel.updateTable(true);\r
+                       statusPanel.updateTable(false);\r
                } else {\r
                        // remove the settings tab\r
                        String[] titles = { Translation.get("gb.settings"), Translation.get("gb.status") };\r
@@ -661,124 +158,9 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                }\r
        }\r
 \r
-       private void updateRepositoriesTable() {\r
-               repositoriesModel.list.clear();\r
-               repositoriesModel.list.addAll(gitblit.getRepositories());\r
-               repositoriesModel.fireTableDataChanged();\r
-               repositoriesHeader.setText(Translation.get("gb.repositories") + " ("\r
-                               + gitblit.getRepositories().size() + ")");\r
-       }\r
-\r
-       private void updateFeedsTable() {\r
-               syndicationModel.entries.clear();\r
-               syndicationModel.entries.addAll(gitblit.getSyndicatedEntries());\r
-               syndicationModel.fireTableDataChanged();\r
-               feedsHeader.setText(Translation.get("gb.recentActivity") + " ("\r
-                               + gitblit.getSyndicatedEntries().size() + ")");\r
-       }\r
-\r
-       private void updateUsersTable() {\r
-               usersModel.list.clear();\r
-               usersModel.list.addAll(gitblit.getUsers());\r
-               usersModel.fireTableDataChanged();\r
-               usersHeader.setText(Translation.get("gb.users") + " (" + gitblit.getUsers().size() + ")");\r
-       }\r
-\r
-       private void updateSettingsTable() {\r
-               settingsModel.setSettings(gitblit.getSettings());\r
-               settingsModel.fireTableDataChanged();\r
-               settingsHeader.setText(Translation.get("gb.settings"));\r
-       }\r
-\r
-       private void updateStatusPanel() {\r
-               statusPanel.setStatus(gitblit.url, gitblit.getStatus());\r
-       }\r
-\r
-       private void filterRepositories(final String fragment) {\r
-               if (StringUtils.isEmpty(fragment)) {\r
-                       repositoriesTable.setRowSorter(defaultRepositoriesSorter);\r
-                       return;\r
-               }\r
-               RowFilter<RepositoriesTableModel, Object> containsFilter = new RowFilter<RepositoriesTableModel, Object>() {\r
-                       public boolean include(Entry<? extends RepositoriesTableModel, ? extends Object> entry) {\r
-                               for (int i = entry.getValueCount() - 1; i >= 0; i--) {\r
-                                       if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {\r
-                                               return true;\r
-                                       }\r
-                               }\r
-                               return false;\r
-                       }\r
-               };\r
-               TableRowSorter<RepositoriesTableModel> sorter = new TableRowSorter<RepositoriesTableModel>(\r
-                               repositoriesModel);\r
-               sorter.setRowFilter(containsFilter);\r
-               repositoriesTable.setRowSorter(sorter);\r
-       }\r
-\r
-       private void filterUsers(final String fragment) {\r
-               if (StringUtils.isEmpty(fragment)) {\r
-                       usersTable.setRowSorter(defaultUsersSorter);\r
-                       return;\r
-               }\r
-               RowFilter<UsersTableModel, Object> containsFilter = new RowFilter<UsersTableModel, Object>() {\r
-                       public boolean include(Entry<? extends UsersTableModel, ? extends Object> entry) {\r
-                               for (int i = entry.getValueCount() - 1; i >= 0; i--) {\r
-                                       if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {\r
-                                               return true;\r
-                                       }\r
-                               }\r
-                               return false;\r
-                       }\r
-               };\r
-               TableRowSorter<UsersTableModel> sorter = new TableRowSorter<UsersTableModel>(usersModel);\r
-               sorter.setRowFilter(containsFilter);\r
-               usersTable.setRowSorter(sorter);\r
-       }\r
-\r
-       private void filterSettings(final String fragment) {\r
-               if (StringUtils.isEmpty(fragment)) {\r
-                       settingsTable.setRowSorter(defaultSettingsSorter);\r
-                       return;\r
-               }\r
-               RowFilter<SettingsTableModel, Object> containsFilter = new RowFilter<SettingsTableModel, Object>() {\r
-                       public boolean include(Entry<? extends SettingsTableModel, ? extends Object> entry) {\r
-                               for (int i = entry.getValueCount() - 1; i >= 0; i--) {\r
-                                       if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {\r
-                                               return true;\r
-                                       }\r
-                               }\r
-                               return false;\r
-                       }\r
-               };\r
-               TableRowSorter<SettingsTableModel> sorter = new TableRowSorter<SettingsTableModel>(\r
-                               settingsModel);\r
-               sorter.setRowFilter(containsFilter);\r
-               settingsTable.setRowSorter(sorter);\r
-       }\r
-\r
-       private List<RepositoryModel> getSelectedRepositories() {\r
-               List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();\r
-               for (int viewRow : repositoriesTable.getSelectedRows()) {\r
-                       int modelRow = repositoriesTable.convertRowIndexToModel(viewRow);\r
-                       RepositoryModel model = repositoriesModel.list.get(modelRow);\r
-                       repositories.add(model);\r
-               }\r
-               return repositories;\r
-       }\r
-\r
-       private List<UserModel> getSelectedUsers() {\r
-               List<UserModel> users = new ArrayList<UserModel>();\r
-               for (int viewRow : usersTable.getSelectedRows()) {\r
-                       int modelRow = usersTable.convertRowIndexToModel(viewRow);\r
-                       UserModel model = usersModel.list.get(modelRow);\r
-                       users.add(model);\r
-               }\r
-               return users;\r
-       }\r
-\r
        @Override\r
        public Insets getInsets() {\r
-               return insets;\r
+               return Utils.INSETS;\r
        }\r
 \r
        @Override\r
@@ -786,158 +168,6 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                gitblit = null;\r
        }\r
 \r
-       protected void refreshRepositories() {\r
-               GitblitWorker worker = new GitblitWorker(GitblitPanel.this, RpcRequest.LIST_REPOSITORIES) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               gitblit.refreshRepositories();\r
-                               return true;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateRepositoriesTable();\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       /**\r
-        * Displays the create repository dialog and fires a SwingWorker to update\r
-        * the server, if appropriate.\r
-        * \r
-        */\r
-       protected void createRepository() {\r
-               EditRepositoryDialog dialog = new EditRepositoryDialog();\r
-               dialog.setLocationRelativeTo(GitblitPanel.this);\r
-               dialog.setUsers(null, gitblit.getUsernames(), null);\r
-               dialog.setRepositories(gitblit.getRepositories());\r
-               dialog.setFederationSets(gitblit.getFederationSets(), null);\r
-               dialog.setVisible(true);\r
-               final RepositoryModel newRepository = dialog.getRepository();\r
-               final List<String> permittedUsers = dialog.getPermittedUsers();\r
-               if (newRepository == null) {\r
-                       return;\r
-               }\r
-\r
-               GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_REPOSITORY) {\r
-\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               boolean success = gitblit.createRepository(newRepository, permittedUsers);\r
-                               if (success) {\r
-                                       gitblit.refreshRepositories();\r
-                                       if (permittedUsers.size() > 0) {\r
-                                               gitblit.refreshUsers();\r
-                                       }\r
-                               }\r
-                               return success;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateRepositoriesTable();\r
-                               updateUsersTable();\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onFailure() {\r
-                               showFailure("Failed to execute request \"{0}\" for repository \"{1}\".",\r
-                                               getRequestType(), newRepository.name);\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       /**\r
-        * Displays the edit repository dialog and fires a SwingWorker to update the\r
-        * server, if appropriate.\r
-        * \r
-        * @param repository\r
-        */\r
-       protected void editRepository(final RepositoryModel repository) {\r
-               EditRepositoryDialog dialog = new EditRepositoryDialog(repository);\r
-               dialog.setLocationRelativeTo(GitblitPanel.this);\r
-               List<String> usernames = gitblit.getUsernames();\r
-               List<String> members = gitblit.getPermittedUsernames(repository);\r
-               dialog.setUsers(repository.owner, usernames, members);\r
-               dialog.setRepositories(gitblit.getRepositories());\r
-               dialog.setFederationSets(gitblit.getFederationSets(), repository.federationSets);\r
-               dialog.setVisible(true);\r
-               final RepositoryModel revisedRepository = dialog.getRepository();\r
-               final List<String> permittedUsers = dialog.getPermittedUsers();\r
-               if (revisedRepository == null) {\r
-                       return;\r
-               }\r
-\r
-               GitblitWorker worker = new GitblitWorker(this, RpcRequest.EDIT_REPOSITORY) {\r
-\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               boolean success = gitblit.updateRepository(repository.name, revisedRepository,\r
-                                               permittedUsers);\r
-                               if (success) {\r
-                                       gitblit.refreshRepositories();\r
-                                       gitblit.refreshUsers();\r
-                               }\r
-                               return success;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateRepositoriesTable();\r
-                               updateUsersTable();\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onFailure() {\r
-                               showFailure("Failed to execute request \"{0}\" for repository \"{1}\".",\r
-                                               getRequestType(), repository.name);\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       protected void deleteRepositories(final List<RepositoryModel> repositories) {\r
-               if (repositories == null || repositories.size() == 0) {\r
-                       return;\r
-               }\r
-               StringBuilder message = new StringBuilder("Delete the following repositories?\n\n");\r
-               for (RepositoryModel repository : repositories) {\r
-                       message.append(repository.name).append("\n");\r
-               }\r
-               int result = JOptionPane.showConfirmDialog(GitblitPanel.this, message.toString(),\r
-                               "Delete Repositories?", JOptionPane.YES_NO_OPTION);\r
-               if (result == JOptionPane.YES_OPTION) {\r
-                       GitblitWorker worker = new GitblitWorker(this, RpcRequest.DELETE_REPOSITORY) {\r
-                               @Override\r
-                               protected Boolean doRequest() throws IOException {\r
-                                       boolean success = true;\r
-                                       for (RepositoryModel repository : repositories) {\r
-                                               success &= gitblit.deleteRepository(repository);\r
-                                       }\r
-                                       if (success) {\r
-                                               gitblit.refreshRepositories();\r
-                                               gitblit.refreshUsers();\r
-                                       }\r
-                                       return success;\r
-                               }\r
-\r
-                               @Override\r
-                               protected void onSuccess() {\r
-                                       updateRepositoriesTable();\r
-                                       updateUsersTable();\r
-                               }\r
-\r
-                               @Override\r
-                               protected void onFailure() {\r
-                                       showFailure("Failed to delete specified repositories!");\r
-                               }\r
-                       };\r
-                       worker.execute();\r
-               }\r
-       }\r
-\r
        protected void subscribeFeeds(final List<FeedModel> feeds) {\r
                SubscriptionsDialog dialog = new SubscriptionsDialog(feeds) {\r
 \r
@@ -948,274 +178,10 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
                                gitblit.updateSubscribedFeeds(feeds);\r
                                listener.saveRegistration(gitblit.reg.name, gitblit.reg);\r
                                setVisible(false);\r
-                               updateRepositoriesTable();\r
-                       }\r
-               };\r
-               dialog.setLocationRelativeTo(GitblitPanel.this);\r
-               dialog.setVisible(true);\r
-       }\r
-\r
-       protected void refreshFeeds() {\r
-               // TODO change request type here\r
-               GitblitWorker worker = new GitblitWorker(GitblitPanel.this, RpcRequest.LIST_USERS) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               gitblit.refreshSubscribedFeeds();\r
-                               return true;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateFeedsTable();\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       protected SyndicatedEntryModel getSelectedSyndicatedEntry() {\r
-               int viewRow = syndicationEntriesTable.getSelectedRow();\r
-               int modelRow = syndicationEntriesTable.convertRowIndexToModel(viewRow);\r
-               SyndicatedEntryModel entry = syndicationModel.get(modelRow);\r
-               return entry;\r
-       }\r
-\r
-       protected void viewCommit() {\r
-               SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
-               browse(entry.link);\r
-       }\r
-\r
-       protected void viewCommitDiff() {\r
-               SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
-               browse(entry.link.replace("/commit/", "/commitdiff/"));\r
-       }\r
-\r
-       protected void viewTree() {\r
-               SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
-               browse(entry.link.replace("/commit/", "/tree/"));\r
-       }\r
-\r
-       protected void browse(String url) {\r
-               try {\r
-                       Desktop.getDesktop().browse(new URI(url));\r
-               } catch (Exception x) {\r
-                       x.printStackTrace();\r
-               }\r
-       }\r
-\r
-       protected void refreshUsers() {\r
-               GitblitWorker worker = new GitblitWorker(GitblitPanel.this, RpcRequest.LIST_USERS) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               gitblit.refreshUsers();\r
-                               return true;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateUsersTable();\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       /**\r
-        * Displays the create user dialog and fires a SwingWorker to update the\r
-        * server, if appropriate.\r
-        * \r
-        */\r
-       protected void createUser() {\r
-               EditUserDialog dialog = new EditUserDialog(gitblit.getSettings());\r
-               dialog.setLocationRelativeTo(GitblitPanel.this);\r
-               dialog.setUsers(gitblit.getUsers());\r
-               dialog.setRepositories(gitblit.getRepositories(), null);\r
-               dialog.setVisible(true);\r
-               final UserModel newUser = dialog.getUser();\r
-               if (newUser == null) {\r
-                       return;\r
-               }\r
-\r
-               GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_USER) {\r
-\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               boolean success = gitblit.createUser(newUser);\r
-                               if (success) {\r
-                                       gitblit.refreshUsers();\r
-                               }\r
-                               return success;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateUsersTable();\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onFailure() {\r
-                               showFailure("Failed to execute request \"{0}\" for user \"{1}\".",\r
-                                               getRequestType(), newUser.username);\r
+                               repositoriesPanel.updateTable(false);\r
                        }\r
                };\r
-               worker.execute();\r
-       }\r
-\r
-       /**\r
-        * Displays the edit user dialog and fires a SwingWorker to update the\r
-        * server, if appropriate.\r
-        * \r
-        * @param user\r
-        */\r
-       protected void editUser(final UserModel user) {\r
-               EditUserDialog dialog = new EditUserDialog(user, gitblit.getSettings());\r
                dialog.setLocationRelativeTo(GitblitPanel.this);\r
-               dialog.setUsers(gitblit.getUsers());\r
-               dialog.setRepositories(gitblit.getRepositories(), new ArrayList<String>(user.repositories));\r
                dialog.setVisible(true);\r
-               final UserModel revisedUser = dialog.getUser();\r
-               if (revisedUser == null) {\r
-                       return;\r
-               }\r
-\r
-               GitblitWorker worker = new GitblitWorker(this, RpcRequest.EDIT_USER) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               boolean success = gitblit.updateUser(user.username, revisedUser);\r
-                               if (success) {\r
-                                       gitblit.refreshUsers();\r
-                               }\r
-                               return success;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateUsersTable();\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onFailure() {\r
-                               showFailure("Failed to execute request \"{0}\" for user \"{1}\".",\r
-                                               getRequestType(), user.username);\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       protected void deleteUsers(final List<UserModel> users) {\r
-               if (users == null || users.size() == 0) {\r
-                       return;\r
-               }\r
-               StringBuilder message = new StringBuilder("Delete the following users?\n\n");\r
-               for (UserModel user : users) {\r
-                       message.append(user.username).append("\n");\r
-               }\r
-               int result = JOptionPane.showConfirmDialog(GitblitPanel.this, message.toString(),\r
-                               "Delete Users?", JOptionPane.YES_NO_OPTION);\r
-               if (result == JOptionPane.YES_OPTION) {\r
-                       GitblitWorker worker = new GitblitWorker(this, RpcRequest.DELETE_USER) {\r
-                               @Override\r
-                               protected Boolean doRequest() throws IOException {\r
-                                       boolean success = true;\r
-                                       for (UserModel user : users) {\r
-                                               success &= gitblit.deleteUser(user);\r
-                                       }\r
-                                       if (success) {\r
-                                               gitblit.refreshUsers();\r
-                                       }\r
-                                       return success;\r
-                               }\r
-\r
-                               @Override\r
-                               protected void onSuccess() {\r
-                                       updateUsersTable();\r
-                               }\r
-\r
-                               @Override\r
-                               protected void onFailure() {\r
-                                       showFailure("Failed to delete specified users!");\r
-                               }\r
-                       };\r
-                       worker.execute();\r
-               }\r
-       }\r
-\r
-       protected void refreshSettings() {\r
-               GitblitWorker worker = new GitblitWorker(GitblitPanel.this, RpcRequest.LIST_SETTINGS) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               gitblit.refreshSettings();\r
-                               return true;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateSettingsTable();\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       protected void refreshStatus() {\r
-               GitblitWorker worker = new GitblitWorker(GitblitPanel.this, RpcRequest.LIST_STATUS) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               gitblit.refreshStatus();\r
-                               return true;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateStatusPanel();\r
-                       }\r
-               };\r
-               worker.execute();\r
-       }\r
-\r
-       protected void editSetting(final SettingModel settingModel) {\r
-               final JTextField textField = new JTextField(settingModel.currentValue);\r
-               JPanel editPanel = new JPanel(new GridLayout(0, 1));\r
-               editPanel.add(new JLabel("New Value"));\r
-               editPanel.add(textField);\r
-\r
-               JPanel settingPanel = new JPanel(new BorderLayout());\r
-               settingPanel.add(new SettingPanel(settingModel), BorderLayout.CENTER);\r
-               settingPanel.add(editPanel, BorderLayout.SOUTH);\r
-               settingPanel.setPreferredSize(new Dimension(800, 200));\r
-\r
-               String[] options;\r
-               if (settingModel.currentValue.equals(settingModel.defaultValue)) {\r
-                       options = new String[] { Translation.get("gb.cancel"), Translation.get("gb.save") };\r
-               } else {\r
-                       options = new String[] { Translation.get("gb.cancel"),\r
-                                       Translation.get("gb.setDefault"), Translation.get("gb.save") };\r
-               }\r
-               String defaultOption = options[0];\r
-               int selection = JOptionPane.showOptionDialog(GitblitPanel.this, settingPanel,\r
-                               settingModel.name, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,\r
-                               new ImageIcon(getClass().getResource("/settings_16x16.png")), options,\r
-                               defaultOption);\r
-               if (selection <= 0) {\r
-                       return;\r
-               }\r
-               if (options[selection].equals(Translation.get("gb.setDefault"))) {\r
-                       textField.setText(settingModel.defaultValue);\r
-               }\r
-               final Map<String, String> newSettings = new HashMap<String, String>();\r
-               newSettings.put(settingModel.name, textField.getText().trim());\r
-               GitblitWorker worker = new GitblitWorker(GitblitPanel.this, RpcRequest.EDIT_SETTINGS) {\r
-                       @Override\r
-                       protected Boolean doRequest() throws IOException {\r
-                               boolean success = gitblit.updateSettings(newSettings);\r
-                               if (success) {\r
-                                       gitblit.refreshSettings();\r
-                               }\r
-                               return success;\r
-                       }\r
-\r
-                       @Override\r
-                       protected void onSuccess() {\r
-                               updateSettingsTable();\r
-                       }\r
-               };\r
-               worker.execute();\r
        }\r
 }
\ No newline at end of file
diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java
new file mode 100644 (file)
index 0000000..1efc876
--- /dev/null
@@ -0,0 +1,454 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Color;\r
+import java.awt.FlowLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.KeyAdapter;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.io.IOException;\r
+import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.JTextField;\r
+import javax.swing.RowFilter;\r
+import javax.swing.SwingConstants;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+import javax.swing.table.DefaultTableCellRenderer;\r
+import javax.swing.table.TableCellRenderer;\r
+import javax.swing.table.TableRowSorter;\r
+\r
+import com.gitblit.Constants.RpcRequest;\r
+import com.gitblit.models.FeedModel;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * RSS Feeds Panel displays recent entries and launches the browser to view the\r
+ * commit. commitdiff, or tree of a commit.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public abstract class RepositoriesPanel extends JPanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final GitblitClient gitblit;\r
+\r
+       private HeaderPanel header;\r
+\r
+       private JTable table;\r
+\r
+       private RepositoriesTableModel tableModel;\r
+\r
+       private TableRowSorter<RepositoriesTableModel> defaultSorter;\r
+\r
+       private JButton createRepository;\r
+\r
+       private JButton editRepository;\r
+\r
+       private JButton delRepository;\r
+\r
+       private JTextField filterTextfield;\r
+\r
+       public RepositoriesPanel(GitblitClient gitblit) {\r
+               super();\r
+               this.gitblit = gitblit;\r
+               initialize();\r
+       }\r
+\r
+       private void initialize() {\r
+               final JButton browseRepository = new JButton(Translation.get("gb.browse"));\r
+               browseRepository.setEnabled(false);\r
+               browseRepository.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               RepositoryModel model = getSelectedRepositories().get(0);\r
+                               String u = MessageFormat.format("{0}/summary/{1}", gitblit.url,\r
+                                               StringUtils.encodeURL(model.name));\r
+                               Utils.browse(u);\r
+                       }\r
+               });\r
+\r
+               JButton refreshRepositories = new JButton(Translation.get("gb.refresh"));\r
+               refreshRepositories.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               refreshRepositories();\r
+                       }\r
+               });\r
+\r
+               createRepository = new JButton(Translation.get("gb.create"));\r
+               createRepository.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               createRepository();\r
+                       }\r
+               });\r
+\r
+               editRepository = new JButton(Translation.get("gb.edit"));\r
+               editRepository.setEnabled(false);\r
+               editRepository.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               editRepository(getSelectedRepositories().get(0));\r
+                       }\r
+               });\r
+\r
+               delRepository = new JButton(Translation.get("gb.delete"));\r
+               delRepository.setEnabled(false);\r
+               delRepository.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               deleteRepositories(getSelectedRepositories());\r
+                       }\r
+               });\r
+\r
+               final JButton subscribeRepository = new JButton(Translation.get("gb.subscribe") + "...");\r
+               subscribeRepository.setEnabled(false);\r
+               subscribeRepository.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               List<FeedModel> feeds = gitblit.getAvailableFeeds(getSelectedRepositories().get(0));\r
+                               subscribeFeeds(feeds);\r
+                       }\r
+               });\r
+\r
+               SubscribedRepositoryRenderer nameRenderer = new SubscribedRepositoryRenderer(gitblit);\r
+               IndicatorsRenderer typeRenderer = new IndicatorsRenderer();\r
+\r
+               DefaultTableCellRenderer sizeRenderer = new DefaultTableCellRenderer();\r
+               sizeRenderer.setHorizontalAlignment(SwingConstants.RIGHT);\r
+               sizeRenderer.setForeground(new Color(0, 0x80, 0));\r
+\r
+               DefaultTableCellRenderer ownerRenderer = new DefaultTableCellRenderer();\r
+               ownerRenderer.setForeground(Color.gray);\r
+               ownerRenderer.setHorizontalAlignment(SwingConstants.CENTER);\r
+\r
+               tableModel = new RepositoriesTableModel();\r
+               defaultSorter = new TableRowSorter<RepositoriesTableModel>(tableModel);\r
+               table = Utils.newTable(tableModel, Utils.DATE_FORMAT);\r
+               table.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+               table.setRowSorter(defaultSorter);\r
+               table.getRowSorter().toggleSortOrder(RepositoriesTableModel.Columns.Name.ordinal());\r
+\r
+               setRepositoryRenderer(RepositoriesTableModel.Columns.Name, nameRenderer, -1);\r
+               setRepositoryRenderer(RepositoriesTableModel.Columns.Indicators, typeRenderer, 100);\r
+               setRepositoryRenderer(RepositoriesTableModel.Columns.Owner, ownerRenderer, -1);\r
+               setRepositoryRenderer(RepositoriesTableModel.Columns.Size, sizeRenderer, 60);\r
+\r
+               table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+                       @Override\r
+                       public void valueChanged(ListSelectionEvent e) {\r
+                               if (e.getValueIsAdjusting()) {\r
+                                       return;\r
+                               }\r
+                               boolean singleSelection = table.getSelectedRowCount() == 1;\r
+                               boolean selected = table.getSelectedRow() > -1;\r
+                               browseRepository.setEnabled(singleSelection);\r
+                               delRepository.setEnabled(selected);\r
+                               subscribeRepository.setEnabled(singleSelection);\r
+                               if (selected) {\r
+                                       int viewRow = table.getSelectedRow();\r
+                                       int modelRow = table.convertRowIndexToModel(viewRow);\r
+                                       RepositoryModel model = ((RepositoriesTableModel) table.getModel()).list\r
+                                                       .get(modelRow);\r
+                                       editRepository.setEnabled(singleSelection\r
+                                                       && (gitblit.allowManagement() || gitblit.isOwner(model)));\r
+                               } else {\r
+                                       editRepository.setEnabled(false);\r
+                               }\r
+                       }\r
+               });\r
+\r
+               table.addMouseListener(new MouseAdapter() {\r
+                       public void mouseClicked(MouseEvent e) {\r
+                               if (e.getClickCount() == 2 && gitblit.allowManagement()) {\r
+                                       editRepository(getSelectedRepositories().get(0));\r
+                               }\r
+                       }\r
+               });\r
+\r
+               filterTextfield = new JTextField();\r
+               filterTextfield.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               filterRepositories(filterTextfield.getText());\r
+                       }\r
+               });\r
+               filterTextfield.addKeyListener(new KeyAdapter() {\r
+                       public void keyReleased(KeyEvent e) {\r
+                               filterRepositories(filterTextfield.getText());\r
+                       }\r
+               });\r
+\r
+               JPanel repositoryFilterPanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               repositoryFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);\r
+               repositoryFilterPanel.add(filterTextfield, BorderLayout.CENTER);\r
+\r
+               JPanel repositoryTablePanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               repositoryTablePanel.add(repositoryFilterPanel, BorderLayout.NORTH);\r
+               repositoryTablePanel.add(new JScrollPane(table), BorderLayout.CENTER);\r
+\r
+               JPanel repositoryControls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0));\r
+               repositoryControls.add(refreshRepositories);\r
+               repositoryControls.add(browseRepository);\r
+               repositoryControls.add(createRepository);\r
+               repositoryControls.add(editRepository);\r
+               repositoryControls.add(delRepository);\r
+               repositoryControls.add(subscribeRepository);\r
+\r
+               setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               header = new HeaderPanel(Translation.get("gb.repositories"), "gitweb-favicon.png");\r
+               add(header, BorderLayout.NORTH);\r
+               add(repositoryTablePanel, BorderLayout.CENTER);\r
+               add(repositoryControls, BorderLayout.SOUTH);\r
+       }\r
+\r
+       @Override\r
+       public void requestFocus() {\r
+               filterTextfield.requestFocus();\r
+       }\r
+\r
+       @Override\r
+       public Insets getInsets() {\r
+               return Utils.INSETS;\r
+       }\r
+\r
+       private void setRepositoryRenderer(RepositoriesTableModel.Columns col,\r
+                       TableCellRenderer renderer, int maxWidth) {\r
+               String name = table.getColumnName(col.ordinal());\r
+               table.getColumn(name).setCellRenderer(renderer);\r
+               if (maxWidth > 0) {\r
+                       table.getColumn(name).setMinWidth(maxWidth);\r
+                       table.getColumn(name).setMaxWidth(maxWidth);\r
+               }\r
+       }\r
+\r
+       protected abstract void subscribeFeeds(List<FeedModel> feeds);\r
+\r
+       protected abstract void updateUsersTable();\r
+\r
+       protected void disableManagement() {\r
+               createRepository.setVisible(false);\r
+               editRepository.setVisible(false);\r
+               delRepository.setVisible(false);\r
+       }\r
+\r
+       protected void updateTable(boolean pack) {\r
+               tableModel.list.clear();\r
+               tableModel.list.addAll(gitblit.getRepositories());\r
+               tableModel.fireTableDataChanged();\r
+               header.setText(Translation.get("gb.repositories") + " (" + gitblit.getRepositories().size()\r
+                               + ")");\r
+               if (pack) {\r
+                       Utils.packColumns(table, Utils.MARGIN);\r
+               }\r
+       }\r
+\r
+       private void filterRepositories(final String fragment) {\r
+               if (StringUtils.isEmpty(fragment)) {\r
+                       table.setRowSorter(defaultSorter);\r
+                       return;\r
+               }\r
+               RowFilter<RepositoriesTableModel, Object> containsFilter = new RowFilter<RepositoriesTableModel, Object>() {\r
+                       public boolean include(Entry<? extends RepositoriesTableModel, ? extends Object> entry) {\r
+                               for (int i = entry.getValueCount() - 1; i >= 0; i--) {\r
+                                       if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {\r
+                                               return true;\r
+                                       }\r
+                               }\r
+                               return false;\r
+                       }\r
+               };\r
+               TableRowSorter<RepositoriesTableModel> sorter = new TableRowSorter<RepositoriesTableModel>(\r
+                               tableModel);\r
+               sorter.setRowFilter(containsFilter);\r
+               table.setRowSorter(sorter);\r
+       }\r
+\r
+       private List<RepositoryModel> getSelectedRepositories() {\r
+               List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();\r
+               for (int viewRow : table.getSelectedRows()) {\r
+                       int modelRow = table.convertRowIndexToModel(viewRow);\r
+                       RepositoryModel model = tableModel.list.get(modelRow);\r
+                       repositories.add(model);\r
+               }\r
+               return repositories;\r
+       }\r
+\r
+       protected void refreshRepositories() {\r
+               GitblitWorker worker = new GitblitWorker(RepositoriesPanel.this,\r
+                               RpcRequest.LIST_REPOSITORIES) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               gitblit.refreshRepositories();\r
+                               return true;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       /**\r
+        * Displays the create repository dialog and fires a SwingWorker to update\r
+        * the server, if appropriate.\r
+        * \r
+        */\r
+       protected void createRepository() {\r
+               EditRepositoryDialog dialog = new EditRepositoryDialog();\r
+               dialog.setLocationRelativeTo(RepositoriesPanel.this);\r
+               dialog.setUsers(null, gitblit.getUsernames(), null);\r
+               dialog.setRepositories(gitblit.getRepositories());\r
+               dialog.setFederationSets(gitblit.getFederationSets(), null);\r
+               dialog.setVisible(true);\r
+               final RepositoryModel newRepository = dialog.getRepository();\r
+               final List<String> permittedUsers = dialog.getPermittedUsers();\r
+               if (newRepository == null) {\r
+                       return;\r
+               }\r
+\r
+               GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_REPOSITORY) {\r
+\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               boolean success = gitblit.createRepository(newRepository, permittedUsers);\r
+                               if (success) {\r
+                                       gitblit.refreshRepositories();\r
+                                       if (permittedUsers.size() > 0) {\r
+                                               gitblit.refreshUsers();\r
+                                       }\r
+                               }\r
+                               return success;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                               updateUsersTable();\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onFailure() {\r
+                               showFailure("Failed to execute request \"{0}\" for repository \"{1}\".",\r
+                                               getRequestType(), newRepository.name);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       /**\r
+        * Displays the edit repository dialog and fires a SwingWorker to update the\r
+        * server, if appropriate.\r
+        * \r
+        * @param repository\r
+        */\r
+       protected void editRepository(final RepositoryModel repository) {\r
+               EditRepositoryDialog dialog = new EditRepositoryDialog(repository);\r
+               dialog.setLocationRelativeTo(RepositoriesPanel.this);\r
+               List<String> usernames = gitblit.getUsernames();\r
+               List<String> members = gitblit.getPermittedUsernames(repository);\r
+               dialog.setUsers(repository.owner, usernames, members);\r
+               dialog.setRepositories(gitblit.getRepositories());\r
+               dialog.setFederationSets(gitblit.getFederationSets(), repository.federationSets);\r
+               dialog.setVisible(true);\r
+               final RepositoryModel revisedRepository = dialog.getRepository();\r
+               final List<String> permittedUsers = dialog.getPermittedUsers();\r
+               if (revisedRepository == null) {\r
+                       return;\r
+               }\r
+\r
+               GitblitWorker worker = new GitblitWorker(this, RpcRequest.EDIT_REPOSITORY) {\r
+\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               boolean success = gitblit.updateRepository(repository.name, revisedRepository,\r
+                                               permittedUsers);\r
+                               if (success) {\r
+                                       gitblit.refreshRepositories();\r
+                                       gitblit.refreshUsers();\r
+                               }\r
+                               return success;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                               updateUsersTable();\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onFailure() {\r
+                               showFailure("Failed to execute request \"{0}\" for repository \"{1}\".",\r
+                                               getRequestType(), repository.name);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       protected void deleteRepositories(final List<RepositoryModel> repositories) {\r
+               if (repositories == null || repositories.size() == 0) {\r
+                       return;\r
+               }\r
+               StringBuilder message = new StringBuilder("Delete the following repositories?\n\n");\r
+               for (RepositoryModel repository : repositories) {\r
+                       message.append(repository.name).append("\n");\r
+               }\r
+               int result = JOptionPane.showConfirmDialog(RepositoriesPanel.this, message.toString(),\r
+                               "Delete Repositories?", JOptionPane.YES_NO_OPTION);\r
+               if (result == JOptionPane.YES_OPTION) {\r
+                       GitblitWorker worker = new GitblitWorker(this, RpcRequest.DELETE_REPOSITORY) {\r
+                               @Override\r
+                               protected Boolean doRequest() throws IOException {\r
+                                       boolean success = true;\r
+                                       for (RepositoryModel repository : repositories) {\r
+                                               success &= gitblit.deleteRepository(repository);\r
+                                       }\r
+                                       if (success) {\r
+                                               gitblit.refreshRepositories();\r
+                                               gitblit.refreshUsers();\r
+                                       }\r
+                                       return success;\r
+                               }\r
+\r
+                               @Override\r
+                               protected void onSuccess() {\r
+                                       updateTable(false);\r
+                                       updateUsersTable();\r
+                               }\r
+\r
+                               @Override\r
+                               protected void onFailure() {\r
+                                       showFailure("Failed to delete specified repositories!");\r
+                               }\r
+                       };\r
+                       worker.execute();\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/src/com/gitblit/client/SettingsPanel.java b/src/com/gitblit/client/SettingsPanel.java
new file mode 100644 (file)
index 0000000..9591947
--- /dev/null
@@ -0,0 +1,275 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Dimension;\r
+import java.awt.FlowLayout;\r
+import java.awt.GridLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.KeyAdapter;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.io.IOException;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.JTextField;\r
+import javax.swing.RowFilter;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+import javax.swing.table.TableRowSorter;\r
+\r
+import com.gitblit.Constants.RpcRequest;\r
+import com.gitblit.models.SettingModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * Settings panel displays a list of server settings and their associated\r
+ * metadata. This panel also allows editing of a setting.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class SettingsPanel extends JPanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final GitblitClient gitblit;\r
+\r
+       private HeaderPanel header;\r
+\r
+       private JTable table;\r
+\r
+       private SettingsTableModel tableModel;\r
+\r
+       private TableRowSorter<SettingsTableModel> defaultSorter;\r
+\r
+       private JTextField filterTextfield;\r
+\r
+       public SettingsPanel(GitblitClient gitblit) {\r
+               super();\r
+               this.gitblit = gitblit;\r
+               initialize();\r
+       }\r
+\r
+       private void initialize() {\r
+               JButton refreshSettings = new JButton(Translation.get("gb.refresh"));\r
+               refreshSettings.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               refreshSettings();\r
+                       }\r
+               });\r
+\r
+               final JButton editSetting = new JButton(Translation.get("gb.edit"));\r
+               editSetting.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               int viewRow = table.getSelectedRow();\r
+                               int modelRow = table.convertRowIndexToModel(viewRow);\r
+                               String key = tableModel.keys.get(modelRow);\r
+                               SettingModel setting = tableModel.settings.get(key);\r
+                               editSetting(setting);\r
+                       }\r
+               });\r
+\r
+               NameRenderer nameRenderer = new NameRenderer();\r
+               final SettingPanel settingPanel = new SettingPanel();\r
+               tableModel = new SettingsTableModel();\r
+               defaultSorter = new TableRowSorter<SettingsTableModel>(tableModel);\r
+               table = Utils.newTable(tableModel, Utils.DATE_FORMAT);\r
+               table.setDefaultRenderer(SettingModel.class, new SettingCellRenderer());\r
+               String name = table.getColumnName(UsersTableModel.Columns.Name.ordinal());\r
+               table.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+               table.getColumn(name).setCellRenderer(nameRenderer);\r
+               table.setRowSorter(defaultSorter);\r
+               table.getRowSorter().toggleSortOrder(SettingsTableModel.Columns.Name.ordinal());\r
+               table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+\r
+                       @Override\r
+                       public void valueChanged(ListSelectionEvent e) {\r
+                               if (e.getValueIsAdjusting()) {\r
+                                       return;\r
+                               }\r
+                               boolean singleSelection = table.getSelectedRows().length == 1;\r
+                               editSetting.setEnabled(singleSelection);\r
+                               if (singleSelection) {\r
+                                       int viewRow = table.getSelectedRow();\r
+                                       int modelRow = table.convertRowIndexToModel(viewRow);\r
+                                       SettingModel setting = tableModel.get(modelRow);\r
+                                       settingPanel.setSetting(setting);\r
+                               } else {\r
+                                       settingPanel.clear();\r
+                               }\r
+                       }\r
+               });\r
+               table.addMouseListener(new MouseAdapter() {\r
+                       public void mouseClicked(MouseEvent e) {\r
+                               if (e.getClickCount() == 2) {\r
+                                       int viewRow = table.getSelectedRow();\r
+                                       int modelRow = table.convertRowIndexToModel(viewRow);\r
+                                       SettingModel setting = tableModel.get(modelRow);\r
+                                       editSetting(setting);\r
+                               }\r
+                       }\r
+               });\r
+\r
+               filterTextfield = new JTextField();\r
+               filterTextfield.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               filterSettings(filterTextfield.getText());\r
+                       }\r
+               });\r
+               filterTextfield.addKeyListener(new KeyAdapter() {\r
+                       public void keyReleased(KeyEvent e) {\r
+                               filterSettings(filterTextfield.getText());\r
+                       }\r
+               });\r
+\r
+               JPanel settingFilterPanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               settingFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);\r
+               settingFilterPanel.add(filterTextfield, BorderLayout.CENTER);\r
+\r
+               JPanel settingsTablePanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               settingsTablePanel.add(settingFilterPanel, BorderLayout.NORTH);\r
+               settingsTablePanel.add(new JScrollPane(table), BorderLayout.CENTER);\r
+               settingsTablePanel.add(settingPanel, BorderLayout.SOUTH);\r
+\r
+               JPanel settingsControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
+               settingsControls.add(refreshSettings);\r
+               settingsControls.add(editSetting);\r
+\r
+               setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               header = new HeaderPanel(Translation.get("gb.settings"), "settings_16x16.png");\r
+               add(header, BorderLayout.NORTH);\r
+               add(settingsTablePanel, BorderLayout.CENTER);\r
+               add(settingsControls, BorderLayout.SOUTH);\r
+       }\r
+       \r
+       @Override\r
+       public void requestFocus() {\r
+               filterTextfield.requestFocus();\r
+       }\r
+\r
+       @Override\r
+       public Insets getInsets() {\r
+               return Utils.INSETS;\r
+       }\r
+\r
+       protected void updateTable(boolean pack) {\r
+               tableModel.setSettings(gitblit.getSettings());\r
+               tableModel.fireTableDataChanged();\r
+               header.setText(Translation.get("gb.settings"));\r
+               if (pack) {\r
+                       Utils.packColumns(table, Utils.MARGIN);\r
+               }\r
+       }\r
+\r
+       private void filterSettings(final String fragment) {\r
+               if (StringUtils.isEmpty(fragment)) {\r
+                       table.setRowSorter(defaultSorter);\r
+                       return;\r
+               }\r
+               RowFilter<SettingsTableModel, Object> containsFilter = new RowFilter<SettingsTableModel, Object>() {\r
+                       public boolean include(Entry<? extends SettingsTableModel, ? extends Object> entry) {\r
+                               for (int i = entry.getValueCount() - 1; i >= 0; i--) {\r
+                                       if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {\r
+                                               return true;\r
+                                       }\r
+                               }\r
+                               return false;\r
+                       }\r
+               };\r
+               TableRowSorter<SettingsTableModel> sorter = new TableRowSorter<SettingsTableModel>(\r
+                               tableModel);\r
+               sorter.setRowFilter(containsFilter);\r
+               table.setRowSorter(sorter);\r
+       }\r
+\r
+       protected void refreshSettings() {\r
+               GitblitWorker worker = new GitblitWorker(SettingsPanel.this, RpcRequest.LIST_SETTINGS) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               gitblit.refreshSettings();\r
+                               return true;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       protected void editSetting(final SettingModel settingModel) {\r
+               final JTextField textField = new JTextField(settingModel.currentValue);\r
+               JPanel editPanel = new JPanel(new GridLayout(0, 1));\r
+               editPanel.add(new JLabel("New Value"));\r
+               editPanel.add(textField);\r
+\r
+               JPanel settingPanel = new JPanel(new BorderLayout());\r
+               settingPanel.add(new SettingPanel(settingModel), BorderLayout.CENTER);\r
+               settingPanel.add(editPanel, BorderLayout.SOUTH);\r
+               settingPanel.setPreferredSize(new Dimension(800, 200));\r
+\r
+               String[] options;\r
+               if (settingModel.currentValue.equals(settingModel.defaultValue)) {\r
+                       options = new String[] { Translation.get("gb.cancel"), Translation.get("gb.save") };\r
+               } else {\r
+                       options = new String[] { Translation.get("gb.cancel"),\r
+                                       Translation.get("gb.setDefault"), Translation.get("gb.save") };\r
+               }\r
+               String defaultOption = options[0];\r
+               int selection = JOptionPane.showOptionDialog(SettingsPanel.this, settingPanel,\r
+                               settingModel.name, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,\r
+                               new ImageIcon(getClass().getResource("/settings_16x16.png")), options,\r
+                               defaultOption);\r
+               if (selection <= 0) {\r
+                       return;\r
+               }\r
+               if (options[selection].equals(Translation.get("gb.setDefault"))) {\r
+                       textField.setText(settingModel.defaultValue);\r
+               }\r
+               final Map<String, String> newSettings = new HashMap<String, String>();\r
+               newSettings.put(settingModel.name, textField.getText().trim());\r
+               GitblitWorker worker = new GitblitWorker(SettingsPanel.this, RpcRequest.EDIT_SETTINGS) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               boolean success = gitblit.updateSettings(newSettings);\r
+                               if (success) {\r
+                                       gitblit.refreshSettings();\r
+                               }\r
+                               return success;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+}\r
index 797ae9b93caf0a8428339c4e2673e4ad46bb5dbb..669aa47a5ffe04328610d42a2789c24497c2609a 100644 (file)
@@ -21,13 +21,18 @@ import java.awt.FlowLayout;
 import java.awt.Font;\r
 import java.awt.GridLayout;\r
 import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.io.IOException;\r
 \r
+import javax.swing.JButton;\r
 import javax.swing.JLabel;\r
 import javax.swing.JPanel;\r
 import javax.swing.JScrollPane;\r
 import javax.swing.JTable;\r
 \r
 import com.gitblit.Constants;\r
+import com.gitblit.Constants.RpcRequest;\r
 import com.gitblit.models.ServerStatus;\r
 import com.gitblit.utils.ByteFormat;\r
 import com.gitblit.utils.TimeUtils;\r
@@ -40,29 +45,32 @@ import com.gitblit.utils.TimeUtils;
 public class StatusPanel extends JPanel {\r
 \r
        private static final long serialVersionUID = 1L;\r
-       private final Insets insets = new Insets(5, 5, 5, 5);\r
+       private final GitblitClient gitblit;\r
        private JLabel bootDate;\r
        private JLabel url;\r
        private JLabel servletContainer;\r
        private JLabel heapMaximum;\r
        private JLabel heapAllocated;\r
        private JLabel heapUsed;\r
-       private PropertiesTableModel model;\r
-       private HeaderPanel headerPanel;\r
+       private PropertiesTableModel tableModel;\r
+       private HeaderPanel header;\r
        private JLabel version;\r
        private JLabel releaseDate;\r
 \r
-       public StatusPanel() {\r
+       public StatusPanel(GitblitClient gitblit) {\r
                super();\r
+               this.gitblit = gitblit;\r
                initialize();\r
        }\r
 \r
-       public StatusPanel(String url, ServerStatus status) {\r
-               this();\r
-               setStatus(url, status);\r
-       }\r
-\r
        private void initialize() {\r
+               JButton refreshStatus = new JButton(Translation.get("gb.refresh"));\r
+               refreshStatus.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               refreshStatus();\r
+                       }\r
+               });\r
+\r
                version = new JLabel();\r
                releaseDate = new JLabel();\r
                bootDate = new JLabel();\r
@@ -73,13 +81,13 @@ public class StatusPanel extends JPanel {
                heapAllocated = new JLabel();\r
                heapUsed = new JLabel();\r
 \r
-               JPanel fieldsPanel = new JPanel(new GridLayout(0, 1, 0, 5)) {\r
+               JPanel fieldsPanel = new JPanel(new GridLayout(0, 1, 0, Utils.MARGIN)) {\r
 \r
                        private static final long serialVersionUID = 1L;\r
 \r
                        @Override\r
                        public Insets getInsets() {\r
-                               return insets;\r
+                               return Utils.INSETS;\r
                        }\r
                };\r
                fieldsPanel.add(createFieldPanel("gb.version", version));\r
@@ -91,8 +99,8 @@ public class StatusPanel extends JPanel {
                fieldsPanel.add(createFieldPanel("gb.heapAllocated", heapAllocated));\r
                fieldsPanel.add(createFieldPanel("gb.heapMaximum", heapMaximum));\r
 \r
-               model = new PropertiesTableModel();\r
-               JTable propertiesTable = Utils.newTable(model, Utils.DATE_FORMAT);\r
+               tableModel = new PropertiesTableModel();\r
+               JTable propertiesTable = Utils.newTable(tableModel, Utils.DATE_FORMAT);\r
                String name = propertiesTable.getColumnName(PropertiesTableModel.Columns.Name.ordinal());\r
                NameRenderer nameRenderer = new NameRenderer();\r
                propertiesTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
@@ -102,14 +110,18 @@ public class StatusPanel extends JPanel {
                centerPanel.add(fieldsPanel, BorderLayout.NORTH);\r
                centerPanel.add(new JScrollPane(propertiesTable), BorderLayout.CENTER);\r
 \r
-               headerPanel = new HeaderPanel(Translation.get("gb.status"), "health_16x16.png");\r
+               JPanel controls = new JPanel();\r
+               controls.add(refreshStatus);\r
+\r
+               header = new HeaderPanel(Translation.get("gb.status"), "health_16x16.png");\r
                setLayout(new BorderLayout());\r
-               add(headerPanel, BorderLayout.NORTH);\r
+               add(header, BorderLayout.NORTH);\r
                add(centerPanel, BorderLayout.CENTER);\r
+               add(controls, BorderLayout.SOUTH);\r
        }\r
 \r
        private JPanel createFieldPanel(String key, JLabel valueLabel) {\r
-               JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));\r
+               JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, Utils.MARGIN, 0));\r
                JLabel textLabel = new JLabel(Translation.get(key));\r
                textLabel.setFont(textLabel.getFont().deriveFont(Font.BOLD));\r
                textLabel.setPreferredSize(new Dimension(120, 10));\r
@@ -120,23 +132,40 @@ public class StatusPanel extends JPanel {
 \r
        @Override\r
        public Insets getInsets() {\r
-               return insets;\r
+               return Utils.INSETS;\r
+       }\r
+\r
+       protected void refreshStatus() {\r
+               GitblitWorker worker = new GitblitWorker(StatusPanel.this, RpcRequest.LIST_STATUS) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               gitblit.refreshStatus();\r
+                               return true;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
        }\r
 \r
-       public void setStatus(String url, ServerStatus status) {\r
-               headerPanel.setText(Translation.get("gb.status"));\r
+       protected void updateTable(boolean pack) {\r
+               ServerStatus status = gitblit.getStatus();\r
+               header.setText(Translation.get("gb.status"));\r
                version.setText(Constants.NAME + (status.isGO ? " GO v" : " WAR v") + status.version);\r
                releaseDate.setText(status.releaseDate);\r
                bootDate.setText(status.bootDate.toString() + " (" + TimeUtils.timeAgo(status.bootDate)\r
                                + ")");\r
-               this.url.setText(url);\r
+               url.setText(gitblit.url);\r
                servletContainer.setText(status.servletContainer);\r
                ByteFormat byteFormat = new ByteFormat();\r
                heapMaximum.setText(byteFormat.format(status.heapMaximum));\r
                heapAllocated.setText(byteFormat.format(status.heapAllocated));\r
                heapUsed.setText(byteFormat.format(status.heapAllocated - status.heapFree) + " ("\r
                                + byteFormat.format(status.heapFree) + " " + Translation.get("gb.free") + ")");\r
-               model.setProperties(status.systemProperties);\r
-               model.fireTableDataChanged();\r
+               tableModel.setProperties(status.systemProperties);\r
+               tableModel.fireTableDataChanged();\r
        }\r
 }\r
diff --git a/src/com/gitblit/client/UsersPanel.java b/src/com/gitblit/client/UsersPanel.java
new file mode 100644 (file)
index 0000000..5d31774
--- /dev/null
@@ -0,0 +1,356 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.FlowLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.KeyAdapter;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JLabel;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.JTextField;\r
+import javax.swing.RowFilter;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+import javax.swing.table.TableRowSorter;\r
+\r
+import com.gitblit.Constants.RpcRequest;\r
+import com.gitblit.models.UserModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * Users panel displays a list of user accounts and allows management of those\r
+ * accounts.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class UsersPanel extends JPanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private final GitblitClient gitblit;\r
+\r
+       private HeaderPanel header;\r
+\r
+       private JTable table;\r
+\r
+       private UsersTableModel tableModel;\r
+\r
+       private TableRowSorter<UsersTableModel> defaultSorter;\r
+\r
+       private JTextField filterTextfield;\r
+\r
+       public UsersPanel(GitblitClient gitblit) {\r
+               super();\r
+               this.gitblit = gitblit;\r
+               initialize();\r
+       }\r
+\r
+       private void initialize() {\r
+               JButton refreshUsers = new JButton(Translation.get("gb.refresh"));\r
+               refreshUsers.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               refreshUsers();\r
+                       }\r
+               });\r
+\r
+               JButton createUser = new JButton(Translation.get("gb.create"));\r
+               createUser.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               createUser();\r
+                       }\r
+               });\r
+\r
+               final JButton editUser = new JButton(Translation.get("gb.edit"));\r
+               editUser.setEnabled(false);\r
+               editUser.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               editUser(getSelectedUsers().get(0));\r
+                       }\r
+               });\r
+\r
+               final JButton delUser = new JButton(Translation.get("gb.delete"));\r
+               delUser.setEnabled(false);\r
+               delUser.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               deleteUsers(getSelectedUsers());\r
+                       }\r
+               });\r
+\r
+               NameRenderer nameRenderer = new NameRenderer();\r
+               tableModel = new UsersTableModel();\r
+               defaultSorter = new TableRowSorter<UsersTableModel>(tableModel);\r
+               table = Utils.newTable(tableModel, Utils.DATE_FORMAT);\r
+               String name = table.getColumnName(UsersTableModel.Columns.Name.ordinal());\r
+               table.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+               table.getColumn(name).setCellRenderer(nameRenderer);\r
+               table.setRowSorter(defaultSorter);\r
+               table.getRowSorter().toggleSortOrder(UsersTableModel.Columns.Name.ordinal());\r
+               table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+\r
+                       @Override\r
+                       public void valueChanged(ListSelectionEvent e) {\r
+                               if (e.getValueIsAdjusting()) {\r
+                                       return;\r
+                               }\r
+                               boolean selected = table.getSelectedRow() > -1;\r
+                               boolean singleSelection = table.getSelectedRows().length == 1;\r
+                               editUser.setEnabled(singleSelection && selected);\r
+                               delUser.setEnabled(selected);\r
+                       }\r
+               });\r
+\r
+               table.addMouseListener(new MouseAdapter() {\r
+                       public void mouseClicked(MouseEvent e) {\r
+                               if (e.getClickCount() == 2) {\r
+                                       editUser(getSelectedUsers().get(0));\r
+                               }\r
+                       }\r
+               });\r
+\r
+               filterTextfield = new JTextField();\r
+               filterTextfield.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               filterUsers(filterTextfield.getText());\r
+                       }\r
+               });\r
+               filterTextfield.addKeyListener(new KeyAdapter() {\r
+                       public void keyReleased(KeyEvent e) {\r
+                               filterUsers(filterTextfield.getText());\r
+                       }\r
+               });\r
+\r
+               JPanel userFilterPanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               userFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);\r
+               userFilterPanel.add(filterTextfield, BorderLayout.CENTER);\r
+\r
+               JPanel userTablePanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               userTablePanel.add(userFilterPanel, BorderLayout.NORTH);\r
+               userTablePanel.add(new JScrollPane(table), BorderLayout.CENTER);\r
+\r
+               JPanel userControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
+               userControls.add(refreshUsers);\r
+               userControls.add(createUser);\r
+               userControls.add(editUser);\r
+               userControls.add(delUser);\r
+\r
+               setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+               header = new HeaderPanel(Translation.get("gb.users"), "user_16x16.png");\r
+               add(header, BorderLayout.NORTH);\r
+               add(userTablePanel, BorderLayout.CENTER);\r
+               add(userControls, BorderLayout.SOUTH);\r
+       }\r
+       \r
+       @Override\r
+       public void requestFocus() {\r
+               filterTextfield.requestFocus();\r
+       }\r
+\r
+       @Override\r
+       public Insets getInsets() {\r
+               return Utils.INSETS;\r
+       }\r
+\r
+       protected void updateTable(boolean pack) {\r
+               tableModel.list.clear();\r
+               tableModel.list.addAll(gitblit.getUsers());\r
+               tableModel.fireTableDataChanged();\r
+               header.setText(Translation.get("gb.users") + " (" + gitblit.getUsers().size() + ")");\r
+               if (pack) {\r
+                       Utils.packColumns(table, Utils.MARGIN);\r
+               }\r
+       }\r
+\r
+       private void filterUsers(final String fragment) {\r
+               if (StringUtils.isEmpty(fragment)) {\r
+                       table.setRowSorter(defaultSorter);\r
+                       return;\r
+               }\r
+               RowFilter<UsersTableModel, Object> containsFilter = new RowFilter<UsersTableModel, Object>() {\r
+                       public boolean include(Entry<? extends UsersTableModel, ? extends Object> entry) {\r
+                               for (int i = entry.getValueCount() - 1; i >= 0; i--) {\r
+                                       if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {\r
+                                               return true;\r
+                                       }\r
+                               }\r
+                               return false;\r
+                       }\r
+               };\r
+               TableRowSorter<UsersTableModel> sorter = new TableRowSorter<UsersTableModel>(tableModel);\r
+               sorter.setRowFilter(containsFilter);\r
+               table.setRowSorter(sorter);\r
+       }\r
+\r
+       private List<UserModel> getSelectedUsers() {\r
+               List<UserModel> users = new ArrayList<UserModel>();\r
+               for (int viewRow : table.getSelectedRows()) {\r
+                       int modelRow = table.convertRowIndexToModel(viewRow);\r
+                       UserModel model = tableModel.list.get(modelRow);\r
+                       users.add(model);\r
+               }\r
+               return users;\r
+       }\r
+\r
+       protected void refreshUsers() {\r
+               GitblitWorker worker = new GitblitWorker(UsersPanel.this, RpcRequest.LIST_USERS) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               gitblit.refreshUsers();\r
+                               return true;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       /**\r
+        * Displays the create user dialog and fires a SwingWorker to update the\r
+        * server, if appropriate.\r
+        * \r
+        */\r
+       protected void createUser() {\r
+               EditUserDialog dialog = new EditUserDialog(gitblit.getSettings());\r
+               dialog.setLocationRelativeTo(UsersPanel.this);\r
+               dialog.setUsers(gitblit.getUsers());\r
+               dialog.setRepositories(gitblit.getRepositories(), null);\r
+               dialog.setVisible(true);\r
+               final UserModel newUser = dialog.getUser();\r
+               if (newUser == null) {\r
+                       return;\r
+               }\r
+\r
+               GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_USER) {\r
+\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               boolean success = gitblit.createUser(newUser);\r
+                               if (success) {\r
+                                       gitblit.refreshUsers();\r
+                               }\r
+                               return success;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onFailure() {\r
+                               showFailure("Failed to execute request \"{0}\" for user \"{1}\".",\r
+                                               getRequestType(), newUser.username);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       /**\r
+        * Displays the edit user dialog and fires a SwingWorker to update the\r
+        * server, if appropriate.\r
+        * \r
+        * @param user\r
+        */\r
+       protected void editUser(final UserModel user) {\r
+               EditUserDialog dialog = new EditUserDialog(user, gitblit.getSettings());\r
+               dialog.setLocationRelativeTo(UsersPanel.this);\r
+               dialog.setUsers(gitblit.getUsers());\r
+               dialog.setRepositories(gitblit.getRepositories(), new ArrayList<String>(user.repositories));\r
+               dialog.setVisible(true);\r
+               final UserModel revisedUser = dialog.getUser();\r
+               if (revisedUser == null) {\r
+                       return;\r
+               }\r
+\r
+               GitblitWorker worker = new GitblitWorker(this, RpcRequest.EDIT_USER) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               boolean success = gitblit.updateUser(user.username, revisedUser);\r
+                               if (success) {\r
+                                       gitblit.refreshUsers();\r
+                               }\r
+                               return success;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onFailure() {\r
+                               showFailure("Failed to execute request \"{0}\" for user \"{1}\".",\r
+                                               getRequestType(), user.username);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
+\r
+       protected void deleteUsers(final List<UserModel> users) {\r
+               if (users == null || users.size() == 0) {\r
+                       return;\r
+               }\r
+               StringBuilder message = new StringBuilder("Delete the following users?\n\n");\r
+               for (UserModel user : users) {\r
+                       message.append(user.username).append("\n");\r
+               }\r
+               int result = JOptionPane.showConfirmDialog(UsersPanel.this, message.toString(),\r
+                               "Delete Users?", JOptionPane.YES_NO_OPTION);\r
+               if (result == JOptionPane.YES_OPTION) {\r
+                       GitblitWorker worker = new GitblitWorker(this, RpcRequest.DELETE_USER) {\r
+                               @Override\r
+                               protected Boolean doRequest() throws IOException {\r
+                                       boolean success = true;\r
+                                       for (UserModel user : users) {\r
+                                               success &= gitblit.deleteUser(user);\r
+                                       }\r
+                                       if (success) {\r
+                                               gitblit.refreshUsers();\r
+                                       }\r
+                                       return success;\r
+                               }\r
+\r
+                               @Override\r
+                               protected void onSuccess() {\r
+                                       updateTable(false);\r
+                               }\r
+\r
+                               @Override\r
+                               protected void onFailure() {\r
+                                       showFailure("Failed to delete specified users!");\r
+                               }\r
+                       };\r
+                       worker.execute();\r
+               }\r
+       }\r
+}\r
index 1f44c32d094fdc00577691d5d0407354e3d19984..538e6be7414620e2b884a599c25d2d78555719dc 100644 (file)
@@ -17,10 +17,13 @@ package com.gitblit.client;
 \r
 import java.awt.Color;\r
 import java.awt.Component;\r
+import java.awt.Desktop;\r
 import java.awt.Dimension;\r
 import java.awt.Font;\r
+import java.awt.Insets;\r
 import java.io.PrintWriter;\r
 import java.io.StringWriter;\r
+import java.net.URI;\r
 import java.text.MessageFormat;\r
 import java.util.Date;\r
 \r
@@ -36,9 +39,13 @@ import javax.swing.table.TableModel;
 import com.gitblit.Constants.RpcRequest;\r
 \r
 public class Utils {\r
-       \r
+\r
+       public final static int MARGIN = 5;\r
+\r
+       public final static Insets INSETS = new Insets(MARGIN, MARGIN, MARGIN, MARGIN);\r
+\r
        public final static String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm";\r
-       \r
+\r
        public final static String DATE_FORMAT = "yyyy-MM-dd";\r
 \r
        public static JTable newTable(TableModel model, String datePattern) {\r
@@ -48,7 +55,8 @@ public class Utils {
                table.getTableHeader().setReorderingAllowed(false);\r
                table.setGridColor(new Color(0xd9d9d9));\r
                table.setBackground(Color.white);\r
-               table.setDefaultRenderer(Date.class, new DateCellRenderer(datePattern, Color.orange.darker()));\r
+               table.setDefaultRenderer(Date.class,\r
+                               new DateCellRenderer(datePattern, Color.orange.darker()));\r
                return table;\r
        }\r
 \r
@@ -131,4 +139,13 @@ public class Utils {
                // Set the width\r
                col.setPreferredWidth(width);\r
        }\r
+\r
+       public static void browse(String url) {\r
+               try {\r
+                       Desktop.getDesktop().browse(new URI(url));\r
+               } catch (Exception x) {\r
+                       showException(null, x);\r
+               }\r
+       }\r
+\r
 }\r
index 67cff9559565018aafdcaa4bda193a6355c69e8c..bed0a9cdf61f2773ad8475fcd1731a27d86f4cad 100644 (file)
@@ -68,7 +68,7 @@ public class FeedModel implements Serializable, Comparable<FeedModel> {
 \r
        @Override\r
        public int compareTo(FeedModel o) {\r
-               int repositoryCompare = repository.compareTo(o.repository);\r
+               int repositoryCompare = StringUtils.compareRepositoryNames(repository, o.repository);\r
                if (repositoryCompare == 0) {\r
                        // same repository\r
                        if (StringUtils.isEmpty(branch)) {\r
index 2237774eec99d546e0591cc7ff024c9d2bddef8e..6ea5f0e10571688e922836516fa9dbca383b448d 100644 (file)
@@ -24,8 +24,6 @@ import java.text.MessageFormat;
 import java.util.ArrayList;\r
 import java.util.List;\r
 \r
-import org.eclipse.jgit.revwalk.RevCommit;\r
-\r
 import com.gitblit.Constants;\r
 import com.gitblit.GitBlitException;\r
 import com.gitblit.models.SyndicatedEntryModel;\r
@@ -50,19 +48,20 @@ import com.sun.syndication.io.XmlReader;
 public class SyndicationUtils {\r
 \r
        /**\r
-        * Outputs an RSS feed of the list of commits to the outputstream.\r
+        * Outputs an RSS feed of the list of entries to the outputstream.\r
         * \r
         * @param hostUrl\r
         * @param title\r
         * @param description\r
         * @param repository\r
-        * @param commits\r
+        * @param entryModels\r
         * @param os\r
         * @throws IOException\r
         * @throws FeedException\r
         */\r
        public static void toRSS(String hostUrl, String title, String description, String repository,\r
-                       List<RevCommit> commits, OutputStream os) throws IOException, FeedException {\r
+                       List<SyndicatedEntryModel> entryModels, OutputStream os) throws IOException,\r
+                       FeedException {\r
 \r
                SyndFeed feed = new SyndFeedImpl();\r
                feed.setFeedType("rss_2.0");\r
@@ -78,17 +77,16 @@ public class SyndicationUtils {
                feed.setImage(image);\r
 \r
                List<SyndEntry> entries = new ArrayList<SyndEntry>();\r
-               for (RevCommit commit : commits) {\r
+               for (SyndicatedEntryModel entryModel : entryModels) {\r
                        SyndEntry entry = new SyndEntryImpl();\r
-                       entry.setTitle(commit.getShortMessage());\r
-                       entry.setAuthor(commit.getAuthorIdent().getName());\r
-                       entry.setLink(MessageFormat.format("{0}/commit/{1}/{2}", hostUrl,\r
-                                       StringUtils.encodeURL(repository), commit.getName()));\r
-                       entry.setPublishedDate(commit.getCommitterIdent().getWhen());\r
+                       entry.setTitle(entryModel.title);\r
+                       entry.setAuthor(entryModel.author);\r
+                       entry.setLink(entryModel.link);\r
+                       entry.setPublishedDate(entryModel.published);\r
 \r
                        SyndContent content = new SyndContentImpl();\r
-                       content.setType("text/plain");\r
-                       content.setValue(commit.getFullMessage());\r
+                       content.setType(entryModel.contentType);\r
+                       content.setValue(entryModel.content);\r
                        entry.setDescription(content);\r
                        entries.add(entry);\r
                }\r
index 6084b990d467aa8758d2efb9a1919d499059d3e6..9a977b2b2d97348cba6540cf7fd5988683ff8f03 100644 (file)
 package com.gitblit.tests;\r
 \r
 import java.io.ByteArrayOutputStream;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
 import java.util.List;\r
 \r
 import junit.framework.TestCase;\r
 \r
-import org.eclipse.jgit.lib.Repository;\r
-import org.eclipse.jgit.revwalk.RevCommit;\r
-\r
 import com.gitblit.models.SyndicatedEntryModel;\r
-import com.gitblit.utils.JGitUtils;\r
 import com.gitblit.utils.SyndicationUtils;\r
 \r
 public class SyndicationUtilsTest extends TestCase {\r
 \r
        public void testSyndication() throws Exception {\r
-               Repository repository = GitBlitSuite.getHelloworldRepository();\r
-               List<RevCommit> commits = JGitUtils.getRevLog(repository, 1);\r
+               List<SyndicatedEntryModel> entries = new ArrayList<SyndicatedEntryModel>();\r
+               for (int i = 0; i < 10; i++) {\r
+                       SyndicatedEntryModel entry = new SyndicatedEntryModel();\r
+                       entry.title = "Title " + i;\r
+                       entry.author = "Author " + i;\r
+                       entry.link = "Link " + i;\r
+                       entry.published = new Date();\r
+                       entry.contentType = "text/plain";\r
+                       entry.content = "Content " + i;\r
+                       entry.repository = "Repository " + i;\r
+                       entry.branch = "Branch " + i;\r
+                       entries.add(entry);\r
+               }\r
                ByteArrayOutputStream os = new ByteArrayOutputStream();\r
-               SyndicationUtils.toRSS("http://localhost", "Title", "Description", "Repository", commits,\r
+               SyndicationUtils.toRSS("http://localhost", "Title", "Description", "Repository", entries,\r
                                os);\r
                String feed = os.toString();\r
                os.close();\r
-               assertTrue(feed.length() > 100);\r
                assertTrue(feed.indexOf("<title>Title</title>") > -1);\r
                assertTrue(feed.indexOf("<description>Description</description>") > -1);\r
        }\r