blob: 0fab934da6b4678271e6889346fc188fc26ab75e [file] [log] [blame]
/*
* 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.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
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;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.Keys;
import com.gitblit.models.FeedModel;
import com.gitblit.models.RegistrantAccessPermission;
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;
private JButton clearCache;
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() {
@Override
public void actionPerformed(ActionEvent e) {
RepositoryModel model = getSelectedRepositories().get(0);
String url = gitblit.getURL("summary", model.name, null);
Utils.browse(url);
}
});
JButton refreshRepositories = new JButton(Translation.get("gb.refresh"));
refreshRepositories.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
refreshRepositories();
}
});
clearCache = new JButton(Translation.get("gb.clearCache"));
clearCache.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clearCache();
}
});
createRepository = new JButton(Translation.get("gb.create"));
createRepository.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
createRepository();
}
});
editRepository = new JButton(Translation.get("gb.edit"));
editRepository.setEnabled(false);
editRepository.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
editRepository(getSelectedRepositories().get(0));
}
});
delRepository = new JButton(Translation.get("gb.delete"));
delRepository.setEnabled(false);
delRepository.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteRepositories(getSelectedRepositories());
}
});
final JButton subscribeRepository = new JButton(Translation.get("gb.subscribe") + "...");
subscribeRepository.setEnabled(false);
subscribeRepository.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<FeedModel> feeds = gitblit.getAvailableFeeds(getSelectedRepositories().get(0));
subscribeFeeds(feeds);
}
});
final JButton logRepository = new JButton(Translation.get("gb.log") + "...");
logRepository.setEnabled(false);
logRepository.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RepositoryModel model = getSelectedRepositories().get(0);
showSearchDialog(false, model);
}
});
final JButton searchRepository = new JButton(Translation.get("gb.search") + "...");
searchRepository.setEnabled(false);
searchRepository.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RepositoryModel model = getSelectedRepositories().get(0);
showSearchDialog(true, model);
}
});
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.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;
if (singleSelection) {
RepositoryModel repository = getSelectedRepositories().get(0);
browseRepository.setEnabled(repository.hasCommits);
logRepository.setEnabled(repository.hasCommits);
searchRepository.setEnabled(repository.hasCommits);
subscribeRepository.setEnabled(repository.hasCommits);
} else {
browseRepository.setEnabled(false);
logRepository.setEnabled(false);
searchRepository.setEnabled(false);
subscribeRepository.setEnabled(false);
}
delRepository.setEnabled(selected);
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() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2 && gitblit.allowManagement()) {
editRepository(getSelectedRepositories().get(0));
}
}
});
filterTextfield = new JTextField();
filterTextfield.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
filterRepositories(filterTextfield.getText());
}
});
filterTextfield.addKeyListener(new KeyAdapter() {
@Override
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(clearCache);
repositoryControls.add(refreshRepositories);
repositoryControls.add(browseRepository);
repositoryControls.add(createRepository);
repositoryControls.add(editRepository);
repositoryControls.add(delRepository);
repositoryControls.add(subscribeRepository);
repositoryControls.add(logRepository);
repositoryControls.add(searchRepository);
setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
header = new HeaderPanel(Translation.get("gb.repositories"), "git-orange-16x16.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 abstract void updateTeamsTable();
protected void disableManagement() {
clearCache.setVisible(false);
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>() {
@Override
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();
}
protected void clearCache() {
GitblitWorker worker = new GitblitWorker(RepositoriesPanel.this,
RpcRequest.CLEAR_REPOSITORY_CACHE) {
@Override
protected Boolean doRequest() throws IOException {
if (gitblit.clearRepositoryCache()) {
gitblit.refreshRepositories();
return true;
}
return false;
}
@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(gitblit.getProtocolVersion());
dialog.setLocationRelativeTo(RepositoriesPanel.this);
dialog.setAccessRestriction(gitblit.getDefaultAccessRestriction());
dialog.setAuthorizationControl(gitblit.getDefaultAuthorizationControl());
dialog.setUsers(null, gitblit.getUsernames(), null);
dialog.setTeams(gitblit.getTeamnames(), null);
dialog.setRepositories(gitblit.getRepositories());
dialog.setFederationSets(gitblit.getFederationSets(), null);
dialog.setIndexedBranches(new ArrayList<String>(Arrays.asList(Constants.DEFAULT_BRANCH)), null);
dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(null),
gitblit.getPreReceiveScriptsInherited(null), null);
dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(null),
gitblit.getPostReceiveScriptsInherited(null), null);
dialog.setVisible(true);
final RepositoryModel newRepository = dialog.getRepository();
final List<RegistrantAccessPermission> permittedUsers = dialog.getUserAccessPermissions();
final List<RegistrantAccessPermission> permittedTeams = dialog.getTeamAccessPermissions();
if (newRepository == null) {
return;
}
GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_REPOSITORY) {
@Override
protected Boolean doRequest() throws IOException {
boolean success = gitblit.createRepository(newRepository, permittedUsers,
permittedTeams);
if (success) {
gitblit.refreshRepositories();
if (permittedUsers.size() > 0) {
gitblit.refreshUsers();
}
if (permittedTeams.size() > 0) {
gitblit.refreshTeams();
}
}
return success;
}
@Override
protected void onSuccess() {
updateTable(false);
updateUsersTable();
updateTeamsTable();
}
@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(gitblit.getProtocolVersion(),
repository);
dialog.setLocationRelativeTo(RepositoriesPanel.this);
List<String> usernames = gitblit.getUsernames();
List<RegistrantAccessPermission> members = gitblit.getUserAccessPermissions(repository);
dialog.setUsers(new ArrayList<String>(repository.owners), usernames, members);
dialog.setTeams(gitblit.getTeamnames(), gitblit.getTeamAccessPermissions(repository));
dialog.setRepositories(gitblit.getRepositories());
dialog.setFederationSets(gitblit.getFederationSets(), repository.federationSets);
List<String> allLocalBranches = new ArrayList<String>();
allLocalBranches.add(Constants.DEFAULT_BRANCH);
allLocalBranches.addAll(repository.getLocalBranches());
dialog.setIndexedBranches(allLocalBranches, repository.indexedBranches);
dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(repository),
gitblit.getPreReceiveScriptsInherited(repository), repository.preReceiveScripts);
dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(repository),
gitblit.getPostReceiveScriptsInherited(repository), repository.postReceiveScripts);
if (gitblit.getSettings().hasKey(Keys.groovy.customFields)) {
Map<String, String> map = gitblit.getSettings().get(Keys.groovy.customFields).getMap();
dialog.setCustomFields(repository, map);
}
dialog.setVisible(true);
final RepositoryModel revisedRepository = dialog.getRepository();
final List<RegistrantAccessPermission> permittedUsers = dialog.getUserAccessPermissions();
final List<RegistrantAccessPermission> permittedTeams = dialog.getTeamAccessPermissions();
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, permittedTeams);
if (success) {
gitblit.refreshRepositories();
gitblit.refreshUsers();
gitblit.refreshTeams();
}
return success;
}
@Override
protected void onSuccess() {
updateTable(false);
updateUsersTable();
updateTeamsTable();
}
@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();
gitblit.refreshTeams();
}
return success;
}
@Override
protected void onSuccess() {
updateTable(false);
updateUsersTable();
updateTeamsTable();
}
@Override
protected void onFailure() {
showFailure("Failed to delete specified repositories!");
}
};
worker.execute();
}
}
private void showSearchDialog(boolean isSearch, final RepositoryModel repository) {
final SearchDialog dialog = new SearchDialog(gitblit, isSearch);
if (repository != null) {
dialog.selectRepository(repository);
}
dialog.setLocationRelativeTo(this);
dialog.setVisible(true);
}
}