diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 6a672ea99..25895da56 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -13,6 +13,7 @@ - fixed #11432: DataTable date input - fixed #11772: Metadata in Post doesn't set default value correctly - fixed #11768: Edit Branch does not update File wgaccess permissions + - added Asset Report Asset allowing creation of reports based on Asset Properties. 7.9.10 - fixed #11721: spamStopWords not in WebGUI.conf.original diff --git a/docs/upgrades/packages-7.9.11/pb_asset_report.wgpkg b/docs/upgrades/packages-7.9.11/pb_asset_report.wgpkg new file mode 100644 index 000000000..a40bfb28d Binary files /dev/null and b/docs/upgrades/packages-7.9.11/pb_asset_report.wgpkg differ diff --git a/docs/upgrades/upgrade_7.9.10-7.9.11.pl b/docs/upgrades/upgrade_7.9.10-7.9.11.pl index 420d8274c..8276f9a1c 100644 --- a/docs/upgrades/upgrade_7.9.10-7.9.11.pl +++ b/docs/upgrades/upgrade_7.9.10-7.9.11.pl @@ -32,6 +32,7 @@ my $session = start(); # this line required # upgrade functions go here alterStoryTopicTable($session); +addAssetReport($session); finish($session); # this line required @@ -45,6 +46,30 @@ finish($session); # this line required # print "DONE!\n" unless $quiet; #} +#---------------------------------------------------------------------------- +# Describe what our function does +sub addAssetReport { + my $session = shift; + print "\tAdding Asset Report Asset ... " unless $quiet; + + #Add the database table + $session->db->write(q{ + CREATE TABLE `AssetReport` ( + `assetId` char(22) character set utf8 collate utf8_bin NOT NULL, + `revisionDate` bigint(20) NOT NULL, + `settings` mediumtext, + `templateId` char(22) character set utf8 collate utf8_bin default NULL, + `paginateAfter` bigint(20) default NULL, + PRIMARY KEY (`assetId`,`revisionDate`) + ) + }); + + #Add the asset to the config file + $session->config->addToHash( "assets", "WebGUI::Asset::Wobject::AssetReport", { category => "utilities" } ); + + print "DONE!\n" unless $quiet; +} + #---------------------------------------------------------------------------- # Describe what our function does sub alterStoryTopicTable { diff --git a/lib/WebGUI/Asset/Wobject/AssetReport.pm b/lib/WebGUI/Asset/Wobject/AssetReport.pm new file mode 100644 index 000000000..4fa6f4c53 --- /dev/null +++ b/lib/WebGUI/Asset/Wobject/AssetReport.pm @@ -0,0 +1,297 @@ +package WebGUI::Asset::Wobject::AssetReport; + +$VERSION = "1.0.0"; + +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2009 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------- +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------- + +use strict; +use Tie::IxHash; +use WebGUI::International; +use WebGUI::Paginator; +use WebGUI::Utility; +use Class::C3; +use base qw/WebGUI::AssetAspect::Installable WebGUI::Asset::Wobject/; + +#------------------------------------------------------------------- + +=head2 definition ( session, definition ) + +=cut + +sub definition { + my $class = shift; + my $session = shift; + my $definition = shift; + my $i18n = WebGUI::International->new( $session, 'Asset_AssetReport' ); + + tie my %properties, 'Tie::IxHash', ( + settings => { + tab => 'properties', + fieldType => 'AssetReportQuery', + defaultValue => undef, + }, + templateId => { + tab => "display", + fieldType => "template", + namespace => "AssetReport", + defaultValue => "sJtcUCfn0CVbKdb4QM61Yw", + label => $i18n->get("templateId label"), + hoverHelp => $i18n->get("templateId description"), + }, + paginateAfter => { + tab => 'display', + fieldType => 'integer', + defaultValue => 25, + label => $i18n->get( 'paginateAfter label' ), + hoverHelp => $i18n->get( 'paginateAfter description' ), + }, + ); + + push @{$definition}, { + assetName => $i18n->get('assetName'), + autoGenerateForms => 1, + tableName => 'AssetReport', + className => 'WebGUI::Asset::Wobject::AssetReport', + properties => \%properties, + }; + + return $class->SUPER::definition( $session, $definition ); +} ## end sub definition + + +#---------------------------------------------------------------------------- + +=head2 prepareView ( ) + +Prepare the view. Add stuff to HEAD. + +=cut + +sub prepareView { + my $self = shift; + $self->SUPER::prepareView(@_); + my $session = $self->session; + + # Prepare the template + my $template = WebGUI::Asset::Template->new( $session, $self->get("templateId") ); + if (!$template) { + WebGUI::Error::ObjectNotFound::Template->throw( + error => qq{Template not found}, + templateId => $self->get("templateId"), + assetId => $self->getId, + ); + } + $template->prepare; + $self->{_template} = $template; + + return; +} ## end sub prepareView + +#---------------------------------------------------------------------------- + +=head2 getTemplateVars ( ) + +Get template variables common to all views of the Asset Report. + +=cut + +sub getTemplateVars { + my $self = shift; + my $session = $self->session; + + my $var = $self->get; + + #Build the lineage query + my $settings = JSON->new->decode($self->getValue("settings")); + + #TO DO - ADD CACHE CONTROL + + my $assetId = $settings->{startNode}; + my $asset = WebGUI::Asset->newByDynamicClass($session,$assetId); + + my $rules = {}; + $rules->{'isa'} = $settings->{className}; + + #Build where condition + my $condition = $settings->{anySelect}; + $rules->{'whereClause'} = undef; + my $where = $settings->{where}; + foreach my $key (keys %{$where}) { + my $clause = $where->{$key}; + my $prop = $clause->{propSelect}; + my $op = $clause->{opSelect}; + my $value = $clause->{valText}; + + $rules->{'whereClause'} .= qq{ $condition } if ($key > 1); + $rules->{'whereClause'} .= qq{$prop $op $value}; + } + + if($rules->{'whereClause'}) { + $rules->{'joinClass'} = $settings->{className}; + } + + #Build the order by condition + my $order = $settings->{order}; + my @order = keys %{$order}; + if(scalar(@order)) { + $rules->{'orderByClause'} = undef; + foreach my $key (@order) { + my $orderBy = $order->{$key}; + my $orderSelect = $orderBy->{orderSelect}; + my $dirSelect = $orderBy->{dirSelect}; + + $rules->{'orderByClause'} .= q{, } if($key > 1); + $rules->{'orderByClause'} .= qq{$orderSelect $dirSelect}; + } + } + + if($settings->{'limit'}) { + $rules->{'limit'} = $settings->{'limit'}; + } + my $sql = $asset->getLineageSql(["descendants"],$rules); + + my $p = WebGUI::Paginator->new($session,$self->getUrl,$self->get("paginateAfter")); + $p->setDataByQuery($sql); + + #Build the data for all the assets on the page + $var->{'asset_loop'} = []; + my $data = $p->getPageData; + foreach my $row (@{$data}) { + my $returnAsset = WebGUI::Asset->new($session,$row->{assetId},$row->{className},$row->{revisionDate}); + push(@{$var->{'asset_loop'}},$returnAsset->get); + } + + #Append template variables + $p->appendTemplateVars($var); + + return $var; +} + +#---------------------------------------------------------------------------- + +=head2 view ( ) + +method called by the www_view method. Returns a processed template +to be displayed within the page style. + +=cut + +sub view { + my $self = shift; + my $var = $self->getTemplateVars; + + return $self->processTemplate( $var, undef, $self->{_template} ); +} ## end sub view + +#------------------------------------------------------------------- +# Install Methods Below - Do Not Modify + +#------------------------------------------------------------------- +sub install { + my $class = shift; + my $session = shift; + $class->next::method( $session ); + + ### Create a folder asset to store the default template + my $importNode = WebGUI::Asset->getImportNode($session); + my $folder = $importNode->addChild({ + className => "WebGUI::Asset::Wobject::Folder", + title => "Asset Report", + menuTitle => "Asset Report", + url => "pb_asset_report", + groupIdView =>"3" + },"AssetReportFolder00001"); + + ### Add the template to the folder + $folder->addChild({ + className => "WebGUI::Asset::Template", + namespace => "AssetReport", + title => "Asset Report Default Template", + menuTitle => "Asset Report Default Template", + ownerUserId => "3", + groupIdView => "7", + groupIdEdit => "4", + isHidden => 1, + isDefault => 1, + template => qq{ + + + +

+
+ + +

+
+ + + + + + + +

+ + + + + + + + + + + + + + + + + + + +
TitleCreation DateCreated By
^D('%C %D, %y %h:%s %p',);^User('username',);
+ + +

+
+ }, + headBlock =>"", + }, "AssetReport00000000001"); + + ### Commit version tag + my $tag = WebGUI::VersionTag->new($session, WebGUI::VersionTag->getWorking($session)->getId); + if (defined $tag) { + $tag->set({comments=>"Template added/updated by Asset Install Process"}); + $tag->requestCommit; + } +} + +#------------------------------------------------------------------- +sub uninstall { + my $class = shift; + my $session = shift; + $class->next::method( $session ); + + my $template = WebGUI::Asset->newByDynamicClass($session,"AssetReport00000000001"); + $template->purge if($template); + + my $folder = WebGUI::Asset->newByDynamicClass($session,"AssetReportFolder00001"); + $folder->purge if($folder); +} + +1; diff --git a/lib/WebGUI/Form/AssetReportQuery.pm b/lib/WebGUI/Form/AssetReportQuery.pm new file mode 100644 index 000000000..ae38ab61f --- /dev/null +++ b/lib/WebGUI/Form/AssetReportQuery.pm @@ -0,0 +1,423 @@ +package WebGUI::Form::AssetReportQuery; + +use strict; +use base 'WebGUI::Form::Control'; +use JSON; +use WebGUI::International; +use WebGUI::Utility; + +=head1 NAME + +WebGUI::Form::BooleanQuery -- Build a boolean query + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +=head1 METHODS + +=cut + + +#------------------------------------------------------------------- + +=head2 getDatabaseFieldType ( ) + +Returns "MEDIUMTEXT". + +=cut + +sub getDatabaseFieldType { + return "MEDIUMTEXT"; +} + +#---------------------------------------------------------------------------- + +=head2 getAnyList + +Get the operator list. + +=cut + +sub getAnyList { + my $self = shift; + my $i18n = $self->i18n; + + tie my %options, 'Tie::IxHash', ( + 'or' => $i18n->get("any option"), + 'and' => $i18n->get("all option"), + ); + + return \%options; +} + +#---------------------------------------------------------------------------- + +=head2 getDirs + +Get the direction list. + +=cut + +sub getDirs { + my $self = shift; + my $i18n = $self->i18n; + + tie my %options, 'Tie::IxHash', ( + 'asc' => $i18n->get("ascending option"), + 'desc' => $i18n->get("descending option"), + ); + + return \%options; +} + + +#---------------------------------------------------------------------------- + +=head2 getOps + +Get the operator list. + +=cut + +sub getOps { + my $self = shift; + + tie my %options, 'Tie::IxHash', ( + '=' => '=', + '<>' => '<>', + '>' => '>', + '>=' => '>=', + '<' => '<', + '<=' => '<=', + 'LIKE' => 'LIKE', + 'NOT LIKE' => 'NOT LIKE', + 'IS NULL' => 'IS NULL', + 'IS NOT NULL' => 'IS NOT NULL', + ); + + return \%options; +} + +#---------------------------------------------------------------------------- + +=head2 getValue () + +Get the value of the form + +=cut + +sub getValue { + my $self = shift; + my $session = $self->session; + my $form = $session->form; + + my $propCount = $form->process("propCount","hidden"); + my $orderCount = $form->process("orderCount","hidden"); + + if($propCount) { + my $where = {}; + my $whereCount = 1; + for(my $i = 0; $i < $propCount; $i++ ) { + my $propSelect = $form->process("propSelect_".$i,"selectBox"); + if($propSelect ne "") { + my $opSelect = $form->process("opSelect_".$i,"selectBox"); + my $valText = $form->process("valText_".$i,"text"); + $where->{$whereCount} = { + propSelect => $propSelect, + opSelect => $opSelect, + valText => $valText, + }; + $whereCount++; + } + } + + my $orderBy = {}; + my $orderByCount = 1; + for(my $i = 0; $i < $orderCount; $i++ ) { + my $orderSelect = $form->process("orderSelect_".$i,"selectBox"); + if($orderSelect ne "") { + my $dirSelect = $form->process("dirSelect_".$i,"selectBox"); + $orderBy->{$orderByCount} = { + "orderSelect" => $orderSelect, + "dirSelect" => $dirSelect, + }; + $orderByCount++; + } + } + + my $jsonHash = { + isNew => "false", + className => $form->process("className","selectBox"), + startNode => $form->process("startNode","asset"), + anySelect => $form->process("anySelect","selectBox"), + where => $where, + whereCount => $whereCount, + order => $orderBy, + orderCount => $orderByCount, + limit => $form->process("limit","integer"), + }; + + my $jsonStr = JSON->new->canonical->encode($jsonHash); + + #Set the value in the form + $self->set('value',$jsonStr); + } + + return $self->get('value') || $self->get('defaultValue'); +} + +#------------------------------------------------------------------- + +=head2 i18n + +Returns the i18n object for the form + +=cut + +sub i18n { + my $self = shift; + my $session = $self->session; + + unless ($self->{_i18n}) { + $self->{_i18n} + = WebGUI::International->new($session,'Form_AssetReportQuery'); + } + + return $self->{_i18n}; +} +#---------------------------------------------------------------------------- + +=head2 toHtml + +Render the form control. + +=cut + +sub toHtml { + my $self = shift; + my $session = $self->session; + my $db = $session->db; + my $style = $session->style; + my $i18n = $self->i18n; + + #Build a JSON Array of all the possible classes and their fields + my $json = {}; + #Get all of the classes being used in the WebGUI instance + my $classes = $db->buildArrayRef(q{ + SELECT + distinct className + FROM + asset + ORDER BY + className + }); + + #Hard code these for now + my %asset = ( + "asset.creationDate" => "creationDate (asset)", + "asset.createdBy" => "createdBy (asset)", + "asset.stateChanged" => "stateChanged (asset)", + "asset.stateChangedBy" => "stateChangedBy (asset)", + "asset.isLockedBy" => "isLockedBy (asset)", + ); + + #Get the fields from the definition of each class + foreach my $class (@{$classes}) { + my $definitions = $class->definition($session); + tie my %fields, "Tie::IxHash", (); + foreach my $definition (@{$definitions}) { + my $properties = $definition->{properties}; + my $tableName = $definition->{tableName}; + foreach my $property (keys %{$properties}) { + my $key = $tableName.".".$property; + $fields{$key} = qq{$property ($tableName)}; + } + } + + %fields = (%asset,%fields); + %fields = WebGUI::Utility::sortHash(%fields); + $json->{$class} = \%fields; + } + + #Encode the JSON and add it to the end of the body + my $jsonStr = JSON->new->encode($json); + $style->setRawHeadTags(qq||); + my $jsonData = $self->get("value") || q|{ "isNew" : "true" }|; + $style->setRawHeadTags(qq||); + $session->style->setScript($session->url->extras("yui-webgui/build/form/assetReportQuery.js"),{ type=>"text/javascript" }); + + #Decode JSON data for filling in some of the fields + my $jsonDataHash = JSON->new->decode($jsonData); + + #Class select list + my $classSelect = WebGUI::Form::selectBox($session,{ + name =>"className", + value => "", + options => {}, + extras => q{onchange="loadClassName(this.value);"}, + }); + + #Start Node + my $startNode = WebGUI::Form::asset($session,{ + name =>"startNode", + value => $jsonDataHash->{startNode}, + }); + + #Any Select + my $anySelect = WebGUI::Form::selectBox($session, { + name => "anySelect", + value => $jsonDataHash->{anySelect}, + options => $self->getAnyList, + }); + + #Property Select + my $propSelect = WebGUI::Form::selectBox($session,{ + name => "propSelect", + value => "", + options => { ""=>$i18n->get("choose one option") }, + }); + + #Op Select + my $opSelect = WebGUI::Form::selectBox( $session, { + name => "opSelect", + value => "", + options => $self->getOps, + }); + + #Value Test + my $valText = WebGUI::Form::text($session,{ + name => "valText" + }); + + #Delete Button + my $deleteButton = WebGUI::Form::button($session,{ + value => "-", + extras => q{id="deleteButton_formId"} + }); + + #Add Button + my $addButton = WebGUI::Form::button($session,{ + value => "+", + extras => q{ onclick="addRow(document.getElementById('row_1'),document.getElementById('whereBody'),'propCount_id');" }, + }); + + #Order Select + my $orderSelect = WebGUI::Form::selectBox($session,{ + name => "orderSelect", + value => "", + options => { ""=>$i18n->get("choose one option") }, + }); + + #Dir Select + my $dirSelect = WebGUI::Form::selectBox($session, { + name => "dirSelect", + value => "", + options => $self->getDirs, + }); + + #Delete Button + my $orderDelButton = WebGUI::Form::button($session,{ + value => "-", + extras => q{id="orderDelButton_formId"} + }); + + #Add Button + my $orderAddButton = WebGUI::Form::button($session,{ + value => "+", + extras => q{ onclick="addRow(document.getElementById('order_1'),document.getElementById('orderBody'),'orderCount_id');" }, + }); + + #Prop Count + my $propCount = WebGUI::Form::hidden($session, { + name => "propCount", + value => 1, + extras => q{id="propCount_id"}, + }); + + #Order Count + my $orderCount = WebGUI::Form::hidden($session, { + name => "orderCount", + value => 1, + extras => q{id="orderCount_id"}, + }); + + #Limit + my $limit = WebGUI::Form::integer($session,{ + name => "limit", + value => $jsonDataHash->{limit}, + }); + + + my $classSelectLabel = $i18n->get("class select label"); + my $startNodeLabel = $i18n->get("start node label"); + my $anySelectLabel = sprintf($i18n->get("any select label"), $anySelect); + my $orderByLabel = $i18n->get("order by label"); + my $limitLabel = $i18n->get("limit label"); + my $limitSubText = $i18n->get("limit subtext"); + + #Choose a class + my $output = qq{ + $propCount + $orderCount + + + + + + + +
$classSelectLabel
$classSelect
+ + + + + + + +
$startNodeLabel
$startNode
+ + + + +
$anySelectLabel
+ + + + + + + + + + +
$propSelect$opSelect$valText$deleteButton$addButton
+ + + + + + + + + + + + +
$orderByLabel
$orderSelect$dirSelect$orderDelButton$orderAddButton
+ + + + + + + + + +
$limitLabel
$limit ($limitSubText)
+ }; + + return $output; +} + +1; diff --git a/lib/WebGUI/i18n/English/Asset_AssetReport.pm b/lib/WebGUI/i18n/English/Asset_AssetReport.pm new file mode 100644 index 000000000..50ff4a949 --- /dev/null +++ b/lib/WebGUI/i18n/English/Asset_AssetReport.pm @@ -0,0 +1,37 @@ +package WebGUI::i18n::English::Asset_AssetReport; + +use strict; + +our $I18N = { + 'assetName' => { + message => q{Asset Report}, + lastUpdated => 0, + }, + + 'templateId label' => { + message => q{Asset Report Template}, + lastUpdated => 1226174617, + context => q{Label for asset edit screen}, + }, + + 'templateId description' => { + message => q{Select a template to display your asset report.}, + lastUpdated => 1226174619, + context => q{Hover help for asset edit screen}, + }, + + 'paginateAfter label' => { + message => q{Assets Per Page}, + lastUpdated => 1226174617, + context => q{Label for asset edit screen}, + }, + + 'paginateAfter description' => { + message => q{Choose the number of assets to display per page.}, + lastUpdated => 1226174619, + context => q{Hover help for asset edit screen}, + }, + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Form_AssetReportQuery.pm b/lib/WebGUI/i18n/English/Form_AssetReportQuery.pm new file mode 100644 index 000000000..979b29b88 --- /dev/null +++ b/lib/WebGUI/i18n/English/Form_AssetReportQuery.pm @@ -0,0 +1,73 @@ +package WebGUI::i18n::English::Form_AssetReportQuery; +use strict; + +our $I18N = { + 'any option' => { + message => q|any|, + lastUpdated => 1078852836, + context => q{Select list option in AssetReportQuery Form}, + }, + + 'all option' => { + message => q|all|, + lastUpdated => 1078852836, + context => q{Select list option in AssetReportQuery Form}, + }, + + 'ascending option' => { + message => q|Ascending|, + lastUpdated => 1078852836, + context => q{Select list option in AssetReportQuery Form}, + }, + + 'descending option' => { + message => q|Descending|, + lastUpdated => 1078852836, + context => q{Select list option in AssetReportQuery Form}, + }, + + 'choose one option' => { + message => q|Choose One|, + lastUpdated => 1078852836, + context => q{Select list option in AssetReportQuery Form}, + }, + + 'class select label' => { + message => q|Search for assets of type|, + lastUpdated => 1078852836, + context => q{Text label in AssetReportQuery Form}, + }, + + 'start node label' => { + message => q|That are descendants of the following asset|, + lastUpdated => 1078852836, + context => q{Text label in AssetReportQuery Form}, + }, + + 'any select label' => { + message => q|Matching %s of the following constraints|, + lastUpdated => 1078852836, + context => q{Text label in AssetReportQuery Form}, + }, + + 'order by label' => { + message => q|Order the results by|, + lastUpdated => 1078852836, + context => q{Text label in AssetReportQuery Form}, + }, + + 'limit label' => { + message => q|Limit the number of results returned to|, + lastUpdated => 1078852836, + context => q{Text label in AssetReportQuery Form}, + }, + + 'limit subtext' => { + message => q|Enter a zero if you do not wish to limit the number of results|, + lastUpdated => 1078852836, + context => q{Subtext for limit field in AssetReportQuery Form}, + }, + +}; + +1; diff --git a/t/Asset/Wobject/AssetReport.t b/t/Asset/Wobject/AssetReport.t new file mode 100644 index 000000000..07480cc23 --- /dev/null +++ b/t/Asset/Wobject/AssetReport.t @@ -0,0 +1,127 @@ +# vim:syntax=perl +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2009 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------ +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------ + +# This tests the AssetReport asset +# +# + +use FindBin; +use strict; +use lib "$FindBin::Bin/../../lib"; +use Test::More; +use Test::Deep; +use JSON; +use WebGUI::Test; # Must use this before any other WebGUI modules +use WebGUI::Session; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; +my $node = WebGUI::Asset->getImportNode( $session ); + +#---------------------------------------------------------------------------- +# Tests + +plan tests => 3; # Increment this number for each test you create + +#---------------------------------------------------------------------------- +# Asset Report creation +use_ok( "WebGUI::Asset::Wobject::AssetReport" ); +my $ar = $node->addChild( { + className => 'WebGUI::Asset::Wobject::AssetReport', +} ); + +isa_ok( $ar, 'WebGUI::Asset::Wobject::AssetReport' ); +WebGUI::Test->addToCleanup($ar); + +my $f = $node->addChild({ + className => 'WebGUI::Asset::Wobject::Folder', + title => 'Asset Report Test', +}); +WebGUI::Test->addToCleanup($f); + +my $sn = $f->addChild({ + className => 'WebGUI::Asset::Snippet', + title => 'Shawshank', +}); + +#---------------------------------------------------------------------------- +# Value and variables +my $value = { + isNew => "false", + className => "WebGUI::Asset::Snippet", + startNode => $f->getId, + anySelect => "or", + where => { + 1 => { + opSelect => "=", + propSelect => "assetData.title", + valText => "'Shawshank'" + }, + }, + whereCount => "2", + order => { + 1 => { + dirSelect => "desc", + orderSelect => "assetData.title" + }, + }, + orderCount => "2", + limit => "0", +}; + +my $settings = JSON->new->encode( $value ); + +$ar->update( { + settings => $settings, + paginateAfter => 50, +} ); + +#---------------------------------------------------------------------------- +# getTemplateVars + +cmp_deeply( + $ar->getTemplateVars, + hash( { + %{ $ar->get }, + 'settings' => $settings, + 'paginateAfter' => 50, + 'templateId' => 'sJtcUCfn0CVbKdb4QM61Yw', + 'pagination.firstPageUrl' => ignore(), + 'pagination.isLastPage' => ignore(), + 'pagination.nextPage' => ignore(), + 'pagination.previousPageUrl' => ignore(), + 'pagination.lastPageText' => ignore(), + 'pagination.pageCount' => ignore(), + 'pagination.firstPageText' => ignore(), + 'pagination.previousPage' => ignore(), + 'pagination.pageLoop' => ignore(), + 'pagination.lastPage' => ignore(), + 'pagination.lastPageUrl' => ignore(), + 'pagination.pageNumber' => ignore(), + 'pagination.pageList.upTo10' => ignore(), + 'pagination.pageCount.isMultiple' => ignore(), + 'pagination.pageList' => ignore(), + 'pagination.previousPageText' => ignore(), + 'pagination.nextPageUrl' => ignore(), + 'pagination.pageLoop.upTo10' => ignore(), + 'pagination.pageList.upTo20' => ignore(), + 'pagination.pageLoop.upTo20' => ignore(), + 'pagination.isFirstPage' => ignore(), + 'pagination.nextPageText' => ignore(), + 'pagination.firstPage' => ignore(), + 'asset_loop' => [{ %{ $sn->get } }], + } ), + "getTemplateVars returns complete and correct data structure", +); + + +#vim:ft=perl diff --git a/t/Form/AssetReportQuery.t b/t/Form/AssetReportQuery.t new file mode 100644 index 000000000..b5b2523c7 --- /dev/null +++ b/t/Form/AssetReportQuery.t @@ -0,0 +1,59 @@ +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2009 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------- +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------- + +use FindBin; +use strict; +use lib "$FindBin::Bin/../lib"; + +use WebGUI::Test; +use WebGUI::Form; +use WebGUI::Form::AssetReportQuery; +use WebGUI::Session; +use HTML::Form; +use WebGUI::Form_Checking; + +#The goal of this test is to verify that Radio form elements work + +use Test::More; # increment this value for each test you create + +my $session = WebGUI::Test->session; +my $node = WebGUI::Asset->getImportNode( $session ); +my $nodeId = $node->getId; + +#---------------------------------------------------------------------------- +# Tests + +plan tests => 1; # Increment this number for each test you create + +#---------------------------------------------------------------------------- +# put your tests here +$session->request->setup_body({ + className => "WebGUI::Asset", + propCount => 2, + orderCount => 2, + startNode => $nodeId, + startNode_display => "Import Node", + anySelect => "or", + propSelect_1 => "asset.createdBy", + opSelect_1 => "=", + valText_1 => "3", + orderSelect_1 => "assetData.title", + dirSelect_1 => "desc", + limit => "25", +}); + +my $arq = WebGUI::Form::AssetReportQuery->new($session); + +my $expected = qq|{"anySelect":"or","className":"WebGUI::Asset","isNew":"false","limit":"25","order":{"1":{"dirSelect":"desc","orderSelect":"assetData.title"}},"orderCount":2,"startNode":"$nodeId","where":{"1":{"opSelect":"=","propSelect":"asset.createdBy","valText":"3"}},"whereCount":2}|; + +is($arq->getValue, $expected, 'getValue'); + + +#my $value = $session->form->process("settings","AssetReportQuery"); diff --git a/www/extras/yui-webgui/build/form/assetReportQuery.js b/www/extras/yui-webgui/build/form/assetReportQuery.js new file mode 100644 index 000000000..01179abdb --- /dev/null +++ b/www/extras/yui-webgui/build/form/assetReportQuery.js @@ -0,0 +1,363 @@ +var classArray = []; + +//----------------------------------------------------------------------------------- +function addRow(row,ttbody,countId,data) { + //Get the count + var count = getCount(countId); + + //Set default data + if(data == null) data = {}; + + //Clone The Row + var tr = row.cloneNode(true); + + //Get the row type + var rowType = getRowType(tr.id); + + //Set the rowId + tr.id = rowType + '_' + count; + + //Reset Row Props + var rowLen = tr.childNodes.length; + for (var i = 0; i < rowLen; i++) { + var td = tr.childNodes[i]; + if(td.nodeType != 1) continue; + + var colLen = td.childNodes.length; + for( var j = 0; j < colLen; j++) { + var node = td.childNodes[j]; + if(node.nodeType != 1) continue; + var result = node.name.match(/([a-zA-Z]+)_(\d+)/); + if(result != null) { + node.name = result[1] + "_" + count; + node.id = result[1] + "_" + count + "_formId"; + var nodeValue = data[result[1]]; + var isSelect = node.type.indexOf("select") > -1 + if(nodeValue) { + if(isSelect) { + selectValue(node,nodeValue); + } + else if(node.type != "button") { + node.value = nodeValue; + } + } + else { + if(isSelect) { + selectValue(node,""); + } + else if(node.type != "button") { + node.value = ""; + } + } + if(result[1] == "deleteButton" || result[1] == "orderDelButton") { + node.onclick = new Function('deleteRow(document.getElementById("' + rowType + '_' + count + '"),document.getElementById("' + ttbody.id + '"));'); + } + } + } + } + + ttbody.appendChild(tr); + incrementCount(countId); +} + +//----------------------------------------------------------------------------------- +function getPropCount() { + return getCount("propCount_id"); +} + +//----------------------------------------------------------------------------------- +function getOrderCount() { + return getCount("orderCount_id"); +} + +//----------------------------------------------------------------------------------- +function getCount(id) { + var count = document.getElementById(id); + return count.value; +} + +//----------------------------------------------------------------------------------- +function getRowType(id) { + var parts = id.split("_"); + return parts[0]; +} + +//----------------------------------------------------------------------------------- +function incrementCount(id) { + var count = document.getElementById(id); + var value = parseInt(count.value); + value++; + count.value = value; + return value; +} + +//----------------------------------------------------------------------------------- +function incrementOrderCount() { + return incrementCount("orderCount_id"); +} + +//----------------------------------------------------------------------------------- +function incrementPropCount() { + return incrementCount("propCount_id"); +} + +//----------------------------------------------------------------------------------- +function deleteRow(row,ttbody) { + var rowId = row.id; + var rowType = getRowType(rowId); + var row1 = rowType + "_1"; + if(rowId != row1) { + ttbody.removeChild(row); + return; + } + alert("The first row may not be deleted. Please adjust your query appropriately"); + return; +} + +//----------------------------------------------------------------------------------- +function getClasses() { + if(classArray.length > 0) { + return classArray; + } + for (var key in classValues) { + classArray.push(key); + } + classArray.sort(); + return classArray; +} + +//----------------------------------------------------------------------------------- +function getClassValue() { + var className = document.getElementById("className_formId"); + return className.value; +} + +//----------------------------------------------------------------------------------- +function getFirstChild(node) { + var rowLen = node.childNodes.length; + for (var i = 0; i < rowLen; i++) { + if(node.childNodes[i].nodeType != 1) continue; + return node.childNodes[i]; + } + return null; +} + +//----------------------------------------------------------------------------------- +function loadClasses(selectBox) { + var classes = getClasses(); + var value = ""; + if(dataValues.isNew != "true") { + value = dataValues.className; + } + populateSelect(selectBox,classes,value); + return; +} + +//----------------------------------------------------------------------------------- +function loadClassName (className) { + //Delete Where Rows + var propCount = getPropCount(); + for(var i = 2; i < propCount; i++) { + var row = document.getElementById("row_" + i); + if(row != null) { + deleteRow(row,document.getElementById("whereBody")); + } + } + //Delete Order Rows + var orderCount = getOrderCount(); + for(var i = 2; i < orderCount; i++) { + var row = document.getElementById("order_" + i); + if(row != null) { + deleteRow(row,document.getElementById("orderBody")); + } + } + + //Load the new properties from the classes + var propSel = document.getElementById("propSelect_1_formId"); + var orderSel = document.getElementById("orderSelect_1_formId"); + + emptySelect(propSel); + emptySelect(orderSel); + + var classValue = getClassValue(); + var propOpts = classValues[classValue]; + + populateSelect( propSel, propOpts, null, true ); + populateSelect( orderSel, propOpts, null, true ); + + //Reset the counts + setCount("propCount_id",2); + setCount("orderCount_id",2); + + return; +} + +//----------------------------------------------------------------------------------- +function loadWhereRows(tbody) { + var propCount = getPropCount(); + //Change the names and ids of the default row + var tr = getFirstChild(tbody); + tr.id = "row_" + propCount; + + var propSelect = document.getElementById("propSelect_formId"); + propSelect.name = "propSelect_" + propCount; + propSelect.id = "propSelect_" + propCount + "_formId"; + var classValue = getClassValue(); + var propOpts = classValues[classValue]; + + var opSelect = document.getElementById("opSelect_formId"); + opSelect.name = "opSelect_" + propCount; + opSelect.id = "opSelect_" + propCount + "_formId"; + + var valText = document.getElementById("valText_formId"); + valText.name = "valText_" + propCount; + valText.id = "valText_" + propCount + "_formId"; + + var deleteButton = document.getElementById("deleteButton_formId"); + deleteButton.name = "deleteButton_" + propCount; + deleteButton.id = "deleteButton_" + propCount + "_formId"; + deleteButton.onclick = new Function('deleteRow(document.getElementById("row_'+propCount+'"),document.getElementById("whereBody"));'); + + if(dataValues.isNew == "true") { + // Build the default row + populateSelect(propSelect,propOpts,null,true); + incrementPropCount(); + } + else { + // Build existing rows + var whereData = dataValues.where; + //Handle case where user chooses no constraints. + var whereValue = null; + var selValue = null; + var valValue = null; + if(whereData[1] != null) { + whereValue = whereData[1].propSelect; + selValue = whereData[1].opSelect; + valValue = whereData[1].valText; + } + //Populate the data + populateSelect(propSelect,propOpts,whereValue,true); + selectValue(opSelect,selValue); + valText.value = valValue; + + incrementPropCount(); + for (var key in whereData) { + if(key > 1) { + addRow(tr,tbody,"propCount_id",whereData[key]); + } + } + } +} + +//----------------------------------------------------------------------------------- +function selectValue (list, value) { + for ( var i = 0; i < list.options.length; i++ ) { + if(list.options[i].value == value) { + list.options[i].selected = true; + return; + } + } +} + +//----------------------------------------------------------------------------------- +function loadOrder(tbody) { + var orderCount = getOrderCount(); + //Change the names and ids of the default row + var tr = getFirstChild(tbody); + tr.id = "order_" + orderCount; + + var orderSelect = document.getElementById("orderSelect_formId"); + orderSelect.name = "orderSelect_" + orderCount; + orderSelect.id = "orderSelect_" + orderCount + "_formId"; + // Build the default row + var classValue = getClassValue(); + var orderOpts = classValues[classValue]; + + var dirSelect = document.getElementById("dirSelect_formId"); + dirSelect.name = "dirSelect_" + orderCount; + dirSelect.id = "dirSelect_" + orderCount + "_formId"; + + var deleteButton = document.getElementById("orderDelButton_formId"); + deleteButton.name = "orderDelButton_" + orderCount; + deleteButton.id = "orderDelButton_" + orderCount + "_formId"; + deleteButton.onclick = new Function('deleteRow(document.getElementById("order_' + orderCount + '"),document.getElementById("orderBody"));'); + + if(dataValues.isNew == "true") { + populateSelect(orderSelect,propOpts,null,true); + incrementOrderCount(); + } + else { + // Build existing rows + var orderData = dataValues.order; + //Handle case where user chooses no order. + var orderValue = null; + var dirValue = null; + if(orderData[1] != null) { + orderValue = orderData[1].orderSelect; + dirValue = orderData[1].dirSelect; + } + //Populate data + populateSelect(orderSelect,orderOpts,orderValue,true); + selectValue(dirSelect,dirValue); + + incrementOrderCount(); + for (var key in orderData) { + if(key > 1) { + addRow(tr,tbody,"orderCount_id",orderData[key]); + } + } + } +} + +//----------------------------------------------------------------------------------- +function populateSelect( list, data, value, isHash ) { + if(isHash) { + for ( var key in data ) { + var opt = document.createElement("option"); + opt.setAttribute("value",key); + if(key == value ) opt.setAttribute("selected",true); + opt.appendChild(document.createTextNode(data[key])); + list.appendChild(opt); + } + } + else { + for ( var i = 0; i < data.length; i++ ) { + var opt = document.createElement("option"); + opt.setAttribute("value",data[i]); + if(data[i] == value ) opt.setAttribute("selected",true); + opt.appendChild(document.createTextNode(data[i])); + list.appendChild(opt); + } + } + + //Fix IE Bug which causes dymamic repopulation to fail + var newList = list; + var col = list.parentNode; + col.removeChild(list); + col.appendChild(newList); + + return; +} + +//----------------------------------------------------------------------------------- +function emptySelect ( list ) { + //Remove all options from list except first one + while (list.options.length > 1) { + var elem = list.options[1]; + list.removeChild(elem); + } +} + +//----------------------------------------------------------------------------------- +function setCount(id,value) { + var count = document.getElementById(id); + count.value = value; +} + + +YAHOO.util.Event.onDOMReady( function () { + loadClasses(document.getElementById("className_formId")); + loadWhereRows(document.getElementById("whereBody")); + loadOrder(document.getElementById("orderBody")); +}); +