summaryrefslogtreecommitdiffstats
path: root/src/com/gitblit
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2011-10-05 22:22:43 -0400
committerJames Moger <james.moger@gitblit.com>2011-10-05 22:22:43 -0400
commit841651baee2181c1543555d1eabcd0e4fee48827 (patch)
treef6a60ba2f468c52e983f051e6fe30c9178ea696e /src/com/gitblit
parent4b0e0641076f802e8da1695fe8a40ff7646b811a (diff)
downloadgitblit-841651baee2181c1543555d1eabcd0e4fee48827.tar.gz
gitblit-841651baee2181c1543555d1eabcd0e4fee48827.zip
New setting to disable RPC administration. Advancing the RPC client.
Diffstat (limited to 'src/com/gitblit')
-rw-r--r--src/com/gitblit/RpcFilter.java22
-rw-r--r--src/com/gitblit/build/Build.java19
-rw-r--r--src/com/gitblit/client/ClosableTabComponent.java149
-rw-r--r--src/com/gitblit/client/DateCellRenderer.java19
-rw-r--r--src/com/gitblit/client/GitblitClient.java141
-rw-r--r--src/com/gitblit/client/GitblitClientLauncher.java105
-rw-r--r--src/com/gitblit/client/GitblitPanel.java378
-rw-r--r--src/com/gitblit/client/GitblitRegistration.java47
-rw-r--r--src/com/gitblit/client/NameRenderer.java65
-rw-r--r--src/com/gitblit/client/RepositoriesModel.java31
-rw-r--r--src/com/gitblit/client/TypeRenderer.java119
-rw-r--r--src/com/gitblit/client/splash.pngbin0 -> 11593 bytes
12 files changed, 1041 insertions, 54 deletions
diff --git a/src/com/gitblit/RpcFilter.java b/src/com/gitblit/RpcFilter.java
index 49df8444..f92dd962 100644
--- a/src/com/gitblit/RpcFilter.java
+++ b/src/com/gitblit/RpcFilter.java
@@ -57,20 +57,21 @@ public class RpcFilter extends AuthenticationFilter {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
- if (!GitBlit.getBoolean(Keys.web.enableRpcServlet, false)) {
- logger.warn(Keys.web.enableRpcServlet + " must be set TRUE for rpc requests.");
- httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
- return;
- }
-
String fullUrl = getFullUrl(httpRequest);
RpcRequest requestType = RpcRequest.fromName(httpRequest.getParameter("req"));
boolean adminRequest = requestType.exceeds(RpcRequest.LIST_REPOSITORIES);
+ // conditionally reject all rpc requests
+ if (!GitBlit.getBoolean(Keys.web.enableRpcServlet, true)) {
+ logger.warn(Keys.web.enableRpcServlet + " must be set TRUE for rpc requests.");
+ httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, false);
boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
-
+
// Wrap the HttpServletRequest with the RpcServletnRequest which
// overrides the servlet container user principal methods.
AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest);
@@ -79,6 +80,13 @@ public class RpcFilter extends AuthenticationFilter {
authenticatedRequest.setUser(user);
}
+ // conditionally reject rpc administration requests
+ if (adminRequest && !GitBlit.getBoolean(Keys.web.enableRpcAdministration, false)) {
+ logger.warn(Keys.web.enableRpcAdministration + " must be set TRUE for administrative rpc requests.");
+ httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
+ return;
+ }
+
// BASIC authentication challenge and response processing
if ((adminRequest && authenticateAdmin) || (!adminRequest && authenticateView)) {
if (user == null) {
diff --git a/src/com/gitblit/build/Build.java b/src/com/gitblit/build/Build.java
index 684f2787..862c295d 100644
--- a/src/com/gitblit/build/Build.java
+++ b/src/com/gitblit/build/Build.java
@@ -48,7 +48,11 @@ import com.gitblit.utils.StringUtils;
*
*/
public class Build {
-
+
+ public interface DownloadListener {
+ public void downloading(String name);
+ }
+
/**
* BuildType enumeration representing compile-time or runtime. This is used
* to download dependencies either for Gitblit GO runtime or for setting up
@@ -57,6 +61,8 @@ public class Build {
public static enum BuildType {
RUNTIME, COMPILETIME;
}
+
+ private static DownloadListener downloadListener;
public static void main(String... args) {
runtime();
@@ -128,6 +134,14 @@ public class Build {
downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME);
}
+
+ public static void rpcClient(DownloadListener listener) {
+ downloadListener = listener;
+ downloadFromApache(MavenObject.GSON, BuildType.RUNTIME);
+ downloadFromApache(MavenObject.JSCH, BuildType.RUNTIME);
+
+ downloadFromEclipse(MavenObject.JGIT, BuildType.RUNTIME);
+ }
/**
* Builds the Keys class based on the gitblit.properties file and inserts
@@ -273,6 +287,9 @@ public class Build {
throw new RuntimeException("Failed to create destination folder structure!");
}
}
+ if (downloadListener != null) {
+ downloadListener.downloading(mo.name);
+ }
ByteArrayOutputStream buff = new ByteArrayOutputStream();
try {
URL url = new URL(mavenURL);
diff --git a/src/com/gitblit/client/ClosableTabComponent.java b/src/com/gitblit/client/ClosableTabComponent.java
new file mode 100644
index 00000000..a121806a
--- /dev/null
+++ b/src/com/gitblit/client/ClosableTabComponent.java
@@ -0,0 +1,149 @@
+/*
+ * 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.BasicStroke;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Stroke;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import javax.swing.AbstractButton;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.plaf.basic.BasicButtonUI;
+
+/**
+ * Closable tab control.
+ */
+public class ClosableTabComponent extends JPanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final MouseListener BUTTON_MOUSE_LISTENER = new MouseAdapter() {
+ public void mouseEntered(MouseEvent e) {
+ Component component = e.getComponent();
+ if (component instanceof AbstractButton) {
+ AbstractButton button = (AbstractButton) component;
+ button.setBorderPainted(true);
+ }
+ }
+
+ public void mouseExited(MouseEvent e) {
+ Component component = e.getComponent();
+ if (component instanceof AbstractButton) {
+ AbstractButton button = (AbstractButton) component;
+ button.setBorderPainted(false);
+ }
+ }
+ };
+
+ private final JTabbedPane pane;
+ private final JLabel label;
+ private final JButton button = new TabButton();
+
+ private final CloseTabListener closeListener;
+
+ public interface CloseTabListener {
+ void closeTab(Component c);
+ }
+
+ public ClosableTabComponent(String title, ImageIcon icon, JTabbedPane pane,
+ CloseTabListener closeListener) {
+ super(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ this.closeListener = closeListener;
+
+ if (pane == null) {
+ throw new NullPointerException("TabbedPane is null");
+ }
+ this.pane = pane;
+ setOpaque(false);
+ label = new JLabel(title);
+ if (icon != null) {
+ label.setIcon(icon);
+ }
+
+ add(label);
+ label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
+ add(button);
+ setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
+ }
+
+ private class TabButton extends JButton implements ActionListener {
+
+ private static final long serialVersionUID = 1L;
+
+ public TabButton() {
+ int size = 17;
+ setPreferredSize(new Dimension(size, size));
+ setToolTipText("Close");
+ setUI(new BasicButtonUI());
+ setContentAreaFilled(false);
+ setFocusable(false);
+ setBorder(BorderFactory.createEtchedBorder());
+ setBorderPainted(false);
+ addMouseListener(BUTTON_MOUSE_LISTENER);
+ setRolloverEnabled(true);
+ addActionListener(this);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ int i = pane.indexOfTabComponent(ClosableTabComponent.this);
+ Component c = pane.getComponentAt(i);
+ if (i != -1) {
+ pane.remove(i);
+ }
+ if (closeListener != null) {
+ closeListener.closeTab(c);
+ }
+ }
+
+ public void updateUI() {
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Graphics2D g2 = (Graphics2D) g;
+ Stroke stroke = g2.getStroke();
+ g2.setStroke(new BasicStroke(2));
+ g.setColor(Color.BLACK);
+ if (getModel().isRollover()) {
+ Color highlight = new Color(0, 51, 153);
+ g.setColor(highlight);
+ }
+ int delta = 5;
+ g.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1);
+ g.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1);
+ g2.setStroke(stroke);
+
+ int i = pane.indexOfTabComponent(ClosableTabComponent.this);
+ pane.setTitleAt(i, label.getText());
+ }
+ }
+}
diff --git a/src/com/gitblit/client/DateCellRenderer.java b/src/com/gitblit/client/DateCellRenderer.java
index 591926b7..053cf52f 100644
--- a/src/com/gitblit/client/DateCellRenderer.java
+++ b/src/com/gitblit/client/DateCellRenderer.java
@@ -15,29 +15,44 @@
*/
package com.gitblit.client;
+import java.awt.Color;
import java.awt.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JTable;
+import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
+import com.gitblit.utils.TimeUtils;
+
+/**
+ * Time ago cell renderer with real date tooltip.
+ *
+ * @author James Moger
+ *
+ */
public class DateCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
private final String pattern;
- public DateCellRenderer(String pattern) {
+ public DateCellRenderer(String pattern, Color foreground) {
this.pattern = (pattern == null ? "yyyy-MM-dd HH:mm" : pattern);
+ setForeground(foreground);
+ setHorizontalAlignment(SwingConstants.CENTER);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value instanceof Date) {
+ Date date = (Date) value;
+ String timeAgo = TimeUtils.timeAgo(date);
String strDate = new SimpleDateFormat(pattern).format((Date) value);
- this.setText(strDate);
+ this.setText(timeAgo);
+ this.setToolTipText(strDate);
}
return this;
}
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index d10cedeb..51d8e7eb 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -16,84 +16,179 @@
package com.gitblit.client;
import java.awt.BorderLayout;
+import java.awt.Dimension;
import java.awt.EventQueue;
-import java.awt.Menu;
-import java.awt.MenuBar;
-import java.awt.MenuItem;
-import java.awt.MenuShortcut;
+import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.ImageIcon;
import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JPasswordField;
import javax.swing.JTabbedPane;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import javax.swing.UIManager;
import com.gitblit.Constants;
import com.gitblit.utils.StringUtils;
+/**
+ * Sample RPC application.
+ *
+ * @author James Moger
+ *
+ */
public class GitblitClient extends JFrame {
private static final long serialVersionUID = 1L;
private JTabbedPane serverTabs;
+ private GitblitRegistration localhost = new GitblitRegistration("default",
+ "https://localhost:8443", "admin", "admin".toCharArray());
+
+ private List<GitblitRegistration> registrations = new ArrayList<GitblitRegistration>();
+ private JMenu recentMenu;
private GitblitClient() {
super();
}
private void initialize() {
- setupMenu();
setContentPane(getCenterPanel());
+ setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
- setTitle("Gitblit Client v" + Constants.VERSION + " (" + Constants.VERSION_DATE + ")");
+ setTitle("Gitblit RPC Client v" + Constants.VERSION + " (" + Constants.VERSION_DATE + ")");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- setSize(800, 600);
- setLocationRelativeTo(null);
+ setSize(950, 600);
}
- private void setupMenu() {
- MenuBar menuBar = new MenuBar();
- setMenuBar(menuBar);
- Menu serversMenu = new Menu("Servers");
+ public void setVisible(boolean value) {
+ if (value) {
+ if (registrations.size() == 0) {
+ // default prompt
+ if (loginPrompt(localhost)) {
+ pack();
+ }
+ } else if (registrations.size() == 1) {
+ // single registration prompt
+ if (loginPrompt(registrations.get(0))) {
+ pack();
+ }
+ }
+ super.setVisible(value);
+ setLocationRelativeTo(null);
+ }
+ }
+
+ private JMenuBar setupMenu() {
+ JMenuBar menuBar = new JMenuBar();
+ JMenu serversMenu = new JMenu("Servers");
menuBar.add(serversMenu);
- MenuItem login = new MenuItem("Login...", new MenuShortcut(KeyEvent.VK_L, false));
+ recentMenu = new JMenu("Recent");
+ serversMenu.add(recentMenu);
+ JMenuItem login = new JMenuItem("Login...");
+ login.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_DOWN_MASK, false));
login.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
- String url = JOptionPane.showInputDialog(GitblitClient.this,
- "Please enter Gitblit server URL", "https://localhost:8443");
- if (StringUtils.isEmpty(url)) {
- return;
- }
- login(url, "admin", "admin".toCharArray());
+ loginPrompt(localhost);
}
});
serversMenu.add(login);
+ return menuBar;
+ }
+
+ private JPanel newLabelPanel(String text, JTextField field) {
+ JLabel label = new JLabel(text);
+ label.setPreferredSize(new Dimension(75, 10));
+ JPanel jpanel = new JPanel(new BorderLayout());
+ jpanel.add(label, BorderLayout.WEST);
+ jpanel.add(field, BorderLayout.CENTER);
+ return jpanel;
}
private JPanel getCenterPanel() {
serverTabs = new JTabbedPane(JTabbedPane.TOP);
+ JMenuBar menubar = setupMenu();
JPanel panel = new JPanel(new BorderLayout());
+ panel.add(menubar, BorderLayout.NORTH);
panel.add(serverTabs, BorderLayout.CENTER);
return panel;
}
- private void login(String url, String account, char[] password) {
+ private boolean loginPrompt(GitblitRegistration reg) {
+ JTextField urlField = new JTextField(reg.url, 30);
+ JTextField nameField = new JTextField(reg.name);
+ JTextField accountField = new JTextField(reg.account);
+ JPasswordField passwordField = new JPasswordField(new String(reg.password));
+
+ JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
+ panel.add(newLabelPanel("name", nameField));
+ panel.add(newLabelPanel("url", urlField));
+ panel.add(newLabelPanel("account", accountField));
+ panel.add(newLabelPanel("password", passwordField));
+
+ int result = JOptionPane.showConfirmDialog(GitblitClient.this, panel, "Login",
+ JOptionPane.OK_CANCEL_OPTION);
+ if (result != JOptionPane.OK_OPTION) {
+ return false;
+ }
+ String url = urlField.getText();
+ if (StringUtils.isEmpty(url)) {
+ return false;
+ }
+ reg = new GitblitRegistration(nameField.getText(), url, accountField.getText(),
+ passwordField.getPassword());
+ login(reg);
+ registrations.add(0, reg);
+ rebuildRecentMenu();
+ return true;
+ }
+
+ private void login(GitblitRegistration reg) {
try {
- GitblitPanel panel = new GitblitPanel(url, account, password);
+ GitblitPanel panel = new GitblitPanel(reg);
panel.login();
- serverTabs.addTab(url.substring(url.indexOf("//") + 2), panel);
- serverTabs.setSelectedIndex(serverTabs.getTabCount() - 1);
+ serverTabs.addTab(reg.name, panel);
+ int idx = serverTabs.getTabCount() - 1;
+ serverTabs.setSelectedIndex(idx);
+ serverTabs.setTabComponentAt(idx, new ClosableTabComponent(reg.name, null, serverTabs,
+ panel));
} catch (IOException e) {
JOptionPane.showMessageDialog(GitblitClient.this, e.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
+ private void rebuildRecentMenu() {
+ recentMenu.removeAll();
+ for (final GitblitRegistration reg : registrations) {
+ JMenuItem item = new JMenuItem(reg.name);
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ login(reg);
+ }
+ });
+ recentMenu.add(item);
+ }
+ }
+
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e) {
+ }
GitblitClient frame = new GitblitClient();
frame.initialize();
frame.setVisible(true);
diff --git a/src/com/gitblit/client/GitblitClientLauncher.java b/src/com/gitblit/client/GitblitClientLauncher.java
new file mode 100644
index 00000000..19e9efd8
--- /dev/null
+++ b/src/com/gitblit/client/GitblitClientLauncher.java
@@ -0,0 +1,105 @@
+/*
+ * 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.Color;
+import java.awt.EventQueue;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.SplashScreen;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import com.gitblit.Launcher;
+import com.gitblit.build.Build;
+import com.gitblit.build.Build.DownloadListener;
+
+/**
+ * Downloads dependencies and launches RPC client.
+ *
+ * @author James Moger
+ *
+ */
+public class GitblitClientLauncher {
+
+ public static void main(String[] args) {
+ final SplashScreen splash = SplashScreen.getSplashScreen();
+
+ DownloadListener downloadListener = new DownloadListener() {
+ @Override
+ public void downloading(String name) {
+ updateSplash(splash, "Downloading " + name + "...");
+ }
+ };
+
+ // download rpc client runtime dependencies
+ Build.rpcClient(downloadListener);
+
+ updateSplash(splash, "Scanning Library Folder...");
+ File libFolder = new File("ext");
+ List<File> jars = Launcher.findJars(libFolder.getAbsoluteFile());
+
+ // sort the jars by name and then reverse the order so the newer version
+ // of the library gets loaded in the event that this is an upgrade
+ Collections.sort(jars);
+ Collections.reverse(jars);
+ for (File jar : jars) {
+ try {
+ updateSplash(splash, "Loading " + jar.getName() + "...");
+ Launcher.addJarFile(jar);
+ } catch (IOException e) {
+
+ }
+ }
+
+ updateSplash(splash, "Starting Gitblit RPC Client...");
+ GitblitClient.main(args);
+ }
+
+ private static void updateSplash(final SplashScreen splash, final String string) {
+ if (splash == null) {
+ return;
+ }
+ try {
+ EventQueue.invokeAndWait(new Runnable() {
+ public void run() {
+ Graphics2D g = splash.createGraphics();
+ if (g != null) {
+ // Splash is 320x120
+ FontMetrics fm = g.getFontMetrics();
+ g.setColor(Color.darkGray);
+ int h = fm.getHeight() + fm.getMaxDescent();
+ int x = 5;
+ int y = 115;
+ int w = 320 - 2 * x;
+ g.fillRect(x, y - h, w, h);
+ g.setColor(Color.lightGray);
+ g.drawRect(x, y - h, w, h);
+ g.setColor(Color.WHITE);
+ int xw = fm.stringWidth(string);
+ g.drawString(string, x + ((w - xw) / 2), y - 5);
+ g.dispose();
+ splash.update();
+ }
+ }
+ });
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+}
diff --git a/src/com/gitblit/client/GitblitPanel.java b/src/com/gitblit/client/GitblitPanel.java
index 911ec0c6..5482593d 100644
--- a/src/com/gitblit/client/GitblitPanel.java
+++ b/src/com/gitblit/client/GitblitPanel.java
@@ -16,61 +16,400 @@
package com.gitblit.client;
import java.awt.BorderLayout;
+import java.awt.Color;
import java.awt.Component;
+import java.awt.Desktop;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.io.IOException;
+import java.net.URI;
+import java.text.MessageFormat;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import java.util.Map;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
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.DefaultTableColumnModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
+import javax.swing.table.TableRowSorter;
+import com.gitblit.GitBlitException.ForbiddenException;
+import com.gitblit.client.ClosableTabComponent.CloseTabListener;
+import com.gitblit.models.FederationModel;
import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
import com.gitblit.utils.RpcUtils;
+import com.gitblit.utils.StringUtils;
-public class GitblitPanel extends JPanel {
+/**
+ * GitblitPanel performs the login, all business logic, and contains all widgets
+ * to represent the state of a repository for the given account credentials.
+ *
+ * @author James Moger
+ *
+ */
+public class GitblitPanel extends JPanel implements CloseTabListener {
private static final long serialVersionUID = 1L;
- String url;
- String account;
- char[] password;
+ private final int margin = 5;
+
+ private final Insets insets = new Insets(margin, margin, margin, margin);
+
+ private String url;
+
+ private String account;
+
+ private char[] password;
- JTabbedPane tabs;
+ private boolean isAdmin;
+
+ private JTabbedPane tabs;
private JTable repositoriesTable;
+ private RepositoriesModel repositoriesModel;
+
+ private JList usersList;
+
+ private JPanel usersPanel;
+
+ private JButton createRepository;
+
+ private JButton delRepository;
+
+ private NameRenderer nameRenderer;
+
+ private TypeRenderer typeRenderer;
+
+ private DefaultTableCellRenderer ownerRenderer;
+
+ private DefaultTableCellRenderer sizeRenderer;
+
+ private TableRowSorter<RepositoriesModel> defaultSorter;
+
+ public GitblitPanel(GitblitRegistration reg) {
+ this(reg.url, reg.account, reg.password);
+ }
+
public GitblitPanel(String url, String account, char[] password) {
this.url = url;
this.account = account;
this.password = password;
- tabs = new JTabbedPane(JTabbedPane.TOP);
- repositoriesTable = new JTable();
- repositoriesTable.setDefaultRenderer(Date.class, new DateCellRenderer(null));
+ final JButton browseRepository = new JButton("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}", GitblitPanel.this.url,
+ StringUtils.encodeURL(model.name));
+ try {
+ Desktop.getDesktop().browse(new URI(u));
+ } catch (Exception x) {
+ x.printStackTrace();
+ }
+ }
+ });
+
+ createRepository = new JButton("Create");
+ createRepository.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("TODO Create Repository");
+ }
+ });
+
+ final JButton editRepository = new JButton("Edit");
+ editRepository.setEnabled(false);
+ editRepository.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (RepositoryModel model : getSelectedRepositories()) {
+ System.out.println("TODO Edit " + model);
+ }
+ }
+ });
+
+ delRepository = new JButton("Delete");
+ delRepository.setEnabled(false);
+ delRepository.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (RepositoryModel model : getSelectedRepositories()) {
+ System.out.println("TODO Delete " + model);
+ }
+ }
+ });
+
+ final JButton cloneRepository = new JButton("Clone");
+ cloneRepository.setEnabled(false);
+ cloneRepository.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (RepositoryModel model : getSelectedRepositories()) {
+ System.out.println("TODO Clone " + model);
+ }
+ }
+ });
+
+ nameRenderer = new NameRenderer(Color.gray, new Color(0x00, 0x69, 0xD6));
+ typeRenderer = new TypeRenderer();
+
+ sizeRenderer = new DefaultTableCellRenderer();
+ sizeRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
+ sizeRenderer.setForeground(new Color(0, 0x80, 0));
+
+ ownerRenderer = new DefaultTableCellRenderer();
+ ownerRenderer.setForeground(Color.gray);
+ ownerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
+
+ repositoriesModel = new RepositoriesModel();
+ defaultSorter = new TableRowSorter<RepositoriesModel>(repositoriesModel);
+ repositoriesTable = new JTable(repositoriesModel);
+ repositoriesTable.setRowSorter(defaultSorter);
+ repositoriesTable.getRowSorter().toggleSortOrder(RepositoriesModel.Columns.Name.ordinal());
+
+ repositoriesTable.setCellSelectionEnabled(false);
+ repositoriesTable.setRowSelectionAllowed(true);
+ repositoriesTable.setRowHeight(nameRenderer.getFont().getSize() + 8);
+ repositoriesTable.getTableHeader().setReorderingAllowed(false);
+ repositoriesTable.setGridColor(new Color(0xd9d9d9));
+ repositoriesTable.setBackground(Color.white);
+ repositoriesTable.setDefaultRenderer(Date.class,
+ new DateCellRenderer(null, Color.orange.darker()));
+ setRenderer(RepositoriesModel.Columns.Name, nameRenderer);
+ setRenderer(RepositoriesModel.Columns.Type, typeRenderer);
+ setRenderer(RepositoriesModel.Columns.Owner, ownerRenderer);
+ setRenderer(RepositoriesModel.Columns.Size, sizeRenderer);
+
+ repositoriesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting()) {
+ return;
+ }
+ boolean singleSelection = repositoriesTable.getSelectedRowCount() == 1;
+ boolean selected = repositoriesTable.getSelectedRow() > -1;
+ browseRepository.setEnabled(singleSelection);
+ delRepository.setEnabled(selected);
+ cloneRepository.setEnabled(selected);
+ if (selected) {
+ int viewRow = repositoriesTable.getSelectedRow();
+ int modelRow = repositoriesTable.convertRowIndexToModel(viewRow);
+ RepositoryModel model = ((RepositoriesModel) repositoriesTable.getModel()).list
+ .get(modelRow);
+ editRepository.setEnabled(singleSelection
+ && (isAdmin || model.owner.equalsIgnoreCase(GitblitPanel.this.account)));
+ } else {
+ editRepository.setEnabled(false);
+ }
+ }
+ });
+
+ final JTextField repositoryFilter = new JTextField();
+ repositoryFilter.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ filterRepositories(repositoryFilter.getText());
+ }
+ });
+
+ JPanel filterPanel = new JPanel(new BorderLayout(margin, margin));
+ filterPanel.add(new JLabel("Filter"), BorderLayout.WEST);
+ filterPanel.add(repositoryFilter, BorderLayout.CENTER);
+
+ JPanel tablePanel = new JPanel(new BorderLayout(margin, margin));
+ tablePanel.add(filterPanel, BorderLayout.NORTH);
+ tablePanel.add(new JScrollPane(repositoriesTable), BorderLayout.CENTER);
+
+ JPanel repositoryControls = new JPanel();
+ repositoryControls.add(browseRepository);
+ repositoryControls.add(cloneRepository);
+ repositoryControls.add(createRepository);
+ repositoryControls.add(editRepository);
+ repositoryControls.add(delRepository);
+
+ JPanel repositoriesPanel = new JPanel(new BorderLayout(margin, margin));
+ repositoriesPanel.add(newHeaderLabel("Repositories"), BorderLayout.NORTH);
+ repositoriesPanel.add(tablePanel, BorderLayout.CENTER);
+ repositoriesPanel.add(repositoryControls, BorderLayout.SOUTH);
+
+ JButton createUser = new JButton("Create");
+ createUser.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("TODO Create User");
+ }
+ });
+
+ final JButton editUser = new JButton("Edit");
+ editUser.setEnabled(false);
+ editUser.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (UserModel user : getSelectedUsers()) {
+ System.out.println("TODO Edit " + user);
+ }
+ }
+ });
- tabs.addTab("Repositories", new JScrollPane(repositoriesTable));
+ final JButton delUser = new JButton("Delete");
+ delUser.setEnabled(false);
+ delUser.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (UserModel user : getSelectedUsers()) {
+ System.out.println("TODO Delete " + user);
+ }
+ }
+ });
+
+ usersList = new JList();
+ usersList.addListSelectionListener(new ListSelectionListener() {
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting()) {
+ return;
+ }
+ boolean selected = usersList.getSelectedIndex() > -1;
+ boolean singleSelection = usersList.getSelectedIndices().length == 1;
+ editUser.setEnabled(singleSelection && selected);
+ delUser.setEnabled(selected);
+ }
+ });
+
+ JPanel userControls = new JPanel();
+ userControls.add(createUser);
+ userControls.add(editUser);
+ userControls.add(delUser);
+
+ usersPanel = new JPanel(new BorderLayout(margin, margin));
+ usersPanel.add(newHeaderLabel("Users"), BorderLayout.NORTH);
+ usersPanel.add(new JScrollPane(usersList), BorderLayout.CENTER);
+ usersPanel.add(userControls, BorderLayout.SOUTH);
+
+ /*
+ * Assemble the main panel
+ */
+ JPanel mainPanel = new JPanel(new BorderLayout(margin, margin));
+ mainPanel.add(repositoriesPanel, BorderLayout.CENTER);
+ mainPanel.add(usersPanel, BorderLayout.EAST);
+
+ tabs = new JTabbedPane(JTabbedPane.BOTTOM);
+ tabs.addTab("Main", mainPanel);
+ tabs.addTab("Federation", new JPanel());
setLayout(new BorderLayout());
add(tabs, BorderLayout.CENTER);
}
+ private JLabel newHeaderLabel(String text) {
+ JLabel label = new JLabel(text);
+ label.setOpaque(true);
+ label.setForeground(Color.white);
+ label.setBackground(Color.gray);
+ label.setFont(label.getFont().deriveFont(14f));
+ return label;
+ }
+
public void login() throws IOException {
refreshRepositoriesTable();
+
+ try {
+ refreshUsersTable();
+ isAdmin = true;
+ refreshFederationPanel();
+ } catch (ForbiddenException e) {
+ // user does not have administrator privileges
+ // hide admin repository buttons
+ createRepository.setVisible(false);
+ delRepository.setVisible(false);
+
+ // hide users panel
+ usersPanel.setVisible(false);
+
+ // remove federation tab
+ tabs.removeTabAt(1);
+ } catch (IOException e) {
+ System.err.println(e.getMessage());
+ }
}
private void refreshRepositoriesTable() throws IOException {
Map<String, RepositoryModel> repositories = RpcUtils
.getRepositories(url, account, password);
- repositoriesTable.setModel(new RepositoriesModel(repositories));
-
+ repositoriesModel.list.clear();
+ repositoriesModel.list.addAll(repositories.values());
+ repositoriesModel.fireTableDataChanged();
packColumns(repositoriesTable, 2);
}
+ private void setRenderer(RepositoriesModel.Columns col, TableCellRenderer renderer) {
+ String name = repositoriesTable.getColumnName(col.ordinal());
+ repositoriesTable.getColumn(name).setCellRenderer(renderer);
+ }
+
+ private void refreshUsersTable() throws IOException {
+ List<UserModel> users = RpcUtils.getUsers(url, account, password);
+ usersList.setListData(users.toArray());
+ }
+
+ private void refreshFederationPanel() throws IOException {
+ List<FederationModel> registrations = RpcUtils.getFederationRegistrations(url, account,
+ password);
+ }
+
+ private void filterRepositories(final String fragment) {
+ if (StringUtils.isEmpty(fragment)) {
+ repositoriesTable.setRowSorter(defaultSorter);
+ return;
+ }
+ RowFilter<RepositoriesModel, Object> containsFilter = new RowFilter<RepositoriesModel, Object>() {
+ public boolean include(Entry<? extends RepositoriesModel, ? extends Object> entry) {
+ for (int i = entry.getValueCount() - 1; i >= 0; i--) {
+ if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ RepositoriesModel model = (RepositoriesModel) repositoriesTable.getModel();
+ TableRowSorter<RepositoriesModel> sorter = new TableRowSorter<RepositoriesModel>(model);
+ sorter.setRowFilter(containsFilter);
+ repositoriesTable.setRowSorter(sorter);
+ }
+
+ private List<RepositoryModel> getSelectedRepositories() {
+ List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();
+ for (int viewRow : repositoriesTable.getSelectedRows()) {
+ int modelRow = repositoriesTable.convertRowIndexToModel(viewRow);
+ RepositoryModel model = ((RepositoriesModel) repositoriesTable.getModel()).list
+ .get(modelRow);
+ repositories.add(model);
+ }
+ return repositories;
+ }
+
+ private List<UserModel> getSelectedUsers() {
+ List<UserModel> users = new ArrayList<UserModel>();
+ for (int viewRow : usersList.getSelectedIndices()) {
+ UserModel model = (UserModel) usersList.getModel().getElementAt(viewRow);
+ users.add(model);
+ }
+ return users;
+ }
+
private void packColumns(JTable table, int margin) {
for (int c = 0; c < table.getColumnCount(); c++) {
packColumn(table, c, 4);
@@ -109,4 +448,21 @@ public class GitblitPanel extends JPanel {
// Set the width
col.setPreferredWidth(width);
}
+
+ @Override
+ public Insets getInsets() {
+ return insets;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ if (isAdmin) {
+ return new Dimension(950, 550);
+ }
+ return new Dimension(775, 450);
+ }
+
+ @Override
+ public void closeTab(Component c) {
+ }
}
diff --git a/src/com/gitblit/client/GitblitRegistration.java b/src/com/gitblit/client/GitblitRegistration.java
new file mode 100644
index 00000000..482bf8f2
--- /dev/null
+++ b/src/com/gitblit/client/GitblitRegistration.java
@@ -0,0 +1,47 @@
+/*
+ * 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.io.Serializable;
+
+import com.gitblit.utils.StringUtils;
+
+/**
+ * Simple class to encapsulate a Gitblit server registration.
+ *
+ * @author James Moger
+ *
+ */
+public class GitblitRegistration implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ String name;
+ String url;
+ String account;
+ char[] password;
+
+ public GitblitRegistration(String name, String url, String account, char[] password) {
+ this.url = url;
+ this.account = account;
+ this.password = password;
+ if (StringUtils.isEmpty(name)) {
+ this.name = url.substring(url.indexOf("//") + 2);
+ } else {
+ this.name = name;
+ }
+ }
+}
diff --git a/src/com/gitblit/client/NameRenderer.java b/src/com/gitblit/client/NameRenderer.java
new file mode 100644
index 00000000..41393fb5
--- /dev/null
+++ b/src/com/gitblit/client/NameRenderer.java
@@ -0,0 +1,65 @@
+/*
+ * 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.Color;
+import java.awt.Component;
+
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableCellRenderer;
+
+/**
+ * Repository name cell renderer. This renderer shows the group name in a gray
+ * color and accentuates the repository name in a cornflower blue color.
+ *
+ * @author James Moger
+ *
+ */
+public class NameRenderer extends DefaultTableCellRenderer {
+
+ private static final long serialVersionUID = 1L;
+
+ final String groupSpan;
+
+ public NameRenderer(Color group, Color repo) {
+ groupSpan = "<span style='color:" + getHexColor(group) + "'>";
+ setForeground(repo);
+ }
+
+ String getHexColor(Color c) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Integer.toHexString((c.getRGB() & 0x00FFFFFF)));
+ while (sb.length() < 6)
+ sb.insert(0, '0');
+ sb.insert(0, '#');
+ return sb.toString();
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
+ boolean hasFocus, int row, int column) {
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ String name = value.toString();
+ int lastSlash = name.lastIndexOf('/');
+ if (!isSelected && lastSlash > -1) {
+ String group = name.substring(0, lastSlash + 1);
+ String repo = name.substring(lastSlash + 1);
+ setText("<html><body>" + groupSpan + group + "</span>" + repo);
+ } else {
+ this.setText(name);
+ }
+ return this;
+ }
+} \ No newline at end of file
diff --git a/src/com/gitblit/client/RepositoriesModel.java b/src/com/gitblit/client/RepositoriesModel.java
index 2a439fb9..d8e448fc 100644
--- a/src/com/gitblit/client/RepositoriesModel.java
+++ b/src/com/gitblit/client/RepositoriesModel.java
@@ -19,22 +19,25 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
-import java.util.Map;
import javax.swing.table.AbstractTableModel;
import com.gitblit.models.RepositoryModel;
+/**
+ * Table model of a list of repositories.
+ *
+ * @author James Moger
+ *
+ */
public class RepositoriesModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
- Map<String, RepositoryModel> repositories;
-
List<RepositoryModel> list;
enum Columns {
- Name, Description, Owner, Last_Change, Size;
+ Name, Description, Owner, Type, Last_Change, Size;
@Override
public String toString() {
@@ -42,15 +45,18 @@ public class RepositoriesModel extends AbstractTableModel {
}
}
- public RepositoriesModel(Map<String, RepositoryModel> repositories) {
- this.repositories = repositories;
- list = new ArrayList<RepositoryModel>(repositories.values());
- Collections.sort(list);
+ public RepositoriesModel() {
+ this(new ArrayList<RepositoryModel>());
+ }
+
+ public RepositoriesModel(List<RepositoryModel> repositories) {
+ this.list = repositories;
+ Collections.sort(this.list);
}
@Override
public int getRowCount() {
- return repositories.size();
+ return list.size();
}
@Override
@@ -74,6 +80,9 @@ public class RepositoriesModel extends AbstractTableModel {
public Class<?> getColumnClass(int columnIndex) {
Columns col = Columns.values()[columnIndex];
switch (col) {
+ case Name:
+ case Type:
+ return RepositoryModel.class;
case Last_Change:
return Date.class;
}
@@ -86,11 +95,13 @@ public class RepositoriesModel extends AbstractTableModel {
Columns col = Columns.values()[columnIndex];
switch (col) {
case Name:
- return model.name;
+ return model;
case Description:
return model.description;
case Owner:
return model.owner;
+ case Type:
+ return model;
case Last_Change:
return model.lastChange;
case Size:
diff --git a/src/com/gitblit/client/TypeRenderer.java b/src/com/gitblit/client/TypeRenderer.java
new file mode 100644
index 00000000..8f92dcf4
--- /dev/null
+++ b/src/com/gitblit/client/TypeRenderer.java
@@ -0,0 +1,119 @@
+/*
+ * 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.Component;
+import java.awt.GridLayout;
+import java.io.Serializable;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+import com.gitblit.models.RepositoryModel;
+
+/**
+ * Renders the type indicators (tickets, frozen, access restriction, etc) in a
+ * single cell.
+ *
+ * @author James Moger
+ *
+ */
+public class TypeRenderer extends JPanel implements TableCellRenderer, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final ImageIcon blankIcon;
+
+ private final ImageIcon pushIcon;
+
+ private final ImageIcon pullIcon;
+
+ private final ImageIcon viewIcon;
+
+ private final ImageIcon tixIcon;
+
+ private final ImageIcon doxIcon;
+
+ private final ImageIcon frozenIcon;
+
+ private final ImageIcon federatedIcon;
+
+ public TypeRenderer() {
+ super(new GridLayout(1, 0, 1, 0));
+ blankIcon = new ImageIcon(getClass().getResource("/blank.png"));
+ pushIcon = new ImageIcon(getClass().getResource("/lock_go_16x16.png"));
+ pullIcon = new ImageIcon(getClass().getResource("/lock_pull_16x16.png"));
+ viewIcon = new ImageIcon(getClass().getResource("/shield_16x16.png"));
+ tixIcon = new ImageIcon(getClass().getResource("/bug_16x16.png"));
+ doxIcon = new ImageIcon(getClass().getResource("/book_16x16.png"));
+ frozenIcon = new ImageIcon(getClass().getResource("/cold_16x16.png"));
+ federatedIcon = new ImageIcon(getClass().getResource("/federated_16x16.png"));
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
+ boolean hasFocus, int row, int column) {
+ if (isSelected)
+ setBackground(table.getSelectionBackground());
+ else
+ setBackground(table.getBackground());
+ removeAll();
+ if (value instanceof RepositoryModel) {
+ RepositoryModel model = (RepositoryModel) value;
+ if (model.useTickets) {
+ add(new JLabel(tixIcon));
+ } else {
+ add(new JLabel(blankIcon));
+ }
+ if (model.useDocs) {
+ add(new JLabel(doxIcon));
+ } else {
+ add(new JLabel(blankIcon));
+ }
+ if (model.isFrozen) {
+ add(new JLabel(frozenIcon));
+ } else {
+ add(new JLabel(blankIcon));
+ }
+ if (model.isFederated) {
+ add(new JLabel(federatedIcon));
+ } else {
+ add(new JLabel(blankIcon));
+ }
+
+ switch (model.accessRestriction) {
+ case NONE:
+ add(new JLabel(blankIcon));
+ break;
+ case PUSH:
+ add(new JLabel(pushIcon));
+ break;
+ case CLONE:
+ add(new JLabel(pullIcon));
+ break;
+ case VIEW:
+ add(new JLabel(viewIcon));
+ break;
+ default:
+ add(new JLabel(blankIcon));
+ }
+ }
+ return this;
+ }
+} \ No newline at end of file
diff --git a/src/com/gitblit/client/splash.png b/src/com/gitblit/client/splash.png
new file mode 100644
index 00000000..d63932fb
--- /dev/null
+++ b/src/com/gitblit/client/splash.png
Binary files differ