}\r
result = repositories;\r
} else if (RpcRequest.LIST_BRANCHES.equals(reqType)) {\r
- // list all branches in all repositories accessible to user\r
- Map<String, List<String>> allBranches = new HashMap<String, List<String>>();\r
+ // list all local branches in all repositories accessible to user\r
+ Map<String, List<String>> localBranches = new HashMap<String, List<String>>();\r
List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user);\r
for (RepositoryModel model : models) {\r
if (!model.hasCommits) {\r
// skip empty repository\r
continue;\r
}\r
- // get branches\r
+ // get local branches\r
Repository repository = GitBlit.self().getRepository(model.name);\r
List<RefModel> refs = JGitUtils.getLocalBranches(repository, false, -1);\r
- refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1));\r
+ if (model.showRemoteBranches) {\r
+ // add remote branches if repository displays them\r
+ refs.addAll(JGitUtils.getRemoteBranches(repository, false, -1));\r
+ }\r
if (refs.size() > 0) {\r
List<String> branches = new ArrayList<String>();\r
for (RefModel ref : refs) {\r
branches.add(ref.getName());\r
}\r
- allBranches.put(model.name, branches);\r
+ localBranches.put(model.name, branches);\r
}\r
repository.close();\r
}\r
- result = allBranches;\r
+ result = localBranches;\r
} else if (RpcRequest.LIST_USERS.equals(reqType)) {\r
// list users\r
List<String> names = GitBlit.self().getAllUsernames();\r
"46a386136c901748e6a3af67ebde6c22bc6b4524",\r
"e223571d77769cdafde59040da235842f3326453");\r
\r
- public static final MavenObject SLF4JNOP = new MavenObject("SLF4J NOP", "org/slf4j",\r
- "slf4j-nop", "1.6.1", 4800, 4100, 32300,\r
- "70249094d4e5653b6bdfea46f3a1a4165c1e1993",\r
- "4a8e77f7bf6897a3c3b7fc3acb4c862dfb905baa",\r
- "24b2b46f9025f2db53b5b32143f7832538fa3178");\r
-\r
public static final MavenObject SLF4LOG4J = new MavenObject("SLF4J LOG4J", "org/slf4j",\r
"slf4j-log4j12", "1.6.1", 9800, 9500, 52400,\r
"bd245d6746cdd4e6203e976e21d597a46f115802",\r
--- /dev/null
+/*\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.Component;\r
+import java.io.Serializable;\r
+\r
+import javax.swing.JCheckBox;\r
+import javax.swing.JTable;\r
+import javax.swing.SwingConstants;\r
+import javax.swing.table.TableCellRenderer;\r
+\r
+/**\r
+ * Boolean checkbox cell renderer.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class BooleanCellRenderer extends JCheckBox implements TableCellRenderer, Serializable {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public BooleanCellRenderer() {\r
+ super();\r
+ setOpaque(false);\r
+ setHorizontalAlignment(SwingConstants.CENTER);\r
+ }\r
+\r
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,\r
+ boolean hasFocus, int row, int column) {\r
+ if (value instanceof Boolean) {\r
+ boolean checked = (Boolean) value;\r
+ this.setSelected(checked);\r
+ }\r
+ return this;\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/*\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.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import javax.swing.table.AbstractTableModel;\r
+\r
+import com.gitblit.models.FeedModel;\r
+\r
+/**\r
+ * Table model of a list of available feeds.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class FeedsTableModel extends AbstractTableModel {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ List<FeedModel> list;\r
+\r
+ enum Columns {\r
+ Subscribed, Repository, Branch, Max_Length;\r
+\r
+ @Override\r
+ public String toString() {\r
+ return name().replace('_', ' ');\r
+ }\r
+ }\r
+\r
+ public FeedsTableModel() {\r
+ this(new ArrayList<FeedModel>());\r
+ }\r
+\r
+ public FeedsTableModel(List<FeedModel> feeds) {\r
+ this.list = feeds;\r
+ Collections.sort(this.list);\r
+ }\r
+\r
+ @Override\r
+ public int getRowCount() {\r
+ return list.size();\r
+ }\r
+\r
+ @Override\r
+ public int getColumnCount() {\r
+ return Columns.values().length;\r
+ }\r
+\r
+ @Override\r
+ public String getColumnName(int column) {\r
+ Columns col = Columns.values()[column];\r
+ switch (col) {\r
+ case Repository:\r
+ return Translation.get("gb.repository");\r
+ case Branch:\r
+ return Translation.get("gb.branch");\r
+ }\r
+ return "";\r
+ }\r
+\r
+ /**\r
+ * Returns <code>Object.class</code> regardless of <code>columnIndex</code>.\r
+ * \r
+ * @param columnIndex\r
+ * the column being queried\r
+ * @return the Object.class\r
+ */\r
+ public Class<?> getColumnClass(int columnIndex) {\r
+ Columns col = Columns.values()[columnIndex];\r
+ switch (col) {\r
+ case Subscribed:\r
+ return Boolean.class;\r
+ case Max_Length:\r
+ return Integer.class;\r
+ }\r
+ return String.class;\r
+ }\r
+\r
+ @Override\r
+ public boolean isCellEditable(int rowIndex, int columnIndex) {\r
+ Columns col = Columns.values()[columnIndex];\r
+ switch (col) {\r
+ case Subscribed:\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public Object getValueAt(int rowIndex, int columnIndex) {\r
+ FeedModel model = list.get(rowIndex);\r
+ Columns col = Columns.values()[columnIndex];\r
+ switch (col) {\r
+ case Repository:\r
+ 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
+ return null;\r
+ }\r
+\r
+ public FeedModel get(int modelRow) {\r
+ return list.get(modelRow);\r
+ }\r
+}\r
import java.io.Serializable;\r
import java.util.ArrayList;\r
import java.util.Collections;\r
+import java.util.Date;\r
import java.util.HashSet;\r
import java.util.List;\r
import java.util.Map;\r
import com.gitblit.GitBlitException.UnknownRequestException;\r
import com.gitblit.Keys;\r
import com.gitblit.models.FederationModel;\r
+import com.gitblit.models.FeedModel;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.ServerSettings;\r
import com.gitblit.models.ServerStatus;\r
import com.gitblit.models.SyndicatedEntryModel;\r
import com.gitblit.models.UserModel;\r
import com.gitblit.utils.RpcUtils;\r
-import com.gitblit.utils.StringUtils;\r
import com.gitblit.utils.SyndicationUtils;\r
\r
/**\r
\r
private final List<FederationModel> federationRegistrations;\r
\r
+ private final List<FeedModel> availableFeeds;\r
+\r
private final List<SyndicatedEntryModel> syndicatedEntries;\r
\r
+ private final Set<String> subscribedRepositories;\r
+\r
private ServerStatus status;\r
\r
public GitblitClient(GitblitRegistration reg) {\r
this.allUsers = new ArrayList<UserModel>();\r
this.allRepositories = new ArrayList<RepositoryModel>();\r
this.federationRegistrations = new ArrayList<FederationModel>();\r
+ this.availableFeeds = new ArrayList<FeedModel>();\r
this.syndicatedEntries = new ArrayList<SyndicatedEntryModel>();\r
+ this.subscribedRepositories = new HashSet<String>();\r
}\r
\r
public void login() throws IOException {\r
+ refreshAvailableFeeds();\r
refreshRepositories();\r
\r
try {\r
} catch (IOException e) {\r
e.printStackTrace();\r
}\r
- \r
+\r
try {\r
// credentials may not have administrator access\r
// or server may have disabled rpc management\r
allRepositories.clear();\r
allRepositories.addAll(repositories.values());\r
Collections.sort(allRepositories);\r
- updateSubscribedStates();\r
+ markSubscribedFeeds();\r
return allRepositories;\r
}\r
\r
return status;\r
}\r
\r
- public List<SyndicatedEntryModel> refreshSubscribedFeeds() throws IOException {\r
- Set<SyndicatedEntryModel> allFeeds = new HashSet<SyndicatedEntryModel>();\r
- if (reg.feeds != null && reg.feeds.size() > 0) {\r
- for (String feed : reg.feeds) {\r
- String[] values = feed.split(":");\r
- String repository = values[0];\r
- String branch = null;\r
- if (values.length > 1) {\r
- branch = values[1];\r
- }\r
- List<SyndicatedEntryModel> list = SyndicationUtils.readFeed(url, repository,\r
- branch, -1, account, password);\r
- allFeeds.addAll(list);\r
- }\r
- }\r
- syndicatedEntries.clear();\r
- syndicatedEntries.addAll(allFeeds);\r
- Collections.sort(syndicatedEntries);\r
- return syndicatedEntries;\r
+ public List<FeedModel> getAvailableFeeds() {\r
+ return availableFeeds;\r
}\r
\r
- private void updateSubscribedStates() {\r
- if (reg.feeds != null) {\r
- Set<String> subscribedRepositories = new HashSet<String>();\r
- for (String feed : reg.feeds) {\r
- if (feed.indexOf(':') > -1) {\r
- // strip branch\r
- subscribedRepositories.add(feed.substring(0, feed.indexOf(':')).toLowerCase());\r
- } else {\r
- // default branch\r
- subscribedRepositories.add(feed.toLowerCase());\r
- }\r
- }\r
- // set subscribed flag\r
- for (RepositoryModel repository : allRepositories) {\r
- repository.subscribed = subscribedRepositories.contains(repository.name\r
- .toLowerCase());\r
+ public List<FeedModel> getAvailableFeeds(RepositoryModel repository) {\r
+ List<FeedModel> repositoryFeeds = new ArrayList<FeedModel>();\r
+ if (repository == null) {\r
+ return repositoryFeeds;\r
+ }\r
+ for (FeedModel feed : availableFeeds) {\r
+ if (feed.repository.equalsIgnoreCase(repository.name)) {\r
+ repositoryFeeds.add(feed);\r
}\r
}\r
+ return repositoryFeeds;\r
}\r
\r
- public List<SyndicatedEntryModel> getSyndicatedEntries() {\r
- return syndicatedEntries;\r
+ public List<FeedModel> refreshAvailableFeeds() throws IOException {\r
+ List<FeedModel> feeds = RpcUtils.getBranchFeeds(url, account, password);\r
+ availableFeeds.clear();\r
+ availableFeeds.addAll(feeds);\r
+ markSubscribedFeeds();\r
+ return availableFeeds;\r
}\r
\r
- public boolean isSubscribed(RepositoryModel repository, String branch) {\r
- if (reg.feeds != null && reg.feeds.size() > 0) {\r
- for (String feed : reg.feeds) {\r
- String[] values = feed.split(":");\r
- String repositoryName = values[0];\r
- if (repository.name.equalsIgnoreCase(repositoryName)) {\r
- return true;\r
- }\r
- // TODO check branch subscriptions\r
- String branchName = null;\r
- if (values.length > 1) {\r
- branchName = values[1];\r
- }\r
+ public List<SyndicatedEntryModel> refreshSubscribedFeeds() throws IOException {\r
+ Set<SyndicatedEntryModel> allEntries = new HashSet<SyndicatedEntryModel>();\r
+ if (reg.feeds.size() > 0) {\r
+ for (FeedModel feed : reg.feeds) {\r
+ feed.lastRefresh = new Date();\r
+ List<SyndicatedEntryModel> entries = SyndicationUtils.readFeed(url,\r
+ feed.repository, feed.branch, feed.maxRetrieval, account, password);\r
+ allEntries.addAll(entries);\r
}\r
}\r
- return false;\r
+ syndicatedEntries.clear();\r
+ syndicatedEntries.addAll(allEntries);\r
+ Collections.sort(syndicatedEntries);\r
+ return syndicatedEntries;\r
}\r
\r
- public boolean subscribe(RepositoryModel repository, String branch) {\r
- String feed = repository.name;\r
- if (!StringUtils.isEmpty(branch)) {\r
- feed += ":" + branch;\r
- }\r
- if (reg.feeds == null) {\r
- reg.feeds = new ArrayList<String>();\r
- }\r
- reg.feeds.add(feed);\r
- updateSubscribedStates();\r
- return true;\r
+ public void updateSubscribedFeeds(List<FeedModel> list) {\r
+ reg.updateSubscribedFeeds(list);\r
+ markSubscribedFeeds();\r
}\r
\r
- public boolean unsubscribe(RepositoryModel repository, String branch) {\r
- String feed = repository.name;\r
- if (!StringUtils.isEmpty(branch)) {\r
- feed += ":" + branch;\r
- }\r
- reg.feeds.remove(feed);\r
- if (syndicatedEntries.size() > 0) {\r
- List<SyndicatedEntryModel> toRemove = new ArrayList<SyndicatedEntryModel>();\r
- for (SyndicatedEntryModel model : syndicatedEntries) {\r
- if (model.repository.equalsIgnoreCase(repository.name)) {\r
- boolean emptyUnsubscribeBranch = StringUtils.isEmpty(branch);\r
- boolean emptyFromBranch = StringUtils.isEmpty(model.branch);\r
- if (emptyUnsubscribeBranch && emptyFromBranch) {\r
- // default branch, remove\r
- toRemove.add(model);\r
- } else if (!emptyUnsubscribeBranch && !emptyFromBranch) {\r
- if (model.branch.equals(branch)) {\r
- // specific branch, remove\r
- toRemove.add(model);\r
- }\r
- }\r
- }\r
+ private void markSubscribedFeeds() {\r
+ subscribedRepositories.clear();\r
+ for (FeedModel feed : availableFeeds) {\r
+ // mark feed in the available list as subscribed\r
+ feed.subscribed = reg.feeds.contains(feed);\r
+ if (feed.subscribed) {\r
+ subscribedRepositories.add(feed.repository.toLowerCase());\r
}\r
}\r
- updateSubscribedStates();\r
- return true;\r
+ }\r
+\r
+ public boolean isSubscribed(RepositoryModel repository) {\r
+ return subscribedRepositories.contains(repository.name.toLowerCase());\r
+ }\r
+\r
+ public List<SyndicatedEntryModel> getSyndicatedEntries() {\r
+ return syndicatedEntries;\r
}\r
\r
public List<FederationModel> refreshFederationRegistrations() throws IOException {\r
import java.text.MessageFormat;\r
import java.text.SimpleDateFormat;\r
import java.util.ArrayList;\r
-import java.util.Arrays;\r
import java.util.Collections;\r
import java.util.Comparator;\r
import java.util.Date;\r
\r
import com.gitblit.Constants;\r
import com.gitblit.GitBlitException.ForbiddenException;\r
+import com.gitblit.models.FeedModel;\r
import com.gitblit.utils.StringUtils;\r
\r
/**\r
return;\r
}\r
// preserve feeds\r
- newReg.feeds = reg.feeds;\r
- \r
+ newReg.feeds.addAll(reg.feeds);\r
+\r
// use new reg\r
reg = newReg;\r
}\r
GitblitRegistration reg = new GitblitRegistration(server, url, account, password);\r
String[] feeds = config.getStringList("servers", server, "feeds");\r
if (feeds != null) {\r
- reg.feeds = new ArrayList<String>(Arrays.asList(feeds));\r
+ // deserialize the field definitions\r
+ for (String definition : feeds) {\r
+ FeedModel feed = new FeedModel(definition);\r
+ reg.feeds.add(feed);\r
+ }\r
}\r
reg.lastLogin = lastLogin;\r
registrations.put(reg.name, reg);\r
if (reg.lastLogin != null) {\r
config.setString("servers", reg.name, "lastLogin", dateFormat.format(reg.lastLogin));\r
}\r
- if (reg.feeds != null) {\r
- config.setStringList("servers", reg.name, "feeds", reg.feeds);\r
+ // serialize the feed definitions\r
+ List<String> definitions = new ArrayList<String>();\r
+ for (FeedModel feed : reg.feeds) {\r
+ definitions.add(feed.toString());\r
+ }\r
+ if (definitions.size() > 0) {\r
+ config.setStringList("servers", reg.name, "feeds", definitions);\r
}\r
config.save();\r
return true;\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
\r
tabs = new JTabbedPane(JTabbedPane.BOTTOM);\r
tabs.addTab(Translation.get("gb.repositories"), createRepositoriesPanel());\r
- tabs.addTab(Translation.get("gb.recentCommits"), createFeedsPanel());\r
+ tabs.addTab(Translation.get("gb.recentActivity"), createFeedsPanel());\r
tabs.addTab(Translation.get("gb.users"), createUsersPanel());\r
tabs.addTab(Translation.get("gb.settings"), createSettingsPanel());\r
tabs.addTab(Translation.get("gb.status"), createStatusPanel());\r
subscribeRepository.setEnabled(false);\r
subscribeRepository.addActionListener(new ActionListener() {\r
public void actionPerformed(ActionEvent e) {\r
- subscribeRepository(getSelectedRepositories().get(0));\r
+ List<FeedModel> feeds = gitblit.getAvailableFeeds(getSelectedRepositories().get(0));\r
+ subscribeFeeds(feeds);\r
}\r
});\r
\r
- NameRenderer nameRenderer = new NameRenderer(true);\r
+ SubscribedRepositoryRenderer nameRenderer = new SubscribedRepositoryRenderer(gitblit);\r
IndicatorsRenderer typeRenderer = new IndicatorsRenderer();\r
\r
DefaultTableCellRenderer sizeRenderer = new DefaultTableCellRenderer();\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.recentCommits"), "feed_16x16.png");\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
syndicationModel.entries.clear();\r
syndicationModel.entries.addAll(gitblit.getSyndicatedEntries());\r
syndicationModel.fireTableDataChanged();\r
- feedsHeader.setText(Translation.get("gb.recentCommits") + " ("\r
+ feedsHeader.setText(Translation.get("gb.recentActivity") + " ("\r
+ gitblit.getSyndicatedEntries().size() + ")");\r
}\r
\r
}\r
}\r
\r
- protected void subscribeRepository(final RepositoryModel repository) {\r
- if (repository == null) {\r
- return;\r
- }\r
- // TODO this is lame. need better ui.\r
- if (gitblit.isSubscribed(repository, null)) {\r
- // unsubscribe\r
- String msg = MessageFormat.format("Do you want to unsubscribe from {0}?",\r
- repository.name);\r
- String[] options = { "no", "yes" };\r
- int result = JOptionPane.showOptionDialog(GitblitPanel.this, msg, "Unsubscribe?",\r
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options,\r
- options[0]);\r
- if (result == 1) {\r
- if (gitblit.unsubscribe(repository, null)) {\r
- updateFeedsTable();\r
- updateRepositoriesTable();\r
- listener.saveRegistration(repository.name, gitblit.reg);\r
- }\r
- }\r
- } else {\r
- // subscribe\r
- String msg = MessageFormat.format("Do you want to subscribe to {0}?", repository.name);\r
- String[] options = { "no", "yes" };\r
- int result = JOptionPane.showOptionDialog(GitblitPanel.this, msg, "Subscribe?",\r
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options,\r
- options[0]);\r
- if (result == 1) {\r
- if (gitblit.subscribe(repository, null)) {\r
- updateRepositoriesTable();\r
- listener.saveRegistration(repository.name, gitblit.reg);\r
- }\r
+ protected void subscribeFeeds(final List<FeedModel> feeds) {\r
+ SubscriptionsDialog dialog = new SubscriptionsDialog(feeds) {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ @Override\r
+ public void save() {\r
+ gitblit.updateSubscribedFeeds(feeds);\r
+ listener.saveRegistration(gitblit.reg.name, gitblit.reg);\r
+ setVisible(false);\r
+ updateRepositoriesTable();\r
}\r
- }\r
+ };\r
+ dialog.setLocationRelativeTo(GitblitPanel.this);\r
+ dialog.setVisible(true);\r
}\r
\r
protected void refreshFeeds() {\r
package com.gitblit.client;\r
\r
import java.io.Serializable;\r
+import java.util.ArrayList;\r
import java.util.Date;\r
import java.util.List;\r
\r
+import com.gitblit.models.FeedModel;\r
import com.gitblit.utils.StringUtils;\r
\r
/**\r
char[] password;\r
boolean savePassword;\r
Date lastLogin;\r
- List<String> feeds;\r
+ final List<FeedModel> feeds;\r
\r
public GitblitRegistration(String name, String url, String account, char[] password) {\r
this.url = url;\r
} else {\r
this.name = name;\r
}\r
+ feeds = new ArrayList<FeedModel>();\r
+ }\r
+\r
+ public void updateSubscribedFeeds(List<FeedModel> list) {\r
+ for (FeedModel feed : list) {\r
+ if (feeds.contains(feed)) {\r
+ // possibly unsubscribe/remove feed\r
+ int index = feeds.indexOf(feed);\r
+ FeedModel existingFeed = feeds.get(index);\r
+ existingFeed.subscribed = feed.subscribed;\r
+ if (!existingFeed.subscribed) {\r
+ feeds.remove(index);\r
+ }\r
+ } else if (feed.subscribed) {\r
+ // new subscription\r
+ feeds.add(feed);\r
+ }\r
+ }\r
}\r
\r
@Override\r
import java.awt.Color;\r
import java.awt.Component;\r
\r
-import javax.swing.ImageIcon;\r
import javax.swing.JTable;\r
import javax.swing.table.DefaultTableCellRenderer;\r
\r
-import com.gitblit.models.RepositoryModel;\r
-\r
/**\r
* Repository name cell renderer. This renderer shows the group name in a gray\r
* color and accentuates the repository name in a cornflower blue color.\r
\r
private static final long serialVersionUID = 1L;\r
\r
- final String groupSpan;\r
-\r
- private final boolean displayIcon;\r
-\r
- private final ImageIcon blankIcon;\r
-\r
- private final ImageIcon subscribedIcon;\r
+ private final String groupSpan;\r
\r
public NameRenderer() {\r
- this(false);\r
- }\r
-\r
- public NameRenderer(boolean showIcon) {\r
- this(Color.gray, new Color(0x00, 0x69, 0xD6), showIcon);\r
+ this(Color.gray, new Color(0x00, 0x69, 0xD6));\r
}\r
\r
- private NameRenderer(Color group, Color repo, boolean showIcon) {\r
- blankIcon = new ImageIcon(getClass().getResource("/blank.png"));\r
- subscribedIcon = new ImageIcon(getClass().getResource("/bullet_feed.png"));\r
- displayIcon = showIcon;\r
+ private NameRenderer(Color group, Color repo) {\r
groupSpan = "<span style='color:" + getHexColor(group) + "'>";\r
setForeground(repo);\r
}\r
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,\r
boolean hasFocus, int row, int column) {\r
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);\r
- if (value instanceof RepositoryModel) {\r
- RepositoryModel model = (RepositoryModel) value;\r
- String name = value.toString();\r
- int lastSlash = name.lastIndexOf('/');\r
- if (!isSelected && lastSlash > -1) {\r
- String group = name.substring(0, lastSlash + 1);\r
- String repo = name.substring(lastSlash + 1);\r
- setText("<html><body>" + groupSpan + group + "</span>" + repo);\r
- } else {\r
- this.setText(name);\r
- }\r
- if (displayIcon) {\r
- if (model.subscribed) {\r
- setIcon(subscribedIcon);\r
- } else {\r
- setIcon(blankIcon);\r
- }\r
- }\r
+ String name = value.toString();\r
+ int lastSlash = name.lastIndexOf('/');\r
+ if (!isSelected && lastSlash > -1) {\r
+ String group = name.substring(0, lastSlash + 1);\r
+ String repo = name.substring(lastSlash + 1);\r
+ setText("<html><body>" + groupSpan + group + "</span>" + repo);\r
} else {\r
- this.setText(value.toString());\r
+ this.setText(name);\r
}\r
return this;\r
}\r
--- /dev/null
+/*\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.Component;\r
+\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JTable;\r
+\r
+import com.gitblit.models.RepositoryModel;\r
+\r
+/**\r
+ * Displays a subscribed icon on the left of the repository name, if there is at\r
+ * least one subscribed branch.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class SubscribedRepositoryRenderer extends NameRenderer {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ private final GitblitClient gitblit;\r
+\r
+ private final ImageIcon blankIcon;\r
+\r
+ private final ImageIcon subscribedIcon;\r
+\r
+ public SubscribedRepositoryRenderer(GitblitClient gitblit) {\r
+ super();\r
+ this.gitblit = gitblit;\r
+ blankIcon = new ImageIcon(getClass().getResource("/blank.png"));\r
+ subscribedIcon = new ImageIcon(getClass().getResource("/bullet_feed.png"));\r
+ }\r
+\r
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,\r
+ boolean hasFocus, int row, int column) {\r
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);\r
+ if (value instanceof RepositoryModel) {\r
+ RepositoryModel model = (RepositoryModel) value;\r
+ if (gitblit.isSubscribed(model)) {\r
+ setIcon(subscribedIcon);\r
+ } else {\r
+ setIcon(blankIcon);\r
+ }\r
+ }\r
+ return this;\r
+ }\r
+}\r
--- /dev/null
+/*\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.KeyEvent;\r
+import java.util.List;\r
+\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JComponent;\r
+import javax.swing.JDialog;\r
+import javax.swing.JPanel;\r
+import javax.swing.JRootPane;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.KeyStroke;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+\r
+import com.gitblit.models.FeedModel;\r
+\r
+/**\r
+ * Displays a list of repository branches and allows the user to check or\r
+ * uncheck branches.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public abstract class SubscriptionsDialog extends JDialog {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ private final List<FeedModel> feeds;\r
+\r
+ private JTable feedsTable;\r
+\r
+ private FeedsTableModel model;\r
+\r
+ public SubscriptionsDialog(List<FeedModel> registrations) {\r
+ super();\r
+ this.feeds = registrations;\r
+ setTitle(Translation.get("gb.manage"));\r
+ setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());\r
+ initialize();\r
+ setSize(600, 400);\r
+ }\r
+\r
+ @Override\r
+ protected JRootPane createRootPane() {\r
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);\r
+ JRootPane rootPane = new JRootPane();\r
+ rootPane.registerKeyboardAction(new ActionListener() {\r
+ public void actionPerformed(ActionEvent actionEvent) {\r
+ setVisible(false);\r
+ }\r
+ }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);\r
+ return rootPane;\r
+ }\r
+\r
+ private void initialize() {\r
+ NameRenderer nameRenderer = new NameRenderer();\r
+ model = new FeedsTableModel(feeds);\r
+ feedsTable = Utils.newTable(model, Utils.DATE_FORMAT);\r
+ feedsTable.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+ feedsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+ @Override\r
+ public void valueChanged(ListSelectionEvent e) {\r
+ if (e.getValueIsAdjusting()) {\r
+ return;\r
+ }\r
+ int viewRow = feedsTable.getSelectedRow();\r
+ if (viewRow == -1) {\r
+ return;\r
+ }\r
+ int modelRow = feedsTable.convertRowIndexToModel(viewRow);\r
+ FeedModel feed = model.get(modelRow);\r
+ feed.subscribed = !feed.subscribed;\r
+ model.fireTableDataChanged();\r
+ }\r
+ });\r
+\r
+ String repository = feedsTable.getColumnName(FeedsTableModel.Columns.Repository.ordinal());\r
+ feedsTable.getColumn(repository).setCellRenderer(nameRenderer);\r
+\r
+ String branch = feedsTable.getColumnName(FeedsTableModel.Columns.Branch.ordinal());\r
+ feedsTable.getColumn(branch).setCellRenderer(nameRenderer);\r
+\r
+ String subscribed = feedsTable.getColumnName(FeedsTableModel.Columns.Subscribed.ordinal());\r
+ feedsTable.getColumn(subscribed).setCellRenderer(new BooleanCellRenderer());\r
+ feedsTable.getColumn(subscribed).setMinWidth(30);\r
+ feedsTable.getColumn(subscribed).setMaxWidth(30);\r
+\r
+ Utils.packColumns(feedsTable, 5);\r
+\r
+ final JButton cancel = new JButton(Translation.get("gb.cancel"));\r
+ cancel.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent event) {\r
+ setVisible(false);\r
+ }\r
+ });\r
+\r
+ final JButton save = new JButton(Translation.get("gb.save"));\r
+ save.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent event) {\r
+ save();\r
+ }\r
+ });\r
+\r
+ feedsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+ @Override\r
+ public void valueChanged(ListSelectionEvent e) {\r
+ if (e.getValueIsAdjusting()) {\r
+ return;\r
+ }\r
+ }\r
+ });\r
+\r
+ JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));\r
+ controls.add(cancel);\r
+ controls.add(save);\r
+\r
+ final Insets insets = new Insets(5, 5, 5, 5);\r
+ JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public Insets getInsets() {\r
+ return insets;\r
+ }\r
+ };\r
+ centerPanel.add(new HeaderPanel(Translation.get("gb.subscribe") + "...", "feed_16x16.png"),\r
+ BorderLayout.NORTH);\r
+ centerPanel.add(new JScrollPane(feedsTable), BorderLayout.CENTER);\r
+ centerPanel.add(controls, BorderLayout.SOUTH);\r
+\r
+ getContentPane().setLayout(new BorderLayout(5, 5));\r
+ getContentPane().add(centerPanel, BorderLayout.CENTER);\r
+ }\r
+\r
+ public abstract void save();\r
+}\r
import com.gitblit.models.SyndicatedEntryModel;\r
\r
/**\r
- * Table model of List<SyndicatedEntryModel>\r
+ * Table model for a list of retrieved feed entries.\r
* \r
* @author James Moger\r
* \r
List<SyndicatedEntryModel> entries;\r
\r
enum Columns {\r
- Date, Repository, Author, Message;\r
+ Date, Repository, Branch, Author, Message;\r
\r
@Override\r
public String toString() {\r
return Translation.get("gb.date");\r
case Repository:\r
return Translation.get("gb.repository");\r
+ case Branch:\r
+ return Translation.get("gb.branch");\r
case Author:\r
return Translation.get("gb.author");\r
case Message:\r
return entry.published;\r
case Repository:\r
return entry.repository;\r
+ case Branch:\r
+ return entry.branch;\r
case Author:\r
return entry.author;\r
case Message:\r
*/\r
package com.gitblit.client;\r
\r
-import java.io.InputStream;\r
-import java.util.Properties;\r
+import java.util.MissingResourceException;\r
+import java.util.ResourceBundle;\r
\r
+/**\r
+ * Loads the Gitblit language resource file.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
public class Translation {\r
\r
- private final static Properties translation;\r
+ private final static ResourceBundle translation;\r
\r
static {\r
- translation = new Properties();\r
- InputStream is = null;\r
+ ResourceBundle bundle;\r
try {\r
- is = Translation.class.getResource("/com/gitblit/wicket/GitBlitWebApp.properties")\r
- .openStream();\r
- } catch (Throwable t) {\r
- try {\r
- is = Translation.class.getResource("/GitBlitWebApp.properties").openStream();\r
- } catch (Throwable x) {\r
- }\r
- }\r
- if (is != null) {\r
- try {\r
- translation.load(is);\r
- } catch (Throwable t) {\r
-\r
- } finally {\r
- try {\r
- is.close();\r
- } catch (Throwable t) {\r
- }\r
- }\r
+ // development location\r
+ bundle = ResourceBundle.getBundle("com/gitblit/wicket/GitBlitWebApp");\r
+ } catch (MissingResourceException e) {\r
+ // runtime location\r
+ bundle = ResourceBundle.getBundle("GitBlitWebApp");\r
}\r
+ translation = bundle;\r
}\r
\r
public static String get(String key) {\r
if (translation.containsKey(key)) {\r
- return translation.getProperty(key).trim();\r
+ return translation.getString(key).trim();\r
}\r
return key;\r
}\r
--- /dev/null
+/*\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.models;\r
+\r
+import java.io.Serializable;\r
+import java.text.MessageFormat;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Date;\r
+\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * FeedModel represents a syndication (RSS) feed.\r
+ * \r
+ * @author James Moger\r
+ */\r
+public class FeedModel implements Serializable, Comparable<FeedModel> {\r
+\r
+ public String repository;\r
+ public String branch;\r
+ public int maxRetrieval;\r
+ public Date lastRefresh;\r
+\r
+ public boolean subscribed;\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public FeedModel() {\r
+ this("");\r
+ }\r
+\r
+ public FeedModel(String definition) {\r
+ maxRetrieval = -1;\r
+ lastRefresh = new Date(0);\r
+\r
+ String[] fields = definition.split(":");\r
+ repository = fields[0];\r
+ if (fields.length > 1) {\r
+ branch = fields[1];\r
+ maxRetrieval = Integer.parseInt(fields[2]);\r
+ try {\r
+ lastRefresh = new SimpleDateFormat("yyyyMMddHHmmss").parse(fields[3]);\r
+ } catch (ParseException e) {\r
+ }\r
+ subscribed = true;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return MessageFormat.format("{0}:{1}:{2,number,0}:{3,date,yyyyMMddHHmmss}", repository,\r
+ branch, maxRetrieval, lastRefresh);\r
+ }\r
+\r
+ @Override\r
+ public int compareTo(FeedModel o) {\r
+ int repositoryCompare = repository.compareTo(o.repository);\r
+ if (repositoryCompare == 0) {\r
+ // same repository\r
+ if (StringUtils.isEmpty(branch)) {\r
+ return 1;\r
+ } else if (StringUtils.isEmpty(o.branch)) {\r
+ return -1;\r
+ }\r
+ return branch.compareTo(o.branch);\r
+ }\r
+ return repositoryCompare;\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return (repository + (StringUtils.isEmpty(branch) ? "" : branch)).toLowerCase().hashCode();\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object o) {\r
+ if (o instanceof FeedModel) {\r
+ return hashCode() == o.hashCode();\r
+ }\r
+ return false;\r
+ }\r
+}\r
public String frequency;\r
public String origin;\r
public String size;\r
- public boolean subscribed;\r
\r
public RepositoryModel() {\r
this("", "", "", new Date(0));\r
import com.gitblit.models.FederationModel;\r
import com.gitblit.models.FederationProposal;\r
import com.gitblit.models.FederationSet;\r
+import com.gitblit.models.FeedModel;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.ServerSettings;\r
import com.gitblit.models.ServerStatus;\r
}\r
\r
/**\r
- * Retrieves a map of all branches in the Gitblit server keyed by\r
+ * Retrieves a map of local branches in the Gitblit server keyed by\r
* repository.\r
* \r
* @param serverUrl\r
* @return\r
* @throws IOException\r
*/\r
- public static Map<String, Collection<String>> getAllBranches(String serverUrl,\r
- String account, char[] password) throws IOException {\r
+ public static Map<String, Collection<String>> getBranches(String serverUrl, String account,\r
+ char[] password) throws IOException {\r
String url = asLink(serverUrl, RpcRequest.LIST_BRANCHES);\r
- Map<String, Collection<String>> allReferences = JsonUtils.retrieveJson(url,\r
- BRANCHES_TYPE, account, password);\r
- return allReferences;\r
+ Map<String, Collection<String>> branches = JsonUtils.retrieveJson(url, BRANCHES_TYPE,\r
+ account, password);\r
+ return branches;\r
+ }\r
+\r
+ /**\r
+ * Retrieves a list of available branch feeds in the Gitblit server.\r
+ * \r
+ * @param serverUrl\r
+ * @param account\r
+ * @param password\r
+ * @return\r
+ * @throws IOException\r
+ */\r
+ public static List<FeedModel> getBranchFeeds(String serverUrl, String account, char[] password)\r
+ throws IOException {\r
+ List<FeedModel> feeds = new ArrayList<FeedModel>();\r
+ Map<String, Collection<String>> allBranches = getBranches(serverUrl, account, password);\r
+ for (Map.Entry<String, Collection<String>> entry : allBranches.entrySet()) {\r
+ for (String branch : entry.getValue()) {\r
+ FeedModel feed = new FeedModel();\r
+ feed.repository = entry.getKey();\r
+ feed.branch = branch;\r
+ feeds.add(feed);\r
+ }\r
+ }\r
+ return feeds;\r
}\r
\r
/**\r
gb.version = version\r
gb.releaseDate = release date\r
gb.date = date\r
-gb.recentCommits = recent commits\r
-gb.subscribe = subscribe
\ No newline at end of file
+gb.recentActivity = recent activity\r
+gb.subscribe = subscribe\r
+gb.branch = branch
\ No newline at end of file
}\r
\r
public void testBranches() throws Exception {\r
- Map<String, Collection<String>> branches = RpcUtils.getAllBranches(url, account,\r
+ Map<String, Collection<String>> branches = RpcUtils.getBranches(url, account,\r
password.toCharArray());\r
assertTrue(branches != null);\r
assertTrue(branches.size() > 0);\r