summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--idrop-lite/src/main/java/org/irods/jargon/idrop/lite/Version.java4
-rw-r--r--idrop-web/application.properties3
-rw-r--r--idrop-web/grails-app/conf/BuildConfig.groovy11
-rw-r--r--idrop-web/grails-app/conf/Config.groovy4
-rw-r--r--idrop-web/grails-app/conf/spring/resources.groovy4
-rw-r--r--idrop-web/grails-app/controllers/org/irods/mydrop/controller/ProfileController.groovy146
-rw-r--r--idrop-web/grails-app/i18n/messages.properties11
-rw-r--r--idrop-web/grails-app/services/org/irods/mydrop/service/ProfileService.groovy73
-rw-r--r--idrop-web/grails-app/views/browse/_browseTabContent.gsp51
-rw-r--r--idrop-web/grails-app/views/common/_topToolbar.gsp40
-rw-r--r--idrop-web/grails-app/views/common/_topbar.gsp3
-rw-r--r--idrop-web/grails-app/views/home/index.gsp93
-rw-r--r--idrop-web/grails-app/views/layouts/main.gsp185
-rw-r--r--idrop-web/grails-app/views/profile/_profileTabContent.gsp19
-rw-r--r--idrop-web/grails-app/views/profile/_profileToolbar.gsp30
-rw-r--r--idrop-web/grails-app/views/profile/changePasswordDialog.gsp37
-rw-r--r--idrop-web/grails-app/views/profile/profileData.gsp28
-rw-r--r--idrop-web/idrop-web-config.groovy5
-rw-r--r--idrop-web/release_notes.txt36
-rw-r--r--idrop-web/test/unit/org/irods/mydrop/controller/ProfileControllerTests.groovy19
-rw-r--r--idrop-web/test/unit/org/irods/mydrop/service/ProfileServiceTests.groovy19
-rw-r--r--idrop-web/web-app/css/main.css4
-rw-r--r--idrop-web/web-app/js/bundles/messages.properties5
-rw-r--r--idrop-web/web-app/js/mydrop/profile.js101
24 files changed, 677 insertions, 254 deletions
diff --git a/idrop-lite/src/main/java/org/irods/jargon/idrop/lite/Version.java b/idrop-lite/src/main/java/org/irods/jargon/idrop/lite/Version.java
index 8fd48d3..d118c07 100644
--- a/idrop-lite/src/main/java/org/irods/jargon/idrop/lite/Version.java
+++ b/idrop-lite/src/main/java/org/irods/jargon/idrop/lite/Version.java
@@ -1,4 +1,8 @@
package org.irods.jargon.idrop.lite;
public final class Version {
+<<<<<<< HEAD
public static String VERSION="20120828-1415";
+=======
+ public static String VERSION="20120828-1442";
+>>>>>>> development
}
diff --git a/idrop-web/application.properties b/idrop-web/application.properties
index 7405b59..32f474a 100644
--- a/idrop-web/application.properties
+++ b/idrop-web/application.properties
@@ -1,5 +1,3 @@
-#Grails Metadata file
-#Thu Aug 23 07:32:11 EDT 2012
app.grails.version=2.0.4
app.name=idrop-web
app.servlet.version=2.5
@@ -7,3 +5,4 @@ app.version=1.0.1
plugins.hibernate=2.0.4
plugins.logging=0.1
plugins.tomcat=2.0.4
+
diff --git a/idrop-web/grails-app/conf/BuildConfig.groovy b/idrop-web/grails-app/conf/BuildConfig.groovy
index 259d4c5..4b60200 100644
--- a/idrop-web/grails-app/conf/BuildConfig.groovy
+++ b/idrop-web/grails-app/conf/BuildConfig.groovy
@@ -29,11 +29,12 @@ grails.project.dependency.resolution = {
test 'org.mockito:mockito-all:1.8.1'
compile 'commons-io:commons-io:2.1'
provided 'junit:junit:4.8.1'
- compile 'org.irods.jargon:jargon-core:3.1.4'
- compile 'org.irods.jargon:jargon-security:3.1.3'
- compile 'org.irods.jargon:jargon-data-utils:3.1.4'
- compile 'org.irods.jargon:jargon-ticket:3.1.4'
- compile ('org.irods.jargon:jargon-user-tagging:3.1.4') { exclude 'junit' }
+ compile 'org.irods.jargon:jargon-core:3.2.0-SNAPSHOT'
+ compile 'org.irods.jargon:jargon-security:3.2.0-SNAPSHOT'
+ compile 'org.irods.jargon:jargon-data-utils:3.2.0-SNAPSHOT'
+ compile 'org.irods.jargon:jargon-ticket:3.2.0-SNAPSHOT'
+ compile 'org.irods.jargon:jargon-user-profile:3.2.0-SNAPSHOT'
+ compile ('org.irods.jargon:jargon-user-tagging:3.2.0-SNAPSHOT') { exclude 'junit' }
compile 'org.springframework.security:spring-security-core:3.0.5.RELEASE'
compile 'org.springframework.security:spring-security-web:3.0.5.RELEASE'
compile 'org.springframework.security:spring-security-config:3.0.5.RELEASE'
diff --git a/idrop-web/grails-app/conf/Config.groovy b/idrop-web/grails-app/conf/Config.groovy
index b9bbefa..5f306a6 100644
--- a/idrop-web/grails-app/conf/Config.groovy
+++ b/idrop-web/grails-app/conf/Config.groovy
@@ -18,7 +18,7 @@ environments {
/*production { grails.serverURL = "http://lifetime-library.ils.unc.edu/${appName}" }
production { grails.serverURL = "http://iren-web.renci.org:8080/${appName}" }
production { grails.serverURL = "http://srbbrick15.ucsd.edu:1525//${appName}" }
- production { grails.serverURL = "http://www.irods.org" } */
+ production { grails.serverURL = "http://www.irods.org" } */2
production { grails.serverURL = "http://edit.your.server.info.in.your.etc.file.or.update.the.groovy.config" }
development { grails.serverURL = "http://localhost:8080/${appName}" }
test { grails.serverURL = "http://localhost:8080/${appName}" }
@@ -34,6 +34,7 @@ environments {
idrop.config.preset.resource="lifelibResc1"
*/
+
/*
* 3) iDROP web includes the idrop-lite Java applet, which is launched from the iDROP web interface. The interface needs to know where to find this jar file.
* The Jar file should be placed on a web server in an accessible directory, and configured below
@@ -70,6 +71,7 @@ idrop.config.idrop.jnlp="http://iren-web.renci.org/idrop-release/idrop.jnlp"
// do I support tickets? This determies whether the ticket feature is available via the interface, it also requires ticket support in iRODS itself (version 3.1+)
idrop.config.use.tickets=true
idrop.config.max.thumbnail.size.mb=20
+idrop.config.use.userprofile=false
/*
* Some properties may be set in an external configuration file, as configured below
diff --git a/idrop-web/grails-app/conf/spring/resources.groovy b/idrop-web/grails-app/conf/spring/resources.groovy
index 2f5f391..a6561c1 100644
--- a/idrop-web/grails-app/conf/spring/resources.groovy
+++ b/idrop-web/grails-app/conf/spring/resources.groovy
@@ -1,6 +1,8 @@
// Place your Spring DSL code here
beans = {
+ profileService(org.irods.mydrop.service.ProfileService) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") }
+
browseController(org.irods.mydrop.controller.BrowseController) {
irodsAccessObjectFactory = ref("irodsAccessObjectFactory")
taggingServiceFactory = ref("taggingServiceFactory")
@@ -35,5 +37,7 @@ beans = {
auditController(org.irods.mydrop.controller.AuditController) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") }
+ profileController(org.irods.mydrop.controller.ProfileController) { irodsAccessObjectFactory = ref("irodsAccessObjectFactory") }
+
}
diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/ProfileController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/ProfileController.groovy
new file mode 100644
index 0000000..38b7a2b
--- /dev/null
+++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/ProfileController.groovy
@@ -0,0 +1,146 @@
+package org.irods.mydrop.controller
+
+import org.irods.jargon.core.connection.IRODSAccount
+import org.irods.jargon.core.pub.IRODSAccessObjectFactory
+import org.irods.jargon.core.pub.UserAO
+import org.irods.jargon.userprofile.UserProfile
+import org.irods.mydrop.service.ProfileService
+import org.jsoup.Jsoup
+import org.jsoup.safety.Whitelist
+
+class ProfileController {
+ IRODSAccessObjectFactory irodsAccessObjectFactory
+ IRODSAccount irodsAccount
+ ProfileService profileService
+ def grailsApplication
+
+ /**
+ * Interceptor grabs IRODSAccount from the SecurityContextHolder
+ */
+ def beforeInterceptor = [action:this.&auth]
+
+ def auth() {
+ if(!session["SPRING_SECURITY_CONTEXT"]) {
+ redirect(controller:"login", action:"login")
+ return false
+ }
+ irodsAccount = session["SPRING_SECURITY_CONTEXT"]
+ }
+
+ def afterInterceptor = {
+ log.debug("closing the session")
+ irodsAccessObjectFactory.closeSession()
+ }
+
+ /**
+ * Initial listing of profile data, this will create a profile if none exists
+ * @return
+ */
+ def index() {
+ log.info "index()"
+ try {
+ UserProfile userProfile = profileService.retrieveProfile(irodsAccount)
+ render(view:"profileData", model:[userProfile:userProfile])
+ } catch (Exception e) {
+ response.sendError(500,e.message)
+ }
+ }
+
+ /**
+ * Update the profile
+ * @return
+ */
+ def updateProfile() {
+
+ log.info("updateProfile")
+
+ /*
+ * Massage the params into the user profile
+ */
+
+ UserProfile userProfile = profileService.retrieveProfile(irodsAccount)
+
+ if (params['nickName'] == null) {
+ def message = message(code:"default.null.message", args: ['nickName', 'parms'])
+ response.sendError(500,message)
+ }
+
+ def nickName = Jsoup.clean(params['nickName'], Whitelist.basic())
+
+ if ( params['description'] == null) {
+ def message = message(code:"default.null.message", args: ['description', 'parms'])
+ response.sendError(500,message)
+ }
+ def description = Jsoup.clean(params['description'], Whitelist.basic())
+
+ if (params['email'] == null) {
+ def message = message(code:"default.null.message", args: ['email', 'parms'])
+ response.sendError(500,message)
+ }
+ def email = Jsoup.clean(params['email'], Whitelist.basic())
+
+ userProfile.userProfilePublicFields.nickName = nickName
+ userProfile.userProfilePublicFields.description = description
+ userProfile.userProfileProtectedFields.mail = email
+
+ log.info "updating profile...."
+ profileService.updateProfile(irodsAccount, userProfile)
+ log.info "updated"
+
+ render(view:"profileData", model:[userProfile:userProfile])
+
+ }
+
+ /**
+ * Show the password change dialog
+ * @return
+ */
+ def showPasswordChangeDialog() {
+ PasswordCommand cmd = new PasswordCommand()
+ render (view:"changePasswordDialog", model:[password:cmd])
+ }
+
+ /**
+ * process a password change
+ * @return
+ */
+ def changePassword(PasswordCommand cmd) {
+ log.info "changePassword()"
+ log.info "cmd: ${cmd}"
+
+ /**
+ * If there is an error send back the view for redisplay with error messages
+ */
+ if (!cmd.validate()) {
+ log.info("errors in page, returning with error info:${cmd}")
+ flash.error = message(code:"error.data.error")
+ render (view:"changePasswordDialog", model:[password:cmd])
+ return
+ }
+
+ log.info("edits pass")
+
+ UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount)
+ userAO.changeAUserPasswordByThatUser(irodsAccount.userName, irodsAccount.password, cmd.password)
+ irodsAccount.password = cmd.password
+ log.info("password changed, fix account in session")
+ flash.message = message(code:"message.update.successful")
+ render (view:"changePasswordDialog", model:[password:cmd])
+
+ }
+}
+
+class PasswordCommand {
+
+ String password
+ String confirmPassword
+
+ static constraints = {
+ password(blank:false)
+ confirmPassword validator: {
+ val, obj ->
+ if (!val) return ['error.confirm.password.missing']
+ if (val != obj.password) return['error.passwords.dont.match']
+ }
+ }
+}
diff --git a/idrop-web/grails-app/i18n/messages.properties b/idrop-web/grails-app/i18n/messages.properties
index 70eb3a3..a7472e7 100644
--- a/idrop-web/grails-app/i18n/messages.properties
+++ b/idrop-web/grails-app/i18n/messages.properties
@@ -12,8 +12,11 @@ text.browse=Browse
text.bulk.action=Bulk Action
text.bulk.upload=Bulk Upload
text.cancel=Cancel
+text.changePassword=Change Password
+text.change.password.header=Enter new password and enter again to confirm, then press Update
text.check.out=Check Out Cart
text.create.ticket=Create Ticket
+text.confirm.password=Confirm Password
text.content=Content
text.delete.all=Delete all selected items
text.delete.metadata=Delete Metadata
@@ -21,6 +24,7 @@ text.description=Description
text.display.option=Display Option
text.download=Download
text.edit=Edit
+text.email=Email
text.file=File
text.forward=Page Forward
text.find.path.in.tree=Open the path in the tree
@@ -40,7 +44,10 @@ text.new.folder=New Folder
text.path=Path
text.password=Password
text.permissions=Permissions
+text.personal.blurb=Personal Blurb
text.port=Port
+text.profile=Profile
+text.profile.header=Profile - Manage personal profile information and settings
text.quick.transfers=Quick Transfer
text.refresh=Refresh
text.rename=Rename
@@ -77,9 +84,11 @@ text.tags=Tags
text.timestamp=Timestamp
text.type=Type
text.unit=Unit
+text.update=Update
text.upload=Upload
text.upload.and.download=Upload and Download
text.user=User Name
+text.nickname=Nick Name
text.value=Value
text.view=View
text.zone=Zone
@@ -104,6 +113,7 @@ heading.upload.ticket.collection=Select a local file to upload to the ticket col
browse.page.prompt=Select a directory or file to see info and tags based on the view option
# messages
+error.confirm.password.missing=Confirmation password is null or blank
error.nothing.selected=Nothing was selected for the action
error.no.audit.access=This user does not have permission to view audit data
error.no.data.found=No data found
@@ -119,6 +129,7 @@ error.duplicate.acl=User already has an ACL
error.duplicate.file=File already exists
error.duplicate.metadata=Metadata entry already exists
error.no.resource=No resource name provided
+error.passwords.dont.match=Confirm password not equal to password
error.rename.to.self=File cannot be renamed to same name, ignored
error.invalid.acl=Invalid ACL value {0}
error.use.bulk.upload=File is too large for HTTP upload, select bulk upload from the upload menu, or use iDrop Desktop from right hand panel
diff --git a/idrop-web/grails-app/services/org/irods/mydrop/service/ProfileService.groovy b/idrop-web/grails-app/services/org/irods/mydrop/service/ProfileService.groovy
new file mode 100644
index 0000000..0892289
--- /dev/null
+++ b/idrop-web/grails-app/services/org/irods/mydrop/service/ProfileService.groovy
@@ -0,0 +1,73 @@
+package org.irods.mydrop.service
+
+import org.irods.jargon.core.connection.IRODSAccount
+import org.irods.jargon.core.exception.DataNotFoundException
+import org.irods.jargon.core.pub.IRODSAccessObjectFactory
+import org.irods.jargon.userprofile.*
+
+class ProfileService {
+ static transactional = false
+ IRODSAccessObjectFactory irodsAccessObjectFactory
+
+ /**
+ * Given an irods account, retrieve the existing user profile, or create a skeleton and return this new skeleton profile
+ * @param irodsAccount
+ * @return
+ */
+ UserProfile retrieveProfile(IRODSAccount irodsAccount) {
+ log.info "retrieveProfile()"
+ if (irodsAccount == null) {
+ throw new IllegalArgumentException("null profile")
+ }
+
+ UserProfileService userProfileService = new UserProfileServiceImpl(irodsAccessObjectFactory, irodsAccount)
+ log.info("attempting to retrieve profile for ${irodsAccount}")
+
+ UserProfile userProfile
+ try {
+ userProfile = userProfileService.retrieveUserProfile(irodsAccount.userName)
+ } catch (DataNotFoundException dnf) {
+ log.info("no profile found, go ahead and create a basic one")
+ userProfile = addSkeletonUserProfile(irodsAccount, userProfileService)
+ }
+
+ log.info("user profile ${userProfile}")
+ return userProfile
+ }
+
+ private UserProfile addSkeletonUserProfile(IRODSAccount irodsAccount, UserProfileService userProfileService) {
+ UserProfile userProfile = new UserProfile()
+ userProfile.userName = irodsAccount.userName
+ userProfile.zone = irodsAccount.zone
+ userProfileService.addProfileForUser(irodsAccount.userName, userProfile)
+ return userProfile
+ }
+
+ /**
+ * Given the user profile information, update the users profile and then return the new state
+ * @param irodsAccount
+ * @param userProfile
+ * @return
+ */
+ UserProfile updateProfile(IRODSAccount irodsAccount, UserProfile userProfile) {
+ log.info "updateProfile"
+
+ if (irodsAccount == null) {
+ throw new IllegalArgumentException("null profile")
+ }
+
+ if (userProfile == null) {
+ throw new IllegalArgumentException("null userProfile")
+ }
+
+ UserProfileService userProfileService = new UserProfileServiceImpl(irodsAccessObjectFactory, irodsAccount)
+ log.info("attempting to update profile for ${irodsAccount}")
+ log.info("desired profile information: ${userProfile}")
+
+ userProfileService.updateUserProfile(userProfile)
+ log.info "updated...now retrieve and display"
+ UserProfile updatedProfile = userProfileService.retrieveUserProfile(irodsAccount.userName)
+ log.info("updated profile: ${updatedProfile}")
+ return updatedProfile
+ }
+}
diff --git a/idrop-web/grails-app/views/browse/_browseTabContent.gsp b/idrop-web/grails-app/views/browse/_browseTabContent.gsp
new file mode 100644
index 0000000..37669f3
--- /dev/null
+++ b/idrop-web/grails-app/views/browse/_browseTabContent.gsp
@@ -0,0 +1,51 @@
+ <div id="browseToolbar" style="display:block; width:100%;position:relative;">
+
+ <div id="infoDivPathArea"
+ style="overflow: hidden; display:block; margin: 3px; font-size: 120%;position:relative;">
+ <!-- area for the path crumb-trails -->
+ </div>
+
+ </div> <!-- browseToolbar -->
+ <div id="browseMenuDiv" style="display:block; width:100%;position:relative;">
+ <g:render template="/common/topToolbar" />
+ </div>
+
+ <div id="browser" class="wrapper" style="height:85%;width:100%;clear:both;">
+ <div id="dataTreeView" style="width: 100%; height: 700px; overflow: hidden;">
+
+ <div id="dataTreeDivWrapper" class="ui-layout-west" style="width: 25%; height: 100%; position:relative;">
+ <div id="dataTreeToolbar" style="width:100%; height:3%;display:block;" class="fg-toolbar">
+
+ <div id="dataTreeMenu" class="fg-buttonset fg-buttonset-multi"
+ style="float: left; clear : both; display:block; overflow:hidden;">
+ <button type="button" id="refreshTreeButton"
+ class="ui-state-default ui-corner-left" value="refreshTreeButton"
+ onclick="refreshTree()")>
+ <g:img dir="images" file="arrow-refresh.png" width="16" height="16"/>
+ </button>
+ <button type="button" id="homeTreeButton"
+ class="ui-state-default" value="homeTreeButton"
+ onclick="setTreeToUserHome()")>
+ <g:img dir="images" file="go-home-4.png" width="16" height="16"/>
+ </button>
+ <button type="button" id="rootTreeButton"
+ class="ui-state-default ui-corner-right" value="rootTreeButton"
+ onclick="setTreeToRoot()")>
+ <g:img dir="images" file="go-parent-folder.png" width="16" height="16"/>
+ </button>
+ </div> <!-- dataTreeMenu -->
+
+ </div> <!-- dataTreeToolbar -->
+
+ <div id="dataTreeDiv" class="clearfix" style="height:95%; width:100%; overflow:auto;"><!-- no empty div --></div>
+ </div> <!-- dataTreeDivWrapper -->
+
+ <div id="infoDivOuter" style="display: block; width: 75%; height: 100%; position: relative; overflow: auto;"
+ class="ui-layout-center">
+
+ <div id="infoDiv" style=""><h2><g:message code="browse.page.prompt" /></h2>
+ </div> <!-- infoDiv -->
+
+ </div> <!-- infoDivOuter -->
+ </div> <!-- data tree view -->
+ </div> <!-- browser -->
diff --git a/idrop-web/grails-app/views/common/_topToolbar.gsp b/idrop-web/grails-app/views/common/_topToolbar.gsp
index fb9933c..bf69c9d 100644
--- a/idrop-web/grails-app/views/common/_topToolbar.gsp
+++ b/idrop-web/grails-app/views/common/_topToolbar.gsp
@@ -77,7 +77,6 @@
code="text.add.to.cart" /></a></li>
-
</ul></li>
<li id="menuBulkActionDetails" class="detailsToolbarMenuItem"><a href="#applyActionToAllDetails"><g:message code="text.apply.to.all"/></a>
@@ -88,23 +87,6 @@
</ul>
</li>
- <!--
- <g:if test="${grailsApplication.config.idrop.config.use.tickets==true}">
- <li id="menuTicketDetails" class="detailsToolbarMenuItem"><a
- href="#ticketsMenu"><g:message
- code="text.tickets" /></a>
- <ul>
-
- <li id="menuCreateAndEmailATicketDetails"><a href="#menuCreateAndEmailATicketDetails"
- onclick="createAndEmailATicketViaBrowseDetailsToolbar()"><g:message
- code="text.ticket.email" /></a></li>
- <li id="menuUseATicket"><a href="#menuUseATicket"
- onclick="useATicketViaBrowseDetailsToolbar()"><g:message
- code="text.ticket.use" /></a></li>
-
- </ul></li>
- </g:if>-->
-
<!-- info toolbar -->
@@ -126,26 +108,7 @@
</ul></li>
- <!--
- <g:if test="${grailsApplication.config.idrop.config.use.tickets==true}">
- <li id="menuTicket" class="toolbarMenuItem"><a
- href="#ticketsMenu"><g:message
- code="text.tickets" /></a>
- <ul>
-
- <li id="menuCreateAndEmailATicket"><a href="#menuCreateAndEmailATicket"
- onclick="createAndEmailATicketToolbar()"><g:message
- code="text.ticket.email" /></a></li>
- <li id="menuUseATicket"><a href="#menuUseATicket"
- onclick="useATicket()"><g:message
- code="text.ticket.use" /></a></li>
-
- </ul></li>
- </g:if>-->
-
-
-
- </ul>
+ </ul>
</div>
@@ -180,7 +143,6 @@
showAuditView(selectedPath);
}
-
/**
* browse view selected
diff --git a/idrop-web/grails-app/views/common/_topbar.gsp b/idrop-web/grails-app/views/common/_topbar.gsp
index 0818efa..ce1c402 100644
--- a/idrop-web/grails-app/views/common/_topbar.gsp
+++ b/idrop-web/grails-app/views/common/_topbar.gsp
@@ -1,6 +1,3 @@
-<!-- <div id="bannercontainer"> -->
- <!-- image banner -->
-<!-- </div> -->
<g:ifAuthenticated>
<div id="headerSearchBox" class="box">
diff --git a/idrop-web/grails-app/views/home/index.gsp b/idrop-web/grails-app/views/home/index.gsp
index 83b212d..0af5f0c 100644
--- a/idrop-web/grails-app/views/home/index.gsp
+++ b/idrop-web/grails-app/views/home/index.gsp
@@ -3,85 +3,26 @@
<g:javascript library="mydrop/home" />
<g:javascript library="mydrop/search" />
<g:javascript library="mydrop/metadata" />
+<g:javascript library="mydrop/profile" />
</head>
-<div id="tabs" class="wrapper"
- style="height: 820px; position: relative; overflow:hidden;">
+<div id="tabs" class="wrapper clearfix"
+ style="height: 820px; overflow:hidden;">
<ul>
<li><a href="#browseTab"><g:message code="text.browse" /> </a></li>
- <!-- <li><a href="#quickView"><g:message code="text.home" />
- </a>
- </li> -->
<li><a href="#searchTab"><g:message code="text.search" /> </a></li>
+ <g:if test="${grailsApplication.config.idrop.config.use.userprofile==true}">
+ <li><a href="#profileTab"><g:message code="text.profile" /> </a></li>
+ </g:if>
</ul>
-
-
- <div id="browseTab" style="padding:0;">
-
- <div id="browser" class="wrapper">
-
- <div id="browseToolbar">
-
- <span id="infoDivPathArea"
- style="overflow: hidden; position: relative; display: inline-block; margin: 3px; font-size: 120%;">
- <!-- area for the path crumb-trails -->
- </span>
- </div>
- <div id="browseMenuDiv">
- <g:render template="/common/topToolbar" />
- </div>
-
- <div id="dataTreeView"
- style="width: 100%; height: 700px; overflow: hidden;">
-
- <div id="dataTreeDivWrapper" class="ui-layout-west"
- style="width: 25%; height: 100%; position:relative;">
- <div id="dataTreeToolbar" style="width:100%; height:3%;display:block; position:relative;" class="fg-toolbar">
- <div id="dataTreeMenu" class="fg-buttonset fg-buttonset-multi"
- style="float: left, clear : both; display:block; overflow:hidden;">
- <button type="button" id="refreshTreeButton"
- class="ui-state-default ui-corner-left" value="refreshTreeButton"
- onclick="refreshTree()")>
- <!--<g:message code="text.refresh" />-->
- <g:img dir="images" file="arrow-refresh.png" width="16" height="16"/>
- </button>
- <button type="button" id="homeTreeButton"
- class="ui-state-default" value="homeTreeButton"
- onclick="setTreeToUserHome()")>
- <!--<g:message code="text.refresh" />-->
- <g:img dir="images" file="go-home-4.png" width="16" height="16"/>
- </button>
- <button type="button" id="rootTreeButton"
- class="ui-state-default ui-corner-right" value="rootTreeButton"
- onclick="setTreeToRoot()")>
- <!--<g:message code="text.refresh" />-->
- <g:img dir="images" file="go-parent-folder.png" width="16" height="16"/>
- </button>
- </div>
- </div>
- <div id="dataTreeDiv" style="width:auto; height:95%; overflow:visible;">
- </div>
- </div>
- <div id="infoDivOuter"
- style="display: block; width: 75%; height: 100%; position: relative; overflow: auto;"
- class="ui-layout-center">
-
- <div id="infoDiv" style="overflow: visible; position: relative;">
- <h2>
- <g:message code="browse.page.prompt" />
- </h2>
- </div>
- </div>
- </div>
- </div>
- </div>
+ <div id="browseTab" style="height:100%;">
+ <g:render template="/browse/browseTabContent" />
+ </div><!-- browse tab -->
-
<div id="searchTab">
-
<div id="searchDivOuter"
style="display: block; width: 95%; height: 90%; position: relative; overflow: hidden;"
class="ui-layout-center">
@@ -91,12 +32,18 @@
<h2>
<g:message code="heading.no.search.yet" />
</h2>
- <!-- search table display div -->
- </div>
- </div>
- </div>
+ </div> <!-- searchTableDiv -->
+ </div> <!-- searchDivOuter -->
+ </div> <!-- search tab -->
+
+ <g:if test="${grailsApplication.config.idrop.config.use.userprofile==true}">
+ <div id="profileTab" style="height:100%;overflow:hidden;">
+ <g:render template="/profile/profileTabContent" />
+ </div><!-- profile tab -->
+ </g:if>
+
-</div>
+</div> <!-- tabs -->
<script type="text/javascript">
var dataLayout;
var tabs;
diff --git a/idrop-web/grails-app/views/layouts/main.gsp b/idrop-web/grails-app/views/layouts/main.gsp
index 21892ca..2da8db6 100644
--- a/idrop-web/grails-app/views/layouts/main.gsp
+++ b/idrop-web/grails-app/views/layouts/main.gsp
@@ -1,112 +1,109 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 //EN">
<html>
-<head>
-<title><g:layoutTitle default="iDrop-web - iRODS Cloud Browser" /></title>
-<link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'base.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'style.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'jqcloud.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'layout-default-latest.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'jquery.fileupload-ui.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'superfish.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'jquery.gritter.css')}" />
-<link rel="stylesheet"
- href="${resource(dir:'css',file:'reset-fonts-grids.css')}" />
-<link rel="stylesheet" href="${resource(dir:'css',file:'start/jquery-ui-1.8.18.custom.css')}" />
+ <head>
+ <title><g:layoutTitle default="iDrop-web - iRODS Cloud Browser" /></title>
+ <link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'base.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'style.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'jqcloud.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'layout-default-latest.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'jquery.fileupload-ui.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'superfish.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'jquery.gritter.css')}" />
+ <link rel="stylesheet"
+ href="${resource(dir:'css',file:'reset-fonts-grids.css')}" />
+ <link rel="stylesheet" href="${resource(dir:'css',file:'start/jquery-ui-1.8.18.custom.css')}" />
-<link rel="shortcut icon"
- href="${resource(dir:'images',file:'favicon.ico')}" type="image/x-icon" />
-<g:layoutHead />
-<g:javascript library="jquery-1.7.2.min" />
-<g:javascript library="jquery-ui-1.8.7.custom.min" />
- <g:javascript library="jquery.hotkeys" />
- <g:javascript library="jquery.jstree" />
-<g:javascript library="jquery.jeditable.mini" />
-<g:javascript library="jquery.dataTables.min" />
-<g:javascript library="mydrop/ticket" />
-<g:javascript library="jquery.i18n.properties-min-1.0.9" />
-<g:javascript library="jqcloud-0.1.6" />
-<g:javascript library="jquery.fileupload-ui" />
-<g:javascript library="jquery.fileupload" />
-<g:javascript library="jquery.media" />
-<g:javascript library="mydrop/lingo_common" />
-<g:javascript library="mydrop/main" />
-<g:javascript library="jquery-ui-13" />
-<g:javascript library="jquery.blockUI" />
-<g:javascript library="jquery.ba-bbq.min" />
-<g:javascript library="jquery.layout-latest.min" />
-<g:javascript library="jquery-ui-13" />
-<g:javascript library="jquery.tools.min" />
-<g:javascript library="mydrop/shopping_cart" />
-<g:javascript library="mydrop/user" />
-<g:javascript library="galleria-1.2.6" />
-<g:javascript library="jquery.gritter.min" />
-<g:javascript library="jquery.opacityrollover" />
-<g:javascript library="superfish" />
-<!-- preserve the application context as a js variable for use in AJAX callbacks -->
-<script type="text/javascript">
- context = "${request.contextPath}";
- scheme = "${request.scheme}";
- host = "${request.localName}";
- port = "${request.localPort}";
+ <link rel="shortcut icon"
+ href="${resource(dir:'images',file:'favicon.ico')}" type="image/x-icon" />
+ <g:layoutHead />
+ <g:javascript library="jquery-1.7.2.min" />
+ <g:javascript library="jquery-ui-1.8.7.custom.min" />
+ <g:javascript library="jquery.hotkeys" />
+ <g:javascript library="jquery.jstree" />
+ <g:javascript library="jquery.jeditable.mini" />
+ <g:javascript library="jquery.dataTables.min" />
+ <g:javascript library="mydrop/ticket" />
+ <g:javascript library="jquery.i18n.properties-min-1.0.9" />
+ <g:javascript library="jqcloud-0.1.6" />
+ <g:javascript library="jquery.fileupload-ui" />
+ <g:javascript library="jquery.fileupload" />
+ <g:javascript library="jquery.media" />
+ <g:javascript library="mydrop/lingo_common" />
+ <g:javascript library="mydrop/main" />
+ <g:javascript library="jquery-ui-13" />
+ <g:javascript library="jquery.blockUI" />
+ <g:javascript library="jquery.ba-bbq.min" />
+ <g:javascript library="jquery.layout-latest.min" />
+ <g:javascript library="jquery-ui-13" />
+ <g:javascript library="jquery.tools.min" />
+ <g:javascript library="mydrop/shopping_cart" />
+ <g:javascript library="mydrop/user" />
+ <g:javascript library="galleria-1.2.6" />
+ <g:javascript library="jquery.gritter.min" />
+ <g:javascript library="jquery.opacityrollover" />
+ <g:javascript library="superfish" />
+ <!-- preserve the application context as a js variable for use in AJAX callbacks -->
+ <script type="text/javascript">
+ context = "${request.contextPath}";
+ scheme = "${request.scheme}";
+ host = "${request.localName}";
+ port = "${request.localPort}";
- $(function(){
- // Keep a mapping of url-to-container for caching purposes.
- var cache = {
- // If url is '' (no fragment), display this div's content.
- '': $('.bbq-default')
- };
+ $(function(){
+ // Keep a mapping of url-to-container for caching purposes.
+ var cache = {
+ // If url is '' (no fragment), display this div's content.
+ '': $('.bbq-default')
+ };
- // Bind an event to window.onhashchange that, when the history state changes,
- // gets the url from the hash and displays either our cached content or fetches
- // new content to be displayed.
- $(window).bind( 'hashchange', function(e) {
+ // Bind an event to window.onhashchange that, when the history state changes,
+ // gets the url from the hash and displays either our cached content or fetches
+ // new content to be displayed.
+ $(window).bind( 'hashchange', function(e) {
- processStateChange( $.bbq.getState());
+ processStateChange( $.bbq.getState());
- });
+ });
- jQuery.i18n.properties({
- name:'messages',
- path:'js/bundles/',
- mode:'both'
- });
+ jQuery.i18n.properties({
+ name:'messages',
+ path:'js/bundles/',
+ mode:'both'
+ });
- // Since the event is only triggered when the hash changes, we need to trigger
- // the event now, to handle the hash the page may have loaded with.
- // $(window).trigger( 'hashchange' );
- });
+ });
-</script>
+ </script>
</head>
<body style="height:100%;overflow:visible;">
-<div id="hd"><!-- PUT MASTHEAD CODE HERE -->
-<g:render template="/common/topbar"/>
-<g:render template="/common/messages"/>
-</div>
-<div id="bd" style="height:100%;">
-<div id="defaultDialogDiv"><!-- default for general jquery dialogs --></div>
-<div id="yui-main" style="height:100%;">
-<div class="yui-b" style="height:100%;">
-<div id="mainDiv" class="yui-ge" style="height:100%;">
-<div id="mainDivCol1" class="yui-u first" style="height:100%;"><!-- PUT MAIN COLUMN 1 CODE HERE -->
- <g:layoutBody />
-</div>
-<div id="secondaryDiv" class="yui-u" style="height:100%;"><!-- PUT MAIN COLUMN 2 CODE HERE -->
-<g:ifAuthenticated>
-<g:render template="/common/secondarymain"/>
-</g:ifAuthenticated>
+ <div id="hd"><!-- PUT MASTHEAD CODE HERE -->
+ <g:render template="/common/topbar"/>
+ <g:render template="/common/messages"/>
+ </div>
+ <div id="bd" style="height:100%;">
+ <div id="defaultDialogDiv"><!-- default for general jquery dialogs --></div>
+ <div id="yui-main" style="height:100%;">
+ <div class="yui-b" style="height:100%;">
+ <div id="mainDiv" class="yui-ge" style="height:100%;">
+ <div id="mainDivCol1" class="yui-u first" style="height:100%;"><!-- PUT MAIN COLUMN 1 CODE HERE -->
+ <g:layoutBody />
+ </div>
+ <div id="secondaryDiv" class="yui-u" style="height:100%;"><!-- PUT MAIN COLUMN 2 CODE HERE -->
+ <g:ifAuthenticated>
+ <g:render template="/common/secondarymain"/>
+ </g:ifAuthenticated>
-</div>
-</div>
-</div>
-</div>
+ </div>
+ </div>
+ </div>
+ </div>
-</div>
-<div id="ft"><!-- PUT FOOTER CODE HERE -->
-<g:render template="/common/footer" />
-</div>
+ </div>
+ <div id="ft"><!-- PUT FOOTER CODE HERE -->
+ <g:render template="/common/footer" />
+ </div>
</body>
</html> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/profile/_profileTabContent.gsp b/idrop-web/grails-app/views/profile/_profileTabContent.gsp
new file mode 100644
index 0000000..32d6fab
--- /dev/null
+++ b/idrop-web/grails-app/views/profile/_profileTabContent.gsp
@@ -0,0 +1,19 @@
+<div id="profileTabContent" class="clearfix" style="display:block;width:100%;height:98%;">
+ <h1><g:message code="text.profile.header"/></h1>
+ <div id="profileToolbar" style="display:block;">
+ <g:render template="/profile/profileToolbar" />
+ </div> <!-- profileToolbar -->
+ <div id="profileDialogArea"><!-- div for optional profile dialogs -->
+ </div>
+ <div id="profileDataArea" style="clear:both;">
+ <!-- area for profile data -->
+ </div>
+</div>
+<script>
+
+$(function() {
+ loadProfileData();
+});
+
+
+</script> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/profile/_profileToolbar.gsp b/idrop-web/grails-app/views/profile/_profileToolbar.gsp
new file mode 100644
index 0000000..154ae95
--- /dev/null
+++ b/idrop-web/grails-app/views/profile/_profileToolbar.gsp
@@ -0,0 +1,30 @@
+<div id="profileToolbar"
+ style="height: 100%; overflow: visible; margin-left: auto; margin-right: auto;">
+
+ <ul id="profileToolbarMenu" class="sf-menu">
+
+ <li id="menuProfileData" class="detailsToolbarMenuItem"><a
+ href="#view"><g:message code="text.view" /></a>
+ <ul>
+ <li id="menuRefresh"><a href="#refresh" onclick="loadProfileData()"><g:message
+ code="text.refresh" /></a></li>
+ </ul>
+ </li>
+ <li id="menuPassword" class="detailsToolbarMenuItem"><a href="#password"><g:message
+ code="text.password" /></a>
+ <ul>
+ <li id="menuChangePassword"><a href="#changePassword" onclick="showChangePasswordDialog()"><g:message
+ code="text.changePassword" /></a></li>
+
+ </ul>
+ </li>
+ </ul>
+</div>
+
+<script type="text/javascript">
+
+ $(function() {
+ $("ul.sf-menu").superfish();
+ });
+
+</script> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/profile/changePasswordDialog.gsp b/idrop-web/grails-app/views/profile/changePasswordDialog.gsp
new file mode 100644
index 0000000..29564c3
--- /dev/null
+++ b/idrop-web/grails-app/views/profile/changePasswordDialog.gsp
@@ -0,0 +1,37 @@
+<div id="changePasswordDialog" class="roundedContainer">
+ <h1><g:message code="text.change.password.header" /></h1>
+ <g:form name="changePasswordForm" id="changePasswordForm">
+
+ <g:if test="${flash.error}">
+ <script>
+ $(function() { setErrorMessage("${flash.error}"); });
+ </script>
+ </g:if>
+
+ <g:hasErrors bean="${password}">
+ <div class="errors">
+ <ul>
+ <g:eachError var="err" bean="${password}">
+ <li><g:message error="${err}" /></li>
+ </g:eachError>
+ </ul>
+ </div>
+ </g:hasErrors>
+ <div id="container" style="height:100%;width:100%;">
+ <div>
+ <div style="width:15%;"><label><g:message code="text.password"/></label></div>
+ <div><g:passwordField name="password" value="${password.password}" /></div>
+ </div>
+ <div>
+ <div style="width:15%;"><label><g:message code="text.confirm.password"/></label></div>
+ <div><g:passwordField name="confirmPassword" value="${password.confirmPassword}" /></div>
+ </div>
+ <div>
+ <div></div>
+ <div><button type="button" class="ui-state-default ui-corner-all" id="changePassword" value="changePassword" onclick="submitChangePassword()"><g:message code="text.update"/></button>
+ <button type="button" class="ui-state-default ui-corner-all" id="cancelChangePassword" value="cancelChangePassword" onclick="closePasswordDialog()"><g:message code="text.cancel"/></button>
+ </div>
+ </div>
+ </div>
+ </g:form>
+</div>
diff --git a/idrop-web/grails-app/views/profile/profileData.gsp b/idrop-web/grails-app/views/profile/profileData.gsp
new file mode 100644
index 0000000..77e957b
--- /dev/null
+++ b/idrop-web/grails-app/views/profile/profileData.gsp
@@ -0,0 +1,28 @@
+<div id="container" style="height:100%;width:100%;">
+ <div>
+ <div style="width:15%;"><label><g:message code="text.user"/></label></div>
+ <div>${userProfile.userName}</div>
+ </div>
+ <div>
+ <div style="width:15%;"><label><g:message code="text.nickname"/></label></div>
+ <div><g:textField id="nickName" name="nickName"
+ value="${userProfile.userProfilePublicFields.nickName}" />
+ </div>
+ </div>
+ <div>
+ <div style="width:15%;"><label><g:message code="text.personal.blurb"/></label></div>
+ <div><g:textArea id="description" name="description" rows="3" cols="40"
+ value="${userProfile.userProfilePublicFields.description}" /></div>
+ </div>
+ <div>
+ <div style="width:15%;"><label><g:message code="text.email"/></label></div>
+ <div><g:textField id="email" name="email"
+ value="${userProfile.userProfileProtectedFields.mail}" /></div>
+ </div>
+ <div>
+ <div></div>
+ <div><button type="button" class="ui-state-default ui-corner-all" id="updateProfile" value="updateProfile" onclick="updateProfile()"><g:message code="text.update"/></button>
+ <button type="button" class="ui-state-default ui-corner-all" id="reloadProfile" value="reloadProfile" onclick="loadProfileData()"><g:message code="text.cancel"/></button>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/idrop-web/idrop-web-config.groovy b/idrop-web/idrop-web-config.groovy
index d1d9cc2..462c414 100644
--- a/idrop-web/idrop-web-config.groovy
+++ b/idrop-web/idrop-web-config.groovy
@@ -60,4 +60,7 @@ idrop.config.idrop.jnlp="http://iren-web.renci.org/idrop-snapshot/idrop.jnlp"
*/
// do I support tickets? This determies whether the ticket feature is available via the interface, it also requires ticket support in iRODS itself (version 3.1+)
-idrop.config.use.tickets=true \ No newline at end of file
+idrop.config.use.tickets=true
+
+// do I want to display the profile tab and maintain user profile info
+idrop.config.use.userprofile=false \ No newline at end of file
diff --git a/idrop-web/release_notes.txt b/idrop-web/release_notes.txt
index f7582fe..f40e606 100644
--- a/idrop-web/release_notes.txt
+++ b/idrop-web/release_notes.txt
@@ -17,42 +17,12 @@ This is a release of iDrop web version 1.0.1
Note that the following bug and feature requests are logged in GForge with related commit information [[https://code.renci.org/gf/project/irodsidrop/tracker/]]
==Bug Fixes==
-
-* [#711] post copy via tree context menu - unable to browse to a location
-
-* [#873] login preset redisplay shows all
-
-* [#919] javascript errors null parent node in dataTable generation
-
-* [#935] idrop desktop launch works inconsistantly
-** took cruft out of webstart launch link to make a direct link to the jnlp file
-
-* [#939] new folder tree refresh fails when in 'home' view
-
-* [#940] safari rename file to self fails to show data when tree node clicked in safari/mac
-
-* [#941] crummy message displayed for add duplicate avu
-
-* [#942] Bulk delete of coll with children fails silently
+* [#959] firefox browse div float error
* [#950] unable to browse to location message in idrop web tree for new safari/mac
** temp catch of icon assignment added as shim in jstree javascript
==Features==
-* [#116] browse/search/tab memory
-** added jquery bbq plug-in for history management and provisional 'back button' functionality
-
-* [#696] Add ticket support
-** refactoring of 'info' pages to add accordion for various types of details, including ticket information
-** development of 'landing page' alternative
-
-* [#851] add anonymous login and other login enhancments
-** Remove spring security and simplify login process
-
-*[#479] audit trail support in idrop web
-** added audit trail views in idrop-web
-
-* [#907] anonymous listing default behavior
-** added default for 'home' listing when anonymous to display a 'public' dir as the top level
-
+* [#922] User Profile Management
+** added profile management tab, including ability to change password by user \ No newline at end of file
diff --git a/idrop-web/test/unit/org/irods/mydrop/controller/ProfileControllerTests.groovy b/idrop-web/test/unit/org/irods/mydrop/controller/ProfileControllerTests.groovy
new file mode 100644
index 0000000..30e8b0c
--- /dev/null
+++ b/idrop-web/test/unit/org/irods/mydrop/controller/ProfileControllerTests.groovy
@@ -0,0 +1,19 @@
+package org.irods.mydrop.controller
+
+
+
+import grails.test.mixin.*
+
+import org.irods.mydrop.controller.ProfileController;
+import org.junit.*
+
+/**
+ * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
+ */
+@TestFor(ProfileController)
+class ProfileControllerTests {
+
+ void testSomething() {
+ fail "Implement me"
+ }
+}
diff --git a/idrop-web/test/unit/org/irods/mydrop/service/ProfileServiceTests.groovy b/idrop-web/test/unit/org/irods/mydrop/service/ProfileServiceTests.groovy
new file mode 100644
index 0000000..850cb5c
--- /dev/null
+++ b/idrop-web/test/unit/org/irods/mydrop/service/ProfileServiceTests.groovy
@@ -0,0 +1,19 @@
+package org.irods.mydrop.service
+
+
+
+import grails.test.mixin.*
+
+import org.irods.mydrop.service.ProfileService;
+import org.junit.*
+
+/**
+ * See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions
+ */
+@TestFor(ProfileService)
+class ProfileServiceTests {
+
+ void testSomething() {
+ fail "Implement me"
+ }
+}
diff --git a/idrop-web/web-app/css/main.css b/idrop-web/web-app/css/main.css
index bc8f384..8e2a4ae 100644
--- a/idrop-web/web-app/css/main.css
+++ b/idrop-web/web-app/css/main.css
@@ -143,8 +143,8 @@ div#tabs { /*width: 100%;
padding: 0;
margin-left: auto;
margin-right: auto;
- background: #fff url(../images/iDropLogo.png) left center no-repeat;
- /*background: #fff url(../images/Lifetime-Library.png) left center no-repeat;*/
+ /*background: #fff url(../images/iDropLogo.png) left center no-repeat;*/
+ background: #fff url(../images/Lifetime-Library.png) left center no-repeat;
display: inline-block;
position: relative;
}
diff --git a/idrop-web/web-app/js/bundles/messages.properties b/idrop-web/web-app/js/bundles/messages.properties
index 25374b1..b12f2eb 100644
--- a/idrop-web/web-app/js/bundles/messages.properties
+++ b/idrop-web/web-app/js/bundles/messages.properties
@@ -2,10 +2,13 @@
msg_hello = Hello
msg_world = World
msg_complex = Good morning {0}!
+msg_password_no_data = No password data found
+msg_password_successful = Password change successful
msg_ticket_update_successful = Ticket update successful
msg_ticket_no_data = Error - No ticket data found
msg_upload_complete = Upload complete
msg_nothing_selected_for_edit = "Nothing was selected for editing"
msg_confirm_delete = Delete selected items?
msg_delete_successful = Delete successful
-msg_resource_changed=Resource changed successfully \ No newline at end of file
+msg_resource_changed=Resource changed successfully
+msg_profile_update_successful = Profile update successful \ No newline at end of file
diff --git a/idrop-web/web-app/js/mydrop/profile.js b/idrop-web/web-app/js/mydrop/profile.js
new file mode 100644
index 0000000..6d57517
--- /dev/null
+++ b/idrop-web/web-app/js/mydrop/profile.js
@@ -0,0 +1,101 @@
+/**
+ * Javascript for profile functions
+ */
+
+/**
+ * Accomplish the password change
+ */
+function submitChangePassword() {
+ var formData = $("#changePasswordForm").serializeArray();
+
+ if (formData == null) {
+ setErrorMessage(jQuery.i18n.prop('msg_no_password_data'));
+ return false;
+ }
+
+ showBlockingPanel();
+
+ var jqxhr = $.post(context + "/profile/changePassword", formData,
+ function(data, status, xhr) {
+ }, "html").success(function(data, status, xhr) {
+ var continueReq = checkForSessionTimeout(data, xhr);
+ if (!continueReq) {
+ return false;
+ }
+
+ $("#profileDialogArea").html(data);
+ closePasswordDialog();
+ setMessage(jQuery.i18n.prop('msg_password_successful'));
+ unblockPanel();
+
+ }).error(function(xhr, status, error) {
+
+ setErrorMessage(xhr.responseText);
+ unblockPanel();
+ });
+}
+
+
+/**
+ * load the profile details information
+ */
+function loadProfileData() {
+ var targetDiv = "#profileDataArea";
+ lcSendValueAndCallbackHtmlAfterErrorCheckPreserveMessage(
+ "/profile/index",
+ targetDiv, targetDiv, null);
+}
+
+/**
+ * Show the password change dialog
+ */
+
+function showChangePasswordDialog() {
+ var targetDiv = "#profileDialogArea";
+ $("#profileDataArea").hide("slow");
+ $("#profileToolbar").hide("slow");
+ lcSendValueAndCallbackHtmlAfterErrorCheckPreserveMessage(
+ "/profile/showPasswordChangeDialog",
+ targetDiv, targetDiv, null);
+}
+
+/**
+ * close the password dialog
+ */
+function closePasswordDialog() {
+ $("#profileDialogArea").html("");
+ $("#profileToolbar").show("slow");
+ $("#profileDataArea").show("slow");
+}
+
+
+/**
+ * Update the profile information
+ */
+function updateProfile() {
+
+ var params = {
+ nickName : $("#nickName").val(),
+ description : $("#description").val(),
+ email : $("#email").val()
+ }
+
+ showBlockingPanel();
+
+ var jqxhr = $.post(context + "/profile/updateProfile", params,
+ function(data, status, xhr) {
+ }, "html").success(function(returnedData, status, xhr) {
+ var continueReq = checkForSessionTimeout(returnedData, xhr);
+ if (!continueReq) {
+ return false;
+ }
+ setMessage(jQuery.i18n.prop('msg_profile_update_successful'));
+ $("#profileDataArea").html(returnedData);
+ unblockPanel();
+ }).error(function(xhr, status, error) {
+ setErrorMessage(xhr.responseText);
+ unblockPanel();
+ });
+}
+
+