summaryrefslogtreecommitdiffstats
path: root/idrop-web
diff options
context:
space:
mode:
authorMike Conway <mikeconway@Mike-Conways-MacBook-Pro.local>2011-03-21 20:16:10 (GMT)
committer Mike Conway <mikeconway@Mike-Conways-MacBook-Pro.local>2011-03-21 20:16:10 (GMT)
commitdd83962e21cab0135e02dec6f8ed9781c3c80545 (patch)
tree26dc21c6eb321e6aa17ace847f93b63436a83a61 /idrop-web
parentd69d0a83d7af09d4d16420cd0f376eef237f4e62 (diff)
downloadQCG-Data-dd83962e21cab0135e02dec6f8ed9781c3c80545.zip
QCG-Data-dd83962e21cab0135e02dec6f8ed9781c3c80545.tar.gz
QCG-Data-dd83962e21cab0135e02dec6f8ed9781c3c80545.tar.bz2
metadata browsing in web
Diffstat (limited to 'idrop-web')
-rw-r--r--idrop-web/LICENSE.txt20
-rw-r--r--idrop-web/grails-app/conf/Config.groovy2
-rw-r--r--idrop-web/grails-app/conf/spring/resources.groovy4
-rw-r--r--idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy26
-rw-r--r--idrop-web/grails-app/controllers/org/irods/mydrop/controller/MetadataController.groovy76
-rw-r--r--idrop-web/grails-app/controllers/org/irods/mydrop/controller/TagsController.groovy48
-rw-r--r--idrop-web/grails-app/views/browse/browseDetails.gsp114
-rw-r--r--idrop-web/grails-app/views/browse/collectionInfo.gsp66
-rw-r--r--idrop-web/grails-app/views/browse/dataObjectInfo.gsp70
-rw-r--r--idrop-web/grails-app/views/browse/pulldownDataDetails.gsp22
-rw-r--r--idrop-web/grails-app/views/common/_secondarymain.gsp22
-rw-r--r--idrop-web/grails-app/views/common/_topbar.gsp12
-rw-r--r--idrop-web/grails-app/views/home/index.gsp9
-rw-r--r--idrop-web/grails-app/views/layouts/main.gsp3
-rw-r--r--idrop-web/grails-app/views/metadata/metadataDetails.gsp57
-rw-r--r--idrop-web/test/unit/org/irods/mydrop/controller/BrowseControllerTests.groovy23
-rw-r--r--idrop-web/test/unit/org/irods/mydrop/controller/MetadataControllerTests.groovy91
-rw-r--r--idrop-web/web-app/css/jqcloud.css59
-rw-r--r--idrop-web/web-app/css/main.css87
-rw-r--r--idrop-web/web-app/css/reset-fonts-grids.css4
-rw-r--r--idrop-web/web-app/js/jqcloud-0.1.5.min.js11
-rw-r--r--idrop-web/web-app/js/jquery.jeditable.mini.js38
-rw-r--r--idrop-web/web-app/js/mydrop/home.js56
-rw-r--r--idrop-web/web-app/js/mydrop/lingo_common.js36
24 files changed, 844 insertions, 112 deletions
diff --git a/idrop-web/LICENSE.txt b/idrop-web/LICENSE.txt
new file mode 100644
index 0000000..146ba1e
--- /dev/null
+++ b/idrop-web/LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Luca Ongaro
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/idrop-web/grails-app/conf/Config.groovy b/idrop-web/grails-app/conf/Config.groovy
index 07473a0..159f673 100644
--- a/idrop-web/grails-app/conf/Config.groovy
+++ b/idrop-web/grails-app/conf/Config.groovy
@@ -52,7 +52,7 @@ grails.validateable.packages = ['org.irods']
// set per-environment serverURL stem for creating absolute links
environments {
production {
- grails.serverURL = "http://www.changeme.com"
+ grails.serverURL = "http://irendb.renci.org:8080/${appName}"
}
development {
grails.serverURL = "http://localhost:8080/${appName}"
diff --git a/idrop-web/grails-app/conf/spring/resources.groovy b/idrop-web/grails-app/conf/spring/resources.groovy
index 8b5a056..ba48eef 100644
--- a/idrop-web/grails-app/conf/spring/resources.groovy
+++ b/idrop-web/grails-app/conf/spring/resources.groovy
@@ -16,4 +16,8 @@ beans = {
taggingServiceFactory = ref("taggingServiceFactory")
}
+ metadataController(org.irods.mydrop.controller.MetadataController) {
+ irodsAccessObjectFactory = ref("irodsAccessObjectFactory")
+ }
+
}
diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy
index 14fbf4f..a9ab2be 100644
--- a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy
+++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/BrowseController.groovy
@@ -90,6 +90,32 @@ class BrowseController {
render jsonBuff as JSON
}
+
+ def displayBrowseGridDetails = {
+ def absPath = params['absPath']
+ if (absPath == null) {
+ throw new JargonException("no absolute path passed to the method")
+ }
+
+ log.info "displayBrowseGridDetails for absPath: ${absPath}"
+ CollectionAndDataObjectListAndSearchAO collectionAndDataObjectListAndSearchAO = irodsAccessObjectFactory.getCollectionAndDataObjectListAndSearchAO(irodsAccount)
+ def entries = collectionAndDataObjectListAndSearchAO.listDataObjectsAndCollectionsUnderPath(absPath)
+ log.debug("retrieved collectionAndDataObjectList: ${entries}")
+ render(view:"browseDetails", model:[collection:entries])
+
+ }
+
+ def displayPulldownDataDetails = {
+ def absPath = params['absPath']
+ if (absPath == null) {
+ throw new JargonException("no absolute path passed to the method")
+ }
+
+ log.info "displayPulldownDataDetails for absPath: ${absPath}"
+ render(view:"pulldownDataDetails")
+
+ }
+
def fileInfo = {
def absPath = params['absPath']
diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/MetadataController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/MetadataController.groovy
new file mode 100644
index 0000000..167c395
--- /dev/null
+++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/MetadataController.groovy
@@ -0,0 +1,76 @@
+package org.irods.mydrop.controller
+
+
+import org.irods.jargon.core.connection.IRODSAccount
+import org.irods.jargon.core.exception.JargonException
+import org.irods.jargon.core.exception.JargonRuntimeException
+import org.irods.jargon.core.pub.CollectionAO
+import org.irods.jargon.core.pub.CollectionAndDataObjectListAndSearchAO
+import org.irods.jargon.core.pub.DataObjectAO
+import org.irods.jargon.core.pub.IRODSAccessObjectFactory
+import org.irods.jargon.core.pub.domain.DataObject
+import org.mockito.Mockito
+import org.springframework.security.core.context.SecurityContextHolder
+
+/**
+ * Controller for displaying and updating various metadata for data objects or collections
+ * @author Mike Conway - DICE (www.irods.org)
+ */
+class MetadataController {
+
+ IRODSAccessObjectFactory irodsAccessObjectFactory
+ IRODSAccount irodsAccount
+
+ /**
+ * Interceptor grabs IRODSAccount from the SecurityContextHolder
+ */
+ def beforeInterceptor = {
+ def irodsAuthentication = SecurityContextHolder.getContext().authentication
+
+ if (irodsAuthentication == null) {
+ throw new JargonRuntimeException("no irodsAuthentication in security context!")
+ }
+
+ irodsAccount = irodsAuthentication.irodsAccount
+ log.debug("retrieved account for request: ${irodsAccount}")
+ }
+
+ def afterInterceptor = {
+ log.debug("closing the session")
+ irodsAccessObjectFactory.closeSession()
+ }
+
+ /**
+ * For a given absolute path, which is a data object, list the AVU metadata values
+ */
+ def listMetadata = {
+ def absPath = params['absPath']
+ if (absPath == null) {
+ throw new JargonException("no absolute path passed to the method")
+ }
+
+ log.info("listMetadataForDataObject for absPath: ${absPath}")
+
+ CollectionAndDataObjectListAndSearchAO collectionAndDataObjectListAndSearchAO = irodsAccessObjectFactory.getCollectionAndDataObjectListAndSearchAO(irodsAccount)
+
+ // TODO: some sort of catch and display of no data available in info?
+ def retObj = collectionAndDataObjectListAndSearchAO.getFullObjectForType(absPath)
+
+ def isDataObject = retObj instanceof DataObject
+ def metadata;
+
+ if (isDataObject) {
+ log.debug("retrieving meta data for a data object");
+ DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount)
+ metadata = dataObjectAO.findMetadataValuesForDataObject(retObj.collectionName, retObj.dataName)
+ } else {
+ CollectionAO collectionAO = irodsAccessObjectFactory.getCollectionAO(irodsAccount)
+ metadata = collectionAO.findMetadataValuesForCollection(retObj.collectionName, 0) // FIXME: switch to no restart sig
+ }
+
+ render(view:"metadataDetails", model:[metadata:metadata])
+
+ }
+
+
+}
diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/TagsController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/TagsController.groovy
index bf67bc1..70d82e3 100644
--- a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/TagsController.groovy
+++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/TagsController.groovy
@@ -11,14 +11,16 @@ import org.irods.jargon.usertagging.domain.UserTagCloudView
import org.jsoup.Jsoup
import org.jsoup.safety.Whitelist
import org.springframework.security.core.context.SecurityContextHolder
+import grails.converters.*
+
class TagsController {
-
+
IRODSAccessObjectFactory irodsAccessObjectFactory
TaggingServiceFactory taggingServiceFactory
IRODSAccount irodsAccount
-
+
def allowedMethods = [
updateTags:['POST']]
@@ -36,27 +38,49 @@ class TagsController {
log.debug("retrieved account for request: ${irodsAccount}")
}
-
- def afterInterceptor = {
+
+ def afterInterceptor = {
log.debug("closing any open sessions")
irodsAccessObjectFactory.closeSession()
}
- def index = { }
-
+ def index = { }
+
/**
* Retrieve a tag cloud for the user
*/
def tagCloud = {
-
+
log.info("getting tag cloud for user: ${irodsAccount}")
UserTagCloudService userTagCloudService = taggingServiceFactory.instanceUserTagCloudService(irodsAccount)
UserTagCloudView userTagCloudView = userTagCloudService.getTagCloud()
def entries = userTagCloudView.getTagCloudEntries().values()
render(view:"tagCloud", model:[tagCloud:entries])
+ }
+
+ /**
+ * Retrieve a formattable tag cloud for the user
+ */
+ def tagCloudFormatted = {
+
+ log.info("getting tag cloud for user: ${irodsAccount}")
+ UserTagCloudService userTagCloudService = taggingServiceFactory.instanceUserTagCloudService(irodsAccount)
+ UserTagCloudView userTagCloudView = userTagCloudService.getTagCloud()
+ def entries = userTagCloudView.getTagCloudEntries().values()
+ def jsonBuff = []
+
+ entries.each {
+
+
+ jsonBuff.add(
+ ["text": it.irodsTagValue.tagData,"weight":2 + it.countOfFiles])
+
+ }
+
+ render jsonBuff as JSON
}
-
+
/**
* update the tag for the collection or data object based on a free tag string
*/
@@ -67,18 +91,16 @@ class TagsController {
if (absPath == null || absPath.isEmpty()) {
throw new JargonException("no absPath passed to method")
}
-
+
if (tagString == null) {
throw new JargonException("null tags passed to method")
}
-
+
log.info("updating tags for file: ${absPath} for user: ${irodsAccount.userName}")
-
+
FreeTaggingService freeTaggingService = taggingServiceFactory.instanceFreeTaggingService(irodsAccount)
freeTaggingService.updateTagsForUserForADataObjectOrCollection(absPath, irodsAccount.userName, tagString)
log.info("tags updated")
render "success"
-
}
-
}
diff --git a/idrop-web/grails-app/views/browse/browseDetails.gsp b/idrop-web/grails-app/views/browse/browseDetails.gsp
new file mode 100644
index 0000000..4959eeb
--- /dev/null
+++ b/idrop-web/grails-app/views/browse/browseDetails.gsp
@@ -0,0 +1,114 @@
+
+ <div>
+ <table cellspacing="0" cellpadding="0" border="0"
+ id="browseDataDetailsTable" style="width: 100%;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Name</th>
+ <th>Type</th>
+ <th>Modified date</th>
+ <th>Length</th>
+ </tr>
+ </thead>
+ <tbody>
+ <g:each in="${collection}" var="entry">
+ <tr id="${entry.formattedAbsolutePath}">
+ <td><span class="ui-icon-circle-plus browse_detail_icon ui-icon"></span></td>
+ <td>
+ ${entry.nodeLabelDisplayValue}
+ </td>
+
+ <td>
+ ${entry.objectType}
+ </td>
+ <td>
+ ${entry.modifiedAt}
+ </td>
+ <td>
+ ${entry.dataSize}
+ </td>
+ </tr>
+ </g:each>
+
+ </tbody>
+
+ <tfoot>
+ <tr>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+<script>
+
+ var dataTable;
+
+ $(function() {
+
+
+ dataTable = lcBuildTableInPlace("#browseDataDetailsTable", browseDetailsClick, ".browse_detail_icon");
+
+ });
+
+ function browseDetailsClick(minMaxIcon) {
+ var nTr = minMaxIcon.parentNode.parentNode;
+
+ if (minMaxIcon.parentNode.innerHTML.match('circle-minus')) {
+ lcCloseTableNodes(dataTable);
+ } else {
+ try {
+ browseDataDetailsFunction(minMaxIcon, nTr);
+ } catch (err) {
+ console.log("error in detailsClick():" + err);
+ }
+
+ }
+ }
+
+ function browseDataDetailsFunction(clickedIcon, rowActionIsOn) {
+ /* Open this row */
+ prepareForCall();
+ lcCloseTableNodes(dataTable);
+ // nTr points to row and has absPath in id
+ var absPath = $(rowActionIsOn).attr('id');
+ //alert("absPath:" + absPath);
+ var detailsId = "details_" + absPath;
+ var detailsHtmlDiv = "details_html_" + absPath;
+
+ clickedIcon.setAttribute("class", "ui-icon ui-icon-circle-minus");
+ newRowNode = dataTable.fnOpen(rowActionIsOn,
+ askForBrowseDetailsPulldown(absPath, detailsId), 'details');
+ newRowNode.setAttribute("id", detailsId);
+
+ }
+
+ function buildDetailsLayout(detailsId) {
+ var td = document.createElement("TD");
+ td.setAttribute("colspan", "4");
+
+ var detailsPulldownDiv = document.createElement("DIV");
+ detailsPulldownDiv.setAttribute("id", detailsId);
+ detailsPulldownDiv.setAttribute("class", "detailsPulldown");
+
+ td.appendChild(detailsPulldownDiv);
+
+ return $(td).html();
+ }
+
+ function askForBrowseDetailsPulldown(absPath, detailsId) {
+ var url = "/browse/displayPulldownDataDetails";
+ var params = {
+ absPath:absPath
+ }
+
+ lcSendValueWithParamsAndPlugHtmlInDiv(url, params, ".details",
+ null);
+
+ }
+
+ </script> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/browse/collectionInfo.gsp b/idrop-web/grails-app/views/browse/collectionInfo.gsp
index 4dee007..f18fe55 100644
--- a/idrop-web/grails-app/views/browse/collectionInfo.gsp
+++ b/idrop-web/grails-app/views/browse/collectionInfo.gsp
@@ -1,38 +1,42 @@
-<div id="infoAccordion">
-<h3>Summary</h3>
-<div>
-<fieldset id="verticalForm"><label for="">Parent
-Collection:</label> <g:textField name="collectionParentName"
- value="${collection.collectionParentName}" readonly="true" /> <br />
-<label for="collectionName">Collection Name:</label> <g:textField
- name="collectionName" value="${collection.collectionName}"
- readonly="true" /> <br />
+<div class="box">
+ <fieldset id="verticalForm">
+ <label for="">Parent Collection:</label>
+ <g:textField name="collectionParentName"
+ value="${collection.collectionParentName}" readonly="true" />
+ <br /> <label for="collectionName">Collection Name:</label>
+ <g:textField name="collectionName"
+ value="${collection.collectionName}" readonly="true" />
+ <br /> <label for="createdAt">Created At:</label>
+ <g:textField name="createdAt" value="${collection.createdAt}"
+ readonly="true" />
-<label for="createdAt">Created At:</label> <g:textField name="createdAt"
- value="${collection.createdAt}" readonly="true" /> <br />
+ <br /> <br /> <label for="updatedAt">Updated At:</label>
+ <g:textField name="updatedAt" value="${collection.modifiedAt}"
+ readonly="true" />
-<label for="tags">Tags:</label> <g:textField id="infoTags" name="tags"
- value="${tags.spaceDelimitedTagsForDomain}" /> <br />
+ <br /> <label for="owner">Owner:</label>
+ <g:textField name="owner" value="${collection.collectionOwnerName}"
+ readonly="true" />
-<g:hiddenField id="infoAbsPath" name="absolutePath"
- value="${collection.collectionName}" />
-<button type="button" id="updateTags" value="updateTags"
- onclick="updateTags()")>Update Tags</button>
-
-<div id="infoUpdateArea"><!-- div for any updates in info --></div>
+ <br /> <label for="ownerZone">Owner Zone:</label>
+ <g:textField name="ownerZone"
+ value="${collection.collectionOwnerZone}" readonly="true" />
-</fieldset>
-</div>
-<h3>Sharing</h3>
-<div>sharing stuff here</div>
-<h3>Metadata</h3>
-<div>Metadata stuff here</div>
+ <g:hiddenField id="infoAbsPath" name="absolutePath"
+ value="${collection.collectionName}" />
+
+ <br /> <label for="tags">Tags:</label>
+ <g:textField id="infoTags" name="tags"
+ value="${tags.spaceDelimitedTagsForDomain}" />
+
+ <button type="button" id="updateTags" value="updateTags"
+ onclick="updateTags()")>Update Tags</button>
+
+ <div id="infoUpdateArea">
+ <!-- div for any updates in info -->
+ </div>
+
+ </fieldset>
</div>
-<script>
- $(function() {
- $( "#infoAccordion" ).accordion();
- });
-
- </script> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/browse/dataObjectInfo.gsp b/idrop-web/grails-app/views/browse/dataObjectInfo.gsp
index e2ee2d5..f0a23e2 100644
--- a/idrop-web/grails-app/views/browse/dataObjectInfo.gsp
+++ b/idrop-web/grails-app/views/browse/dataObjectInfo.gsp
@@ -1,28 +1,44 @@
-<fieldset id="verticalForm"><label for="collectionName">Parent
-Collection:</label> <g:textField name="collectionName"
- value="${dataObject.collectionName}" readonly="true" /> <br />
-<label for="dataName">File Name:</label> <g:textField name="dataName"
- value="${dataObject.dataName}" readonly="true" /> <br />
-
-<label for="createdAt">Created At:</label> <g:textField name="createdAt"
- value="${dataObject.createdAt}" readonly="true" /> <br />
-
-<label for="dataSize">Size:</label> <g:textField name="dataSize"
- value="${dataObject.dataSize}" readonly="true" /> <br />
-
-<label for="checksum">Checksum:</label> <g:textField name="checksum"
- value="${dataObject.checksum}" readonly="true" /> <br />
-
-<label for="tags">Tags:</label> <g:textField id="infoTags" name="tags"
- value="${tags.spaceDelimitedTagsForDomain}" /> <br />
-
-<g:hiddenField id="infoAbsPath" name="absolutePath"
- value="${dataObject.absolutePath}" />
-
-<button type="button" id="updateTags" value="updateTags"
- onclick="updateTags()")>Update Tags</button>
-
- <div id="infoUpdateArea"><!-- div for any updates in info --></div>
-
-</fieldset> \ No newline at end of file
+<div class="box">
+ <fieldset id="verticalForm">
+ <label for="">Collection:</label>
+ <g:textField name="collectionName"
+ value="${dataObject.collectionName}" readonly="true" />
+ <br /> <label for="dataName">Name:</label>
+ <g:textField name="dataName" value="${dataObject.dataName}"
+ readonly="true" />
+ <br /> <label for="size">Size:</label>
+ <g:textField name="size" value="${dataObject.dataSize}" readonly="true "/>
+ <br /> <label for="createdAt">Created At:</label>
+ <g:textField name="createdAt" value="${dataObject.createdAt}"
+ readonly="true" />
+ <br /> <label for="updatedAt">Updated At:</label>
+ <g:textField name="updatedAt" value="${dataObject.updatedAt}"
+ readonly="true" />
+
+ <br /> <label for="owner">Owner:</label>
+ <g:textField name="owner" value="${dataObject.dataOwnerName}"
+ readonly="true" />
+
+
+ <br /> <label for="ownerZone">Owner Zone:</label>
+ <g:textField name="ownerZone" value="${dataObject.dataOwnerZone}"
+ readonly="true" />
+
+ <br /> <label for="tags">Tags:</label>
+ <g:textField id="infoTags" name="tags"
+ value="${tags.spaceDelimitedTagsForDomain}" />
+ <br />
+
+ <g:hiddenField id="infoAbsPath" name="absolutePath"
+ value="${dataObject.absolutePath}" />
+
+ <button type="button" id="updateTags" value="updateTags"
+ onclick="updateTags()")>Update Tags</button>
+
+ <div id="infoUpdateArea">
+ <!-- div for any updates in info -->
+ </div>
+
+ </fieldset>
+</div> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/browse/pulldownDataDetails.gsp b/idrop-web/grails-app/views/browse/pulldownDataDetails.gsp
new file mode 100644
index 0000000..54c6f03
--- /dev/null
+++ b/idrop-web/grails-app/views/browse/pulldownDataDetails.gsp
@@ -0,0 +1,22 @@
+<div id="dataDetailsAccordion" style="width: 100%; height: 100%;">
+
+ <h3>Data details</h3>
+ <div id="pulldownTabs">
+ <ul>
+ <li><a href="#summary">Info</a></li>
+ <li><a href="#sharing">Sharing</a></li>
+ <li><a href="#metadata">Metadata</a></li>
+ </ul>
+ <div id="pulldownInfo"></div>
+ <div id="sharing"></div>
+ <div id="metadata"></div>
+
+ </div>
+</div>
+
+
+<script type="text/javascript">
+$(document).ready(function() {
+ $( "#pulldownTabs" ).tabs();
+ //retrieveBrowserFirstView();
+}); \ No newline at end of file
diff --git a/idrop-web/grails-app/views/common/_secondarymain.gsp b/idrop-web/grails-app/views/common/_secondarymain.gsp
index a13dc28..179458f 100644
--- a/idrop-web/grails-app/views/common/_secondarymain.gsp
+++ b/idrop-web/grails-app/views/common/_secondarymain.gsp
@@ -1,9 +1,19 @@
<script>
$(function() {
$("#secondaryTabs").tabs();
- lcSendValueAndCallbackHtmlAfterErrorCheck("/tags/tagCloud", "#tagCloudDiv",
- "#tagCloudDiv", null);
+ //lcSendValueAndCallbackHtmlAfterErrorCheck("/tags/tagCloud", "#tagCloudDiv",
+ // "#tagCloudDiv", null);
+
+ lcSendValueAndCallbackWithJsonAfterErrorCheck("/tags/tagCloudFormatted", null,
+ "#tagCloudDiv", function(data){haveTagCloudData(data);});//function(data){haveTagCloudData(data);});
+
+
});
+
+ function haveTagCloudData(data) {
+ $("#tagCloudDiv").jQCloud(data, new function(){});
+ }
+
</script>
<div id="secondaryTabs">
<ul>
@@ -13,7 +23,7 @@
</ul>
<div id="tabs-1">
-<div id="tagCloudDiv" class="scroll">
+<div id="tagCloudDiv" >
<!-- tag cloud div is ajax loaded -->
@@ -29,13 +39,13 @@
<div id="tabs-3">
- <h1>Launch iDrop Desktop Client v 0.9.1 alpha - work in progress</h1>
+ <h1>Launch iDrop Desktop Client</h1>
<script src="http://www.java.com/js/deployJava.js"></script>
<script>
// using JavaScript to get location of JNLP file relative to HTML page
- var url = "http://irendb.renci.org:8080/llclient/launchLLDrop.html";
+ var url = "http://irendb.renci.org:8080/idrop/launchIDrop.html";
//deployJava.createWebStartLaunchButton(url, '1.6.0');
- </script><a onmouseover="window.status=''; return true;" href="javascript:if (!deployJava.isWebStartInstalled(&quot;1.6.0&quot;)) {if (deployJava.installLatestJRE()) {if (deployJava.launch(&quot;http://irendb.renci.org:8080/llclient/idrop.jnlp&quot;)) {}}} else {if (deployJava.launch(&quot;http://irendb.renci.org:8080/llclient/idrop.jnlp&quot;)) {}}"><img border="0" src="http://java.sun.com/products/jfc/tsc/articles/swing2d/webstart.png"></a>
+ </script><a onmouseover="window.status=''; return true;" href="javascript:if (!deployJava.isWebStartInstalled(&quot;1.6.0&quot;)) {if (deployJava.installLatestJRE()) {if (deployJava.launch(&quot;http://irendb.renci.org:8080/idrop/idrop.jnlp&quot;)) {}}} else {if (deployJava.launch(&quot;http://irendb.renci.org:8080/idrop/idrop.jnlp&quot;)) {}}"><img border="0" src="http://java.sun.com/products/jfc/tsc/articles/swing2d/webstart.png"></a>
</div>
diff --git a/idrop-web/grails-app/views/common/_topbar.gsp b/idrop-web/grails-app/views/common/_topbar.gsp
index d1734f8..4448a22 100644
--- a/idrop-web/grails-app/views/common/_topbar.gsp
+++ b/idrop-web/grails-app/views/common/_topbar.gsp
@@ -6,7 +6,7 @@
<button type="button" id="search" value="search" onclick="search()")>Search</button> as a
-<g:select name="searchType" id="searchType" from="${['file', 'tag']}" noSelection="['file':'']" />
+<g:select name="searchType" id="searchType" from="${['file', 'tag']}" />
</fieldset>
@@ -31,14 +31,24 @@ function showMenu() {
menuShown = false;
$("#mainDiv").width="100%";
$("#mainDivCol1").width="100%";
+ $("#mainDivCol1").removeClass()
} else {
$("#secondaryDiv").show('slow');
$("#mainDiv").width="80%";
$("#mainDivCol1").width="80%";
$("#secondaryDiv").width="20%";
+ $("#mainDivCol1").addClass("yui-u first");
+
menuShown = true;
}
}
+
+
+
+function search() {
+ prosecuteSearch($("#searchTerm").val(), $("#searchType").val());
+}
+
//-->
</script>
diff --git a/idrop-web/grails-app/views/home/index.gsp b/idrop-web/grails-app/views/home/index.gsp
index 18f3e1c..4c321f1 100644
--- a/idrop-web/grails-app/views/home/index.gsp
+++ b/idrop-web/grails-app/views/home/index.gsp
@@ -16,7 +16,7 @@
</ul>
<div id="quickView">
<div class="objectContainer">
- <div class="objectContainerGrouping"></div>
+
<div class="objectContainerDetails">
<span class="objectHeader">A data object</span>
<div class="objectDescription">This is a really nice data
@@ -39,7 +39,7 @@
<div class="objectContainer">
- <div class="objectContainerGrouping"></div>
+
<div class="objectContainerDetails">
<span class="objectHeader">A data object</span>
<div class="objectDescription">This is a really nice data
@@ -81,9 +81,11 @@
<div id="dataTreeDiv" class="ui-layout-west">
<!-- no empty divs -->
</div>
+ <div id="browseToolbar" class="ui-layout-north">
+ Display Option:<g:select name="browseDisplayOption" id="browseDisplayOption" from="${['info', 'details', 'sharing', 'metadata']}" onChange="setBrowseMode()" /></div>
<div id="infoDiv" class="ui-layout-center">
- <h2>Select a directory or file to see info and tags</h2>
+ <h2>Select a directory or file to see info and tags based on the view option</h2>
</div>
</div>
@@ -104,6 +106,7 @@ $(document).ready(function() {
});
$( "#tabs" ).tabs();
retrieveBrowserFirstView();
+
});
</script> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/layouts/main.gsp b/idrop-web/grails-app/views/layouts/main.gsp
index 844057d..a0bf7c1 100644
--- a/idrop-web/grails-app/views/layouts/main.gsp
+++ b/idrop-web/grails-app/views/layouts/main.gsp
@@ -4,7 +4,7 @@
<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:'reset-fonts-grids.css')}" />
<link rel="stylesheet" href="${resource(dir:'css',file:'overcast/jquery-ui-1.8.7.custom.css')}" />
@@ -16,6 +16,7 @@
<g:javascript library="jquery-ui-1.8.7.custom.min" />
<g:javascript library="jquery.jstree.min" />
<g:javascript library="jquery.dataTables.min" />
+<g:javascript library="jqcloud-0.1.5.min" />
<g:javascript library="mydrop/lingo_common" />
<g:javascript library="mydrop/main" />
<g:javascript library="jquery-ui-13" />
diff --git a/idrop-web/grails-app/views/metadata/metadataDetails.gsp b/idrop-web/grails-app/views/metadata/metadataDetails.gsp
new file mode 100644
index 0000000..12cd527
--- /dev/null
+++ b/idrop-web/grails-app/views/metadata/metadataDetails.gsp
@@ -0,0 +1,57 @@
+<div id="detailsTopSection" class="box">
+
+<div id="detailsToolbar" class="nav">
+<button type="button" id="addMetadataButton" class="menuButton" value="addMetadata" onclick="addMetadata()")>Add Metadata</button>
+<button type="button" id="updateMetadataButton" class="menuButton" value="updateMetadata" onclick="updateMetadata()")>Update Metadata</button>
+<button type="button" id="deleteMetadataButton" class="menuButton" value="deleteMetadata" onclick="deleteMetadata()")>Delete Metadata</button>
+</div>
+</div>
+<div>
+ <table cellspacing="0" cellpadding="0" border="0"
+ id="metaDataDetailsTable" style="width: 100%;">
+ <thead>
+ <tr>
+ <th></th>
+ <th>Attribute</th>
+ <th>Value</th>
+ <th>Unit</th>
+ </tr>
+ </thead>
+ <tbody>
+ <g:each in="${metadata}" var="entry">
+ <tr id="${entry.domainObjectUniqueName}">
+ <td><g:checkBox name="selectedMetadata" />
+ </td>
+ <td>
+ ${entry.avuAttribute}
+ </td>
+ <td>
+ ${entry.avuValue}
+ </td>
+ <td>
+ ${entry.avuUnit}
+ </td>
+ </tr>
+ </g:each>
+
+ </tbody>
+
+ <tfoot>
+ <tr>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+ </tfoot>
+ </table>
+</div>
+<script type="text/javascript">
+
+
+ $(function() {
+
+ dataTable = lcBuildTableInPlace("#metaDataDetailsTable", null, null);
+ });
+
+ </script> \ No newline at end of file
diff --git a/idrop-web/test/unit/org/irods/mydrop/controller/BrowseControllerTests.groovy b/idrop-web/test/unit/org/irods/mydrop/controller/BrowseControllerTests.groovy
index 5aab305..57613e5 100644
--- a/idrop-web/test/unit/org/irods/mydrop/controller/BrowseControllerTests.groovy
+++ b/idrop-web/test/unit/org/irods/mydrop/controller/BrowseControllerTests.groovy
@@ -11,8 +11,9 @@ import org.irods.jargon.core.exception.JargonException
import org.irods.jargon.core.pub.CollectionAndDataObjectListAndSearchAO
import org.irods.jargon.core.pub.IRODSAccessObjectFactory
import org.irods.jargon.core.pub.IRODSFileSystem
-import org.irods.jargon.core.pub.domain.DataObject
import org.irods.jargon.core.pub.domain.Collection
+import org.irods.jargon.core.pub.domain.DataObject
+import org.irods.jargon.core.query.CollectionAndDataObjectListingEntry
import org.irods.jargon.core.query.MetaDataAndDomainData
import org.irods.jargon.spring.security.IRODSAuthenticationToken
import org.irods.jargon.testutils.TestingPropertiesHelper
@@ -134,4 +135,24 @@ class BrowseControllerTests extends ControllerUnitTestCase {
}
+ void testBrowseDetailsWithCollection() {
+ def testPath = "/testpath"
+ def irodsAccessObjectFactory = Mockito.mock(IRODSAccessObjectFactory.class)
+ CollectionAndDataObjectListAndSearchAO collectionListAndSearchAO = Mockito.mock(CollectionAndDataObjectListAndSearchAO.class)
+ def retObject = new ArrayList<CollectionAndDataObjectListingEntry>()
+ Mockito.when(collectionListAndSearchAO.listDataObjectsAndCollectionsUnderPath(testPath)).thenReturn(retObject)
+ Mockito.when(irodsAccessObjectFactory.getCollectionAndDataObjectListAndSearchAO(irodsAccount)).thenReturn(collectionListAndSearchAO)
+ controller.irodsAccessObjectFactory = irodsAccessObjectFactory
+ controller.irodsAccount = irodsAccount
+ controller.params.absPath = testPath
+ controller.displayBrowseGridDetails()
+ def mav = controller.modelAndView
+ def name = mav.viewName
+ assertNotNull("null mav", mav)
+ assertEquals("view name should be browseDetails", "browseDetails", name)
+ def collection = mav.model.collection
+ assertNotNull("null collection object", collection)
+
+ }
+
}
diff --git a/idrop-web/test/unit/org/irods/mydrop/controller/MetadataControllerTests.groovy b/idrop-web/test/unit/org/irods/mydrop/controller/MetadataControllerTests.groovy
new file mode 100644
index 0000000..3a3e519
--- /dev/null
+++ b/idrop-web/test/unit/org/irods/mydrop/controller/MetadataControllerTests.groovy
@@ -0,0 +1,91 @@
+
+package org.irods.mydrop.controller
+
+import grails.converters.*
+import grails.test.*
+
+import java.util.Properties
+
+import java.util.List;
+
+import org.irods.jargon.core.query.MetaDataAndDomainData;
+
+import java.util.Properties;
+
+import org.irods.jargon.core.connection.IRODSAccount;
+import org.irods.jargon.core.pub.IRODSAccessObjectFactory;
+import org.irods.jargon.core.pub.IRODSFileSystem;
+import org.irods.jargon.testutils.TestingPropertiesHelper;
+
+
+import org.irods.jargon.core.connection.IRODSAccount
+import org.irods.jargon.core.exception.JargonException
+import org.irods.jargon.core.pub.CollectionAndDataObjectListAndSearchAO
+import org.irods.jargon.core.pub.IRODSAccessObjectFactory
+import org.irods.jargon.core.pub.IRODSFileSystem
+import org.irods.jargon.core.pub.domain.Collection
+import org.irods.jargon.core.pub.CollectionAO
+import org.irods.jargon.core.pub.domain.DataObject
+import org.irods.jargon.core.query.CollectionAndDataObjectListingEntry
+import org.irods.jargon.core.query.MetaDataAndDomainData
+import org.irods.jargon.spring.security.IRODSAuthenticationToken
+import org.irods.jargon.testutils.TestingPropertiesHelper
+import org.irods.jargon.usertagging.FreeTaggingService
+import org.irods.jargon.usertagging.TaggingServiceFactory
+import org.irods.jargon.usertagging.domain.IRODSTagGrouping
+import org.mockito.Mockito
+import org.springframework.security.core.context.SecurityContextHolder
+
+
+class MetadataControllerTests extends ControllerUnitTestCase {
+
+ IRODSAccessObjectFactory irodsAccessObjectFactory
+ IRODSAccount irodsAccount
+ Properties testingProperties
+ TestingPropertiesHelper testingPropertiesHelper
+ IRODSFileSystem irodsFileSystem
+
+
+ protected void setUp() {
+ super.setUp()
+ testingPropertiesHelper = new TestingPropertiesHelper()
+ testingProperties = testingPropertiesHelper.getTestProperties()
+ irodsAccount = testingPropertiesHelper.buildIRODSAccountFromTestProperties(testingProperties)
+ irodsFileSystem = IRODSFileSystem.instance()
+ irodsAccessObjectFactory = irodsFileSystem.getIRODSAccessObjectFactory()
+ def irodsAuthentication = new IRODSAuthenticationToken(irodsAccount)
+ SecurityContextHolder.getContext().authentication = irodsAuthentication
+ }
+
+ protected void tearDown() {
+ super.tearDown()
+ }
+
+ void testMetadataWhenCollection() {
+ def testPath = "/testpath"
+ def irodsAccessObjectFactory = Mockito.mock(IRODSAccessObjectFactory.class)
+ CollectionAndDataObjectListAndSearchAO collectionListAndSearchAO = Mockito.mock(CollectionAndDataObjectListAndSearchAO.class)
+ Collection retObject = new Collection()
+ retObject.setCollectionName(testPath)
+ Mockito.when(collectionListAndSearchAO.getFullObjectForType(testPath)).thenReturn(retObject)
+ Mockito.when(irodsAccessObjectFactory.getCollectionAndDataObjectListAndSearchAO(irodsAccount)).thenReturn(collectionListAndSearchAO)
+
+ CollectionAO collectionAO = Mockito.mock(CollectionAO.class)
+ List<MetaDataAndDomainData> mockMetadata = new ArrayList<MetaDataAndDomainData>();
+ Mockito.when(collectionAO.findMetadataValuesForCollection(testPath, 0)).thenReturn(mockMetadata);
+ Mockito.when(irodsAccessObjectFactory.getCollectionAO(irodsAccount)).thenReturn(collectionAO)
+
+ controller.irodsAccessObjectFactory = irodsAccessObjectFactory
+ controller.irodsAccount = irodsAccount
+ controller.params.absPath = testPath
+ controller.listMetadata()
+ def mav = controller.modelAndView
+ def name = mav.viewName
+
+ assertNotNull("null mav", mav)
+ assertEquals("view name should be metadataDetails", "metadataDetails", name)
+ def metadata = mav.model.metadata
+ assertNotNull("null metadata object", metadata)
+
+ }
+}
diff --git a/idrop-web/web-app/css/jqcloud.css b/idrop-web/web-app/css/jqcloud.css
new file mode 100644
index 0000000..85de347
--- /dev/null
+++ b/idrop-web/web-app/css/jqcloud.css
@@ -0,0 +1,59 @@
+div.jqcloud {
+ font-family: "Helvetica", "Arial", sans-serif;
+ color: #09f;
+ overflow: hidden;
+ position: relative;
+}
+div.jqcloud a {
+ color: inherit;
+ text-decoration: none;
+}
+div.jqcloud a:hover {
+ color: #0df;
+}
+div.jqcloud a:hover {
+ color: #0cf;
+}
+div.jqcloud span {
+ padding: 0;
+}
+div.jqcloud span.w10 {
+ font-size: 20px;
+ color: #15063A;
+}
+div.jqcloud span.w9 {
+ font-size: 19px;
+ color: #170F2C;
+}
+div.jqcloud span.w8 {
+ font-size: 18px;
+ color: #0C0226;
+}
+div.jqcloud span.w7 {
+ font-size: 17px;
+ color: #002810;
+}
+div.jqcloud span.w6 {
+ font-size: 16px;
+ color: #0B2E19;
+}
+div.jqcloud span.w5 {
+ font-size: 15px;
+ color: #370B00;
+}
+div.jqcloud span.w4 {
+ font-size: 14px;
+ color: #0C0226;
+}
+div.jqcloud span.w3 {
+ font-size: 13px;
+ color: #ffffff;
+}
+div.jqcloud span.w2 {
+ font-size: 12px;
+ color: #15063A;
+}
+div.jqcloud span.w1 {
+ font-size: 12px;
+ color: #170F2C;
+}
diff --git a/idrop-web/web-app/css/main.css b/idrop-web/web-app/css/main.css
index 324101b..29c16da 100644
--- a/idrop-web/web-app/css/main.css
+++ b/idrop-web/web-app/css/main.css
@@ -29,7 +29,7 @@ ul {
/* form styling */
div.box {
- background: none repeat scroll 0 0 #AABBC2;
+ background: none repeat scroll 0 0 #DDDDDD;
border: 1px solid #C6CFE1;
color: #333333;
margin-bottom: 20px;
@@ -142,7 +142,7 @@ div#tabs {
/* NAVIGATION MENU */
.nav {
- background: #A16A51 url(../images/skin/shadow.jpg) bottom repeat-x;
+ background: #244857 bottom repeat-x;
border: 1px solid #ccc;
border-style: solid none solid none;
margin-top: 5px;
@@ -226,12 +226,13 @@ table {
tr {
border: 0;
+ padding:8px;
}
td,th {
- font: 11px verdana, arial, helvetica, sans-serif;
- line-height: 12px;
- padding: 5px 6px;
+ font: 14px verdana, arial, helvetica, sans-serif;
+ line-height: 14px;
+ padding: 8px;
text-align: left;
vertical-align: top;
}
@@ -299,22 +300,48 @@ th.desc a {
padding: 2px 6px;
}
+#quickView {
+ background: none repeat scroll 0 0 #FFFFFF;
+ color: #333333;
+ margin-bottom: 3px;
+ padding: 3px;
+ width: auto;
+ height: auto;
+ display: block;
+ overflow: auto;
+}
/* object container */
.objectContainer {
- background: none repeat scroll 0 0 #B0BDC2;
- border-top: 1px solid #685A68;
+
color: #333333;
- margin-bottom: 20px;
- padding: 10px;
+
+ dislay: inline-block;
+ clear: both;
+
+ -moz-background-clip: border;
+ -moz-background-inline-policy: continuous;
+ -moz-background-origin: padding;
+ -moz-border-radius-bottomleft: 8pt;
+ -moz-border-radius-bottomright: 8pt;
+ -moz-border-radius-topleft: 8pt;
+ -moz-border-radius-topright: 8pt;
+ background: #FFFFFF none repeat scroll 0 0;
+ border: 3px solid #000000;
+ cursor: default;
+ padding: 3px;
+ margin: 3px;
+ display: inline-block;
+
+
+
}
.objectContainerGrouping {
- border-top: 1px solid #E9E9E9;
color: #999999;
font-weight: normal;
left: -5em;
padding-top: 9px;
- position: absolute;
+ position: relative;
text-align: left;
top: -1px;
width: 5em;
@@ -323,13 +350,16 @@ th.desc a {
.objectContainerDetails {
float: right;
text-align: left;
+ display:inline-block;
}
.objectHeader {
- color: #210021;
- font-weight: normal;
- font-size: 16px;
- margin: .8em 0 .3em 0;
+ display: block;
+ fload: left;
+ margin-bottom: 10px;
+ color: #555555;
+ margin-bottom: 10px;
+
}
.objectDescription {
@@ -345,6 +375,12 @@ th.desc a {
padding: 10px;
}
+.objectContainerTags {
+ display: block;
+ float: right;
+ padding: 10px;
+}
+
/* standard form layouts */
#columnarForm fieldset {
@@ -536,6 +572,12 @@ th.desc a {
display: block;
}
+/* details section */
+#detailsTopSection {
+ display: block;
+ clear: both;
+}
+
/* browser */
#browse {
background: #ffffff;
@@ -546,6 +588,21 @@ th.desc a {
height:95%;width:100%;margin:0;padding:0;
}
+#secondaryDiv {
+ height:400px;
+ display:inline-block;
+ //overflow:auto;
+}
+
+
+#tagCloudDiv {
+ height:400px;
+ display:inline-block;
+ width:100%;
+ overflow:auto;
+}
+
+
#dataTreeDiv{
float:left;
height:auto;
diff --git a/idrop-web/web-app/css/reset-fonts-grids.css b/idrop-web/web-app/css/reset-fonts-grids.css
index d0a32fc..ee45367 100644
--- a/idrop-web/web-app/css/reset-fonts-grids.css
+++ b/idrop-web/web-app/css/reset-fonts-grids.css
@@ -11,8 +11,8 @@ html {
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td
{
- margin: 0;
- padding: 0;
+ /*margin: 0;
+ padding: 0;*/
}
table {
diff --git a/idrop-web/web-app/js/jqcloud-0.1.5.min.js b/idrop-web/web-app/js/jqcloud-0.1.5.min.js
new file mode 100644
index 0000000..953f108
--- /dev/null
+++ b/idrop-web/web-app/js/jqcloud-0.1.5.min.js
@@ -0,0 +1,11 @@
+/*
+ * jQCloud Plugin for jQuery
+ *
+ * Version 0.1.5
+ *
+ * Copyright 2011, Luca Ongaro
+ * Licensed under the MIT license.
+ *
+ * Date: Tue Mar 1 11:09:37 +0100 2011
+ */
+(function(a){a.fn.jQCloud=function(c,f){var e=this;var d=e.attr("id");e.addClass("jqcloud");var b=function(){var h=function(p,n){var m=function(r,q){if(Math.abs(2*r.offsetLeft+r.offsetWidth-2*q.offsetLeft-q.offsetWidth)<r.offsetWidth+q.offsetWidth){if(Math.abs(2*r.offsetTop+r.offsetHeight-2*q.offsetTop-q.offsetHeight)<r.offsetHeight+q.offsetHeight){return true}}return false};var o=0;for(o=0;o<n.length;o++){if(m(p,n[o])){return true}}return false};c.sort(function(n,m){if(n.weight<m.weight){return 1}else{if(n.weight>m.weight){return -1}else{return 0}}});var j=2;var g=[];var i=e.width()/e.height();var l=e.width()/2;var k=e.height()/2;a.each(c,function(s,m){var q=d+"_word_"+s;var u="#"+q;var p=6.28*Math.random();var t=0;var r=Math.round((m.weight-c[c.length-1].weight)/(c[0].weight-c[c.length-1].weight)*9)+1;var x=m.url!==undefined?"<a href='"+m.url+"'>"+m.text+"</a></span>":m.text;e.append("<span id='"+q+"' class='w"+r+"' title='"+(m.title||"")+"'>"+x+"</span>");var n=a(u).width();var w=a(u).height();var o=l-n/2;var v=k-w/2;a(u).css("position","absolute");a(u).css("left",o+"px");a(u).css("top",v+"px");while(h(document.getElementById(q),g)){t+=j;p+=(s%2===0?1:-1)*j;o=l+(t*Math.cos(p)-(n/2))*i;v=k+t*Math.sin(p)-(w/2);a(u).css("left",o+"px");a(u).css("top",v+"px")}g.push(document.getElementById(q))});if(typeof f==="function"){f.call(this)}};setTimeout(function(){b()},100);return this}})(jQuery); \ No newline at end of file
diff --git a/idrop-web/web-app/js/jquery.jeditable.mini.js b/idrop-web/web-app/js/jquery.jeditable.mini.js
new file mode 100644
index 0000000..ef885f0
--- /dev/null
+++ b/idrop-web/web-app/js/jquery.jeditable.mini.js
@@ -0,0 +1,38 @@
+
+(function($){$.fn.editable=function(target,options){if('disable'==target){$(this).data('disabled.editable',true);return;}
+if('enable'==target){$(this).data('disabled.editable',false);return;}
+if('destroy'==target){$(this).unbind($(this).data('event.editable')).removeData('disabled.editable').removeData('event.editable');return;}
+var settings=$.extend({},$.fn.editable.defaults,{target:target},options);var plugin=$.editable.types[settings.type].plugin||function(){};var submit=$.editable.types[settings.type].submit||function(){};var buttons=$.editable.types[settings.type].buttons||$.editable.types['defaults'].buttons;var content=$.editable.types[settings.type].content||$.editable.types['defaults'].content;var element=$.editable.types[settings.type].element||$.editable.types['defaults'].element;var reset=$.editable.types[settings.type].reset||$.editable.types['defaults'].reset;var callback=settings.callback||function(){};var onedit=settings.onedit||function(){};var onsubmit=settings.onsubmit||function(){};var onreset=settings.onreset||function(){};var onerror=settings.onerror||reset;if(settings.tooltip){$(this).attr('title',settings.tooltip);}
+settings.autowidth='auto'==settings.width;settings.autoheight='auto'==settings.height;return this.each(function(){var self=this;var savedwidth=$(self).width();var savedheight=$(self).height();$(this).data('event.editable',settings.event);if(!$.trim($(this).html())){$(this).html(settings.placeholder);}
+$(this).bind(settings.event,function(e){if(true===$(this).data('disabled.editable')){return;}
+if(self.editing){return;}
+if(false===onedit.apply(this,[settings,self])){return;}
+e.preventDefault();e.stopPropagation();if(settings.tooltip){$(self).removeAttr('title');}
+if(0==$(self).width()){settings.width=savedwidth;settings.height=savedheight;}else{if(settings.width!='none'){settings.width=settings.autowidth?$(self).width():settings.width;}
+if(settings.height!='none'){settings.height=settings.autoheight?$(self).height():settings.height;}}
+if($(this).html().toLowerCase().replace(/(;|")/g,'')==settings.placeholder.toLowerCase().replace(/(;|")/g,'')){$(this).html('');}
+self.editing=true;self.revert=$(self).html();$(self).html('');var form=$('<form />');if(settings.cssclass){if('inherit'==settings.cssclass){form.attr('class',$(self).attr('class'));}else{form.attr('class',settings.cssclass);}}
+if(settings.style){if('inherit'==settings.style){form.attr('style',$(self).attr('style'));form.css('display',$(self).css('display'));}else{form.attr('style',settings.style);}}
+var input=element.apply(form,[settings,self]);var input_content;if(settings.loadurl){var t=setTimeout(function(){input.disabled=true;content.apply(form,[settings.loadtext,settings,self]);},100);var loaddata={};loaddata[settings.id]=self.id;if($.isFunction(settings.loaddata)){$.extend(loaddata,settings.loaddata.apply(self,[self.revert,settings]));}else{$.extend(loaddata,settings.loaddata);}
+$.ajax({type:settings.loadtype,url:settings.loadurl,data:loaddata,async:false,success:function(result){window.clearTimeout(t);input_content=result;input.disabled=false;}});}else if(settings.data){input_content=settings.data;if($.isFunction(settings.data)){input_content=settings.data.apply(self,[self.revert,settings]);}}else{input_content=self.revert;}
+content.apply(form,[input_content,settings,self]);input.attr('name',settings.name);buttons.apply(form,[settings,self]);$(self).append(form);plugin.apply(form,[settings,self]);$(':input:visible:enabled:first',form).focus();if(settings.select){input.select();}
+input.keydown(function(e){if(e.keyCode==27){e.preventDefault();reset.apply(form,[settings,self]);}});var t;if('cancel'==settings.onblur){input.blur(function(e){t=setTimeout(function(){reset.apply(form,[settings,self]);},500);});}else if('submit'==settings.onblur){input.blur(function(e){t=setTimeout(function(){form.submit();},200);});}else if($.isFunction(settings.onblur)){input.blur(function(e){settings.onblur.apply(self,[input.val(),settings]);});}else{input.blur(function(e){});}
+form.submit(function(e){if(t){clearTimeout(t);}
+e.preventDefault();if(false!==onsubmit.apply(form,[settings,self])){if(false!==submit.apply(form,[settings,self])){if($.isFunction(settings.target)){var str=settings.target.apply(self,[input.val(),settings]);$(self).html(str);self.editing=false;callback.apply(self,[self.innerHTML,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}}else{var submitdata={};submitdata[settings.name]=input.val();submitdata[settings.id]=self.id;if($.isFunction(settings.submitdata)){$.extend(submitdata,settings.submitdata.apply(self,[self.revert,settings]));}else{$.extend(submitdata,settings.submitdata);}
+if('PUT'==settings.method){submitdata['_method']='put';}
+$(self).html(settings.indicator);var ajaxoptions={type:'POST',data:submitdata,dataType:'html',url:settings.target,success:function(result,status){if(ajaxoptions.dataType=='html'){$(self).html(result);}
+self.editing=false;callback.apply(self,[result,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}},error:function(xhr,status,error){onerror.apply(form,[settings,self,xhr]);}};$.extend(ajaxoptions,settings.ajaxoptions);$.ajax(ajaxoptions);}}}
+$(self).attr('title',settings.tooltip);return false;});});this.reset=function(form){if(this.editing){if(false!==onreset.apply(form,[settings,self])){$(self).html(self.revert);self.editing=false;if(!$.trim($(self).html())){$(self).html(settings.placeholder);}
+if(settings.tooltip){$(self).attr('title',settings.tooltip);}}}};});};$.editable={types:{defaults:{element:function(settings,original){var input=$('<input type="hidden"></input>');$(this).append(input);return(input);},content:function(string,settings,original){$(':input:first',this).val(string);},reset:function(settings,original){original.reset(this);},buttons:function(settings,original){var form=this;if(settings.submit){if(settings.submit.match(/>$/)){var submit=$(settings.submit).click(function(){if(submit.attr("type")!="submit"){form.submit();}});}else{var submit=$('<button type="submit" />');submit.html(settings.submit);}
+$(this).append(submit);}
+if(settings.cancel){if(settings.cancel.match(/>$/)){var cancel=$(settings.cancel);}else{var cancel=$('<button type="cancel" />');cancel.html(settings.cancel);}
+$(this).append(cancel);$(cancel).click(function(event){if($.isFunction($.editable.types[settings.type].reset)){var reset=$.editable.types[settings.type].reset;}else{var reset=$.editable.types['defaults'].reset;}
+reset.apply(form,[settings,original]);return false;});}}},text:{element:function(settings,original){var input=$('<input />');if(settings.width!='none'){input.width(settings.width);}
+if(settings.height!='none'){input.height(settings.height);}
+input.attr('autocomplete','off');$(this).append(input);return(input);}},textarea:{element:function(settings,original){var textarea=$('<textarea />');if(settings.rows){textarea.attr('rows',settings.rows);}else if(settings.height!="none"){textarea.height(settings.height);}
+if(settings.cols){textarea.attr('cols',settings.cols);}else if(settings.width!="none"){textarea.width(settings.width);}
+$(this).append(textarea);return(textarea);}},select:{element:function(settings,original){var select=$('<select />');$(this).append(select);return(select);},content:function(data,settings,original){if(String==data.constructor){eval('var json = '+data);}else{var json=data;}
+for(var key in json){if(!json.hasOwnProperty(key)){continue;}
+if('selected'==key){continue;}
+var option=$('<option />').val(key).append(json[key]);$('select',this).append(option);}
+$('select',this).children().each(function(){if($(this).val()==json['selected']||$(this).text()==$.trim(original.revert)){$(this).attr('selected','selected');}});}}},addInputType:function(name,input){$.editable.types[name]=input;}};$.fn.editable.defaults={name:'value',id:'id',type:'text',width:'auto',height:'auto',event:'click.editable',onblur:'cancel',loadtype:'GET',loadtext:'Loading...',placeholder:'Click to edit',loaddata:{},submitdata:{},ajaxoptions:{}};})(jQuery); \ No newline at end of file
diff --git a/idrop-web/web-app/js/mydrop/home.js b/idrop-web/web-app/js/mydrop/home.js
index 60a47dc..a3a9f3d 100644
--- a/idrop-web/web-app/js/mydrop/home.js
+++ b/idrop-web/web-app/js/mydrop/home.js
@@ -8,6 +8,7 @@
* Global var holds jquery ref to the dataTree
*/
var dataTree;
+var browseOptionVal = "info";
/**
* Initialize the tree control for the first view by issuing an ajax directory
@@ -21,14 +22,13 @@ function retrieveBrowserFirstView() {
lcSendValueAndCallbackWithJsonAfterErrorCheck(url, "dir=/",
"#dataTreeDiv", browserFirstViewRetrieved);
} else {
-
+
}
}
/**
- * FIXME: intercept timeouts here?
- * Callback to initialize a browser tree for the first time, set to the root
- * node as indicated in the data
+ * FIXME: intercept timeouts here? Callback to initialize a browser tree for the
+ * first time, set to the root node as indicated in the data
*
* @param data
* ajax response from browse controller containing the JSON
@@ -70,6 +70,10 @@ function browserFirstViewRetrieved(data) {
}
},
+ "ui" : {
+ "select_limit" : 1,
+ "initially_select" : [ "phtml_2" ]
+ },
"themes" : {
"theme" : "default",
@@ -106,23 +110,63 @@ function nodeSelected(event, data) {
// given the path, put in the node data
var id = data[0].id;
- lcSendValueAndCallbackHtmlAfterErrorCheck("/browse/fileInfo?absPath=" + id,
- "#infoDiv", "#infoDiv", null);
+ updateBrowseDetailsForPathBasedOnCurrentModel(id);
}
+
+
/**
* Linked to update tags button on info view, update the tags in iRODS
*/
function updateTags() {
var infoTagsVal = $("#infoTags").val();
var absPathVal = $("#infoAbsPath").val();
+
var params = {
absPath : absPathVal,
tags : infoTagsVal
}
+
lcSendValueViaPostAndCallbackHtmlAfterErrorCheck("/tags/updateTags",
params, "#infoUpdateArea", "#infoUpdateArea", function() {
$("#infoUpdateArea").html("Tags updated");
});
}
+
+/**
+ * On selection of a browser mode (from the top bar of the browse view), set the option such that selected directories in the
+ * tree result in the given view in the right hand pane
+ */
+function setBrowseMode() {
+ browseOptionVal = $("#browseDisplayOption").val();
+}
+
+/**
+ * Upon selection of a collection or data object from the tree, display the content on the right-hand side. The type of
+ * detail shown is contingent on the 'browseOption' that is set in the drop-down above the browse area.
+ */
+function updateBrowseDetailsForPathBasedOnCurrentModel(absPath) {
+
+
+ if (browseOptionVal === null) {
+ browseOptionVal = "info";
+ }
+
+ if (browseOptionVal == "details") {
+
+ lcSendValueAndCallbackHtmlAfterErrorCheck(
+ "/browse/displayBrowseGridDetails?absPath=" + absPath, "#infoDiv",
+ "#infoDiv", null);
+ } else if (browseOptionVal == "info") {
+ lcSendValueAndCallbackHtmlAfterErrorCheck(
+ "/browse/fileInfo?absPath=" + absPath, "#infoDiv",
+ "#infoDiv", null);
+ } else if (browseOptionVal == "metadata") {
+ lcSendValueAndCallbackHtmlAfterErrorCheck(
+ "/metadata/listMetadata?absPath=" + absPath, "#infoDiv",
+ "#infoDiv", null);
+ }
+}
+
+
diff --git a/idrop-web/web-app/js/mydrop/lingo_common.js b/idrop-web/web-app/js/mydrop/lingo_common.js
index 4575182..d84b24c 100644
--- a/idrop-web/web-app/js/mydrop/lingo_common.js
+++ b/idrop-web/web-app/js/mydrop/lingo_common.js
@@ -196,18 +196,44 @@ function lcSendValueAndBuildTable(getUrl, params, tableDiv, newTableId, detailsF
* the table if detail icons are to be setup @return - DataTable that was
* created
*/
-function lcBuildTable(data, tableDiv, newTableId, detailsFunction) {
+function lcBuildTable(data, tableDiv, newTableId, detailsFunction, dataIconSelector) {
$(tableDiv).html(data);
var dataTableCreated = $(newTableId).dataTable({
"bJQueryUI": true
});
if (detailsFunction != null) {
- $('.detail_icon', dataTableCreated.fnGetNodes()).each(detailsFunction);
+ $(dataIconSelector, dataTableCreated.fnGetNodes()).each(detailsFunction);
}
}
+
+/**
+ * Given a table structure in an existing DOM, build a table based on a JQuery selector,
+ * assigning it a function that can be called when a given selector is clicked. This is
+ * useful for cases where tables are expanded based on click
+ * @param newTableId
+ * @param detailsFunction
+ * @param dataIconSelector
+ */
+function lcBuildTableInPlace(newTableId, detailsFunction, dataIconSelector) {
+ var dataTableCreated = $(newTableId).dataTable({"bJQueryUI": true});
+
+ if (detailsFunction != null) {
+ $(dataIconSelector, dataTableCreated.fnGetNodes()).each(function() {
+ $(this).click(function() {
+ detailsFunction(this);
+ });
+ });
+
+ }
+
+ return dataTableCreated;
+
+}
+
+
/**
* Close table nodes when using +/- details icon
* @param dataTable - reference to jquery dataTable (not a selector, the table)
@@ -277,7 +303,7 @@ function lcSendValueAndPlugHtmlInDiv(getUrl, resultDiv, context,
/**
* Send a query via ajax that results in html plugged into the correct div
*/
-function lcSendValueWithParamsAndPlugHtmlInDiv(getUrl, params, resultDiv, context,
+function lcSendValueWithParamsAndPlugHtmlInDiv(getUrl, params, resultDiv,
postLoadFunction) {
prepareForCall();
@@ -286,13 +312,13 @@ function lcSendValueWithParamsAndPlugHtmlInDiv(getUrl, params, resultDiv, contex
}
var img = document.createElement('IMG');
- img.setAttribute("src", +context + "/images/ajax-loader.gif");
+ img.setAttribute("src", context + "/images/ajax-loader.gif");
$(resultDiv).html(img);
try {
- $.get(getUrl, params, function(data, status, xhr) {
+ $.get(context + getUrl, params, function(data, status, xhr) {
checkForSessionTimeout(data, xhr);
lcFillInDivWithHtml(data, resultDiv, postLoadFunction);
}, "html");