From 3cbcf8552c3bdbdfc5c9d3a69741522180e81faf Mon Sep 17 00:00:00 2001
From: Demian Katz <demian.katz@villanova.edu>
Date: Wed, 19 Dec 2012 12:07:38 -0500
Subject: [PATCH] Implemented tree view within collection module.

---
 config/vufind/config.ini                      |  2 +
 languages/en-gb.ini                           |  2 +
 languages/en.ini                              |  2 +
 module/VuFind/config/module.config.php        |  5 +
 .../Controller/CollectionController.php       | 12 ++-
 .../VuFind/Controller/HierarchyController.php | 24 ++++-
 .../RecordTab/CollectionHierarchyTree.php     | 91 +++++++++++++++++++
 .../src/VuFind/RecordTab/HierarchyTree.php    |  5 +-
 .../src/VuFind/Theme/Root/Helper/Record.php   | 10 ++
 .../VuFind/xsl/Hierarchy/CollectionList.xsl   | 32 +++++++
 .../VuFind/xsl/Hierarchy/CollectionTree.xsl   | 24 +++++
 themes/blueprint/css/styles.css               | 28 +++++-
 themes/blueprint/js/hierarchyTree_JSTree.js   | 41 +++++++++
 .../SolrDefault/collection-record.phtml       | 63 +++++++++++++
 .../RecordTab/collectionhierarchytree.phtml   | 19 ++++
 .../templates/RecordTab/hierarchytree.phtml   |  4 +-
 .../collection/collection-record-error.phtml  |  1 +
 .../blueprint/templates/collection/view.phtml | 23 +++--
 .../SolrDefault/collection-record.phtml       | 51 +++++++++++
 .../RecordTab/collectionhierarchytree.phtml   | 10 ++
 .../collection/collection-record-error.phtml  |  1 +
 21 files changed, 430 insertions(+), 20 deletions(-)
 create mode 100644 module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php
 create mode 100644 module/VuFind/xsl/Hierarchy/CollectionList.xsl
 create mode 100644 module/VuFind/xsl/Hierarchy/CollectionTree.xsl
 create mode 100644 themes/blueprint/templates/RecordDriver/SolrDefault/collection-record.phtml
 create mode 100644 themes/blueprint/templates/RecordTab/collectionhierarchytree.phtml
 create mode 100644 themes/blueprint/templates/collection/collection-record-error.phtml
 create mode 100644 themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml
 create mode 100644 themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml
 create mode 100644 themes/jquerymobile/templates/collection/collection-record-error.phtml

diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index b5ca32c561f..0e523e0a393 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -788,6 +788,8 @@ HMACkey = mySuperSecretValue
 ; link to the respective collections page rather than the record page
 ; (default = false).
 ;collections = true
+; Control default tab of Collection view (default = CollectionList)
+;defaultTab = CollectionList
 ; This controls where data is retrieved from to build the Collections/Home page.
 ; It can be set to Index (use the Solr index) or Alphabetic (use the AlphaBrowse
 ; index). Index is subject to "out of memory" errors if you have many (150000+)
diff --git a/languages/en-gb.ini b/languages/en-gb.ini
index 500e882a3a9..522b910ff12 100644
--- a/languages/en-gb.ini
+++ b/languages/en-gb.ini
@@ -398,6 +398,8 @@ Video = Video
 Video Clips = "Video Clips"
 Videos = Videos
 View Book Bag = "View Book Bag"
+View Full Collection = "View Full Collection"
+View Full Record = "View Full Record"
 View Record = "View Record"
 View Records = "View Records"
 View online: Full view Book Preview from the Hathi Trust = "View online: Full view Book Preview from the Hathi Trust"
diff --git a/languages/en.ini b/languages/en.ini
index c2c55514ad6..4310f965cf8 100644
--- a/languages/en.ini
+++ b/languages/en.ini
@@ -398,6 +398,8 @@ Video = Video
 Video Clips = "Video Clips"
 Videos = Videos
 View Book Bag = "View Book Bag"
+View Full Collection = "View Full Collection"
+View Full Record = "View Full Record"
 View Record = "View Record"
 View Records = "View Records"
 View online: Full view Book Preview from the Hathi Trust = "View online: Full view Book Preview from the Hathi Trust"
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index 4b47642d213..40337b43aab 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -324,6 +324,11 @@ $config = array(
     'recordtab_plugin_manager' => array(
         'abstract_factories' => array('VuFind\RecordTab\PluginFactory'),
         'factories' => array(
+            'collectionhierarchytree' => function ($sm) {
+                return new \VuFind\RecordTab\CollectionHierarchyTree(
+                    $sm->getServiceLocator()->get('VuFind\RecordLoader')
+                );
+            },
             'collectionlist' => function ($sm) {
                 $searchManager = $sm->getServiceLocator()->get('SearchManager');
                 return new \VuFind\RecordTab\CollectionList(
diff --git a/module/VuFind/src/VuFind/Controller/CollectionController.php b/module/VuFind/src/VuFind/Controller/CollectionController.php
index 14fff32568f..380af3f1ed0 100644
--- a/module/VuFind/src/VuFind/Controller/CollectionController.php
+++ b/module/VuFind/src/VuFind/Controller/CollectionController.php
@@ -46,7 +46,11 @@ class CollectionController extends AbstractRecord
         // Call standard record controller initialization:
         parent::__construct();
 
-        // TODO: set appropriate default tab
+        // Set default tab, if specified:
+        $config = \VuFind\Config\Reader::getConfig();
+        if (isset($config->Collections->defaultTab)) {
+            $this->defaultTab = $config->Collections->defaultTab;
+        }
     }
 
     /**
@@ -56,10 +60,12 @@ class CollectionController extends AbstractRecord
      */
     protected function getTabConfiguration()
     {
-        // TODO: fill in
         return array(
             'VuFind\RecordDriver\AbstractBase'
-                => array('CollectionList' => 'CollectionList')
+                => array(
+                    'CollectionList' => 'CollectionList',
+                    'HierarchyTree' => 'CollectionHierarchyTree',
+                )
         );
     }
 
diff --git a/module/VuFind/src/VuFind/Controller/HierarchyController.php b/module/VuFind/src/VuFind/Controller/HierarchyController.php
index af651f3b911..ec8109bd65c 100644
--- a/module/VuFind/src/VuFind/Controller/HierarchyController.php
+++ b/module/VuFind/src/VuFind/Controller/HierarchyController.php
@@ -110,7 +110,7 @@ class HierarchyController extends AbstractBase
     /**
      * Gets a Hierarchy Tree
      *
-     * @return void
+     * @return mixed
      */
     public function gettreeAction()
     {
@@ -143,4 +143,26 @@ class HierarchyController extends AbstractBase
             "<error>" . $this->translate("hierarchy_tree_error") . "</error>"
         );
     }
+
+    /**
+     * Get a record for display within a tree
+     *
+     * @return mixed
+     */
+    public function getrecordAction()
+    {
+        $id = $this->params()->fromQuery('id');
+        $loader = $this->getServiceLocator()->get('VuFind\RecordLoader');
+        try {
+            $record = $loader->load($id);
+            $result = $this->getViewRenderer()->record($record)
+                ->getCollectionBriefRecord();
+        } catch (\VuFind\Exception\RecordMissing $e) {
+            $result = $this->getViewRenderer()
+                ->render('collection/collection-record-error.phtml');
+        }
+        $response = $this->getResponse();
+        $response->setContent($result);
+        return $response;
+    }
 }
diff --git a/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php b/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php
new file mode 100644
index 00000000000..f0f275ae37f
--- /dev/null
+++ b/module/VuFind/src/VuFind/RecordTab/CollectionHierarchyTree.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * HierarchyTree tab
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind2
+ * @package  RecordTabs
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/creating_a_session_handler Wiki
+ */
+namespace VuFind\RecordTab;
+
+/**
+ * HierarchyTree tab
+ *
+ * @category VuFind2
+ * @package  RecordTabs
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     http://vufind.org/wiki/creating_a_session_handler Wiki
+ */
+class CollectionHierarchyTree extends HierarchyTree
+{
+    /**
+     * Record loader
+     *
+     * @var \VuFind\Record\Loader
+     */
+    protected $loader;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Record\Loader $loader Record loader
+     */
+    public function __construct(\VuFind\Record\Loader $loader)
+    {
+        $this->loader = $loader;
+    }
+
+    /**
+     * Render a hierarchy tree
+     *
+     * @param string $baseUrl Base URL to use in links within tree
+     * @param string $id      Hierarchy ID (omit to use active tree)
+     * @param string $context Context for use by renderer
+     *
+     * @return string
+     */
+    public function renderTree($baseUrl, $id = null, $context = 'Collection')
+    {
+        // Same as parent -- we just have a different default context:
+        return parent::renderTree($baseUrl, $id, $context);
+    }
+
+    /**
+     * Get the current active record.  Returns record driver if found, false
+     * if no record requested, null if ID invalid.
+     *
+     * @return mixed
+     */
+    public function getActiveRecord()
+    {
+        $id = $this->getRequest()->getQuery('recordID', false);
+        if ($id === false) {
+            return $id;
+        }
+        try {
+            return $this->loader->load($id);
+        } catch (\VuFind\Exception\RecordMissing $e) {
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php b/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php
index 5ab1debb8eb..93cb4db462b 100644
--- a/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php
+++ b/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php
@@ -159,16 +159,17 @@ class HierarchyTree extends AbstractBase
      *
      * @param string $baseUrl Base URL to use in links within tree
      * @param string $id      Hierarchy ID (omit to use active tree)
+     * @param string $context Context for use by renderer
      *
      * @return string
      */
-    public function renderTree($baseUrl, $id = null)
+    public function renderTree($baseUrl, $id = null, $context = 'Record')
     {
         $id = (null === $id) ? $this->getActiveTree() : $id;
         $recordDriver = $this->getRecordDriver();
         $hierarchyDriver = $recordDriver->tryMethod('getHierarchyDriver');
         if (is_object($hierarchyDriver)) {
-            $tree = $hierarchyDriver->render($recordDriver, 'Record', 'List', $id);
+            $tree = $hierarchyDriver->render($recordDriver, $context, 'List', $id);
             return str_replace(
                 '%%%%VUFIND-BASE-URL%%%%', rtrim($baseUrl, '/'), $tree
             );
diff --git a/module/VuFind/src/VuFind/Theme/Root/Helper/Record.php b/module/VuFind/src/VuFind/Theme/Root/Helper/Record.php
index e8a77658be4..f53d864b064 100644
--- a/module/VuFind/src/VuFind/Theme/Root/Helper/Record.php
+++ b/module/VuFind/src/VuFind/Theme/Root/Helper/Record.php
@@ -120,6 +120,16 @@ class Record extends AbstractHelper
         return $this->renderTemplate('core.phtml');
     }
 
+    /**
+     * Render the a brief record for use in collection mode.
+     *
+     * @return string
+     */
+    public function getCollectionBriefRecord()
+    {
+        return $this->renderTemplate('collection-record.phtml');
+    }
+
     /**
      * Render the core metadata area of the collection view.
      *
diff --git a/module/VuFind/xsl/Hierarchy/CollectionList.xsl b/module/VuFind/xsl/Hierarchy/CollectionList.xsl
new file mode 100644
index 00000000000..bed1a1caaa6
--- /dev/null
+++ b/module/VuFind/xsl/Hierarchy/CollectionList.xsl
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
+
+    <xsl:template match="/">
+        <div id="treeList">
+        <xsl:apply-templates select="//root">
+        </xsl:apply-templates>
+        </div>
+    </xsl:template>
+
+    <xsl:template match="item">
+        <ul>
+        <xsl:variable name="id" select="@id" />
+        <li>
+          <xsl:attribute name="id">tree-<xsl:value-of select="$id"/></xsl:attribute>
+          <xsl:variable name="isCollection" select="@isCollection" />
+          <xsl:attribute name="class">
+          <xsl:if test="$isCollection = 'true'">hierarchy </xsl:if>
+          <xsl:choose>
+            <xsl:when test="$isCollection = 'true' and $recordID = $id">currentHierarchy</xsl:when>
+            <xsl:when test="$isCollection != 'true' and $recordID = $id">currentRecord</xsl:when>
+          </xsl:choose>
+          </xsl:attribute>
+          <a href="{$baseURL}/Collection/{$collectionID}/HierarchyTree?recordID={$id}#tabnav" title="{$titleText}">
+              <xsl:value-of select="./content/name" />
+          </a>
+          <xsl:apply-templates select="item"/>
+      </li>
+      </ul>
+    </xsl:template>
+
+</xsl:stylesheet>
diff --git a/module/VuFind/xsl/Hierarchy/CollectionTree.xsl b/module/VuFind/xsl/Hierarchy/CollectionTree.xsl
new file mode 100644
index 00000000000..9e3ef5ed33c
--- /dev/null
+++ b/module/VuFind/xsl/Hierarchy/CollectionTree.xsl
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl">
+ 
+    <xsl:template match="/">
+        <root>
+        <xsl:apply-templates select="//root">
+        </xsl:apply-templates>
+        </root>
+    </xsl:template>
+
+    <xsl:template match="item">
+        <xsl:variable name="id" select="@id" />
+        <item>
+          <content>
+              <name class="JSTreeID"><xsl:value-of select="$id"/></name>
+              <name href="{$baseURL}/Collection/{$collectionID}/HierarchyTree?recordID={$id}#tabnav" title="{$titleText}">
+                  <xsl:value-of select="./content/name" />
+              </name>
+          </content>
+          <xsl:apply-templates select="item"/>
+      </item>
+    </xsl:template>
+    
+</xsl:stylesheet>
diff --git a/themes/blueprint/css/styles.css b/themes/blueprint/css/styles.css
index 366516fe6c8..3c916f5d4ff 100644
--- a/themes/blueprint/css/styles.css
+++ b/themes/blueprint/css/styles.css
@@ -1857,13 +1857,20 @@ div#closeContextHelp:active {
     display: none;
 }
 
-#hierarchyTreeHolder {
+#hierarchyTreeHolder, #hierarchyRecordHolder {
     background-color: #FFF;
-    border: 1px solid #DCDCDC;
     padding: 0.5em;
 }
 
-#hierarchyTree {
+#hierarchyTreeHolder {
+    border: 1px solid #DCDCDC;
+}
+
+.collectionDetailsTree #hierarchyTreeHolder, .collectionDetailsTree #hierarchyRecordHolder {
+    border-top: 0;
+}
+
+#hierarchyTree, #hierarchyRecord {
     padding: 0.5em 0.5em 0.5em 0;
     max-height:375px;
     min-height:375px;
@@ -1871,6 +1878,14 @@ div#closeContextHelp:active {
     overflow-y: auto;
 }
 
+#hierarchyRecord {
+    overflow: auto;
+}
+
+#hierarchyRecord th {
+   width: 12em;
+}
+
 #treeSearch {
     display:none;
     float: right;
@@ -1991,6 +2006,13 @@ div#closeContextHelp:active {
     padding: 0.25em;
 }
 
+.collectionDetailsTree #treeSelector {
+    background-color: #FAFAFA;
+    border: 1px solid #DCDCDC;
+    border-top: 0 none;
+    padding: 0.25em;
+}
+
 #treeSelector a {
     margin-right: 1em;
 }
diff --git a/themes/blueprint/js/hierarchyTree_JSTree.js b/themes/blueprint/js/hierarchyTree_JSTree.js
index 059d3de3e31..e5486269a7c 100644
--- a/themes/blueprint/js/hierarchyTree_JSTree.js
+++ b/themes/blueprint/js/hierarchyTree_JSTree.js
@@ -30,6 +30,21 @@ $(document).ready(function()
             $(this).remove();
         });
 
+        $(".Collection").each(function()
+        {
+            var id = $(this).attr("value");
+            $(this).next("a").click(function(e)
+            {
+                e.preventDefault();
+                $("#hierarchyTree a").removeClass("jstree-clicked");
+                $(this).addClass("jstree-clicked");
+                // Open this node
+                $(this).parent().removeClass("jstree-closed").addClass("jstree-open");
+                getRecord(id);
+                return false;
+            });
+        });
+
         $("#hierarchyTree a").click(function(e)
         {
             e.preventDefault();
@@ -113,6 +128,25 @@ function showTreeError(msg)
     $("#hierarchyTreeHolder").html('<p class="error">' + msg + '</p>');
 }
 
+function getRecord(recordID)
+{
+    $.ajax({
+      url: path + '/Hierarchy/GetRecord?' + $.param({id: recordID}),
+      dataType: 'html',
+      success: function(response) {
+        if (response) {
+            $('#hierarchyRecord').html(response);
+            // Remove the old path highlighting
+            $('#hierarchyTree a').removeClass("jstree-highlight");
+            // Add Current path highlighting
+            var jsTreeNode = $(":input[value='"+recordID+"']").parent();
+            jsTreeNode.children("a").addClass("jstree-highlight");
+            jsTreeNode.parents("li").children("a").addClass("jstree-highlight");
+        }
+      }
+    });
+}
+
 function scroll(scroller, mode)
 {
     // Get the currently cicked item
@@ -200,6 +234,13 @@ function doTreeSearch()
                 $(this).show();
             });
         });
+        if (results["results"].length == 1) {
+            $("#hierarchyTree .jstree-clicked").removeClass("jstree-clicked");
+            // only do this for collection pages
+            if ($(".Collection").length != 0) {
+                getRecord(results["results"][0]);
+            }
+        }
         $("#treeSearchLoadingImg").hide();
     });
 }
diff --git a/themes/blueprint/templates/RecordDriver/SolrDefault/collection-record.phtml b/themes/blueprint/templates/RecordDriver/SolrDefault/collection-record.phtml
new file mode 100644
index 00000000000..fea1ce46cf6
--- /dev/null
+++ b/themes/blueprint/templates/RecordDriver/SolrDefault/collection-record.phtml
@@ -0,0 +1,63 @@
+<h1><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h1>
+<a href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc('View Full ' . ($this->driver->isCollection() ? 'Collection' : 'Record'))?></a>
+
+<table cellpadding="2" cellspacing="0" border="0" class="citation" summary="<?=$this->transEsc('Bibliographic Details')?>">
+  <? $summary = $this->driver->getSummary(); $summary = isset($summary[0]) ? $summary[0] : false; ?>
+  <? if ($summary): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Description')?>: </th>
+      <td><?=$this->escapeHtml($summary)?></td>
+    </tr>
+  <? endif; ?>
+
+  <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
+  <? if (isset($authors['main']) && !empty($authors['main'])): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Main Author')?>: </th>
+      <td><a href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></td>
+    </tr>
+  <? endif; ?>
+
+  <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Corporate Author')?>: </th>
+      <td><a href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></td>
+    </tr>
+  <? endif; ?>
+
+  <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Language')?>: </th>
+      <td><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?><br/><? endforeach; ?></td>
+    </tr>
+  <? endif; ?>
+
+  <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Format')?>: </th>
+      <td><?=$this->record($this->driver)->getFormatList()?></td>
+    </tr>
+  <? endif; ?>
+
+  <? $access = $this->driver->getAccessRestrictions(); if (!empty($access)): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Access')?>: </th>
+      <td>
+        <? foreach ($access as $field): ?>
+          <?=$this->escapeHtml($field)?><br/>
+        <? endforeach; ?>
+      </td>
+    </tr>
+  <? endif; ?>
+
+  <? $related = $this->driver->getRelationshipNotes(); if (!empty($related)): ?>
+    <tr valign="top">
+      <th><?=$this->transEsc('Related Items')?>: </th>
+      <td>
+        <? foreach ($related as $field): ?>
+          <?=$this->escapeHtml($field)?><br/>
+        <? endforeach; ?>
+      </td>
+    </tr>
+  <? endif; ?>
+</table>
\ No newline at end of file
diff --git a/themes/blueprint/templates/RecordTab/collectionhierarchytree.phtml b/themes/blueprint/templates/RecordTab/collectionhierarchytree.phtml
new file mode 100644
index 00000000000..63084987769
--- /dev/null
+++ b/themes/blueprint/templates/RecordTab/collectionhierarchytree.phtml
@@ -0,0 +1,19 @@
+<?
+    $this->mainTreeClass = 'span-11';
+    $this->treeContext = 'Collection';
+?>
+<?=$this->render('RecordTab/hierarchytree.phtml')?>
+<div class="span-11">
+    <div id="hierarchyRecordHolder">
+      <div id="hierarchyRecord">
+        <? if (($collectionRecord = $this->tab->getActiveRecord()) !== false): ?>
+          <? if ($collectionRecord === null): ?>
+            <?=$this->render('collection/collection-record-error.phtml')?>
+          <? else: ?>
+            <?=$this->record($collectionRecord)->getCollectionBriefRecord()?>
+          <? endif; ?>
+        <? endif; ?>
+      </div>
+   </div>
+</div>
+<div class="clear">&nbsp;</div>
\ No newline at end of file
diff --git a/themes/blueprint/templates/RecordTab/hierarchytree.phtml b/themes/blueprint/templates/RecordTab/hierarchytree.phtml
index 9c19fda27b1..2ed308b124c 100644
--- a/themes/blueprint/templates/RecordTab/hierarchytree.phtml
+++ b/themes/blueprint/templates/RecordTab/hierarchytree.phtml
@@ -17,7 +17,7 @@
     $this->inlineScript(\Zend\View\Helper\HeadScript::FILE, 'hierarchyTree_JSTree.js');
     echo $this->inlineScript();
 ?>
-<div>
+<div<?=isset($this->mainTreeClass) ? ' class="' . $this->mainTreeClass . '"' : ''?>>
   <? if (count($hierarchyTreeList) > 1): ?>
     <div id="treeSelector">
       <? foreach ($hierarchyTreeList as $hierarchy => $hierarchyTitle): ?>
@@ -43,7 +43,7 @@
       <div id="hierarchyTree">
         <input type="hidden" value="<?=$this->escapeHtml($this->driver->getUniqueId())?>" class="hiddenRecordId" />
         <input type="hidden" value="<?=$this->escapeHtml($activeTree)?>" class="hiddenHierarchyId" />
-        <input type="hidden" value="Record" class="hiddenContext" />
+        <input type="hidden" value="<?=isset($this->treeContext) ? $this->treeContext : 'Record'?>" class="hiddenContext" />
         <noscript>
           <?=$this->tab->renderTree($this->url('home'))?>
         </noscript>
diff --git a/themes/blueprint/templates/collection/collection-record-error.phtml b/themes/blueprint/templates/collection/collection-record-error.phtml
new file mode 100644
index 00000000000..5cfd1f89b51
--- /dev/null
+++ b/themes/blueprint/templates/collection/collection-record-error.phtml
@@ -0,0 +1 @@
+<h1><?=$this->transEsc('Cannot find record')?></h1>
diff --git a/themes/blueprint/templates/collection/view.phtml b/themes/blueprint/templates/collection/view.phtml
index 9d9dc970d1e..11996c55730 100644
--- a/themes/blueprint/templates/collection/view.phtml
+++ b/themes/blueprint/templates/collection/view.phtml
@@ -8,12 +8,15 @@
         $this->headLink()->appendAlternate($this->recordLink()->getActionUrl($this->driver, 'RDF'), 'application/rdf+xml', 'RDF Representation');
     }
 
+    // Set flag for special cases relating to full-width hierarchy tree tab:
+    $tree = (strtolower($this->activeTab) == 'hierarchytree');
+    
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = $this->getLastSearchLink($this->transEsc('Search'), '', '<span>&gt;</span>') .
         '<a href="' . $this->url('collections-home') . '">' . $this->transEsc('Collections') . '</a><span>&gt;</span>' .
         $this->recordLink()->getBreadcrumb($this->driver);
 ?>
-<div class="<?=$this->layoutClass('mainbody')?>">
+<div class="<?=$tree ? 'span-23' : $this->layoutClass('mainbody')?>">
   <?=$this->record($this->driver)->getToolbar()?>
 
   <div class="record recordId source<?=$this->escapeHtml($this->driver->getResourceSource())?>" id="record">
@@ -51,19 +54,21 @@
   <? endif; ?>
 
 
-  <div class="collectionDetails">
+  <div class="collectionDetails<?=$tree ? 'Tree' : ''?>">
     <?=isset($activeTabObj) ? $this->record($this->driver)->getTab($activeTabObj) : '' ?>
   </div>
 
   <span class="Z3988" title="<?=$this->escapeHtml($this->driver->getOpenURL())?>"></span>
 </div>
 
-<div class="<?=$this->layoutClass('sidebar')?>">
-  <? if (isset($activeTabObj) && is_callable(array($activeTabObj, 'getSideRecommendations'))): ?>
-    <? foreach ($activeTabObj->getSideRecommendations() as $current): ?>
-      <?=$this->recommend($current)?>
-    <? endforeach; ?>
-  <? endif; ?>
-</div>
+<? if (!$tree): ?>
+  <div class="<?=$this->layoutClass('sidebar')?>">
+    <? if (isset($activeTabObj) && is_callable(array($activeTabObj, 'getSideRecommendations'))): ?>
+      <? foreach ($activeTabObj->getSideRecommendations() as $current): ?>
+        <?=$this->recommend($current)?>
+      <? endforeach; ?>
+    <? endif; ?>
+  </div>
+<? endif; ?>
 
 <div class="clear"></div>
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml
new file mode 100644
index 00000000000..7ceb7ade4d7
--- /dev/null
+++ b/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml
@@ -0,0 +1,51 @@
+<h3><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h3>
+<p><a rel="external" href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc('View Full ' . ($this->driver->isCollection() ? 'Collection' : 'Record'))?></a></p>
+
+<dl class="biblio" title="<?=$this->transEsc('Bibliographic Details')?>">
+  <? $summary = $this->driver->getSummary(); $summary = isset($summary[0]) ? $summary[0] : false; ?>
+  <? if ($summary): ?>
+    <dt><?=$this->transEsc('Description')?>: </dt>
+    <dd><?=$this->escapeHtml($summary)?></dd>
+  <? endif; ?>
+
+  <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
+  <? if (isset($authors['main']) && !empty($authors['main'])): ?>
+    <dt><?=$this->transEsc('Main Author')?>: </dt>
+    <dd><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></dd>
+  <? endif; ?>
+
+  <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
+    <dt><?=$this->transEsc('Corporate Author')?>: </dt>
+    <dd><p><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></p></dd>
+  <? endif; ?>
+
+  <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
+    <dt><?=$this->transEsc('Language')?>: </dt>
+    <dd><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?> <? endforeach; ?></dd>
+  <? endif; ?>
+
+  <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?>
+    <dt><?=$this->transEsc('Format')?>: </dt>
+    <dd><?=$this->record($this->driver)->getFormatList()?></dd>
+  <? endif; ?>
+
+  <? $access = $this->driver->getAccessRestrictions(); if (!empty($access)): ?>
+    <? $contentDisplayed = true; ?>
+    <dt><?=$this->transEsc('Access')?>: </dt>
+    <dd>
+      <? foreach ($access as $field): ?>
+        <p><?=$this->escapeHtml($field)?></p>
+      <? endforeach; ?>
+    </dd>
+  <? endif; ?>
+
+  <? $related = $this->driver->getRelationshipNotes(); if (!empty($related)): ?>
+    <? $contentDisplayed = true; ?>
+    <dt><?=$this->transEsc('Related Items')?>: </dt>
+    <dd>
+      <? foreach ($related as $field): ?>
+        <p><?=$this->escapeHtml($field)?></p>
+      <? endforeach; ?>
+    </dd>
+  <? endif; ?>
+</table>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml b/themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml
new file mode 100644
index 00000000000..0e11a7cf9f1
--- /dev/null
+++ b/themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml
@@ -0,0 +1,10 @@
+<? if (($collectionRecord = $this->tab->getActiveRecord()) !== false): ?>
+  <? $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb()); ?>
+  <? if ($collectionRecord === null): ?>
+    <?=$this->render('collection/collection-record-error.phtml')?>
+  <? else: ?>
+    <?=$this->record($collectionRecord)->getCollectionBriefRecord()?>
+  <? endif; ?>
+<? else: ?>
+  <?=$this->render('RecordTab/hierarchytree.phtml')?>
+<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/collection/collection-record-error.phtml b/themes/jquerymobile/templates/collection/collection-record-error.phtml
new file mode 100644
index 00000000000..e680913f886
--- /dev/null
+++ b/themes/jquerymobile/templates/collection/collection-record-error.phtml
@@ -0,0 +1 @@
+<h3><?=$this->transEsc('Cannot find record')?></h3>
-- 
GitLab