Continue working on wicket components

This commit is contained in:
steve 2013-10-07 03:54:07 +08:00
parent 0ba160fca5
commit 283766c0c2
18 changed files with 260 additions and 67 deletions

13
.gitignore vendored
View File

@ -5,3 +5,16 @@ target/
.settings/
release.properties
pom.xml.releaseBackup
.loadpath
*.class
*~
*.lock
*.swp
*.out
*.tmp
*.bak
*.swp
*~.nib
*.DS_Store
*.log

View File

@ -42,7 +42,7 @@ public class SitePaths {
}
public File userAvatarDir(User user) {
return userAvatarDir(checkNotNull(user));
return userAvatarDir(checkNotNull(user).getId());
}
public File tempDir() {

View File

@ -251,6 +251,8 @@ a > .icon-null, .icon-null { display: inline-block; width: 10px; }
.avatar-circle { border-radius: 50%; }
.avatar-circle > img { border-radius: 50%; }
.avatar-xlarge { width: 128px; height: 128px; }
/**
* LAYOUT
*/

View File

@ -5,6 +5,8 @@ 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.behavior.AttributeAppender;
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;
@ -48,4 +50,12 @@ 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,7 +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;
import org.apache.wicket.model.Model;
@ -44,8 +44,10 @@ 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(); });",
markupId)));
}
@Override

View File

@ -41,10 +41,4 @@
});
}
$(document).ready(function() {
$('.confirm-link').click(function(e) {
e.preventDefault();
$(this).confirm();
})
});
}(window.jQuery, window, document);

View File

@ -31,7 +31,6 @@ public class FeedbackPanel extends org.apache.wicket.markup.html.panel.FeedbackP
super.onInitialize();
this.setOutputMarkupId(true);
add(AttributeModifier.append("class", new AbstractReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;

View File

@ -1,6 +1,10 @@
package com.pmease.gitop.web.common.form.flatcheckbox;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.model.IModel;
@ -29,6 +33,19 @@ public class FlatCheckBoxElement extends CheckBoxElement {
panel.add(label);
panel.add(new FlatCheckBoxBehavior());
panel.add(new AbstractDefaultAjaxBehavior() {
@Override
protected void respond(AjaxRequestTarget target) {
}
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(OnDomReadyHeaderItem.forScript(String.format("$('#%s').checkbox()", checkbox.getMarkupId(true))));
}
});
return panel;
}
}

View File

@ -1,6 +1,10 @@
package com.pmease.gitop.web.common.form.flatradio;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Radio;
import org.apache.wicket.model.IModel;
@ -19,12 +23,25 @@ public class FlatRadioElement<T> extends RadioButtonElement<T> {
this.descriptionModel = Model.of(description);
}
@SuppressWarnings("serial")
@Override
protected Component createInputComponent(String id) {
radioContainer = new FlatRadioElementPanel(id);
radioContainer.add(radio = createRadio("radio"));
radioContainer.add(new Label("description", descriptionModel));
radioContainer.add(new FlatRadioBehavior());
radioContainer.add(new AbstractDefaultAjaxBehavior() {
@Override
protected void respond(AjaxRequestTarget target) {
}
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(OnDomReadyHeaderItem.forScript(String.format("$('#%s').radio()", radio.getMarkupId(true))));
}
});
return radioContainer;
}

View File

@ -23,7 +23,8 @@ public class AvatarImageResource extends DynamicImageResource {
@Override
protected byte[] getImageData(Attributes attributes) {
PageParameters params = attributes.getParameters();
AvatarImageType imageType = AvatarImageType.valueOf(params.get("type").toString().toUpperCase());
AvatarImageType imageType = AvatarImageType.valueOf(params.get("type")
.toString().toUpperCase());
long id = params.get("id").toLong();
File avatarFile = null;
@ -31,12 +32,15 @@ public class AvatarImageResource extends DynamicImageResource {
User user = AppLoader.getInstance(UserManager.class).get(id);
if (!Strings.isNullOrEmpty(user.getAvatarUrl())) {
avatarFile = new File(SitePaths.get().userAvatarDir(id), user.getAvatarUrl());
avatarFile = new File(SitePaths.get().userAvatarDir(id),
user.getAvatarUrl());
}
} else {
// Repository project = AppLoader.getInstance(RepositoryManager.class).get(id);
// Repository project =
// AppLoader.getInstance(RepositoryManager.class).get(id);
// if (!Strings.isNullOrEmpty(project.getAvatarUrl())) {
// avatarFile = new File(GitopWebApp.getProjectAvatarDir(id), project.getAvatarUrl());
// avatarFile = new File(GitopWebApp.getProjectAvatarDir(id),
// project.getAvatarUrl());
// }
}

View File

@ -1,6 +1,5 @@
package com.pmease.gitop.web.page;
import org.apache.shiro.SecurityUtils;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Panel;
@ -40,7 +39,7 @@ public class GlobalHeaderPanel extends Panel {
}
protected boolean isSignedIn() {
return SecurityUtils.getSubject().isAuthenticated();
return currentUser().isPresent();
}
protected Optional<User> currentUser() {

View File

@ -1,6 +1,5 @@
package com.pmease.gitop.web.page.account;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.IModel;
@ -14,7 +13,6 @@ import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.page.AbstractLayoutPage;
@SuppressWarnings("serial")
@RequiresAuthentication
public class AccountHomePage extends AbstractLayoutPage {
private final IModel<User> accountModel;

View File

@ -1,7 +1,6 @@
package com.pmease.gitop.web.page.account.setting;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
@ -23,7 +22,6 @@ import com.pmease.gitop.web.page.account.setting.profile.AccountProfilePage;
import com.pmease.gitop.web.page.account.setting.repos.AccountReposPage;
@SuppressWarnings("serial")
@RequiresAuthentication
public abstract class AccountSettingPage extends AbstractLayoutPage {
public static enum Category {

View File

@ -13,6 +13,7 @@ import org.apache.wicket.validation.ValidationError;
import com.pmease.commons.loader.AppLoader;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.common.component.messenger.Messenger;
import com.pmease.gitop.web.common.form.passwordfield.PasswordFieldElement;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
@ -76,9 +77,12 @@ public class AccountPasswordPage extends AccountSettingPage {
User account = getAccount();
account.setPasswordHash(ps.encryptPassword(newPass));
AppLoader.getInstance(UserManager.class).save(account);
form.success("The password was changed successfully.");
if (target != null) {
oldPass = null;
newPass = null;
confirmPass = null;
target.add(form);
Messenger.success("Your password has been changed successfully.").execute(target);
}
}

View File

@ -20,9 +20,23 @@
<h3>Change your avatar</h3>
</div>
<div class="padder">
<div class="clearfix">
<div class="left avatar avatar-xlarge" wicket:id="currentavatar"></div>
<form wicket:id="avatarForm" class="form-md" style="padding-left: 150px;">
<div wicket:id="feedback" class="form-feedback"></div>
<p>
Here is your avatar?
<input type="file" wicket:id="fileInput" />
</p>
<p class="text-muted">
Supported image types are png, gif, jpg and jpeg. The image size should be less than 128K bytes.
</p>
<hr/>
<div class="btn-group btn-group-justified">
<a wicket:id="submit" class="btn btn-colorful-text btn-primary">Change avatar</a>
<a wicket:id="remove" class="btn btn-colorful-text btn-warning">Reset avatar</a>
</div>
</form>
</div>
</div>
</section>
</wicket:extend>

View File

@ -1,17 +1,33 @@
package com.pmease.gitop.web.page.account.setting.profile;
import java.io.File;
import java.io.IOException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.bean.validation.PropertyValidator;
import org.apache.wicket.event.Broadcast;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.markup.html.form.upload.FileUploadField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.io.Files;
import com.pmease.commons.loader.AppLoader;
import com.pmease.commons.util.FileUtils;
import com.pmease.gitop.core.manager.UserManager;
import com.pmease.gitop.core.model.User;
import com.pmease.gitop.web.SitePaths;
import com.pmease.gitop.web.common.component.messenger.Messenger;
import com.pmease.gitop.web.common.component.vex.AjaxConfirmButton;
import com.pmease.gitop.web.common.form.FeedbackPanel;
import com.pmease.gitop.web.common.form.textfield.TextFieldElement;
import com.pmease.gitop.web.component.avatar.AvatarChanged;
import com.pmease.gitop.web.component.avatar.AvatarImage;
import com.pmease.gitop.web.model.UserModel;
import com.pmease.gitop.web.page.account.setting.AccountSettingPage;
@ -32,7 +48,11 @@ public class AccountProfilePage extends AccountSettingPage {
protected void onInitialize() {
super.onInitialize();
add(new ProfileForm("form", new UserModel(getAccount())));
IModel<User> userModel = new UserModel(getAccount());
add(new ProfileForm("form", userModel));
add(new AvatarImage("currentavatar", userModel));
add(new AvatarForm("avatarForm", userModel));
}
private class ProfileForm extends Form<User> {
@ -51,8 +71,7 @@ public class AccountProfilePage extends AccountSettingPage {
add(new FeedbackPanel("feedback", this));
add(new TextFieldElement<String>("displayName", "Display Name",
new PropertyModel<String>(model, "displayName"))
.setRequired(false)
.add(new PropertyValidator<String>()));
.setRequired(false).add(new PropertyValidator<String>()));
add(new TextFieldElement<String>("email", "Email Address",
new PropertyModel<String>(model, "email"))
.add(new PropertyValidator<String>()));
@ -67,7 +86,100 @@ public class AccountProfilePage extends AccountSettingPage {
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
User user = model.getObject();
AppLoader.getInstance(UserManager.class).save(user);
form.success("Your profile has been updated");
Messenger.success("Account profile has been updated.")
.execute(target);
}
});
}
}
private class AvatarForm extends Form<User> {
AvatarForm(String id, IModel<User> model) {
super(id, model);
}
private User getUser() {
return (User) getDefaultModelObject();
}
@Override
protected void onInitialize() {
super.onInitialize();
final FileUploadField uploadField = new FileUploadField("fileInput");
uploadField.setRequired(false);
add(uploadField);
add(new FeedbackPanel("feedback"));
add(new AjaxButton("submit", this) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
FileUpload upload = uploadField.getFileUpload();
if (upload == null) {
form.error("Please select an avatar file");
target.add(form);
return;
}
User user = getUser();
if (upload != null) {
File dir = SitePaths.get().userAvatarDir(user);
if (!dir.exists()) {
try {
FileUtils.forceMkdir(dir);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
String filename = upload.getClientFileName();
String ext = Files.getFileExtension(filename);
File avatarFile;
// delete old avatar file
String avatarPath = user.getAvatarUrl();
if (!Strings.isNullOrEmpty(avatarPath)
&& !(avatarPath.startsWith("http") || avatarPath
.startsWith("https"))) {
avatarFile = new File(dir, user.getAvatarUrl());
// TODO: lock avatarFile for write
if (avatarFile.exists()) {
try {
FileUtils.forceDelete(avatarFile);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}
avatarFile = new File(dir, "avatar." + ext);
try {
upload.writeTo(avatarFile);
} catch (IOException e) {
throw Throwables.propagate(e);
}
user.setAvatarUrl(avatarFile.getName());
AppLoader.getInstance(UserManager.class).save(user);
send(getPage(), Broadcast.BREADTH, new AvatarChanged(target));
target.add(form);
Messenger.success("Your avatar has been changed!").execute(target);;
}
}
});
add(new AjaxConfirmButton("remove", this,
Model.of("Are you sure you want to use the default avatar?"),
null, Model.of("Yes"), Model.of("No"), null) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
User user = getUser();
user.setAvatarUrl(null);
AppLoader.getInstance(UserManager.class).save(user);
send(getPage(), Broadcast.BREADTH, new AvatarChanged(target));
Messenger.success("Your avatar has been reset to the default.").execute(target);
target.add(form);
}
});

View File

@ -2,7 +2,7 @@
<wicket:extend>
<div class="container">
<h2>Messenger Test</h2>
<div class="btn btn-group">
<div class="btn-group">
<a class="btn btn-info" wicket:id="ajaxinfo">ajax info</a>
<a class="btn btn-danger" wicket:id="ajaxerror">ajax error</a>
<a class="btn btn-success" wicket:id="ajaxsuccess">ajax success</a>
@ -11,6 +11,7 @@
<h3>Flat UI Form</h3>
<form class="custom-form" wicket:id="form">
<div wicket:id="feedback" class="form-feedback"></div>
<div wicket:id="check"></div>
<wicket:container wicket:id="group">

View File

@ -13,6 +13,7 @@ import com.google.common.collect.ImmutableList;
import com.pmease.gitop.web.common.component.messenger.Messenger;
import com.pmease.gitop.web.common.component.vex.AjaxConfirmButton;
import com.pmease.gitop.web.common.component.vex.VexLinkBehavior.VexIcon;
import com.pmease.gitop.web.common.form.FeedbackPanel;
import com.pmease.gitop.web.common.form.flatcheckbox.FlatCheckBoxElement;
import com.pmease.gitop.web.common.form.flatradio.FlatRadioElement;
import com.pmease.gitop.web.page.AbstractLayoutPage;
@ -60,12 +61,20 @@ public class HomePage extends AbstractLayoutPage {
Form<?> form = new Form<Void>("form");
add(form);
form.add(new FeedbackPanel("feedback"));
form.add(new FlatCheckBoxElement("check", new PropertyModel<Boolean>(this, "displayed"),
Model.of("Displayed screen")));
form.add(new AjaxConfirmButton("btn", form, Model.of("Are you want to save this form?")) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
if (displayed) {
form.info("yes");
target.add(form);
return;
}
System.out.println("Here is " + vexIcon);
target.add(form);
}
});