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