Add account permissions page

This commit is contained in:
steve 2013-10-14 11:09:35 +08:00
parent 679ec52eb4
commit fd13b87d86
36 changed files with 1975 additions and 464 deletions

View File

@ -72,7 +72,7 @@ public class DefaultGeneralDao implements GeneralDao, Serializable {
return null;
}
return (Class<T>) entityClass;
return entityClass;
}
@Sessional
@ -99,7 +99,7 @@ public class DefaultGeneralDao implements GeneralDao, Serializable {
public <T extends AbstractEntity> int count(DetachedCriteria detachedCriteria) {
Criteria criteria = detachedCriteria.getExecutableCriteria(getSession());
criteria.setProjection(Projections.rowCount());
return (Integer) criteria.uniqueResult();
return ((Long) criteria.uniqueResult()).intValue();
}
public Object writeReplace() throws ObjectStreamException {

View File

@ -36,7 +36,13 @@
<version>1.0.29</version>
</dependency>
<!-- JERSEY CLIENT -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.17.1</version>
</dependency>
<!-- WICKET -->
<dependency>
<groupId>com.vaynberg.wicket.select2</groupId>
@ -66,7 +72,7 @@
<artifactId>imgscalr-lib</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>com.pmease</groupId>
<artifactId>commons.jetty</artifactId>

View File

@ -2,10 +2,13 @@ package com.pmease.gitop.web;
import javax.inject.Singleton;
import com.pmease.commons.jersey.JerseyConfigurator;
import com.pmease.commons.jersey.JerseyEnvironment;
import com.pmease.commons.jetty.ServletConfigurator;
import com.pmease.commons.loader.AbstractPluginModule;
import com.pmease.commons.wicket.AbstractWicketConfig;
import com.pmease.gitop.core.validation.UserNameReservation;
import com.pmease.gitop.web.resource.TestResource;
/**
* NOTE: Do not forget to rename moduleClass property defined in the pom if you've renamed this class.
@ -23,6 +26,15 @@ public class WebModule extends AbstractPluginModule {
contribute(ServletConfigurator.class, WebServletConfigurator.class);
contribute(UserNameReservation.class, WebUserNameReservation.class);
contribute(JerseyConfigurator.class, new JerseyConfigurator() {
@Override
public void configure(JerseyEnvironment environment) {
environment.addComponentFromPackage(TestResource.class);
}
});
}
}

View File

@ -38,6 +38,10 @@ ul.disc { list-style:disc outside; }
.piped:after { clear: both; }
ul.piped, ol.piped { margin: 0; padding: 0; }
.action-links { white-space: nowrap; }
.action-links > .link-item { display: inline-block; margin-left: 12px; }
.action-links > .link-item:first-child { margin-left: 0;}
/* LINKS */
.checkable-link { color: #333; cursor: pointer; }
.checkable-link:hover { text-decoration: none; }
@ -47,10 +51,19 @@ ul.piped, ol.piped { margin: 0; padding: 0; }
em.checkable-link { color: #888 !important; }
/** LIST GROUP */
.list-navs > .list-group-item { border-width: 1px 0; }
.list-navs > .list-group-item { border-width: 1px 0; positioin: relative; }
.list-navs > .list-group-item:first-child,
.list-navs > .list-group-item:last-child { border-radius: 0; }
.list-group.list-group-hoverable .list-group-item:hover { background: #ffe; }
.list-group-item .item-actions { position: absolute; right: 30px; top: 10px; }
.list-group-item .item-actions a { color: #999; }
.list-group-item .item-actions a:hover { color: #333; text-decoration: none; }
.list-view .list-group-item { border-left: none; border-right: none; position: relative; }
.list-view .list-group-item:first-child,
.list-view .list-group-item:last-child { border-radius: 0; }
/* ADDITIONAL ICONS */
@font-face {
@ -190,17 +203,23 @@ a > .icon-null, .icon-null { display: inline-block; width: 10px; }
.table { width: 100%; }
.norecords-tr .norecords-td { background: #F9F7ED; font-size: 1.5em; line-height: 3em; font-weight: bold; text-align: center; }
.table th a { color: #333; text-decoration: underline; }
.operations-td a { color: #999; }
.operations-td a:hover { color: #333; }
.table .operations-td { white-space: nowrap; }
.operations-td a, .operations-td a.iconlink { color: #999; }
.operations-td a:hover { color: #333; text-decoration: none; }
.search-nav-td { font-size: 11px; }
.search-nav-td form { position: relative; }
.search-nav-td input.form-control, .search-nav-td select.form-control { padding: 2px 4px; height: 24px; }
.search-nav-td .btn { padding: 2px 8px; height: 24px; }
.form-inline.navigation-form select.form-control { width: 60px; }
.form-inline.navigation-form input.form-control { width: 40px; }
.form-inline.navigation-form .btn-group { margin-left: 6px; }
.search-form button { position: absolute; right: 2px; top: 1px; border: none; height: 22px; background: transparent; color: #888; }
/**
* FORM COMPONENT
*/
/* FORM COMPONENT */
.select2-container .select2-choice { padding-top: 4px; padding-bottom: 4px; height: auto; }
.user-choice-row .img-thumbnail { float: left; }
.user-choice-row p { margin-left: 44px; margin-bottom: 0; }
.user-choice-row p.text-muted { font-size: 0.85em; }
.select2-highlighted .user-choice-row p.text-muted { color: #ccc; }
.required { color: #a00; margin-left: 3px;}
@ -258,65 +277,13 @@ a > .icon-null, .icon-null { display: inline-block; width: 10px; }
transition: all 0.2s ease-in-out;
}
.avatar.img-thumbnail { padding: 1px; }
.avatar > img { display: block; margin: 0 auto; width: 100%; height: 100%; border-radius: 3px; }
.avatar-circle { border-radius: 50%; }
.avatar-circle > img { border-radius: 50%; }
.avatar-big { width: 32px; height: 32px; }
.avatar-xlarge { width: 128px; height: 128px; }
/**
* LAYOUT
*/
#globalheader, #main, #globalfooter {position: relative;}
#globalheader:before, #globalheader:after, #main:before, #main:after, #globalfooter:before, #globalfooter:after {
display: table;
content: " ";
}
#globalheader:after, #main:after, #globalfooter:after { clear: both; }
/**
* GLOBAL HEADER
*/
#globalheader .navbar { border-width: 0 0 1px 0; border-color: #ddd; border-radius: 0; margin: 0;
background: #f0f2f4; color: white;
}
#globalheader .navbar-brand { padding: 10px 10px 10px 20px; }
#globalheader .search-form { margin-top: 12px; margin-bottom: 0;}
.search-form input.text-field {
height: 30px;
width: 200px;
line-height: normal;
text-indent: 0;
position: relative;
padding: 3px 30px 3px 8px;
font-size: 12px;
-webkit-transition: width 200ms, background 200ms ease; transition: width 200ms, background 200ms ease;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAEJWlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XpShal6dgqJJQ6N4mpmxjb6baqT3uBNwb8AUDZAw9IPCGNX2J72fYA2qSpoIpqEtIeOvFDiEl7QVX4rp3YDoqYo15/Pec753zn3GubqO+zkmkaUYVope5YhUxSOX1mUenboig9Sf00RP0lzTYT+fwc4RJccQ9dEaIHPxFWottjPfwhak/YX+a2RhR5BN5G2dZWgM8RxQzNtByi+F3YJ886JnDfU8CPWxAIrApc9XBK4CUPn3Y5xcI0OEKrrNVKZeB14NGlkL0awp4GMJAnw+vc0jVFzCJvNSq6wV2HtzzEHWL+H1wxmujZvYaxDtjL8ydwHxG916yZQht/rJXS88DPwX7DdJLC/gLw783lhQTwAaLoYxXr+ILHj768Viu+DrwH9rLuZItt+1p9KXcSGLHRjeXGCZFHcG5o9jRmSc8A36nxrNhj6JGozFNp4FHg4Vpzpp1fmrVX54XdzbNWm84BI49kvVWazQMPAb9rNQqiFjRLG9zIiFrIL10znXxbg7RTN3KiFvplMrfdHpFT2nFqxRkvlh12rGI7li1W9OPZNn/dNNyzCG3sktUsCG3Iz26VrHQGGHnY37y+IOYGHNtbLqXEbMeBj9GpSIk4NWgJq0Z12iWFCpShJO4mWfBUSCcDFg4vh0WPPErLsPXm5V2OFxMwqm70johGld4cr8K9NqfBBpnKDuHvCJtjR9kkmyKFvcJeZcdYCtYpdsRXkA/pVKhK96DUy/M2NVFZ6DhFyYtDzRE/RrlgvalrN9/7C2qCLhuBH3n8jqG5EZ4A2ZhAp7ux8Jyur3+71/com+zyG7cHrq/TyYfNN3Y3thPbxLoV2w7iY7/EtvHbogR2wHAVrUCV7u6E7fPGunq4CqZDJay/gteA1o7Srh2t1C8OBR4xCf5O7kGOLowGVvVn9Q91U/1EvaT+1lUjyNg1JelD6UvpO+kr6WvpB1KkK9JV6XvpmvSF9I2fs/fee1n8vXf7FTbRrdiFTr3wrDkZclLeJz8rp+Sn5eflOZ+lyIPyhDwj74dnn79vRuDv6kWnM5hVZ6q9a4knQKcFKNHpLLgWpiomXKfzyBp+TtpK2TCbYNn/nNpJcZY7KuLpeCqeICV+ID4Vn4jPCtx58uL74ZvCmvbVe0+Oz+jqgIdYmIqfZ8w9deKsiuhV6Dagmzv8HL4dRNMN87ylV2uOclBVX1IS+JRxJVvXxkeVkmEorstWLG5za5WXx0l8B0Uc0f2C+32L7LkZ2JzXiI7+iXfWrcC22CT63CYafDGwjeCd+MRHRJcPa01r1ctHkciPRHbl0EH3/8hAEu+mO63Wfbyv+j4g2n2/1fpno9Xa/RT5t4muGP8CYGVxecXFpEEAAAEiSURBVCgVhZG9SsRAFIVnkhBwSZ7AYGUXlDSCrYVYaCFKirBZCfgOamvrGySdkGwKEQRXO7XQxiKFINjrvsB2QoT4jThhENELh7nnnHvm5kd2XSeKohh4nncghBiBAEzRT9u2Pcmy7B3elx2G4ZzjODcoQynlA5jQu5z7tm2vNU0zjqLoQyccbjmErDKwkyTJhTbKsty1LOvMdV3lH2vdohkxfGkOKzNN03P0a9o9xXWpQMDzvmjBPNGf4AumpgJTEJmi0S/TvxlcWKwtEdbrut42DfUO8E2g/L5knucD3/dvWb9CeML5jLsEtgCSfOQrbsRxPFMpyYD+D0fwIZgHr2D8zRfN0FcA49eqqipg+A6zD/0ZULf8CN3/GzBCV2ybfQLGkGWtzcDkHAAAAABJRU5ErkJggg==') white no-repeat 180px 8px;
}
.search-form input.text-field:focus { width: 300px; background: white; }
#globalheader .tooltip { white-space: nowrap; }
#globalheader .navbar-right { margin-right: 20px; }
#globalheader .user-links { margin: 0; }
.user-links > li { margin: 0; }
.user-links > li.separator { height: 50px; border-left: 1px solid #d5d5d5; border-right: 1px solid #fefefe; margin: 0 6px;}
.user-links a { padding: 16px 10px 5px; line-height: 20px; }
.user-links a > i { font-size: 16px; }
.user-links a:hover { color: #333; text-decoration: none; }
.user-links li .caret { border-top-color: #09f; }
.user-links li a:hover .caret { border-top-color: #333; }
.user-links > li.avatar-user { white-space: nowrap; }
.user-links > li.avatar-user .avatar { margin-right: 3px; }
/**
* GLOBAL FOOTER
*/
#globalfooter { padding: 20px; border-top: 1px solid #ddd; font-size: 11.9px; }
/**
* MAIN
*/
#main { background: white; }
/** FAUX ROW */
.faux { display: table; width: 100%; border-collapse: collapse; table-layout: fixed; border-spacing: 0; }
.faux-row { display: table-row; }
@ -325,24 +292,3 @@ a > .icon-null, .icon-null { display: inline-block; width: 10px; }
.sidebar-inner { position: relative; width: 240px; overflow-x: hidden; }
.faux .content { }
.sidebar .head, .content .head { padding: 15px 20px; white-space: nowrap; overflow: hidden; border-bottom: 1px solid #ddd; margin-bottom: 20px; }
.sidebar .head a { color: #666; font-weight:bold; line-height: 24px; }
.sidebar .head a:hover { text-decoration: none; color: #09F; }
.sidebar .list-navs > .list-group-item,
.sidebar .list-navs > .list-group-item.active {
padding: 0; margin: 0; border-top-width: 0; background: transparent;
}
.sidebar .list-navs > .list-group-item.active { border-color: #ccc; }
.sidebar .list-navs > .list-group-item:first-child { border-top-width: 1px; }
.sidebar .list-navs > .list-group-item a { padding: 10px 20px; display: block; color: #888; }
.sidebar .list-navs > .list-group-item a:hover { color: #333; text-decoration: none; background: #f2f2f2; }
.sidebar .list-navs > .list-group-item.active a,
.sidebar .list-navs > .list-group-item.active a:hover { color: #222; background: #e5e5e5; font-weight: bold; }
section .head { border-style: solid; border-width: 1px 0; border-color: #ddd; }
section:first-child .head { border-top: none; }
section .head h2, section .head h3 { margin: 0; font-size: 18px; line-height: 24px; color: #888; font-weight: 300; }
section .padder, section > .body { padding: 0px 20px 20px; margin-bottom: 18px; }

View File

@ -1,3 +1,100 @@
/**
* LAYOUT
*/
#globalheader, #main, #globalfooter {position: relative;}
#globalheader:before, #globalheader:after, #main:before, #main:after, #globalfooter:before, #globalfooter:after {
display: table;
content: " ";
}
#globalheader:after, #main:after, #globalfooter:after { clear: both; }
/**
* GLOBAL HEADER
*/
#globalheader .navbar { border-width: 0 0 1px 0; border-color: #ddd; border-radius: 0; margin: 0;
background: #f0f2f4; color: white;
}
#globalheader .navbar-brand { padding: 10px 10px 10px 20px; }
#globalheader .search-form { margin-top: 12px; margin-bottom: 0;}
.search-form input.text-field {
height: 30px;
width: 200px;
line-height: normal;
text-indent: 0;
position: relative;
padding: 3px 30px 3px 8px;
font-size: 12px;
-webkit-transition: width 200ms, background 200ms ease; transition: width 200ms, background 200ms ease;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAEJWlDQ1BJQ0MgUHJvZmlsZQAAOBGFVd9v21QUPolvUqQWPyBYR4eKxa9VU1u5GxqtxgZJk6XpShal6dgqJJQ6N4mpmxjb6baqT3uBNwb8AUDZAw9IPCGNX2J72fYA2qSpoIpqEtIeOvFDiEl7QVX4rp3YDoqYo15/Pec753zn3GubqO+zkmkaUYVope5YhUxSOX1mUenboig9Sf00RP0lzTYT+fwc4RJccQ9dEaIHPxFWottjPfwhak/YX+a2RhR5BN5G2dZWgM8RxQzNtByi+F3YJ886JnDfU8CPWxAIrApc9XBK4CUPn3Y5xcI0OEKrrNVKZeB14NGlkL0awp4GMJAnw+vc0jVFzCJvNSq6wV2HtzzEHWL+H1wxmujZvYaxDtjL8ydwHxG916yZQht/rJXS88DPwX7DdJLC/gLw783lhQTwAaLoYxXr+ILHj768Viu+DrwH9rLuZItt+1p9KXcSGLHRjeXGCZFHcG5o9jRmSc8A36nxrNhj6JGozFNp4FHg4Vpzpp1fmrVX54XdzbNWm84BI49kvVWazQMPAb9rNQqiFjRLG9zIiFrIL10znXxbg7RTN3KiFvplMrfdHpFT2nFqxRkvlh12rGI7li1W9OPZNn/dNNyzCG3sktUsCG3Iz26VrHQGGHnY37y+IOYGHNtbLqXEbMeBj9GpSIk4NWgJq0Z12iWFCpShJO4mWfBUSCcDFg4vh0WPPErLsPXm5V2OFxMwqm70johGld4cr8K9NqfBBpnKDuHvCJtjR9kkmyKFvcJeZcdYCtYpdsRXkA/pVKhK96DUy/M2NVFZ6DhFyYtDzRE/RrlgvalrN9/7C2qCLhuBH3n8jqG5EZ4A2ZhAp7ux8Jyur3+71/com+zyG7cHrq/TyYfNN3Y3thPbxLoV2w7iY7/EtvHbogR2wHAVrUCV7u6E7fPGunq4CqZDJay/gteA1o7Srh2t1C8OBR4xCf5O7kGOLowGVvVn9Q91U/1EvaT+1lUjyNg1JelD6UvpO+kr6WvpB1KkK9JV6XvpmvSF9I2fs/fee1n8vXf7FTbRrdiFTr3wrDkZclLeJz8rp+Sn5eflOZ+lyIPyhDwj74dnn79vRuDv6kWnM5hVZ6q9a4knQKcFKNHpLLgWpiomXKfzyBp+TtpK2TCbYNn/nNpJcZY7KuLpeCqeICV+ID4Vn4jPCtx58uL74ZvCmvbVe0+Oz+jqgIdYmIqfZ8w9deKsiuhV6Dagmzv8HL4dRNMN87ylV2uOclBVX1IS+JRxJVvXxkeVkmEorstWLG5za5WXx0l8B0Uc0f2C+32L7LkZ2JzXiI7+iXfWrcC22CT63CYafDGwjeCd+MRHRJcPa01r1ctHkciPRHbl0EH3/8hAEu+mO63Wfbyv+j4g2n2/1fpno9Xa/RT5t4muGP8CYGVxecXFpEEAAAEiSURBVCgVhZG9SsRAFIVnkhBwSZ7AYGUXlDSCrYVYaCFKirBZCfgOamvrGySdkGwKEQRXO7XQxiKFINjrvsB2QoT4jThhENELh7nnnHvm5kd2XSeKohh4nncghBiBAEzRT9u2Pcmy7B3elx2G4ZzjODcoQynlA5jQu5z7tm2vNU0zjqLoQyccbjmErDKwkyTJhTbKsty1LOvMdV3lH2vdohkxfGkOKzNN03P0a9o9xXWpQMDzvmjBPNGf4AumpgJTEJmi0S/TvxlcWKwtEdbrut42DfUO8E2g/L5knucD3/dvWb9CeML5jLsEtgCSfOQrbsRxPFMpyYD+D0fwIZgHr2D8zRfN0FcA49eqqipg+A6zD/0ZULf8CN3/GzBCV2ybfQLGkGWtzcDkHAAAAABJRU5ErkJggg==') white no-repeat 180px 8px;
}
.search-form input.text-field:focus { width: 300px; background: white; }
#globalheader .tooltip { white-space: nowrap; }
#globalheader .navbar-right { margin-right: 20px; }
#globalheader .user-links { margin: 0; }
.user-links > li { margin: 0; }
.user-links > li.separator { height: 50px; border-left: 1px solid #d5d5d5; border-right: 1px solid #fefefe; margin: 0 6px;}
.user-links a { padding: 16px 10px 5px; line-height: 20px; }
.user-links a > i { font-size: 16px; }
.user-links a:hover { color: #333; text-decoration: none; }
.user-links li .caret { border-top-color: #09f; }
.user-links li a:hover .caret { border-top-color: #333; }
.user-links > li.avatar-user { white-space: nowrap; }
.user-links > li.avatar-user .avatar { margin-right: 3px; }
/**
* GLOBAL FOOTER
*/
#globalfooter { padding: 20px; border-top: 1px solid #ddd; font-size: 11.9px; }
/**
* MAIN
*/
#main { background: white; }
.sidebar .head, .content .head { padding: 15px 20px; white-space: nowrap; overflow: hidden; border-bottom: 1px solid #ddd; margin-bottom: 20px; }
.sidebar .head a { color: #666; font-weight:bold; line-height: 24px; }
.sidebar .head a:hover { text-decoration: none; color: #09F; }
.sidebar .list-navs > .list-group-item,
.sidebar .list-navs > .list-group-item.active {
padding: 0; margin: 0; border-top-width: 0; background: transparent;
}
.sidebar .list-navs > .list-group-item.active { border-color: #ccc; }
.sidebar .list-navs > .list-group-item:first-child { border-top-width: 1px; }
.sidebar .list-navs > .list-group-item a { padding: 10px 20px; display: block; color: #888; }
.sidebar .list-navs > .list-group-item a:hover { color: #333; text-decoration: none; background: #f2f2f2; }
.sidebar .list-navs > .list-group-item.active a,
.sidebar .list-navs > .list-group-item.active a:hover { color: #222; background: #e5e5e5; font-weight: bold; }
section .head { border-style: solid; border-width: 1px 0; border-color: #ddd; }
section:first-child .head { border-top: none; }
section .head h2, section .head h3 { margin: 0; font-size: 18px; line-height: 24px; color: #888; font-weight: 300; }
section .padder, section > .body { padding: 0px 20px 20px; margin-bottom: 18px; }
/** TABLE */
th.wicket_orderUp, th.wicket_orderDown, th.wicket_orderNone { position: relative; }
.wicket_orderUp:before, .wicket_orderDown:before, .wicket_orderNone:before {
font-family: pmease-icons;
font-weight: normal;
font-style: normal;
-webkit-font-smoothing: antialiased;
*margin-right: .3em;
text-decoration: none;
display: inline-block;
speak: none;
position: absolute;
left: 5px;
top: 5px;
color: #666;
}
th.wicket_orderUp a, th.wicket_orderDown a { padding-left: 20px; }
.wicket_orderUp:before { content: "\f062"; }
.wicket_orderDown:before { content: "\f063"; }
/** SERVER INIT PAGE */
.server-init {
text-align: center;
width: 50%;
@ -20,28 +117,22 @@
#login-form .btn { width: 100%;}
#dropzone {
background: white;
width: 150px;
height: 50px;
line-height: 50px;
text-align: center;
font-weight: bold;
}
#dropzone.in {
width: 600px;
height: 200px;
line-height: 200px;
font-size: larger;
}
#dropzone.hover {
background: lawngreen;
}
#dropzone.fade {
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-ms-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
opacity: 1;
}
/* TEAM EDIT PAGE */
.member-list .members { width: 48%; }
.member-list .members.first { float: left; }
.member-list .members.last { float: right; }
.members a { color: #999; font-size: 16px; }
.members .list-group-item:hover a { color: #333; }
.members .item-actions {top: 12px;}
.members .item-actions .img-link { color: #ddd; font-size: 20px; }
.members .list-group-item:hover .img-link, .members .item-actions .img-link:hover { color: #990000; }
.members .avatar { width: 32px; height: 32px; margin-right: 8px; }
.permission-link { color: #666; }
a.permission-link:hover { color: #333; text-decoration: none; }
.user-choice-row .img-thumbnail { float: left; }
.user-choice-row p { margin-left: 44px; margin-bottom: 0; }
.user-choice-row p.text-muted { font-size: 0.85em; }
.btn-group-permissions > a { width: 80px; }

View File

@ -0,0 +1,5 @@
<html xmlns:wicket>
<wicket:panel>
<a wicket:id="link" class="iconlink"><i wicket:id="icon"></i> <span wicket:id="label"></span></a>
</wicket:panel>
</html>

View File

@ -0,0 +1,51 @@
package com.pmease.gitop.web.common.bootstrap;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
public abstract class AjaxIconLink extends Panel {
private static final long serialVersionUID = 1L;
private final IModel<IconType> iconModel;
private final IModel<String> labelModel;
public AjaxIconLink(String id, IModel<IconType> iconModel) {
this(id, iconModel, Model.of(""));
}
public AjaxIconLink(String id, IModel<IconType> iconModel,
IModel<String> labelModel) {
super(id);
this.iconModel = iconModel;
this.labelModel = labelModel;
}
@Override
protected void onInitialize() {
super.onInitialize();
AjaxLink<?> link = createLink("link");
add(link);
link.add(new Icon("icon", iconModel));
link.add(new Label("label", labelModel));
}
@Override
protected void onDetach() {
super.onDetach();
if (iconModel != null) {
iconModel.detach();
}
if (labelModel != null) {
labelModel.detach();
}
}
abstract protected AjaxLink<?> createLink(String id);
}

View File

@ -0,0 +1,29 @@
package com.pmease.gitop.web.common.bootstrap;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
public class Icon extends WebMarkupContainer {
private static final long serialVersionUID = 1L;
public Icon(String id, final IconType type) {
super(id);
add(type.newCssClassNameModifier());
}
@SuppressWarnings("serial")
public Icon(String id, final IModel<IconType> type) {
super(id);
add(AttributeAppender.append("class",
new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return type.getObject().cssClassName();
}
}));
}
}

View File

@ -0,0 +1,400 @@
package com.pmease.gitop.web.common.bootstrap;
import org.apache.wicket.behavior.AttributeAppender;
public enum IconType {
NULL("icon-null"),
ADJUST("icon-adjust"),
ANCHOR("icon-anchor"),
ARCHIVE("icon-archive"),
ASTERISK("icon-asterisk"),
BAN_CIRCLE("icon-ban-circle"),
BAR_CHART("icon-bar-chart"),
BARCODE("icon-barcode"),
BEAKER("icon-beaker"),
BEER("icon-beer"),
BELL("icon-bell"),
BELL_ALT("icon-bell-alt"),
BOLT("icon-bolt"),
BOOK("icon-book"),
BOOKMARK("icon-bookmark"),
BOOKMARK_EMPTY("icon-bookmark-empty"),
BRIEFCASE("icon-briefcase"),
BUG("icon-bug"),
BUILDING("icon-building"),
BULLHORN("icon-bullhorn"),
BULLSEYE("icon-bullseye"),
CALENDAR("icon-calendar"),
CALENDAR_EMPTY("icon-calendar-empty"),
CAMERA("icon-camera"),
CAMERA_RETRO("icon-camera-retro"),
CERTIFICATE("icon-certificate"),
CHECK("icon-check"),
CHECK_EMPTY("icon-check-empty"),
CHECK_MINUS("icon-check-minus"),
CHECK_SIGN("icon-check-sign"),
CIRCLE("icon-circle"),
CIRCLE_BLANK("icon-circle-blank"),
CLOUD("icon-cloud"),
CLOUD_DOWNLOAD("icon-cloud-download"),
CLOUD_UPLOAD("icon-cloud-upload"),
CODE("icon-code"),
CODE_FORK("icon-code-fork"),
COFFEE("icon-coffee"),
COG("icon-cog"),
COGS("icon-cogs"),
COLLAPSE("icon-collapse"),
COLLAPSE_ALT("icon-collapse-alt"),
COLLAPSE_TOP("icon-collapse-top"),
COMMENT("icon-comment"),
COMMENT_ALT("icon-comment-alt"),
COMMENTS("icon-comments"),
COMMENTS_ALT("icon-comments-alt"),
COMPASS("icon-compass"),
CREDIT_CARD("icon-credit-card"),
CROP("icon-crop"),
DASHBOARD("icon-dashboard"),
DESKTOP("icon-desktop"),
DOWNLOAD("icon-download"),
DOWNLOAD_ALT("icon-download-alt"),
EDIT("icon-edit"),
EDIT_SIGN("icon-edit-sign"),
ELLIPSIS_HORIZONTAL("icon-ellipsis-horizontal"),
ELLIPSIS_VERTICAL("icon-ellipsis-vertical"),
ENVELOPE("icon-envelope"),
ENVELOPE_ALT("icon-envelope-alt"),
ERASER("icon-eraser"),
EXCHANGE("icon-exchange"),
EXCLAMATION("icon-exclamation"),
EXCLAMATION_SIGN("icon-exclamation-sign"),
EXPAND("icon-expand"),
EXPAND_ALT("icon-expand-alt"),
EXTERNAL_LINK("icon-external-link"),
EXTERNAL_LINK_SIGN("icon-external-link-sign"),
EYE_CLOSE("icon-eye-close"),
EYE_OPEN("icon-eye-open"),
FACETIME_VIDEO("icon-facetime-video"),
FEMALE("icon-female"),
FIGHTER_JET("icon-fighter-jet"),
FILM("icon-film"),
FILTER("icon-filter"),
FIRE("icon-fire"),
FIRE_EXTINGUISHER("icon-fire-extinguisher"),
FLAG("icon-flag"),
FLAG_ALT("icon-flag-alt"),
FLAG_CHECKERED("icon-flag-checkered"),
FOLDER_CLOSE("icon-folder-close"),
FOLDER_CLOSE_ALT("icon-folder-close-alt"),
FOLDER_OPEN("icon-folder-open"),
FOLDER_OPEN_ALT("icon-folder-open-alt"),
FOOD("icon-food"),
FROWN("icon-frown"),
GAMEPAD("icon-gamepad"),
GEAR("icon-gear"),
GEARS("icon-gears"),
GIFT("icon-gift"),
GLASS("icon-glass"),
GLOBE("icon-globe"),
GROUP("icon-group"),
HDD("icon-hdd"),
HEADPHONES("icon-headphones"),
HEART("icon-heart"),
HEART_EMPTY("icon-heart-empty"),
HOME("icon-home"),
INBOX("icon-inbox"),
INFO("icon-info"),
INFO_SIGN("icon-info-sign"),
KEY("icon-key"),
KEYBOARD("icon-keyboard"),
LAPTOP("icon-laptop"),
LEAF("icon-leaf"),
LEGAL("icon-legal"),
LEMON("icon-lemon"),
LEVEL_DOWN("icon-level-down"),
LEVEL_UP("icon-level-up"),
LIGHTBULB("icon-lightbulb"),
LOCATION_ARROW("icon-location-arrow"),
LOCK("icon-lock"),
MAGIC("icon-magic"),
MAGNET("icon-magnet"),
MAIL_FORWARD("icon-mail-forward"),
MAIL_REPLY("icon-mail-reply"),
MAIL_REPLY_ALL("icon-mail-reply-all"),
MALE("icon-male"),
MAP_MARKER("icon-map-marker"),
MEH("icon-meh"),
MICROPHONE("icon-microphone"),
MICROPHONE_OFF("icon-microphone-off"),
MINUS("icon-minus"),
MINUS_SIGN("icon-minus-sign"),
MINUS_SIGN_ALT("icon-minus-sign-alt"),
MOBILE_PHONE("icon-mobile-phone"),
MONEY("icon-money"),
MOON("icon-moon"),
MOVE("icon-move"),
MUSIC("icon-music"),
OFF("icon-off"),
OK("icon-ok"),
OK_CIRCLE("icon-ok-circle"),
OK_SIGN("icon-ok-sign"),
PENCIL("icon-pencil"),
PHONE("icon-phone"),
PHONE_SIGN("icon-phone-sign"),
PICTURE("icon-picture"),
PLANE("icon-plane"),
PLUS("icon-plus"),
PLUS_SIGN("icon-plus-sign"),
PLUS_SIGN_ALT("icon-plus-sign-alt"),
POWER_OFF("icon-power-off"),
PRINT("icon-print"),
PUSHPIN("icon-pushpin"),
PUZZLE_PIECE("icon-puzzle-piece"),
QRCODE("icon-qrcode"),
QUESTION("icon-question"),
QUESTION_SIGN("icon-question-sign"),
QUOTE_LEFT("icon-quote-left"),
QUOTE_RIGHT("icon-quote-right"),
RANDOM("icon-random"),
REFRESH("icon-refresh"),
REMOVE("icon-remove"),
REMOVE_CIRCLE("icon-remove-circle"),
REMOVE_SIGN("icon-remove-sign"),
REORDER("icon-reorder"),
REPLY("icon-reply"),
REPLY_ALL("icon-reply-all"),
RESIZE_HORIZONTAL("icon-resize-horizontal"),
RESIZE_VERTICAL("icon-resize-vertical"),
RETWEET("icon-retweet"),
ROAD("icon-road"),
ROCKET("icon-rocket"),
RSS("icon-rss"),
RSS_SIGN("icon-rss-sign"),
SCREENSHOT("icon-screenshot"),
SEARCH("icon-search"),
SHARE("icon-share"),
SHARE_ALT("icon-share-alt"),
SHARE_SIGN("icon-share-sign"),
SHIELD("icon-shield"),
SHOPPING_CART("icon-shopping-cart"),
SIGN_BLANK("icon-sign-blank"),
SIGNAL("icon-signal"),
SIGNIN("icon-signin"),
SIGNOUT("icon-signout"),
SITEMAP("icon-sitemap"),
SMILE("icon-smile"),
SORT("icon-sort"),
SORT_BY_ALPHABET("icon-sort-by-alphabet"),
SORT_BY_ALPHABET_ALT("icon-sort-by-alphabet-alt"),
SORT_BY_ATTRIBUTES("icon-sort-by-attributes"),
SORT_BY_ATTRIBUTES_ALT("icon-sort-by-attributes-alt"),
SORT_BY_ORDER("icon-sort-by-order"),
SORT_BY_ORDER_ALT("icon-sort-by-order-alt"),
SORT_DOWN("icon-sort-down"),
SORT_UP("icon-sort-up"),
SPINNER("icon-spinner"),
STAR("icon-star"),
STAR_EMPTY("icon-star-empty"),
STAR_HALF("icon-star-half"),
STAR_HALF_EMPTY("icon-star-half-empty"),
STAR_HALF_FULL("icon-star-half-full"),
SUBSCRIPT("icon-subscript"),
SUITCASE("icon-suitcase"),
SUN("icon-sun"),
SUPERSCRIPT("icon-superscript"),
TABLET("icon-tablet"),
TAG("icon-tag"),
TAGS("icon-tags"),
TASKS("icon-tasks"),
TERMINAL("icon-terminal"),
THUMBS_DOWN("icon-thumbs-down"),
THUMBS_DOWN_ALT("icon-thumbs-down-alt"),
THUMBS_UP("icon-thumbs-up"),
THUMBS_UP_ALT("icon-thumbs-up-alt"),
TICKET("icon-ticket"),
TIME("icon-time"),
TINT("icon-tint"),
TRASH("icon-trash"),
TROPHY("icon-trophy"),
TRUCK("icon-truck"),
UMBRELLA("icon-umbrella"),
UNCHECKED("icon-unchecked"),
UNLOCK("icon-unlock"),
UNLOCK_ALT("icon-unlock-alt"),
UPLOAD("icon-upload"),
UPLOAD_ALT("icon-upload-alt"),
USER("icon-user"),
VOLUME_DOWN("icon-volume-down"),
VOLUME_OFF("icon-volume-off"),
VOLUME_UP("icon-volume-up"),
WARNING_SIGN("icon-warning-sign"),
WRENCH("icon-wrench"),
ZOOM_IN("icon-zoom-in"),
ZOOM_OUT("icon-zoom-out"),
BITCOIN("icon-bitcoin"),
BTC("icon-btc"),
CNY("icon-cny"),
DOLLAR("icon-dollar"),
EUR("icon-eur"),
EURO("icon-euro"),
GBP("icon-gbp"),
INR("icon-inr"),
JPY("icon-jpy"),
KRW("icon-krw"),
RENMINBI("icon-renminbi"),
RUPEE("icon-rupee"),
USD("icon-usd"),
WON("icon-won"),
YEN("icon-yen"),
ALIGN_CENTER("icon-align-center"),
ALIGN_JUSTIFY("icon-align-justify"),
ALIGN_LEFT("icon-align-left"),
ALIGN_RIGHT("icon-align-right"),
BOLD("icon-bold"),
COLUMNS("icon-columns"),
COPY("icon-copy"),
CUT("icon-cut"),
FILE("icon-file"),
FILE_ALT("icon-file-alt"),
FILE_TEXT("icon-file-text"),
FILE_TEXT_ALT("icon-file-text-alt"),
FONT("icon-font"),
INDENT_LEFT("icon-indent-left"),
INDENT_RIGHT("icon-indent-right"),
ITALIC("icon-italic"),
LINK("icon-link"),
LIST("icon-list"),
LIST_ALT("icon-list-alt"),
LIST_OL("icon-list-ol"),
LIST_UL("icon-list-ul"),
PAPER_CLIP("icon-paper-clip"),
PAPERCLIP("icon-paperclip"),
PASTE("icon-paste"),
REPEAT("icon-repeat"),
ROTATE_LEFT("icon-rotate-left"),
ROTATE_RIGHT("icon-rotate-right"),
SAVE("icon-save"),
STRIKETHROUGH("icon-strikethrough"),
TABLE("icon-table"),
TEXT_HEIGHT("icon-text-height"),
TEXT_WIDTH("icon-text-width"),
TH("icon-th"),
TH_LARGE("icon-th-large"),
TH_LIST("icon-th-list"),
UNDERLINE("icon-underline"),
UNDO("icon-undo"),
UNLINK("icon-unlink"),
ANGLE_DOWN("icon-angle-down"),
ANGLE_LEFT("icon-angle-left"),
ANGLE_RIGHT("icon-angle-right"),
ANGLE_UP("icon-angle-up"),
ARROW_DOWN("icon-arrow-down"),
ARROW_LEFT("icon-arrow-left"),
ARROW_RIGHT("icon-arrow-right"),
ARROW_UP("icon-arrow-up"),
CARET_DOWN("icon-caret-down"),
CARET_LEFT("icon-caret-left"),
CARET_RIGHT("icon-caret-right"),
CARET_UP("icon-caret-up"),
CHEVRON_DOWN("icon-chevron-down"),
CHEVRON_LEFT("icon-chevron-left"),
CHEVRON_RIGHT("icon-chevron-right"),
CHEVRON_SIGN_DOWN("icon-chevron-sign-down"),
CHEVRON_SIGN_LEFT("icon-chevron-sign-left"),
CHEVRON_SIGN_RIGHT("icon-chevron-sign-right"),
CHEVRON_SIGN_UP("icon-chevron-sign-up"),
CHEVRON_UP("icon-chevron-up"),
CIRCLE_ARROW_DOWN("icon-circle-arrow-down"),
CIRCLE_ARROW_LEFT("icon-circle-arrow-left"),
CIRCLE_ARROW_RIGHT("icon-circle-arrow-right"),
CIRCLE_ARROW_UP("icon-circle-arrow-up"),
DOUBLE_ANGLE_DOWN("icon-double-angle-down"),
DOUBLE_ANGLE_LEFT("icon-double-angle-left"),
DOUBLE_ANGLE_RIGHT("icon-double-angle-right"),
DOUBLE_ANGLE_UP("icon-double-angle-up"),
HAND_DOWN("icon-hand-down"),
HAND_LEFT("icon-hand-left"),
HAND_RIGHT("icon-hand-right"),
HAND_UP("icon-hand-up"),
LONG_ARROW_DOWN("icon-long-arrow-down"),
LONG_ARROW_LEFT("icon-long-arrow-left"),
LONG_ARROW_RIGHT("icon-long-arrow-right"),
LONG_ARROW_UP("icon-long-arrow-up"),
BACKWARD("icon-backward"),
EJECT("icon-eject"),
FAST_BACKWARD("icon-fast-backward"),
FAST_FORWARD("icon-fast-forward"),
FORWARD("icon-forward"),
FULLSCREEN("icon-fullscreen"),
PAUSE("icon-pause"),
PLAY("icon-play"),
PLAY_CIRCLE("icon-play-circle"),
PLAY_SIGN("icon-play-sign"),
RESIZE_FULL("icon-resize-full"),
RESIZE_SMALL("icon-resize-small"),
STEP_BACKWARD("icon-step-backward"),
STEP_FORWARD("icon-step-forward"),
STOP("icon-stop"),
YOUTUBE_PLAY("icon-youtube-play"),
ADN("icon-adn"),
ANDROID("icon-android"),
APPLE("icon-apple"),
BITBUCKET("icon-bitbucket"),
BITBUCKET_SIGN("icon-bitbucket-sign"),
CSS3("icon-css3"),
DRIBBBLE("icon-dribbble"),
DROPBOX("icon-dropbox"),
FACEBOOK("icon-facebook"),
FACEBOOK_SIGN("icon-facebook-sign"),
FLICKR("icon-flickr"),
FOURSQUARE("icon-foursquare"),
GITHUB("icon-github"),
GITHUB_ALT("icon-github-alt"),
GITHUB_SIGN("icon-github-sign"),
GITTIP("icon-gittip"),
GOOGLE_PLUS("icon-google-plus"),
GOOGLE_PLUS_SIGN("icon-google-plus-sign"),
HTML5("icon-html5"),
INSTAGRAM("icon-instagram"),
LINKEDIN("icon-linkedin"),
LINKEDIN_SIGN("icon-linkedin-sign"),
LINUX("icon-linux"),
MAXCDN("icon-maxcdn"),
PINTEREST("icon-pinterest"),
PINTEREST_SIGN("icon-pinterest-sign"),
RENREN("icon-renren"),
SKYPE("icon-skype"),
STACKEXCHANGE("icon-stackexchange"),
TRELLO("icon-trello"),
TUMBLR("icon-tumblr"),
TUMBLR_SIGN("icon-tumblr-sign"),
TWITTER("icon-twitter"),
TWITTER_SIGN("icon-twitter-sign"),
VK("icon-vk"),
WEIBO("icon-weibo"),
WINDOWS("icon-windows"),
XING("icon-xing"),
XING_SIGN("icon-xing-sign"),
YOUTUBE("icon-youtube"),
YOUTUBE_SIGN("icon-youtube-sign"),
AMBULANCE("icon-ambulance"),
H_SIGN("icon-h-sign"),
HOSPITAL("icon-hospital"),
MEDKIT("icon-medkit"),
STETHOSCOPE("icon-stethoscope"),
USER_MD("icon-user-md");
private final String cssClassName;
IconType(String cssClassName) {
this.cssClassName = cssClassName;
}
public String cssClassName() {
return cssClassName;
}
public AttributeAppender newCssClassNameModifier() {
return AttributeAppender.append("class", cssClassName());
}
}

View File

@ -28,15 +28,15 @@ public abstract class HibernateDataProvider<T extends AbstractEntity> extends So
public Iterator<? extends T> iterator(long first, long count) {
GeneralDao dao = getDao();
DetachedCriteria criteria = getCriteria();
SortParam<String> param = getSort();
if (param != null) {
DetachedCriteria crit = getCriteria();
Iterable<String> it = Splitter.on(",").trimResults().split(param.getProperty());
for (String each : it) {
if (param.isAscending())
crit.addOrder(Order.asc(each));
criteria.addOrder(Order.asc(each));
else
crit.addOrder(Order.desc(each));
criteria.addOrder(Order.desc(each));
}
}

View File

@ -28,205 +28,217 @@ import com.pmease.gitop.web.common.component.datagrid.event.SearchStringChanged;
public class SearchNavToolbar extends AbstractToolbar {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public SearchNavToolbar(DataTable<?, ?> table) {
super(table);
public SearchNavToolbar(DataTable<?, ?> table) {
super(table);
setOutputMarkupId(true);
}
setOutputMarkupId(true);
}
@Override
protected void onInitialize() {
super.onInitialize();
@Override
protected void onInitialize() {
super.onInitialize();
WebMarkupContainer span = new WebMarkupContainer("td");
add(span);
span.add(AttributeModifier.replace("colspan", new AbstractReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;
WebMarkupContainer span = new WebMarkupContainer("td");
add(span);
span.add(AttributeModifier.replace("colspan",
new AbstractReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;
@Override
public String getObject() {
return String.valueOf(getTable().getColumns().size());
}
}));
@Override
public String getObject() {
return String.valueOf(getTable().getColumns().size());
}
}));
span.add(newSearchForm("search"));
span.add(newNavigationForm("nav"));
}
span.add(newSearchForm("search"));
span.add(newNavigationForm("nav"));
}
@Override
protected void onConfigure() {
super.onConfigure();
this.setVisibilityAllowed(getTable().getRowCount() > 0);
}
protected Component newSearchForm(String id) {
Fragment frag = new Fragment(id, "searchFrag", this);
frag.add(new SearchForm("searchForm"));
return frag;
}
@SuppressWarnings({"serial"})
private class SearchForm extends Form<Void> {
@Override
protected void onConfigure() {
super.onConfigure();
private String pattern;
public SearchForm(String id) {
super(id);
}
@Override
protected void onInitialize() {
super.onInitialize();
TextField<String> input = new TextField<String>("input", new PropertyModel<String>(this, "pattern"));
add(input);
IndicatingAjaxButton submit = new IndicatingAjaxButton("submit", this) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
send(getTable(), Broadcast.BREADTH, new SearchStringChanged(target, pattern));
}
};
add(submit);
setDefaultButton(submit);
}
@Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof SearchStringChanged) {
SearchStringChanged e = (SearchStringChanged) event.getPayload();
this.pattern = e.getPattern();
e.getTarget().add(this);
}
}
}
this.setVisibilityAllowed(getTable().getRowCount() > 0);
}
protected void onPageChanged(AjaxRequestTarget target) {
target.add(getTable());
target.add(this);
}
protected Component newNavigationForm(String id) {
Fragment frag = new Fragment(id, "navFrag", this);
frag.add(new NavigationForm("form"));
return frag;
}
protected Component newSearchForm(String id) {
Fragment frag = new Fragment(id, "searchFrag", this);
frag.add(new SearchForm("searchForm"));
return frag;
}
static final List<Integer> ROWS_PER_PAGE = ImmutableList.<Integer>of(10, 25, 50, 100, 250, 500);
@SuppressWarnings({"serial"})
private class NavigationForm extends Form<Void> {
private int rowsPerPage = 10;
private int currentPage = 1;
public NavigationForm(String id) {
super(id);
}
@Override
protected void onInitialize() {
super.onInitialize();
DropDownChoice<Integer> rowsSelector = new DropDownChoice<Integer>("rowsSelector",
new PropertyModel<Integer>(this, "rowsPerPage"), ROWS_PER_PAGE);
add(rowsSelector);
rowsSelector.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@SuppressWarnings({ "serial" })
private class SearchForm extends Form<Void> {
@Override
protected void onUpdate(AjaxRequestTarget target) {
currentPage = 1;
getTable().setItemsPerPage(rowsPerPage);
send(getTable(), Broadcast.BREADTH, new PageChanged(target, currentPage - 1));
}
});
add(new AjaxLink<Void>("previousLink") {
private String pattern;
@Override
public void onClick(AjaxRequestTarget target) {
long current = getTable().getCurrentPage();
if (current == 0) {
return;
}
current--;
if (current < 0) {
current = 0;
}
send(getTable(), Broadcast.BREADTH, new PageChanged(target, (int) current));
}
});
add(new AjaxLink<Void>("nextLink") {
public SearchForm(String id) {
super(id);
}
@Override
public void onClick(AjaxRequestTarget target) {
long current = getTable().getCurrentPage();
long totals = getTable().getPageCount();
if (current == totals) {
return;
}
current++;
if (current >= totals) {
current = totals - 1;
}
send(getTable(), Broadcast.BREADTH, new PageChanged(target, (int) current));
}
});
add(new TextField<Integer>("pageInput", new PropertyModel<Integer>(this, "currentPage")));
AjaxButton btn = new AjaxButton("submit", this) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
if (currentPage == getTable().getCurrentPage() + 1) {
return;
}
long totals = getTable().getPageCount();
currentPage = Math.min(currentPage, (int) totals);
currentPage = Math.max(currentPage, 0);
send(getTable(), Broadcast.BREADTH, new PageChanged(target, currentPage - 1));
}
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.add(form);
}
};
add(btn);
setDefaultButton(btn);
add(new Label("navlabel", new AbstractReadOnlyModel<String>() {
@Override
protected void onInitialize() {
super.onInitialize();
@Override
public String getObject() {
long totals = getTable().getRowCount();
long items = getTable().getItemsPerPage();
long start = (currentPage - 1) * items + 1;
long end = start + items - 1;
end = Math.min(end, totals);
return start + " - " + end + " of " + totals;
}
}));
}
@Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof PageChanged) {
PageChanged e = (PageChanged) event.getPayload();
currentPage = e.getPage() + 1;
rowsPerPage = (int) getTable().getItemsPerPage();
e.getTarget().add(this);
}
}
}
TextField<String> input = new TextField<String>("input",
new PropertyModel<String>(this, "pattern"));
add(input);
IndicatingAjaxButton submit = new IndicatingAjaxButton("submit",
this) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
send(getTable(), Broadcast.BREADTH,
new SearchStringChanged(target, pattern));
}
};
add(submit);
setDefaultButton(submit);
}
@Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof SearchStringChanged) {
SearchStringChanged e = (SearchStringChanged) event
.getPayload();
this.pattern = e.getPattern();
e.getTarget().add(this);
}
}
}
protected void onPageChanged(AjaxRequestTarget target) {
target.add(getTable());
target.add(this);
}
protected Component newNavigationForm(String id) {
Fragment frag = new Fragment(id, "navFrag", this);
frag.add(new NavigationForm("form"));
return frag;
}
static final List<Integer> ROWS_PER_PAGE = ImmutableList.<Integer> of(10,
25, 50, 100, 250, 500);
@SuppressWarnings({ "serial" })
private class NavigationForm extends Form<Void> {
private int rowsPerPage = 10;
private int currentPage = 1;
public NavigationForm(String id) {
super(id);
}
@Override
protected void onInitialize() {
super.onInitialize();
DropDownChoice<Integer> rowsSelector = new DropDownChoice<Integer>(
"rowsSelector", new PropertyModel<Integer>(this,
"rowsPerPage"), ROWS_PER_PAGE);
add(rowsSelector);
rowsSelector.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
currentPage = 1;
getTable().setItemsPerPage(rowsPerPage);
send(getTable(), Broadcast.BREADTH, new PageChanged(target,
currentPage - 1));
}
});
add(new AjaxLink<Void>("previousLink") {
@Override
public void onClick(AjaxRequestTarget target) {
long current = getTable().getCurrentPage();
if (current == 0) {
return;
}
current--;
if (current < 0) {
current = 0;
}
send(getTable(), Broadcast.BREADTH, new PageChanged(target,
(int) current));
}
});
add(new AjaxLink<Void>("nextLink") {
@Override
public void onClick(AjaxRequestTarget target) {
long current = getTable().getCurrentPage();
long totals = getTable().getPageCount();
if (current == totals) {
return;
}
current++;
if (current >= totals) {
current = totals - 1;
}
send(getTable(), Broadcast.BREADTH, new PageChanged(target,
(int) current));
}
});
add(new TextField<Integer>("pageInput", new PropertyModel<Integer>(
this, "currentPage")));
AjaxButton btn = new AjaxButton("submit", this) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
if (currentPage == getTable().getCurrentPage() + 1) {
return;
}
long totals = getTable().getPageCount();
currentPage = Math.min(currentPage, (int) totals);
currentPage = Math.max(currentPage, 0);
send(getTable(), Broadcast.BREADTH, new PageChanged(target,
currentPage - 1));
}
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.add(form);
}
};
add(btn);
setDefaultButton(btn);
add(new Label("navlabel", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
long totals = getTable().getRowCount();
long items = getTable().getItemsPerPage();
long start = (currentPage - 1) * items + 1;
long end = start + items - 1;
end = Math.min(end, totals);
return start + " - " + end + " of " + totals;
}
}));
}
@Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof PageChanged) {
PageChanged e = (PageChanged) event.getPayload();
currentPage = e.getPage() + 1;
rowsPerPage = (int) getTable().getItemsPerPage();
e.getTarget().add(this);
}
}
}
}

View File

@ -7,7 +7,7 @@ import com.pmease.gitop.web.common.util.Options;
public class Messenger {
static enum Type {
INFO, SUCCESS, ERROR
INFO, SUCCESS, WARNING, ERROR
}
private final String jsFunc;
@ -31,6 +31,10 @@ public class Messenger {
public static Messenger error(String message) {
return message(message, Type.ERROR);
}
public static Messenger warn(String message) {
return message(message, Type.WARNING);
}
private static Messenger message(String message, Type type) {
return post(new Options()

View File

@ -356,6 +356,9 @@ ul.messenger-theme-flat .messenger-message.alert-success .messenger-message-inne
ul.messenger-theme-flat .messenger-message.alert-info .messenger-message-inner:before {
background: #00B5AD;
}
ul.messenger-theme-flat .messenger-message.alert-warning .messenger-message-inner:before {
background: #ff9500;
}
/* line 103, ../../src/sass/messenger-theme-flat.sass */
ul.messenger-theme-flat .messenger-message.alert-error .messenger-message-inner:before {
background: #ff2a68;

View File

@ -5,7 +5,6 @@ import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.IModel;
@ -51,8 +50,5 @@ public class AjaxConfirmButton extends AjaxButton {
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptHeaderItem.forReference(VexConfirmJavaScriptResourceReference.get()));
response.render(JavaScriptHeaderItem.forScript("vex.defaultOptions.className = 'vex-theme-wireframe'", "vex-theme-options"));
}
}

View File

@ -4,6 +4,7 @@ import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.model.IComponentAssignedModel;
import org.apache.wicket.model.IModel;
@ -44,6 +45,9 @@ public class VexLinkBehavior extends Behavior {
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(JavaScriptHeaderItem.forReference(VexConfirmJavaScriptResourceReference.get()));
response.render(JavaScriptHeaderItem.forScript("vex.defaultOptions.className = 'vex-theme-wireframe'", "vex-theme-options"));
String markupId = component.getMarkupId(true);
response.render(OnDomReadyHeaderItem.forScript(String.format(
"$('#%s').on('click', function(e){e.preventDefault(); $(this).confirm(); });",

View File

@ -0,0 +1,41 @@
package com.pmease.gitop.web.component.choice;
import java.util.Collection;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import com.pmease.gitop.core.model.User;
import com.vaynberg.wicket.select2.Select2MultiChoice;
public class MultipleUserChoice extends Select2MultiChoice<User> {
private static final long serialVersionUID = 1L;
public MultipleUserChoice(String id, IModel<Collection<User>> model) {
super(id, model, new UserChoiceProvider());
}
@Override
protected void onInitialize() {
super.onInitialize();
// getSettings().setMinimumInputLength(1);
getSettings().setPlaceholder("Choose an user ...");
getSettings().setFormatResult("UserChoice.formatter.formatResult");
getSettings()
.setFormatSelection("UserChoice.formatter.formatSelection");
getSettings().setEscapeMarkup("UserChoice.formatter.escapeMarkup");
}
private ResourceReference userChoiceReference = new PackageResourceReference(
SingleUserChoice.class, "userchoice.js");
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptHeaderItem.forReference(userChoiceReference));
}
}

View File

@ -0,0 +1,39 @@
package com.pmease.gitop.web.component.choice;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import com.pmease.gitop.core.model.Team;
import com.vaynberg.wicket.select2.ChoiceProvider;
import com.vaynberg.wicket.select2.Select2Choice;
@SuppressWarnings("serial")
public class SingleTeamChoice extends Select2Choice<Team> {
public SingleTeamChoice(String id, IModel<Team> model,
ChoiceProvider<Team> teamsProvider) {
super(id, model, teamsProvider);
}
@Override
protected void onInitialize() {
super.onInitialize();
getSettings().setPlaceholder("Choose a team ...");
getSettings().setFormatResult("TeamChoice.formatter.formatResult");
getSettings()
.setFormatSelection("TeamChoice.formatter.formatSelection");
getSettings().setEscapeMarkup("TeamChoice.formatter.escapeMarkup");
}
private ResourceReference teamChoiceReference =
new JavaScriptResourceReference(SingleUserChoice.class, "teamchoice.js");
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptHeaderItem.forReference(teamChoiceReference));
}
}

View File

@ -0,0 +1,39 @@
package com.pmease.gitop.web.component.choice;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import com.pmease.gitop.core.model.User;
import com.vaynberg.wicket.select2.Select2Choice;
@SuppressWarnings("serial")
public class SingleUserChoice extends Select2Choice<User> {
public SingleUserChoice(String id, IModel<User> model) {
super(id, model, new UserChoiceProvider());
}
@Override
protected void onInitialize() {
super.onInitialize();
// getSettings().setMinimumInputLength(1);
getSettings().setPlaceholder("Choose an user ...");
getSettings().setFormatResult("UserChoice.formatter.formatResult");
getSettings()
.setFormatSelection("UserChoice.formatter.formatSelection");
getSettings().setEscapeMarkup("UserChoice.formatter.escapeMarkup");
}
private ResourceReference userChoiceReference =
new JavaScriptResourceReference(SingleUserChoice.class, "userchoice.js");
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(JavaScriptHeaderItem.forReference(userChoiceReference));
}
}

View File

@ -0,0 +1,75 @@
package com.pmease.gitop.web.component.choice;
import java.util.Collection;
import java.util.List;
import org.apache.wicket.model.IModel;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.common.collect.Lists;
import com.pmease.commons.hibernate.dao.GeneralDao;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.TeamManager;
import com.pmease.gitop.core.model.Team;
import com.vaynberg.wicket.select2.ChoiceProvider;
import com.vaynberg.wicket.select2.Response;
public class TeamChoiceProvider extends ChoiceProvider<Team> {
private static final long serialVersionUID = 1L;
IModel<DetachedCriteria> criteria;
public TeamChoiceProvider(IModel<DetachedCriteria> criteria) {
this.criteria = criteria;
}
@Override
public void query(String term, int page, Response<Team> response) {
DetachedCriteria crit = criteria == null ? null : criteria.getObject();
if (crit == null) {
crit = DetachedCriteria.forClass(Team.class);
}
crit.add(Restrictions.ilike("name", term, MatchMode.START));
crit.addOrder(Order.asc("name"));
int first = page * 10;
@SuppressWarnings("unchecked")
List<Team> teams = (List<Team>) Gitop.getInstance(GeneralDao.class).query(crit, first, 10);
response.addAll(teams);
}
@Override
public void toJson(Team choice, JSONWriter writer) throws JSONException {
writer.key("id").value(choice.getId())
.key("name").value(choice.getName())
.key("permission").value(choice.getAuthorizedOperation());
}
@Override
public Collection<Team> toChoices(Collection<String> ids) {
List<Team> teams = Lists.newArrayList();
TeamManager tm = Gitop.getInstance(TeamManager.class);
for (String each : ids) {
Long id = Long.valueOf(each);
teams.add(tm.get(id));
}
return teams;
}
@Override
public void detach() {
super.detach();
if (criteria != null) {
criteria.detach();
}
}
}

View File

@ -0,0 +1,81 @@
package com.pmease.gitop.web.component.choice;
import java.util.Collection;
import java.util.List;
import org.apache.wicket.request.cycle.RequestCycle;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.GitopWebApp;
import com.pmease.gitop.web.component.avatar.AvatarImageResourceReference;
import com.pmease.gitop.web.util.Gravatar;
import com.pmease.gitop.web.util.WicketUtils;
import com.vaynberg.wicket.select2.ChoiceProvider;
import com.vaynberg.wicket.select2.Response;
public class UserChoiceProvider extends ChoiceProvider<User> {
private static final long serialVersionUID = 1L;
@Override
public void query(String term, int page, Response<User> response) {
if (Strings.isNullOrEmpty(term)) {
return;
}
UserManager um = Gitop.getInstance(UserManager.class);
int first = page * 10;
List<User> users = um.query(new Criterion[] {
Restrictions.ilike("name", term, MatchMode.START),
Restrictions.ilike("displayName", term, MatchMode.START)
}, new Order[0], first, 10);
response.addAll(users);
}
@Override
public void toJson(User choice, JSONWriter writer) throws JSONException {
writer.key("id").value(choice.getId())
.key("name").value(choice.getName())
.key("displayName").value(choice.getDisplayName())
.key("email").value(choice.getEmail())
.key("avatar").value(getAvatarUrl(choice));
}
@Override
public Collection<User> toChoices(Collection<String> ids) {
List<User> users = Lists.newArrayList();
UserManager um = Gitop.getInstance(UserManager.class);
for (String each : ids) {
Long id = Long.valueOf(each);
users.add(um.get(id));
}
return users;
}
private String getAvatarUrl(User user) {
String path = user.getAvatarUrl();
if (GitopWebApp.get().isGravatarEnabled() && Strings.isNullOrEmpty(path)) {
return Gravatar.getURL(user.getEmail());
} else {
CharSequence url = RequestCycle.get().urlFor(
new AvatarImageResourceReference(),
WicketUtils.newPageParams(
"id",String.valueOf(user.getId()),
"type", "user"));
return url.toString() + "?antiCache=" + System.currentTimeMillis();
}
}
}

View File

@ -0,0 +1,14 @@
var TeamChoice = TeamChoice || {};
TeamChoice.formatter = {
formatSelection: function(team) {
return team.name;
},
formatResult: function(team) {
return team.name;
},
escapeMarkup: function(m) {
return m;
}
};

View File

@ -0,0 +1,17 @@
var UserChoice = UserChoice || {};
UserChoice.formatter = {
formatSelection: function(user) {
return "<img class='img-thumbnail avatar' src='" + user.avatar + "' /> " + user.name + " (" + user.displayName + ")";
},
formatResult: function(user) {
return "<div class='user-choice-row'><img class='img-thumbnail avatar avatar-big' src='" + user.avatar + "' />"
+ "<p>"+ user.name + " (" + user.displayName + ")" + "</p>"
+ "<p class='text-muted'>" + user.email + "</p>"
+ "</div>";
},
escapeMarkup: function(m) {
return m;
}
};

View File

@ -1,36 +1,37 @@
package com.pmease.gitop.web.model;
import org.apache.wicket.model.LoadableDetachableModel;
import com.google.common.base.Preconditions;
import com.pmease.commons.hibernate.AbstractEntity;
import com.pmease.commons.hibernate.dao.GeneralDao;
import com.pmease.commons.loader.AppLoader;
public class EntityModel<T extends AbstractEntity> extends LoadableDetachableModel<T> {
private static final long serialVersionUID = 1L;
protected T entity;
private final Class<T> entityClass;
protected GeneralDao getDao() {
return AppLoader.getInstance(GeneralDao.class);
}
@SuppressWarnings("unchecked")
public EntityModel(T entity) {
this.entity = entity;
this.entityClass = (Class<T>) entity.getClass();
}
@Override
protected T load() {
if (entity.isNew()) {
return entity;
} else {
return getDao().get(entityClass, entity.getId());
}
}
private static final long serialVersionUID = 1L;
protected T entity;
private final Class<T> entityClass;
protected GeneralDao getDao() {
return AppLoader.getInstance(GeneralDao.class);
}
@SuppressWarnings("unchecked")
public EntityModel(T entity) {
Preconditions.checkNotNull(entity, "entity");
this.entity = entity;
this.entityClass = (Class<T>) entity.getClass();
}
@Override
protected T load() {
if (entity.isNew()) {
return entity;
} else {
return getDao().get(entityClass, entity.getId());
}
}
}

View File

@ -15,7 +15,7 @@
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/ico/apple-touch-icon-144-precomposed.png">
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
</head>
<body>
<body wicket:id="body">
<wicket:container wicket:id="globalResourceBinder"></wicket:container>
<!--[if lt IE 7]>

View File

@ -1,16 +1,26 @@
package com.pmease.gitop.web.page;
import java.util.Iterator;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.IMarkupFragment;
import org.apache.wicket.markup.MarkupElement;
import org.apache.wicket.markup.MarkupResourceStream;
import org.apache.wicket.markup.html.TransparentWebMarkupContainer;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.flow.RedirectToUrlException;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.google.common.base.Strings;
import com.pmease.commons.util.StringUtils;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.web.assets.BaseResourcesBehavior;
@ -23,7 +33,7 @@ import com.pmease.gitop.web.page.init.ServerInitPage;
@SuppressWarnings("serial")
public abstract class BasePage extends WebPage {
// private WebMarkupContainer body;
private WebMarkupContainer body;
private boolean shouldInitialize = true;
@ -44,17 +54,17 @@ public abstract class BasePage extends WebPage {
}
private void commonInit() {
// body = new TransparentWebMarkupContainer("body");
// add(body);
// body.add(AttributeAppender.append("class",
// new AbstractReadOnlyModel<String>() {
//
// @Override
// public String getObject() {
// String css = getPageCssClass();
// return Strings.isNullOrEmpty(css) ? "" : css;
// }
// }));
body = new TransparentWebMarkupContainer("body");
add(body);
body.add(AttributeAppender.append("class",
new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
String css = getPageCssClass();
return Strings.isNullOrEmpty(css) ? "" : css;
}
}));
modal = new Modal("modal");
add(modal);
@ -67,58 +77,58 @@ public abstract class BasePage extends WebPage {
shouldInitialize = true;
}
// @Override
// public IMarkupFragment getMarkup(Component child) {
// if (child != null) {
// IMarkupFragment markup = super.getMarkup(child);
// if (markup != null)
// return markup;
// else if (body != null)
// return body.getMarkup(child);
// else
// return null;
// } else {
// final IMarkupFragment markup = super.getMarkup(child);
// return new IMarkupFragment() {
//
// @Override
// public String toString(boolean markupOnly) {
// return markup.toString();
// }
//
// @Override
// public int size() {
// return markup.size();
// }
//
// @Override
// public MarkupResourceStream getMarkupResourceStream() {
// return markup.getMarkupResourceStream();
// }
//
// @Override
// public MarkupElement get(int index) {
// return markup.get(index);
// }
//
// @Override
// public IMarkupFragment find(String id) {
// IMarkupFragment found = markup.find(id);
// if (found != null)
// return found;
// else if (body != null)
// return body.getMarkup().find(id);
// else
// return null;
// }
//
// @Override
// public Iterator<MarkupElement> iterator() {
// return markup.iterator();
// }
// };
// }
// }
@Override
public IMarkupFragment getMarkup(Component child) {
if (child != null) {
IMarkupFragment markup = super.getMarkup(child);
if (markup != null)
return markup;
else if (body != null)
return body.getMarkup(child);
else
return null;
} else {
final IMarkupFragment markup = super.getMarkup(child);
return new IMarkupFragment() {
@Override
public String toString(boolean markupOnly) {
return markup.toString();
}
@Override
public int size() {
return markup.size();
}
@Override
public MarkupResourceStream getMarkupResourceStream() {
return markup.getMarkupResourceStream();
}
@Override
public MarkupElement get(int index) {
return markup.get(index);
}
@Override
public IMarkupFragment find(String id) {
IMarkupFragment found = markup.find(id);
if (found != null)
return found;
else if (body != null)
return body.getMarkup().find(id);
else
return null;
}
@Override
public Iterator<MarkupElement> iterator() {
return markup.iterator();
}
};
}
}
public final void redirectWithInterception(final Class<? extends Page> clazz) {
shouldInitialize = true;

View File

@ -1,9 +1,14 @@
package com.pmease.gitop.web.page;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.pmease.gitop.core.model.Project;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.component.avatar.AvatarImage.AvatarImageType;
import com.pmease.gitop.web.page.account.AccountHomePage;
import com.pmease.gitop.web.page.project.ProjectHomePage;
import com.pmease.gitop.web.util.WicketUtils;
public class PageSpec {
@ -11,11 +16,30 @@ public class PageSpec {
public static final String ID = "id";
public static final String TYPE = "type";
public static final String USER = "user";
public static final String PROJECT = "project";
public static final String REPO = "repo";
public static final String TAB = "tab";
public static PageParameters avatarOfUser(User user) {
return WicketUtils.newPageParams(TYPE, AvatarImageType.USER.name().toLowerCase(),
ID, String.valueOf(user.getId()));
return WicketUtils.newPageParams(TYPE, AvatarImageType.USER.name()
.toLowerCase(), ID, String.valueOf(user.getId()));
}
public static PageParameters forUser(User user) {
return WicketUtils.newPageParams(USER, user.getName());
}
public static PageParameters forProject(Project project) {
return WicketUtils.newPageParams(USER, project.getOwner().getName(),
PROJECT, project.getName());
}
public static Link<?> newUserHomeLink(String id, User user) {
return new BookmarkablePageLink<Void>(id, AccountHomePage.class, forUser(user));
}
public static Link<?> newProjectHomeLink(String id, Project project) {
return new BookmarkablePageLink<Void>(id, ProjectHomePage.class, forProject(project));
}
}

View File

@ -51,9 +51,7 @@ public class RegisterPage extends AbstractLayoutPage {
@Override
protected void onInitialize() {
super.onInitialize();
}
};
add(form);

View File

@ -22,7 +22,8 @@
<hr/>
<h4>Teams</h4>
<p class="text-muted"></p>
<p class="text-muted">Manage teams and grant the permissions so that all members in the team can have the permission to access any repositories under this account.</p>
<wicket:container wicket:id="teams"></wicket:container>
</div>
</section>
</wicket:extend>

View File

@ -14,6 +14,7 @@ import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.permission.operation.GeneralOperation;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
@SuppressWarnings("serial")
@ -72,6 +73,8 @@ public class AccountPermissionPage extends AccountSettingPage {
}
});
add(new TeamsPanel("teams", new UserModel(getAccount())));
}
class PermissionLink extends AjaxLink<Void> {

View File

@ -1,5 +1,12 @@
<html xmlns:wicket>
<wicket:extend>
<div wicket:id="editor"></div>
<section>
<div class="head">
<h2 wicket:id="head">Edit Team</h2>
</div>
<div class="body">
<div wicket:id="editor"></div>
</div>
</section>
</wicket:extend>
</html>

View File

@ -1,25 +1,27 @@
package com.pmease.gitop.web.page.account.setting.permission;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.TeamManager;
import com.pmease.gitop.core.model.Team;
import com.pmease.gitop.web.model.TeamModel;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
@SuppressWarnings("serial")
public class EditTeamPage extends AccountSettingPage {
private final Long teamId;
protected final Long teamId;
protected EditTeamPage() {
teamId = null;
public EditTeamPage() {
this.teamId = null;
}
public EditTeamPage(PageParameters params) {
Long teamId = params.get("teamId").toLongObject();
this.teamId = teamId;
this.teamId = params.get("teamId").toLongObject();
}
@Override
@ -36,7 +38,15 @@ public class EditTeamPage extends AccountSettingPage {
protected void onPageInitialize() {
super.onPageInitialize();
add(new TeamEditor("editor", new TeamModel(getTeam())));
add(new TeamEditor("editor", new UserModel(getAccount()), new TeamModel(getTeam())));
add(new Label("head", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return getTeam().isNew() ? "Create Team" : "Edit Team";
}
}));
}
protected Team getTeam() {

View File

@ -2,25 +2,26 @@
<wicket:panel>
<form class="form-inline" wicket:id="infoForm">
<div wicket:id="feedback" class="form-feedback"></div>
<p>Team Name:</p>
<input class="form-control focusable" type="text" placeholder="Team Name" wicket:id="name" />
<div class="btn-group btn-radio-group btn-group-permissions" wicket:id="permissionContainer">
<wicket:container wicket:id="permissions">
<a wicket:id="link" class="btn btn-default">
<a wicket:id="permission" class="btn btn-default">
<span class="icon-ok"></span>
<span wicket:id="name"></span>
</a>
</wicket:container>
</div>
<button type="submit" class="btn btn-primary" wicket:id="submit">Save Team</button>
<button type="submit" class="btn btn-primary btn-colorful-text" wicket:id="submit"><span wicket:id="label"></span></button>
</form>
<wicket:container wicket:id="span">
<hr />
<h4>Members</h4>
<form class="form-inline" wicket:id="memberForm">
<form class="form-inline" wicket:id="membersForm">
<div class="form-feedback" wicket:id="feedback"></div>
<input wicket:id="userchoice" class="user-choice" type="hidden" style="width: 300px"></input>
<button type="submit" class="btn btn-default" wicket:id="submit">Add</button>
<button type="submit" class="btn btn-success btn-colorful-text" wicket:id="submit"><i class="icon-plus"></i> Add</button>
</form>
<hr/>
<div>
@ -32,11 +33,12 @@
</div>
</div>
</div>
</wicket:container>
<wicket:fragment wicket:id="membersview">
<ul class="list-group list-view list-group-hoverable">
<li class="list-group-item" wicket:id="member">
<span wicket:id="avatar"></span>
<span class="avatar" wicket:id="avatar"></span>
<a class="name" wicket:id="link">
<span wicket:id="name"></span>
(<em wicket:id="fullname"></em>)

View File

@ -1,5 +1,9 @@
package com.pmease.gitop.web.page.account.setting.permission;
import java.util.Collections;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
@ -8,115 +12,333 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
import org.hibernate.criterion.Restrictions;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.MembershipManager;
import com.pmease.gitop.core.manager.TeamManager;
import com.pmease.gitop.core.model.Membership;
import com.pmease.gitop.core.model.Team;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.permission.operation.GeneralOperation;
import com.pmease.gitop.web.common.component.messenger.Messenger;
import com.pmease.gitop.web.common.form.FeedbackPanel;
import com.pmease.gitop.web.component.avatar.AvatarImage;
import com.pmease.gitop.web.component.choice.SingleUserChoice;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.PageSpec;
@SuppressWarnings("serial")
public class TeamEditor extends Panel {
public TeamEditor(String id, IModel<Team> model) {
private final IModel<User> userModel;
private WebMarkupContainer membersContainer;
public TeamEditor(String id, IModel<User> userModel, IModel<Team> model) {
super(id, model);
this.userModel = userModel;
this.setOutputMarkupId(true);
}
private User getAccount() {
return userModel.getObject();
}
private Team getTeam() {
return (Team) getDefaultModelObject();
}
@Override
protected void onInitialize() {
super.onInitialize();
this.name = getTeam().getName();
this.operation = getTeam().getAuthorizedOperation();
add(createInfoForm());
membersContainer = new WebMarkupContainer("span") {
@Override
protected void onConfigure() {
super.onConfigure();
this.setVisibilityAllowed(!getTeam().isNew());
}
};
add(membersContainer);
membersContainer.setOutputMarkupId(true);
membersContainer.add(createMembersForm());
final IModel<List<Membership>> relationModel = new LoadableDetachableModel<List<Membership>>() {
@Override
protected List<Membership> load() {
Team team = getTeam();
if (team.isNew()) {
return Collections.emptyList();
}
List<Membership> r = Gitop.getInstance(MembershipManager.class)
.query(Restrictions.eq("team", getTeam()));
Collections.sort(r, new java.util.Comparator<Membership>() {
@Override
public int compare(Membership o1, Membership o2) {
return o1.getUser().getName()
.compareTo(o2.getUser().getName());
}
});
return r;
}
};
membersContainer.add(createMemberList("oddlist", relationModel, true));
membersContainer.add(createMemberList("evenlist", relationModel, false));
membersContainer.add(new Label("total", new AbstractReadOnlyModel<Integer>() {
@Override
public Integer getObject() {
return relationModel.getObject().size();
}
}).setOutputMarkupId(true));
}
private GeneralOperation operation;
private String name;
private Form<?> createInfoForm() {
@SuppressWarnings("unchecked")
IModel<Team> teamModel = (IModel<Team>) getDefaultModel();
Form<Team> infoForm = new Form<Team>("infoForm", teamModel);
operation = getTeam().getAuthorizedOperation();
Form<?> infoForm = new Form<Void>("infoForm");
add(infoForm);
infoForm.add(new FeedbackPanel("feedback"));
infoForm.add(new TextField<String>("name", new PropertyModel<String>(teamModel, "name")).setRequired(true));
WebMarkupContainer permissionContainer =
new WebMarkupContainer("permissionContainer");
infoForm.add(permissionContainer);
permissionContainer.add(
new ListView<GeneralOperation>("permissions",
ImmutableList.<GeneralOperation>of(
GeneralOperation.READ,
GeneralOperation.WRITE,
GeneralOperation.ADMIN)) {
infoForm.add(new TextField<String>("name", new PropertyModel<String>(
this, "name")).add(new IValidator<String>() {
@Override
protected void populateItem(ListItem<GeneralOperation> item) {
GeneralOperation permission = item.getModelObject();
AjaxLink<?> link = new PermissionLink("link", permission);
link.add(new Label("name", permission.toString()));
item.add(link);
@Override
public void validate(IValidatable<String> validatable) {
TeamManager tm = Gitop.getInstance(TeamManager.class);
Team team = tm.find(getAccount(), validatable.getValue());
Team current = getTeam();
if (team != null && !Objects.equal(team, current)) {
validatable.error(new ValidationError()
.setMessage("The team is already exist."));
}
}
}).setRequired(true));
WebMarkupContainer permissionContainer = new WebMarkupContainer(
"permissionContainer");
permissionContainer.setOutputMarkupId(true);
infoForm.add(permissionContainer);
permissionContainer.add(new ListView<GeneralOperation>("permissions",
ImmutableList.<GeneralOperation> of(
GeneralOperation.READ,
GeneralOperation.WRITE,
GeneralOperation.ADMIN)) {
@Override
protected void populateItem(ListItem<GeneralOperation> item) {
GeneralOperation permission = item.getModelObject();
AjaxLink<?> link = new PermissionLink("permission", permission);
link.add(new Label("name", permission.toString()));
item.add(link);
}
});
infoForm.add(new AjaxButton("submit", infoForm) {
AjaxButton btn = new AjaxButton("submit", infoForm) {
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.add(form);
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
Team team = getTeam();
boolean isNew = team.isNew();
User owner = getAccount();
Preconditions.checkNotNull(owner, "owner");
team.setName(name);
team.setAuthorizedOperation(operation);
team.setOwner(owner);
Gitop.getInstance(TeamManager.class).save(team);
Messenger
.success(String.format("Team has been %s successfully.",
isNew ? "created" : "updated"))
.run(target);
target.add(TeamEditor.this);
Messenger.success(
String.format("Team has been %s successfully.",
isNew ? "created" : "updated")).run(target);
}
});
};
btn.add(new Label("label", new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return getTeam().isNew() ? "Create Team" : "Update Team";
}
}));
infoForm.add(btn);
return infoForm;
}
class PermissionLink extends AjaxLink<Void> {
final GeneralOperation permssion;
final GeneralOperation permission;
PermissionLink(String id, final GeneralOperation permission) {
super(id);
this.permssion = permission;
add(AttributeAppender.append("class", new AbstractReadOnlyModel<String>() {
this.permission = permission;
@Override
public String getObject() {
return getTeam().getAuthorizedOperation() == permission ?
"active" : "";
}
}));
add(AttributeAppender.append("class",
new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return Objects.equal(operation, permission) ?
"active" : "";
}
}));
}
@Override
public void onClick(AjaxRequestTarget target) {
Team team = getTeam();
if (team.getAuthorizedOperation() == permssion) {
if (Objects.equal(operation, permission)) {
return;
}
team.setAuthorizedOperation(permssion);
Gitop.getInstance(TeamManager.class).save(team);
target.add(TeamEditor.this.get("infoForm"));
operation = permission;
target.add(TeamEditor.this.get("infoForm").get("permissionContainer"));
}
}
User userToAdd;
private Form<?> createMembersForm() {
Form<?> form = new Form<Void>("membersForm");
form.add(new FeedbackPanel("feedback"));
form.add(new SingleUserChoice("userchoice", new PropertyModel<User>(
this, "userToAdd")));
form.add(new AjaxButton("submit", form) {
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
form.error("Please fix errors below.");
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
if (userToAdd == null) {
form.error("Please select an user first");
target.add(form);
return;
}
Team team = getTeam();
MembershipManager mm = Gitop
.getInstance(MembershipManager.class);
Membership m = mm.find(Restrictions.eq("team", team),
Restrictions.eq("user", userToAdd));
if (m != null) {
form.warn("User has been added already");
target.add(form);
return;
}
m = new Membership();
m.setUser(userToAdd);
m.setTeam(team);
mm.save(m);
Messenger.success(String.format("User [%s] is added to team [%s]",
userToAdd.getName(), team.getName()))
.run(target);
userToAdd = null;
target.add(form);
onMembersChanged(target);
}
});
return form;
}
private void onMembersChanged(AjaxRequestTarget target) {
target.add(membersContainer.get("oddlist"));
target.add(membersContainer.get("evenlist"));
target.add(membersContainer.get("total"));
}
private Component createMemberList(String id,
IModel<List<Membership>> model, final boolean expected) {
Fragment frag = new Fragment(id, "membersview", this);
frag.setOutputMarkupId(true);
frag.add(new ListView<Membership>("member", model) {
@Override
protected void populateItem(ListItem<Membership> item) {
int index = item.getIndex();
boolean odd = index % 2 == 0;
if (odd != expected) {
item.setVisibilityAllowed(false);
return;
}
Membership membership = item.getModelObject();
User user = membership.getUser();
item.add(new AvatarImage("avatar", new UserModel(user)));
Link<?> link = PageSpec.newUserHomeLink("link", user);
link.add(new Label("name", user.getName()));
link.add(new Label("fullname", user.getDisplayName()));
item.add(link);
final Long id = membership.getId();
item.add(new AjaxLink<Void>("remove") {
@Override
public void onClick(AjaxRequestTarget target) {
MembershipManager mm = Gitop.getInstance(MembershipManager.class);
Membership membership = mm.get(id);
Gitop.getInstance(MembershipManager.class).delete(membership);
Messenger.warn(String.format("User [%s] is removed from team [%s]",
membership.getUser().getName(),
membership.getTeam().getName()))
.run(target);
onMembersChanged(target);
}
});
}
});
return frag;
}
@Override
public void onDetach() {
if (userModel != null) {
userModel.detach();
}
super.onDetach();
}
}

View File

@ -0,0 +1,19 @@
<html xmlns:wicket>
<wicket:panel>
<p>
<a class="btn btn-info" wicket:id="addTeam"><i class="icon-plus"></i> Create a team</a>
</p>
<table class="table table-condensed table-hover" wicket:id="teams"></table>
<wicket:fragment wicket:id="ops">
<div class="action-links">
<span class="link-item"><a wicket:id="edit"><i class="icon-edit"></i> edit</a></span>
<span class="link-item"><a wicket:id="remove"><i class="icon-remove-sign"></i> remove</a></span>
</div>
</wicket:fragment>
<wicket:fragment wicket:id="namefrag">
<span wicket:id="name"></span> <span class="text-muted">(<b wicket:id="members"></b> members)</span>
</wicket:fragment>
</wicket:panel>
</html>

View File

@ -0,0 +1,214 @@
package com.pmease.gitop.web.page.account.setting.permission;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.event.IEvent;
import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackHeadersToolbar;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.NoRecordsToolbar;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.pmease.gitop.core.Gitop;
import com.pmease.gitop.core.manager.TeamManager;
import com.pmease.gitop.core.model.Team;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.core.permission.operation.GeneralOperation;
import com.pmease.gitop.web.common.bootstrap.AjaxIconLink;
import com.pmease.gitop.web.common.bootstrap.IconType;
import com.pmease.gitop.web.common.component.datagrid.DataGrid;
import com.pmease.gitop.web.common.component.datagrid.event.SearchStringChanged;
import com.pmease.gitop.web.common.component.datagrid.hibernate.HibernateDataProvider;
import com.pmease.gitop.web.common.component.datagrid.toolbar.SearchNavToolbar;
import com.pmease.gitop.web.common.component.vex.AjaxConfirmLink;
import com.pmease.gitop.web.util.WicketUtils;
@SuppressWarnings("serial")
public class TeamsPanel extends Panel {
public TeamsPanel(String id, IModel<User> user) {
super(id, user);
}
@Override
protected void onInitialize() {
super.onInitialize();
add(new BookmarkablePageLink<Void>("addTeam", AddTeamPage.class));
add(createTeamPermissionsTable("teams"));
}
private Component createTeamPermissionsTable(String id) {
List<IColumn<Team, String>> columns = Lists.newArrayList();
columns.add(new AbstractColumn<Team, String>(Model.of("Name"), "name") {
@Override
public void populateItem(Item<ICellPopulator<Team>> cellItem,
String componentId, IModel<Team> rowModel) {
Team team = rowModel.getObject();
Fragment frag = new Fragment(componentId, "namefrag",
TeamsPanel.this);
frag.add(new Label("name", team.getName()));
frag.add(new Label("members", team.getMemberships().size()));
cellItem.add(frag);
}
});
columns.add(new TeamPermissionColumn(Model.of("Read"), GeneralOperation.READ));
columns.add(new TeamPermissionColumn(Model.of("Write"), GeneralOperation.WRITE));
columns.add(new TeamPermissionColumn(Model.of("Admin"), GeneralOperation.ADMIN));
columns.add(new AbstractColumn<Team, String>(Model.of("")) {
@Override
public void populateItem(Item<ICellPopulator<Team>> cellItem,
String componentId, final IModel<Team> rowModel) {
Fragment frag = new Fragment(componentId, "ops", TeamsPanel.this);
frag.add(new BookmarkablePageLink<Void>("edit",
EditTeamPage.class, WicketUtils.newPageParams("teamId", rowModel.getObject().getId())));
Team team = rowModel.getObject();
frag.add(new AjaxConfirmLink<Void>("remove",
Model.of("Are you sure you want to remove team " + team.getName())) {
@Override
public void onClick(AjaxRequestTarget target) {
Team p = rowModel.getObject();
Gitop.getInstance(TeamManager.class).delete(p);
onTeamTableChanged(target);
}
});
cellItem.add(frag);
}
@Override
public String getCssClass() {
return "operations-td";
}
});
final List<Criterion> criterions = Lists.newArrayList();
HibernateDataProvider<Team> teamProvider = new HibernateDataProvider<Team>() {
@Override
protected DetachedCriteria getCriteria() {
DetachedCriteria criteria = DetachedCriteria.forClass(Team.class);
criteria.add(Restrictions.eq("owner", getUser()));
for (Criterion each : criterions) {
criteria.add(each);
}
return criteria;
}
};
DataGrid<Team> dataTable = new DataGrid<Team>(id, columns,
teamProvider, 10) {
@Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof SearchStringChanged) {
SearchStringChanged e = (SearchStringChanged) event.getPayload();
criterions.clear();
if (!Strings.isNullOrEmpty(e.getPattern())) {
criterions.add(Restrictions.ilike("name", e.getPattern(), MatchMode.ANYWHERE));
}
e.getTarget().add(this);
}
}
};
dataTable.setOutputMarkupId(true);
dataTable.addTopToolbar(new AjaxFallbackHeadersToolbar<String>(dataTable, teamProvider));
dataTable.addBottomToolbar(new NoRecordsToolbar(dataTable, Model.of("No Teams Found")));
dataTable.addBottomToolbar(new SearchNavToolbar(dataTable));
return dataTable;
}
private class TeamPermissionColumn extends AbstractColumn<Team, String> {
private GeneralOperation expected;
public TeamPermissionColumn(IModel<String> displayModel,
GeneralOperation expected) {
super(displayModel);
this.expected = expected;
}
@Override
public void populateItem(Item<ICellPopulator<Team>> cellItem,
String componentId, final IModel<Team> rowModel) {
IModel<IconType> iconModel = new AbstractReadOnlyModel<IconType>() {
@Override
public IconType getObject() {
return rowModel.getObject().getAuthorizedOperation().can(expected) ?
IconType.CHECK : IconType.CHECK_EMPTY;
}
};
cellItem.add(new AjaxIconLink(componentId, iconModel) {
@Override
protected AjaxLink<?> createLink(String id) {
AjaxLink<?> link = new AjaxLink<Void>(id) {
@Override
public void onClick(AjaxRequestTarget target) {
GeneralOperation old = rowModel.getObject().getAuthorizedOperation();
Team team = rowModel.getObject();
if (old == expected) {
int ordinal = expected.ordinal() - 1;
if (ordinal < 0) {
ordinal = 0;
}
team.setAuthorizedOperation(GeneralOperation.values()[ordinal]);
} else {
team.setAuthorizedOperation(expected);
}
Gitop.getInstance(TeamManager.class).save(team);
onTeamTableChanged(target);
}
};
link.add(AttributeAppender.append("class", "permission-link"));
return link;
}
});
}
}
private void onTeamTableChanged(AjaxRequestTarget target) {
target.add(get("teams"));
}
private User getUser() {
return (User) getDefaultModelObject();
}
}

View File

@ -0,0 +1,135 @@
package com.pmease.gitop.web.resource;
import java.io.IOException;
import java.util.List;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.apache.shiro.authc.credential.PasswordService;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
@Path("/github")
public class GitHubUserResource {
@Inject ObjectMapper objectMapper;
@Inject UserManager userManager;
@Inject PasswordService passwordService;
@GET
public Response get() {
try {
updateDatabase("github");
} catch (Exception e) {
throw Throwables.propagate(e);
}
return Response.ok("Everything is ok").build();
}
private void updateDatabase(String org) throws JsonParseException,
JsonMappingException, UniformInterfaceException,
ClientHandlerException, IOException {
Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("zhenyuluo", "hongmei9"));
WebResource r = client.resource("https://api.github.com/orgs/" + org
+ "/public_members");
String content = r.get(String.class);
objectMapper.configure(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
List<HubUser> users = objectMapper.readValue(content,
new TypeReference<List<HubUser>>() {
});
users = users.subList(102, users.size());
for (HubUser each : users) {
try {
r = client.resource("https://api.github.com/users/"
+ each.login);
HubUser u = objectMapper.readValue(r.get(String.class),
HubUser.class);
User user = new User();
user.setName(u.login);
user.setDisplayName(u.name);
if (Strings.isNullOrEmpty(u.email)) {
user.setEmail(u.login + "@github.com");
} else {
user.setEmail(u.email);
}
user.setPasswordHash(passwordService.encryptPassword("12345"));
userManager.save(user);
System.out.println(user.getId() + " " + user);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class HubUsers {
@JsonProperty
List<HubUser> users = Lists.newArrayList();
public List<HubUser> getUsers() {
return users;
}
public void setUsers(List<HubUser> users) {
this.users = users;
}
}
public static class HubUser {
@JsonProperty
private String login;
@JsonProperty
private String name;
@JsonProperty
private String email;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}