1 /**
  2  * Copyright (C) 2005-2010 Alfresco Software Limited.
  3  *
  4  * This file is part of Alfresco
  5  *
  6  * Alfresco is free software: you can redistribute it and/or modify
  7  * it under the terms of the GNU Lesser General Public License as published by
  8  * the Free Software Foundation, either version 3 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * Alfresco is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public License
 17  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 18  */
 19 
 20 /**
 21  * User Profile component.
 22  * 
 23  * @namespace Alfresco
 24  * @class Alfresco.UserProfile
 25  * @extends Alfresco.component.Base
 26  */
 27 (function()
 28 {
 29    /**
 30     * YUI Library aliases
 31     */
 32    var Dom = YAHOO.util.Dom,
 33       Event = YAHOO.util.Event,
 34       Element = YAHOO.util.Element;
 35    
 36    /**
 37     * UserProfile constructor.
 38     * 
 39     * @param {String} htmlId The HTML id of the parent element
 40     * @return {Alfresco.UserProfile} The new UserProfile instance
 41     * @constructor
 42     */
 43    Alfresco.UserProfile = function(htmlId)
 44    {
 45       Alfresco.UserProfile.superclass.constructor.call(this, "Alfresco.UserProfile", htmlId, ["button"]);
 46       return this;
 47    };
 48    
 49    YAHOO.extend(Alfresco.UserProfile, Alfresco.component.Base,
 50    {
 51       /**
 52        * Object container for initialization options
 53        *
 54        * @property options
 55        * @type object
 56        */
 57       options:
 58       {
 59          /**
 60           * Current userId.
 61           * 
 62           * @property userId
 63           * @type string
 64           * @default ""
 65           */
 66          userId: "",
 67          
 68          /**
 69           * Profile data
 70           * 
 71           * @property profile
 72           * @type object
 73           * @default {}
 74           */
 75          profile: {}
 76       },
 77 
 78       /**
 79        * FileUpload module instance.
 80        * 
 81        * @property fileUpload
 82        * @type Alfresco.module.FileUpload
 83        */
 84       fileUpload: null,
 85 
 86       /**
 87        * Fired by YUI when parent element is available for scripting.
 88        * Component initialisation, including instantiation of YUI widgets and event listener binding.
 89        *
 90        * @method onReady
 91        */
 92       onReady: function UP_onReady()
 93       {
 94          // Allow edit if profile is editable
 95          if (this.options.profile.isEditable)
 96          {
 97             // Buttons
 98             this.widgets.upload = Alfresco.util.createYUIButton(this, "button-upload", this.onUpload);
 99             this.widgets.clearphoto = Alfresco.util.createYUIButton(this, "button-clearphoto", this.onClearPhoto);
100             this.widgets.edit = Alfresco.util.createYUIButton(this, "button-edit", this.onEditProfile);
101             this.widgets.save = Alfresco.util.createYUIButton(this, "button-save", null,
102                {
103                   type: "submit"
104                });
105             this.widgets.cancel = Alfresco.util.createYUIButton(this, "button-cancel", this.onCancel);
106             
107             // Form definition
108             var form = new Alfresco.forms.Form(this.id + "-form");
109             this.widgets.form = form;
110             form.setSubmitElements(this.widgets.save);
111             form.setShowSubmitStateDynamically(true);
112             form.setSubmitAsJSON(true);
113             form.setAJAXSubmit(true,
114             {
115                successCallback:
116                {
117                   fn: this.onSuccess,
118                   scope: this
119                }
120             });
121             
122             // Form field validation
123             form.addValidation(this.id + "-input-firstName", Alfresco.forms.validation.mandatory, null, "keyup");
124             
125             // Initialise the form
126             form.init();
127          }
128          
129          // If the profile is editable and the link includes a request to edit it, then reveal the edit form...
130          if (this.options.profile.isEditable && window.location.hash == "#edit")
131          {
132             this.onEditProfile();
133          }
134          else
135          {
136             // Finally show the main component body here to prevent UI artifacts on YUI button decoration
137             Dom.removeClass(this.id + "-readview", "hidden");
138          }
139       },
140       
141       /**
142        * Edit Profile button click handler
143        * 
144        * @method onEditProfile
145        * @param e {object} DomEvent
146        * @param p_obj {object} Object passed back from addListener method
147        */
148       onEditProfile: function UP_onEditProfile(e, p_obj)
149       {
150          // Hide view panel
151          Dom.addClass(this.id + "-readview", "hidden");
152 
153          // Reset form data
154          var p = this.options.profile,
155             prefix = this.id + "-input-";
156          Dom.get(prefix + "lastName").value = p.lastName;
157          Dom.get(prefix + "firstName").value = p.firstName;
158          Dom.get(prefix + "jobtitle").value = p.jobtitle;
159          Dom.get(prefix + "location").value = p.location;
160          Dom.get(prefix + "bio").value = p.bio;
161          Dom.get(prefix + "telephone").value = p.telephone;
162          Dom.get(prefix + "mobile").value = p.mobile;
163          Dom.get(prefix + "email").value = p.email;
164          Dom.get(prefix + "skype").value = p.skype;
165          Dom.get(prefix + "instantmsg").value = p.instantmsg;
166          Dom.get(prefix + "googleusername").value = p.googleusername;
167          Dom.get(prefix + "organization").value = p.organization;
168          Dom.get(prefix + "companyaddress1").value = p.companyaddress1;
169          Dom.get(prefix + "companyaddress2").value = p.companyaddress2;
170          Dom.get(prefix + "companyaddress3").value = p.companyaddress3;
171          Dom.get(prefix + "companypostcode").value = p.companypostcode;
172          Dom.get(prefix + "companytelephone").value = p.companytelephone;
173          Dom.get(prefix + "companyfax").value = p.companyfax;
174          Dom.get(prefix + "companyemail").value = p.companyemail;
175          
176          this.widgets.form.updateSubmitElements();
177          
178          // Show edit panel
179          Dom.removeClass(this.id + "-editview", "hidden");
180       },
181 
182 
183       /**
184        * YUI WIDGET EVENT HANDLERS
185        * Handlers for standard events fired from YUI widgets, e.g. "click"
186        */
187       
188       /**
189        * Upload button click handler
190        *
191        * @method onUpload
192        * @param e {object} DomEvent
193        * @param p_obj {object} Object passed back from addListener method
194        */
195       onUpload: function UP_onUpload(e, p_obj)
196       {
197          if (this.fileUpload === null)
198          {
199             this.fileUpload = Alfresco.getFileUploadInstance();
200          }
201          
202          // Show uploader for single file select - override the upload URL to use avatar upload service
203          var uploadConfig =
204          {
205             flashUploadURL: "slingshot/profile/uploadavatar",
206             htmlUploadURL: "slingshot/profile/uploadavatar.html",
207             username: this.options.userId,
208             mode: this.fileUpload.MODE_SINGLE_UPLOAD,
209             onFileUploadComplete:
210             {
211                fn: this.onFileUploadComplete,
212                scope: this
213             }
214          };
215          this.fileUpload.show(uploadConfig);
216          Event.preventDefault(e);
217       },
218       
219       /**
220        * Clear photo button click handler
221        *
222        * @method onClearPhoto
223        * @param e {object} DomEvent
224        * @param p_obj {object} Object passed back from addListener method
225        */
226       onClearPhoto: function UP_onClearPhoto(e, p_obj)
227       {
228          Alfresco.util.Ajax.request(
229          {
230             url: Alfresco.constants.PROXY_URI + "slingshot/profile/resetavatar/" + encodeURIComponent(this.options.userId),
231             method: Alfresco.util.Ajax.PUT,
232             requestContentType: Alfresco.util.Ajax.JSON,
233             successCallback:
234             {
235                fn: function(res)
236                {
237                   // replace all avatar image URLs with the updated one
238                   var photos = Dom.getElementsByClassName("photoimg", "img");
239                   for (i in photos)
240                   {
241                      photos[i].src = Alfresco.constants.URL_RESCONTEXT + "components/images/no-user-photo-64.png";
242                   }
243                },
244                scope: this
245             }
246          });
247       },
248       
249       /**
250        * File Upload complete event handler
251        *
252        * @method onFileUploadComplete
253        * @param complete {object} Object literal containing details of successful and failed uploads
254        */
255       onFileUploadComplete: function UP_onFileUploadComplete(complete)
256       {
257          var success = complete.successful.length;
258          if (success > 0)
259          {
260             var noderef = complete.successful[0].nodeRef;
261             
262             // replace all avatar image URLs with the updated one
263             var photos = Dom.getElementsByClassName("photoimg", "img");
264             for (i in photos)
265             {
266                photos[i].src = Alfresco.constants.PROXY_URI + "api/node/" + noderef.replace("://", "/") +
267                                "/content/thumbnails/avatar?c=force";
268             }
269             
270             // call to update the user object - photo changes take effect immediately!
271             var json = {};
272             json[this.id + "-photoref"] = noderef;
273             var config =
274             {
275                method: "POST",
276                url: Dom.get(this.id + "-form").attributes.action.nodeValue,
277                dataObj: json
278             };
279             Alfresco.util.Ajax.jsonRequest(config);
280          }
281       },
282       
283       /**
284        * Save Changes form submit success handler
285        *
286        * @method onSuccess
287        * @param response {object} Server response object
288        */
289       onSuccess: function UP_onSuccess(response)
290       {
291          if (response)
292          {
293             // succesfully updated details - refresh the page with the new user details
294             if (window.location.hash == "#edit")
295             {
296                // If the location has the #edit hash then we need to remove it so that we
297                // return to the read view...
298                window.location = window.location.href.replace( /#.*/, "");
299             }
300             else
301             {
302                location.reload(true);
303             }
304             
305          }
306          else
307          {
308             Alfresco.util.PopupManager.displayPrompt(
309             {
310                text: Alfresco.util.message("message.failure", this.name)
311             });
312          }
313       },
314       
315       /**
316        * Cancel Changes button click handler
317        *
318        * @method onCancel
319        * @param e {object} DomEvent
320        * @param p_obj {object} Object passed back from addListener method
321        */
322       onCancel: function UP_onCancel(e, p_obj)
323       {
324          Dom.addClass(this.id + "-editview", "hidden");
325          Dom.removeClass(this.id + "-readview", "hidden");
326       }
327 
328    });
329 })();