|
|
@@ -30,202 +30,202 @@ import com.gitblit.wicket.pages.UserPage; |
|
|
|
|
|
|
|
public class NestedRepositoryTreePanel extends BasePanel { |
|
|
|
|
|
|
|
private static final long serialVersionUID = 1L; |
|
|
|
|
|
|
|
public NestedRepositoryTreePanel(String wicketId, IModel<TreeNodeModel> model, final Map<AccessRestrictionType, String> accessRestrictionTranslations, boolean linksActive) { |
|
|
|
super(wicketId); |
|
|
|
|
|
|
|
final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true); |
|
|
|
final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true); |
|
|
|
|
|
|
|
TreeNodeModel node = model.getObject(); |
|
|
|
Fragment nodeHeader = new Fragment("nodeHeader", "groupRepositoryRow", this); |
|
|
|
add(nodeHeader); |
|
|
|
WebMarkupContainer firstColumn = new WebMarkupContainer("firstColumn"); |
|
|
|
nodeHeader.add(firstColumn); |
|
|
|
RepeatingView depth = new RepeatingView("depth"); |
|
|
|
for(int i=0; i<node.getDepth();i++) { |
|
|
|
depth.add(new WebMarkupContainer(depth.newChildId())); |
|
|
|
} |
|
|
|
firstColumn.add(depth); |
|
|
|
firstColumn.add(new Fragment("groupCollapsible", "tableGroupMinusCollapsible", this)); |
|
|
|
if(node.getParent()!=null) { |
|
|
|
addChildOfNodeIdCssClassesToRow(nodeHeader, node.getParent()); |
|
|
|
} |
|
|
|
nodeHeader.add(new AttributeAppender("data-node-id", Model.of(node.hashCode()), " ")); |
|
|
|
|
|
|
|
String name = node.getName(); |
|
|
|
if (name.startsWith(ModelUtils.getUserRepoPrefix())) { |
|
|
|
// user page |
|
|
|
String username = ModelUtils.getUserNameFromRepoPath(name); |
|
|
|
UserModel user = app().users().getUserModel(username); |
|
|
|
firstColumn.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()), UserPage.class, WicketUtils.newUsernameParameter(username))); |
|
|
|
nodeHeader.add(new Label("groupDescription", getString("gb.personalRepositories"))); |
|
|
|
} else { |
|
|
|
// project page |
|
|
|
firstColumn.add(new LinkPanel("groupName", null, name, ProjectPage.class, WicketUtils.newProjectParameter(name))); |
|
|
|
nodeHeader.add(new Label("groupDescription", "")); |
|
|
|
} |
|
|
|
WicketUtils.addCssClass(nodeHeader, "group collapsible tree"); |
|
|
|
|
|
|
|
add(new ListView<TreeNodeModel>("subFolders", node.getSubFolders()) { |
|
|
|
private static final long serialVersionUID = 1L; |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void populateItem(ListItem<TreeNodeModel> item) { |
|
|
|
item.add(new NestedRepositoryTreePanel("rowContent", item.getModel(), accessRestrictionTranslations, linksActive)); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean isVisible() { |
|
|
|
return super.isVisible() && !node.getSubFolders().isEmpty(); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
add(new ListView<RepositoryModel>("repositories", node.getRepositories()) { |
|
|
|
private static final long serialVersionUID = 1L; |
|
|
|
|
|
|
|
int counter = 0; |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean isVisible() { |
|
|
|
return super.isVisible() && !node.getRepositories().isEmpty(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void populateItem(ListItem<RepositoryModel> item) { |
|
|
|
|
|
|
|
RepositoryModel entry = item.getModelObject(); |
|
|
|
WebMarkupContainer rowContent = new WebMarkupContainer("rowContent"); |
|
|
|
item.add(rowContent); |
|
|
|
addChildOfNodeIdCssClassesToRow(rowContent, node); |
|
|
|
WebMarkupContainer firstColumn = new WebMarkupContainer("firstColumn"); |
|
|
|
rowContent.add(firstColumn); |
|
|
|
RepeatingView depth = new RepeatingView("depth"); |
|
|
|
for(int i=0; i<node.getDepth();i++) { |
|
|
|
depth.add(new WebMarkupContainer(depth.newChildId())); |
|
|
|
} |
|
|
|
firstColumn.add(depth); |
|
|
|
|
|
|
|
// show colored repository type icon |
|
|
|
Fragment iconFragment; |
|
|
|
if (entry.isMirror) { |
|
|
|
iconFragment = new Fragment("repoIcon", "mirrorIconFragment", this); |
|
|
|
} else if (entry.isFork()) { |
|
|
|
iconFragment = new Fragment("repoIcon", "forkIconFragment", this); |
|
|
|
} else if (entry.isBare) { |
|
|
|
iconFragment = new Fragment("repoIcon", "repoIconFragment", this); |
|
|
|
} else { |
|
|
|
iconFragment = new Fragment("repoIcon", "cloneIconFragment", this); |
|
|
|
} |
|
|
|
if (showSwatch) { |
|
|
|
WicketUtils.setCssStyle(iconFragment, "color:" + StringUtils.getColor(entry.toString())); |
|
|
|
} |
|
|
|
firstColumn.add(iconFragment); |
|
|
|
|
|
|
|
// try to strip group name for less cluttered list |
|
|
|
String repoName = StringUtils.getLastPathElement(entry.toString()); |
|
|
|
|
|
|
|
if (linksActive) { |
|
|
|
Class<? extends BasePage> linkPage = SummaryPage.class; |
|
|
|
PageParameters pp = WicketUtils.newRepositoryParameter(entry.name); |
|
|
|
firstColumn.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp)); |
|
|
|
rowContent.add(new LinkPanel("repositoryDescription", "list", entry.description, linkPage, pp)); |
|
|
|
} else { |
|
|
|
// no links like on a federation page |
|
|
|
firstColumn.add(new Label("repositoryName", repoName)); |
|
|
|
rowContent.add(new Label("repositoryDescription", entry.description)); |
|
|
|
} |
|
|
|
if (entry.hasCommits) { |
|
|
|
// Existing repository |
|
|
|
rowContent.add(new Label("repositorySize", entry.size).setVisible(showSize)); |
|
|
|
} else { |
|
|
|
// New repository |
|
|
|
rowContent.add(new Label("repositorySize", "<span class='empty'>(" + getString("gb.empty") + ")</span>").setEscapeModelStrings(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (entry.isSparkleshared()) { |
|
|
|
rowContent.add(WicketUtils.newImage("sparkleshareIcon", "star_16x16.png", getString("gb.isSparkleshared"))); |
|
|
|
} else { |
|
|
|
rowContent.add(WicketUtils.newClearPixel("sparkleshareIcon").setVisible(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (!entry.isMirror && entry.isFrozen) { |
|
|
|
rowContent.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", getString("gb.isFrozen"))); |
|
|
|
} else { |
|
|
|
rowContent.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (entry.isFederated) { |
|
|
|
rowContent.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png", getString("gb.isFederated"))); |
|
|
|
} else { |
|
|
|
rowContent.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (entry.isMirror) { |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png", getString("gb.isMirror"))); |
|
|
|
} else { |
|
|
|
switch (entry.accessRestriction) { |
|
|
|
case NONE: |
|
|
|
rowContent.add(WicketUtils.newBlankImage("accessRestrictionIcon")); |
|
|
|
break; |
|
|
|
case PUSH: |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction))); |
|
|
|
break; |
|
|
|
case CLONE: |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction))); |
|
|
|
break; |
|
|
|
case VIEW: |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction))); |
|
|
|
break; |
|
|
|
default: |
|
|
|
rowContent.add(WicketUtils.newBlankImage("accessRestrictionIcon")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
String owner = ""; |
|
|
|
if (!ArrayUtils.isEmpty(entry.owners)) { |
|
|
|
// display first owner |
|
|
|
for (String username : entry.owners) { |
|
|
|
UserModel ownerModel = app().users().getUserModel(username); |
|
|
|
if (ownerModel != null) { |
|
|
|
owner = ownerModel.getDisplayName(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (entry.owners.size() > 1) { |
|
|
|
owner += ", ..."; |
|
|
|
} |
|
|
|
} |
|
|
|
Label ownerLabel = new Label("repositoryOwner", owner); |
|
|
|
WicketUtils.setHtmlTooltip(ownerLabel, ArrayUtils.toString(entry.owners)); |
|
|
|
rowContent.add(ownerLabel); |
|
|
|
|
|
|
|
String lastChange; |
|
|
|
if (entry.lastChange.getTime() == 0) { |
|
|
|
lastChange = "--"; |
|
|
|
} else { |
|
|
|
lastChange = getTimeUtils().timeAgo(entry.lastChange); |
|
|
|
} |
|
|
|
Label lastChangeLabel = new Label("repositoryLastChange", lastChange); |
|
|
|
rowContent.add(lastChangeLabel); |
|
|
|
WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange)); |
|
|
|
if (!StringUtils.isEmpty(entry.lastChangeAuthor)) { |
|
|
|
WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor); |
|
|
|
} |
|
|
|
|
|
|
|
String clazz = counter % 2 == 0 ? "light" : "dark"; |
|
|
|
WicketUtils.addCssClass(rowContent, clazz); |
|
|
|
counter++; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private void addChildOfNodeIdCssClassesToRow(Component row, TreeNodeModel parentNode) { |
|
|
|
row.add(new AttributeAppender("class", Model.of("child-of-"+ parentNode.hashCode()), " ")); |
|
|
|
if(parentNode.getParent() != null) { |
|
|
|
addChildOfNodeIdCssClassesToRow(row, parentNode.getParent()); |
|
|
|
} |
|
|
|
} |
|
|
|
private static final long serialVersionUID = 1L; |
|
|
|
|
|
|
|
public NestedRepositoryTreePanel(final String wicketId, final IModel<TreeNodeModel> model, final Map<AccessRestrictionType, String> accessRestrictionTranslations, final boolean linksActive) { |
|
|
|
super(wicketId); |
|
|
|
|
|
|
|
final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true); |
|
|
|
final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true); |
|
|
|
|
|
|
|
final TreeNodeModel node = model.getObject(); |
|
|
|
Fragment nodeHeader = new Fragment("nodeHeader", "groupRepositoryRow", this); |
|
|
|
add(nodeHeader); |
|
|
|
WebMarkupContainer firstColumn = new WebMarkupContainer("firstColumn"); |
|
|
|
nodeHeader.add(firstColumn); |
|
|
|
RepeatingView depth = new RepeatingView("depth"); |
|
|
|
for(int i=0; i<node.getDepth();i++) { |
|
|
|
depth.add(new WebMarkupContainer(depth.newChildId())); |
|
|
|
} |
|
|
|
firstColumn.add(depth); |
|
|
|
firstColumn.add(new Fragment("groupCollapsible", "tableGroupMinusCollapsible", this)); |
|
|
|
if(node.getParent()!=null) { |
|
|
|
addChildOfNodeIdCssClassesToRow(nodeHeader, node.getParent()); |
|
|
|
} |
|
|
|
nodeHeader.add(new AttributeAppender("data-node-id", Model.of(node.hashCode()), " ")); |
|
|
|
|
|
|
|
String name = node.getName(); |
|
|
|
if (name.startsWith(ModelUtils.getUserRepoPrefix())) { |
|
|
|
// user page |
|
|
|
String username = ModelUtils.getUserNameFromRepoPath(name); |
|
|
|
UserModel user = app().users().getUserModel(username); |
|
|
|
firstColumn.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()), UserPage.class, WicketUtils.newUsernameParameter(username))); |
|
|
|
nodeHeader.add(new Label("groupDescription", getString("gb.personalRepositories"))); |
|
|
|
} else { |
|
|
|
// project page |
|
|
|
firstColumn.add(new LinkPanel("groupName", null, name, ProjectPage.class, WicketUtils.newProjectParameter(name))); |
|
|
|
nodeHeader.add(new Label("groupDescription", "")); |
|
|
|
} |
|
|
|
WicketUtils.addCssClass(nodeHeader, "group collapsible tree"); |
|
|
|
|
|
|
|
add(new ListView<TreeNodeModel>("subFolders", node.getSubFolders()) { |
|
|
|
private static final long serialVersionUID = 1L; |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void populateItem(ListItem<TreeNodeModel> item) { |
|
|
|
item.add(new NestedRepositoryTreePanel("rowContent", item.getModel(), accessRestrictionTranslations, linksActive)); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean isVisible() { |
|
|
|
return super.isVisible() && !node.getSubFolders().isEmpty(); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
add(new ListView<RepositoryModel>("repositories", node.getRepositories()) { |
|
|
|
private static final long serialVersionUID = 1L; |
|
|
|
|
|
|
|
int counter = 0; |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean isVisible() { |
|
|
|
return super.isVisible() && !node.getRepositories().isEmpty(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
protected void populateItem(ListItem<RepositoryModel> item) { |
|
|
|
|
|
|
|
RepositoryModel entry = item.getModelObject(); |
|
|
|
WebMarkupContainer rowContent = new WebMarkupContainer("rowContent"); |
|
|
|
item.add(rowContent); |
|
|
|
addChildOfNodeIdCssClassesToRow(rowContent, node); |
|
|
|
WebMarkupContainer firstColumn = new WebMarkupContainer("firstColumn"); |
|
|
|
rowContent.add(firstColumn); |
|
|
|
RepeatingView depth = new RepeatingView("depth"); |
|
|
|
for(int i=0; i<node.getDepth();i++) { |
|
|
|
depth.add(new WebMarkupContainer(depth.newChildId())); |
|
|
|
} |
|
|
|
firstColumn.add(depth); |
|
|
|
|
|
|
|
// show colored repository type icon |
|
|
|
Fragment iconFragment; |
|
|
|
if (entry.isMirror) { |
|
|
|
iconFragment = new Fragment("repoIcon", "mirrorIconFragment", this); |
|
|
|
} else if (entry.isFork()) { |
|
|
|
iconFragment = new Fragment("repoIcon", "forkIconFragment", this); |
|
|
|
} else if (entry.isBare) { |
|
|
|
iconFragment = new Fragment("repoIcon", "repoIconFragment", this); |
|
|
|
} else { |
|
|
|
iconFragment = new Fragment("repoIcon", "cloneIconFragment", this); |
|
|
|
} |
|
|
|
if (showSwatch) { |
|
|
|
WicketUtils.setCssStyle(iconFragment, "color:" + StringUtils.getColor(entry.toString())); |
|
|
|
} |
|
|
|
firstColumn.add(iconFragment); |
|
|
|
|
|
|
|
// try to strip group name for less cluttered list |
|
|
|
String repoName = StringUtils.getLastPathElement(entry.toString()); |
|
|
|
|
|
|
|
if (linksActive) { |
|
|
|
Class<? extends BasePage> linkPage = SummaryPage.class; |
|
|
|
PageParameters pp = WicketUtils.newRepositoryParameter(entry.name); |
|
|
|
firstColumn.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp)); |
|
|
|
rowContent.add(new LinkPanel("repositoryDescription", "list", entry.description, linkPage, pp)); |
|
|
|
} else { |
|
|
|
// no links like on a federation page |
|
|
|
firstColumn.add(new Label("repositoryName", repoName)); |
|
|
|
rowContent.add(new Label("repositoryDescription", entry.description)); |
|
|
|
} |
|
|
|
if (entry.hasCommits) { |
|
|
|
// Existing repository |
|
|
|
rowContent.add(new Label("repositorySize", entry.size).setVisible(showSize)); |
|
|
|
} else { |
|
|
|
// New repository |
|
|
|
rowContent.add(new Label("repositorySize", "<span class='empty'>(" + getString("gb.empty") + ")</span>").setEscapeModelStrings(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (entry.isSparkleshared()) { |
|
|
|
rowContent.add(WicketUtils.newImage("sparkleshareIcon", "star_16x16.png", getString("gb.isSparkleshared"))); |
|
|
|
} else { |
|
|
|
rowContent.add(WicketUtils.newClearPixel("sparkleshareIcon").setVisible(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (!entry.isMirror && entry.isFrozen) { |
|
|
|
rowContent.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", getString("gb.isFrozen"))); |
|
|
|
} else { |
|
|
|
rowContent.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (entry.isFederated) { |
|
|
|
rowContent.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png", getString("gb.isFederated"))); |
|
|
|
} else { |
|
|
|
rowContent.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false)); |
|
|
|
} |
|
|
|
|
|
|
|
if (entry.isMirror) { |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png", getString("gb.isMirror"))); |
|
|
|
} else { |
|
|
|
switch (entry.accessRestriction) { |
|
|
|
case NONE: |
|
|
|
rowContent.add(WicketUtils.newBlankImage("accessRestrictionIcon")); |
|
|
|
break; |
|
|
|
case PUSH: |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction))); |
|
|
|
break; |
|
|
|
case CLONE: |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction))); |
|
|
|
break; |
|
|
|
case VIEW: |
|
|
|
rowContent.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction))); |
|
|
|
break; |
|
|
|
default: |
|
|
|
rowContent.add(WicketUtils.newBlankImage("accessRestrictionIcon")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
String owner = ""; |
|
|
|
if (!ArrayUtils.isEmpty(entry.owners)) { |
|
|
|
// display first owner |
|
|
|
for (String username : entry.owners) { |
|
|
|
UserModel ownerModel = app().users().getUserModel(username); |
|
|
|
if (ownerModel != null) { |
|
|
|
owner = ownerModel.getDisplayName(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (entry.owners.size() > 1) { |
|
|
|
owner += ", ..."; |
|
|
|
} |
|
|
|
} |
|
|
|
Label ownerLabel = new Label("repositoryOwner", owner); |
|
|
|
WicketUtils.setHtmlTooltip(ownerLabel, ArrayUtils.toString(entry.owners)); |
|
|
|
rowContent.add(ownerLabel); |
|
|
|
|
|
|
|
String lastChange; |
|
|
|
if (entry.lastChange.getTime() == 0) { |
|
|
|
lastChange = "--"; |
|
|
|
} else { |
|
|
|
lastChange = getTimeUtils().timeAgo(entry.lastChange); |
|
|
|
} |
|
|
|
Label lastChangeLabel = new Label("repositoryLastChange", lastChange); |
|
|
|
rowContent.add(lastChangeLabel); |
|
|
|
WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange)); |
|
|
|
if (!StringUtils.isEmpty(entry.lastChangeAuthor)) { |
|
|
|
WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor); |
|
|
|
} |
|
|
|
|
|
|
|
String clazz = counter % 2 == 0 ? "light" : "dark"; |
|
|
|
WicketUtils.addCssClass(rowContent, clazz); |
|
|
|
counter++; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private void addChildOfNodeIdCssClassesToRow(Component row, TreeNodeModel parentNode) { |
|
|
|
row.add(new AttributeAppender("class", Model.of("child-of-"+ parentNode.hashCode()), " ")); |
|
|
|
if(parentNode.getParent() != null) { |
|
|
|
addChildOfNodeIdCssClassesToRow(row, parentNode.getParent()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |