Browse Source

Merged data collections with the file management

Stephen Ficklin 6 years ago
parent
commit
f81aec1b59

+ 4 - 2
tripal/api/tripal.collections.api.inc

@@ -54,11 +54,13 @@ function tripal_create_collection($details) {
     $collection_id = $collection->getCollectionID();
     $collection->addBundle($details);
 
-    drupal_set_message(t("Collection '%name' created with %num_recs record(s). Check the !view to generate file links.",
+    
+    
+    drupal_set_message(t("Collection '%name' created with %num_recs record(s). Files for this collection are not yet created.  To generate files, check the !view.",
       array(
         '%name' => $details['collection_name'],
         '%num_recs' => count($details['ids']),
-        '!view' => l('data collections page', 'user/' . $user->uid . '/data-collections'),
+        '!view' => l('files page', 'user/' . $user->uid . '/files'),
       ))
     );
     return $collection;

+ 2 - 2
tripal/api/tripal.quotas.api.inc

@@ -114,7 +114,7 @@ function tripal_expire_files(TripalJob $job = NULL) {
  *   The file ID of the file to reset.
  *   
  * @return
- *   TRUE on success, FALSE on failure.
+ *   The new expiration date on success, FALSE on failure.
  */
 function tripal_reset_file_expiration($fid) {
   
@@ -138,5 +138,5 @@ function tripal_reset_file_expiration($fid) {
     tripal_report_error('trp_quota', TRIPAL_ERROR, $e->getMessage());
     return FALSE;
   }
-  return TRUE;
+  return $expiration_date;
 }

+ 2 - 1
tripal/includes/TripalEntityCollection.inc

@@ -463,9 +463,10 @@ class TripalEntityCollection {
     }
 
     $outfile = $this->getOutfile($formatter);
+    
     // Make sure the user directory exists
     $user_dir = 'public://tripal/users/' . $this->user->uid;
-    $outfilePath = $user_dir. '/' . $outfile;
+    $outfilePath = $user_dir. '/data_collections/' . $outfile;
     return $outfilePath;
   }
 

+ 1 - 1
tripal/includes/TripalFieldDownloaders/TripalCSVDownloader.inc

@@ -54,7 +54,7 @@ class TripalCSVDownloader extends TripalFieldDownloader {
       $field_name = $field['field_name'];
 
       // If we only have one item for this value then add it.
-      if (count($entity->{$field_name}['und']) == 1) {
+      if (is_array($entity->{$field_name}['und']) and count($entity->{$field_name}['und']) == 1) {
         $value = $entity->{$field_name}['und'][0]['value'];
 
         // If the single element is not an array then this is good.

+ 18 - 15
tripal/includes/TripalFieldDownloaders/TripalFieldDownloader.inc

@@ -143,11 +143,22 @@ abstract class TripalFieldDownloader {
 
     // Make sure the user directory exists
     $user = user_load($this->collection->uid);
-    $user_dir = 'public://tripal/users/' . $user->uid;
+    $user_dir = tripal_get_user_files_dir($user);
+    if (!tripal_is_user_files_dir_writeable($user)) {
+      throw new Exception(t("The user's data directory is not writeable: !user_dir.", array('!user_dir' => $user_dir)));
+    }
 
     // Set the collection ID of the collection that this downloader will use.
     $this->collection_id = $collection_id;
-    $this->outfile = $user_dir . '/' . $outfile_name;
+    
+    // Make sure the data_collections directory exists.
+    $collections_dir = $user_dir . '/data_collections';
+    if (!file_exists($collections_dir)) {
+      if (!file_prepare_directory($collections_dir, [FILE_CREATE_DIRECTORY])) {
+        throw new Exception(t("The data_collection directory cannot be created: !collections_dir.", array('!collections_dir' => $collections_dir)));
+      }
+    }
+    $this->outfile = $collections_dir . '/' . $outfile_name;
 
     // A data collection may have multiple bundles.  We'll need to get
     // them all and store them.
@@ -161,11 +172,6 @@ abstract class TripalFieldDownloader {
       $this->collection_bundles[] = $collection_bundle;
     }
  
-    $user_dir = tripal_get_user_files_dir($user);
-    if (!tripal_is_user_files_dir_writeable($user)) {
-      throw new Exception(t("The user's data directory is not writeable: !user_dir.", array('!user_dir' => $user_dir)));
-    }
-
     // Map the fields to their term accessions.
     $this->setFields();
     $this->setFields2Terms();
@@ -294,15 +300,12 @@ abstract class TripalFieldDownloader {
       $fid = $file->fid;
       $file = file_load($fid);
     }
-
-    // We use the fid for the last argument because these files
-    // aren't really associated with any entity, but we need a value./
-    // But, only add the usage if it doens't already exists.
+    
+    // Associate this file with data collections if it isn't already
     $usage = file_usage_list($file);
-    if (array_key_exists('tripal', $usage)) {
-      if (!array_key_exists('data-collection', $usage['tripal'])) {
-        file_usage_add($file, 'tripal', 'data-collection', $fid);
-      }
+    if (!array_key_exists('tripal', $usage) or 
+        !array_key_exists('data_collection', $usage['tripal'])) {
+      file_usage_add($file, 'tripal', 'data_collection', $this->collection_id);
     }
   }
 

+ 1 - 1
tripal/includes/TripalFieldDownloaders/TripalTabDownloader.inc

@@ -54,7 +54,7 @@ class TripalTabDownloader extends TripalFieldDownloader {
        $field_name = $field['field_name'];
 
        // If we only have one item for this value then add it.
-       if (count($entity->{$field_name}['und']) == 1) {
+       if (is_array($entity->{$field_name}['und']) and count($entity->{$field_name}['und']) == 1) {
          $value = $entity->{$field_name}['und'][0]['value'];
 
          // If the single element is not an array then this is good.

+ 3 - 0
tripal/includes/TripalFieldQuery.inc

@@ -121,6 +121,9 @@ class TripalFieldQuery extends EntityFieldQuery {
     }
 
     if ($this->count == TRUE) {
+      if (is_numeric($results)) {
+        return $results;
+      }
       return count($results['TripalEntity']);
     }
     return $results;

+ 7 - 92
tripal/includes/tripal.collections.inc

@@ -1,85 +1,6 @@
 <?php
 
 
-/**
- *
- */
-function tripal_user_collections_page() {
-  global $user;
-
-  $headers = array('Name', 'Description', 'Create Date', 'Download Formats',
-    'Generate File', 'Actions');
-  $rows = array();
-
-  $collections = db_select('tripal_collection', 'tc')
-    ->fields('tc', array('collection_id'))
-    ->condition('uid', $user->uid)
-    ->orderBy('tc.collection_name')
-    ->execute();
-
-  while ($collection_id = $collections->fetchField()) {
-    $collection = new TripalEntityCollection();
-    $collection->load($collection_id);
-
-    $downloads = array();
-    $formatters = $collection->getFormatters();
-
-    foreach ($formatters as $class_name => $label) {
-
-      $outfile = $collection->getOutfilePath($class_name);
-
-      if (file_exists($outfile)) {
-        $outfileURL = file_create_url($outfile);
-        $downloads[] = l($label, $outfileURL);
-      }
-      else {
-        $downloads[] = 'Waiting on ' . $label . '...';
-      }
-    }
-    $download_list = theme_item_list(array(
-      'items' => $downloads,
-      'title' => '',
-      'type' => 'ul',
-      'attributes' => array(),
-    ));
-
-    $rows[] = array(
-      'data' => array(
-        $collection->getName(),
-        $collection->getDescription(),
-        $collection->getCreateDate(),
-        $download_list,
-        l('Generate File for Download', 'user/' . $user->uid . '/data-collections/generate/' . $collection_id),
-        l('View', 'user/' . $user->uid . '/data-collections/' . $collection_id . '/view') . ' ' .
-        l('Delete', 'user/' . $user->uid . '/data-collections/' . $collection_id . '/delete'),
-      ),
-    );
-  }
-
-  $content['instructions'] = array(
-    '#type' => 'markup',
-    '#markup' => '<p>' .  t('Data collections allow you to store sets of data
-       for download or later use by other tools on this site.  Typically data
-       collections are created using search tools.  The following data
-       collections are available to you.  Some files take time to generate
-       before they can be downloaded.') . '</p>',
-  );
-  $content['files_table'] = array(
-    '#type' => 'item',
-    '#title' => 'Data Collections',
-    '#markup' => theme_table(array(
-      'header' => $headers,
-      'rows' => $rows,
-      'attributes' => array(),
-      'caption' => '',
-      'colgroups' => array(),
-      'sticky' => TRUE,
-      'empty' => t('You currently have no data collections.')
-    )),
-  );
-
-  return $content;
-}
 
 /**
  * Renders a view of a data collection
@@ -91,7 +12,7 @@ function tripal_user_collections_view_page($uid, $collection_id) {
   $breadcrumb = array();
   $breadcrumb[] = l('Home', '<front>');
   $breadcrumb[] = l($user->name, 'user/' . $uid);
-  $breadcrumb[] = l('Data Collections', 'user/' . $uid . '/data-collections');
+  $breadcrumb[] = l('Files', 'user/' . $uid . '/files');
   drupal_set_breadcrumb($breadcrumb);
 
   $collection = new TripalEntityCollection();
@@ -161,13 +82,6 @@ function tripal_user_collections_view_page($uid, $collection_id) {
     '#markup' => number_format($num_entities),
   );
 
-  $contents['peek'] = array(
-    '#type' => 'item',
-    '#title' => 'Data View',
-    '#markup' => 'Coming soon...',
-  );
-
-
   return $contents;
 }
 /**
@@ -182,7 +96,7 @@ function tripal_user_collections_delete_form($form, &$form_state,  $uid, $collec
 
   $form = confirm_form($form,
       t('Click the delete button below to confirm deletion of the collection titled: %title',
-          array('%title' => $collection->getName())), 'user/' . $uid . '/data-collections',
+          array('%title' => $collection->getName())), 'user/' . $uid . '/files',
       '<p>' .t('This action cannot be undone.') .'</p>', t('Delete'), t('Cancel'), 'confirm');
 
   return $form;
@@ -206,10 +120,11 @@ function tripal_user_collections_delete_form_submit($form, &$form_state) {
     }
     catch (Exception $e) {
       drupal_set_message(t('There was a problem deleting the data collection ' .
-          'please contact the site to report the error: !message', array('!message', $e->getMessage())), 'error');
+        'please contact the site to report the error: !message', 
+        array('!message'=> $e->getMessage())), 'error');
     }
   }
-  drupal_goto('user/' . $user->uid . '/data-collections');
+  drupal_goto('user/' . $user->uid . '/files');
 }
 
 function tripal_user_collections_generate_file_form($form, &$form_state,  $uid, $collection_id) {
@@ -220,7 +135,7 @@ function tripal_user_collections_generate_file_form($form, &$form_state,  $uid,
   $collection->load($collection_id);
   $form = confirm_form($form,
       t('Confirm creation of files for the data collection named: "%title"',
-          array('%title' => $collection->getName())), 'user/' . $uid . '/data-collections',
+          array('%title' => $collection->getName())), 'user/' . $uid . '/files',
       '<p>' .t('It may take some time for the file(s) to be generated.  An email will be sent when files are ready.') .'</p>', t('Generate File'), t('Cancel'), 'confirm');
 
   return $form;
@@ -249,5 +164,5 @@ function tripal_user_collections_generate_file_form_submit($form, &$form_state)
     }
   }
 
-  drupal_goto('user/' . $user->uid . '/data-collections');
+  drupal_goto('user/' . $user->uid . '/files');
 }

+ 348 - 73
tripal/includes/tripal.user.inc

@@ -1,53 +1,211 @@
 <?php
 
 
-/**
- * Provides the page with a list of files uploaded by the user.
- *
- * @param $uid
- *   The user ID.
- *
- * @return
- *   A Drupal render array.
- */
- function tripal_user_files_page($uid) {
-
-   // Get all of the files that have been uploaded by the user.
-   // TODO: we should make this a paged query in case a user has a huge
-   // numbef of uploaded files.
-   $sql = "
-     SELECT FM.fid, FM.filename, TGEF.expiration_date
+function tripal_user_get_files($uid){
+  $directory = [];
+  
+  // Get all of the files that have been uploaded by the user.
+  $sql = "
+     SELECT FM.fid, FM.filename, FM.uri, FM.uid, FM.filesize, TGEF.expiration_date
      FROM {file_managed} FM
        INNER JOIN {file_usage} FU on FM.fid = FU.fid and FM.uid = :user_id
        LEFT JOIN {tripal_expiration_files} TGEF on TGEF.fid = FU.fid
      WHERE FU.module = 'tripal'
      ORDER BY FM.filename
    ";
-   $files = db_query($sql, array(':user_id' => $uid));
-   $rows = array();
-   While ($entry = $files->fetchObject()) {
-    $file = file_load($entry->fid);
-
+  $files = db_query($sql, array(':user_id' => $uid));
+  $rows = array();
+  While ($file = $files->fetchObject()) {
+    
     // Don't list files that don't exist on the file system.
     if (!file_exists($file->uri)) {
       continue;
     }
+    
+    // Files have to be in the User's directory.
+    if (!preg_match('/^public:\/\/tripal\/users\//', $file->uri)) {
+      continue;
+    }
+    
+    // If the expiration date is somehow not set, then set it.
+    if (!$file->expiration_date) {
+      $file->expiration_date = tripal_reset_file_expiration($file->fid);
+    }
+    
+    // Organize the file into it's directory structure.
+    $rpath = preg_replace('/^public:\/\/tripal\/users\/'. $uid . '\//', '', $file->uri); 
+    $paths = explode('/', $rpath);
+    _tripal_user_build_files_dir($directory, $paths, $file); 
+  }
+  
+  return $directory;
+}
+
+/** 
+ * A recursive helper function for building the directory file tree.
+ * 
+ * @param $directory
+ *   The $directory array into which the file will be placed.
+ * @param $paths
+ *   An containing the directory path of the file. Each Directory
+ *   is a separate element of the array.
+ * @param $file
+ *   The file object to add to the $directory object.
+ */
+function _tripal_user_build_files_dir(&$directory, $paths, $file) {
+  $path = array_shift($paths);
+  if (count($paths) == 0) {
+    $directory[$path] = $file;
+  }
+  else {
+    _tripal_user_build_files_dir($directory[$path], $paths, $file);
+  }
+}
 
-    $date_uploaded = date('Y-m-d H:i:s', $file->timestamp);
-    $expiration = $entry->expiration_date ? date('Y-m-d H:i:s', $entry->expiration_date) : '';
-    $actions = l('Delete', "user/$uid/files/$file->fid/delete") . ' | ' .
-               l('Renew', "user/$uid/files/$file->fid/renew");
+/** 
+ * Generates an item list of the files.
+ * 
+ * The results from this function can be passed to the theme_item_list function
+ * and then themed as a file tree..
+ * 
+ * @param $files_list
+ *   The array as returned by tripal_user_get_files().
+ * 
+ * @return 
+ *   An item list.
+ */
+function tripal_user_get_files_item_list($files_list, &$i = 0) {
+  $items = [];
+  
+  // Add a header row
+  if ($i == 0) {
+    $items[] = [
+      'data' => '<span><b>File</b></span>' .
+      '<span class="file-expires"><b>Expires</b></span>' .
+      '<span class="file-size"><b>Size</b></span>' ,
+    ];
+  }
+  
+  // Iterate through each file and recursively add it to our items array.
+  foreach ($files_list as $filename => $file) {
+    $i++;
+    // If this is a folder then recurse.
+    if (is_array($file)) {
+      $items[] = [
+        'data' => $filename,
+        'children' => tripal_user_get_files_item_list($file, $i),
+        'class' => ['tree-node-folder', 'tree-node-closed', ($i % 2 == 0) ? 'even' : 'odd'],
+      ];
+    }
+    // If this is a file then give details for it.
+    else {
+      $datediff = $file->expiration_date - time();
+      $dayleft = round($datediff / (60 * 60 * 24));
+      if ($dayleft < 0) {
+        $dayleft = 0;
+      }
+      $expiration = $file->expiration_date ? date('Y-m-d', $file->expiration_date) : '';
+      $items[] = [
+        'data' => '<span class="file-name">' . $filename . '</span>' . 
+          '<span class="file-expires">' . $dayleft . ' days</span>' . 
+          '<span class="file-size">' . tripal_format_bytes($file->filesize) . '</span>' ,
+        'class' => ['tree-node-file', ($i % 2 == 0) ? 'even' : 'odd'],
+        'fid' => $file->fid,
+        'uid' => $file->uid,
+      ];
+    }
+  }
+  
+  return $items;
+}
 
-    $rows[] = array(
-      $entry->fid,
-      l($file->filename,"/user/$uid/files/$file->fid"),
-      $date_uploaded,
-      $expiration,
-      tripal_format_bytes($file->filesize),
-      $actions,
-    );
+/**
+ * Gets the list of collections that have not yet generated files.
+ * 
+ * @param $uid
+ *   The ID of the user.
+ */
+function tripal_user_files_get_pending_collections_table($uid) {
+  
+  $collections = db_select('tripal_collection', 'tc')
+    ->fields('tc', array('collection_id'))
+    ->condition('uid', $uid)
+    ->orderBy('tc.collection_name')
+    ->execute();
+
+  $headers = array('Name', 'Download Formats', 'Actions');
+  $rows = array();
+  
+  while ($collection_id = $collections->fetchField()) {
+    $collection = new TripalEntityCollection();
+    $collection->load($collection_id);
+    
+    $downloads = array();
+    $formatters = $collection->getFormatters();
+    $formatter_labels = [];
+    
+    $status = 'complete';
+    foreach ($formatters as $class_name => $label) {
+      $formatter_labels[] = $label;
+      
+      $outfile = $collection->getOutfilePath($class_name);
+      
+      if (file_exists($outfile)) {
+        continue;
+      }
+      else {
+        $status = 'pending';
+      }
+    }
+    
+    if ($status == 'pending') {    
+      $rows[] = array(
+        'data' => array(
+          $collection->getName(),
+          implode(', ', $formatters),
+          l('Create Files', 'user/' . $uid . '/data-collections/generate/' . $collection_id) . ' | ' .
+          l('View', 'user/' . $uid . '/data-collections/' . $collection_id . '/view') . ' | ' .
+          l('Delete', 'user/' . $uid . '/data-collections/' . $collection_id . '/delete'),
+        ),
+      );
+    }
   }
-  $header = array('ID', 'File Name', 'Upload Date', 'Expiration', 'Size', 'Actions');
+  return theme_table(array(
+      'header' => $headers,
+      'rows' => $rows,
+      'attributes' => array(),
+      'caption' => '',
+      'colgroups' => array(),
+      'sticky' => TRUE,
+      'empty' => t('You currently have no pending data collections.')
+    ));
+}
+/**
+ * Provides the page with a list of files uploaded by the user.
+ *
+ * @param $uid
+ *   The user ID.
+ *
+ * @return
+ *   A Drupal render array.
+ */
+ function tripal_user_files_page($uid) {
+
+  drupal_add_css(drupal_get_path('module', 'tripal') . '/theme/css/tripal_user_files.css');
+  drupal_add_js(drupal_get_path('module', 'tripal') . '/theme/js/tripal.user_files.js', 'file');
+   
+  $user_files = tripal_user_get_files($uid);
+  $items = tripal_user_get_files_item_list($user_files);  
+  $theme_files = theme_item_list([
+    'items' => $items,
+    'title' => '',
+    'type' => 'ul',
+    'attributes' => [
+      'id' => 'tripal-user-file-tree'
+    ],
+  ]);
+   
+  $data_collections = tripal_user_files_get_pending_collections_table($uid);
 
   // Get the user quota settings.
   $quota = tripal_get_user_quota($uid);
@@ -56,11 +214,11 @@
   $content = array(
     'page_title' => array(
       '#type' => 'markup',
-      '#markup' => '<h2>Your Uploaded Files</h2>',
+      '#markup' => '<h2>Your Files</h2>',
     ),
     'page_description' => array(
       '#type' => 'markup',
-      '#markup' => '<p>' . t('Each user is allowed to consume a limited amount of space with uploaded files. This page provides details about your current usage, your limits and files you\'ve uploaded.') . '</p>',
+      '#markup' => '<p>' . t('Each user is allowed to consume a limited amount of space for files. This page provides details about your current usage, your limits and files in your account.') . '</p>',
     ),
     'usage' => array(
       '#type' => 'item',
@@ -78,20 +236,26 @@
       '#type' => 'item',
       '#title' => 'Current Days to Expire',
       '#markup' => $quota->custom_expiration,
-      '#description' => t('The number of days a file will remain on the server before deletion. The expiration of date of a file can be renewed using the "Renew" link in the table below.')
+      '#description' => t('The number of days a file will remain on the server before deletion. The expiration of date of a file can be renewed by selecting the file name and then selecting the "Renew" link in the file details table.')
+    ),
+    'data_collections' => array(
+      '#type' => 'item',
+      '#title' => 'Pending Data Collections',
+      '#markup' => $data_collections,
+      '#description' =>  t('Data collections allow you to store custom sets of data
+       for use on this site.  Typically data collections are created using search 
+       tools.  The above data collections are waiting to be generated. You must
+       generate the files before you can use them.'),
     ),
     'file_list' => array(
       '#type' => 'item',
-      '#title' => 'Uploaded Files',
-      '#markup' => theme_table(array(
-        'header' => $header,
-        'rows' => $rows,
-        'attributes' => array(),
-        'caption' => t('Click a file name for more details.'),
-        'colgroups' => array(),
-        'sticky' => TRUE,
-        'empty' => 'You currently have no uploaded files.',
-      )),
+      '#title' => 'File Browser',
+      '#markup' => $theme_files,
+    ),
+    'file_details' => array(
+      '#type' => 'item',
+      '#title' => 'File Details',
+      '#markup' => '<div id="tripal-user-file-details">Click a file above for details.</div>',
     )
   );
 
@@ -211,12 +375,59 @@ function tripal_delete_file_form_submit($form, &$form_state) {
  */
 function tripal_view_file($uid, $fid) {
   $file = file_load($fid);
+  $usage = file_usage_list($file);
+  
+  // Check to see if this is a data collection.  
+  $collection = NULL;
+  $collection_ctypes = [];
+  $collection_field_list = [];
+  $collection_formatters = [];
+  $collection_entities = 0;
+  if (array_key_exists('tripal', $usage)) {
+    if (array_key_exists('data_collection', $usage['tripal'])) {
+      $collection_id = array_keys($usage['tripal']['data_collection'])[0];
+      $collection = new TripalEntityCollection();
+      $collection->load($collection_id);
+      
+      // Get the content types for this data collection.
+      $cbundles = $collection->getBundles();     
+      foreach ($cbundles as $cbundle) {
+        $eids = $collection->getEntityIDs($cbundle->bundle_name);
+        $fields = $collection->getFieldIDs($cbundle->bundle_name);
+        
+        // Convert local field IDs to their names.
+        if (!$cbundle->site_id) {
+          $bundle = tripal_load_bundle_entity(array('name' => $cbundle->bundle_name));
+          $collection_ctypes[] = $bundle->label;
+          
+          foreach ($fields as $field_id) {
+            $field = field_info_field_by_id($field_id);
+            $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle->name);
+            $collection_field_list[] = $instance['label'];
+            
+            $field_formatters = tripal_get_field_field_formatters($field, $instance);
+            foreach ($field_formatters as $class_name => $label) {
+              tripal_load_include_downloader_class($class_name);
+              $collection_formatters[] = $class_name::$label . ' (' . $class_name::$full_label . ')';
+            }
+          }
+        }
+        // Convert remote field IDs to their names.
+        // TODO: add in retrieval of remote details.
+        
+        
+        $collection_entities += count($eids);
+      }
+      
+    }
+  }
 
   $headers = array();
   $rows = array();
 
   $actions = l('Delete', "user/$uid/files/$file->fid/delete") . '<br>' .
-             l('Download', "user/$uid/files/$file->fid/download");
+             l('Download', "user/$uid/files/$file->fid/download") . '<br>' .
+             l('Renew', "user/$uid/files/$file->fid/renew");
 
   // Name row
   $rows[] = array(
@@ -231,7 +442,7 @@ function tripal_view_file($uid, $fid) {
   $date_uploaded = date('Y-m-d H:i:s', $file->timestamp);
   $rows[] = array(
     array(
-      'data' => 'Upload Date',
+      'data' => 'Create Date',
       'header' => TRUE,
       'width' => '20%',
     ),
@@ -252,7 +463,18 @@ function tripal_view_file($uid, $fid) {
     ),
     $expiration
   );
-
+  
+  $md5_file = $file->uri . '.md5';
+  if (file_exists($md5_file)) {
+    $rows[] = array(
+      array(
+        'data' => 'MD5',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      file_get_contents($md5_file),
+    );
+  } 
   $rows[] = array(
     array(
       'data' => 'Actions',
@@ -262,29 +484,82 @@ function tripal_view_file($uid, $fid) {
     $actions
   );
 
-  $content = array(
-    'description' => array(
-      '#type' => 'markup',
-      '#markup' => '<p>' . t('The following file has been uploaded.') . '</p>',
-    ),
-    'return' => array(
-      '#type' => 'markup',
-      '#markup' => '<p>' . l('View all Uploaded Files', "user/$uid/files") . '</p>',
-    ),
-    'file_details' => array(
-      '#type' => 'markup',
-      '#markup' => theme_table(array(
-        'header' => $headers,
-        'rows' => $rows,
-        'attributes' => array(),
-        'sticky' => FALSE,
-        'caption' => '',
-        'colgroups' => array(),
-        'empty' => '',
-      )),
-    ),
-  );
-  return $content;
+  $file_content = theme_table([
+    'header' => $headers,
+    'rows' => $rows,
+    'attributes' => [],
+    'sticky' => FALSE,
+    'caption' => '',
+    'colgroups' => [],
+    'empty' => '',
+  ]);
+  
+  
+  $collection_content = '';
+  if ($collection) {
+    $rows = [];
+    $rows[] = array(
+      array(
+        'data' => 'Description',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      $collection->getDescription(),
+    );
+    $rows[] = array(
+      array(
+        'data' => 'Content types',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      join(', ', $collection_ctypes),
+    );
+    
+    $rows[] = array(
+      array(
+        'data' => 'Fields',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      join(', ', array_unique($collection_field_list)),
+    );
+    $rows[] = array(
+      array(
+        'data' => 'Supported File Types',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      join(', ', array_unique($collection_formatters)),
+    );
+    $rows[] = array(
+      array(
+        'data' => 'Records',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      number_format($collection_entities),
+    );
+    $rows[] = array(
+      array(
+        'data' => 'Actions',
+        'header' => TRUE,
+        'width' => '20%',
+      ),
+      l('Delete', 'user/' . $uid . '/data-collections/' . $collection->getCollectionID() . '/delete')
+    );
+    
+    $collection_content = '<b>Collection Details</b>' . theme_table([
+      'header' => $headers,
+      'rows' => $rows,
+      'attributes' => [],
+      'sticky' => FALSE,
+      'caption' => '',
+      'colgroups' => [],
+      'empty' => '',
+    ]);
+  }
+  
+  drupal_json_output($file_content . $collection_content);
 }
 
 

+ 56 - 0
tripal/theme/css/tripal_user_files.css

@@ -0,0 +1,56 @@
+#tripal-user-file-tree {
+  margin: 0;
+  padding: 10px;
+  height: 250px;
+  overflow: auto;
+  border: 1px solid #AAAAAA;
+}
+#tripal-user-file-tree li.tree-node-folder {
+  background: url(../images/directory.png) no-repeat;
+  background-size: 22px 22px;
+  cursor: pointer;
+}
+#tripal-user-file-tree li.tree-node-file {
+  background: url(../images/txt.png) no-repeat;
+  background-size: 22px 22px;
+  cursor: pointer;
+}
+#tripal-user-file-tree li.odd {
+  
+}
+#tripal-user-file-tree li.even {
+  background-color: #EEEEEE;
+}
+#tripal-user-file-tree ul {
+  margin: 0;
+  padding: 0;
+}
+#tripal-user-file-tree li {
+	list-style-type: none;
+  margin: 0px;
+  padding: 0px 0px 0px 30px;
+  line-height: 22px;
+}
+#tripal-user-file-tree .file-name {
+  color: #369;	
+}
+#tripal-user-file-tree .file-size {
+  float: right; 
+  padding-left: 10px;
+  font-size: 0.8em; 
+  width: 50px;
+  text-align: right;
+}
+#tripal-user-file-tree .file-expires {
+  float: right; 
+  padding-left: 10px;
+  font-size: 0.8em; 
+  width: 50px;
+  text-align: right;
+}
+#tripal-user-file-tree a {
+  border-bottom-width: 1px;
+  border-bottom-style: dotted;
+}
+#tripal-user-file-details {
+}

BIN
tripal/theme/images/directory.png


BIN
tripal/theme/images/txt.png


+ 68 - 0
tripal/theme/js/tripal.user_files.js

@@ -0,0 +1,68 @@
+(function ($) {
+  
+  Drupal.behaviors.TripalUserFiles = {
+    attach: function (context, settings) {
+
+      // The Drupal theme_items_list duplicates the classes of the li on
+      // the ul of nexted children.  This screws up our collapse/open so
+      // we'll remove it.
+      $('#tripal-user-file-tree ul').removeAttr('class');
+      
+      // Set default actions for closed and open folders.
+      $('.tree-node-closed').children().hide();
+      $('.tree-node-closed').click(function(event) {
+        expandNode($(this));
+      });
+      $('.tree-node-open').click(function(event) {
+        collapseNode($(this));
+      });
+      
+      // Keep clicks on the files from propagating up to folders and
+      // causing collapse.
+      $('.tree-node-file').click(function(event) {
+      	event.stopPropagation();
+      	showFileDetails($(this));
+      });
+    }
+  }
+  
+  /**
+   * Prints the details of the selected file from the tree.
+   */
+  function showFileDetails(item) {  
+	var fid = item.attr('fid');
+	var uid = item.attr('uid');
+    $.ajax({
+      url : baseurl + '/user/' + uid + '/files/' + fid,
+      success: function(data) {
+        $('#tripal-user-file-details').html(data);
+      }
+    });
+  }
+  
+  /**
+   * Collapses a node in the CV tree browser and removes its children.
+   */
+  function collapseNode(item) {
+    item.removeClass('tree-node-open');
+    item.addClass('tree-node-closed');
+    item.children().hide()
+    item.unbind('click');
+    item.click(function(event){
+      expandNode($(this));
+    })
+  }
+  
+  /**
+   * Expands a node in the CV tree browser and loads it's children via AJAX.
+   */
+  function expandNode(item){
+    item.removeClass('tree-node-closed');
+    item.addClass('tree-node-open');
+    item.children().show()
+    item.unbind('click');
+    item.click(function(event){
+      collapseNode($(this));
+    }) 
+  }
+})(jQuery);

+ 8 - 18
tripal/tripal.module

@@ -358,17 +358,6 @@ function tripal_menu() {
   /**
    * Data Collections
    */
-  $items['user/%/data-collections'] = array (
-    'title' => 'Data Collections',
-    'description' => 'Your list of saved data collections',
-    'page callback' => 'tripal_user_collections_page',
-    'access callback' => 'tripal_accesss_user_collections',
-    'access arguments' => array(1),
-    'type' => MENU_LOCAL_TASK,
-    'file' => 'includes/tripal.collections.inc',
-    'file path' => drupal_get_path('module', 'tripal'),
-  );
-
   $items['user/%/data-collections/%/delete'] = array (
     'title' => 'Delete a Collections',
     'description' => 'Deletes a data collection.',
@@ -511,11 +500,11 @@ function tripal_menu() {
   
   // User view quota (Tab)
   $items['user/%/files'] = [
-    'title' => 'Uploads',
+    'title' => 'Files',
     'description' => 'Monitors what files that have been uploaded by user through the tripal module',
     'page callback' => 'tripal_user_files_page',
     'page arguments' => [1],
-    'access callback' => 'tripal_access_user_uploads',
+    'access callback' => 'tripal_access_user_files',
     'access arguments' => ['view', 1],
     'type' => MENU_LOCAL_TASK,
     'file' => 'includes/tripal.user.inc',
@@ -528,19 +517,20 @@ function tripal_menu() {
     'description' => "View details about the file",
     'page callback' => 'tripal_view_file',
     'page arguments' => [1, 3],
-    'access callback' => 'tripal_access_user_uploads',
+    'access callback' => 'tripal_access_user_files',
     'access arguments' => ['renew', 1, 3],
     'type' => MENU_CALLBACK,
     'file' => 'includes/tripal.user.inc',
     'file path' => drupal_get_path('module', 'tripal'),
   ];
+  
   // User file renew.
   $items['user/%/files/%/renew'] = [
     'title' => 'Renew File',
     'description' => "Renew a user's file",
     'page callback' => 'tripal_renew_file',
     'page arguments' => [3],
-    'access callback' => 'tripal_access_user_uploads',
+    'access callback' => 'tripal_access_user_files',
     'access arguments' => ['renew', 1, 3],
     'type' => MENU_CALLBACK,
     'file' => 'includes/tripal.user.inc',
@@ -553,7 +543,7 @@ function tripal_menu() {
     'page callback' => 'tripal_download_file',
     'page arguments' => [3],
     'access arguments' => ['download', 1, 3],
-    'access callback' => 'tripal_access_user_uploads',
+    'access callback' => 'tripal_access_user_files',
     'type' => MENU_CALLBACK,
     'file' => 'includes/tripal.user.inc',
     'file path' => drupal_get_path('module', 'tripal'),
@@ -564,7 +554,7 @@ function tripal_menu() {
     'description' => "Delete a user's file based on either user action or expired file",
     'page callback' => 'drupal_get_form',
     'page arguments' => ['tripal_delete_file_form', 1, 3],
-    'access callback' => 'tripal_access_user_uploads',
+    'access callback' => 'tripal_access_user_files',
     'access arguments' => ['delete', 1, 3],
     'type' => MENU_CALLBACK,
     'file' => 'includes/tripal.user.inc',
@@ -584,7 +574,7 @@ function tripal_menu() {
  * @param $fid
  *   The file ID.
  */
-function tripal_access_user_uploads($op, $uid, $fid = NULL) {
+function tripal_access_user_files($op, $uid, $fid = NULL) {
   global $user;
   
   // The site admin can do anything.

+ 1 - 1
tripal/tripal_views_query.inc

@@ -277,7 +277,7 @@ class tripal_views_query extends views_plugin_query {
           // really should create a new tripal_views_plugin_pager class
           // and call the corresponding function here, but due to time
           // constraints this is the shortcut.
-          $total_items = $cquery->execute();
+          $total_items = $this->cquery->execute();
           $this->pager->total_items = $total_items;
           if (!empty($this->pager->options['offset'])) {
             $this->pager->total_items -= $this->pager->options['offset'];

+ 2 - 2
tripal/views_handlers/tripal_views_handler_area_collections.inc

@@ -458,11 +458,11 @@ function tripal_views_handler_area_collections_search_api_form_submit($form, $fo
   }
 
   // Finally, tell the user we're done and link them to the collection.
-  drupal_set_message(t("Collection '%name' created with %num_recs record(s). Check the !view to generate file links.",
+  drupal_set_message(t("Collection '%name' created with %num_recs record(s). Files for this collection have not yet been created. To create files for download or use with other tools, check the !view.",
     array(
       '%name' => $collection_details['collection_name'],
       '%num_recs' => count($results),
-      '!view' => l('data collections page', 'user/' . $user->uid . '/data-collections'),
+      '!view' => l('files page', 'user/' . $user->uid . '/files'),
     ))
   );
 }