Add Asset Dashlets to Dashboard. Add required and static properties to Dashboard Assets. Add caching to StockData and WeatherData assets. Add LastModifiedBy macro. Add GroupManager to the Group form control.

This commit is contained in:
Colin Kuskie 2011-03-09 21:33:44 -08:00
parent 79aa44cf7e
commit 88797c1d6c
42 changed files with 3506 additions and 448 deletions

View file

@ -1,5 +1,10 @@
7.10.12
- fixed #12072: Product, related and accessory assets
- added: Add Asset Dashlets to Dashboard
- added: Required and Static properties to assets in a dashboard.
- added: Caching to StockData and WeatherData asset.
- added: LastModifiedBy macro
- added: Group Manager form control
7.10.11
- fixed #12057: WebGUI::Search, assetIds search clause

View file

@ -7,6 +7,21 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief.
7.10.12
--------------------------------------------------------------------
* The Dashboard has been extended to include Asset Dashlets. This gives
Assets fine control over which properties can be extended and which can't.
Assets in the Dashboard can be set to be required, which prevents them from
being deleted, and fixed, which prevents them from moved.
* The StockData and WeatherData assets now include cache settings to reduce
server side load. The browser interface for the StockData asset still does
real time lookups.
* A new macro has been added, LastModifiedBy. This returns the username of
the user who last modified an Asset. If the asset in question is a Page
Layout or Folder, then querying that asset will also check all children.
* The Group form control has been extended to add a simple interface for
adding new Groups and changing their membership.
7.10.11
--------------------------------------------------------------------
* Modified TimeField, now provides popupless immediate validation with

View file

@ -31,6 +31,11 @@ my $quiet; # this line required
my $session = start(); # this line required
# upgrade functions go here
installNewDashboardTables($session);
addStockDataCacheColumn($session);
addWeatherDataCacheColumn($session);
addLastModifiedByMacro($session);
finish($session); # this line required
@ -44,6 +49,67 @@ finish($session); # this line required
# print "DONE!\n" unless $quiet;
#}
#----------------------------------------------------------------------------
# Describe what our function does
sub addLastModifiedMacro {
my $session = shift;
print "\tAdd LastModifiedBy macro to the config file... " unless $quiet;
# and here's our code
$session->config->addToHash('macros', 'LastModifiedBy', 'LastModifiedBy');
print "DONE!\n" unless $quiet;
}
#----------------------------------------------------------------------------
# Describe what our function does
sub installNewDashboardTables {
my $session = shift;
print "\tInstall new Dashboard tables... " unless $quiet;
$session->db->write(<<EOSQL);
CREATE TABLE IF NOT EXISTS Dashboard_dashlets (
dashboardAssetId CHAR(22) BINARY,
dashletAssetId CHAR(22) BINARY,
isStatic BOOLEAN,
isRequired BOOLEAN,
PRIMARY KEY (dashboardAssetId, dashletAssetId)
) TYPE=MyISAM CHARSET=utf8;
EOSQL
$session->db->write(<<EOSQL);
CREATE TABLE IF NOT EXISTS Dashboard_userPrefs (
dashboardAssetId CHAR(22) BINARY,
dashletAssetId CHAR(22) BINARY,
userId CHAR(22) BINARY,
isMinimized BOOLEAN,
properties LONGTEXT,
PRIMARY KEY (dashboardAssetId, dashletAssetId, userId)
) TYPE=MyISAM CHARSET=utf8;
EOSQL
# and here's our code
print "DONE!\n" unless $quiet;
}
#----------------------------------------------------------------------------
# Describe what our function does
sub addStockDataCacheColumn {
my $session = shift;
print "\tAdd cache column for the StockData asset... " unless $quiet;
$session->db->write(<<EOSQL);
ALTER TABLE StockData ADD COLUMN cacheTimeout BIGINT
EOSQL
# and here's our code
print "DONE!\n" unless $quiet;
}
#----------------------------------------------------------------------------
# Describe what our function does
sub addWeatherDataCacheColumn {
my $session = shift;
print "\tAdd cache column for the WeatherData asset... " unless $quiet;
$session->db->write(<<EOSQL);
ALTER TABLE WeatherData ADD COLUMN cacheTimeout BIGINT
EOSQL
# and here's our code
print "DONE!\n" unless $quiet;
}
# -------------- DO NOT EDIT BELOW THIS LINE --------------------------------

View file

@ -820,6 +820,7 @@
"If" : "If",
"International" : "International",
"LastModified" : "LastModified",
"LastModifiedBy" : "LastModifiedBy",
"L" : "L_loginBox",
"LoginToggle" : "LoginToggle",
"MiniCart" : "MiniCart",

View file

@ -1821,6 +1821,19 @@ sub getContentLastModified {
}
#-------------------------------------------------------------------
=head2 getContentLastModifiedBy ( )
Returns the userId that modified the content last.
=cut
sub getContentLastModifiedBy {
my $self = shift;
return $self->get("revisedBy");
}
#-------------------------------------------------------------------
=head2 getValue ( key )

View file

@ -323,13 +323,17 @@ sub purge {
=head2 view
Render the dashboard.
Render the dashboard. Of all the positions for content, position1 is reserved for hidden content
or content to be placed. Deleting content causes it to go into position1.
=cut
sub view {
my $self = shift;
my $self = shift;
my $session = $self->session;
my %vars = %{$self->get()};
$vars{canEdit} = $self->canEdit;
$vars{fullUrl} = $self->getUrl;
$self->session->style->setScript(
$self->session->url->extras('yui/build/utilities/utilities.js'),
@ -363,60 +367,84 @@ sub view {
my @found;
my $newStuff;
my $showPerformance = $self->session->errorHandler->canShowPerformanceIndicators();
my $user = $self->session->user;
foreach my $position (@positions) {
my @assets = split(",",$position);
foreach my $asset (@assets) {
foreach my $child (@{$children}) {
CHILD: foreach my $child (@{$children}) {
if ($asset eq $child->getId) {
unless (isIn($asset,@hidden) || !($child->canView)) {
$self->session->style->setRawHeadTags($child->getExtraHeadTags);
$child->{_properties}{title} = $child->getTitle;
$child->{_properties}{title} = $child->getShortcut->getTitle if (ref $child eq 'WebGUI::Asset::Shortcut');
if ($i == 1 || $i > $numPositions) {
push(@{$vars{"position1_loop"}},{
id=>$child->getId,
content=>'', #so things in the New Content bar don't display.
dashletTitle=>$child->{_properties}{title},
shortcutUrl=>$child->getUrl,
canPersonalize=>$self->canPersonalize,
showReloadIcon=>$child->{_properties}{showReloadIcon},
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
});
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
} else {
$child->prepareView;
push(@{$vars{"position".$i."_loop"}},{
id=>$child->getId,
content=>$child->view,
dashletTitle=>$child->{_properties}{title},
shortcutUrl=>$child->getUrl,
canPersonalize=>$self->canPersonalize,
showReloadIcon=>$child->{_properties}{showReloadIcon},
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
});
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
}
}
push(@found, $child->getId);
}
##Filter based on visibility
next CHILD unless $child->canView;
next CHILD if isIn($asset, @hidden);
##Detect child types
my $is_shortcut = $child->isa('WebGUI::Asset::Shortcut');
my $is_dashlet = $child->can('getOverrideFormDefinition');
$self->session->style->setRawHeadTags($child->getExtraHeadTags);
##Override the title for shortcuts
if ($is_shortcut) {
$child->{_properties}{title} = $child->getShortcut->getTitle;
}
##Fetch dashlet options from the database
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $child->getId]);
if (!($i == 1 || $i > $numPositions)) {
$child->prepareView;
}
my $spot = $i > $numPositions ? 1 : $i;
my $canMove = $self->canPersonalize && !$options->{isStatic};
my $editFormUrl = ($is_shortcut && $child->getPrefsFieldToShow) ? $child->getUrl('func=getUserPrefsForm')
: ($is_dashlet && $child->getOverrideFormDefinition) ? $self->getUrl('func=customizeDashlet;dashletAssetId='.$child->getId)
: ''
;
my $canEditUserPrefs = $user->isRegistered && $editFormUrl;
push(@{$vars{"position".$spot."_loop"}},{
id => $child->getId,
content => $child->view,
dashletTitle => $child->get('title'),
shortcutUrl => ($is_shortcut ? $child->getUrl : ''),
editFormUrl => $editFormUrl,
dashletUrl => ($is_dashlet ? $child->getUrl : ''),
canDelete => $self->canPersonalize && !$options->{isRequired},
canMove => $canMove,
canPersonalize => $self->canPersonalize,
showReloadIcon => $is_shortcut && $child->get('showReloadIcon'),
canEditUserPrefs => $canEditUserPrefs,
});
if ($canMove) {
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
}
}
}
}
$i++;
}
# deal with unplaced children
# deal with unplaced children, they go into position 1
foreach my $child (@{$children}) {
unless (isIn($child->getId, @found)||isIn($child->getId,@hidden)) {
if ($child->canView) {
$child->{_properties}{title} = $child->getShortcut->get("title") if (ref $child eq 'WebGUI::Asset::Shortcut');
my $is_shortcut = $child->isa('WebGUI::Asset::Shortcut');
my $is_dashlet = $child->can('getOverrideFormDefinition');
my $title = $child->{_properties}{title} = $is_shortcut ? $child->getShortcut->getTitle : $child->getTitle;
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $child->getId]);
my $canMove = $self->canPersonalize && !$options->{isStatic};
my $editFormUrl = ($is_shortcut && $child->getPrefsFieldToShow) ? $child->getUrl('func=getUserPrefsForm')
: ($is_dashlet && $child->getOverrideFormDefinition) ? $self->getUrl('func=customizeDashlet;dashletAssetId='.$child->getId)
: ''
;
my $canEditUserPrefs = $user->isRegistered && $editFormUrl;
push(@{$vars{"position1_loop"}},{
id=>$child->getId,
content=>'',
dashletTitle=>$child->getTitle,
shortcutUrl=>$child->getUrl,
showReloadIcon=>$child->{_properties}{showReloadIcon},
canPersonalize=>$self->canPersonalize,
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
id => $child->getId,
content => '',
dashletTitle => $title,
shortcutUrl => ($is_shortcut ? $child->getUrl : ''),
editFormUrl => $editFormUrl,
dashletUrl => ($is_dashlet ? $child->getUrl : ''),
canDelete => $self->canPersonalize && !$options->{isRequired},
canMove => $canMove,
canPersonalize => $self->canPersonalize,
showReloadIcon => $is_shortcut && $child->{_properties}{showReloadIcon},
canEditUserPrefs => $canEditUserPrefs,
});
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
}
@ -425,9 +453,9 @@ sub view {
$vars{showAdmin} = ($self->session->var->isAdminOn && $self->canEdit);
$vars{"dragger.init"} = '
<script type="text/javascript">
dragable_init("'.$self->getUrl.'");
var available_dashlets= new Array();
'.$newStuff.'
dragable_init("'.$self->getUrl.'");
</script>
';
return $self->processTemplate(\%vars, $templateId);
@ -435,6 +463,128 @@ sub view {
#-------------------------------------------------------------------
=head2 www_customizeDashlet
Web facing method for saving per dashlet configuration, such as being required, or movable.
=cut
sub www_customizeDashlet {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($session->user->isRegistered);
my $dashletAssetId = $session->form->get('dashletAssetId');
my $dashlet = WebGUI::Asset->newByDynamicClass($session, $dashletAssetId);
return $session->privilege->insufficient() unless ($dashlet && $dashlet->canView && $dashlet->can('getOverrideFormDefinition'));
my $i18n = WebGUI::International->new($session, 'Asset_Dashboard');
my $form = $session->form;
my $html_form = WebGUI::HTMLForm->new($session, action => $self->getUrl, method => 'POST', );
$html_form->hidden(name => 'func', value => 'customizeDashletSave', );
$html_form->hidden(name => 'dashletAssetId', value => $dashletAssetId, );
$html_form->readOnly(name => $i18n->get(), value => $dashlet->getTitle, );
my $overrides = $dashlet->fetchUserOverrides($self->getId);
my @dashlet_properties = $dashlet->getOverrideFormDefinition;
foreach my $property (@dashlet_properties) {
my %properties = %{ $property };
$properties{value} = $overrides->{$property->{name}} || $dashlet->get($property->{name});
$html_form->dynamicField(%properties);
}
$html_form->submit();
return $html_form->print;
}
#-------------------------------------------------------------------
=head2 www_customizeDashletSave
Web facing method for saving per dashlet configuration, such as being required, or movable.
=cut
sub www_customizeDashletSave {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($session->user->isRegistered);
my $dashletAssetId = $session->form->get('dashletAssetId');
my $dashlet = WebGUI::Asset->newByDynamicClass($session, $dashletAssetId);
return $session->privilege->insufficient() unless ($dashlet && $dashlet->canView && $dashlet->can('getOverrideFormDefinition'));
my $overrides = {};
my @dashlet_properties = $dashlet->getOverrideFormDefinition;
my $form = $session->form;
foreach my $property (@dashlet_properties) {
my $value = $form->process($property->{name}, $property->{fieldType}, $property->{value});
$overrides->{$property->{name}} = $value;
}
$dashlet->storeUserOverrides($self->getId, $overrides);
return $self->www_view;
}
##-------------------------------------------------------------------
=head2 www_editDashlet
Web facing method for saving per dashlet configuration, such as being required, or movable.
=cut
sub www_editDashlet {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($self->canEdit);
my $dashletAssetId = $session->form->get('dashletAssetId');
my $dashlet = WebGUI::Asset->newByDynamicClass($session, $dashletAssetId);
return $session->privilege->insufficient() unless ($dashletAssetId);
my $i18n = WebGUI::International->new($session, 'Asset_Dashboard');
my $form = $session->form;
my $html_form = WebGUI::HTMLForm->new($session, action => $self->getUrl, method => 'POST', );
$html_form->hidden(name => 'func', value => 'editDashletSave', );
$html_form->hidden(name => 'dashletAssetId', value => $dashletAssetId, );
$html_form->readOnly(name => $i18n->get(), value => $dashlet->getTitle, );
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $dashletAssetId]);
$html_form->yesNo(
name => 'isStatic',
label => $i18n->get('Is static'),
hoverHelp => $i18n->get('Is static help'),
value => $form->get('isStatic') || $options->{isStatic},
);
$html_form->yesNo(
name => 'isRequired',
label => $i18n->get('Is required'),
hoverHelp => $i18n->get('Is required help'),
value => $form->get('isRequired') || $options->{isRequired},
);
$html_form->submit();
return $html_form->print;
}
#-------------------------------------------------------------------
=head2 www_editDashletSave
Web facing method for saving per dashlet configuration, such as being required, or movable.
=cut
sub www_editDashletSave {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($self->canEdit);
my $dashletAssetId = $session->form->get('dashletAssetId');
my $isStatic = $session->form->get('isStatic', 'yesNo');
my $isRequired = $session->form->get('isRequired', 'yesNo');
$session->db->write('DELETE FROM Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?',[$self->getId, $dashletAssetId, ]);
$session->db->write('INSERT INTO Dashboard_dashlets (dashboardAssetId, dashletAssetId, isStatic, isRequired) VALUES (?,?,?,?)', [$self->getId, $dashletAssetId, $isStatic, $isRequired, ]);
return $self->www_view;
}
#-------------------------------------------------------------------
=head2 www_setContentPositions
Web method for saving the positions of dashlets in the dashboard.

View file

@ -121,7 +121,7 @@ Overridden to check the revision dates of children as well
sub getContentLastModified {
my $self = shift;
my $mtime = $self->get("revisionDate");
my $mtime = $self->get("lastModified");
my $childIter = $self->getLineageIterator(["children"]);
while ( 1 ) {
my $child;
@ -139,6 +139,36 @@ sub getContentLastModified {
#-------------------------------------------------------------------
=head2 getContentLastModifiedBy
Overridden to check the updated dates of children as well
=cut
sub getContentLastModifiedBy {
my $self = shift;
my $mtime = $self->SUPER::getContentLastModified;
my $userId = $self->get('revisedBy');
my $childIter = $self->getLineageIterator(["children"]);
while ( 1 ) {
my $child;
eval { $child = $childIter->() };
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
$self->session->log->error($x->full_message);
next;
}
last unless $child;
my $child_mtime = $child->getContentLastModified;
if ($child_mtime > $mtime) {
$mtime = $child_mtime;
$userId = $child->get("revisedBy");
}
}
return $userId;
}
#-------------------------------------------------------------------
=head2 getEditForm ( )
Returns the TabForm object that will be used in generating the edit page for this asset.

View file

@ -443,6 +443,36 @@ sub getContentLastModified {
#-------------------------------------------------------------------
=head2 getContentLastModifiedBy
Extend the base class to include the userid of the person that made last modification.
=cut
sub getContentLastModifiedBy {
my $self = shift;
my $mtime = $self->SUPER::getContentLastModified;
my $userId = $self->get('revisedBy');
my $childIter = $self->getLineageIterator(["children"],{excludeClasses=>['WebGUI::Asset::Wobject::Layout']});
while ( 1 ) {
my $child;
eval { $child = $childIter->() };
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
$self->session->log->error($x->full_message);
next;
}
last unless $child;
my $child_mtime = $child->getContentLastModified;
if ($child_mtime > $mtime) {
$mtime = $child_mtime;
$userId = $child->get("revisedBy");
}
}
return $userId;
}
#-------------------------------------------------------------------
=head2 www_view
Extend the base method to handle caching and ad rotation.

View file

@ -16,7 +16,8 @@ use WebGUI::Utility;
use WebGUI::Asset::Wobject;
use Finance::Quote;
our @ISA = qw(WebGUI::Asset::Wobject);
use Class::C3;
use base qw/WebGUI::Asset::Wobject WebGUI::AssetAspect::Dashlet/;
#-------------------------------------------------------------------
@ -165,7 +166,9 @@ sub _convertToEpoch {
if($time =~ m/pm/i) {
$hour += 12;
}
$hour ||= 0;
$hour = $self->_appendZero($hour);
$minute ||= 0;
$minute = $self->_appendZero($minute);
my $epoch = eval {$self->session->datetime->humanToEpoch("$year-$month-$day $hour:$minute:00")};
return $epoch;
@ -184,21 +187,47 @@ List of stock symbols to find passed in as an array reference. Stock symbols sh
=cut
sub _getStocks {
my $self = shift;
my $stocks = $_[0];
my $self = shift;
my $stocks = $_[0];
my $session = $self->session;
# Create a new Finance::Quote object
my $q = Finance::Quote->new;
# Disable failover if specified
unless ($self->getValue("failover")) {
$q->failover(0);
}
# Create a new Finance::Quote object
my $q = Finance::Quote->new;
# Disable failover if specified
unless ($self->getValue("failover")) {
$q->failover(0);
}
# Hardcoded timeout for now.
$q->timeout(15);
# Hardcoded timeout for now.
$q->timeout(15);
my $source = $self->getValue('source');
my %stocks = ();
my @stocks_to_fetch = ();
STOCK: foreach my $stock (@{$stocks}) {
$stock = uc $stock;
my $cache = WebGUI::Cache->new($session, [$self->getId, $source, $stock]);
if ($cache->get()) {
my $value = $cache->get();
%stocks = (%stocks, %{ $value });
}
else {
push @stocks_to_fetch, $stock;
}
}
# Fetch the stock information and return the results
return $q->fetch($self->getValue("source"),@{$stocks});
# Fetch the information for uncached stocks, cache them individually, and build the composite data.
my %new_stocks = $q->fetch($source, @stocks_to_fetch);
foreach my $stock (@stocks_to_fetch) {
$stock = uc $stock;
my @stock_keys = grep { /$stock\b/ } keys %new_stocks;
my $cache = WebGUI::Cache->new($session, [$self->getId, $source, $stock]);
my %slice;
@slice{ @stock_keys } = @new_stocks{ @stock_keys };
$slice{$stock,'last_fetch'} = time();
$cache->set(\%slice, $self->get('cacheTimeout'));
%stocks = (%stocks, %slice);
}
return \%stocks;
}
#-------------------------------------------------------------------
@ -284,6 +313,7 @@ sub definition {
tab=>'properties',
label=> $i18n->get("default_stock_label"),
hoverHelp=> $i18n->get("default_stock_label_description"),
dashletOverridable => 1,
},
source=>{
fieldType=>"selectList",
@ -297,8 +327,16 @@ sub definition {
fieldType=>"yesNo",
defaultValue=>undef,
label=> $i18n->get("failover_label"),
hoverHelp=> $i18n->get("failover_description")
}
hoverHelp=> $i18n->get("failover_description"),
},
cacheTimeout => {
tab => "display",
fieldType => "interval",
defaultValue => 3600,
uiLevel => 5,
label => $i18n->get("cache timeout", 'Asset_Snippet'),
hoverHelp => $i18n->get("cache timeout help"),
},
);
push(@{$definition}, {
@ -370,7 +408,8 @@ sub view {
$var->{'stock.display.url'} = $self->getUrl("func=displayStock;symbol=");
#Build list of stocks as an array
my $defaults = $self->getValue("defaultStocks");
my $overrides = $self->fetchUserOverrides($self->getParent->getId);
my $defaults = $overrides->{defaultStocks} || $self->getValue("defaultStocks");
#replace any windows newlines
$defaults =~ s/\r//;
my @array = split("\n",$defaults);

View file

@ -17,7 +17,8 @@ package WebGUI::Asset::Wobject::WeatherData;
use strict;
use Weather::Com::Finder;
use WebGUI::International;
use base 'WebGUI::Asset::Wobject';
use Class::C3;
use base qw/WebGUI::Asset::Wobject WebGUI::AssetAspect::Dashlet/;
use WebGUI::Utility;
#-------------------------------------------------------------------
@ -62,8 +63,17 @@ sub definition {
defaultValue=>"Madison, WI\nToronto, Canada\n53536",
tab=>"properties",
hoverHelp=>$i18n->get("Your list of default weather locations"),
label=>$i18n->get("Default Locations")
label=>$i18n->get("Default Locations"),
dashletOverridable => 1,
},
cacheTimeout => {
tab => "display",
fieldType => "interval",
defaultValue => 3600,
uiLevel => 5,
label => $i18n->get("cache timeout", 'Asset_Snippet'),
hoverHelp => $i18n->get("cache timeout help"),
},
};
push(@{$definition}, {
tableName=>'WeatherData',
@ -110,49 +120,72 @@ to be displayed within the page style
sub view {
my $self = shift;
my $session = $self->session;
my %var;
my $url = $self->session->url;
if ($self->get("partnerId") ne "" && $self->get("licenseKey") ne "") {
foreach my $location (split("\n", $self->get("locations"))) {
my $weather = Weather::Com::Finder->new({
'partner_id' => $self->get("partnerId"),
'license' => $self->get("licenseKey"),
'cache' => '/tmp',
});
next unless defined $weather;
my $overrides = $self->fetchUserOverrides($self->getParent->getId);
my $locations = $overrides->{locations} || $self->get('locations');
foreach my $location (split("\n", $locations)) {
my $cache = WebGUI::Cache->new($session, [$self->getId, $location]);
my $loop_data;
my $link_data = [];
my $cached_data = $cache->get();
if ($cached_data) {
$loop_data = $cached_data->{locations};
$link_data = $cached_data->{links} || [];
}
else {
my $weather = Weather::Com::Finder->new({
'partner_id' => $self->get("partnerId"),
'license' => $self->get("licenseKey"),
'cache' => '/tmp',
});
next unless defined $weather;
foreach my $foundLocation(@{$weather->find($location)}) {
my $current_conditions = $foundLocation->current_conditions;
my $conditions = $current_conditions->description;
$conditions =~ s/\b(\w)/uc($1)/eg;
my $tempC = $current_conditions->temperature;
my $tempF;
$tempF = sprintf("%.0f",(((9/5)*$tempC) + 32)) if($tempC);
my $icon = $current_conditions->icon || "na";
foreach my $foundLocation(@{$weather->find($location)}) {
my $current_conditions = $foundLocation->current_conditions;
my $conditions = $current_conditions->description;
$conditions =~ s/\b(\w)/uc($1)/eg;
my $tempC = $current_conditions->temperature;
my $tempF;
$tempF = sprintf("%.0f",(((9/5)*$tempC) + 32)) if($tempC);
my $icon = $current_conditions->icon || "na";
push(@{$var{'ourLocations.loop'}}, {
query => $location,
cityState => $foundLocation->name || $location,
sky => $conditions || 'N/A',
tempF => (defined $tempF)?$tempF:'N/A',
tempC => (defined $tempC)?$tempC:'N/A',
smallIcon => $url->extras("wobject/WeatherData/small_icons/".$icon.".png"),
mediumIcon => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
largeIcon => $url->extras("wobject/WeatherData/large_icons/".$icon.".png"),
iconUrl => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
iconAlt => $conditions,
});
if (!$var{links_loop}) {
$var{links_loop} = [];
push @{$loop_data}, {
query => $location,
cityState => $foundLocation->name || $location,
sky => $conditions || 'N/A',
tempF => (defined $tempF)?$tempF:'N/A',
tempC => (defined $tempC)?$tempC:'N/A',
smallIcon => $url->extras("wobject/WeatherData/small_icons/".$icon.".png"),
mediumIcon => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
largeIcon => $url->extras("wobject/WeatherData/large_icons/".$icon.".png"),
iconUrl => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
iconAlt => $conditions,
last_fetch => time(),
};
for my $lnk (@{$foundLocation->current_conditions->{WEATHER}{lnks}{link}} ) {
push @{$var{links_loop}}, {
link_url => $lnk->{l},
link_title => $lnk->{t},
};
if (! $link_data) {
push @{ $link_data }, {
link_url => $lnk->{l},
link_title => $lnk->{t},
};
}
}
}
}
my $cache = WebGUI::Cache->new($session, [$self->getId, $location]);
my $cached_data = {
locations => $loop_data,
links => $link_data,
};
$cache->set($cached_data, $self->get('cacheTimeout'));
}
push @{$var{'ourLocations.loop'}}, @{ $loop_data };
if (!$var{links_loop}) {
$var{links_loop} = $link_data;
}
}
}
return $self->processTemplate(\%var, undef, $self->{_viewTemplate});

View file

@ -0,0 +1,129 @@
package WebGUI::AssetAspect::Dashlet;
use strict;
use Class::C3;
use JSON qw/to_json from_json/;
=head1 NAME
WebGUI::AssetAspect::Dashlet - Implement features to turn Assets into Dashlets
=head1 SYNOPSIS
This Aspect provides methods that allow a Dashboard to determine, store and retrieve
customization options for Assets.
=head1 DESCRIPTION
=head1 METHODS
#----------------------------------------------------------------------------
=head2 fetchUserOverrides ($dashboardAssetId, [$userId])
Retrieve user preferences for a particular dashboard and user for this Asset from the database.
=head3 $dashboardId
The assetId of the dashboard to reference.
=head3 $userId
The userId to whose preferences should be returned. Uses the current session user if omitted.
=cut
sub fetchUserOverrides {
my $self = shift;
my $dashboardAssetId = shift;
my $userId = shift || $self->session->user->userId;
my $properties_json = $self->session->db->quickScalar('select properties from Dashboard_userPrefs where dashboardAssetId=? and userId=? and dashletAssetId=?',[$dashboardAssetId, $userId, $self->getId,]);
$properties_json ||= '{}';
my $properties = from_json($properties_json);
return $properties;
}
#----------------------------------------------------------------------------
=head2 getOverrideFormDefinition
Return an array ref of form properties. The form properties are those that the
Asset has marked as being able to be overridden by a Dashboard asset by giving
the property the dashletOverridable flag.
Assets that want to allow additional properties outside of their definition should
override and extend this method.
=cut
sub getOverrideFormDefinition {
my $self = shift;
my $session = $self->session;
my @definitions = reverse @{ $self->definition($session) };
my @properties = ();
foreach my $definition (@definitions) {
foreach my $property_name (keys %{ $definition->{properties} }) {
my $property = $definition->{properties}->{$property_name};
next unless $property->{dashletOverridable};
$property->{name} = $property_name;
push @properties, $property;
}
}
return @properties;
}
#----------------------------------------------------------------------------
=head2 getUserOverrides
Store user preferences for this Asset. This is direct reference from inside the object, so
if you plan to modify the data, Clone it first.
=cut
sub getUserOverrides {
return shift->{_userOverrides};
}
#----------------------------------------------------------------------------
=head2 setUserOverrides
Store user preferences for this Asset.
=cut
sub setUserOverrides {
shift->{_userOverrides} = shift;
}
#----------------------------------------------------------------------------
=head2 storeUserOverrides ($dashboardAssetId, $properties, [$userId])
Store user preferences for a particular dashboard and user for this Asset to the database.
=head3 $dashboardId
The assetId of the dashboard to reference.
=head3 $userId
The userId to whose preferences should be returned. Uses the current session user if omitted.
=cut
sub storeUserOverrides {
my $self = shift;
my $session = $self->session;
my $dashboardAssetId = shift;
my $properties = shift;
my $userId = shift || $session->user->userId;
my $properties_json = to_json($properties);
$session->db->write('DELETE FROM Dashboard_userPrefs where dashboardAssetId=? and userId=? and dashletAssetId=?',[$dashboardAssetId, $userId, $self->getId]);
$session->db->write('INSERT INTO Dashboard_userPrefs (dashboardAssetId, userId, dashletAssetId, properties) VALUES (?,?,?,?)', [$dashboardAssetId, $userId, $self->getId, $properties_json]);
}
1; # You can't handle the truth

View file

@ -141,6 +141,31 @@ sub getValueAsHtml {
}
#-------------------------------------------------------------------
=head2 headTags ( )
Set the head tags for this form plugin
=cut
sub headTags {
my $self = shift;
my $style = $self->session->style;
my $url = $self->session->url;
$style->setLink($url->extras('yui/build/container/assets/skins/sam/container.css'), { rel => 'stylesheet', type => 'text/css' });
$style->setLink($url->extras('yui/build/button/assets/skins/sam/button.css'), { rel => 'stylesheet', type => 'text/css' });
$style->setScript($url->extras('yui/build/connection/connection-min.js'), { type=>'text/javascript' });
$style->setScript($url->extras('yui/build/element/element-min.js'), { type=>'text/javascript' });
$style->setScript($url->extras('yui/build/button/button-min.js'), { type=>'text/javascript' });
$style->setScript($url->extras('yui/build/container/container-min.js'), { type=>'text/javascript' });
$style->setScript($url->extras('yui-webgui/build/form/form.js'), { type=>'text/javascript' });
$style->setScript($url->extras('yui/build/json/json-min.js'), {type => 'text/javascript'});
$style->setScript($url->extras('yui-webgui/build/i18n/i18n.js'), {type => 'text/javascript'} );
$style->setScript($url->extras('yui-webgui/build/form/groupManager.js'), { type=>'text/javascript' });
$style->setLink($url->extras('yui-webgui/build/form/groupManager.css'), { rel => 'stylesheet', type => 'text/css' });
}
#-------------------------------------------------------------------
=head2 isDynamicCompatible ( )
@ -180,9 +205,9 @@ Creates a series of hidden fields representing the data in the list.
=cut
sub toHtmlAsHidden {
my $self = shift;
$self->set("options", $self->session->db->buildHashRef("select groupId,groupName from groups"));
return $self->SUPER::toHtmlAsHidden();
my $self = shift;
$self->set("options", $self->session->db->buildHashRef("select groupId,groupName from groups"));
return $self->SUPER::toHtmlAsHidden();
}
#-------------------------------------------------------------------
@ -194,14 +219,187 @@ Renders the form field to HTML as a table row complete with labels, subtext, hov
=cut
sub toHtmlWithWrapper {
my $self = shift;
if ($self->session->user->isAdmin) {
my $subtext = $self->session->icon->manage("op=listGroups");
$self->set("subtext",$subtext . $self->get("subtext"));
my $self = shift;
my $session = $self->session;
my $user = $session->user;
if ($user->isAdmin) {
my $subtext = $session->icon->manage("op=listGroups");
$self->set("subtext", $subtext . $self->get("subtext"));
}
my $dialog = $self->get('name') . '_groupDialog';
my $group_manager = $user->isInGroup($session->setting->get('groupIdAdminGroup'));
my $form;
if ($group_manager) {
my $i18n = WebGUI::International->new($self->session,'Icon');
my $name = $self->get('name');
my $groupId = $self->getOriginalValue;
my $extra_subtext = qq!<span class="toolbarIcon" style="vertical-align:middle;"><a href="#" onClick="WebGUI.Form.GroupManager.show_dialog('$name'); return false;"><img src="!. $session->icon->getBaseURL().qq!edit.gif" alt="!. $i18n->get('Edit') .qq!"style="vertical-align:middle;border: 0px;" /></a></span>!;
$extra_subtext .= qq!<span class="toolbarIcon" style="vertical-align:middle;"><a href="#" onClick="WebGUI.Form.GroupManager.show_dialog('$name', 'new'); return false;"><img src="!. $session->icon->getBaseURL().qq!add.gif" alt="!. $i18n->get('Add') .qq!" style="vertical-align:middle;border: 0px;" /></a></span>!;
$self->set("subtext", $self->get('subtext').$extra_subtext);
}
$self->headTags;
$form .= $self->SUPER::toHtmlWithWrapper;
return $form;
}
#-------------------------------------------------------------------
=head2 www_groupMembers ($session)
Returns a list of users that are in the sub-group specified by the form variable
variable C<groupId>. Data returned is in JSON format.
This is a class method.
=head3 $session
A WebGUI::Session object.
=cut
sub www_groupMembers {
my $session = shift;
return '{}' unless $session->user->isInGroup($session->setting->get('groupIdAdminGroup'));
my $groupId = $session->form->param('groupId');
return '{}' unless $groupId;
my $group = WebGUI::Group->new($session, $groupId);
return '{}' unless $group;
my $results = {
groupName => $group->name,
users => [],
groups => [],
};
my $userIds = $group->getUsers('withoutExpired');
USER: foreach my $userId (@{ $userIds }) {
my $user = WebGUI::User->new($session, $userId);
next USER unless $user;
push @{$results->{users}},
{
username => $user->username,
userId => $userId,
};
}
my $groupIds = $group->getGroupsIn(0); ##Without recursion
GROUP: foreach my $groupId (@{ $groupIds }) {
my $group = WebGUI::Group->new($session, $groupId);
next GROUP unless $group;
push @{$results->{groups}},
{
groupName => $group->name,
groupId => $groupId,
};
}
return JSON::to_json($results);
}
#-------------------------------------------------------------------
=head2 www_saveGroup ($session)
Save new information about the membership of a group, which users have
been added and deleted, and which groups have been added and deleted.
This is a subroutine, not a class method, not an object method.
=head3 $session
A WebGUI::Session object.
=head3 Expected form variables
=head4 groupId
The GUID for the group to modify.
=head4 groupName
The name of the group. This is always set, so it should always be included.
=head4 usersAdded
A list of userId's for users who were added.
=head4 usersDeleted
A list of userId's for users who were deleted. Deleting happens after adding.
=head4 groupsAdded
A list of groupId's for groups who were added.
=head4 groupsDeleted
A list of groupId's for groups who were deleted. Deleting happens after adding.
=cut
sub www_saveGroup {
my $session = shift;
$session->log->warn("hit the group plugin");
return '{}' unless $session->user->isInGroup($session->setting->get('groupIdAdminGroup'));
my $form = $session->form;
my $groupId = $form->get('groupId');
my $group = WebGUI::Group->new($session, $groupId);
$session->log->warn("got groupId: $groupId");
return '{}' unless $group;
$session->log->warn("updating group data, name = ".$form->get('groupName'));
$group->name($form->get('groupName'));
my @usersAdded = $form->get('usersAdded');
use Data::Dumper;
$session->log->warn("users added ".Dumper(\@usersAdded));
$group->addUsers(\@usersAdded);
my @usersDeleted = $form->get('usersDeleted');
$group->deleteUsers(\@usersDeleted);
my @groupsAdded = $form->get('groupsAdded');
$session->log->warn("groups added ".Dumper(\@groupsAdded));
$group->addGroups(\@groupsAdded);
my @groupsDeleted = $form->get('groupsDeleted');
$group->deleteGroups(\@groupsDeleted);
return JSON::to_json({ groupId => $group->getId, groupName => $group->name, originalGroupId => $groupId });
}
#-------------------------------------------------------------------
=head2 www_searchGroups ($session)
Returns groups that match the supplied group name. Group name is specified via the form
variable C<search>. A list of groups will be returned of up to 15 names and groupIds.
This is a subroutine, not a class method, not an object method.
=head3 $session
A WebGUI::Session object.
=head3 Sample JSON
{
'results' : [
{
'groupId': 'someGroupId',
'groupName' : 'Great Group'
}
return $self->SUPER::toHtmlWithWrapper;
//Other hashes may be in the list, or it could be completely empty
]
}
=cut
sub www_searchGroups {
my $session = shift;
return '{"results":[]}' unless $session->user->isInGroup($session->setting->get('groupIdAdminGroup'));
my $search = $session->form->param('query');
my $results = $session->db->buildArrayRefOfHashRefs(q|select groupId, groupName from groups where groupName like CONCAT(?, '%') and showInForms=1 LIMIT 15|, [ $search ]);
return JSON::to_json({ results => $results });
}
1;

View file

@ -170,5 +170,25 @@ sub toHtml {
)->toHtml).$manage;
}
#-------------------------------------------------------------------
=head2 www_searchUsers
Returns users that match the supplied username. Username is specified via the form
variable C<search>. A list of usernames will be returned of up to 15 names and userIds.
=cut
sub www_searchUsers {
my $session = shift;
return '{"results":[]}' unless $session->user->isInGroup($session->setting->get('groupIdAdminUser'));
my $search = $session->form->param('query');
my $results = $session->db->buildArrayRefOfHashRefs(q|select userId, username from users where username like CONCAT(?, '%') LIMIT 15|, [ $search ]);
return JSON::to_json({ results => $results });
}
1;

View file

@ -0,0 +1,60 @@
package WebGUI::Help::Asset_Dashboard;
use strict;
our $HELP = {
'dashboard template' => {
title => 'Dashboard Template Variables',
isa => [
{ namespace => "Asset_Dashboard",
tag => "dashboard asset template variables"
},
{ namespace => "Asset",
tag => "asset template"
},
],
fields => [],
variables => [
{ name => 'dragger.init' },
{ name => 'fullUrl' },
{ name => 'canEdit' },
{ name => 'positionN_loop',
variables => [
{ 'name' => 'id' },
{ 'name' => 'content' },
{ 'name' => 'dashletTitle' },
{ 'name' => 'shortcutUrl' },
{ 'name' => 'dashletUrl' },
{ 'name' => 'canDelete' },
{ 'name' => 'canMove' },
{ 'name' => 'canPersonalize' },
{ 'name' => 'showReloadIcon' },
{ 'name' => 'canEditUserPrefs' },
{ 'name' => 'editFormUrl' },
]
},
],
related => []
},
'dashboard asset template variables' => {
private => 1,
title => 'dashboard asset template variables title',
isa => [
{ namespace => "Asset_Wobject",
tag => "wobject template variables"
},
],
fields => [],
variables => [
{ name => 'templateId' },
{ name => 'adminsGroupId' },
{ name => 'usersGroupId' },
{ name => 'isInitialized' },
],
related => []
},
};
1;

View file

@ -0,0 +1,48 @@
package WebGUI::Macro::LastUpdatedBy;
#-------------------------------------------------------------------
# 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 WebGUI::Asset;
use WebGUI::User;
=head1 NAME
Package WebGUI::Macro::LastUpdatedBy
=head1 DESCRIPTION
Macro for displaying the username of the user that made the most recent revision of current Asset.
=head2 process ( )
Display the username, if the user still exists in the system. If not, of if the user does not
have a username, then display an internationalized label for "Unknown".
=cut
#-------------------------------------------------------------------
sub process {
my $session = shift;
return '' unless $session->asset;
my $userId = $session->asset->getContentLastModifiedBy();
my $user = WebGUI::User->new($session, $userId);
if ($user && $user->username) {
return $user->username;
}
my $i18n = WebGUI::International->new($session,'Macro_LastModified');
return $i18n->get('Unknown');
}
1;

View file

@ -130,6 +130,8 @@ sub getOperations {
'listGroups' => 'Group',
'manageGroupsInGroup' => 'Group',
'manageUsersInGroup' => 'Group',
'manageGroups' => 'Group',
'updateGroupUsers' => 'Group',
'viewHelp' => 'Help',
'viewHelpIndex' => 'Help',

View file

@ -30,16 +30,6 @@ our $I18N = {
message => q|The group whose users may save their personalizations/preferences to the site. If someone is in the "Who can view?" group but not in this group, they can personalize the arrangement of the Dashlets (whose positions will be saved in cookies), but they will not be able to edit the preferences of any particular Dashlet.|,
lastUpdated => 1133619940
},
'dashboard template field label' => {
message => q|Dashboard Template|,
lastUpdated => 1133619940
},
'dashboard template field label' => {
message => q|Dashboard Template|,
lastUpdated => 1133619940
},
'assets to hide' => {
message => q|Assets To Hide.|,
lastUpdated => 1118942468
@ -57,6 +47,168 @@ checkbox for any Asset that you do not want displayed in the Page Layout Asset.
lastUpdated => 1230356526,
},
'Edit Dashlet' => {
message => q|Edit Dashlet|,
lastUpdated => 1230356526,
context => q|A dashlet is an asset being displayed by the Dashboard. It may not have a translation.|,
},
'Is static' => {
message => q|Is static|,
lastUpdated => 1230356526,
context => q|Can it be moved, or rearranged?|,
},
'Is static help' => {
message => q|Can this dashlet be moved around on the dashboard by users of the Dashboard?|,
lastUpdated => 1230356526,
context => q|Can it be moved, or rearranged?|,
},
'Is required' => {
message => q|Is required|,
lastUpdated => 1230356526,
context => q|Can it be deleted from a dashboard by a user?|,
},
'Is required help' => {
message => q|Can this dashlet be deleted from the dashboard by users of the Dashboard?|,
lastUpdated => 1230356526,
context => q|Can it be moved, or rearranged?|,
},
'Dashboard Template Variables' => {
message => q|Dashboard Template Variables|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'dragger.init' => {
message => q|Javascript necessary to initialize the Dashboard. It should be placed at the bottom of the template.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'fullUrl' => {
message => q|The full URL to this Dashboard, including sitename and any gateway configuration.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'canEdit' => {
message => q|A boolean which will be true if the current user can edit this Dashboard.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'positionN_loop' => {
message => q|By default, there are four positions, numbered 1, 2, 3 and 4. Each loop contains the list of assets that have been placed into it. Position 1 is special, because it also contains any assets which have not been specifically placed by the user.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'id' => {
message => q|Asset ID of the current dashlet.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'content' => {
message => q|The dashlet's content|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'dashletTitle' => {
message => q|The title of the dashlet, the raw asset title.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'shortcutUrl' => {
message => q|If this dashlet is a shortcut, the URL of the shortcut.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'dashletUrl' => {
message => q|The URL to this dashlet.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'canDelete' => {
message => q|A boolean that is true if the current user is in the group who can personalize the dashboard and if this dashlet is not set to be required.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'canMove' => {
message => q|A boolean that is true if the current user is in the group who can personalize the dashboard and if this dashlet is not set to be static.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'canPersonalize' => {
message => q|A boolean that is true if the current user is in the group who can personalize the dashboard.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'showReloadIcon' => {
message => q|A boolean that is true if this dashlet is a shortcut, and the Show Reload Icon property is set to be true.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'canEditUserPrefs' => {
message => q|A boolean that is true if the current user is in the Registered Users group, and the dashlet is a Shortcut, and the Shortcut has preferences that can be configured.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'dashboard asset template variables title' => {
message => q|Dashboard Asset Template Variables|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'templateId' => {
message => q|The GUID of the template used to display the dashboard|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'adminsGroupId' => {
message => q|The GUID of the group that is allowed to set the default appearance of the dashboard for visitors.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'usersGroupId' => {
message => q|The GUID of the group that is allowed to change the appearance of their own dashboard.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'isInitialized' => {
message => q|A boolean which is true if this Dashboard has been initialized. You really don't need to know more than that.|,
lastUpdated => 1230356526,
context => q|Template variable help|,
},
'Add New Content' => {
message => q|Add New Content|,
lastUpdated => 1230356526,
context => q|i18n phrase for the view template|,
},
'editFormUrl' => {
message => q|The URL to fetch the user overrides form for this dashlet, whether it is Shortcut based or a regular asset with overrides.|,
lastUpdated => 1230356526,
context => q|i18n phrase for the view template|,
},
};
1;

View file

@ -514,6 +514,12 @@ our $I18N = {
lastUpdated => 1229493261,
},
'cache timeout help' => {
message => q|How long should lookups for each stock symbol be cached internally? Note, the default template has javascript that does fetches on the client side.|,
context => q|Template variable help|,
lastUpdated => 1229493261,
},
};
1;

View file

@ -102,6 +102,12 @@ our $I18N = {
lastUpdated => 1167972337
},
'cache timeout help' => {
message => q|How long should lookups for each location be cached internally?|,
context => q|Template variable help|,
lastUpdated => 1229493261,
},
};
1;

View file

@ -0,0 +1,33 @@
package WebGUI::i18n::English::Form_Group;
use strict; ##Required for all good Perl::Critic compliant code
our $I18N = {
'Group Manager' => {
message => q|Group Manager|,
lastUpdated => 1131394070, #seconds from the epoch
context => q|A form to add or do minor edits to groups|
},
'Add User...' => {
message => q|Add User...|,
lastUpdated => 1131394070, #seconds from the epoch
context => q|Hint for a text box where you enter in a username|
},
'Add Group...' => {
message => q|Add Group...|,
lastUpdated => 1131394070, #seconds from the epoch
context => q|Hint for a text box where you enter in a groupname|
},
'New Group' => {
message => q|New Group|,
lastUpdated => 1131394070, #seconds from the epoch
context => q|Label for a button to create a new group.|
},
};
1;
#vim:ft=perl

View file

@ -92,6 +92,12 @@ our $I18N = {
lastUpdated => 1096319562
},
'Add' => {
message => q|Add|,
lastUpdated => 1096319562,
context => q|to add something new, to create/acquire|,
},
'Edit help' => {
message => q|Edit the properties of this Asset. This icon is only available if the asset isn't locked, or if it is locked and you are using the tag it was edited under.|,
lastUpdated => 1165448622

View file

@ -8,6 +8,12 @@ our $I18N = {
lastUpdated => 1134969093
},
'Unknown' => {
message => q|Unknown|,
lastUpdated => 1134969093,
context => q|meaning, we do not know who it is, and it is not Visitor|,
},
};
1;

View file

@ -3049,6 +3049,12 @@ or are under your current version tag.</p>
context => q|Label of the cancel button|
},
'Cancel' => {
message => q|Cancel|,
lastUpdated =>1092930637,
context => q|Label of the cancel button, with capital C|
},
'trash' => {
message => q|Trash|,
lastUpdated =>1211131614,

View file

@ -71,6 +71,7 @@ checkModule("Test::LongString", 0.13, 2 );
checkModule("Test::Exception", 0.27, 2 );
checkModule("Test::Differences", 0.5, 2 );
checkModule("Test::Class", 0.31, 2 );
checkModule("Test::MockTime", 0.09, 2 );
checkModule("Pod::Coverage", 0.19, 2 );
checkModule("Text::Balanced", 2.00, 2 );
checkModule("Digest::MD5", 2.38 );

View file

@ -172,7 +172,7 @@ sub definition {
package main;
plan tests => 134
plan tests => 137
+ scalar(@fixIdTests)
+ scalar(@fixTitleTests)
+ 2*scalar(@getTitleTests) #same tests used for getTitle and getMenuTitle
@ -1011,8 +1011,12 @@ $session->http->setRedirectLocation('');
is $clippedAsset->checkView(), 'chunked', 'checkView: returns "chunked" when admin is on for cut asset';
is $session->http->getRedirectLocation, $clippedAsset->getUrl('func=manageClipboard'), '... cut asset sets redirect to manageClipboard';
#----------------------------------------------------------------------------
# packed head tags
################################################################
#
# Packed head tags
#
################################################################
use HTML::Packer;
my $asset = WebGUI::Asset->getImportNode( $session )->addChild({
className => 'WebGUI::Asset::Snippet',
@ -1035,6 +1039,30 @@ is $asset->get('extraHeadTagsPacked'), $packed, 'extraHeadTagsPacked';
$asset->update({ extraHeadTags => '' });
ok !$asset->get('extraHeadTagsPacked'), 'extraHeadTagsPacked cleared';
################################################################
#
# getContentLastModifiedBy
#
################################################################
{
my $revised_user1 = WebGUI::User->new($session, 'new');
my $revised_user2 = WebGUI::User->new($session, 'new');
WebGUI::Test->addToCleanup($revised_user1, $revised_user2 );
$session->user({user => $revised_user1});
my $versionTag = WebGUI::VersionTag->getWorking($session);
my $asset = WebGUI::Asset->getImportNode( $session )->addChild({
className => 'WebGUI::Asset::Snippet',
}, undef, 12);
$versionTag->commit;
$asset = $asset->cloneFromDb;
WebGUI::Test->addToCleanup($asset, $versionTag);
is $asset->getContentLastModifiedBy, $asset->get('revisedBy'), 'getContentLastModifiedBy returns revisedBy for most assets';
is $asset->getContentLastModifiedBy, $revised_user1->userId, '... real userId check';
$session->user({user => $revised_user2});
$asset = $asset->addRevision({ title => 'titular', }, 14);
is $asset->getContentLastModifiedBy, $revised_user2->userId, '... check that a new revision tracks';
}
##Return an array of hashrefs. Each hashref describes a test
##for the fixId method.

67
t/Asset/Wobject/Folder.t Normal file
View file

@ -0,0 +1,67 @@
#-------------------------------------------------------------------
# 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 File::Spec;
use lib "$FindBin::Bin/../../lib";
use Test::MockTime qw/:all/; ##Must be loaded before all other code
use WebGUI::Test;
use WebGUI::Session;
use Test::More tests => 3; # increment this value for each test you create
use WebGUI::Asset::Wobject::Folder;
my $session = WebGUI::Test->session;
# Do our work in the import node
my $node = WebGUI::Asset->getImportNode($session);
################################################################
#
# getContentLastModifiedBy
#
################################################################
my $revised_user1 = WebGUI::User->new($session, 'new');
my $revised_user2 = WebGUI::User->new($session, 'new');
WebGUI::Test->addToCleanup($revised_user1, $revised_user2 );
$session->user({userId => 3});
set_relative_time(-600);
WebGUI::Test->addToCleanup(sub { restore_time(); });
my $versionTag = WebGUI::VersionTag->getWorking($session);
my $folder = $node->addChild({
className => 'WebGUI::Asset::Wobject::Folder',
}, undef, 12);
$session->user({user => $revised_user1});
my $snip1 = $folder->addChild({
className => 'WebGUI::Asset::Snippet',
}, undef, 14);
set_relative_time(-500);
$session->user({user => $revised_user2});
my $snip2 = $folder->addChild({
className => 'WebGUI::Asset::Snippet',
}, undef, 16);
$folder = $folder->cloneFromDb;
$snip1 = $snip1->cloneFromDb;
$snip2 = $snip2->cloneFromDb;
WebGUI::Test->addToCleanup($folder);
is $folder->getContentLastModifiedBy, $snip2->get('revisedBy'), 'getContentLastModifiedBy returns revisedBy for most recent child asset';
is $folder->getContentLastModifiedBy, $revised_user2->userId, '... real userId check';
$session->user({user => $revised_user1});
set_relative_time(-100);
$snip1 = $snip1->addRevision({ title => 'titular', }, 18);
is $folder->getContentLastModifiedBy, $revised_user1->userId, '... check that a new revision tracks';

67
t/Asset/Wobject/Layout.t Normal file
View file

@ -0,0 +1,67 @@
#-------------------------------------------------------------------
# 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 File::Spec;
use lib "$FindBin::Bin/../../lib";
use Test::MockTime qw/:all/; ##Must be loaded before all other code
use WebGUI::Test;
use WebGUI::Session;
use Test::More tests => 3; # increment this value for each test you create
use WebGUI::Asset::Wobject::Layout;
my $session = WebGUI::Test->session;
# Do our work in the import node
my $node = WebGUI::Asset->getImportNode($session);
################################################################
#
# getContentLastModifiedBy
#
################################################################
my $revised_user1 = WebGUI::User->new($session, 'new');
my $revised_user2 = WebGUI::User->new($session, 'new');
WebGUI::Test->addToCleanup($revised_user1, $revised_user2 );
$session->user({userId => 3});
set_relative_time(-600);
WebGUI::Test->addToCleanup(sub { restore_time(); });
my $versionTag = WebGUI::VersionTag->getWorking($session);
my $page = $node->addChild({
className => 'WebGUI::Asset::Wobject::Layout',
}, undef, 12);
$session->user({user => $revised_user1});
my $snip1 = $page->addChild({
className => 'WebGUI::Asset::Snippet',
}, undef, 14);
set_relative_time(-500);
$session->user({user => $revised_user2});
my $snip2 = $page->addChild({
className => 'WebGUI::Asset::Snippet',
}, undef, 16);
$page = $page->cloneFromDb;
$snip1 = $snip1->cloneFromDb;
$snip2 = $snip2->cloneFromDb;
WebGUI::Test->addToCleanup($page);
is $page->getContentLastModifiedBy, $snip2->get('revisedBy'), 'getContentLastModifiedBy returns revisedBy for most recent child asset';
is $page->getContentLastModifiedBy, $revised_user2->userId, '... real userId check';
$session->user({user => $revised_user1});
set_relative_time(-100);
$snip1 = $snip1->addRevision({ title => 'titular', }, 18);
is $page->getContentLastModifiedBy, $revised_user1->userId, '... check that a new revision tracks';

View file

@ -0,0 +1,65 @@
# 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 Test::MockTime qw/:all/;
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;
use WebGUI::Cache;
#----------------------------------------------------------------------------
# Init
my $session = WebGUI::Test->session;
my $node = WebGUI::Asset->getImportNode( $session );
#----------------------------------------------------------------------------
# Tests
plan tests => 6; # Increment this number for each test you create
#----------------------------------------------------------------------------
# Asset Report creation
my $asset = $node->addChild( {
className => 'WebGUI::Asset::Wobject::StockData',
source => 'usa',
defaultStocks => "GWR",
cacheTimeout => 2000,
} );
WebGUI::Test->addToCleanup($asset);
my $now = time();
set_relative_time(-1000);
my $stocks = $asset->_getStocks(["GWR"]);
is $stocks->{qw/GWR symbol/}, 'GWR', 'stock fetch successful';
cmp_ok $stocks->{qw/GWR last_fetch/}, '<', $now-500, 'last_fetch set in the past';
my $last_fetch = $stocks->{qw/GWR last_fetch/};
my $cache = WebGUI::Cache->new($session, [$asset->getId, 'usa', 'GWR']);
is $cache->get()->{qw/GWR symbol/}, 'GWR', 'cache loaded with valid data';
restore_time();
my $stocks2 = $asset->_getStocks([qw/GWR UNP/]);
is $stocks2->{qw/UNP symbol/}, 'UNP', 'stock fetch successful, new stock';
is $stocks2->{qw/GWR symbol/}, 'GWR', '... cached stock';
is $stocks2->{qw/GWR last_fetch/}, $last_fetch, 'GWR stock lookup was cached';
#vim:ft=perl

View file

@ -0,0 +1,111 @@
# 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 Test::MockTime qw/:all/;
use FindBin;
use strict;
use lib "$FindBin::Bin/../../lib";
use Test::More;
use Test::Deep;
use Clone qw/clone/;
use WebGUI::Test; # Must use this before any other WebGUI modules
use WebGUI::Session;
use WebGUI::Cache;
#----------------------------------------------------------------------------
# Init
my $session = WebGUI::Test->session;
my $node = WebGUI::Asset->getImportNode( $session );
#----------------------------------------------------------------------------
# Tests
my $can_test = 1;
my $partnerId = $session->config->get('testing/WeatherData_partnerId');
if (!$partnerId) {
$partnerId = 'partnerId';
$can_test = 0;
}
my $licenseKey = $session->config->get('testing/WeatherData_licenseKey');
if (!$licenseKey) {
$partnerId = 'licenseKey';
$can_test = 0;
}
if ($can_test) {
plan tests => 7; # Increment this number for each test you create
}
else {
plan skip_all => 'Missing credentials for Weather.com';
}
#----------------------------------------------------------------------------
# Asset Report creation
#1234567890123456789012#
my $templateId = 'FAKE_WEATHER_TEMPLATEq';
my $templateMock = Test::MockObject->new({});
$templateMock->set_isa('WebGUI::Asset::Template');
$templateMock->set_always('getId', $templateId);
my $templateVars;
$templateMock->mock('process', sub { $templateVars = clone $_[1]; } );
my $asset = $node->addChild( {
className => 'WebGUI::Asset::Wobject::WeatherData',
cacheTimeout => 2000,
partnerId => $partnerId,
licenseKey => $licenseKey,
locations => "53715",
templateId => $templateId,
} );
WebGUI::Test->addToCleanup($asset);
my $now = time();
diag $now;
set_relative_time(-1000);
diag time();
WebGUI::Test->mockAssetId($templateId, $templateMock);
$asset->prepareView();
$asset->view();
my $weather_data = $templateVars->{'ourLocations.loop'}->[0];
is $weather_data->{cityState}, 'Madison, WI (53715)', 'data from weather.com returned';
my $last_fetch = $weather_data->{last_fetch};
diag $last_fetch;
cmp_ok $last_fetch, '<', $now-500, 'last_fetch set in the past';
my $cache = WebGUI::Cache->new($session, [$asset->getId, '53715']);
is $cache->get()->{'locations'}->[0]->{cityState}, 'Madison, WI (53715)', 'cache loaded with valid data';
restore_time();
$cache = WebGUI::Cache->new($session, [$asset->getId, '53715']);
is $cache->get()->{'locations'}->[0]->{cityState}, 'Madison, WI (53715)', 'cache loaded with valid data';
$asset->update({locations => "53715\n97123"});
$asset->view();
$weather_data = $templateVars->{'ourLocations.loop'};
is $weather_data->[1]->{cityState}, 'Hillsboro, OR (97123)', 'weather data fetch successful, new location';
is $weather_data->[0]->{cityState}, 'Madison, WI (53715)', '...cached weather data';
is $weather_data->[0]->{last_fetch}, $last_fetch, '53715 lookup was cached';
#vim:ft=perl

178
t/Form/Group.t Normal file
View file

@ -0,0 +1,178 @@
# 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::Group;
use WebGUI::Group;
use WebGUI::Session;
#The goal of this test is to verify that various www_ methods for the Group plugin work.
use Test::More;
use Test::Deep;
use JSON ();
use Data::Dumper;
my $session = WebGUI::Test->session;
# put your tests here
plan tests => 11;
my $groupAdminUser = WebGUI::User->new($session, 'new');
my $groupAdminGroup = WebGUI::Group->new($session, 'new');
$groupAdminGroup->addUsers([$groupAdminUser->userId]);
$session->setting->set('groupIdAdminGroup', $groupAdminGroup->getId);
WebGUI::Test->addToCleanup($groupAdminUser, $groupAdminGroup);
my $json;
$json = WebGUI::Form::Group::www_searchGroups($session);
is $json, '{"results":[]}', 'www_searchGroups: unprivileged user is not allowed to use this';
$session->user({user => $groupAdminUser});
$json = WebGUI::Form::Group::www_searchGroups($session);
is $json, '{"results":[]}', '... without a body parameter, returns valid empty JSON array';
$session->request->setup_body({query => 'Registered Users'});
$json = WebGUI::Form::Group::www_searchGroups($session);
my $group_data = JSON::from_json($json);
cmp_deeply(
$group_data,
{
results => [
{
groupId => 2,
groupName => 'Registered Users',
},
],
},
'... with an exact match, get one result back'
);
{
my @groups = map { my $group = WebGUI::Group->new($session, 'new'); $group->name('Test Group '. $_); $group; } 1..20;
my $cleanup = WebGUI::Test->cleanupGuard(@groups);
$session->request->setup_body({query => 'Test Group'});
$json = WebGUI::Form::Group::www_searchGroups($session);
my $group_data = JSON::from_json($json);
is scalar @{ $group_data->{results} }, 15, '... results are limited to 15';
}
{
my @groups = map { my $group = WebGUI::Group->new($session, 'new'); $group->name('Test Group '. $_); $group; } 1..5;
$groups[0]->showInForms(0);
my $cleanup = WebGUI::Test->cleanupGuard(@groups);
$session->request->setup_body({query => 'Test Group'});
$json = WebGUI::Form::Group::www_searchGroups($session);
my $group_data = JSON::from_json($json);
my $has_group0 = grep { $_->{groupName} eq $groups[0]->name } @{ $group_data->{results} };
ok ! $has_group0, '... group with showInForms set to false does not show up in the results';
}
my $test_group = WebGUI::Group->new($session, 'new');
$test_group->name('Testing Group');
my $andy = WebGUI::User->new($session, 'new');
$andy->username('andy');
my $red = WebGUI::User->new($session, 'new');
$red->username('red');
WebGUI::Test->addToCleanup($test_group, $andy, $red);
$session->request->setup_body({});
$session->user({userId => 1});
$json = WebGUI::Form::Group::www_groupMembers($session);
is $json, '{}', 'www_groupMembers: returns empty hashref for an unprivileged user';
$session->user({user => $groupAdminUser});
$json = WebGUI::Form::Group::www_groupMembers($session);
is $json, '{}', '... returns empty hashref if no form variable';
#1234567890123456789012
$session->request->setup_body({groupId => 'neverAWebGUIGroupId001'});
$json = WebGUI::Form::Group::www_groupMembers($session);
is $json, '{}', 'www_groupMembers: returns empty hashref if no groupId does not exist in the db';
$session->request->setup_body({groupId => $test_group->getId});
$json = WebGUI::Form::Group::www_groupMembers($session);
$group_data = JSON::from_json($json);
cmp_deeply(
$group_data,
{
groupName => 'Testing Group',
users => [ ],
groups => [
{
groupId => '3',
groupName => 'Admins',
},
],
},
'... with an exact match on an empty group, returns a hashref with arrayrefs'
);
$test_group->addUsers([$andy->getId]);
$json = WebGUI::Form::Group::www_groupMembers($session);
$group_data = JSON::from_json($json);
cmp_deeply(
$group_data,
{
groupName => 'Testing Group',
users => [
{
userId => $andy->userId,
username => 'andy',
}
],
groups => [
{
groupId => '3',
groupName => 'Admins',
},
],
},
'... with an exact match on a populated group, return users and groups'
);
$test_group->addGroups(['2']);
$json = WebGUI::Form::Group::www_groupMembers($session);
$group_data = JSON::from_json($json);
cmp_deeply(
$group_data,
{
groupName => 'Testing Group',
users => [
{
userId => $andy->userId,
username => 'andy',
}
],
groups => bag(
{
groupId => '2',
groupName => 'Registered Users',
},
{
groupId => '3',
groupName => 'Admins',
},
),
},
'... users not listed recursively, groups do not show up twice'
);

74
t/Form/User.t Normal file
View file

@ -0,0 +1,74 @@
# 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::User;
use WebGUI::Group;
use WebGUI::Session;
#The goal of this test is to verify that various www_ methods for the Group plugin work.
use Test::More;
use Test::Deep;
use JSON ();
use Data::Dumper;
my $session = WebGUI::Test->session;
# put your tests here
plan tests => 4;
my $userAdminUser = WebGUI::User->new($session, 'new');
my $userAdminGroup = WebGUI::Group->new($session, 'new');
$userAdminGroup->addUsers([$userAdminUser->userId]);
$session->setting->set('groupIdAdminUser', $userAdminGroup->getId);
WebGUI::Test->addToCleanup($userAdminUser, $userAdminGroup);
my $json;
$json = WebGUI::Form::User::www_searchUsers($session);
is $json, '{"results":[]}', 'www_searchUsers: unprivileged user is not allowed to use this';
$session->user({user => $userAdminUser});
$json = WebGUI::Form::User::www_searchUsers($session);
is $json, '{"results":[]}', '... without a body parameter, returns valid empty JSON array';
$session->request->setup_body({query => 'Visitor'});
$json = WebGUI::Form::User::www_searchUsers($session);
my $group_data = JSON::from_json($json);
cmp_deeply(
$group_data,
{
results => [
{
userId => 1,
username => 'Visitor',
},
],
},
'... with an exact match, get one result back'
);
{
my @users = map { my $user = WebGUI::User->new($session, 'new'); $user->username('Test User '. $_); $user; } 1..20;
my $cleanup = WebGUI::Test->cleanupGuard(@users);
$session->request->setup_body({query => 'Test User'});
$json = WebGUI::Form::User::www_searchUsers($session);
my $group_data = JSON::from_json($json);
is scalar @{ $group_data->{results} }, 15, '... results are limited to 15';
}

71
t/Macro/LastUpdatedBy.t Normal file
View file

@ -0,0 +1,71 @@
#-------------------------------------------------------------------
# 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::Session;
use WebGUI::User;
use WebGUI::Macro::LastUpdatedBy;
use Test::More; # increment this value for each test you create
my $session = WebGUI::Test->session;
$session->user({userId => 1});
my $homeAsset = WebGUI::Asset->getDefault($session);
my $numTests = 3;
plan tests => $numTests;
my $versionTag = WebGUI::VersionTag->getWorking($session);
addToCleanup($versionTag);
my $output = WebGUI::Macro::LastUpdatedBy::process($session);
is($output, '', "Macro returns '' if no asset is defined");
##Make the homeAsset the default asset in the session.
$session->asset($homeAsset);
$versionTag->set({name=>"Adding asset for LastUpdatedBy macro tests"});
my $revised_user = WebGUI::User->new($session, 'new');
$revised_user->username('Andy');
WebGUI::Test->addToCleanup($revised_user);
$session->user({user => $revised_user});
my $root = WebGUI::Asset->getRoot($session);
my %properties_A = (
className => 'WebGUI::Asset',
title => 'Asset A',
url => 'asset-a',
ownerUserId => 3,
groupIdView => 7,
groupIdEdit => 3,
id => '1',
# '1234567890123456789012',
);
my $assetA = $root->addChild(\%properties_A, $properties_A{id});
$versionTag->commit;
$session->asset($assetA);
$output = WebGUI::Macro::LastUpdatedBy::process($session);
is($output, 'Andy', 'Default asset last revised by andy');
$revised_user->delete;
#$revised_user->uncache;
$output = WebGUI::Macro::LastUpdatedBy::process($session);
is($output, 'Unknown', 'macro returns Unknown when the user object cannot be found');

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,258 +1,258 @@
body
{
margin: 0;
margin-top: 0;
padding: 0;
}
table.dashboardColumn
{
width: 100%;
background: none;
background-color:transparent;
}
.dashboardColumn td {
width:100%;
}
#dashboardContainer
{
font: 11px Lucida Grande, Verdana, Arial, Helvetica, sans serif;
background-color:white;
}
#dashboardChooserContainer
{
margin:0px;
padding:0px;
border:0px;
width:100%;
}
#position1 {
width:200px;
max-width:200px;
width:expression("200px");
}
#position1 td {
margin-top:40px;
padding:5px;
}
tbody.availableDashlet * div.content {
display: none;
}
#availableDashlets * td {
width:200px;
max-width:200px;
}
#availableDashlets * div.content {
width:200px;
max-width:200px;
height:0px;
display:none;
overflow-x:hidden;
overflow-y:hidden;
}
#columnsContainerDiv
{
margin:6px;
}
td
{
vertical-align: top;
}
h1
{
font: 12px Lucida Grande, Verdana, Arial, Helvetica, sans serif;
font-weight:bold;
margin:0px;
margin-bottom:3px;
}
h2
{
font: 19px Verdana;
margin-bottom:0px;
padding-bottom:0px;
}
ul
{
margin-top:2px;
left:-10px;
position:relative;
}
div.weatherTitle
{
font-weight:bold;
color:white;
}
div.content
{
overflow-x:hidden;
border-bottom:solid orange 1px;
border-top:solid orange 1px;
border-left:solid orange 1px;
border-right:solid orange 1px;
margin-bottom:10px;
padding:5px;
padding-top:10px;
background: #fff url('content_bg.gif') no-repeat top right;
}
div.content a:link, div.content a:visited
{
color:#F48117;
}
table.tableSearch
{
background-color:#F2F2F2;
border:solid #CCC 1px;
width:100%;
}
table.tableSearch td select
{
margin:0px;
padding:0px;
}
div.dragTitle
{
overflow-x:visible;
background: url('dragable_bg.gif');
width:100%;
z-index:998;
border:solid black 0px;
height:22px;
top:0px;
left:0px;
right:30px;
position:absolute;
}
span.headerTitle
{
height:22px;
clip:rect(auto,auto,auto,auto);
overflow:hidden;
display:block;
float:left;
line-height:18px;
z-index:999;
margin-right:10px;
padding-left:9px;
padding-top:2px;
}
span.options
{
display:block;
position:absolute;
top:0px;
right:-1px;
float:right;
z-index:1000;
padding-right:35px;
background: transparent url('dragtitle_bg.gif') no-repeat top right;
}
span.options img {
opacity:0;
filter:alpha(opacity=0);
}
span.options:hover img {
opacity:100;
}
span.optionsHoverIE img {
filter:alpha(opacity=100);
}
div#availableDashlets * span.options:hover {
opacity:0;
filter:alpha(opacity=0);
}
div#availableDashlets * span.options {
display:none;
opacity:0;
top:500px;
filter:alpha(opacity=0);
}
div#availableDashlets * div.dragTrigger {
background: none;
float:none;
margin-bottom:0px;
/* height:auto;*/
}
div#availableDashlets * div.dragTitle {
background:none;
/* height:auto;*/
overflow:hidden;
float:none;
background-color: #eeeeee;
border: solid #bbbbbb 1px;
color: black;
}
div#availableDashlets * span.headerTitle {
display:block;
width:100%;
line-height:auto;
/* height:22px;*/
background: none;
}
#hideNewContentButton,#showNewContentButton {
/* position:absolute;*/
color: #465D94;
font-size: 1.2em;
font-weight: 600;
top: 20px;
cursor: pointer; cursor: hand;
left: 20px;
width:200px;
}
#availableBox {
display:none;
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
#availableBox2 {
padding-top:40px;
border:solid navy 2px;
height: 600px;
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
#availableDashlets {
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
.availableDashlet
{
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
#availableDashlets tbody {
height: 0px;
}
#leftBox {
width:210px;
}
#rightBox {
width:100%;
body
{
margin: 0;
margin-top: 0;
padding: 0;
}
table.dashboardColumn
{
width: 100%;
background: none;
background-color:transparent;
}
.dashboardColumn td {
width:100%;
}
#dashboardContainer
{
font: 11px Lucida Grande, Verdana, Arial, Helvetica, sans serif;
background-color:white;
}
#dashboardChooserContainer
{
margin:0px;
padding:0px;
border:0px;
width:100%;
}
#position1 {
width:200px;
max-width:200px;
width:expression("200px");
}
#position1 td {
margin-top:40px;
padding:5px;
}
tbody.availableDashlet * div.content {
display: none;
}
#availableDashlets * td {
width:200px;
max-width:200px;
}
#availableDashlets * div.content {
width:200px;
max-width:200px;
height:0px;
display:none;
overflow-x:hidden;
overflow-y:hidden;
}
#columnsContainerDiv
{
margin:6px;
}
td
{
vertical-align: top;
}
h1
{
font: 12px Lucida Grande, Verdana, Arial, Helvetica, sans serif;
font-weight:bold;
margin:0px;
margin-bottom:3px;
}
h2
{
font: 19px Verdana;
margin-bottom:0px;
padding-bottom:0px;
}
ul
{
margin-top:2px;
left:-10px;
position:relative;
}
div.weatherTitle
{
font-weight:bold;
color:white;
}
div.content
{
overflow-x:hidden;
border-bottom:solid orange 1px;
border-top:solid orange 1px;
border-left:solid orange 1px;
border-right:solid orange 1px;
margin-bottom:10px;
padding:5px;
padding-top:10px;
background: #fff url('content_bg.gif') no-repeat top right;
}
div.content a:link, div.content a:visited
{
color:#F48117;
}
table.tableSearch
{
background-color:#F2F2F2;
border:solid #CCC 1px;
width:100%;
}
table.tableSearch td select
{
margin:0px;
padding:0px;
}
div.dragTitle
{
overflow-x:visible;
background: url('dragable_bg.gif');
width:100%;
z-index:998;
border:solid black 0px;
height:22px;
top:0px;
left:0px;
right:30px;
position:absolute;
}
span.headerTitle
{
height:22px;
clip:rect(auto,auto,auto,auto);
overflow:hidden;
display:block;
float:left;
line-height:18px;
z-index:999;
margin-right:10px;
padding-left:9px;
padding-top:2px;
}
span.options
{
display:block;
position:absolute;
top:0px;
right:-1px;
float:right;
z-index:1000;
padding-right:35px;
background: transparent url('dragtitle_bg.gif') no-repeat top right;
}
span.options img {
opacity:0;
filter:alpha(opacity=0);
}
span.options:hover img {
opacity:100;
}
span.optionsHoverIE img {
filter:alpha(opacity=100);
}
div#availableDashlets * span.options:hover {
opacity:0;
filter:alpha(opacity=0);
}
div#availableDashlets * span.options {
display:none;
opacity:0;
top:500px;
filter:alpha(opacity=0);
}
div#availableDashlets * div.dragTrigger {
background: none;
float:none;
margin-bottom:0px;
/* height:auto;*/
}
div#availableDashlets * div.dragTitle {
background:none;
/* height:auto;*/
overflow:hidden;
float:none;
background-color: #eeeeee;
border: solid #bbbbbb 1px;
color: black;
}
div#availableDashlets * span.headerTitle {
display:block;
width:100%;
line-height:auto;
/* height:22px;*/
background: none;
}
#hideNewContentButton,#showNewContentButton {
/* position:absolute;*/
color: #465D94;
font-size: 1.2em;
font-weight: 600;
top: 20px;
cursor: pointer; cursor: hand;
left: 20px;
width:200px;
}
#availableBox {
display:none;
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
#availableBox2 {
padding-top:40px;
border:solid navy 2px;
height: 600px;
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
#availableDashlets {
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
.availableDashlet
{
/* width:200px;
max-width:200px;
width:expression("200px");*/
}
#availableDashlets tbody {
height: 0px;
}
#leftBox {
width:210px;
}
#rightBox {
width:100%;
}

View file

@ -20,7 +20,6 @@ var endTD = null;
var topelement=dom? "HTML" : "BODY"
var currentDiv = null;
var clipboard = null;
var contra = "";
var pageHeight=0;
var pageWidth=0;
var scrollJump=50;
@ -28,36 +27,6 @@ var blankCount=1;
// var getScript = s/<script>(.*)?<\/script>/$1/m;
var reloadIntervals = new Array();
//checks the key Events for copy and paste operations
//ctrlC ctrlV shiftP shiftY
function dragable_checkKeyEvent(e) {
e=dom? e : event;
if (e.keyCode == 38 || e.keyCode == 40 || e.keyCode==37 || e.keyCode==39 || e.keyCode == 66 || e.keyCode == 65){
contra+=e.keyCode;
if (contra.indexOf("38403840373937396665") != -1) {
alert("WebGUI was created by Plain Black Corporation");
contra="";
}
}else {
contra = "";
}
if (currentDiv == null) {
return;
}
if ((e.keyCode == 67 && e.ctrlKey) || (e.keyCode==89 && e.shiftKey)) {
clipboard=currentDiv;
return;
}else if ((e.keyCode == 86 && e.ctrlKey) || (e.keyCode==80 && e.shiftKey)) {
if (clipboard != currentDiv && !dragable_isBlank(clipboard)) {
dragable_moveContent(clipboard,currentDiv);
}
}
}
//goes up the parent tree until class is found. If not found, returns null
function dragable_getObjectByClass(target,clazz) {
while (target.tagName!=topelement&&target.className!=clazz){
@ -69,7 +38,7 @@ function dragable_getObjectByClass(target,clazz) {
}else {
return null;
}
}
//checks to see if the scroll bars need to be adjusted
@ -122,29 +91,32 @@ function dragable_init(url) {
docElement = document.body;
}
pageURL = url;
//window.scroll(10,500);
pageURL = url;
//set up event handlers
document.onmouseup=dragable_dragStop;
// document.onkeydown=dragable_checkKeyEvent;
document.onmousemove=dragable_move;
//fill the draggableObject list
obj = document.getElementById("position1");
contentCount=2;
while (obj != null) {
tbody = dragable_getElementChildren(obj);
children = dragable_getElementChildren(tbody[0]);
if (children.length == 0) {
//stick in a blank
dragable_appendBlankRow(tbody[0]);
}else {
for (i = 0; i< children.length;i++) {
var hasMovableChildren = false;
for (i = 0; i< children.length;i++) {
var childId = children[i].id;
childId = childId.replace(/^td/,'');
if (available_dashlets[childId]) {
draggableObjectList[draggableObjectList.length] = children[i];
dragableList[dragableList.length]=document.getElementById(children[i].id + "_div");
hasMovableChildren = true;
}
}
//Add a blank row if the position is empty, or if there are no movable children.
if (! hasMovableChildren) {
dragable_appendBlankRow(tbody[0]);
}
obj = document.getElementById("position" + contentCount);
contentCount++;
}
@ -165,7 +137,7 @@ function dragable_move(e){
dragable_dragOver(tmp[0],tmp[1]);
}else {
//only occurs if not found
if (endTD != null) {
if (!dragable_isBlank(endTD)) {
document.getElementById(endTD.id + "_div").className="dragable";
@ -181,22 +153,22 @@ function dragable_move(e){
}else {
accuracyCount++;
}
dragable_adjustScrollBars(e);
// alert('x is: '+ (temp1+e.clientX-x));
z.style.left=(temp1+e.clientX-x)+"px";
z.style.top=(temp2+e.clientY-y)+"px";
return false
// }else {
// tmp = dragable_spy(dom? e.pageX: (e.clientX + docElement.scrollLeft),dom? e.pageY: (e.clientY + docElement.scrollTop));
// if (tmp.length == 0) {
// currentDiv = null;
// }else {
// currentDiv = tmp[0];
// }
}
}
@ -249,11 +221,11 @@ function dragable_isBlank(td) {
//returns an array. array[0] holds the tr object, and array[1] holds the position (top or bottom)
function dragable_spy(x, y) {
var returnArray = new Array();
for (i=0;i<draggableObjectList.length;i++) {
td = draggableObjectList[i];
//this is a hack
if (td == null || td == startTD || !td.parentNode || !td.parentNode.parentNode) { continue; }
var fObj=td;
@ -280,7 +252,7 @@ function dragable_spy(x, y) {
}
}
}
return returnArray;
}
@ -305,7 +277,7 @@ function dragable_dragOver(obj,position) {
}else {
divName = td.id + "_div";
}
if (dragable_isBlank(obj)) {
document.getElementById(divName).className="blankOver";
endTDPos=null;
@ -329,12 +301,12 @@ function dragable_dragStop(e) {
dragable_moveContent(startTD,endTD,endTDPos);
if (fObj2) {
var replId = startTD.id;
replId = replId.replace(/^td/gi,'');
replId = replId.replace(/^td/,'');
//alert(replId);
var replUrl = available_dashlets[replId];
//alert(replUrl);
contentDiv = document.getElementById("ct" + replId + "_div");
var callback = {
success : function(req) {
var myArr528 = req.responseText.split(/beginDebug/mg,1);
@ -344,12 +316,12 @@ function dragable_dragStop(e) {
alert("Move failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = replUrl + "?func=ajaxInlineView";
var status = YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
startTD=null;
if (dragable_isBlank(endTD)) {
divName = endTD.id;
}
@ -365,7 +337,7 @@ function dragable_dragStop(e) {
dragableList[i].style.left='0px';
dragableList[i].className="dragable";
}
//this is a ie hack for a render bug
for(i=0;i<draggableObjectList.length;i++) {
if (draggableObjectList[i]) {
@ -376,9 +348,9 @@ function dragable_dragStop(e) {
}
}
}
startTD=null;
if (endTD != null) {
endTD.position = null;
endTD=null;
@ -392,11 +364,11 @@ function dragable_postNewContentMap() {
alert("Post New Content Map Failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = pageURL;
var dataParts = "func=setContentPositions&map=" + dragable_getContentMap();
var status = YAHOO.util.Connect.asyncRequest('POST',url,callback,dataParts);
}
//gets the element children of a dom object
@ -412,6 +384,23 @@ function dragable_getElementChildren(obj) {
return myArray;
}
//gets the element children of a dom object that can be moved, including the blank row
function dragable_getMovableChildren(obj) {
var myArray= new Array();
mycnt = 0;
for (i=0;i<obj.childNodes.length;i++) {
if (obj.childNodes[i].nodeType==1) {
var childId = obj.childNodes[i].id;
childId = childId.replace(/^td/,'');
if (available_dashlets[childId] || dragable_isBlank(obj.childNodes[i])) {
myArray[mycnt] = obj.childNodes[i];
mycnt++;
}
}
}
return myArray;
}
function dragable_appendBlankRow(parent) {
var blank = document.getElementById("blank");
blank.className="blank";
@ -440,13 +429,13 @@ function dragable_moveContent(from, to,position) {
var fromParent = from.parentNode;
fromParent.removeChild(from);
if (dragable_getElementChildren(fromParent).length == 0) {
if (dragable_getMovableChildren(fromParent).length == 0) {
dragable_appendBlankRow(fromParent);
}
var toParent = to.parentNode;
var toChildren = dragable_getElementChildren(toParent);
var toChildren = dragable_getMovableChildren(toParent);
if (toChildren[0].id.indexOf("blank") != -1) {
toParent.removeChild(document.getElementById(toChildren[0].id));
toParent.appendChild(from);
@ -482,12 +471,12 @@ function dragable_getContentMap() {
//get down to the tr area
children = dragable_getElementChildren(contentArea);
children=dragable_getElementChildren(children[0]);
for (i=0;i<children.length;i++) {
if (contentMap != "" && (contentMap.lastIndexOf(".") != contentMap.length-1)) {
contentMap+=",";
}
if (children[i].id.indexOf("blank") == -1) {
contentMap+=children[i].id.replace(/^td/,"");
}
@ -499,7 +488,7 @@ function dragable_getContentMap() {
return contentMap;
}
function dashboard_toggleEditForm(event,shortcutId,shortcutUrl) {
function dashboard_toggleEditForm(event,shortcutId,editFormUrl) {
//discover if form is there.
var existingForm = document.getElementById("form" + shortcutId + "_div");
if (existingForm) {
@ -513,7 +502,7 @@ function dashboard_toggleEditForm(event,shortcutId,shortcutUrl) {
var parentDiv = document.getElementById("td" + shortcutId + "_div");
var contentDiv = document.getElementById("ct" + shortcutId + "_div");
parentDiv.insertBefore(formDiv,contentDiv);
var callback = {
success : function(req) {
var myHtml = req.responseText.split(/beginDebug/mg,1)[0];
@ -523,21 +512,74 @@ function dashboard_toggleEditForm(event,shortcutId,shortcutUrl) {
eval(myScript);
}
formDiv.innerHTML = myHtml;
var myTips;
myTips = YAHOO.util.Dom.getElementsByClassName('wg-hoverhelp','',formDiv);
for (var i = myTips.length; i--; ) {
var myTip = new YAHOO.widget.Tooltip(myTips[i], {
autodismissdelay: 1000000,
context: myTips[i].parentNode,
text : myTips[i].innerHTML
});
myTips[i].innerHTML = "";
}
},
failure : function(req) {
alert("Toggle Edit Form failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = shortcutUrl + "?func=getUserPrefsForm";
var status = YAHOO.util.Connect.asyncRequest('GET',editFormUrl,callback);
}
//Edit Dashlet Form is for the new per-asset settings for the Dashboard that
//sets required, and movable. It calls a method from the Dashboard and saves
//settings in a dashboard collateral table.
function dashboard_toggleEditDashletForm(event,assetId,dashboardUrl) {
//discover if form is there.
var divId = "form" + assetId + "_editDashlet_div";
var existingForm = document.getElementById(divId);
if (existingForm) {
var throwAway = existingForm.parentNode.removeChild(existingForm);
return;
}
// Create the new form element.
var formDiv = document.createElement("div");
formDiv.id = divId;
formDiv.className = "userPrefsForm";
var parentDiv = document.getElementById("td" + assetId + "_div");
var contentDiv = document.getElementById("ct" + assetId + "_div");
parentDiv.insertBefore(formDiv,contentDiv);
var callback = {
success : function(req) {
formDiv.innerHTML = req.responseText;
var myTips;
myTips = YAHOO.util.Dom.getElementsByClassName('wg-hoverhelp','',formDiv);
for (var i = myTips.length; i--; ) {
var myTip = new YAHOO.widget.Tooltip(myTips[i], {
autodismissdelay: 1000000,
context: myTips[i].parentNode,
text : myTips[i].innerHTML
});
myTips[i].innerHTML = "";
}
},
failure : function(req) {
alert("Dashlet Edit Form failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = dashboardUrl + "?func=editDashlet;dashletAssetId="+assetId;
var status = YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
function dashboard_reloadDashlet(event,shortcutId,shortcutUrl) {
// Reload the content div.
contentDiv = document.getElementById("ct" + shortcutId + "_div");
var callback = {
success : function(req) {
var myHtml = req.responseText.split(/beginDebug/mg,1)[0];
@ -552,7 +594,612 @@ function dashboard_reloadDashlet(event,shortcutId,shortcutUrl) {
alert("Reload Dashlet failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = shortcutUrl + "?func=ajaxInlineView";
var status = YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
function makeActive(o) { o.style.display = "inline"; }
function makeInactive(o) { o.style.display = "none"; }
//Confugration
//sets the drag accruacy
//a value of 0 is most accurate. The number can be raised to improve performance.
var accuracy = 4;
//list of the content item names. Could be searched for, but hard coded for performance
var draggableObjectList=new Array();
var dragableList=new Array();
//Internal Config (Do not Edit)
//browser check
var dom=document.getElementById&&!document.all
var docElement = document.documentElement;
var pageURL = "";
var dragging=false;
var z,x,y
var accuracyCount =0;
var startTD = null;
var endTD = null;
var topelement=dom? "HTML" : "BODY"
var currentDiv = null;
var clipboard = null;
var pageHeight=0;
var pageWidth=0;
var scrollJump=50;
var blankCount=1;
// var getScript = s/<script>(.*)?<\/script>/$1/m;
var reloadIntervals = new Array();
//goes up the parent tree until class is found. If not found, returns null
function dragable_getObjectByClass(target,clazz) {
while (target.tagName!=topelement&&target.className!=clazz){
target=dom? target.parentNode : target.parentElement
}
if (target.className==clazz){
return target;
}else {
return null;
}
}
//checks to see if the scroll bars need to be adjusted
function dragable_adjustScrollBars(e) {
scrY=0;
scrX=0;
if (e.clientY > docElement.clientHeight-scrollJump) {
if (e.clientY + docElement.scrollTop < pageHeight - (scrollJump + 60)) {
scrY=scrollJump;
window.scroll(docElement.scrollLeft,docElement.scrollTop + scrY);
y-=scrY;
}
}else if (e.clientY < scrollJump) {
if (docElement.scrollTop < scrollJump) {
scrY = docElement.scrollTop;
}else {
scrY=scrollJump;
}
window.scroll(docElement.scrollLeft,docElement.scrollTop - scrY);
y+=scrY;
}
if (e.clientX > docElement.clientWidth-scrollJump) {
if (e.clientX + docElement.scrollLeft < pageWidth - (scrollJump + 60)) {
scrX=scrollJump;
window.scroll(docElement.scrollLeft + scrX,docElement.scrollTop);
x-=scrX;
}
}else if (e.clientX < scrollJump) {
if (docElement.scrollLeft < scrollJump) {
scrX = docElement.scrollLeft;
}else {
scrX=scrollJump;
}
window.scroll(docElement.scrollLeft - scrX,docElement.scrollTop);
x+=scrX;
}
}
//initialization routine, must be called on load. Sets up event handlers
function dragable_init(url) {
docElement = document.documentElement;
if (document.compatMode == "BackCompat") {
docElement = document.body;
}
pageURL = url;
//set up event handlers
document.onmouseup=dragable_dragStop;
document.onmousemove=dragable_move;
//fill the draggableObject list
obj = document.getElementById("position1");
contentCount=2;
while (obj != null) {
tbody = dragable_getElementChildren(obj);
children = dragable_getElementChildren(tbody[0]);
var hasMovableChildren = false;
for (i = 0; i< children.length;i++) {
var childId = children[i].id;
childId = childId.replace(/^td/,'');
if (available_dashlets[childId]) {
draggableObjectList[draggableObjectList.length] = children[i];
dragableList[dragableList.length]=document.getElementById(children[i].id + "_div");
hasMovableChildren = true;
}
}
//Add a blank row if the position is empty, or if there are no movable children.
if (! hasMovableChildren) {
dragable_appendBlankRow(tbody[0]);
}
obj = document.getElementById("position" + contentCount);
contentCount++;
}
for (i=0;i<draggableObjectList.length;i++) {
eval("document.getElementById('" + draggableObjectList[i].id + "').onmousedown=dragable_dragStart");
}
}
//called on mouse move.
function dragable_move(e){
e=dom? e : event;
if (dragging){
if (accuracyCount==accuracy) {
tmp = dragable_spy(dom? e.pageX: (e.clientX + docElement.scrollLeft),dom? e.pageY: (e.clientY + docElement.scrollTop));
if (tmp.length != 0) {
dragable_dragOver(tmp[0],tmp[1]);
}else {
//only occurs if not found
if (endTD != null) {
if (!dragable_isBlank(endTD)) {
document.getElementById(endTD.id + "_div").className="dragable";
}else {
endTD.className="blank";
}
endTDPos=null;
endTD=null;
}
}
accuracyCount=0;
}else {
accuracyCount++;
}
dragable_adjustScrollBars(e);
// alert('x is: '+ (temp1+e.clientX-x));
z.style.left=(temp1+e.clientX-x)+"px";
z.style.top=(temp2+e.clientY-y)+"px";
return false
// }else {
// tmp = dragable_spy(dom? e.pageX: (e.clientX + docElement.scrollLeft),dom? e.pageY: (e.clientY + docElement.scrollTop));
// if (tmp.length == 0) {
// currentDiv = null;
// }else {
// currentDiv = tmp[0];
// }
}
}
function dragable_dragStart(e){
e=dom? e : event;
var fObj=dom? e.target : e.srcElement
if (fObj.nodeName=='IMG') { return;}
fObj2 = dragable_getObjectByClass(fObj,"dragTrigger");
if (!fObj2) {
return;
}
fObj = dragable_getObjectByClass(fObj,"dragable");
if (fObj == null) return;
//set the start td
startTD=document.getElementById(fObj.id.substr(0,fObj.id.indexOf("_div")));
fObj.className="dragging";
//set the page height and width in a var since IE changes them when scrolling
pageHeight = docElement.scrollHeight;
pageWidth = docElement.scrollWidth;
dragging=true
z=fObj;
temp1=z.style.left;
temp1=temp1.replace(/px/g,'')+0;
temp1=parseInt(temp1);
temp2=z.style.top;
temp2=temp2.replace(/px/g,'')+0;
temp2=parseInt(temp2);
// alert(temp1,temp2);
x=e.clientX;
y=e.clientY;
return false
}
function dragable_isBlank(td) {
if (td.id.indexOf("blank") != -1) {
return true;
}
return false;
}
//returns an array. array[0] holds the tr object, and array[1] holds the position (top or bottom)
function dragable_spy(x, y) {
var returnArray = new Array();
for (i=0;i<draggableObjectList.length;i++) {
td = draggableObjectList[i];
//this is a hack
if (td == null || td == startTD || !td.parentNode || !td.parentNode.parentNode) { continue; }
var fObj=td;
y1=0;
x1=0;
var gap = (td.className=='blank' || (td.parentNode.parentNode.rows.length == td.rowIndex + 1)) ? 500 : 0
while (fObj!=null && fObj.tagName!=topelement){
y1+=fObj.offsetTop;
x1+=fObj.offsetLeft;
fObj=fObj.offsetParent;
}
if (x >x1 && x < (x1 + td.offsetWidth)) {
if (y> y1 && y< (y1 + (td.offsetHeight/2))) {
returnArray[0] = td;
returnArray[1] = "top";
return returnArray;
}else if (y> y1 && y< (y1 + td.offsetHeight + gap)) {
returnArray[0] = td;
returnArray[1] = "bottom";
return returnArray;
}
}
}
return returnArray;
}
//Called when a content item is dragged over
function dragable_dragOver(obj,position) {
if (endTD == obj && endTDPos == position ) {
return;
}
if(endTD != null && endTD != obj) {
if (dragable_isBlank(endTD)) {
document.getElementById(endTD.id).className="blank";
}else {
document.getElementById(endTD.id + "_div").className="dragable";
}
}
if (dragable_isBlank(obj)) {
divName = td.id;
}else {
divName = td.id + "_div";
}
if (dragable_isBlank(obj)) {
document.getElementById(divName).className="blankOver";
endTDPos=null;
}else if (position == "top") {
endTDPos=position;
document.getElementById(divName).className="draggedOverTop";
}else {
endTDPos=position;
document.getElementById(divName).className="draggedOverBottom";
}
endTD=obj;
}
//called on mouse up, If an element is being dragged, this method does the right thing.
function dragable_dragStop(e) {
dragging=false;
if (z) {
if (endTD !=null && startTD!=null) {
fObj2 = dragable_getObjectByClass(startTD,"availableDashlet");
dragable_moveContent(startTD,endTD,endTDPos);
if (fObj2) {
var replId = startTD.id;
replId = replId.replace(/^td/,'');
//alert(replId);
var replUrl = available_dashlets[replId];
//alert(replUrl);
contentDiv = document.getElementById("ct" + replId + "_div");
var callback = {
success : function(req) {
var myArr528 = req.responseText.split(/beginDebug/mg,1);
contentDiv.innerHTML = myArr528[0];
},
failure : function(req) {
alert("Move failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = replUrl + "?func=ajaxInlineView";
var status = YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
startTD=null;
if (dragable_isBlank(endTD)) {
divName = endTD.id;
}
else {
divName=endTD.id + "_div";
document.getElementById(divName).className="dragable";
}
dragable_postNewContentMap();
}
for(i=0;i<dragableList.length;i++) {
dragableList[i].style.top='0px';
dragableList[i].style.left='0px';
dragableList[i].className="dragable";
}
//this is a ie hack for a render bug
for(i=0;i<draggableObjectList.length;i++) {
if (draggableObjectList[i]) {
draggableObjectList[i].style.top='1px';
draggableObjectList[i].style.left='1px';
draggableObjectList[i].style.top='0px';
draggableObjectList[i].style.left='0px';
}
}
}
startTD=null;
if (endTD != null) {
endTD.position = null;
endTD=null;
}
}
function dragable_postNewContentMap() {
var callback = {
success : function(req) { },
failure : function(req) {
alert("Post New Content Map Failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = pageURL;
var dataParts = "func=setContentPositions&map=" + dragable_getContentMap();
var status = YAHOO.util.Connect.asyncRequest('POST',url,callback,dataParts);
}
//gets the element children of a dom object
function dragable_getElementChildren(obj) {
var myArray= new Array();
mycnt = 0;
for (i=0;i<obj.childNodes.length;i++) {
if (obj.childNodes[i].nodeType==1) {
myArray[mycnt] = obj.childNodes[i];
mycnt++;
}
}
return myArray;
}
//gets the element children of a dom object that can be moved, including the blank row
function dragable_getMovableChildren(obj) {
var myArray= new Array();
mycnt = 0;
for (i=0;i<obj.childNodes.length;i++) {
if (obj.childNodes[i].nodeType==1) {
var childId = obj.childNodes[i].id;
childId = childId.replace(/^td/,'');
if (available_dashlets[childId] || dragable_isBlank(obj.childNodes[i])) {
myArray[mycnt] = obj.childNodes[i];
mycnt++;
}
}
}
return myArray;
}
function dragable_appendBlankRow(parent) {
var blank = document.getElementById("blank");
blank.className="blank";
blankClone = blank.cloneNode(true);
blankClone.id = "blank" + new Date().getTime() + blankCount++;
draggableObjectList[draggableObjectList.length] = blankClone;
parent.appendChild(blankClone);
blankClone.style.top='0px';
blankClone.style.left='0px';
blank.className="hidden";
}
// deletes a dashlet (moves it from its current location to the bottom of position 1)
function dragable_deleteContent(e,from,postNewContentMap) {
from = dragable_getObjectByClass(from,"dragable");
from = document.getElementById(from.id.substr(0,from.id.indexOf("_div")));
dragable_moveContent(from,document.getElementById('position1').rows[document.getElementById('position1').rows.length - 1],"bottom");
if (postNewContentMap) {dragable_postNewContentMap();} // This will help avoid meaningless web server hits.
}
//moves a table row from one table to another. from and to are table row objects
//if the last row is removed from a table, id blank is placed in the table
function dragable_moveContent(from, to,position) {
if (from!=to && from && to) {
var fromParent = from.parentNode;
fromParent.removeChild(from);
if (dragable_getMovableChildren(fromParent).length == 0) {
dragable_appendBlankRow(fromParent);
}
var toParent = to.parentNode;
var toChildren = dragable_getMovableChildren(toParent);
if (toChildren[0].id.indexOf("blank") != -1) {
toParent.removeChild(document.getElementById(toChildren[0].id));
toParent.appendChild(from);
}else if (position == "top"){
toParent.insertBefore( from, to );
}else {
children = dragable_getElementChildren(toParent);
i=0;
while(children[i] != to && i < children.length) {
i++;
}
if (i == children.length - 1) {
toParent.appendChild(from);
}else {
toParent.insertBefore(from,children[i+1]);
}
}
}
}
function dragable_getContentMap() {
//ex 1001,2004;896,494,10010
contentMap = "";
contentCount=1;
var contentArea = document.getElementById("position1");
while (contentArea) {
if ((contentMap != "") || (contentArea.id == 'position2')) {
contentMap+=".";
}
//get down to the tr area
children = dragable_getElementChildren(contentArea);
children=dragable_getElementChildren(children[0]);
for (i=0;i<children.length;i++) {
if (contentMap != "" && (contentMap.lastIndexOf(".") != contentMap.length-1)) {
contentMap+=",";
}
if (children[i].id.indexOf("blank") == -1) {
contentMap+=children[i].id.replace(/^td/,"");
}
}
contentCount++;
contentArea = document.getElementById("position" + contentCount);
}
return contentMap;
}
function dashboard_toggleEditForm(event,shortcutId,editFormUrl) {
//discover if form is there.
var existingForm = document.getElementById("form" + shortcutId + "_div");
if (existingForm) {
var throwAway = existingForm.parentNode.removeChild(existingForm);
return;
}
// Create the new form element.
var formDiv = document.createElement("div");
formDiv.id = "form" + shortcutId + "_div";
formDiv.className = "userPrefsForm";
var parentDiv = document.getElementById("td" + shortcutId + "_div");
var contentDiv = document.getElementById("ct" + shortcutId + "_div");
parentDiv.insertBefore(formDiv,contentDiv);
var callback = {
success : function(req) {
var myHtml = req.responseText.split(/beginDebug/mg,1)[0];
var myScript = myHtml.split(/\<script\>/mg)[1];
if (myScript) {
myScript = myScript.split(/\<\/script\>/mg)[0];
eval(myScript);
}
formDiv.innerHTML = myHtml;
var myTips;
myTips = YAHOO.util.Dom.getElementsByClassName('wg-hoverhelp','',formDiv);
for (var i = myTips.length; i--; ) {
var myTip = new YAHOO.widget.Tooltip(myTips[i], {
autodismissdelay: 1000000,
context: myTips[i].parentNode,
text : myTips[i].innerHTML
});
myTips[i].innerHTML = "";
}
},
failure : function(req) {
alert("Toggle Edit Form failed. Problem with connection. Please refresh the page and try again.");
}
}
var status = YAHOO.util.Connect.asyncRequest('GET',editFormUrl,callback);
}
//Edit Dashlet Form is for the new per-asset settings for the Dashboard that
//sets required, and movable. It calls a method from the Dashboard and saves
//settings in a dashboard collateral table.
function dashboard_toggleEditDashletForm(event,assetId,dashboardUrl) {
//discover if form is there.
var divId = "form" + assetId + "_editDashlet_div";
var existingForm = document.getElementById(divId);
if (existingForm) {
var throwAway = existingForm.parentNode.removeChild(existingForm);
return;
}
// Create the new form element.
var formDiv = document.createElement("div");
formDiv.id = divId;
formDiv.className = "userPrefsForm";
var parentDiv = document.getElementById("td" + assetId + "_div");
var contentDiv = document.getElementById("ct" + assetId + "_div");
parentDiv.insertBefore(formDiv,contentDiv);
var callback = {
success : function(req) {
formDiv.innerHTML = req.responseText;
var myTips;
myTips = YAHOO.util.Dom.getElementsByClassName('wg-hoverhelp','',formDiv);
for (var i = myTips.length; i--; ) {
var myTip = new YAHOO.widget.Tooltip(myTips[i], {
autodismissdelay: 1000000,
context: myTips[i].parentNode,
text : myTips[i].innerHTML
});
myTips[i].innerHTML = "";
}
},
failure : function(req) {
alert("Dashlet Edit Form failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = dashboardUrl + "?func=editDashlet;dashletAssetId="+assetId;
var status = YAHOO.util.Connect.asyncRequest('GET',url,callback);
}
function dashboard_reloadDashlet(event,shortcutId,shortcutUrl) {
// Reload the content div.
contentDiv = document.getElementById("ct" + shortcutId + "_div");
var callback = {
success : function(req) {
var myHtml = req.responseText.split(/beginDebug/mg,1)[0];
var myScript = myHtml.split(/\<script\>/mg)[1];
if (myScript) {
myScript = myScript.split(/\<\/script\>/mg)[0];
eval(myScript);
}
contentDiv.innerHTML = myHtml;
},
failure : function(req) {
alert("Reload Dashlet failed. Problem with connection. Please refresh the page and try again.");
}
}
var url = shortcutUrl + "?func=ajaxInlineView";
var status = YAHOO.util.Connect.asyncRequest('GET',url,callback);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

View file

@ -0,0 +1,170 @@
.yui-panel .bd {
overflow: visible !important;
padding-bottom: 15px;
}
.yui-panel {
overflow: visible !important;
}
.yui-skin-sam .yui-ac-container {
min-height: 50px;
height: auto !important;
width: 154px;
display: none;
z-index: 9999;
clear: both;
}
.yui-skin-sam .yui-ac {
width: 170px !important;
}
#groupManagerTable, #dialog1{
width: 300px !important;
}
#groupManagerForm, #groupManagerTable {
width: 270px !important;
}
#group_lookup, #user_lookup {
width: 150px;
margin-top: -9px;
height: 13px;
}
#groupManagerTable div {
display: block;
}
#groupsAdded_row, #usersAdded_row{
display: none !important;
clear: both;
}
#groupsAdded_row ul, #usersAdded_row ul{
margin: 0px !important
padding: 0px !important;
padding-left: 0px !important;
list-style: none;
}
#groupsAdded_row ul li, #usersAdded_row ul li {
margin-bottom: 5px;
clear: both;
}
.removeLink {
margin-right: 10px;
display: block;
float: left;
height: 19px !important;
width: 15px !important;
}
#groupResultsContainer, #userResultsContainer {
display: none;
left: 30px;
}
.ft {
padding-top: 10px !important;
font-size: 11px !important;
text-align: left !important;
color: #000 !important;
}
.yui-skin-sam .yui-button {
border: 0px !important;
border-style: hidden !important;
}
.yui-skin-sam .yui-button .first-child {
border: 0px !important;
border-style: none !important;
}
.yui-skin-sam .yui-dialog .ft span.default button {
color: #000 !important;
}
.yui-skin-sam .yui-dialog .ft .button-group {
text-align: left !important;
}
.yui-skin-sam .yui-dialog .ft span.default {
background-position: 0 0 !important;
}
.button-group button{
border-color: #ccc #666 #333 #fff !important;
}
.yui-dialog .ft, .yui-simple-dialog .ft {
padding-left: 5px !important;
padding-bottom: 10px !important;
text-align: left !important;
}
#groupManagerTable label {
font-weight: bold;
}
#groupManagerTable .firstcol {
padding-top: 7px;
padding-right: 7px;
}
.groupLabel {
height: 35px;
margin-top: 15px;
clear: both;
}
#groupEntry, #userEntry {
}
.addBtn {
padding-right: 10px;
float: left;
width: 20px;
position: relative;
top: -8px;
}
.entryInput {
float: left;
}
#createNewGroupRow img {
margin-right: 7px;
margin-left: 7px;
position: relative;
top: 6px;
}
#createNewGroupRow a, #createNewGroupRow a:link, #createNewGroupRow a:hover, #createNewGroupRow a:active {
font-size: 11px !important;
position: relative;
top: -7px;
text-decoration: none !important;
}
#groupNameRow {
float: left;
padding-right: 10px;
margin-bottom: 10px;
}
#createNewGroupRow {
float: left;
margin-bottom: 10px;
}
#groupManagerContainer {
padding-left: 10px;
padding-top: 10px;
padding-right: 10px;
}

View file

@ -0,0 +1,525 @@
if ( typeof WebGUI.Form == "undefined" ) {
WebGUI.Form = {};
}
if ( typeof WebGUI.Form.GroupManager == "undefined" ) {
WebGUI.Form.GroupManager = {};
WebGUI.Form.GroupManager.users_added = new Array();
WebGUI.Form.GroupManager.users_deleted = new Array();
WebGUI.Form.GroupManager.groups_added = new Array();
WebGUI.Form.GroupManager.groups_deleted = new Array();
WebGUI.Form.GroupManager.last_groupId = '';
WebGUI.Form.GroupManager.last_userId = '';
}
WebGUI.Form.GroupManager.handleCancel = function () {
this.cancel();
}
YAHOO.util.Event.onDOMReady(function () {
WebGUI.Form.GroupManager.i18n = new WebGUI.i18n( {
namespaces : {
'WebGUI' : [
'submit', 'Cancel', '84', '89', '149'
],
'Form_Group' : [
'Group Manager', 'Add Group...', 'Add User...', 'New Group'
]
},
onpreload : {
fn : WebGUI.Form.GroupManager.initDialog
}
});
});
var groupId = "";
WebGUI.Form.GroupManager.initDialog = function () {
var tabWrapper = document.getElementById('application_workarea');
document.body.className= "yui-skin-sam";
var headID = document.getElementsByTagName("head")[0];
var dialogBox = document.createElement('div');
dialogBox.id= "dialog1";
dialogBox.className= "yui-pe-content";
dialogBox.innerHTML = '<div class=\'hd\'>' + WebGUI.Form.GroupManager.i18n.get('Form_Group','Group Manager') + '</div>'
+ '<div class=\'bd\'>'
+ '<div id=\'groupManagerContainer\'>'
+ '<form method="POST" action=\'?op=formHelper;class=Group;method=saveGroup;\' id=\'groupManagerForm\'>'
+ '<input type=\'hidden\' name=\'groupId\' id=\'groupManager_groupId\' />'
+' <div id=\'groupManagerTable\'>'
+ '<div id=\'groupNameRow\'><input type=\'textbox\' name=\'groupName\' id=\'groupName\' /></div><div id=\'createNewGroupRow\'><a href=\'#\' onClick=\'WebGUI.Form.GroupManager.createNewGroup()\'><img src=\'/extras/yui-webgui/build/form/assets/new_group.png\' border=\'0\' style=\'width: 24px; height 24px; \' />' + WebGUI.Form.GroupManager.i18n.get('Form_Group','New Group') + '</a></div>'
+ '<div class=\'groupLabel\'><label for=\'group_lookup\'>'+WebGUI.Form.GroupManager.i18n.get('WebGUI','89')+'</label></div>'
+ '<div id=\'groupEntry\'><div class=\'addBtn\'><a href="#" id="addGroupBtn" onClick="WebGUI.Form.GroupManager.addGroups()"><img src=\'/extras/yui-webgui/build/form/assets/add.png\' border=\'0\' style=\'width: 16px; height 16px; \' /></a></div><div class=\'entryInput\'><input type=\'textbox\' id=\'group_lookup\' onclick=\'WebGUI.Form.GroupManager.showAutocomplete("group_lookup")\' value=\''+WebGUI.Form.GroupManager.i18n.get('Form_Group','Add Group...')+'\' class=\'yui-ac-input\' autocomplete=\'off\' /></div><div id=\'groupResultsContainer\' class=\'yui-ac-container\'></div></div>'
+ '<div id=\'groupsAdded_row\'><ul id=\'list_of_groups\'></ul></div>'
+ '<div class=\'groupLabel\'><label for=\'user_lookup\'>'+WebGUI.Form.GroupManager.i18n.get('WebGUI','149')+'</label></div>'
+ '<div id=\'userEntry\'><div class=\'addBtn\'><a href="#" id="addGroupBtn" onClick="WebGUI.Form.GroupManager.addUsers()"><img src=\'/extras/yui-webgui/build/form/assets/add.png\' border=\'0\' style=\'width: 16px; height 16px; \' /></a></div><div class=\'entryInput\'><input type=\'textbox\' id=\'user_lookup\' onclick=\'WebGUI.Form.GroupManager.showAutocomplete("user_lookup")\' value=\''+WebGUI.Form.GroupManager.i18n.get('Form_Group','Add Group...')+'\' class=\'yui-ac-input\' autocomplete=\'off\' /></div><div id=\'userResultsContainer\' class=\'yui-ac-container\'></div></div>'
+ '<div id=\'usersAdded_row\'><ul id=\'list_of_users\'></ul></div>'
+ '</div>'
+ '<div id=\'gm_form_target\'></div>'
+ '</form></div></div>';
tabWrapper.appendChild(dialogBox);
// Define various event handlers for Dialog
var handleSubmit = function() {
this.cancel();
var url = "?op=formHelper;class=Group;sub=saveGroup;";
var getEverything = "?op=formHelper;class=Group;sub=groupMembers;groupId=" + groupId;
var form_target = document.getElementById("gm_form_target");
for(var i=0; i < WebGUI.Form.GroupManager.users_added.length; i++) {
var formlet = document.createElement('input');
formlet.setAttribute('name', 'usersAdded');
formlet.setAttribute('type', 'hidden');
formlet.setAttribute('value', WebGUI.Form.GroupManager.users_added[i]);
form_target.appendChild(formlet);
}
for(var i=0; i < WebGUI.Form.GroupManager.users_deleted.length; i++) {
var formlet = document.createElement('input');
formlet.setAttribute('name', 'usersDeleted');
formlet.setAttribute('type', 'hidden');
formlet.setAttribute('value', WebGUI.Form.GroupManager.users_deleted[i]);
form_target.appendChild(formlet);
}
for(var i=0; i < WebGUI.Form.GroupManager.groups_added.length; i++) {
var formlet = document.createElement('input');
formlet.setAttribute('name', 'groupsAdded');
formlet.setAttribute('type', 'hidden');
formlet.setAttribute('value', WebGUI.Form.GroupManager.groups_added[i]);
form_target.appendChild(formlet);
}
for(var i=0; i < WebGUI.Form.GroupManager.groups_deleted.length; i++) {
var formlet = document.createElement('input');
formlet.setAttribute('name', 'groupsDeleted');
formlet.setAttribute('type', 'hidden');
formlet.setAttribute('value', WebGUI.Form.GroupManager.groups_deleted[i]);
form_target.appendChild(formlet);
}
YAHOO.util.Connect.setForm('groupManagerForm', false);
YAHOO.util.Connect.asyncRequest('POST', url,{
success: function (o) {
var groupObj = YAHOO.lang.JSON.parse(o.responseText);
var dropdown = document.getElementById(WebGUI.Form.GroupManager.original_form);
if (groupObj.originalGroupId === 'new') {
//Insert this option into the list in the right place, and make it the selected option.
var groupOption = new Option(groupObj.groupName, groupObj.groupId, false, true);
var groupInserted = false;
for(var i=0, dlen = dropdown.options.length; i < dlen; i++) {
var gOption = dropdown.options[i];
gOption.defaultSelected = false;
if(gOption.text > groupObj.groupName && !groupInserted) {
groupInserted = true;
dropdown.add(groupOption, gOption);
}
}
}
else {
dropdown.options[dropdown.selectedIndex].innerHTML = groupObj.groupName;
}
}
});
};
var handleCancel = function() {
this.cancel();
};
var handleSuccess = function(o) {
};
var handleFailure = function(o) {
alert("Submission failed: " + o.status);
};
// Remove progressively enhanced content class, just before creating the module
YAHOO.util.Dom.removeClass("dialog1", "yui-pe-content");
// Instantiate the Dialog
WebGUI.Form.GroupManager.dialog = new YAHOO.widget.Dialog("dialog1",
{ width : "40em",
fixedcenter : true,
visible : false,
//constraintoviewport : true,
buttons : [ { text:WebGUI.Form.GroupManager.i18n.get('WebGUI', 'submit'), handler:handleSubmit, isDefault:true },
{ text:WebGUI.Form.GroupManager.i18n.get('WebGUI', 'Cancel'), handler:handleCancel } ]
});
// Wire up the success and failure handlers
WebGUI.Form.GroupManager.dialog.callback = { success: handleSuccess,
failure: handleFailure };
// Render the Dialog
WebGUI.Form.GroupManager.dialog.render();
};
WebGUI.Form.GroupManager.show_dialog = function(formName, isNew) {
var e = document.getElementById(formName + "_formId");
groupId = e.options[e.selectedIndex].value;
WebGUI.Form.GroupManager.original_form = formName + "_formId";
//Clear out all stored data.
WebGUI.Form.GroupManager.users_added = new Array();
WebGUI.Form.GroupManager.users_deleted = new Array();
WebGUI.Form.GroupManager.groups_added = new Array();
WebGUI.Form.GroupManager.groups_deleted = new Array();
WebGUI.Form.GroupManager.last_userId = '';
WebGUI.Form.GroupManager.last_groupId = '';
var form_target = document.getElementById("gm_form_target");
form_target.innerHTML = '';
var groupsAdded = document.getElementById("list_of_groups");
var usersAdded = document.getElementById("list_of_users");
var groupTextbox = document.getElementById("group_lookup");
var userTextbox = document.getElementById("user_lookup");
groupsAdded.innerHTML = "";
usersAdded.innerHTML = "";
userTextbox.value = WebGUI.Form.GroupManager.i18n.get('Form_Group','Add User...');
groupTextbox.value = WebGUI.Form.GroupManager.i18n.get('Form_Group','Add Group...');
//TODO: groupFilter and userFilter never change. They don't depend on which group is being added or
//edited. Move them into init to prevent memory leaks.
//GROUPS AUTOCOMPLETE
var groupFilter = { };
groupFilter.dataSource = new YAHOO.util.XHRDataSource( '?op=formHelper;class=Group;sub=searchGroups;');
groupFilter.dataSource.responseType = YAHOO.util.XHRDataSource.TYPE_JSON;
groupFilter.dataSource.responseSchema = {
resultsList : "results",
fields : [ 'groupName', 'groupId' ]
};
// Function to create an autocomplete field
var createGroupAutocomplete = function ( groupFilter ) {
groupFilter.autocomplete = new YAHOO.widget.AutoComplete("group_lookup", "groupResultsContainer", groupFilter.dataSource );
groupFilter.autocomplete.queryQuestionMark = false;
groupFilter.autocomplete.animVert = true;
groupFilter.autocomplete.animSpeed = 0.1;
groupFilter.autocomplete.minQueryLength = 1;
groupFilter.autocomplete.queryDelay = 0.2;
groupFilter.autocomplete.typeAhead = true;
groupFilter.autocomplete.resultTypeList = false;
groupFilter.autocomplete.applyLocalFilter = true;
var getGroupId = function (sType, args) {
var oData = args[2];
WebGUI.Form.GroupManager.last_groupId = oData.groupId;
}
groupFilter.autocomplete.itemSelectEvent.subscribe(getGroupId);
//This will override any of the functions that work with the default filterResults method
groupFilter.autocomplete.filterResults = function ( sQuery , oFullResponse , oParsedResponse , oCallback ) {
var allResults = oParsedResponse.results;
var uniqueResults = [];
for(var i=0, len=allResults.length; i<len; i++) {
var oResult = allResults[i];
var foundGroup = false;
for(var j=0, len2=WebGUI.Form.GroupManager.groups_added.length; j<len2; j++) {
if(oResult.groupId === WebGUI.Form.GroupManager.groups_added[j]) {
foundGroup = true;
}
}
if (! foundGroup) {
uniqueResults.push(oResult);
}
}
oParsedResponse.results = uniqueResults;
return oParsedResponse;
};
};
createGroupAutocomplete( groupFilter );
groupFilter.autocomplete.formatResult = function ( result, query, match ) {
return '<div class="autocomplete_value">' + result.groupName + "</div>";
};
//TODO: groupFilter and userFilter never change. They don't depend on which group is being added or
//edited. Move them into init to prevent memory leaks.
//USERS AUTOCOMPLETE
var userFilter = { };
userFilter.dataSource = new YAHOO.util.XHRDataSource( '?op=formHelper;class=User;sub=searchUsers;');
userFilter.dataSource.responseType = YAHOO.util.XHRDataSource.TYPE_JSON;
userFilter.dataSource.responseSchema = {
resultsList : "results",
fields : [ 'username', 'userId' ]
};
// Function to create an autocomplete field
var createUserAutocomplete = function ( userFilter ) {
userFilter.autocomplete = new YAHOO.widget.AutoComplete("user_lookup", "userResultsContainer", userFilter.dataSource );
userFilter.autocomplete.queryQuestionMark = false;
userFilter.autocomplete.animVert = true;
userFilter.autocomplete.animSpeed = 0.1;
userFilter.autocomplete.minQueryLength = 1;
userFilter.autocomplete.queryDelay = 0.2;
userFilter.autocomplete.typeAhead = true;
userFilter.autocomplete.resultTypeList = false;
userFilter.autocomplete.applyLocalFilter = true;
var getUserId = function (sType, args) {
var oData = args[2];
WebGUI.Form.GroupManager.last_userId = oData.userId;
}
userFilter.autocomplete.itemSelectEvent.subscribe(getUserId);
//This will override any of the functions that work with the default filterResults method
userFilter.autocomplete.filterResults = function ( sQuery , oFullResponse , oParsedResponse , oCallback ) {
var allResults = oParsedResponse.results;
var uniqueResults = [];
for(var i=0, len=allResults.length; i<len; i++) {
var oResult = allResults[i];
var foundUser = false;
for(var j=0, len2=WebGUI.Form.GroupManager.users_added.length; j<len2; j++) {
if(oResult.userId === WebGUI.Form.GroupManager.users_added[j]) {
foundUser = true;
}
}
if (! foundUser) {
uniqueResults.push(oResult);
}
}
oParsedResponse.results = uniqueResults;
return oParsedResponse;
};
};
createUserAutocomplete( userFilter );
userFilter.autocomplete.formatResult = function ( result, query, match ) {
return '<div class="autocomplete_value">' + result.username + '</div>';
var user_lookup = document.getElementById ("user_lookup");
user_lookup.setAttribute("name", result.userId);
};
if (isNew != "new") {
var requestUrl = this.url + "?op=formHelper;class=Group;sub=groupMembers;groupId=" + groupId;
var callback = {
failure : function ( o ) {
// TODO: YUI logger for this
},
success : function ( o ) {
var responseObj = YAHOO.lang.JSON.parse( o.responseText );
//Insert groupname into the group field
WebGUI.Form.GroupManager.dialog.form.groupName.value = responseObj[ 'groupName' ];
var responseObj = YAHOO.lang.JSON.parse( o.responseText );
var groups = responseObj.groups;
var users = responseObj.users;
for (var i = 0; i < groups.length; i++){
var groupId = responseObj.groups[i].groupId;
var groupsAdded = document.getElementById("list_of_groups");
var groupsAddedRow = document.getElementById("groupsAdded_row");
groupsAddedRow.style.cssText= "min-height: 27px !important; height: auto !important; display: block !important;";
var newGroup = document.createElement('li');
newGroup.setAttribute('id', 'gm_groupId_'+groupId)
newGroup.innerHTML = '<a href=\'#\' onClick=\'WebGUI.Form.GroupManager.removeGroups("'+groupId+'")\' class=\'removeLink\'><img src=\'/extras/yui-webgui/build/form/assets/remove.png\' border=\'0\' style=\'width: 16px; height 16px; \' /></a>' + responseObj.groups[i].groupName;
groupsAdded.appendChild(newGroup);
}
for (var i = 0; i < users.length; i++){
var userId = responseObj.users[i].userId;
var usersAdded = document.getElementById("list_of_users");
var usersAddedRow = document.getElementById("usersAdded_row");
usersAddedRow.style.cssText= "min-height: 27px !important; height: auto !important; display: block !important;";
var newUser = document.createElement('li');
newUser.setAttribute('id', 'gm_userId_'+userId)
newUser.innerHTML = '<a href=\'#\' onClick=\'WebGUI.Form.GroupManager.removeUsers("'+userId+'")\' class=\'removeLink\'><img src=\'/extras/yui-webgui/build/form/assets/remove.png\' border=\'0\' style=\'width: 16px; height 16px; \' /></a>' + responseObj.users[i].username;
usersAdded.appendChild(newUser);
}
}
};
var groupIdHidden = document.getElementById("groupManager_groupId");
groupIdHidden.setAttribute("value", groupId);
YAHOO.util.Connect.asyncRequest( "POST", requestUrl, callback );
}
else {
WebGUI.Form.GroupManager.dialog.form.groupName.value = '';
var groupIdHidden = document.getElementById("groupManager_groupId");
groupIdHidden.setAttribute("value", "new");
}
WebGUI.Form.GroupManager.dialog.show();
};
//ADD GROUPS
WebGUI.Form.GroupManager.addGroups = function() {
var groupTextbox = document.getElementById("group_lookup");
var groupsAdded = document.getElementById("list_of_groups");
var groupsAddedRow = document.getElementById("groupsAdded_row");
if (groupTextbox.value !== "" && groupTextbox.value !== WebGUI.Form.GroupManager.i18n.get('Form_Group','Add Group...') && WebGUI.Form.GroupManager.last_groupId !== '') {
var last_groupId = WebGUI.Form.GroupManager.last_groupId;
WebGUI.Form.GroupManager.last_groupId = '';
groupsAddedRow.style.cssText= "min-height: 27px !important; height: auto !important; display: block !important;";
var newGroup = document.createElement('li');
newGroup.setAttribute('id', 'gm_groupId_'+last_groupId)
newGroup.innerHTML = '<a href=\'#\' onClick=\'WebGUI.Form.GroupManager.removeGroups("'+last_groupId+'")\' class=\'removeLink\'><img src=\'/extras/yui-webgui/build/form/assets/remove.png\' border=\'0\' style=\'width: 16px; height 16px; \' /></a>' +groupTextbox.value;
groupsAdded.appendChild(newGroup);
groupTextbox.value = WebGUI.Form.GroupManager.i18n.get('Form_Group','Add Group...');
var groupDeleted = false;
for(var i=0; i < WebGUI.Form.GroupManager.groups_deleted.length; i++) {
if(WebGUI.Form.GroupManager.groups_deleted[i] == last_groupId) {
WebGUI.Form.GroupManager.groups_deleted.splice(i,1);
groupDeleted = true;
}
}
if (! groupDeleted) {
WebGUI.Form.GroupManager.groups_added.push(last_groupId);
}
}
}
//REMOVE GROUPS
WebGUI.Form.GroupManager.removeGroups = function(groupId) {
var groupsAdded = document.getElementById("list_of_groups");
var group = document.getElementById('gm_groupId_'+groupId);
groupsAdded.removeChild(group);
var groupAdded = false;
for(var i = WebGUI.Form.GroupManager.groups_added.length-1; i >= 0; i--){
if(WebGUI.Form.GroupManager.groups_added[i] == groupId) {
WebGUI.Form.GroupManager.groups_added.splice(i,1);
groupAdded = true;
}
}
if (! groupAdded) {
WebGUI.Form.GroupManager.groups_deleted.push(groupId);
}
if (groupsAdded.innerHTML == "") {
groupsAdded.setAttribute("style", "display: none !important;");
}
}
//ADD USERS
WebGUI.Form.GroupManager.addUsers = function() {
var userTextbox = document.getElementById("user_lookup");
var usersAdded = document.getElementById("list_of_users");
var userssAddedRow = document.getElementById("usersAdded_row");
if (userTextbox.value !== "" && userTextbox.value !== WebGUI.Form.GroupManager.i18n.get('Form_Group','Add User...') && WebGUI.Form.GroupManager.last_userId !== '') {
var last_userId = WebGUI.Form.GroupManager.last_userId;
WebGUI.Form.GroupManager.last_userId = '';
userssAddedRow.style.cssText= "min-height: 27px !important; height: auto !important; display: block !important;"
var newUser = document.createElement('li');
newUser.setAttribute('id', 'gm_userId_'+last_userId)
newUser.innerHTML = '<a href=\'#\' onClick=\'WebGUI.Form.GroupManager.removeUsers("'+last_userId+'")\' class=\'removeLink\'><img src=\'/extras/yui-webgui/build/form/assets/remove.png\' border=\'0\' style=\'width: 16px; height 16px; \' /></a>' +userTextbox.value;
usersAdded.appendChild(newUser);
userTextbox.value = WebGUI.Form.GroupManager.i18n.get('Form_Group','Add User...');
var userDeleted = false;
for(var i = WebGUI.Form.GroupManager.users_deleted.length-1; i >= 0; i--){
if(WebGUI.Form.GroupManager.users_deleted[i] == last_userId) {
WebGUI.Form.GroupManager.users_deleted.splice(i,1);
userDeleted = true;
}
}
if (! userDeleted) {
WebGUI.Form.GroupManager.users_added.push(last_userId);
}
}
}
//REMOVE USERS
WebGUI.Form.GroupManager.removeUsers = function(userId) {
var usersAdded = document.getElementById("list_of_users");
var user = document.getElementById('gm_userId_'+userId);
usersAdded.removeChild(user);
//Keep the lists up to date. If this user was added, then take them out of the
//added list, and do not add them to the deleted list since the group doesn't know
//about it yet.
var userAdded = false;
for(var i = WebGUI.Form.GroupManager.users_added.length-1; i >= 0; i--){
if(WebGUI.Form.GroupManager.users_added[i] == userId) {
WebGUI.Form.GroupManager.users_added.splice(i,1);
userAdded = true;
}
}
if (! userAdded) {
WebGUI.Form.GroupManager.users_deleted.push(userId);
}
if (usersAdded.innerHTML == "") {
usersAdded.setAttribute("style", "display: none !important;");
}
}
//CREATE NEW GROUP
WebGUI.Form.GroupManager.createNewGroup = function() {
WebGUI.Form.GroupManager.dialog.form.groupName.value = '';
var groupIdHidden = document.getElementById("groupManager_groupId");
groupIdHidden.setAttribute("value", "new");
WebGUI.Form.GroupManager.users_added = new Array();
WebGUI.Form.GroupManager.users_deleted = new Array();
WebGUI.Form.GroupManager.groups_added = new Array();
WebGUI.Form.GroupManager.groups_deleted = new Array();
WebGUI.Form.GroupManager.last_groupId = '';
WebGUI.Form.GroupManager.last_userId = '';
var form_target = document.getElementById("gm_form_target");
form_target.innerHTML = '';
var groupsAdded = document.getElementById("list_of_groups");
var usersAdded = document.getElementById("list_of_users");
var groupTextbox = document.getElementById("group_lookup");
var userTextbox = document.getElementById("user_lookup");
groupsAdded.innerHTML = "";
usersAdded.innerHTML = "";
userTextbox.value = WebGUI.Form.GroupManager.i18n.get('Form_Group','Add User...');
groupTextbox.value = WebGUI.Form.GroupManager.i18n.get('Form_Group','Add Group...');
var groupName = document.getElementById("groupName");
groupName.focus();
var groupsAddedRow = document.getElementById("groupsAdded_row");
groupsAddedRow.setAttribute("style", "display: none; visibility: hidden;");
var usersAddedRow = document.getElementById("usersAdded_row");
usersAddedRow.setAttribute("style", "display: none; visibility: hidden;");
var createNewGroupRow = document.getElementById('createNewGroupRow');
createNewGroupRow.setAttribute("style", "display: none; visibility: hidden;");
}
WebGUI.Form.GroupManager.showAutocomplete = function(showWhat) {
var textInput = document.getElementById(showWhat);
textInput.value = "";
var groupsDiv = document.getElementById("groupResultsContainer");
var usersDiv = document.getElementById("userResultsContainer");
switch (showWhat) {
case "group_lookup":
groupsDiv.setAttribute("style", "display: block;");
usersDiv.setAttribute("style", "display: none;");
break;
case "user_lookup":
usersDiv.setAttribute("style", "display: block;");
groupsDiv.setAttribute("style", "display: none;");
break;
}
}