package WebGUI::Admin; # The new WebGUI Admin console use Moose; use JSON qw( from_json to_json ); use namespace::autoclean; use Scalar::Util; use WebGUI::Pluggable; use WebGUI::Macro; has 'session' => ( is => 'ro', isa => 'WebGUI::Session', required => 1, ); sub BUILDARGS { my ( $class, $session, @args ) = @_; return { session => $session, @args }; } # Use the template data located in our DATA block my $tdata = do { local $/ = undef; }; #---------------------------------------------------------------------- sub getAdminPluginTemplateVars { my $self = shift; my $session = $self->session; my ( $user, $url, $setting ) = $session->quick(qw(user url setting)); my $functions = $session->config->get("adminConsole"); my %processed; # title => attributes # process the raw information from the config file foreach my $funcId ( keys %{$functions} ) { my $funcDef = $functions->{$funcId}; my $var = {}; # If we have a class name, we've got a new WebGUI::Admin::Plugin if ( $funcDef->{className} ) { my $plugin = $funcDef->{className}->new( $session, $funcId, $funcDef ); next unless $plugin->canUse; $var = { title => $plugin->getTitle, icon => $plugin->getIcon, 'icon.small' => $plugin->getIconSmall, url => $plugin->getUrl, }; # build the list of processed items $processed{$plugin->getTitle} = $var; } # Don't know what we have (old admin console functions) else { # make title my $title = $funcDef->{title}; WebGUI::Macro::process( $session, \$title ); # determine if the user can use this thing my $canUse = 0; if ( defined $funcDef->{group} ) { $canUse = $user->isInGroup( $funcDef->{group} ); } elsif ( defined $funcDef->{groupSetting} ) { $canUse = $user->isInGroup( $setting->get( $funcDef->{groupSetting} ) ); } if ( $funcDef->{uiLevel} > $user->profileField("uiLevel") ) { $canUse = 0; } next unless $canUse; # build the attributes $var = { title => $title, icon => $url->extras( "/adminConsole/" . $funcDef->{icon} ), 'icon.small' => $url->extras( "adminConsole/small/" . $funcDef->{icon} ), url => $funcDef->{url}, }; # build the list of processed items $processed{$title} = $var; } ## end else [ if ( $funcDef->{className...})] } ## end foreach my $funcId ( keys %...) #sort the functions alphabetically return [ map { $processed{$_} } sort keys %processed ]; } ## end sub getAdminFunctionTemplateVars #---------------------------------------------------------------------- =head2 getAssetTypes ( ) Get a hash of className => info pairs containing information about the asset class. Info will include at least the following keys: title => The i18n title of the asset icon => The small icon icon_full => The full sized icon uiLevel => The UI Level of the asset canAdd => True if the current user can add the asset url => URL to add the asset category => A string or an arrayref of categories =cut sub getAssetTypes { my ( $self ) = @_; my $session = $self->session; my ( $config ) = $session->quick(qw( config )); my %configList = %{ $config->get('assets') }; my %assetList = (); for my $class ( keys %configList ) { my $assetConfig = $configList{ $class }; # Create a dummy asset my $dummy = WebGUI::Asset->newByPropertyHashRef( $session, { dummy => 1, className => $class } ); next unless defined $dummy; $assetList{ $class } = { ( %$assetConfig ), url => 'func=add;className=' . $class, icon => $dummy->getIcon(1), # default icon is small for back-compat icon_full => $dummy->getIcon, title => $dummy->getTitle, uiLevel => $dummy->getUiLevel( $assetConfig->{uiLevel} ), canAdd => $dummy->canAdd( $session ), }; } return %assetList; } #---------------------------------------------------------------------- =head2 getNewContentTemplateVars Get an array of tabs for the new content menu. Each tab contains items of new content that can be added to the site. =cut sub getNewContentTemplateVars { my ( $self ) = @_; my $session = $self->session; my ( $user, $config ) = $session->quick(qw( user config )); my $i18n = WebGUI::International->new($session,'Macro_AdminBar'); my $tabs = []; # Add a dummy asset to the session to pass canAdd checks # The future canAdd will not check validParent, www_add will instead # This asset is removed before we return... $session->asset( WebGUI::Asset->getDefault( $session ) ); # Build the categories my %rawCategories = %{ $config->get('assetCategories') }; my %categories; # All the categories we have my $userUiLevel = $user->profileField('uiLevel'); foreach my $category ( keys %rawCategories ) { # Check the ui level next if $rawCategories{$category}{uiLevel} > $userUiLevel; # Check group permissions next if ( exists $rawCategories{$category}{group} && !$user->isInGroup( $rawCategories{$category}{group} ) ); my $title = $rawCategories{$category}{title}; # Process macros on the title WebGUI::Macro::process( $session, \$title ); $categories{$category}{title} = $title; } # assets my %assetList = $self->getAssetTypes; foreach my $assetClass ( keys %assetList ) { my $assetConfig = $assetList{$assetClass}; next unless $assetConfig->{canAdd}; next unless $assetConfig->{uiLevel} <= $userUiLevel; # Add the asset to all categories it should appear in my @assetCategories = ref $assetConfig->{category} ? @{ $assetConfig->{category} } : $assetConfig->{category}; for my $category (@assetCategories) { next unless exists $categories{$category}; $categories{$category}{items} ||= []; push @{ $categories{$category}{items} }, $assetConfig; } } ## end foreach my $assetClass ( keys...) # packages foreach my $package ( @{ WebGUI::Asset::getPackageList( $session ) } ) { # Check permissions and UI level next unless ( $package->canView && $package->canAdd($session) && $package->getUiLevel <= $userUiLevel ); # Create the "packages" category $categories{packages}{items} ||= []; push @{ $categories{packages}{items} }, { className => Scalar::Util::blessed( $package ), url => "func=deployPackage;assetId=" . $package->getId, title => $package->getTitle, icon => $package->getIcon(1), }; } # If we have any packages, fill in the package category title if ( $categories{packages}{items} && @{ $categories{packages}{items} } ) { $categories{packages}{title} = $i18n->get('packages'); } # prototypes foreach my $prototype ( @{ WebGUI::Asset::getPrototypeList( $session ) } ) { # Check permissions and UI level next unless ( $prototype->canView && $prototype->canAdd($session) && $prototype->getUiLevel <= $userUiLevel ); # Create the "prototypes" category $categories{prototypes}{items} ||= []; push @{ $categories{prototypes}{items} }, { className => $prototype->get('className'), url => "func=add;className=" . $prototype->get('className') . ";prototype=" . $prototype->getId, title => $prototype->getTitle, icon => $prototype->getIcon(1), }; } # If we have any prototypes, fill in the prototype category title if ( $categories{prototypes}{items} && @{ $categories{prototypes}{items} } ) { $categories{prototypes}{title} = $i18n->get('prototypes'); } # sort the categories by title my @sortedIds = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [ $_, $categories{$_}->{title} ] } grep { $categories{$_}->{items} && @{$categories{$_}->{items}} } keys %categories; # Schwartzian transform foreach my $categoryId ( @sortedIds ) { my $category = $categories{ $categoryId }; my $tab = { id => $categoryId, title => $category->{title}, items => [], }; push @{$tabs}, $tab; my $items = $category->{items}; next unless ( ref $items eq 'ARRAY' ); # in case the category is empty foreach my $item ( sort { $a->{title} cmp $b->{title} } @{$items} ) { push @{ $tab->{items} }, $item; } } # Remove the session asset we added above delete $session->{_asset}; return $tabs; } #---------------------------------------------------------------------------- =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->quote_identifier( $orderByColumn ) . ' ' . $orderByDirection; $p->setDataByArrayRef( $asset->getLineage( ['children'], { orderByClause => $orderBy } ) ); return $p; } #---------------------------------------------------------------------- =head2 www_findUser ( ) Find a user based on a partial name, username, alias, or e-mail address =cut sub www_findUser { my ( $self ) = @_; my $session = $self->session; my ( $form, $db, $url ) = $session->quick(qw( form db url )); my $query = '%' . $form->get('query') . '%'; my @places; # Places to look for my $col ( 'username', 'alias', 'firstName', 'lastName', 'CONCAT(firstName," ",lastName)' ) { push @places, $col . " LIKE ?"; } my $sql = 'SELECT userId, CONCAT(firstName,lastName) AS name, username, alias, avatar FROM users JOIN userProfileData USING (userId) WHERE ' . join( ' || ', @places ); my $params = [ ( $query ) x scalar @places ]; $session->log->warn( 'SQL: ' . $sql ); $session->log->warn( 'PARAM: ' . join ", ", @$params ); my $sth = $db->read( $sql, $params ); my @results; while ( my $result = $sth->hashRef ) { $result->{avatar} ||= $url->extras('icon/user.png'); push @results, $result; } my $output = JSON->new->encode( { results => \@results } ); $session->log->warn( $output ); return $output; } #---------------------------------------------------------------------- =head2 www_getClipboard ( ) Get the assets currently on the user's clipboard =cut sub www_getClipboard { my ( $self ) = @_; my $session = $self->session; my ( $user, $form ) = $session->quick(qw{ user form }); my $userOnly = !$form->get('all'); my $assets = WebGUI::Asset->getRoot( $session )->getAssetsInClipboard( $userOnly ); my @assetInfo = (); for my $asset ( @{$assets} ) { push @assetInfo, { assetId => $asset->getId, url => $asset->getUrl, title => $asset->menuTitle, revisionDate => $asset->revisionDate, icon => $asset->getIcon("small"), }; } return JSON->new->encode( \@assetInfo ); } #---------------------------------------------------------------------- =head2 www_getCurrentVersionTag ( ) Get information about the current version tag =cut sub www_getCurrentVersionTag { my ( $self ) = @_; my $session = $self->session; my $currentUrl = $session->url->getRequestedUrl; my $currentTag = WebGUI::VersionTag->getWorking( $session, "nocreate" ); return JSON->new->encode( {} ) unless $currentTag; my %tagInfo = ( tagId => $currentTag->getId, name => $currentTag->get('name'), editUrl => $currentTag->getEditUrl, commitUrl => $currentTag->getCommitUrl, leaveUrl => $currentUrl . '?op=leaveVersionTag', ); return JSON->new->encode( \%tagInfo ); } #---------------------------------------------------------------------- =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 : ''), canEdit => $asset->canEdit && $asset->canEditIfLocked, helpers => $asset->getHelpers, ); $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' ); $assetInfo->{ currentAsset } = { assetId => $asset->getId, url => $asset->getUrl, title => $asset->getTitle, icon => $asset->getIcon("small"), helpers => $asset->getHelpers, }; $assetInfo->{ crumbtrail } = []; for my $asset ( @{ $asset->getLineage( ['ancestors'], { returnObjects => 1 } ) } ) { push @{ $assetInfo->{crumbtrail} }, { title => $asset->getTitle, url => $asset->getUrl }; } $session->http->setMimeType( 'application/json' ); return to_json( $assetInfo ); } #---------------------------------------------------------------------- =head2 www_getVersionTags Get the current version tags a user can join =cut sub www_getVersionTags { my ( $self ) = @_; my $session = $self->session; my ( $user ) = $session->quick(qw( user )); my $vars = []; my $current = WebGUI::VersionTag->getWorking( $session, "nocreate" ); my $tags = WebGUI::VersionTag->getOpenTags($session); if ( @$tags ) { for my $tag ( @$tags ) { next unless $user->isInGroup( $tag->get("groupToUse") ); my $isCurrent = ( $current && $current->getId eq $tag->getId ) ? 1 : 0; my $icon = $isCurrent ? $session->url->extras( 'icon/tag_green.png' ) : $session->url->extras( 'icon/tag_blue.png' ) ; push @$vars, { tagId => $tag->getId, name => $tag->get("name"), isCurrent => $isCurrent, joinUrl => $tag->getJoinUrl, editUrl => $tag->getEditUrl, icon => $icon, }; } } return JSON->new->encode( $vars ); } #---------------------------------------------------------------------- =head2 www_processAssetHelper ( ) Process the given asset helper with the given asset =cut sub www_processAssetHelper { my ( $self ) = @_; my $session = $self->session; my ( $form ) = $session->quick(qw{ form }); my $assetId = $form->get('assetId'); my $class = $form->get('className'); WebGUI::Pluggable::load( $class ); my $asset = WebGUI::Asset->newById( $session, $assetId ); return JSON->new->encode( $class->process( $asset ) ); } #---------------------------------------------------------------------- =head2 www_view ( session ) Show the main Admin console wrapper =cut sub www_view { my ( $self ) = @_; my $session = $self->session; my ( $user, $url, $style ) = $session->quick(qw{ user url style }); my $var; $var->{backToSiteUrl} = $url->page; # temporary! We are now in admin mode! $session->var->switchAdminOn; # Add vars for AdminBar $var->{adminPlugins} = $self->getAdminPluginTemplateVars; $var->{newContentTabs} = $self->getNewContentTemplateVars; # Add vars for current user $var->{username} = $user->username; $var->{profileUrl} = $user->getProfileUrl; $var->{logoutUrl} = $url->page("op=auth;method=logout"); $var->{viewUrl} = $url->page; $var->{homeUrl} = WebGUI::Asset->getDefault( $session )->getUrl; # Asset types for later use $var->{assetTypesJson} = JSON->new->encode( { $self->getAssetTypes } ); # All this needs to be template attachments $style->setCss( $url->extras('yui/build/button/assets/skins/sam/button.css')); $style->setCss( $url->extras('yui/build/menu/assets/skins/sam/menu.css')); $style->setCss( $url->extras('yui/build/tabview/assets/skins/sam/tabview.css')); $style->setCss( $url->extras('yui/build/paginator/assets/skins/sam/paginator.css')); $style->setCss( $url->extras('yui/build/datatable/assets/skins/sam/datatable.css')); $style->setCss( $url->extras('yui/build/container/assets/skins/sam/container.css')); $style->setCss( $url->extras('yui/build/autocomplete/assets/skins/sam/autocomplete.css')); $style->setCss( $url->extras('yui/build/menu/assets/skins/sam/menu.css')); #$style->setCss( $url->extras('yui-webgui/build/assetManager/assetManager.css' )); $style->setCss( $url->extras('admin/admin.css')); $style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js')); $style->setScript($url->extras('yui/build/utilities/utilities.js')); $style->setScript($url->extras('yui/build/element/element-min.js')); $style->setScript( $url->extras( 'yui/build/paginator/paginator-min.js ' ) ); $style->setScript($url->extras('yui/build/animation/animation-min.js')); $style->setScript( $url->extras( 'yui/build/datasource/datasource-min.js ' ) ); $style->setScript( $url->extras( 'yui/build/connection/connection-min.js ' ) ); $style->setScript( $url->extras( 'yui/build/datatable/datatable-min.js ' ) ); $style->setScript( $url->extras( 'yui/build/dragdrop/dragdrop-min.js' ) ); $style->setScript( $url->extras( 'yui/build/container/container-min.js' ) ); $style->setScript($url->extras('yui/build/tabview/tabview-min.js')); $style->setScript($url->extras('yui/build/menu/menu-min.js')); $style->setScript($url->extras('yui/build/button/button-min.js')); $style->setScript($url->extras('yui/build/autocomplete/autocomplete-min.js')); $style->setScript( $url->extras( 'yui/build/json/json-min.js' ) ); $style->setScript( $url->extras( 'yui-webgui/build/i18n/i18n.js' ) ); $style->setScript($url->extras('admin/admin.js')); # Use the template in our __DATA__ block my $tmpl = WebGUI::Asset::Template::HTMLTemplate->new( $session ); # Use the blank style my $output = $style->process( $tmpl->process( $tdata, $var ), "PBtmplBlankStyle000001" ); return $output; } ## end sub www_view 1; __DATA__
^International("admin console","AdminConsole");
  • );">
^International('version tags','VersionTag');
^International('1082','Asset');
^International('asset helpers','WebGUI');

^International('history','Asset');

^International('1083','Macro_AdminBar');
  • );">