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:
parent
79aa44cf7e
commit
88797c1d6c
42 changed files with 3506 additions and 448 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
docs/upgrades/packages-7.10.12/root_import_dashboard.wgpkg
Normal file
BIN
docs/upgrades/packages-7.10.12/root_import_dashboard.wgpkg
Normal file
Binary file not shown.
|
|
@ -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 --------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -820,6 +820,7 @@
|
|||
"If" : "If",
|
||||
"International" : "International",
|
||||
"LastModified" : "LastModified",
|
||||
"LastModifiedBy" : "LastModifiedBy",
|
||||
"L" : "L_loginBox",
|
||||
"LoginToggle" : "LoginToggle",
|
||||
"MiniCart" : "MiniCart",
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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});
|
||||
|
|
|
|||
129
lib/WebGUI/AssetAspect/Dashlet.pm
Normal file
129
lib/WebGUI/AssetAspect/Dashlet.pm
Normal 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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
60
lib/WebGUI/Help/Asset_Dashboard.pm
Normal file
60
lib/WebGUI/Help/Asset_Dashboard.pm
Normal 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;
|
||||
48
lib/WebGUI/Macro/LastUpdatedBy.pm
Normal file
48
lib/WebGUI/Macro/LastUpdatedBy.pm
Normal 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;
|
||||
|
|
@ -130,6 +130,8 @@ sub getOperations {
|
|||
'listGroups' => 'Group',
|
||||
'manageGroupsInGroup' => 'Group',
|
||||
'manageUsersInGroup' => 'Group',
|
||||
'manageGroups' => 'Group',
|
||||
'updateGroupUsers' => 'Group',
|
||||
|
||||
'viewHelp' => 'Help',
|
||||
'viewHelpIndex' => 'Help',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
33
lib/WebGUI/i18n/English/Form_Group.pm
Normal file
33
lib/WebGUI/i18n/English/Form_Group.pm
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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
67
t/Asset/Wobject/Folder.t
Normal 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
67
t/Asset/Wobject/Layout.t
Normal 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';
|
||||
|
||||
|
||||
65
t/Asset/Wobject/StockData.t
Normal file
65
t/Asset/Wobject/StockData.t
Normal 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
|
||||
111
t/Asset/Wobject/WeatherData.t
Normal file
111
t/Asset/Wobject/WeatherData.t
Normal 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
178
t/Form/Group.t
Normal 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
74
t/Form/User.t
Normal 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
71
t/Macro/LastUpdatedBy.t
Normal 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');
|
||||
BIN
www/extras/toolbar/bullet/add.gif
Normal file
BIN
www/extras/toolbar/bullet/add.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -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%;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
BIN
www/extras/wobject/Dashboard/permissions_btn.jpg
Normal file
BIN
www/extras/wobject/Dashboard/permissions_btn.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
www/extras/yui-webgui/build/form/assets/add.png
Normal file
BIN
www/extras/yui-webgui/build/form/assets/add.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 807 B |
BIN
www/extras/yui-webgui/build/form/assets/new_group.png
Normal file
BIN
www/extras/yui-webgui/build/form/assets/new_group.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
www/extras/yui-webgui/build/form/assets/remove.png
Executable file
BIN
www/extras/yui-webgui/build/form/assets/remove.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 931 B |
170
www/extras/yui-webgui/build/form/groupManager.css
Normal file
170
www/extras/yui-webgui/build/form/groupManager.css
Normal 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;
|
||||
}
|
||||
|
||||
525
www/extras/yui-webgui/build/form/groupManager.js
vendored
Normal file
525
www/extras/yui-webgui/build/form/groupManager.js
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue