/** * Copyright (c) 2008-2012 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sakaiproject.profile2.tool.pages.panels; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.feedback.FeedbackMessage; 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.panel.FeedbackPanel; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; import org.apache.wicket.validation.validator.EmailAddressValidator; import org.apache.wicket.validation.validator.UrlValidator; import org.sakaiproject.api.common.edu.person.SakaiPerson; import org.sakaiproject.profile2.logic.ProfileLogic; import org.sakaiproject.profile2.logic.ProfileWallLogic; import org.sakaiproject.profile2.logic.SakaiProxy; import org.sakaiproject.profile2.model.UserProfile; import org.sakaiproject.profile2.tool.components.ComponentVisualErrorBehaviour; import org.sakaiproject.profile2.tool.components.ErrorLevelsFeedbackMessageFilter; import org.sakaiproject.profile2.tool.components.FeedbackLabel; import org.sakaiproject.profile2.tool.components.PhoneNumberValidator; import org.sakaiproject.profile2.util.ProfileConstants; public class MyContactEdit extends Panel { private static final long serialVersionUID = 1L; private static final Logger log = Logger.getLogger(MyInfoEdit.class); @SpringBean(name="org.sakaiproject.profile2.logic.SakaiProxy") private SakaiProxy sakaiProxy; @SpringBean(name="org.sakaiproject.profile2.logic.ProfileWallLogic") private ProfileWallLogic wallLogic; @SpringBean(name="org.sakaiproject.profile2.logic.ProfileLogic") private ProfileLogic profileLogic; public MyContactEdit(final String id, final UserProfile userProfile) { super(id); log.debug("MyContactEdit()"); //this panel final Component thisPanel = this; //get userId final String userId = userProfile.getUserUuid(); //heading add(new Label("heading", new ResourceModel("heading.contact.edit"))); //setup form Form form = new Form("form", new Model(userProfile)); form.setOutputMarkupId(true); //form submit feedback final Label formFeedback = new Label("formFeedback"); formFeedback.setOutputMarkupPlaceholderTag(true); form.add(formFeedback); //add warning message if superUser and not editing own profile Label editWarning = new Label("editWarning"); editWarning.setVisible(false); if(sakaiProxy.isSuperUserAndProxiedToUser(userId)) { editWarning.setDefaultModel(new StringResourceModel("text.edit.other.warning", null, new Object[]{ userProfile.getDisplayName() } )); editWarning.setEscapeModelStrings(false); editWarning.setVisible(true); } form.add(editWarning); //We don't need to get the info from userProfile, we load it into the form with a property model //just make sure that the form element id's match those in the model // FeedbackPanel final FeedbackPanel feedback = new FeedbackPanel("feedback"); feedback.setOutputMarkupId(true); form.add(feedback); // filteredErrorLevels will not be shown in the FeedbackPanel int[] filteredErrorLevels = new int[]{FeedbackMessage.ERROR}; feedback.setFilter(new ErrorLevelsFeedbackMessageFilter(filteredErrorLevels)); //email WebMarkupContainer emailContainer = new WebMarkupContainer("emailContainer"); emailContainer.add(new Label("emailLabel", new ResourceModel("profile.email"))); final TextField email = new TextField("email", new PropertyModel(userProfile, "email")); email.setOutputMarkupId(true); email.setMarkupId("emailinput"); email.add(EmailAddressValidator.getInstance()); //readonly view Label emailReadOnly = new Label("emailReadOnly", new PropertyModel(userProfile, "email")); if(sakaiProxy.isAccountUpdateAllowed(userId)) { emailReadOnly.setVisible(false); } else { email.setVisible(false); } emailContainer.add(email); emailContainer.add(emailReadOnly); //email feedback final FeedbackLabel emailFeedback = new FeedbackLabel("emailFeedback", email); emailFeedback.setMarkupId("emailFeedback"); emailFeedback.setOutputMarkupId(true); emailContainer.add(emailFeedback); email.add(new ComponentVisualErrorBehaviour("onblur", emailFeedback)); form.add(emailContainer); //homepage WebMarkupContainer homepageContainer = new WebMarkupContainer("homepageContainer"); homepageContainer.add(new Label("homepageLabel", new ResourceModel("profile.homepage"))); final TextField homepage = new TextField("homepage", new PropertyModel(userProfile, "homepage")) { private static final long serialVersionUID = 1L; // add http:// if missing @Override protected void convertInput() { String input = getInput(); if (StringUtils.isNotBlank(input) && !(input.startsWith("http://") || input.startsWith("https://"))) { setConvertedInput("http://" + input); } else { setConvertedInput(StringUtils.isBlank(input) ? null : input); } } }; homepage.setMarkupId("homepageinput"); homepage.setOutputMarkupId(true); homepage.add(new UrlValidator()); homepageContainer.add(homepage); //homepage feedback final FeedbackLabel homepageFeedback = new FeedbackLabel("homepageFeedback", homepage); homepageFeedback.setMarkupId("homepageFeedback"); homepageFeedback.setOutputMarkupId(true); homepageContainer.add(homepageFeedback); homepage.add(new ComponentVisualErrorBehaviour("onblur", homepageFeedback)); form.add(homepageContainer); //workphone WebMarkupContainer workphoneContainer = new WebMarkupContainer("workphoneContainer"); workphoneContainer.add(new Label("workphoneLabel", new ResourceModel("profile.phone.work"))); final TextField workphone = new TextField("workphone", new PropertyModel(userProfile, "workphone")); workphone.setMarkupId("workphoneinput"); workphone.setOutputMarkupId(true); workphone.add(new PhoneNumberValidator()); workphoneContainer.add(workphone); //workphone feedback final FeedbackLabel workphoneFeedback = new FeedbackLabel("workphoneFeedback", workphone); workphoneFeedback.setMarkupId("workphoneFeedback"); workphoneFeedback.setOutputMarkupId(true); workphoneContainer.add(workphoneFeedback); workphone.add(new ComponentVisualErrorBehaviour("onblur", workphoneFeedback)); form.add(workphoneContainer); //homephone WebMarkupContainer homephoneContainer = new WebMarkupContainer("homephoneContainer"); homephoneContainer.add(new Label("homephoneLabel", new ResourceModel("profile.phone.home"))); final TextField homephone = new TextField("homephone", new PropertyModel(userProfile, "homephone")); homephone.setMarkupId("homephoneinput"); homephone.setOutputMarkupId(true); homephone.add(new PhoneNumberValidator()); homephoneContainer.add(homephone); //homephone feedback final FeedbackLabel homephoneFeedback = new FeedbackLabel("homephoneFeedback", homephone); homephoneFeedback.setMarkupId("homephoneFeedback"); homephoneFeedback.setOutputMarkupId(true); homephoneContainer.add(homephoneFeedback); homephone.add(new ComponentVisualErrorBehaviour("onblur", homephoneFeedback)); form.add(homephoneContainer); //mobilephone WebMarkupContainer mobilephoneContainer = new WebMarkupContainer("mobilephoneContainer"); mobilephoneContainer.add(new Label("mobilephoneLabel", new ResourceModel("profile.phone.mobile"))); final TextField mobilephone = new TextField("mobilephone", new PropertyModel(userProfile, "mobilephone")); mobilephone.setMarkupId("mobilephoneinput"); mobilephone.setOutputMarkupId(true); mobilephone.add(new PhoneNumberValidator()); mobilephoneContainer.add(mobilephone); //mobilephone feedback final FeedbackLabel mobilephoneFeedback = new FeedbackLabel("mobilephoneFeedback", mobilephone); mobilephoneFeedback.setMarkupId("mobilephoneFeedback"); mobilephoneFeedback.setOutputMarkupId(true); mobilephoneContainer.add(mobilephoneFeedback); mobilephone.add(new ComponentVisualErrorBehaviour("onblur", mobilephoneFeedback)); form.add(mobilephoneContainer); //facsimile WebMarkupContainer facsimileContainer = new WebMarkupContainer("facsimileContainer"); facsimileContainer.add(new Label("facsimileLabel", new ResourceModel("profile.phone.facsimile"))); final TextField facsimile = new TextField("facsimile", new PropertyModel(userProfile, "facsimile")); facsimile.setMarkupId("facsimileinput"); facsimile.setOutputMarkupId(true); facsimile.add(new PhoneNumberValidator()); facsimileContainer.add(facsimile); //facsimile feedback final FeedbackLabel facsimileFeedback = new FeedbackLabel("facsimileFeedback", facsimile); facsimileFeedback.setMarkupId("facsimileFeedback"); facsimileFeedback.setOutputMarkupId(true); facsimileContainer.add(facsimileFeedback); facsimile.add(new ComponentVisualErrorBehaviour("onblur", facsimileFeedback)); form.add(facsimileContainer); //submit button AjaxFallbackButton submitButton = new AjaxFallbackButton("submit", new ResourceModel("button.save.changes"), form) { protected void onSubmit(AjaxRequestTarget target, Form form) { //save() form, show message, then load display panel if(save(form)) { //post update event sakaiProxy.postEvent(ProfileConstants.EVENT_PROFILE_CONTACT_UPDATE, "/profile/"+userId, true); //post to wall if enabled if (true == sakaiProxy.isWallEnabledGlobally() && false == sakaiProxy.isSuperUserAndProxiedToUser(userId)) { wallLogic.addNewEventToWall(ProfileConstants.EVENT_PROFILE_CONTACT_UPDATE, sakaiProxy.getCurrentUserId()); } //repaint panel Component newPanel = new MyContactDisplay(id, userProfile); newPanel.setOutputMarkupId(true); thisPanel.replaceWith(newPanel); if(target != null) { target.addComponent(newPanel); //resize iframe target.appendJavascript("setMainFrameHeight(window.name);"); } } else { //String js = "alert('Failed to save information. Contact your system administrator.');"; //target.prependJavascript(js); formFeedback.setDefaultModel(new ResourceModel("error.profile.save.contact.failed")); formFeedback.add(new AttributeModifier("class", true, new Model<String>("save-failed-error"))); target.addComponent(formFeedback); } } // This is called if the form validation fails, ie Javascript turned off, //or we had preexisting invalid data before this fix was introduced protected void onError(AjaxRequestTarget target, Form form) { //check which item didn't validate and update the class and feedback model for that component if(!email.isValid()) { email.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); emailFeedback.setDefaultModel(new ResourceModel("EmailAddressValidator")); target.addComponent(email); target.addComponent(emailFeedback); } if(!homepage.isValid()) { homepage.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); homepageFeedback.setDefaultModel(new ResourceModel("UrlValidator")); target.addComponent(homepage); target.addComponent(homepageFeedback); } if(!facsimile.isValid()) { facsimile.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); facsimileFeedback.setDefaultModel(new ResourceModel("PhoneNumberValidator")); target.addComponent(facsimile); target.addComponent(facsimileFeedback); } if(!workphone.isValid()) { workphone.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); workphoneFeedback.setDefaultModel(new ResourceModel("PhoneNumberValidator")); target.addComponent(workphone); target.addComponent(workphoneFeedback); } if(!homephone.isValid()) { homephone.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); homephoneFeedback.setDefaultModel(new ResourceModel("PhoneNumberValidator")); target.addComponent(homephone); target.addComponent(homephoneFeedback); } if(!mobilephone.isValid()) { mobilephone.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); mobilephoneFeedback.setDefaultModel(new ResourceModel("PhoneNumberValidator")); target.addComponent(mobilephone); target.addComponent(mobilephoneFeedback); } if(!facsimile.isValid()) { facsimile.add(new AttributeAppender("class", new Model<String>("invalid"), " ")); facsimileFeedback.setDefaultModel(new ResourceModel("PhoneNumberValidator")); target.addComponent(facsimile); target.addComponent(facsimileFeedback); } } }; form.add(submitButton); //cancel button AjaxFallbackButton cancelButton = new AjaxFallbackButton("cancel", new ResourceModel("button.cancel"), form) { private static final long serialVersionUID = 1L; protected void onSubmit(AjaxRequestTarget target, Form form) { Component newPanel = new MyContactDisplay(id, userProfile); newPanel.setOutputMarkupId(true); thisPanel.replaceWith(newPanel); if(target != null) { target.addComponent(newPanel); //resize iframe target.appendJavascript("setMainFrameHeight(window.name);"); } } }; cancelButton.setDefaultFormProcessing(false); form.add(cancelButton); //add form to page add(form); } //called when the form is to be saved private boolean save(Form form) { //get the backing model UserProfile userProfile = (UserProfile) form.getModelObject(); //get userId from the UserProfile (because admin could be editing), then get existing SakaiPerson for that userId String userId = userProfile.getUserUuid(); SakaiPerson sakaiPerson = sakaiProxy.getSakaiPerson(userId); //set the attributes from userProfile that this form dealt with, into sakaiPerson //this WILL fail if there is no sakaiPerson for the user however this should have been caught already //as a new Sakaiperson for a user is created in MyProfile if they don't have one. //sakaiPerson.setMail(userProfile.getEmail()); //email sakaiPerson.setLabeledURI(userProfile.getHomepage()); //homepage sakaiPerson.setTelephoneNumber(userProfile.getWorkphone()); //workphone sakaiPerson.setHomePhone(userProfile.getHomephone()); //homephone sakaiPerson.setMobile(userProfile.getMobilephone()); //mobilephone sakaiPerson.setFacsimileTelephoneNumber(userProfile.getFacsimile()); //facsimile if(profileLogic.saveUserProfile(sakaiPerson)) { log.info("Saved SakaiPerson for: " + userId ); //update their email address in their account if allowed if(sakaiProxy.isAccountUpdateAllowed(userId)) { sakaiProxy.updateEmailForUser(userId, userProfile.getEmail()); } return true; } else { log.info("Couldn't save SakaiPerson for: " + userId); return false; } } }