package WebGUI::Content::AssetManager; use strict; use JSON qw( from_json to_json ); use URI; use WebGUI::Form; use WebGUI::Paginator; use WebGUI::Utility; #---------------------------------------------------------------------------- =head2 getClassSelectBox ( session ) Gets a select box to choose a class name. =cut sub getClassSelectBox { my $session = shift; tie my %classes, "Tie::IxHash", ( "" => "Any Class", $session->db->buildHash("select distinct(className) from asset"), ); delete $classes{"WebGUI::Asset"}; # don't want to search for the root asset return WebGUI::Form::selectBox( $session, { name => "class", value => $session->form->process("class","className"), defaultValue => "", options => \%classes, }); } #---------------------------------------------------------------------------- =head2 getCurrentAsset ( session ) Returns the asset we would be looking at if we weren't looking at the Asset Manager. =cut sub getCurrentAsset { my $session = shift; return WebGUI::Asset->newByUrl( $session ); } #---------------------------------------------------------------------------- =head2 getHeader ( session ) Get a header to pick "Manage" or "Search". Add other things later maybe? =cut sub getHeader { my $session = shift; my $output = ''; my $i18n = WebGUI::International->new( $session, "Asset" ); if ( $session->form->get( 'method' ) eq "search" ) { $output .= '
' . join( " | ", q{} . $i18n->get( 'manage' ) . q{}, q{} . $i18n->get( "search" ) . q{}, ) . q{
} ; } else { $output .= '
' . join( " | ", q{} . $i18n->get( "manage" ) . q{}, q{} . $i18n->get( "search" ) . q{}, ) . q{
} ; } return $output; } #---------------------------------------------------------------------------- =head2 getManagerPaginator ( session ) Get a page for the Asset Manager view. Returns a WebGUI::Paginator object filled with asset IDs. =cut sub getManagerPaginator { my $session = shift; my $asset = getCurrentAsset( $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' ) || 15; 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 getSearchPaginator ( session, query ) Get a page for the Asset Search view. Returns a WebGUI::Paginator object filled with asset IDs. =cut sub getSearchPaginator { my $session = shift; my $query = shift; my %parms; my $s = WebGUI::Search->new( $session, 0 ); $s->search( { keywords => $query->{ keywords }, classes => $query->{ classes }, } ); my $queryString = 'op=assetManager;method=search;keywords=' . $query->{ keywords }; for my $class ( @{ $query->{ classes } } ) { $queryString .= ';class=' . $class; } my $p = $s->getPaginatorResultSet( $session->url->page( $queryString ) ); return $p; } #---------------------------------------------------------------------------- =head2 getMoreMenu ( session, label ) Gets the "More" menu with the specified label. =cut sub getMoreMenu { my $session = shift; my $label = shift || "More"; my $userUiLevel = $session->user->profileField("uiLevel"); my $toolbarUiLevel = $session->config->get("assetToolbarUiLevel"); my $i18n = WebGUI::International->new( $session, "Asset" ); ### The More menu my @more_fields = (); # FIXME: Add a show callback with the record as first argument. If it # returns true, the URL will be shown. # These links are shown based on UI level if ( $userUiLevel >= $toolbarUiLevel->{ "changeUrl" } ) { push @more_fields, { url => '?func=changeUrl;proceed=manageAssets', label => $i18n->get( 'change url' ), }; } if ( $userUiLevel >= $toolbarUiLevel->{ "editBranch" } ) { push @more_fields, { url => '?func=editBranch', label => $i18n->get( 'edit branch' ), }; } if ( $userUiLevel >= $toolbarUiLevel->{ "shortcut" } ) { push @more_fields, { url => '?func=createShortcut;proceed=manageAssets', label => $i18n->get( 'create shortcut' ), }; } if ( $userUiLevel >= $toolbarUiLevel->{ "revisions" } ) { push @more_fields, { url => '?func=manageRevisions', label => $i18n->get( 'revisions' ), }; } if ( $userUiLevel >= $toolbarUiLevel->{ "view" } ) { push @more_fields, { url => '', label => $i18n->get( 'view' ), }; } if ( $userUiLevel >= $toolbarUiLevel->{ "edit" } ) { push @more_fields, { url => '?func=edit;proceed=manageAssets', label => $i18n->get( 'edit' ), }; } if ( $userUiLevel >= $toolbarUiLevel->{ "lock" } ) { push @more_fields, { url => '?func=lock;proceed=manageAssets', label => $i18n->get( 'lock' ), }; } if ( $session->config->get("exportPath") && $userUiLevel >= $toolbarUiLevel->{"export"} ) { push @more_fields, { url => '?func=export', label => $i18n->get( 'Export Page' ), }; } return to_json \@more_fields; } #---------------------------------------------------------------------------- =head2 handler ( session ) Handle the session, if we can. Otherwise pass it on. Check permissions =cut sub handler { my ( $session ) = @_; if ( $session->form->get( 'op' ) eq 'assetManager' && getCurrentAsset( $session ) ) { return $session->privilege->noAccess unless getCurrentAsset( $session )->canEdit; my $method = $session->form->get( 'method' ) ? 'www_' . $session->form->get( 'method' ) : 'www_manage' ; # Validate the method name if ( !__PACKAGE__->can( $method ) ) { return "Invalid method"; } else { return __PACKAGE__->can( $method )->( $session ); } } else { return; } } #---------------------------------------------------------------------------- =head2 www_ajaxGetManagerPage ( session ) Get a page of Asset Manager data, ajax style. Returns a JSON array to be formatted in a WebGUI.AssetManager data table. =cut sub www_ajaxGetManagerPage { my $session = shift; my $i18n = WebGUI::International->new( $session, "Asset" ); my $assetInfo = {}; my $p = getManagerPaginator( $session ); for my $assetId ( @{ $p->getPageData } ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); # Populate the required fields to fill in my %fields = ( assetId => $asset->getId, url => $asset->getUrl, lineage => $asset->get( "lineage" ), title => $asset->get( "title" ), revisionDate => $asset->get( "revisionDate" ), childCount => $asset->getChildCount, assetSize => $asset->get( 'assetSize' ), lockedBy => $asset->lockedBy, canEditIfLocked => $asset->canEditIfLocked, ); $fields{ className } = {}; # The asset icon my $icon = [ grep { $_->{ icon } } @{ $asset->definition( $session ) } ]->[ 0 ]->{ icon }; $fields{ icon } = $session->url->extras( '/assets/small/' . $icon ); # The asset type (i18n name) my $type = [ grep { $_->{ assetName } } @{ $asset->definition( $session ) } ]->[ 0 ]->{ assetName }; $fields{ className } = $type; 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_manage ( session ) Show the main screen of the asset manager, paginated. Also load the JavaScript that will take over if the browser has the cojones. =cut sub www_manage { my ( $session ) = @_; my $ac = WebGUI::AdminConsole->new( $session, "assets" ); my $currentAsset = getCurrentAsset( $session ); my $i18n = WebGUI::International->new( $session, "Asset" ); ### Do Action if ( my $action = $session->form->get( 'action' ) ) { my @assetIds = $session->form->get( 'assetId' ); if ( $action eq "update" ) { for my $assetId ( @assetIds ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); next unless $asset; my $rank = $session->form->get( $assetId . '_rank' ); next unless $rank; # There's no such thing as zero $asset->setRank( $rank ); } } elsif ( $action eq "trash" ) { for my $assetId ( @assetIds ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); next unless $asset; $asset->trash; } } elsif ( $action eq "cut" ) { for my $assetId ( @assetIds ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); next unless $asset; $asset->cut; } } elsif ( $action eq "copy" ) { for my $assetId ( @assetIds ) { # Copy == Duplicate + Cut my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId); my $newAsset = $asset->duplicate( { skipAutoCommitWorkflows => 1 } ); $newAsset->update( { title => $newAsset->getTitle . ' (copy)' } ); $newAsset->cut; } } elsif ( $action eq "duplicate" ) { for my $assetId ( @assetIds ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); next unless $asset; $asset->duplicate( { skipAutoCommitWorkflows => 1 } ); } } } # Show the page $session->style->setLink( $session->url->extras('yui/build/datatable/assets/skins/sam/datatable.css'), {rel=>'stylesheet', type=>'text/css'}); $session->style->setLink( $session->url->extras('yui/build/menu/assets/skins/sam/menu.css'), {rel=>'stylesheet', type=>'text/css'}); $session->style->setLink( $session->url->extras( 'yui-webgui/build/assetManager/assetManager.css' ), { rel => "stylesheet", type => 'text/css' } ); $session->style->setScript( $session->url->extras( 'yui/build/yahoo/yahoo.js' ) ); $session->style->setScript( $session->url->extras( 'yui/build/dom/dom.js' ) ); $session->style->setScript( $session->url->extras( 'yui/build/event/event.js' ) ); $session->style->setScript( $session->url->extras( 'yui/build/element/element-beta-min.js ' ) ); $session->style->setScript( $session->url->extras( 'yui/build/connection/connection-min.js ' ) ); $session->style->setScript( $session->url->extras( 'yui/build/datasource/datasource-beta.js ' ) ); $session->style->setScript( $session->url->extras( 'yui/build/datatable/datatable-beta.js ' ) ); $session->style->setScript( $session->url->extras( 'yui/build/container/container-min.js' ) ); $session->style->setScript( $session->url->extras( 'yui/build/menu/menu-min.js' ) ); $session->style->setScript( $session->url->extras( 'yui-webgui/build/assetManager/assetManager.js' ) ); $session->style->setScript( $session->url->extras( 'yui-webgui/build/form/form.js' ) ); my $extras = $session->url->extras; $session->style->setRawHeadTags( < WebGUI.AssetManager.extrasUrl = '$extras'; YAHOO.util.Event.onDOMReady( WebGUI.AssetManager.initManager ); ENDHTML my $output = '
' . getHeader( $session ); ### Crumbtrail my $crumb_markup = '
  • %s >
  • '; my $ancestors = $currentAsset->getLineage( ['ancestors'], { returnObjects => 1 } ); $output .= '
      '; for my $asset ( @{ $ancestors } ) { $output .= sprintf $crumb_markup, $asset->getUrl( 'op=assetManager;method=manage' ), $asset->get( "menuTitle" ), ; } # And ourself $output .= sprintf q{
    1. %s
    2. }, $currentAsset->getUrl, $currentAsset->get( "menuTitle" ), ; $output .= '
    '; ### The page of assets $output .= q{
    } . q{
    } . q{} . q{} . q{
    } . q{
    } . q{

    } . $i18n->get( 'with selected' ) . q{} . q{} . q{} . q{} . q{} . q{

    } . q{
    } . q{} . q{
    } ; ### Clearing div $output .= q{
     
    }; ### New Content $output .= q{
    } . $i18n->get( '1083' ) . ''; foreach my $link (@{$currentAsset->getAssetAdderLinks("proceed=manageAssets","assetContainers")}) { $output .= '

    '.$link->{label}.'

    '.$link->{label}.' '; $output .= $session->icon->edit("func=edit;proceed=manageAssets",$link->{asset}->get("url")) if ($link->{isPrototype}); $output .= '
    '; } $output .= '
    '; foreach my $link (@{$currentAsset->getAssetAdderLinks("proceed=manageAssets")}) { $output .= '

    '.$link->{label}.'

    '.$link->{label}.' '; $output .= $session->icon->edit("func=edit;proceed=manageAssets",$link->{asset}->get("url")) if ($link->{isPrototype}); $output .= '
    '; } $output .= '
    '; foreach my $link (@{$currentAsset->getAssetAdderLinks("proceed=manageAssets","utilityAssets")}) { $output .= '

    '.$link->{label}.'

    '.$link->{label}.' '; $output .= $session->icon->edit("func=edit;proceed=manageAssets",$link->{asset}->get("url")) if ($link->{isPrototype}); $output .= '
    '; } $output .= '
    '; tie my %options, 'Tie::IxHash'; my $hasClips = 0; foreach my $asset (@{$currentAsset->getAssetsInClipboard(1)}) { $options{$asset->getId} = ''.$asset->getName.' '.$asset->getTitle; $hasClips = 1; } if ($hasClips) { $output .= '
    '.$i18n->get(1082).'' .WebGUI::Form::formHeader($session, {action=>$currentAsset->getUrl}) .WebGUI::Form::hidden($session,{name=>"func",value=>"pasteList"}) .WebGUI::Form::checkbox($session,{extras=>'onclick="toggleClipboardSelectAll(this.form);"'}) .' '.$i18n->get("select all").'
    ' .WebGUI::Form::checkList($session,{name=>"assetId",vertical=>1,options=>\%options}) .'
    ' .WebGUI::Form::submit($session,{value=>"Paste"}) .WebGUI::Form::formFooter($session) .'
    ' .''; } ## Packages $output .= '
    '.$i18n->get("packages").''; foreach my $asset (@{$currentAsset->getPackageList}) { $output .= '

    '.$asset->getName.'

    getId).'">'.$asset->getTitle.' ' .$session->icon->edit("func=edit;proceed=manageAssets",$asset->get("url")) .$session->icon->export("func=exportPackage",$asset->get("url")) .'
    '; } $output .= '
    '.WebGUI::Form::formHeader($session, {action=>$currentAsset->getUrl}) .WebGUI::Form::hidden($session, {name=>"func", value=>"importPackage"}) .'' .WebGUI::Form::submit($session, {value=>$i18n->get("import"), extras=>'style="font-size: 10px;"'}) .WebGUI::Form::formFooter($session); $output .= '
    '; ### Clearing div $output .= q{
     
    }; $output .= q{
    }; ### Write the JavaScript that will take over $output .= ' ENDJS return $ac->render( $output ); } #---------------------------------------------------------------------------- =head2 www_search ( session ) Search assets underneath this asset. =cut sub www_search { my $session = shift; my $ac = WebGUI::AdminConsole->new( $session, "assets" ); my $i18n = WebGUI::International->new( $session, "Asset" ); my $output = '
    ' . getHeader( $session ); $session->style->setLink( $session->url->extras( 'yui-webgui/build/assetManager/assetManager.css' ), { rel => "stylesheet", type => 'text/css' } ); $session->style->setScript( $session->url->extras( 'yui/build/yahoo-dom-event/yahoo-dom-event.js' ) ); $session->style->setScript( $session->url->extras( 'yui-webgui/build/assetManager/assetManager.js' ) ); $session->style->setScript( $session->url->extras( 'yui-webgui/build/form/form.js' ) ); ### Show the form $output .= q{

    } . q{} . q{} . q{} . getClassSelectBox( $session ) . q{} . q{

    } ; ### Actions if ( my $action = $session->form->get( 'action' ) ) { my @assetIds = $session->form->get( 'assetId' ); if ( $action eq "trash" ) { for my $assetId ( @assetIds ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); next unless $asset; $asset->trash; } } elsif ( $action eq "cut" ) { for my $assetId ( @assetIds ) { my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId ); next unless $asset; $asset->cut; } } elsif ( $action eq "copy" ) { for my $assetId ( @assetIds ) { # Copy == Duplicate + Cut my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId); my $newAsset = $asset->duplicate( { skipAutoCommitWorkflows => 1 } ); $newAsset->update( { title => $newAsset->getTitle . ' (copy)' } ); $newAsset->cut; } } } ### Run the search if ( $session->form->get( 'keywords' ) || $session->form->get( 'class' ) ) { my $keywords = $session->form->get( 'keywords' ); my @classes = $session->form->get( 'class' ); my $p = getSearchPaginator( $session, { keywords => $keywords, classes => \@classes, orderByColumn => $session->form->get( 'orderByColumn' ), orderByDirection => $session->form->get( 'orderByDirection' ), } ); if ( $p->getRowCount == 0 ) { $output .= q{

    } . $i18n->get( 'no results' ) . q{

    }; } else { ### Display the search results $output .= q{
    } . q{} . q{} . q{} . q{} ; # Add classes to the form for my $class ( @classes ) { $output .= q{}; } $output .= q{} . q{} . q{} . q{} # Checkbox column . q{} # Edit . q{} # Title . q{} # Type . q{} # Revision Date . q{} # Size . q{} # Lock . q{} . q{} ; # The markup for a single asset my $row_markup = q{} . q{} . q{} . q{} . q{} . q{} . q{} . q{} . q{} ; # The field keys to fill in the placeholders my @row_fields = qw( alt assetId editLink title iconUrl type revisionDate size url lockIcon ); my $count = 0; for my $assetInfo ( @{ $p->getPageData } ) { $count++; my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetInfo->{ assetId } ); # Populate the required fields to fill in my %fields = ( alt => ( $count % 2 == 0 ? 'class="alt"' : '' ), assetId => $asset->getId, url => $asset->getUrl, title => $asset->get( "title" ), revisionDate => $session->datetime->epochToHuman( $asset->get( "revisionDate" ) ), hasChildren => ( $asset->hasChildren ? "+ " : "  " ), rank => $asset->getRank, size => formatBytes( $asset->get( 'assetSize' ) ), ); # The asset icon my $icon = [ grep { $_->{ icon } } @{ $asset->definition( $session ) } ]->[ 0 ]->{ icon }; $fields{ iconUrl } = $session->url->extras( '/assets/small/' . $icon ); # The asset type (i18n name) my $type = [ grep { $_->{ assetName } } @{ $asset->definition( $session ) } ]->[ 0 ]->{ assetName }; $fields{ type } = $type; # The lock if ( $asset->lockedBy ) { # lockedBy in case someone overrides isLocked (like the Collab System Thread ) $fields{ lockIcon } = sprintf 'locked by %s', $session->url->extras( 'assetManager/locked.gif' ), WebGUI::HTML::format( $asset->lockedBy->username, "text" ), WebGUI::HTML::format( $asset->lockedBy->username, "text" ), ; } else { $fields{ lockIcon } = sprintf 'unlocked', $session->url->extras( 'assetManager/unlocked.gif' ), ; } # The edit link if ( !$asset->lockedBy || $asset->canEditIfLocked ) { $fields{ editLink } = sprintf '' . $i18n->get( "edit" ) . '', $asset->getUrl( 'func=edit' ) ; } $output .= sprintf $row_markup, @fields{ @row_fields }; } $output .= q{} . q{
     } . $i18n->get( '99' ) . q{} . $i18n->get( "type" ) . q{} . $i18n->get( "last updated" ) . q{} . $i18n->get( "size" ) . q{} . $i18n->get( "locked" ) . q{
    %s%s %s%s%s%s
    } . q{

    } . $i18n->get( 'with selected' ) . q{} . q{} . q{} . q{

    } . q{
    } ; ### Page links $output .= q{}; ### Page description $output .= sprintf q{
    } . $i18n->get( 'page indicator' ) . q{
    }, $p->getPageNumber, $p->getNumberOfPages, ; ### Clearing div $output .= q{
     
    }; } } $output .= '
    '; return $ac->render( $output ); } 1;