diff --git a/lib/WebGUI/Admin.pm b/lib/WebGUI/Admin.pm
index a100ecc40..d21283b55 100644
--- a/lib/WebGUI/Admin.pm
+++ b/lib/WebGUI/Admin.pm
@@ -3,6 +3,7 @@ package WebGUI::Admin;
# The new WebGUI Admin console
use Moose;
+use JSON qw( from_json to_json );
use namespace::autoclean;
has 'session' => (
@@ -112,6 +113,40 @@ sub getNewContentTemplateVars {
my $vars = [];
}
+#----------------------------------------------------------------------------
+
+=head2 getTreePaginator ( $asset )
+
+Get a page for the Asset Tree view. Returns a WebGUI::Paginator object
+filled with asset IDs.
+
+=cut
+
+sub getTreePaginator {
+ my ( $self, $asset ) = @_;
+ my $session = $self->session;
+
+ my $orderByColumn = $session->form->get( 'orderByColumn' )
+ || "lineage"
+ ;
+ my $orderByDirection = lc $session->form->get( 'orderByDirection' ) eq "desc"
+ ? "DESC"
+ : "ASC"
+ ;
+
+ my $recordOffset = $session->form->get( 'recordOffset' ) || 1;
+ my $rowsPerPage = $session->form->get( 'rowsPerPage' ) || 100;
+ my $currentPage = int ( $recordOffset / $rowsPerPage ) + 1;
+
+ my $p = WebGUI::Paginator->new( $session, '', $rowsPerPage, 'pn', $currentPage );
+
+ my $orderBy = $session->db->dbh->quote_identifier( $orderByColumn ) . ' ' . $orderByDirection;
+ $p->setDataByArrayRef( $asset->getLineage( ['children'], { orderByClause => $orderBy } ) );
+
+ return $p;
+}
+
+
#----------------------------------------------------------------------
=head2 getVersionTagTemplateVars
@@ -143,6 +178,61 @@ sub getVersionTagTemplateVars {
#----------------------------------------------------------------------
+=head2 www_getTreeData ( )
+
+Get the Tree data for a given asset URL
+
+=cut
+
+sub www_getTreeData {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my ( $user, $form ) = $session->quick(qw{ user form });
+
+ my $assetUrl = $form->get('assetUrl');
+ my $asset = WebGUI::Asset->newByUrl( $session, $assetUrl );
+
+ my $i18n = WebGUI::International->new( $session, "Asset" );
+ my $assetInfo = { assets => [] };
+ my $p = $self->getTreePaginator( $asset );
+
+ for my $assetId ( @{ $p->getPageData } ) {
+ my $asset = WebGUI::Asset->newById( $session, $assetId );
+
+ # Populate the required fields to fill in
+ my %fields = (
+ assetId => $asset->getId,
+ url => $asset->getUrl,
+ lineage => $asset->lineage,
+ title => $asset->menuTitle,
+ revisionDate => $asset->revisionDate,
+ childCount => $asset->getChildCount,
+ assetSize => $asset->assetSize,
+ lockedBy => ($asset->isLockedBy ? $asset->lockedBy->username : ''),
+ actions => $asset->canEdit && $asset->canEditIfLocked,
+ );
+
+ $fields{ className } = {};
+ # The asset icon
+ $fields{ icon } = $asset->getIcon("small");
+
+ # The asset type (i18n name)
+ $fields{ className } = $asset->getName;
+
+ push @{ $assetInfo->{ assets } }, \%fields;
+ }
+
+ $assetInfo->{ totalAssets } = $p->getRowCount;
+ $assetInfo->{ sort } = $session->form->get( 'orderByColumn' );
+ $assetInfo->{ dir } = lc $session->form->get( 'orderByDirection' );
+
+ $session->http->setMimeType( 'application/json' );
+
+ return to_json( $assetInfo );
+}
+
+#----------------------------------------------------------------------
+
=head2 www_view ( session )
Show the main Admin console wrapper
@@ -150,7 +240,7 @@ Show the main Admin console wrapper
=cut
sub www_view {
- my ($self) = @_;
+ my ( $self ) = @_;
my $session = $self->session;
my ( $user, $url, $style ) = $session->quick(qw{ user url style });
diff --git a/www/extras/admin/admin.js b/www/extras/admin/admin.js
index 696db56dd..af80cf597 100644
--- a/www/extras/admin/admin.js
+++ b/www/extras/admin/admin.js
@@ -7,38 +7,28 @@
if ( typeof WebGUI == "undefined" ) {
WebGUI = {};
}
-WebGUI.Admin = (function(){
- // Public methods
+WebGUI.Admin = function(){
+ // Public properties
+ this.cfg = cfg;
+ this.currentAssetDef = null;
+ this.viewOrTree = 0; // 0 - Last on View tab. 1 - Last on Tree tab
- return function (cfg) {
- // Public properties
- this.cfg = cfg;
- this.currentAssetDef = null;
- this.viewOrTree = 0; // 0 - Last on View tab. 1 - Last on Tree tab
+ // Default configuration
+ if ( !this.cfg.locationBarId ) {
+ this.cfg.locationBarId = "locationBar";
+ }
+ if ( !this.cfg.tabBarId ) {
+ this.cfg.tabBarId = "tabBar";
+ }
- // Default configuration
- if ( !this.cfg.locationBarId ) {
- this.cfg.locationBarId = "locationBar";
- }
- if ( !this.cfg.tabBarId ) {
- this.cfg.tabBarId = "tabBar";
- }
+ this.locationBar = new WebGUI.Admin.LocationBar( this.cfg.locationBarId );
+ this.tabBar = new YAHOO.widget.TabView( this.cfg.tabBarId );
+ // Keep track of View and Tree tabs
+ this.tabBar.getTab(0).addListener('click',this.afterShowViewTab,this,true);
+ this.tabBar.getTab(1).addListener('click',this.afterShowTreeTab,this,true);
- // Private properties
- var self = this;
-
- // Private methods
- function _init() {
- self.locationBar = new WebGUI.Admin.LocationBar( self.cfg.locationBarId );
- self.tabBar = new YAHOO.widget.TabView( self.cfg.tabBarId );
- // Keep track of View and Tree tabs
- self.tabBar.getTab(0).addListener('click',self.afterShowViewTab,self,true);
- self.tabBar.getTab(1).addListener('click',self.afterShowTreeTab,self,true);
- }
-
- _init();
- };
-})();
+ // Private methods
+};
/**
* afterShowTreeTab()
@@ -111,44 +101,41 @@ WebGUI.Admin.LocationBar
var self = this;
var _element = document.getElementById( self.id );
- function _init () {
- // Create buttons
- self.btnBack = new YAHOO.widget.Button( "backButton", {
- type : "split",
- label : '
',
- disabled : true,
- lazyloadmenu : false,
- onclick : { fn: self.goBack, scope: self },
- menu : []
- } );
- self.btnForward = new YAHOO.widget.Button( "forwardButton", {
- type : "split",
- label : '
',
- disabled : true,
- lazyloadmenu : false,
- onclick : { fn: self.goForward, scope: self },
- menu : []
- } );
- self.btnSearch = new YAHOO.widget.Button( "searchButton", {
- label : '
',
- onclick : { fn: self.clickSearchButton, scope: self }
- } );
- self.btnHome = new YAHOO.widget.Button( "homeButton", {
- type : "button",
- label : '
',
- onclick : { fn: self.goHome, scope: self }
- } );
- // Take control of the location input
- self.klInput = new YAHOO.util.KeyListener( "locationUrl", { keys: 13 }, {
- fn: self.doInputSearch,
- scope: self,
- correctScope: true
- } );
- YAHOO.util.Event.addListener( "locationUrl", "focus", self.inputFocus, self, true );
- YAHOO.util.Event.addListener( "locationUrl", "blur", self.inputBlur, self, true );
- }
+ // Create buttons
+ this.btnBack = new YAHOO.widget.Button( "backButton", {
+ type : "split",
+ label : '
',
+ disabled : true,
+ lazyloadmenu : false,
+ onclick : { fn: this.goBack, scope: this },
+ menu : []
+ } );
+ this.btnForward = new YAHOO.widget.Button( "forwardButton", {
+ type : "split",
+ label : '
',
+ disabled : true,
+ lazyloadmenu : false,
+ onclick : { fn: this.goForward, scope: this },
+ menu : []
+ } );
+ this.btnSearch = new YAHOO.widget.Button( "searchButton", {
+ label : '
',
+ onclick : { fn: this.clickSearchButton, scope: this }
+ } );
+ this.btnHome = new YAHOO.widget.Button( "homeButton", {
+ type : "button",
+ label : '
',
+ onclick : { fn: this.goHome, scope: this }
+ } );
+ // Take control of the location input
+ this.klInput = new YAHOO.util.KeyListener( "locationUrl", { keys: 13 }, {
+ fn: this.doInputSearch,
+ scope: this,
+ correctScope: true
+ } );
+ YAHOO.util.Event.addListener( "locationUrl", "focus", this.inputFocus, this, true );
+ YAHOO.util.Event.addListener( "locationUrl", "blur", this.inputBlur, this, true );
- _init();
};
/**
@@ -381,5 +368,400 @@ WebGUI.Admin.LocationBar.prototype.swapForwardToBack
};
+/****************************************************************************
+ *
+ * WebGUI.Admin.Tree
+ */
+
+WebGUI.Admin.Tree = function(){
+ this.moreMenusDisplayed = {};
+ this.crumbMoreMenu = null;
+};
+
+/**
+ * appendToUrl( url, params )
+ * Add URL components to a URL;
+ */
+WebGUI.Admin.Tree.prototype.appendToUrl = function ( url, params ) {
+ var components = [ url ];
+ if (url.match(/\?/)) {
+ components.push(";");
+ }
+ else {
+ components.push("?");
+ }
+ components.push(params);
+ return components.join('');
+};
+
+/**
+ * addHighlightToRow ( child )
+ * Highlight the row containing this element by adding to it the "highlight"
+ * class
+ */
+WebGUI.Admin.Tree.prototype.addHighlightToRow = function ( child ) {
+ var row = this.findRow( child );
+ if ( !YAHOO.util.Dom.hasClass( row, "highlight" ) ) {
+ YAHOO.util.Dom.addClass( row, "highlight" );
+ }
+};
+
+/**
+ * buildMoreMenu ( url, linkElement )
+ * Build a WebGUI style "More" menu for the asset referred to by url
+ */
+WebGUI.AssetManager.buildMoreMenu = function ( url, linkElement, isNotLocked ) {
+ var rawItems = this.moreMenuItems;
+ var menuItems = [];
+ var isLocked = !isNotLocked;
+ for ( var i = 0; i < rawItems.length; i++ ) {
+ var itemUrl = rawItems[i].url
+ ? this.appendToUrl(url, rawItems[i].url)
+ : url
+ ;
+ if (! (itemUrl.match( /func=edit;/) && isLocked )) {
+ menuItems.push( { "url" : itemUrl, "text" : rawItems[i].label } );
+ }
+ }
+ var options = {
+ "zindex" : 1000,
+ "clicktohide" : true,
+ "position" : "dynamic",
+ "context" : [ linkElement, "tl", "bl", ["beforeShow", "windowResize"] ],
+ "itemdata" : menuItems
+ };
+
+ return options;
+};
+
+/**
+ * findRow ( child )
+ * Find the row that contains this child element.
+ */
+WebGUI.Admin.Tree.prototype.findRow = function ( child ) {
+ var node = child;
+ while ( node ) {
+ if ( node.tagName == "TR" ) {
+ return node;
+ }
+ node = node.parentNode;
+ }
+};
+
+/**
+ * formatActions ( )
+ * Format the Edit and More links for the row
+ */
+WebGUI.AssetManager.formatActions = function ( elCell, oRecord, oColumn, orderNumber ) {
+ if ( oRecord.getData( 'actions' ) ) {
+ elCell.innerHTML
+ = ''
+ + WebGUI.AssetManager.i18n.get('Asset', 'edit') + ''
+ + ' | '
+ ;
+ }
+ else {
+ elCell.innerHTML = "";
+ }
+ var more = document.createElement( 'a' );
+ elCell.appendChild( more );
+ more.appendChild( document.createTextNode( WebGUI.AssetManager.i18n.get('Asset','More' ) ) );
+ more.href = '#';
+
+ // Delete the old menu
+ if ( document.getElementById( 'moreMenu' + oRecord.getData( 'assetId' ) ) ) {
+ var oldMenu = document.getElementById( 'moreMenu' + oRecord.getData( 'assetId' ) );
+ oldMenu.parentNode.removeChild( oldMenu );
+ }
+
+ var options = WebGUI.AssetManager.buildMoreMenu(oRecord.getData( 'url' ), more, oRecord.getData( 'actions' ));
+
+ var menu = new YAHOO.widget.Menu( "moreMenu" + oRecord.getData( 'assetId' ), options );
+ YAHOO.util.Event.onDOMReady( function () { menu.render( document.getElementById( 'assetManager' ) ); } );
+ YAHOO.util.Event.addListener( more, "click", function (e) { YAHOO.util.Event.stopEvent(e); menu.show(); menu.focus(); }, null, menu );
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatAssetIdCheckbox ( )
+ Format the checkbox for the asset ID.
+*/
+WebGUI.AssetManager.formatAssetIdCheckbox = function ( elCell, oRecord, oColumn, orderNumber ) {
+ elCell.innerHTML = '';
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatAssetSize ( )
+ Format the asset class name
+*/
+WebGUI.AssetManager.formatAssetSize = function ( elCell, oRecord, oColumn, orderNumber ) {
+ elCell.innerHTML = oRecord.getData( "assetSize" );
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatClassName ( )
+ Format the asset class name
+*/
+WebGUI.AssetManager.formatClassName = function ( elCell, oRecord, oColumn, orderNumber ) {
+ elCell.innerHTML = '
'
+ + oRecord.getData( "className" );
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatLockedBy ( )
+ Format the asset class name
+*/
+WebGUI.AssetManager.formatLockedBy = function ( elCell, oRecord, oColumn, orderNumber ) {
+ var extras = getWebguiProperty('extrasURL');
+ elCell.innerHTML
+ = oRecord.getData( 'lockedBy' )
+ ? ''
+ + '
'
+ + ''
+ : ''
+ + '
'
+ + ''
+ ;
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatRank ( )
+ Format the input for the rank box
+*/
+WebGUI.AssetManager.formatRank = function ( elCell, oRecord, oColumn, orderNumber ) {
+ var rank = oRecord.getData("lineage").match(/[1-9][0-9]{0,5}$/);
+ elCell.innerHTML = '';
+};
+
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.DefaultSortedBy ( )
+*/
+WebGUI.AssetManager.DefaultSortedBy = {
+ "key" : "lineage",
+ "dir" : YAHOO.widget.DataTable.CLASS_ASC
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.BuildQueryString ( )
+*/
+WebGUI.AssetManager.BuildQueryString = function ( state, dt ) {
+ var query = "recordOffset=" + state.pagination.recordOffset
+ + ';orderByDirection=' + ((state.sortedBy.dir === YAHOO.widget.DataTable.CLASS_DESC) ? "DESC" : "ASC")
+ + ';rowsPerPage=' + state.pagination.rowsPerPage
+ + ';orderByColumn=' + state.sortedBy.key
+ ;
+ return query;
+ };
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatRevisionDate ( )
+ Format the asset class name
+*/
+WebGUI.AssetManager.formatRevisionDate = function ( elCell, oRecord, oColumn, orderNumber ) {
+ var revisionDate = new Date( oRecord.getData( "revisionDate" ) * 1000 );
+ var minutes = revisionDate.getMinutes();
+ if (minutes < 10) {
+ minutes = "0" + minutes;
+ }
+ elCell.innerHTML = revisionDate.getFullYear() + '-' + ( revisionDate.getMonth() + 1 )
+ + '-' + revisionDate.getDate() + ' ' + ( revisionDate.getHours() )
+ + ':' + minutes
+ ;
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.formatTitle ( )
+ Format the link for the title
+*/
+WebGUI.AssetManager.formatTitle = function ( elCell, oRecord, oColumn, orderNumber ) {
+ elCell.innerHTML = ''
+ + ( oRecord.getData( 'childCount' ) > 0 ? "+" : " " )
+ + ' '
+ + oRecord.getData( 'title' )
+ + ''
+ ;
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.initManager ( )
+ Initialize the i18n interface
+*/
+WebGUI.AssetManager.initManager = function (o) {
+ WebGUI.AssetManager.i18n
+ = new WebGUI.i18n( {
+ namespaces : {
+ 'Asset' : [
+ "edit",
+ "More",
+ "unlocked",
+ "locked by"
+ ],
+ 'WebGUI' : [
+ "< prev",
+ "next >"
+ ]
+ },
+ onpreload : {
+ fn : WebGUI.AssetManager.initDataTable
+ }
+ } );
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.initDataTable ( )
+ Initialize the www_manage page
+*/
+WebGUI.AssetManager.initDataTable = function (o) {
+ var assetPaginator = new YAHOO.widget.Paginator({
+ containers : ['pagination'],
+ pageLinks : 7,
+ rowsPerPage : 100,
+ previousPageLinkLabel : WebGUI.AssetManager.i18n.get('WebGUI', '< prev'),
+ nextPageLinkLabel : WebGUI.AssetManager.i18n.get('WebGUI', 'next >'),
+ template : "{CurrentPageReport} {PreviousPageLink} {PageLinks} {NextPageLink}"
+ });
+
+
+ // initialize the data source
+ WebGUI.AssetManager.DataSource
+ = new YAHOO.util.DataSource( '?op=assetManager;method=ajaxGetManagerPage;',{connTimeout:30000} );
+ WebGUI.AssetManager.DataSource.responseType
+ = YAHOO.util.DataSource.TYPE_JSON;
+ WebGUI.AssetManager.DataSource.responseSchema
+ = {
+ resultsList: 'assets',
+ fields: [
+ { key: 'assetId' },
+ { key: 'lineage' },
+ { key: 'actions' },
+ { key: 'title' },
+ { key: 'className' },
+ { key: 'revisionDate' },
+ { key: 'assetSize' },
+ { key: 'lockedBy' },
+ { key: 'icon' },
+ { key: 'url' },
+ { key: 'childCount' }
+ ],
+ metaFields: {
+ totalRecords: "totalAssets" // Access to value in the server response
+ }
+ };
+
+
+
+ // Initialize the data table
+ WebGUI.AssetManager.DataTable
+ = new YAHOO.widget.DataTable( 'dataTableContainer',
+ WebGUI.AssetManager.ColumnDefs,
+ WebGUI.AssetManager.DataSource,
+ {
+ initialRequest : 'recordOffset=0',
+ dynamicData : true,
+ paginator : assetPaginator,
+ sortedBy : WebGUI.AssetManager.DefaultSortedBy,
+ generateRequest : WebGUI.AssetManager.BuildQueryString
+ }
+ );
+
+ WebGUI.AssetManager.DataTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
+ oPayload.totalRecords = oResponse.meta.totalRecords;
+ return oPayload;
+ };
+
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.removeHighlightFromRow ( child )
+ Remove the highlight from a row by removing the "highlight" class.
+*/
+WebGUI.AssetManager.removeHighlightFromRow = function ( child ) {
+ var row = WebGUI.AssetManager.findRow( child );
+ if ( YAHOO.util.Dom.hasClass( row, "highlight" ) ) {
+ YAHOO.util.Dom.removeClass( row, "highlight" );
+ }
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.selectRow ( child )
+ Check the assetId checkbox in the row that contains the given child.
+ Used when something in the row changes.
+*/
+WebGUI.AssetManager.selectRow = function ( child ) {
+ // First find the row
+ var node = WebGUI.AssetManager.findRow( child );
+ WebGUI.AssetManager.addHighlightToRow( child );
+
+ // Now find the assetId checkbox in the first element
+ var inputs = node.getElementsByTagName( "input" );
+ for ( var i = 0; i < inputs.length; i++ ) {
+ if ( inputs[i].name == "assetId" ) {
+ inputs[i].checked = true;
+ break;
+ }
+ }
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.showMoreMenu ( url, linkTextId )
+ Build a More menu for the last element of the Crumb trail
+*/
+WebGUI.AssetManager.showMoreMenu
+= function ( url, linkTextId, isNotLocked ) {
+
+ var menu;
+ if ( typeof WebGUI.AssetManager.CrumbMoreMenu == "undefined" ) {
+ var more = document.getElementById(linkTextId);
+ var options = WebGUI.AssetManager.buildMoreMenu(url, more, isNotLocked);
+ menu = new YAHOO.widget.Menu( "crumbMoreMenu", options );
+ menu.render( document.getElementById( 'assetManager' ) );
+ WebGUI.AssetManager.CrumbMoreMenu = menu;
+ }
+ else {
+ menu = WebGUI.AssetManager.CrumbMoreMenu;
+ }
+ menu.show();
+ menu.focus();
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.toggleHighlightForRow ( checkbox )
+ Toggle the highlight for the row based on the state of the checkbox
+*/
+WebGUI.AssetManager.toggleHighlightForRow = function ( checkbox ) {
+ if ( checkbox.checked ) {
+ WebGUI.AssetManager.addHighlightToRow( checkbox );
+ }
+ else {
+ WebGUI.AssetManager.removeHighlightFromRow( checkbox );
+ }
+};
+
+/*---------------------------------------------------------------------------
+ WebGUI.AssetManager.toggleRow ( child )
+ Toggles the entire row by finding the checkbox and doing what needs to be
+ done.
+*/
+WebGUI.AssetManager.toggleRow = function ( child ) {
+ var row = WebGUI.AssetManager.findRow( child );
+
+ // Find the checkbox
+ var inputs = row.getElementsByTagName( "input" );
+ for ( var i = 0; i < inputs.length; i++ ) {
+ if ( inputs[i].name == "assetId" ) {
+ inputs[i].checked = inputs[i].checked
+ ? false
+ : true
+ ;
+ WebGUI.AssetManager.toggleHighlightForRow( inputs[i] );
+ break;
+ }
+ }
+};