Merge in HEAD, up to 9866.
This commit is contained in:
parent
c7a66861a6
commit
2bd7a60a01
107 changed files with 6258 additions and 2436 deletions
|
|
@ -1,5 +1,23 @@
|
|||
7.7.0
|
||||
- fixed #9913: New Content Side Bar missing in Asset window
|
||||
- fixed: New Mail macro never returns any messages
|
||||
- fixed: Template parser cannot be set
|
||||
- fixed #9836: Matrix: Group to Add Listings is missing
|
||||
- fixed #9924: WebGUI::Shop::Cart::readyForCheckout fails randomly (Henry Tang, Long Term Results B.v.)
|
||||
- fixed #9873: third-> first in post template help
|
||||
- fixed #9892: Typo in "Default Gallery View Album" Template [TEMPLATE]
|
||||
- fixed #9826: Inbox messages sent by email don't include from username
|
||||
- rfe: added Asset History browser (perlDreamer Consulting, LLC and Plain Black)
|
||||
- fixed: Commit w/ approval workflow can crash under race conditions resulting in permanently locked content (Martin Kamerbeek / Oqapi )
|
||||
- fixed: Each textarea inserts identical JS that should be inserted only once ( Martin Kamerbeek / Oqapi )
|
||||
- added: Vendor payout system ( Martin Kamerbeek / Oqapi )
|
||||
- fixed #9942: Upgrade script fails with ITransact driver (William McKee, Knowmad Technologies)
|
||||
- fixed #9943: Upgrade script fails with Payment Gateways
|
||||
- fixed #9948: Data form cannot be deleted.
|
||||
- fixed #9950: Wrong var in help for thread
|
||||
- fixed #9956: Product Import
|
||||
- added Survey now has a loading mask on Survey edit ajax calls.
|
||||
- fixed: Sliders fixed. Improved algorithm for determining pixel step size.
|
||||
|
||||
7.6.14
|
||||
- fixed: IE6 shows Admin Bar over Asset Manager
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ 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.7.0
|
||||
--------------------------------------------------------------------
|
||||
* WebGUI now requires Params::Validate version 0.81 or greater.
|
||||
|
||||
7.6.11
|
||||
--------------------------------------------------------------------
|
||||
* If upgrading from WebGUI 7.5, you should upgrade to 7.5.40 first,
|
||||
|
|
|
|||
BIN
docs/upgrades/packages-7.7.0/admin_console.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/admin_console.wgpkg
Normal file
Binary file not shown.
BIN
docs/upgrades/packages-7.7.0/admin_console2.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/admin_console2.wgpkg
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
docs/upgrades/packages-7.7.0/matrix-default-screenshots.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/matrix-default-screenshots.wgpkg
Normal file
Binary file not shown.
BIN
docs/upgrades/packages-7.7.0/matrix-default-view-template.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/matrix-default-view-template.wgpkg
Normal file
Binary file not shown.
BIN
docs/upgrades/packages-7.7.0/root_import_account_shop.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/root_import_account_shop.wgpkg
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
docs/upgrades/packages-7.7.0/survey-root_import_prop-style.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/survey-root_import_prop-style.wgpkg
Normal file
Binary file not shown.
BIN
docs/upgrades/packages-7.7.0/survey.css.wgpkg
Normal file
BIN
docs/upgrades/packages-7.7.0/survey.css.wgpkg
Normal file
Binary file not shown.
|
|
@ -254,7 +254,7 @@ sub upgradeMatrix {
|
|||
my $session = shift;
|
||||
print "\tUpgrading matrix assets... \n" unless $quiet;
|
||||
my $db = $session->db;
|
||||
$db->write("alter table Matrix drop column groupToRate, drop column groupToAdd, drop column privilegedGroup,
|
||||
$db->write("alter table Matrix drop column groupToRate, drop column privilegedGroup,
|
||||
drop column ratingTimeout, drop column ratingTimeoutPrivileged, drop column ratingDetailTemplateId,
|
||||
drop column visitorCacheTimeout");
|
||||
$db->write("alter table Matrix add column defaultSort char(22) not null default 'score',
|
||||
|
|
@ -337,6 +337,7 @@ sub upgradeMatrix {
|
|||
$listing->{title} = $listing->{productName};
|
||||
$listing->{version} = $listing->{versionNumber};
|
||||
$listing->{screenshots} = $listing->{storageId};
|
||||
$listing->{ownerUserId} = $listing->{maintainerId};
|
||||
$listing->{productURL} = $listing->{productUrl};
|
||||
$listing->{manufacturerURL} = $listing->{manufacturerUrl};
|
||||
my $newMatrixListing = $matrix->addChild($listing,undef,undef,{skipAutoCommitWorkflows=>1});
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ use Getopt::Long;
|
|||
use WebGUI::Session;
|
||||
use WebGUI::Storage;
|
||||
use WebGUI::Asset;
|
||||
|
||||
use WebGUI::PassiveAnalytics::Rule;
|
||||
use WebGUI::Utility;
|
||||
|
||||
my $toVersion = '7.7.0';
|
||||
my $quiet; # this line required
|
||||
|
|
@ -34,8 +35,282 @@ my $session = start(); # this line required
|
|||
installStoryManagerTables($session);
|
||||
upgradeConfigFiles($session);
|
||||
|
||||
addGroupToAddToMatrix( $session );
|
||||
addScreenshotTemplatesToMatrix( $session );
|
||||
surveyDoAfterTimeLimit($session);
|
||||
surveyRemoveResponseTemplate($session);
|
||||
surveyEndWorkflow($session);
|
||||
installAssetHistory($session);
|
||||
|
||||
# Passive Analytics
|
||||
pa_installLoggingTables($session);
|
||||
pa_installPassiveAnalyticsRule($session);
|
||||
pa_installPassiveAnalyticsConfig($session);
|
||||
pa_installWorkflow($session);
|
||||
pa_addPassiveAnalyticsSettings($session);
|
||||
pa_addPassiveAnalyticsStatus($session);
|
||||
|
||||
# vendor payouts
|
||||
addTransactionItemFlags( $session );
|
||||
createShopAcccountPluginSettings( $session );
|
||||
|
||||
finish($session); # this line required
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub addGroupToAddToMatrix {
|
||||
my $session = shift;
|
||||
print "\tAdding groupToAdd to Matrix table, if needed... \n" unless $quiet;
|
||||
my $sth = $session->db->read('describe Matrix groupToAdd');
|
||||
if (! defined $sth->hashRef) {
|
||||
$session->db->write("alter table Matrix add column groupToAdd char(22) default 2");
|
||||
}
|
||||
print "Done.\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub addScreenshotTemplatesToMatrix {
|
||||
my $session = shift;
|
||||
print "\tAdding screenshot templates to Matrix table \n" unless $quiet;
|
||||
|
||||
$session->db->write("alter table Matrix add screenshotsConfigTemplateId char(22);");
|
||||
$session->db->write("update Matrix set screenshotsConfigTemplateId = 'matrixtmpl000000000007';");
|
||||
$session->db->write("alter table Matrix add screenshotsTemplateId char(22);");
|
||||
$session->db->write("update Matrix set screenshotsTemplateId = 'matrixtmpl000000000006';");
|
||||
|
||||
print "Done.\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub surveyDoAfterTimeLimit {
|
||||
my $session = shift;
|
||||
print "\tAdding column doAfterTimeLimit to Survey table... " unless $quiet;
|
||||
$session->db->write('alter table Survey add doAfterTimeLimit char(22)');
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub surveyEndWorkflow {
|
||||
my $session = shift;
|
||||
print "\tAdding column onSurveyEndWorkflowId to Survey table... " unless $quiet;
|
||||
$session->db->write('alter table Survey add onSurveyEndWorkflowId varchar(22) character set utf8 collate utf8_bin');
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub surveyRemoveResponseTemplate {
|
||||
my $session = shift;
|
||||
print "\tRemoving responseTemplate... " unless $quiet;
|
||||
$session->db->write('alter table Survey drop responseTemplateId');
|
||||
if (my $template = WebGUI::Asset->new($session, 'PBtmpl0000000000000064')) {
|
||||
$template->purge();
|
||||
}
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub installAssetHistory {
|
||||
my $session = shift;
|
||||
print "\tAdding Asset History content handler... \n" unless $quiet;
|
||||
##Content Handler
|
||||
my $contentHandlers = $session->config->get('contentHandlers');
|
||||
if (! isIn('WebGUI::Content::Handler', @{ $contentHandlers }) ) {
|
||||
my @newHandlers = ();
|
||||
foreach my $handler (@{ $contentHandlers }) {
|
||||
push @newHandlers, $handler;
|
||||
push @newHandlers, 'WebGUI::Content::AssetHistory' if
|
||||
$handler eq 'WebGUI::Content::Account';
|
||||
}
|
||||
$session->config->set('contentHandlers', \@newHandlers);
|
||||
}
|
||||
##Admin Console
|
||||
$session->config->addToHash('adminConsole', 'assetHistory', {
|
||||
"icon" => "assetHistory.gif",
|
||||
"groupSetting" => "groupIdAdminHistory",
|
||||
"uiLevel" => 5,
|
||||
"url" => "^PageUrl(\"\",op=assetHistory);",
|
||||
"title" => "^International(assetHistory,Asset);"
|
||||
});
|
||||
##Setting for custom group
|
||||
$session->setting->add('groupIdAdminHistory', 12);
|
||||
print "Done.\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub pa_installLoggingTables {
|
||||
my $session = shift;
|
||||
print "\tInstall logging tables... " unless $quiet;
|
||||
my $db = $session->db;
|
||||
$db->write(<<EOT1);
|
||||
DROP TABLE IF EXISTS `passiveLog`
|
||||
EOT1
|
||||
$db->write(<<EOT1);
|
||||
CREATE TABLE `passiveLog` (
|
||||
`userId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`assetId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`sessionId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`timeStamp` bigint(20),
|
||||
`url` varchar(255) character set utf8 collate utf8_bin NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
EOT1
|
||||
$db->write(<<EOT2);
|
||||
DROP TABLE IF EXISTS `deltaLog`
|
||||
EOT2
|
||||
$db->write(<<EOT2);
|
||||
CREATE TABLE `deltaLog` (
|
||||
`userId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`assetId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`delta` integer,
|
||||
`timeStamp` bigint(20),
|
||||
`url` varchar(255) character set utf8 collate utf8_bin NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
EOT2
|
||||
$db->write(<<EOT3);
|
||||
DROP TABLE IF EXISTS `bucketLog`
|
||||
EOT3
|
||||
$db->write(<<EOT3);
|
||||
CREATE TABLE `bucketLog` (
|
||||
`userId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`Bucket` varchar(22) character set utf8 collate utf8_bin NOT NULL default '',
|
||||
`duration` integer,
|
||||
`timeStamp` datetime
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
EOT3
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Add the PassiveAnalytics Rule table
|
||||
sub pa_installPassiveAnalyticsRule {
|
||||
my $session = shift;
|
||||
print "\tInstall Passive Analytics rule table, via Crud... " unless $quiet;
|
||||
# and here's our code
|
||||
WebGUI::PassiveAnalytics::Rule->crud_createTable($session);
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Add the PassiveAnalytics Settings
|
||||
sub pa_addPassiveAnalyticsSettings {
|
||||
my $session = shift;
|
||||
print "\tInstall Passive Analytics settings... " unless $quiet;
|
||||
# and here's our code
|
||||
$session->setting->add('passiveAnalyticsInterval', 300);
|
||||
$session->setting->add('passiveAnalyticsDeleteDelta', 0);
|
||||
$session->setting->add('passiveAnalyticsEnabled', 0);
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Add the PassiveAnalytics Rule table
|
||||
sub pa_addPassiveAnalyticsStatus {
|
||||
my $session = shift;
|
||||
my $db = $session->db;
|
||||
print "\tInstall Passive Analytics status table... " unless $quiet;
|
||||
# and here's our code
|
||||
$db->write(<<EOT2);
|
||||
DROP TABLE if exists passiveAnalyticsStatus;
|
||||
EOT2
|
||||
$db->write(<<EOT3);
|
||||
CREATE TABLE `passiveAnalyticsStatus` (
|
||||
`startDate` datetime,
|
||||
`endDate` datetime,
|
||||
`running` integer(2) DEFAULT 0,
|
||||
`userId` varchar(22) character set utf8 collate utf8_bin NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
EOT3
|
||||
$db->write('insert into passiveAnalyticsStatus (userId) VALUES (3)');
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Add the Passive Analytics config file entry
|
||||
# for the adminConsole and the content handler
|
||||
sub pa_installPassiveAnalyticsConfig {
|
||||
my $session = shift;
|
||||
print "\tAdd Passive Analytics entry to the config file... " unless $quiet;
|
||||
# Admin Bar/Console
|
||||
my $adminConsole = $session->config->get('adminConsole');
|
||||
if (!exists $adminConsole->{'passiveAnalytics'}) {
|
||||
$adminConsole->{'passiveAnalytics'} = {
|
||||
"icon" => "passiveAnalytics.png",
|
||||
"uiLevel" => 1,
|
||||
"url" => "^PageUrl(\"\",op=passiveAnalytics;func=editRuleflow);",
|
||||
"title" => "^International(Passive Analytics,PassiveAnalytics);",
|
||||
"groupSetting" => "3",
|
||||
};
|
||||
$session->config->set('adminConsole', $adminConsole);
|
||||
}
|
||||
# Content Handler
|
||||
my $contentHandlers = $session->config->get('contentHandlers');
|
||||
if (!isIn('WebGUI::Content::PassiveAnalytics',@{ $contentHandlers} ) ) {
|
||||
my $contentIndex = 0;
|
||||
HANDLER: while ($contentIndex <= $#{ $contentHandlers } ) {
|
||||
##Insert before Operation
|
||||
if($contentHandlers->[$contentIndex] eq 'WebGUI::Content::Operation') {
|
||||
splice @{ $contentHandlers }, $contentIndex, 0, 'WebGUI::Content::PassiveAnalytics';
|
||||
last HANDLER;
|
||||
}
|
||||
++$contentIndex;
|
||||
}
|
||||
$session->config->set('contentHandlers', $contentHandlers);
|
||||
}
|
||||
# Workflow Activities
|
||||
my $workflowActivities = $session->config->get('workflowActivities');
|
||||
my @none = @{ $workflowActivities->{'None'} };
|
||||
if (!isIn('WebGUI::Workflow::Activity::SummarizePassiveAnalytics', @none)) {
|
||||
push @none, 'WebGUI::Workflow::Activity::SummarizePassiveAnalytics';
|
||||
}
|
||||
if (!isIn('WebGUI::Workflow::Activity::BucketPassiveAnalytics', @none)) {
|
||||
push @none, 'WebGUI::Workflow::Activity::BucketPassiveAnalytics';
|
||||
}
|
||||
$workflowActivities->{'None'} = [ @none ];
|
||||
$session->config->set('workflowActivities', $workflowActivities);
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Add the Passive Analytics Workflow
|
||||
sub pa_installWorkflow {
|
||||
my $session = shift;
|
||||
print "\tAdd Passive Analytics Workflow... " unless $quiet;
|
||||
my $workflow = WebGUI::Workflow->create(
|
||||
$session,
|
||||
{
|
||||
title => 'Analyze Passive Analytics',
|
||||
mode => 'singleton',
|
||||
type => 'None',
|
||||
description => 'Manual changes to this workflow will be lost. Please only use the Passive Analytics screen to make changes',
|
||||
},
|
||||
'PassiveAnalytics000001',
|
||||
);
|
||||
my $summarize = $workflow->addActivity('WebGUI::Workflow::Activity::SummarizePassiveAnalytics');
|
||||
my $bucket = $workflow->addActivity('WebGUI::Workflow::Activity::BucketPassiveAnalytics');
|
||||
$summarize->set('title', 'Perform duration analysis');
|
||||
$bucket->set( 'title', 'Please log entries into buckets');
|
||||
$workflow->set({enabled => 1});
|
||||
print "DONE!\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub addTransactionItemFlags {
|
||||
my $session = shift;
|
||||
print "\tAdding columns for vendor payout tracking to transaction items..." unless $quiet;
|
||||
|
||||
$session->db->write('alter table transactionItem add column vendorPayoutStatus char(10) default \'NotPaid\'');
|
||||
$session->db->write('alter table transactionItem add column vendorPayoutAmount float (6,2) default 0.00');
|
||||
|
||||
print "Done.\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
sub createShopAcccountPluginSettings {
|
||||
my $session = shift;
|
||||
print "Creating default settings for the account plugin..." unless $quiet;
|
||||
|
||||
$session->setting->add('shopMySalesTemplateId', '-zxyB-O50W8YnL39Ouoc4Q');
|
||||
|
||||
print "Done.\n" unless $quiet;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Describe what our function does
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ sub upgradeMatrix {
|
|||
my $session = shift;
|
||||
print "\tUpgrading matrix assets... \n" unless $quiet;
|
||||
my $db = $session->db;
|
||||
$db->write("alter table Matrix drop column groupToRate, drop column groupToAdd, drop column privilegedGroup,
|
||||
$db->write("alter table Matrix drop column groupToRate, drop column privilegedGroup,
|
||||
drop column ratingTimeout, drop column ratingTimeoutPrivileged, drop column ratingDetailTemplateId,
|
||||
drop column visitorCacheTimeout");
|
||||
$db->write("alter table Matrix add column defaultSort char(22) not null default 'score',
|
||||
|
|
@ -144,6 +144,7 @@ sub upgradeMatrix {
|
|||
$listing->{title} = $listing->{productName};
|
||||
$listing->{version} = $listing->{versionNumber};
|
||||
$listing->{screenshots} = $listing->{storageId};
|
||||
$listing->{ownerUserId} = $listing->{maintainerId};
|
||||
$listing->{productURL} = $listing->{productUrl};
|
||||
$listing->{manufacturerURL} = $listing->{manufacturerUrl};
|
||||
my $newMatrixListing = $matrix->addChild($listing,undef,undef,{skipAutoCommitWorkflows=>1});
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ sub setDefaultItransactCredentialTemplate {
|
|||
my $drivers = $pay->getPaymentGateways($session);
|
||||
DRIVER: foreach my $driver (@{ $drivers }) {
|
||||
##Only work on ITransact drivers
|
||||
next DRIVER unless $driver->className eq "WebGUI::Shop::PayDriver::ITransact";
|
||||
next DRIVER unless $driver && $driver->className eq "WebGUI::Shop::PayDriver::ITransact";
|
||||
my $properties = $driver->get();
|
||||
##And only ones that don't already have a template set
|
||||
next DRIVER if $properties->{credentialsTemplateId};
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ sub fixPayDriverLabels {
|
|||
print "\tGet rid of the duplicate label properties in the PayDrivers... " unless $quiet;
|
||||
my $pay = WebGUI::Shop::Pay->new($session);
|
||||
my $gateways = $pay->getPaymentGateways;
|
||||
foreach my $gateway (@{ $gateways }) {
|
||||
GATEWAY: foreach my $gateway (@{ $gateways }) {
|
||||
next GATEWAY unless $gateway;
|
||||
my $gatewayId = $gateway->getId;
|
||||
my $jsonLabel = $gateway->get('label');
|
||||
next if $jsonLabel;
|
||||
|
|
|
|||
|
|
@ -331,6 +331,13 @@
|
|||
"url" : "^PageUrl(\"\",op=assetManager);",
|
||||
"title" : "^International(assets,Asset);"
|
||||
},
|
||||
"assetHistory" : {
|
||||
"icon" : "assetHistory.gif",
|
||||
"groupSetting" : "groupIdAdminHistory",
|
||||
"uiLevel" : 5,
|
||||
"url" : "^PageUrl(\"\",op=assetHistory);",
|
||||
"title" : "^International(assetHistory,Asset);"
|
||||
},
|
||||
"graphics" : {
|
||||
"icon" : "graphics.gif",
|
||||
"uiLevel" : 5,
|
||||
|
|
@ -902,6 +909,7 @@
|
|||
"WebGUI::Content::AssetDiscovery",
|
||||
"WebGUI::Content::AjaxI18N",
|
||||
"WebGUI::Content::Account",
|
||||
"WebGUI::Content::AssetHistory",
|
||||
"WebGUI::Content::Operation",
|
||||
"WebGUI::Content::Setup",
|
||||
"WebGUI::Content::Shop",
|
||||
|
|
|
|||
|
|
@ -433,5 +433,15 @@ sub showError {
|
|||
return $self->processTemplate($var,$templateId)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 store ( )
|
||||
|
||||
This method returns an internal hash where you can store things for your Account Plugin.
|
||||
The store is private to your plugin, to each user's copy of the plugin, and only lasts as
|
||||
long as the session does.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ sub www_removeFriend {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_removeFriend ( )
|
||||
=head2 www_removeFriendConfirm ( )
|
||||
|
||||
This is a confirmation page of whether or not the user wishes to remove the selected user from friend
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,11 @@ sub appendCommonVars {
|
|||
my $user = $session->user;
|
||||
my $method = $session->form->get("do");
|
||||
|
||||
$var->{'manage_purchases_url' } = $self->getUrl("module=shop;do=managePurchases");
|
||||
$var->{'managesPurchasesIsActive'} = WebGUI::Utility::isIn($method,("","managePurchases","view","viewTransaction"));
|
||||
$var->{ 'manage_purchases_url' } = $self->getUrl("module=shop;do=managePurchases");
|
||||
$var->{ 'managesPurchasesIsActive' } = WebGUI::Utility::isIn($method,("","managePurchases","view","viewTransaction"));
|
||||
|
||||
$var->{ 'view_sales_url' } = $self->getUrl( 'module=shop;do=viewSales' );
|
||||
$var->{ 'viewSalesIsActive' } = $method eq 'viewSales';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -108,6 +111,13 @@ sub editSettingsForm {
|
|||
label => $shopi18n->get("my purchases detail template"),
|
||||
hoverHelp => $shopi18n->get("my purchases detail template help")
|
||||
);
|
||||
$f->template(
|
||||
name => 'shopMySalesTemplateId',
|
||||
value => $self->session->setting->get('shopMySalesTemplateId'),
|
||||
namespace => 'Shop/MySales',
|
||||
label => $shopi18n->echo('my sales template'),
|
||||
hoverHelp => $shopi18n->echo('my sales template help'),
|
||||
);
|
||||
|
||||
return $f->printRowsOnly;
|
||||
}
|
||||
|
|
@ -130,6 +140,7 @@ sub editSettingsFormSave {
|
|||
$setting->set("shopLayoutTemplateId", $form->process("shopLayoutTemplateId","template"));
|
||||
$setting->set("shopMyPurchasesTemplateId", $form->process("shopMyPurchasesTemplateId","template"));
|
||||
$setting->set("shopMyPurchasesDetailTemplateId", $form->process("shopMyPurchasesDetailTemplateId","template"));
|
||||
$setting->set("shopMySalesTemplateId", $form->process("shopMySalesTemplateId","template"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -208,6 +219,43 @@ sub www_view {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewSales ( )
|
||||
|
||||
Page that show your earnings if you are a vendor.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewSales {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $vendor = WebGUI::Shop::Vendor->newByUserId( $session, $session->user->userId );
|
||||
|
||||
my $var = $vendor->getPayoutTotals;
|
||||
my $totalSales = 0;
|
||||
my @products;
|
||||
|
||||
my $sth = $session->db->read(
|
||||
'select *, sum(quantity) as quantity, sum(vendorPayoutAmount) as payoutAmount from transactionItem '
|
||||
.'where vendorId=? group by assetId order by quantity desc',
|
||||
[ $vendor->getId ]
|
||||
);
|
||||
while (my $row = $sth->hashRef) {
|
||||
push @products, $row;
|
||||
$totalSales += $row->{quantity};
|
||||
}
|
||||
$sth->finish;
|
||||
|
||||
$var->{ product_loop } = \@products;
|
||||
$var->{ total_products } = scalar @products;
|
||||
$var->{ total_sales } = $totalSales;
|
||||
|
||||
$self->appendCommonVars( $var );
|
||||
|
||||
return $self->processTemplate( $var, $session->setting->get('shopMySalesTemplateId') );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewTransaction ( )
|
||||
|
||||
The main view page for editing the user's profile.
|
||||
|
|
@ -294,4 +342,5 @@ sub www_viewTransaction {
|
|||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,43 @@ sub addRevision {
|
|||
return $newSelf;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 canAdd ( )
|
||||
|
||||
Override canAdd to ignore its permissions check. Permissions are handled
|
||||
by the parent Matrix.
|
||||
|
||||
=cut
|
||||
|
||||
sub canAdd {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 canEdit ( )
|
||||
|
||||
Returns true if the user can edit this asset. C<userId> is a WebGUI user ID.
|
||||
|
||||
Users can edit this Matrix listing if they are the owner, or if they can edit
|
||||
the parent Matrix.
|
||||
|
||||
=cut
|
||||
|
||||
sub canEdit {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->session->form->process("assetId") eq "new" ) {
|
||||
return $self->getParent->canAddMatrixListing();
|
||||
}
|
||||
else {
|
||||
return 1 if $self->session->user->userId eq $self->get("ownerUserId");
|
||||
|
||||
return $self->getParent->canEdit();
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
|
@ -327,7 +364,7 @@ sub getEditForm {
|
|||
|
||||
$form->raw(
|
||||
'<tr><td COLSPAN=2>'.
|
||||
WebGUI::Form::Button($session, {}).
|
||||
WebGUI::Form::Submit($session, {}).
|
||||
WebGUI::Form::Button($session, {
|
||||
-value => $i18n->get('cancel', 'WebGUI'),
|
||||
-extras => q|onclick="history.go(-1);" class="backwardButton"|
|
||||
|
|
@ -580,6 +617,14 @@ sub view {
|
|||
if ($emailSent){
|
||||
$var->{emailSent} = 1;
|
||||
}
|
||||
|
||||
unless($self->hasBeenCommitted){
|
||||
my $workflowInstanceId = $db->quickScalar("select workflowInstanceId from assetVersionTag where tagId =?"
|
||||
,[$self->get('tagId')]);
|
||||
$var->{canApprove} = $self->getParent->canEdit;
|
||||
$var->{approveOrDenyUrl} = $self->getUrl("op=manageRevisionsInTag;workflowInstanceId=".$workflowInstanceId
|
||||
.";tagId=".$self->get('tagId'));
|
||||
}
|
||||
$var->{canEdit} = $self->canEdit;
|
||||
$var->{editUrl} = $self->getUrl("func=edit");
|
||||
$var->{controls} = $self->getToolbar;
|
||||
|
|
@ -647,33 +692,10 @@ sub view {
|
|||
my $storage = $file->getStorageLocation;
|
||||
my @files;
|
||||
@files = @{ $storage->getFiles } if (defined $storage);
|
||||
|
||||
$var->{screenshots} = qq|
|
||||
<script type="text/javascript" src="/extras/ukplayer/swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
swfobject.registerObject("myFlashContent","9.0.0","/extras/ukplayer/expressInstall.swf");
|
||||
</script>
|
||||
<div>
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400" height="300" id="myFlashContent">
|
||||
<param name="movie" value="/extras/ukplayer/slideShow.swf" />
|
||||
<param name="flashvars" value="config=?func=getScreenshotsConfig" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="/extras/ukplayer/slideShow.swf" width="400"
|
||||
height="300">
|
||||
<param name="flashvars" value="config=?func=getScreenshotsConfig" />
|
||||
<!--<![endif]-->
|
||||
<a href="http:/www.adobe.com/go/getflashplayer">
|
||||
<img src="http:/www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe
|
||||
Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
|;
|
||||
$var->{screenshotsUrl} = $self->getUrl('func=viewScreenshots');
|
||||
$var->{screenshotThumbnail} = $storage->getUrl('thumb-'.$files[0]);
|
||||
}
|
||||
|
||||
|
||||
# Rating form
|
||||
|
||||
my %rating;
|
||||
|
|
@ -835,12 +857,14 @@ Web facing method which is the default edit page
|
|||
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
|
||||
return $self->session->privilege->noAccess() unless $self->getParent->canAddMatrixListing();
|
||||
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_MatrixListing");
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
|
||||
if($self->session->form->process('func') eq 'add'){
|
||||
return $self->session->privilege->noAccess() unless $self->getParent->canAddMatrixListing();
|
||||
}else{
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
}
|
||||
|
||||
my $var = $self->get;
|
||||
my $matrix = $self->getParent;
|
||||
|
|
@ -930,9 +954,7 @@ sub www_getScreenshots {
|
|||
my $thumb = 'thumb-'.$file;
|
||||
$xml .= "
|
||||
<slide>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
<title><![CDATA[<b>Slide</b> One]]></title>
|
||||
<title></title>
|
||||
<description><![CDATA[ Screenshots ]]></description>
|
||||
<image_source>".$storage->getUrl($file)."</image_source>
|
||||
<duration>5</duration>
|
||||
|
|
@ -960,56 +982,14 @@ Returns the xml config file for the ukplayer that displays the screenshots.
|
|||
=cut
|
||||
|
||||
sub www_getScreenshotsConfig {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $var = $self->get;
|
||||
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
|
||||
$self->session->http->setMimeType('text/xml');
|
||||
|
||||
my $xml = qq|<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config>
|
||||
|
||||
<content_url>?func=getScreenshots</content_url>
|
||||
|
||||
<width>400</width><!-- this value is overwritten by the flashVars but the tag needs to be here (and it is
|
||||
useful for offline testing) -->
|
||||
<height>300</height><!-- this value is overwritten by the flashVars but the tag needs to be here (and it is
|
||||
useful for offline testing) -->
|
||||
<background_color>0xDDDDEE</background_color>
|
||||
<default_duration>20</default_duration>
|
||||
<default_slidewidth>100</default_slidewidth>
|
||||
<default_slideheight>100</default_slideheight>
|
||||
|
||||
<font>Verdana</font>
|
||||
<font_size>12</font_size>
|
||||
<font_color>0xCCCCCC</font_color>
|
||||
<text_border_color>0xCCCCCC</text_border_color>
|
||||
<text_bg_color>0x000000</text_bg_color>
|
||||
<text_autohide>true</text_autohide>
|
||||
|
||||
<controls_color>0xCCCCCC</controls_color>
|
||||
<controls_border_color>0xCCCCCC</controls_border_color>
|
||||
<controls_bg_color>0x000000</controls_bg_color>
|
||||
<controls_autohide>false</controls_autohide>
|
||||
|
||||
<thumbnail_width>48</thumbnail_width>
|
||||
<thumbnail_height>36</thumbnail_height>
|
||||
<thumbnail_border_color>0x000000</thumbnail_border_color>
|
||||
<menu_autohide>true</menu_autohide>
|
||||
<menu_dead_zone_width>100</menu_dead_zone_width>
|
||||
<menu_gaps>5</menu_gaps>
|
||||
|
||||
<mute_at_start>false</mute_at_start>
|
||||
<autostart>true</autostart>
|
||||
<autopause>false</autopause>
|
||||
<loop>false</loop>
|
||||
<error_message_content><![CDATA[XML not found: ]]></error_message_content>
|
||||
<error_message_image><![CDATA[Image not found]]></error_message_image>
|
||||
|
||||
</config>
|
||||
|;
|
||||
|
||||
return $xml;
|
||||
return $self->processTemplate($var,$self->getParent->get("screenshotsConfigTemplateId"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1117,7 +1097,24 @@ sub www_view {
|
|||
return $self->view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewScreenshots ( )
|
||||
|
||||
Returns this listing's screenshots in a ukplayer.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewScreenshots {
|
||||
my $self = shift;
|
||||
my $var = $self->get;
|
||||
|
||||
$var->{configUrl} = 'config='.$self->getUrl("func=getScreenshotsConfig");
|
||||
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
|
||||
return $self->processTemplate($var,$self->getParent->get("screenshotsTemplateId"));
|
||||
}
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
|
|
|
|||
|
|
@ -292,6 +292,31 @@ sub getThumbnailUrl {
|
|||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 getVendorId ( )
|
||||
|
||||
Returns the vendorId of the vendor for this sku. Defaults to the default
|
||||
vendor with id defaultvendor000000000.
|
||||
|
||||
=cut
|
||||
|
||||
sub getVendorId {
|
||||
my $self = shift;
|
||||
return 'defaultvendor000000000';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getVendorPayout ( )
|
||||
|
||||
Returns the amount that should be payed to the vendor for this sku.
|
||||
|
||||
=cut
|
||||
|
||||
sub getVendorPayout {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getWeight ( )
|
||||
|
|
|
|||
|
|
@ -391,12 +391,13 @@ sub _cacheFieldConfig {
|
|||
my $fieldData;
|
||||
if ($jsonData && eval { $jsonData = JSON::from_json($jsonData) ; 1 }) {
|
||||
# jsonData is an array in the order the fields should be
|
||||
$self->{_fieldConfig} = {
|
||||
map { $_->{name}, $_ } @{ $jsonData }
|
||||
};
|
||||
$self->{_fieldOrder} = [
|
||||
map { $_->{name} } @{ $jsonData }
|
||||
];
|
||||
$self->{_fieldConfig} = {};
|
||||
$self->{_fieldOrder} = [];
|
||||
FIELD: foreach my $field (@{ $jsonData } ) {
|
||||
next FIELD unless ref $field eq 'HASH';
|
||||
$self->{_fieldConfig}->{$field->{name}} = $field;
|
||||
push @{ $self->{_fieldOrder} }, $field->{name};
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->{_fieldConfig} = {};
|
||||
|
|
|
|||
|
|
@ -30,10 +30,46 @@ Returns true if able to add MatrixListings.
|
|||
|
||||
sub canAddMatrixListing {
|
||||
my $self = shift;
|
||||
my $user = $self->session->user;
|
||||
|
||||
return 0 if $self->session->user->isVisitor;
|
||||
# Users in the groupToAdd group can add listings
|
||||
if ( $user->isInGroup( $self->get("groupToAdd") ) ) {
|
||||
return 1;
|
||||
}
|
||||
# Users who can edit matrix can add listings
|
||||
else {
|
||||
return $self->canEdit;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 canEdit ( [userId] )
|
||||
|
||||
Returns true if the user can edit this Matrix.
|
||||
|
||||
Also checks if a user is adding a Matrix Listing and allows them to if they are
|
||||
part of the C<groupToAdd> group.
|
||||
|
||||
=cut
|
||||
|
||||
sub canEdit {
|
||||
my $self = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
|
||||
my $form = $self->session->form;
|
||||
if ( $form->get('func') eq "editSave" && $form->get('assetId') eq "new" && $form->get( 'class' )->isa(
|
||||
'WebGUI::Asset::MatrixListing' ) ) {
|
||||
return $self->canAddMatrixListing();
|
||||
}
|
||||
else {
|
||||
if ($userId eq $self->get("ownerUserId")) {
|
||||
return 1;
|
||||
}
|
||||
my $user = WebGUI::User->new($self->session, $userId);
|
||||
return $user->isInGroup($self->get("groupIdEdit"));
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -94,6 +130,22 @@ sub definition {
|
|||
hoverHelp =>$i18n->get('edit listing template description'),
|
||||
label =>$i18n->get('edit listing template label'),
|
||||
},
|
||||
screenshotsTemplateId=>{
|
||||
defaultValue =>"matrixtmpl000000000006",
|
||||
fieldType =>"template",
|
||||
tab =>"display",
|
||||
namespace =>"Matrix/Screenshots",
|
||||
hoverHelp =>$i18n->get('screenshots template description'),
|
||||
label =>$i18n->get('screenshots template label'),
|
||||
},
|
||||
screenshotsConfigTemplateId=>{
|
||||
defaultValue =>"matrixtmpl000000000007",
|
||||
fieldType =>"template",
|
||||
tab =>"display",
|
||||
namespace =>"Matrix/ScreenshotsConfig",
|
||||
hoverHelp =>$i18n->get('screenshots config template description'),
|
||||
label =>$i18n->get('screenshots config template label'),
|
||||
},
|
||||
defaultSort=>{
|
||||
fieldType =>"selectBox",
|
||||
tab =>"display",
|
||||
|
|
@ -164,6 +216,13 @@ sub definition {
|
|||
hoverHelp =>$i18n->get('max comparisons privileged description'),
|
||||
label =>$i18n->get('max comparisons privileged label'),
|
||||
},
|
||||
groupToAdd=>{
|
||||
fieldType =>"group",
|
||||
tab =>"security",
|
||||
defaultValue =>2,
|
||||
hoverHelp =>$i18n->get('group to add description'),
|
||||
label =>$i18n->get('group to add label'),
|
||||
},
|
||||
submissionApprovalWorkflowId=>{
|
||||
fieldType =>"workflow",
|
||||
tab =>"security",
|
||||
|
|
@ -543,7 +602,8 @@ sub view {
|
|||
}) };
|
||||
foreach my $pendingListing (@pendingListings){
|
||||
push (@{ $var->{pending_loop} }, {
|
||||
url => $pendingListing->getUrl,
|
||||
url => $pendingListing->getUrl
|
||||
."?func=view;revision=".$pendingListing->get('revisionDate'),
|
||||
name => $pendingListing->get('title'),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,7 +210,11 @@ sub importProducts {
|
|||
}
|
||||
|
||||
if ($productRow{title} ne $product->getTitle) {
|
||||
$product->update({ title => $product->fixTitle($productRow{title}) });
|
||||
my $newTitle = $product->fixTitle($productRow{title});
|
||||
$product->update({
|
||||
title => $newTitle,
|
||||
menuTitle => $newTitle,
|
||||
});
|
||||
}
|
||||
|
||||
my $collaterals = $product->getAllCollateral('variantsJSON');
|
||||
|
|
@ -230,10 +234,12 @@ sub importProducts {
|
|||
##Insert a new product;
|
||||
$session->log->warn("Making a new product: $productRow{sku}\n");
|
||||
my $newProduct = $node->addChild({className => 'WebGUI::Asset::Sku::Product'});
|
||||
my $newTitle = $newProduct->fixTitle($productRow{title});
|
||||
$newProduct->update({
|
||||
title => $newProduct->fixTitle($productRow{title}),
|
||||
url => $newProduct->fixUrl($productRow{title}),
|
||||
sku => $productRow{mastersku},
|
||||
title => $newTitle,
|
||||
menuTitle => $newTitle,
|
||||
url => $newProduct->fixUrl($productRow{title}),
|
||||
sku => $productRow{mastersku},
|
||||
});
|
||||
$newProduct->setCollateral('variantsJSON', 'variantId', 'new', \%productCollateral);
|
||||
$newProduct->commit;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -18,6 +18,7 @@ use strict;
|
|||
use LWP::MediaTypes qw(guess_media_type);
|
||||
use Time::HiRes;
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::PassiveAnalytics::Logging;
|
||||
|
||||
use Apache2::Const -compile => qw(OK);
|
||||
|
||||
|
|
@ -170,6 +171,9 @@ sub page {
|
|||
$method = "view";
|
||||
}
|
||||
}
|
||||
##Passive Analytics Logging
|
||||
WebGUI::PassiveAnalytics::Logging::log($session, $asset);
|
||||
|
||||
$output = tryAssetMethod($session,$asset,$method);
|
||||
$output = tryAssetMethod($session,$asset,"view") unless ($output || ($method eq "view"));
|
||||
}
|
||||
|
|
|
|||
165
lib/WebGUI/Content/AssetHistory.pm
Normal file
165
lib/WebGUI/Content/AssetHistory.pm
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
package WebGUI::Content::AssetHistory;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
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
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Content::AssetHistory
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Give the admins an interface to view the history of assets on their site.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::Content::AssetHistory;
|
||||
my $output = WebGUI::Content::AssetHistory::handler($session);
|
||||
|
||||
=head1 SUBROUTINES
|
||||
|
||||
These subroutines are available from this package:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 handler ( session )
|
||||
|
||||
The content handler for this package.
|
||||
|
||||
=cut
|
||||
|
||||
sub handler {
|
||||
my ($session) = @_;
|
||||
return undef unless ($session->form->get('op') eq 'assetHistory');
|
||||
my $method = $session->form->get( 'method' )
|
||||
? 'www_' . $session->form->get( 'method' )
|
||||
: 'www_view'
|
||||
;
|
||||
|
||||
# Validate the method name
|
||||
if ( !__PACKAGE__->can( $method ) ) {
|
||||
return "Invalid method";
|
||||
}
|
||||
else {
|
||||
return __PACKAGE__->can( $method )->( $session );
|
||||
}
|
||||
my $output = "";
|
||||
# ...
|
||||
return $output;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_getHistoryAsJson ( )
|
||||
|
||||
Servers side pagination for asset history data displayed in a YUI DataTable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_getHistoryAsJson {
|
||||
my ($session) = @_;
|
||||
return $session->privilege->insufficient
|
||||
unless $session->user->isInGroup(12);
|
||||
my ($db, $form) = $session->quick(qw(db form));
|
||||
my $startIndex = $form->get('startIndex') || 0;
|
||||
my $numberOfResults = $form->get('results') || 25;
|
||||
my %goodKeys = qw/assetId 1 url 1 username 1 dateStamp 1/;
|
||||
my $sortKey = $form->get('sortKey');
|
||||
$sortKey = $goodKeys{$sortKey} == 1 ? $sortKey : 'dateStamp';
|
||||
my $sortDir = $form->get('sortDir');
|
||||
$sortDir = lc($sortDir) eq 'desc' ? 'desc' : 'asc';
|
||||
my @placeholders = ();
|
||||
my $sql = <<EOSQL;
|
||||
select SQL_CALC_FOUND_ROWS assetHistory.*,users.username from assetHistory join users on assetHistory.userId=users.userId
|
||||
EOSQL
|
||||
my $keywords = $form->get("keywords");
|
||||
if ($keywords ne "") {
|
||||
$db->buildSearchQuery(\$sql, \@placeholders, $keywords, [qw{url assetId username}])
|
||||
}
|
||||
push(@placeholders, $startIndex, $numberOfResults);
|
||||
$sql .= sprintf (" order by %s limit ?,?","$sortKey $sortDir");
|
||||
my %results = ();
|
||||
my @records = ();
|
||||
my $sth = $db->read($sql, \@placeholders);
|
||||
while (my $record = $sth->hashRef) {
|
||||
push(@records,$record);
|
||||
}
|
||||
$results{'recordsReturned'} = $sth->rows()+0;
|
||||
$sth->finish;
|
||||
$results{'records'} = \@records;
|
||||
$results{'totalRecords'} = $db->quickScalar('select found_rows()')+0; ##Convert to numeric
|
||||
$results{'startIndex'} = $startIndex;
|
||||
$results{'sort'} = undef;
|
||||
$results{'dir'} = $sortDir;
|
||||
$session->http->setMimeType('application/json');
|
||||
my $json = JSON::to_json(\%results);
|
||||
return $json;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
YUI DataTable for browsing asset history.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_view {
|
||||
my $session = shift;
|
||||
return $session->privilege->insufficient
|
||||
unless $session->user->isInGroup(12);
|
||||
##YUI specific datatable CSS
|
||||
my $ac = WebGUI::AdminConsole->new( $session, "assetHistory", {
|
||||
showAdminBar => 1
|
||||
} );
|
||||
my ($style, $url) = $session->quick(qw(style url));
|
||||
$style->setLink($url->extras('/yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/build/datatable/assets/skins/sam/datatable.css'), {rel=>'stylesheet', type => 'text/CSS'});
|
||||
$style->setLink($url->extras('yui/build/paginator/assets/skins/sam/paginator.css'), {rel=>'stylesheet', type => 'text/CSS'});
|
||||
$style->setScript($url->extras('/yui/build/utilities/utilities.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/json/json-min.js'), {type => 'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/paginator/paginator-min.js'), {type => 'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/datasource/datasource-min.js'), {type => 'text/javascript'});
|
||||
##YUI Datatable
|
||||
$style->setScript($url->extras('yui/build/datatable/datatable-min.js'), {type => 'text/javascript'});
|
||||
##WebGUI YUI AssetHistory
|
||||
$style->setScript( $url->extras( 'yui-webgui/build/i18n/i18n.js' ), {type => 'text/javascript'} );
|
||||
$style->setScript( $url->extras('yui-webgui/build/assetHistory/assetHistory.js'), {type => 'text/javascript'});
|
||||
##Default CSS
|
||||
$style->setRawHeadTags('<style type="text/css"> #paging a { color: #0000de; } #search form { display: inline; } </style>');
|
||||
my $i18n=WebGUI::International->new($session);
|
||||
|
||||
my $output;
|
||||
|
||||
$output .= q|
|
||||
<div class="yui-skin-sam">
|
||||
<div id="search"><form id="keywordSearchForm"><input type="text" name="keywords" id="keywordsField" /><input type="submit" value="|.$i18n->get(364, 'WebGUI').q|" /></form></div>
|
||||
<div id="dynamicdata"></div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
YAHOO.util.Event.onDOMReady( WebGUI.AssetHistory.initManager );
|
||||
</script>
|
||||
|;
|
||||
|
||||
return $ac->render( $output );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
49
lib/WebGUI/Content/PassiveAnalytics.pm
Normal file
49
lib/WebGUI/Content/PassiveAnalytics.pm
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package WebGUI::Content::PassiveAnalytics;
|
||||
|
||||
use strict;
|
||||
use WebGUI::AdminConsole;
|
||||
use WebGUI::Exception;
|
||||
use WebGUI::PassiveAnalytics::Flow;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Content::PassiveAnalytics
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Handle all requests for building and editing Passive Analytic flows.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::Content::PassiveAnalytics;
|
||||
my $output = WebGUI::Content::PassiveAnalytics::handler($session);
|
||||
|
||||
=head1 SUBROUTINES
|
||||
|
||||
These subroutines are available from this package:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 handler ( session )
|
||||
|
||||
The content handler for this package.
|
||||
|
||||
=cut
|
||||
|
||||
sub handler {
|
||||
my ($session) = @_;
|
||||
my $output = undef;
|
||||
return undef unless $session->form->get('op') eq 'passiveAnalytics';
|
||||
my $function = "www_".$session->form->get('func');
|
||||
if ($function ne "www_" && (my $sub = WebGUI::PassiveAnalytics::Flow->can($function))) {
|
||||
$output = $sub->($session);
|
||||
}
|
||||
else {
|
||||
WebGUI::Error::MethodNotFound->throw(error=>"Couldn't call non-existant method $function inside PassiveAnalytics", method=>$function);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -159,11 +159,16 @@ sub toHtml {
|
|||
$url->extras( 'yui-webgui/build/form/textarea.js' ),
|
||||
{ type => 'text/javascript' },
|
||||
);
|
||||
$style->setRawHeadTags( q|
|
||||
<script type="text/javascript">
|
||||
YAHOO.util.Event.onDOMReady( function () { WebGUI.Form.Textarea.setMaxLength() } );
|
||||
</script>
|
||||
| );
|
||||
|
||||
unless ( $self->session->stow->get( 'texareaHeadTagsLoaded' ) ) {
|
||||
$style->setRawHeadTags( q|
|
||||
<script type="text/javascript">
|
||||
YAHOO.util.Event.onDOMReady( function () { WebGUI.Form.Textarea.setMaxLength() } );
|
||||
</script>
|
||||
| );
|
||||
|
||||
$self->session->stow->set( 'texareaHeadTagsLoaded', 1 )
|
||||
}
|
||||
|
||||
if ($self->get("resizable")) {
|
||||
$style->setLink($url->extras("resize.css"), {type=>"text/css", rel=>"stylesheet"});
|
||||
|
|
|
|||
|
|
@ -543,7 +543,8 @@ sub getAllGroupsFor {
|
|||
=head2 getAllUsers ( [ withoutExpired ] )
|
||||
|
||||
Returns an array reference containing a list of users that belong to this group
|
||||
and in any group that belongs to this group.
|
||||
and in any group that belongs to this group. The list is unique, so that each
|
||||
userId is only in it one time.
|
||||
|
||||
=head3 withoutExpired
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ our $HELP = {
|
|||
{ 'name' => 'open.label' },
|
||||
{ 'name' => 'close.label' },
|
||||
{ 'name' => 'closed.label' },
|
||||
{ 'name' => 'collaborationAssetId' },
|
||||
{ 'name' => 'critical.label' },
|
||||
{ 'name' => 'minor.label' },
|
||||
{ 'name' => 'cosmetic.label' },
|
||||
|
|
@ -155,6 +154,7 @@ our $HELP = {
|
|||
{ 'name' => 'sortby.views.url' },
|
||||
{ 'name' => 'sortby.replies.url' },
|
||||
{ 'name' => 'sortby.rating.url' }
|
||||
{ 'name' => 'collaborationAssetId' },
|
||||
],
|
||||
related => [
|
||||
{ tag => 'collaboration template labels',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ our $HELP = {
|
|||
},
|
||||
],
|
||||
variables => [
|
||||
{ 'name' => 'canEdit' },
|
||||
{ 'name' => 'editUrl' },
|
||||
{ 'name' => 'canApprove' },
|
||||
{ 'name' => 'approveOrDenyUrl' },
|
||||
{ 'name' => 'screenshots' },
|
||||
{ 'name' => 'emailForm' },
|
||||
{ 'name' => 'emailSent' },
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ sub process {
|
|||
|
||||
my $db = $session->db;
|
||||
my $i18n = WebGUI::International->new($session);
|
||||
my ($count) = $db->quickArray("select count(*) from inbox where userId=? and status='unread'",[$session->user->userId]);
|
||||
my $count = WebGUI::Inbox->new($session)->getUnreadMessageCount;
|
||||
my $output = "";
|
||||
|
||||
if($count > 0) {
|
||||
|
|
|
|||
|
|
@ -485,6 +485,7 @@ sub definition {
|
|||
groupIdAdminGraphics
|
||||
groupIdAdminGroup
|
||||
groupIdAdminGroupAdmin
|
||||
groupIdAdminHistory
|
||||
groupIdAdminHelp
|
||||
groupIdAdminLDAPLink
|
||||
groupIdAdminLoginHistory
|
||||
|
|
|
|||
458
lib/WebGUI/PassiveAnalytics/Flow.pm
Normal file
458
lib/WebGUI/PassiveAnalytics/Flow.pm
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
package WebGUI::PassiveAnalytics::Flow;
|
||||
|
||||
use strict;
|
||||
use Tie::IxHash;
|
||||
use WebGUI::AdminConsole;
|
||||
use WebGUI::HTMLForm;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Pluggable;
|
||||
use WebGUI::PassiveAnalytics::Rule;
|
||||
use WebGUI::Utility;
|
||||
use WebGUI::HTMLForm;
|
||||
use WebGUI::Workflow;
|
||||
use WebGUI::Workflow::Instance;
|
||||
use WebGUI::User;
|
||||
use WebGUI::Text;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::PassiveAnalytics::Flow
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Web interface for making sets of rules for doing passive analytics, and
|
||||
running them.
|
||||
|
||||
=cut
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 analysisActive ( session )
|
||||
|
||||
Returns true if an instance of the PassiveAnalytics workflow is active.
|
||||
|
||||
=cut
|
||||
|
||||
sub analysisActive {
|
||||
my $session = shift;
|
||||
my ($running, $startDate, $endDate, $userId) = $session->db->quickArray(q!select running, startDate, endDate, userId from passiveAnalyticsStatus!);
|
||||
if (wantarray) {
|
||||
return $running, $startDate, $endDate, WebGUI::User->new($session, $userId);
|
||||
}
|
||||
return $running;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 canView ( session [, user] )
|
||||
|
||||
Returns true if the user can administrate this operation. user defaults to
|
||||
the current user.
|
||||
|
||||
=cut
|
||||
|
||||
sub canView {
|
||||
my $session = shift;
|
||||
my $user = shift || $session->user;
|
||||
return $user->isInGroup( 3 );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 exportSomething ( session, sth, filename )
|
||||
|
||||
Generates CSV data from the supplied statement handle and generates
|
||||
a temporary WebGUI::Storage object containing that data in the requested
|
||||
filename.
|
||||
|
||||
This subroutine also does a setRedirect to the URL of the file in
|
||||
the storage object.
|
||||
|
||||
=head3 session
|
||||
|
||||
Session variable, to set the http redirect correctly.
|
||||
|
||||
=head3 sth
|
||||
|
||||
Statement handle for reading data and getting column names
|
||||
|
||||
=head3 filename
|
||||
|
||||
The name of the file to create inside the storage object.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportSomething {
|
||||
my ($session, $sth, $filename) = @_;
|
||||
my $storage = WebGUI::Storage->createTemp($session);
|
||||
my @columns = $sth->getColumnNames;
|
||||
my $csvData = WebGUI::Text::joinCSV( @columns ). "\n";
|
||||
while (my $row = $sth->hashRef()) {
|
||||
my @row = @{ $row }{@columns};
|
||||
$csvData .= WebGUI::Text::joinCSV(@row) . "\n";
|
||||
}
|
||||
$storage->addFileFromScalar($filename, $csvData);
|
||||
$session->http->setRedirect($storage->getUrl($filename));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_deleteRule ( )
|
||||
|
||||
Deletes an activity from a workflow.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_deleteRule {
|
||||
my $session = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
my $rule = WebGUI::PassiveAnalytics::Rule->new($session, $session->form->get("ruleId"));
|
||||
if (defined $rule) {
|
||||
$rule->delete;
|
||||
}
|
||||
return www_editRuleflow($session);
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------
|
||||
|
||||
=head2 www_demoteRule ( session )
|
||||
|
||||
Moves a Rule down one position in the execution order.
|
||||
|
||||
=head3 session
|
||||
|
||||
A reference to the current session.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_demoteRule {
|
||||
my $session = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
my $rule = WebGUI::PassiveAnalytics::Rule->new($session, $session->form->get("ruleId"));
|
||||
if (defined $rule) {
|
||||
$rule->demote;
|
||||
}
|
||||
return www_editRuleflow($session);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editRuleflow ( session )
|
||||
|
||||
Configure a set of analyses to run on the passive logs. The analysis is destructive.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editRuleflow {
|
||||
my $session = shift;
|
||||
my $error = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
my ($running, $startDate, $endDate, $user) = analysisActive($session);
|
||||
if ($error) {
|
||||
$error = qq|<div class="error">$error</div>\n|;
|
||||
}
|
||||
elsif (!$running) {
|
||||
$error = qq|<div class="error">Passive Analytics analysis completed on $endDate</div>\n|;
|
||||
}
|
||||
my $i18n = WebGUI::International->new($session, "PassiveAnalytics");
|
||||
my $addmenu = '<div style="float: left; width: 200px; font-size: 11px;">';
|
||||
$addmenu .= sprintf '<a href="%s">%s</a>',
|
||||
$session->url->page('op=passiveAnalytics;func=editRule'),
|
||||
$i18n->get('Add a bucket');
|
||||
$addmenu .= '</div>';
|
||||
my $f = WebGUI::HTMLForm->new($session);
|
||||
$f->hidden(
|
||||
name=>'op',
|
||||
value=>'passiveAnalytics'
|
||||
);
|
||||
$f->hidden(
|
||||
name=>'func',
|
||||
value=>'editRuleflowSave'
|
||||
);
|
||||
$f->integer(
|
||||
name => 'pauseInterval',
|
||||
value => $session->form->get('pauseInterval') || $session->setting->get('passiveAnalyticsInterval') || 300,
|
||||
label => $i18n->get('pause interval'),
|
||||
hoverHelp => $i18n->get('pause interval help'),
|
||||
);
|
||||
if ($running) {
|
||||
$f->raw(sprintf <<EOD, $startDate, $user->username);
|
||||
<tr><td colspan="2">Passive Analytics analysis is currently active. Analysis was begun at %s by %s</td></tr>
|
||||
EOD
|
||||
}
|
||||
else {
|
||||
$f->submit(value => $i18n->get('Begin analysis'));
|
||||
}
|
||||
my $steps = '<table class="content"><tbody>';
|
||||
my $getARule = WebGUI::PassiveAnalytics::Rule->getAllIterator($session);
|
||||
my $icon = $session->icon;
|
||||
while (my $rule = $getARule->()) {
|
||||
my $id = $rule->getId;
|
||||
my $bucket = $rule->get('bucketName');
|
||||
$steps .= '<tr><td>'
|
||||
. $icon->delete( 'op=passiveAnalytics;func=deleteRule;ruleId='.$id, undef, $i18n->get('confirm delete rule'))
|
||||
. $icon->edit( 'op=passiveAnalytics;func=editRule;ruleId='.$id)
|
||||
. $icon->moveDown('op=passiveAnalytics;func=demoteRule;ruleId='.$id)
|
||||
. $icon->moveUp( 'op=passiveAnalytics;func=promoteRule;ruleId='.$id)
|
||||
. '</td><td>'.$bucket.'</td></tr>';
|
||||
|
||||
}
|
||||
$steps .= '<tr><td> </td><td>Other</td></tbody></table><div style="clear: both;"></div>';
|
||||
my $ac = WebGUI::AdminConsole->new($session,'passiveAnalytics');
|
||||
$ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=settings'), $i18n->get('Passive Analytics Settings'));
|
||||
if (!$running) {
|
||||
$ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=exportBucketData'), $i18n->get('Export bucket data'));
|
||||
$ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=exportDeltaData'), $i18n->get('Export delta data'));
|
||||
$ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=exportLogs'), $i18n->get('Export raw logs'));
|
||||
}
|
||||
return $ac->render($error.$f->print.$addmenu.$steps, 'Passive Analytics');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editRuleflowSave ( )
|
||||
|
||||
Saves the results of www_editRuleflow()
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editRuleflowSave {
|
||||
my $session = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
return www_editRuleflow($session, 'Passive Analytics is already active. Please do not try to subvert the UI in the future')
|
||||
if analysisActive($session);
|
||||
my $workflow = WebGUI::Workflow->new($session, 'PassiveAnalytics000001');
|
||||
return www_editRuleflow($session, "The Passive Analytics workflow has been deleted. Please contact an Administrator immediately.") unless defined $workflow;
|
||||
my $delta = $session->form->process('pauseInterval','integer');
|
||||
my $activities = $workflow->getActivities();
|
||||
##Note, they're in order, and the order is known.
|
||||
$activities->[0]->set('deltaInterval', $delta);
|
||||
$activities->[1]->set('userId', $session->user->userId);
|
||||
my $instance = WebGUI::Workflow::Instance->create($session, {
|
||||
workflowId => $workflow->getId,
|
||||
priority => 1,
|
||||
});
|
||||
if (!defined $instance) {
|
||||
return www_editRuleflow($session, "A Passive Analytics analysis is currently running.") if $session->stow->get('singletonWorkflowClash');
|
||||
return www_editRuleflow($session, "Error creating the workflow instance.");
|
||||
}
|
||||
$instance->start('skipRealtime');
|
||||
$session->db->write('update passiveAnalyticsStatus set startDate=NOW(), userId=?, endDate=?, running=1', [$session->user->userId, '']);
|
||||
return www_editRuleflow($session);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editRule ( )
|
||||
|
||||
Displays a form to edit the properties rule.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editRule {
|
||||
my ($session, $error) = @_;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
|
||||
if ($error) {
|
||||
$error = qq|<div class="error">$error</div>\n|;
|
||||
}
|
||||
##Make a PassiveAnalytics rule to use to populate the form.
|
||||
my $ruleId = $session->form->get('ruleId');
|
||||
my $rule;
|
||||
if ($ruleId) {
|
||||
$rule = WebGUI::PassiveAnalytics::Rule->new($session, $ruleId);
|
||||
}
|
||||
else {
|
||||
##We need a temporary rule so that we can call dynamicForm, below
|
||||
$ruleId = 'new';
|
||||
$rule = WebGUI::PassiveAnalytics::Rule->create($session, {});
|
||||
}
|
||||
|
||||
##Build the form
|
||||
my $form = WebGUI::HTMLForm->new($session);
|
||||
$form->hidden( name=>"op", value=>"passiveAnalytics");
|
||||
$form->hidden( name=>"func", value=>"editRuleSave");
|
||||
$form->hidden( name=>"ruleId", value=>$ruleId);
|
||||
$form->dynamicForm([WebGUI::PassiveAnalytics::Rule->crud_definition($session)], 'properties', $rule);
|
||||
$form->submit;
|
||||
|
||||
my $i18n = WebGUI::International->new($session, 'PassiveAnalytics');
|
||||
my $ac = WebGUI::AdminConsole->new($session,'passiveAnalytics');
|
||||
$ac->addSubmenuItem($session->url->page("op=passiveAnalytics;func=editRuleflow"), $i18n->get("manage ruleset"));
|
||||
if ($ruleId eq 'new') {
|
||||
$rule->delete;
|
||||
}
|
||||
return $ac->render($error.$form->print,$i18n->get('Edit Rule'));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editRuleSave ( )
|
||||
|
||||
Saves the results of www_editRule().
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editRuleSave {
|
||||
my $session = shift;
|
||||
my $form = $session->form;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
my $regexp = $form->get('regexp');
|
||||
eval {
|
||||
'fooBarBaz' =~ qr/$regexp/;
|
||||
};
|
||||
if ($@) {
|
||||
my $error = $@;
|
||||
$error =~ s/at \S+?\.pm line \d+.*$//;
|
||||
my $i18n = WebGUI::International->new($session, 'PassiveAnalytics');
|
||||
$error = join ' ', $i18n->get('Regular Expression Error:'), $error;
|
||||
return www_editRule($session, $error);
|
||||
}
|
||||
my $ruleId = $form->get('ruleId');
|
||||
my $rule;
|
||||
if ($ruleId eq 'new') {
|
||||
$rule = WebGUI::PassiveAnalytics::Rule->create($session, {});
|
||||
}
|
||||
else {
|
||||
$rule = WebGUI::PassiveAnalytics::Rule->new($session, $ruleId);
|
||||
}
|
||||
$rule->updateFromFormPost if $rule;
|
||||
return www_editRuleflow($session);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_exportBucketData ( )
|
||||
|
||||
Dump the contents of the bucket log.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_exportBucketData {
|
||||
my ($session) = @_;
|
||||
my $bucket = $session->db->read('select * from bucketLog order by userId, Bucket, timeStamp');
|
||||
exportSomething($session, $bucket, 'bucketData.csv');
|
||||
return "redirect";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_exportDeltaData ( )
|
||||
|
||||
Dump the contents of the delta log.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_exportDeltaData {
|
||||
my ($session) = @_;
|
||||
my $delta = $session->db->read('select * from deltaLog order by userId, timeStamp');
|
||||
exportSomething($session, $delta, 'deltaData.csv');
|
||||
return "redirect";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_exportLogs ( )
|
||||
|
||||
Dump the contents of the raw log.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_exportLogs {
|
||||
my ($session) = @_;
|
||||
my $raw = $session->db->read('select * from passiveLog order by userId, timeStamp');
|
||||
exportSomething($session, $raw, 'passiveData.csv');
|
||||
return "redirect";
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------
|
||||
|
||||
=head2 www_promoteRule ( session )
|
||||
|
||||
Moves a rule up one position in the execution order.
|
||||
|
||||
=head3 session
|
||||
|
||||
A reference to the current session.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_promoteRule {
|
||||
my $session = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
my $rule = WebGUI::PassiveAnalytics::Rule->new($session, $session->form->get("ruleId"));
|
||||
if (defined $rule) {
|
||||
$rule->promote;
|
||||
}
|
||||
return www_editRuleflow($session);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_settings ( session )
|
||||
|
||||
Configure Passive Analytics settings.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_settings {
|
||||
my $session = shift;
|
||||
my $error = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
if ($error) {
|
||||
$error = qq|<div class="error">$error</div>\n|;
|
||||
}
|
||||
my $i18n = WebGUI::International->new($session, "PassiveAnalytics");
|
||||
my $f = WebGUI::HTMLForm->new($session);
|
||||
$f->hidden(
|
||||
name=>'op',
|
||||
value=>'passiveAnalytics'
|
||||
);
|
||||
$f->hidden(
|
||||
name=>'func',
|
||||
value=>'settingsSave'
|
||||
);
|
||||
$f->integer(
|
||||
name => 'pauseInterval',
|
||||
value => $session->form->get('pauseInterval') || $session->setting->get('passiveAnalyticsInterval') || 300,
|
||||
label => $i18n->get('default pause interval'),
|
||||
hoverHelp => $i18n->get('default pause interval help'),
|
||||
);
|
||||
$f->yesNo(
|
||||
name => 'deleteDelta',
|
||||
value => $session->form->get('deleteDelta') || $session->setting->get('passiveAnalyticsDeleteDelta') || 0,
|
||||
label => $i18n->get('Delete Delta Table?'),
|
||||
hoverHelp => $i18n->get('Delete Delta Table? help'),
|
||||
);
|
||||
$f->yesNo(
|
||||
name => 'enabled',
|
||||
value => $session->form->get('enabled') || $session->setting->get('passiveAnalyticsEnabled') || 0,
|
||||
label => $i18n->get('Enabled?'),
|
||||
hoverHelp => $i18n->get('Enabled? help'),
|
||||
);
|
||||
$f->submit();
|
||||
my $ac = WebGUI::AdminConsole->new($session,'passiveAnalytics');
|
||||
$ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=editRuleflow'), $i18n->get('Passive Analytics'));
|
||||
return $ac->render($error.$f->print, 'Passive Analytics Settings');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_settingsSave ( session )
|
||||
|
||||
Save Passive Analytics settings.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_settingsSave {
|
||||
my $session = shift;
|
||||
return $session->privilege->insufficient() unless canView($session);
|
||||
my $form = $session->form;
|
||||
$session->setting->set('passiveAnalyticsInterval', $form->process('pauseInterval', 'integer'));
|
||||
$session->setting->set('passiveAnalyticsDeleteDelta', $form->process('deleteDelta', 'yesNo' ));
|
||||
$session->setting->set('passiveAnalyticsEnabled', $form->process('enabled', 'yesNo' ));
|
||||
return www_settings($session);
|
||||
}
|
||||
|
||||
1;
|
||||
47
lib/WebGUI/PassiveAnalytics/Logging.pm
Normal file
47
lib/WebGUI/PassiveAnalytics/Logging.pm
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package WebGUI::PassiveAnalytics::Logging;
|
||||
|
||||
use strict;
|
||||
use WebGUI::Session;
|
||||
use WebGUI::Asset;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::PassiveAnalytics::Logging
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Encapsulate all logging functions in here.
|
||||
|
||||
=cut
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 log ( session, asset )
|
||||
|
||||
Log Passive Analytics data to the db.
|
||||
|
||||
=head3 session
|
||||
|
||||
A session variable.
|
||||
|
||||
=head3 asset
|
||||
|
||||
The asset to log.
|
||||
|
||||
=cut
|
||||
|
||||
sub log {
|
||||
my ($session, $asset) = @_;
|
||||
return unless $session->setting->get('passiveAnalyticsEnabled');
|
||||
my $assetClass = $asset->get('className');
|
||||
$assetClass =~ s/^WebGUI::Asset:://;
|
||||
if ( $assetClass ne 'Snippet'
|
||||
&& substr($assetClass,0,4) ne 'File') {
|
||||
$session->db->write(
|
||||
q|INSERT INTO `passiveLog` (userId, sessionId, assetId, timestamp, url) VALUES (?,?,?,?,?)|,
|
||||
[ $session->user->userId, $session->getId, $asset->getId, time(), $session->request->unparsed_uri,]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
92
lib/WebGUI/PassiveAnalytics/Rule.pm
Normal file
92
lib/WebGUI/PassiveAnalytics/Rule.pm
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package WebGUI::PassiveAnalytics::Rule;
|
||||
|
||||
use base qw/WebGUI::Crud/;
|
||||
use WebGUI::International;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::PassiveAnalytics::Rule;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Base class for rules that are used to analyze the Passive Analytics log.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 crud_definition ( )
|
||||
|
||||
WebGUI::Crud definition for this class.
|
||||
|
||||
=head3 tableName
|
||||
|
||||
analyticRule.
|
||||
|
||||
=head3 tableKey
|
||||
|
||||
ruleId
|
||||
|
||||
=head3 sequenceKey
|
||||
|
||||
None. There is only 1 sequence of rules for a site.
|
||||
|
||||
=head3 properties
|
||||
|
||||
=head4 bucketName
|
||||
|
||||
The name of a bucket to hold results for this rule.
|
||||
|
||||
=head4 rules
|
||||
|
||||
JSON blob with configuration data for the individual rules.
|
||||
|
||||
=cut
|
||||
|
||||
sub crud_definition {
|
||||
my ($class, $session) = @_;
|
||||
my $definition = $class->SUPER::crud_definition($session);
|
||||
$definition->{tableName} = 'analyticRule';
|
||||
$definition->{tableKey} = 'ruleId';
|
||||
$definition->{sequenceKey} = '';
|
||||
my $properties = $definition->{properties};
|
||||
my $i18n = WebGUI::International->new($session);
|
||||
$properties->{bucketName} = {
|
||||
fieldType => 'text',
|
||||
label => $i18n->get('Bucket Name','PassiveAnalytics'),
|
||||
hoverHelp => $i18n->get('Bucket Name help','PassiveAnalytics'),
|
||||
defaultValue => '',
|
||||
};
|
||||
$properties->{regexp} = {
|
||||
fieldType => 'text',
|
||||
label => $i18n->get('regexp','PassiveAnalytics'),
|
||||
hoverHelp => $i18n->get('regexp help','PassiveAnalytics'),
|
||||
defaultValue => '.+',
|
||||
};
|
||||
return $definition;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 matchesBucket ( $logLine )
|
||||
|
||||
Executes the rule to determine if a log file entry matches the rule.
|
||||
|
||||
=head3 $logLine
|
||||
|
||||
A hashref of information from 1 line of the logs.
|
||||
|
||||
=cut
|
||||
|
||||
sub matchesBucket {
|
||||
my ($self, $logLine) = @_;
|
||||
my $regexp = $self->get('regexp');
|
||||
return $logLine->{url} =~ m/$regexp/;
|
||||
}
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
|
|
@ -220,12 +220,13 @@ sub buildHashRef {
|
|||
|
||||
=head2 buildArrayRefOfHashRefs ( sql )
|
||||
|
||||
Builds an array reference of hash references of data
|
||||
from a series of rows. Useful for returning many rows at once.
|
||||
Builds an array reference of hash references of data from a series of rows.
|
||||
Useful for returning many rows at once. Each element of the returned array
|
||||
reference is a hash of column names to column values.
|
||||
|
||||
=head3 sql
|
||||
|
||||
An SQL query. The query must select at least two columns of data, the first being the key for the hash, the second being the value. If the query selects more than two columns, then the last column will be the value and the remaining columns will be joined together by a colon ":" to form a complex key. If the query selects only one column, then the key and the value will be the same.
|
||||
An SQL query.
|
||||
|
||||
=head3 params
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ An address object's unique id.
|
|||
|
||||
sub getAddress {
|
||||
my ($self, $addressId) = @_;
|
||||
my $id = ref $self;
|
||||
my $id = id $self;
|
||||
unless (exists $addressCache{$id}{$addressId}) {
|
||||
$addressCache{$id}{$addressId} = WebGUI::Shop::Address->new($self, $addressId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ sub getAdminConsole {
|
|||
$ac->addSubmenuItem($url->page("shop=ship;method=manage"), $i18n->get("shipping methods"));
|
||||
$ac->addSubmenuItem($url->page("shop=transaction;method=manage"), $i18n->get("transactions"));
|
||||
$ac->addSubmenuItem($url->page("shop=vendor;method=manage"), $i18n->get("vendors"));
|
||||
$ac->addSubmenuItem($url->page("shop=vendor;method=managePayouts"), $i18n->get("vendor payouts"));
|
||||
$ac->addSubmenuItem($url->page("shop=credit;method=manage"), $i18n->get("in shop credit"));
|
||||
return $ac;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ Returns a reference to the address book for the user who's cart this is.
|
|||
|
||||
sub getAddressBook {
|
||||
my $self = shift;
|
||||
my $id = ref $self;
|
||||
my $id = id $self;
|
||||
unless (exists $addressBookCache{$id}) {
|
||||
$addressBookCache{$id} = WebGUI::Shop::AddressBook->newBySession($self->session);
|
||||
}
|
||||
|
|
@ -297,7 +297,6 @@ sub getItem {
|
|||
unless (defined $itemId && $itemId =~ m/^[A-Za-z0-9_-]{22}$/) {
|
||||
WebGUI::Error::InvalidParam->throw(error=>"Need an itemId.");
|
||||
}
|
||||
my $id = ref $self;
|
||||
my $item = WebGUI::Shop::CartItem->new($self, $itemId);
|
||||
return $item;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,6 @@ Returns an instanciated WebGUI::Asset::Sku object for this cart item.
|
|||
|
||||
sub getSku {
|
||||
my ($self) = @_;
|
||||
my $id = ref $self;
|
||||
my $asset = '';
|
||||
$asset = WebGUI::Asset->newByDynamicClass($self->cart->session, $self->get("assetId"));
|
||||
$asset->applyOptions($self->get("options"));
|
||||
|
|
|
|||
|
|
@ -267,11 +267,14 @@ sub update {
|
|||
if (exists $newProperties->{item}) {
|
||||
my $item = $newProperties->{ item };
|
||||
my $sku = $item->getSku;
|
||||
$newProperties->{ options } = $sku->getOptions;
|
||||
$newProperties->{ assetId } = $sku->getId;
|
||||
$newProperties->{ price } = $sku->getPrice;
|
||||
$newProperties->{ configuredTitle } = $item->get('configuredTitle');
|
||||
$newProperties->{ quantity } = $item->get('quantity');
|
||||
$newProperties->{ options } = $sku->getOptions;
|
||||
$newProperties->{ assetId } = $sku->getId;
|
||||
$newProperties->{ price } = $sku->getPrice;
|
||||
$newProperties->{ configuredTitle } = $item->get('configuredTitle');
|
||||
$newProperties->{ quantity } = $item->get('quantity');
|
||||
$newProperties->{ vendorId } = $sku->getVendorId;
|
||||
$newProperties->{ vendorPayoutAmount } = sprintf '%.2f', $sku->getVendorPayout * $item->get('quantity');
|
||||
|
||||
my $address = $item->getShippingAddress;
|
||||
$newProperties->{ shippingAddressId } = $address->getId;
|
||||
$newProperties->{ shippingAddressName } = $address->get('name');
|
||||
|
|
@ -289,7 +292,8 @@ sub update {
|
|||
}
|
||||
my @fields = (qw(assetId configuredTitle options shippingAddressId shippingTrackingNumber orderStatus
|
||||
shippingName shippingAddress1 shippingAddress2 shippingAddress3 shippingCity shippingState
|
||||
shippingCountry shippingCode shippingPhoneNumber quantity price vendorId));
|
||||
shippingCountry shippingCode shippingPhoneNumber quantity price vendorId
|
||||
vendorPayoutStatus vendorPayoutAmount));
|
||||
foreach my $field (@fields) {
|
||||
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use Class::InsideOut qw{ :std };
|
|||
use WebGUI::Shop::Admin;
|
||||
use WebGUI::Exception::Shop;
|
||||
use WebGUI::International;
|
||||
|
||||
use WebGUI::Utility qw{ isIn };
|
||||
use List::Util qw{ sum };
|
||||
use JSON qw{ encode_json };
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -406,4 +408,225 @@ sub www_manage {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPayoutTotals ( )
|
||||
|
||||
Returns a hash ref, containing the payout details for this vendor. The keys in the hash are:
|
||||
|
||||
=head3 paid
|
||||
|
||||
The amount of money already transfered to the vendor.
|
||||
|
||||
=head3 scheduled
|
||||
|
||||
The amount of money scheduled to be transfered to the vendor.
|
||||
|
||||
=head3 notPaid
|
||||
|
||||
The amount of money that is yet to be scheduled for payment to the vendor.
|
||||
|
||||
=head3 total
|
||||
|
||||
The sum of these three values.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPayoutTotals {
|
||||
my $self = shift;
|
||||
|
||||
my %totals = $self->session->db->buildHash(
|
||||
'select vendorPayoutStatus, sum(vendorPayoutAmount) as amount from transactionItem '
|
||||
.'where vendorId=? group by vendorPayoutStatus ',
|
||||
[ $self->getId ]
|
||||
);
|
||||
|
||||
# Format the payout categories and calc the total those.
|
||||
%totals =
|
||||
map { lcfirst $_ => sprintf '%.2f', $totals{ $_ } }
|
||||
qw( Paid Scheduled NotPaid );
|
||||
$totals{ total } = sprintf '%.2f', sum values %totals;
|
||||
|
||||
return \%totals;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_submitScheduledPayouts ()
|
||||
|
||||
Sets the vendorPayoutStatus flag of scheduled payments to 'Paid'.
|
||||
|
||||
NOTE: This method does no payments at all. In the future this method should trigger some automated payout
|
||||
mechanism.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_submitScheduledPayouts {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
$session->db->write(
|
||||
q{ update transactionItem set vendorPayoutStatus = 'Paid' where vendorPayoutStatus = 'Scheduled' }
|
||||
);
|
||||
|
||||
return $class->www_managePayouts( $session );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_setPayoutStatus ( )
|
||||
|
||||
Sets the vendorPayoutStatus flag for each transaction passed by the form param 'itemId'. The new status is passed
|
||||
by the form param 'status'. Status can either be 'NotPaid' or 'Scheduled' and may only be applied on items that do
|
||||
not have their vendorPayoutStatus set to 'Paid'.
|
||||
|
||||
Returns the status to which the item(s) are set.
|
||||
=cut
|
||||
|
||||
sub www_setPayoutStatus {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my @itemIds = $session->form->process('itemId');
|
||||
my $status = $session->form->process('status');
|
||||
return "error: wrong status [$status]" unless isIn( $status, qw{ NotPaid Scheduled } );
|
||||
|
||||
foreach my $itemId (@itemIds) {
|
||||
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction( $session, $itemId );
|
||||
return "error: invalid transactionItemId [$itemId]" unless $item;
|
||||
return "error: cannot change status of a Paid item" if $item->get('vendorPayoutStatus') eq 'Paid';
|
||||
|
||||
$item->update({ vendorPayoutStatus => $status });
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_vendorTotalsAsJSON ( )
|
||||
|
||||
Returns a JSON string containing all vendors and their payout details. If a vendor id is passed through form param
|
||||
'vendorId' only results for that vendor will be returned.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_vendorTotalsAsJSON {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my $vendorId = $session->form->process('vendorId');
|
||||
my ($vendorPayoutData, @placeholders);
|
||||
|
||||
my @sql;
|
||||
push @sql,
|
||||
'select vendorId, vendorPayoutStatus, sum(vendorPayoutAmount) as total from transactionItem';
|
||||
push @sql, ' where vendorId=? ' if $vendorId;
|
||||
push @sql, ' group by vendorId, vendorPayoutStatus ';
|
||||
|
||||
push @placeholders, $vendorId if $vendorId;
|
||||
|
||||
my $sth = $session->db->read( join( ' ', @sql) , \@placeholders );
|
||||
while (my $row = $sth->hashRef) {
|
||||
$vendorPayoutData->{ $row->{vendorId} }->{ $row->{vendorPayoutStatus} } = $row->{total};
|
||||
}
|
||||
$sth->finish;
|
||||
|
||||
my @dataset;
|
||||
foreach my $vendorId (keys %{ $vendorPayoutData }) {
|
||||
my $vendor = WebGUI::Shop::Vendor->new( $session, $vendorId );
|
||||
|
||||
push @dataset, {
|
||||
%{ $vendor->get },
|
||||
%{ $vendorPayoutData->{ $vendorId } },
|
||||
}
|
||||
}
|
||||
|
||||
$session->http->setMimeType( 'application/json' );
|
||||
return JSON::to_json( { vendors => \@dataset } );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_payoutDataAsJSON {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my $vendorId = $session->form->process('vendorId');
|
||||
my $startIndex = $session->form->process('startIndex');
|
||||
my $rowsPerPage = $session->form->process('results') || 100;
|
||||
my $pageNumber = int( $startIndex / $rowsPerPage ) + 1;
|
||||
|
||||
my $sql =
|
||||
"select t1.* from transactionItem as t1 join transaction as t2 on t1.transactionId=t2.transactionId "
|
||||
." where vendorId=? and vendorPayoutAmount > 0 and vendorPayoutStatus <> 'Paid' order by t2.orderNumber";
|
||||
my $placeholders = [ $vendorId ];
|
||||
|
||||
my $paginator = WebGUI::Paginator->new( $session, '', $rowsPerPage, '', $pageNumber );
|
||||
$paginator->setDataByQuery( $sql, undef, 0, $placeholders );
|
||||
|
||||
my $data = {
|
||||
totalRecords => $paginator->getRowCount,
|
||||
results => $paginator->getPageData,
|
||||
};
|
||||
|
||||
$session->http->setMimeType( 'application/json' );
|
||||
|
||||
return JSON::to_json( $data );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_managePayouts {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
# Load the required YUI stuff.
|
||||
$session->style->setLink('/extras/yui/build/paginator/assets/skins/sam/paginator.css', {type=>'text/css', rel=>'stylesheet'});
|
||||
$session->style->setLink('/extras/yui/build/datatable/assets/skins/sam/datatable.css', {type=>'text/css', rel=>'stylesheet'});
|
||||
$session->style->setLink('/extras/yui/build/button/assets/skins/sam/button.css', {type=>'text/css', rel=>'stylesheet'});
|
||||
$session->style->setScript('/extras/yui/build/yahoo-dom-event/yahoo-dom-event.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/element/element-beta-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/connection/connection-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/json/json-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/paginator/paginator-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/datasource/datasource.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/datatable/datatable-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/button/button-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/VendorPayout/vendorPayout.js', {type=>'text/javascript'});
|
||||
|
||||
# Add css for scheduled payout highlighting
|
||||
$session->style->setRawHeadTags(<<CSS);
|
||||
<style type="text/css">
|
||||
.yui-skin-sam .yui-dt tr.scheduled,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc {
|
||||
background-color : #080;
|
||||
color : #fff;
|
||||
}
|
||||
</style>
|
||||
CSS
|
||||
|
||||
my $output = q{<div id="vendorPayoutContainer" class="yui-skin-sam"></div>}
|
||||
.q{<script type="text/javascript">var vp = new WebGUI.VendorPayout( 'vendorPayoutContainer' );</script>};
|
||||
|
||||
my $console = WebGUI::Shop::Admin->new($session)->getAdminConsole;
|
||||
return $console->render($output, 'Vendor payout'); #$i18n->get("vendors"));
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
153
lib/WebGUI/Workflow/Activity/BucketPassiveAnalytics.pm
Normal file
153
lib/WebGUI/Workflow/Activity/BucketPassiveAnalytics.pm
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
package WebGUI::Workflow::Activity::BucketPassiveAnalytics;
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::PassiveAnalytics::Rule;
|
||||
use WebGUI::Inbox;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::BucketPassiveAnalytics
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Run through a set of rules to figure out how to classify log file entries.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "PassiveAnalytics");
|
||||
push( @{$definition}, {
|
||||
name=>$i18n->get("Bucket Passive Analytics"),
|
||||
properties=> {
|
||||
notifyUser => {
|
||||
fieldType => 'user',
|
||||
label => $i18n->get('User'),
|
||||
hoverHelp => $i18n->get('User help'),
|
||||
defaultValue => $session->user->userId,
|
||||
},
|
||||
},
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( [ object ] )
|
||||
|
||||
Analyze the deltaLog table, and generate the bucketLog table.
|
||||
|
||||
=head3 notes
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my ($self, undef, $instance) = @_;
|
||||
my $session = $self->session;
|
||||
my $endTime = time() + $self->getTTL;
|
||||
my $expired = 0;
|
||||
|
||||
##Load all the rules into an array
|
||||
my @rules = ();
|
||||
my $getARule = WebGUI::PassiveAnalytics::Rule->getAllIterator($session);
|
||||
while (my $rule = $getARule->()) {
|
||||
my $regexp = $rule->get('regexp');
|
||||
push @rules, [ $rule->get('bucketName'), qr/$regexp/];
|
||||
}
|
||||
|
||||
##Get the index stored from the last invocation of the Activity. If this is
|
||||
##the first run, then clear out the table.
|
||||
my $logIndex = $instance->getScratch('lastPassiveLogIndex') || 0;
|
||||
if ($logIndex == 0) {
|
||||
$session->db->write('delete from bucketLog');
|
||||
}
|
||||
my %bucketCache = ();
|
||||
|
||||
##Configure all the SQL
|
||||
my $deltaSql = <<"EOSQL1";
|
||||
select userId, assetId, url, delta, from_unixtime(timeStamp) as stamp
|
||||
from deltaLog order by timestamp limit $logIndex, 1234567890
|
||||
EOSQL1
|
||||
my $deltaSth = $session->db->read($deltaSql);
|
||||
my $bucketSth = $session->db->prepare('insert into bucketLog (userId, Bucket, duration, timeStamp) VALUES (?,?,?,?)');
|
||||
|
||||
##Walk through the log file entries, one by one. Run each entry against
|
||||
##all the rules until 1 matches. If it doesn't match any rule, then bin it
|
||||
##into the "Other" bucket.
|
||||
DELTA_ENTRY: while (my $entry = $deltaSth->hashRef()) {
|
||||
++$logIndex;
|
||||
my $bucketFound = 0;
|
||||
my $url = $entry->{url};
|
||||
if (exists $bucketCache{$url}) {
|
||||
$bucketSth->execute([$entry->{userId}, $bucketCache{$url}, $entry->{delta}, $entry->{stamp}]);
|
||||
}
|
||||
else {
|
||||
RULE: foreach my $rule (@rules) {
|
||||
next RULE unless $url =~ $rule->[1];
|
||||
|
||||
# Into the bucket she goes..
|
||||
$bucketCache{$url} = $rule->[0];
|
||||
$bucketSth->execute([$entry->{userId}, $rule->[0], $entry->{delta}, $entry->{stamp}]);
|
||||
$bucketFound = 1;
|
||||
last RULE;
|
||||
}
|
||||
if (!$bucketFound) {
|
||||
$bucketCache{$url} = 'Other';
|
||||
$bucketSth->execute([$entry->{userId}, 'Other', $entry->{delta}, $entry->{stamp}]);
|
||||
}
|
||||
}
|
||||
if (time() > $endTime) {
|
||||
$expired = 1;
|
||||
last DELTA_ENTRY;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expired) {
|
||||
$instance->setScratch('logIndex', $logIndex);
|
||||
return $self->WAITING(1);
|
||||
}
|
||||
my $message = 'Passive analytics is done.';
|
||||
if ($session->setting->get('passiveAnalyticsDeleteDelta')) {
|
||||
$session->log->info('Clearing Passive Analytics delta log');
|
||||
$session->db->write('delete from deltaLog');
|
||||
$message .= ' The delta log has been cleaned up.';
|
||||
}
|
||||
##If userId was set to 0, do not send any emails.
|
||||
if ($self->get('userId')) {
|
||||
my $inbox = WebGUI::Inbox->new($self->session);
|
||||
$inbox->addMessage({
|
||||
status => 'unread',
|
||||
subject => 'Passive analytics is done',
|
||||
userId => $self->get('userId'),
|
||||
message => $message,
|
||||
});
|
||||
}
|
||||
$session->db->write('update passiveAnalyticsStatus set endDate=NOW(), running=0');
|
||||
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
152
lib/WebGUI/Workflow/Activity/ExpireIncompleteSurveyResponses.pm
Normal file
152
lib/WebGUI/Workflow/Activity/ExpireIncompleteSurveyResponses.pm
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
package WebGUI::Workflow::Activity::ExpireIncompleteSurveyResponses;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2008 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
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::DateTime;
|
||||
use DateTime::Duration;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::ExpireIncompleteSurveyResponses
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This activity deletes the survey responses for which the allowed time has expired and emails the survey user.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Workflow_Activity_ExpireIncompleteSurveyResponses");
|
||||
push(@{$definition}, {
|
||||
name => $i18n->get("name"),
|
||||
properties => {
|
||||
deleteExpired=>{
|
||||
fieldType=>"yesNo",
|
||||
defaultValue=>0,
|
||||
label=>$i18n->get("Delete expired survey responses"),
|
||||
hoverHelp=>$i18n->get("delete expired")
|
||||
},
|
||||
emailUsers=>{
|
||||
fieldType=>"yesNo",
|
||||
defaultValue=>0,
|
||||
label=>$i18n->get("Email users that responses were deleted"),
|
||||
hoverHelp=>$i18n->get("email users")
|
||||
},
|
||||
emailTemplateId => {
|
||||
fieldType => "template",
|
||||
defaultValue => 'ExpireIncResptmpl00001',
|
||||
namespace => "ExpireIncompleteSurveyResponses",
|
||||
label => $i18n->get('Email template sent to user'),
|
||||
hoverHelp => $i18n->get('email template'),
|
||||
},
|
||||
from => {
|
||||
fieldType=>"text",
|
||||
label=>$i18n->get("from"),
|
||||
defaultValue=>$session->setting->get("companyEmail"),
|
||||
hoverHelp=>$i18n->get("from mouse over"),
|
||||
},
|
||||
subject => {
|
||||
fieldType=>"text",
|
||||
label=>$i18n->get("subject"),
|
||||
defaultValue=>"Expired Survey",
|
||||
hoverHelp=>$i18n->get("subject mouse over"),
|
||||
},
|
||||
}
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( [ object ] )
|
||||
|
||||
Finds all the expired Survey Responses on the system. If delete is selected, they are removed. Then if
|
||||
email is selected, the users are emailed the template.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
my $sql = "select r.Survey_responseId, r.username, r.userId, upd.email,upd.firstName,upd.lastName, r.startDate, s.timeLimit, ad.title, ad.url
|
||||
from Survey s, Survey_response r, assetData ad, userProfileData upd
|
||||
where r.isComplete = 0 and s.timeLimit > 0 and (unix_timestamp() - r.startDate) > (s.timeLimit * 60)
|
||||
and r.assetId = s.assetId and s.revisionDate = (select max(revisionDate) from Survey where assetId = s.assetId)
|
||||
and ad.assetId = s.assetId and ad.revisionDate = s.revisionDate and upd.userId = r.userId";
|
||||
my $refs = $self->session->db->buildArrayRefOfHashRefs($sql);
|
||||
for my $ref (@{$refs}) {
|
||||
if($self->get("deleteExpired") == 1){
|
||||
$self->session->db->write("delete from Survey_response where Survey_responseId = ?",[$ref->{Survey_responseId}]);
|
||||
}else{#else sent to expired but not deleted
|
||||
$self->session->db->write("update Survey_response set isComplete = 99 where Survey_responseId = ?",[$ref->{Survey_responseId}]);
|
||||
}
|
||||
if($self->get("emailUsers") == 1 && $ref->{email} =~ /\@/){
|
||||
|
||||
my $var = {
|
||||
to => $ref->{email},
|
||||
from => $self->get("from"),
|
||||
firstName => $ref->{firstName},
|
||||
lastName => $ref->{lastName},
|
||||
surveyTitle => $ref->{title},
|
||||
surveyUrl => $ref->{url},
|
||||
responseId => $ref->{Survey_responseId},
|
||||
deleted => $self->get("deleteExpired"),
|
||||
companyName => $self->session->setting->get("companyName"),
|
||||
};
|
||||
my $template = WebGUI::Asset->newByDynamicClass($self->session,$self->get('emailTemplateId'));
|
||||
my $message = $template->processTemplate($var, $self->get("emailTemplateId"));
|
||||
WebGUI::Macro::process($self->session,\$message);
|
||||
my $mail = WebGUI::Mail::Send->create($self->session,{
|
||||
to => $ref->{email},
|
||||
subject => $self->get("subject"),
|
||||
from => $self->get('from'),
|
||||
});
|
||||
$mail->addHtml($message);
|
||||
$mail->addFooter;
|
||||
$mail->queue;
|
||||
}
|
||||
}
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
|
@ -342,8 +342,10 @@ sub setMessageCompleted {
|
|||
|
||||
# Set all messages to completed
|
||||
for my $messageId ( split /,/, $instance->getScratch("messageId") ) {
|
||||
my $message = $inbox->getMessage( $messageId );
|
||||
$message->setCompleted;
|
||||
if($messageId){
|
||||
my $message = $inbox->getMessage( $messageId );
|
||||
$message->setCompleted if $message;
|
||||
}
|
||||
}
|
||||
|
||||
$instance->deleteScratch( "messageId" );
|
||||
|
|
|
|||
148
lib/WebGUI/Workflow/Activity/SummarizePassiveAnalytics.pm
Normal file
148
lib/WebGUI/Workflow/Activity/SummarizePassiveAnalytics.pm
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
package WebGUI::Workflow::Activity::SummarizePassiveAnalytics;
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::SummarizePassiveAnalytics
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Summarize how long a user stayed on a page, using a user supplied interval.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'PassiveAnalytics');
|
||||
push(@{$definition}, {
|
||||
name=>$i18n->get('Summarize Passive Analytics'),
|
||||
properties=> {
|
||||
deltaInterval => {
|
||||
fieldType => 'interval',
|
||||
label => $i18n->get('pause interval'),
|
||||
defaultValue => 15,
|
||||
hoverHelp => $i18n->get('pause interval help'),
|
||||
},
|
||||
}
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( [ object ] )
|
||||
|
||||
Analyze the passiveLog table, and generate the deltaLog table.
|
||||
|
||||
=head3 notes
|
||||
|
||||
If there is only 1 line in the table for a particular sessionId or
|
||||
userId, no conclusions as to how long the user viewed a page can be
|
||||
drawn from that. Similarly, the last entry in their browsing log
|
||||
yields no data, since we require another entry in the passiveLog to
|
||||
determine a delta.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my ($self, undef, $instance) = @_;
|
||||
my $session = $self->session;
|
||||
my $endTime = time() + $self->getTTL;
|
||||
my $deltaInterval = $self->get('deltaInterval');
|
||||
|
||||
my $passive = q{select * from passiveLog where userId <> '1' order by userId, sessionId, timeStamp};
|
||||
my $sth;
|
||||
my $lastUserId;
|
||||
my $lastSessionId;
|
||||
my $lastTimeStamp;
|
||||
my $lastAssetId;
|
||||
my $lastUrl;
|
||||
my $counter = $instance->getScratch('counter');
|
||||
if ($counter) {
|
||||
$passive .= ' limit '. $counter .', 1234567890';
|
||||
$sth = $session->db->read($passive);
|
||||
$lastUserId = $instance->getScratch('lastUserId');
|
||||
$lastSessionId = $instance->getScratch('lastSessionId');
|
||||
$lastTimeStamp = $instance->getScratch('lastTimeStamp');
|
||||
$lastAssetId = $instance->getScratch('lastAssetId');
|
||||
$lastUrl = $instance->getScratch('lastUrl');
|
||||
}
|
||||
else {
|
||||
$sth = $session->db->read($passive);
|
||||
my $logLine = $sth->hashRef();
|
||||
$lastUserId = $logLine->{userId};
|
||||
$lastSessionId = $logLine->{sessionId};
|
||||
$lastTimeStamp = $logLine->{timeStamp};
|
||||
$lastAssetId = $logLine->{assetId};
|
||||
$lastUrl = $logLine->{url};
|
||||
}
|
||||
|
||||
$session->db->write('delete from deltaLog'); ##Only if we're starting out
|
||||
my $deltaLog = $session->db->prepare('insert into deltaLog (userId, assetId, delta, timeStamp, url) VALUES (?,?,?,?,?)');
|
||||
|
||||
my $expired = 0;
|
||||
LOG_ENTRY: while (my $logLine = $sth->hashRef()) {
|
||||
$counter++;
|
||||
my $delta = $logLine->{timeStamp} - $lastTimeStamp;
|
||||
if ( $logLine->{userId} eq $lastUserId
|
||||
&& $logLine->{sessionId} eq $lastSessionId
|
||||
&& $delta < $deltaInterval ) {
|
||||
$deltaLog->execute([$lastUserId, $lastAssetId, $delta, $lastTimeStamp, $lastUrl]);
|
||||
}
|
||||
$lastUserId = $logLine->{userId};
|
||||
$lastSessionId = $logLine->{sessionId};
|
||||
$lastTimeStamp = $logLine->{timeStamp};
|
||||
$lastAssetId = $logLine->{assetId};
|
||||
$lastUrl = $logLine->{url};
|
||||
if (time() > $endTime) {
|
||||
$instance->setScratch('lastUserId', $lastUserId);
|
||||
$instance->setScratch('lastSessionId', $lastSessionId);
|
||||
$instance->setScratch('lastTimeStamp', $lastTimeStamp);
|
||||
$instance->setScratch('lastAssetId', $lastAssetId);
|
||||
$instance->setScratch('lastUrl', $lastUrl);
|
||||
$instance->setScratch('counter', $counter);
|
||||
$expired = 1;
|
||||
last LOG_ENTRY;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expired) {
|
||||
return $self->WAITING(1);
|
||||
}
|
||||
|
||||
$instance->deleteScratch('lastUserId');
|
||||
$instance->deleteScratch('lastSessionId');
|
||||
$instance->deleteScratch('lastTimeStamp');
|
||||
$instance->deleteScratch('lastAssetId');
|
||||
$instance->deleteScratch('lastUrl');
|
||||
$instance->deleteScratch('counter');
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
|
|
@ -49,6 +49,11 @@ our $I18N = {
|
|||
lastUpdated => 1230867169,
|
||||
},
|
||||
|
||||
'my sales label' => {
|
||||
message => q{Sales},
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -1196,6 +1196,12 @@ Couldn't open %-s because %-s <br />
|
|||
context => q{Asset Manager label, as in "locked by admin"},
|
||||
},
|
||||
|
||||
'assetHistory' => {
|
||||
message => q{Asset History},
|
||||
lastUpdated => 0,
|
||||
context => q{Admin Console label. Shows the history of assets in this site.},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -372,6 +372,11 @@ listing,|,
|
|||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'group to add description' => {
|
||||
message => q|Select the group that is allowed to add listings to this matrix.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'ratings duration description' => {
|
||||
message => q|Select the interval after which old ratings are cleaned out.|,
|
||||
lastUpdated => 0,
|
||||
|
|
@ -476,6 +481,16 @@ listing,|,
|
|||
message => q|Select a template to be used to show the listing edit screen.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'screenshots template description' => {
|
||||
message => q|Select a template to be used to show a listing's screenshots.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'screenshots config template description' => {
|
||||
message => q|Select a template for a listing's screenshots configuration.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'categories label' => {
|
||||
message => q|Categories|,
|
||||
|
|
@ -487,6 +502,11 @@ listing,|,
|
|||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'group to add label' => {
|
||||
message => q|Group To Add|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'ratings duration label' => {
|
||||
message => q|Ratings Duration|,
|
||||
lastUpdated => 0,
|
||||
|
|
@ -602,6 +622,16 @@ listing,|,
|
|||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'screenshots template label' => {
|
||||
message => q|Listing Screenshots Template|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'screenshots config template label' => {
|
||||
message => q|Listing Screenshots Config Template|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'edit listing template label' => {
|
||||
message => q|Edit Listing Template|,
|
||||
lastUpdated => 0,
|
||||
|
|
@ -750,6 +780,12 @@ selectBox.</p>|
|
|||
message => q|Hide/show stickied|,
|
||||
},
|
||||
|
||||
'approve or deny label' => {
|
||||
lastUpdated => 0,
|
||||
message => q|Approve/Deny|,
|
||||
context => q|Label for the approve or deny link on the matrix listing detail screen.|,
|
||||
},
|
||||
|
||||
'matrix asset template variables title' => {
|
||||
lastUpdated => 0,
|
||||
message => q|Matrix Asset Template Variables|,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ fields below.|,
|
|||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'edit label' => {
|
||||
message => q|Edit|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'version description' => {
|
||||
message => q|Enter the version/edition/model number for the product.|,
|
||||
lastUpdated => 0,
|
||||
|
|
@ -221,6 +226,30 @@ it would be best to make sure the names are the same.|,
|
|||
context => q|Description of the form tmpl_var for the template help.|,
|
||||
},
|
||||
|
||||
'canEdit' => {
|
||||
message => q|A boolean indicating whether the user can edit this listing.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the screenshots tmpl_var for the template help.|,
|
||||
},
|
||||
|
||||
'editUrl' => {
|
||||
message => q|The url to this listing's edit screen.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the screenshots tmpl_var for the template help.|,
|
||||
},
|
||||
|
||||
'canApprove' => {
|
||||
message => q|A boolean indicating whether the user can approve or deny this listing.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the screenshots tmpl_var for the template help.|,
|
||||
},
|
||||
|
||||
'approveOrDenyUrl' => {
|
||||
message => q|The url to this listing's approve or deny screen.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the screenshots tmpl_var for the template help.|,
|
||||
},
|
||||
|
||||
'screenshots' => {
|
||||
message => q|This listings screenshots displayed using the ukplayer.|,
|
||||
lastUpdated => 0,
|
||||
|
|
|
|||
|
|
@ -487,8 +487,8 @@ editing an existing Post, and a thread containing the Post exists.|,
|
|||
},
|
||||
|
||||
'userDefined3' => {
|
||||
message => q|The value contained in the first user defined variable.|,
|
||||
lastUpdated => 1150167057,
|
||||
message => q|The value contained in the third user defined variable.|,
|
||||
lastUpdated => 1236354498,
|
||||
},
|
||||
|
||||
'userDefined4' => {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ our $I18N = {
|
|||
message => q|View Grade Book|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'delete responses' => {
|
||||
message => q|Delete Responses|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'continue button' => {
|
||||
message => q|Continue|,
|
||||
lastUpdated => 1224686319
|
||||
|
|
@ -83,7 +87,7 @@ our $I18N = {
|
|||
},
|
||||
|
||||
'section name' => {
|
||||
message => q|Section name:|,
|
||||
message => q|Section title:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'section name description' => {
|
||||
|
|
@ -101,7 +105,7 @@ our $I18N = {
|
|||
lastUpdated => 0
|
||||
},
|
||||
'section custom variable name' => {
|
||||
message => q|Section custom variable name:|,
|
||||
message => q|Section variable name:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'section custom variable name description' => {
|
||||
|
|
@ -110,7 +114,7 @@ our $I18N = {
|
|||
lastUpdated => 0
|
||||
},
|
||||
'section branch goto variable name' => {
|
||||
message => q|Section branch goto variable name:|,
|
||||
message => q|Jump to:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'section branch goto variable name description' => {
|
||||
|
|
@ -222,6 +226,10 @@ our $I18N = {
|
|||
message => q|Question type:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'randomized words' => {
|
||||
message => q|Randomized words:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'question type description' => {
|
||||
message => q|Select this question's field type.|,
|
||||
context => q|Description of the 'question type' field, used as hoverhelp in the edit question dialog.|,
|
||||
|
|
@ -256,21 +264,21 @@ our $I18N = {
|
|||
context => q|Description of the 'allow comment' field, used as hoverhelp in the edit question dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'cols' => {
|
||||
message => q|Cols:|,
|
||||
'comment cols' => {
|
||||
message => q|Comment Cols:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'cols description' => {
|
||||
message => q|The number of columns of the textarea input.|,
|
||||
message => q|The number of columns used for the comment TextArea input field.|,
|
||||
context => q|Description of the 'cols' field, used as hoverhelp in the edit question dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'rows' => {
|
||||
message => q|Rows:|,
|
||||
'comment rows' => {
|
||||
message => q|Comment Rows:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'rows description' => {
|
||||
message => q|The number of rows of the textarea input.|,
|
||||
message => q|The number of rows shown for the comment TextArea input field.|,
|
||||
context => q|Description of the 'rows' field, used as hoverhelp in the edit question dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
|
@ -325,11 +333,11 @@ our $I18N = {
|
|||
lastUpdated => 0
|
||||
},
|
||||
'recorded answer' => {
|
||||
message => q|Recorded answer:|,
|
||||
message => q|Answer title:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'recorded answer description' => {
|
||||
message => q|The answer that will be recorded in the database. The recorded answer will be displayed in a multiple choice question's buttons, only if the question's 'Show text in button' property is set to yes. Otherwise the multiple choice buttons will be empty. |,
|
||||
message => q|Text to display inside multiple-choice answer buttons (only if 'Show text in button' is enabled for this question).|,
|
||||
context => q|Description of the 'recorded answer' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
|
@ -337,13 +345,22 @@ our $I18N = {
|
|||
message => q|Jump to:|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'jump expression' => {
|
||||
message => q|Jump expression:|,
|
||||
lastUpdated => 1229318805
|
||||
},
|
||||
'jump to description' => {
|
||||
message => q|The section or question with this variable name will be the next to be displayed after this answer.|,
|
||||
context => q|Description of the 'jump to' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'jump expression description' => {
|
||||
message => q|An expression used to control complex branching based user responses to previous questions. A branch expression is made up of a list of rules, one per line, along with a branch target for each rule. |,
|
||||
context => q|Description of the 'jump expression' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'text answer' => {
|
||||
message => q|Text answer|,
|
||||
message => q|TextArea|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'is this the correct answer' => {
|
||||
|
|
@ -363,30 +380,30 @@ our $I18N = {
|
|||
message => q|No|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'min' => {
|
||||
message => q|Min|,
|
||||
'min label' => {
|
||||
message => q|Slider Min|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'min description' => {
|
||||
message => q|Set the min value of this answer for slider type questions.|,
|
||||
message => q|The minimum value of this answer for slider type questions.|,
|
||||
context => q|Description of the 'min' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'max label' => {
|
||||
message => q|Max|,
|
||||
message => q|Slider Max|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'max description' => {
|
||||
message => q|Set the max value of this answer for slider type questions.|,
|
||||
message => q|The maximum value of this answer for slider type questions.|,
|
||||
context => q|Description of the 'max' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
'step label' => {
|
||||
message => q|Step|,
|
||||
message => q|Slider Step|,
|
||||
lastUpdated => 1224686319
|
||||
},
|
||||
'step description' => {
|
||||
message => q|Set the step value of this answer for slider type questions.|,
|
||||
message => q|The step value of this answer for slider type questions.|,
|
||||
context => q|Description of the 'step' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
|
@ -395,7 +412,7 @@ our $I18N = {
|
|||
lastUpdated => 1224686319
|
||||
},
|
||||
'verbatim description' => {
|
||||
message => q|Set to yes to add an extra text input to the answer, where the user can enter a single line of text.|,
|
||||
message => q|Set to yes to add an extra text input to the answer, where the user can enter a single line of text. Typically used to permit a free-text 'other' response.|,
|
||||
context => q|Description of the 'verbatim' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
|
@ -404,7 +421,7 @@ our $I18N = {
|
|||
lastUpdated => 1224686319
|
||||
},
|
||||
'answer value description' => {
|
||||
message => q|Enter a value for this answer.|,
|
||||
message => q|Assign a numeric scores to this answers. Used in question scoring and jump expressions.|,
|
||||
context => q|Description of the 'answer value' field, used as hoverhelp in the edit answer dialog.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
|
@ -429,7 +446,35 @@ our $I18N = {
|
|||
message => q|The template to display the main page of the survey.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'do after timelimit label' => {
|
||||
message => q|Do After Time Limit:|,
|
||||
lastUpdated => 1224686319,
|
||||
context => q|label for the 'do after timelimit' field on the Properties tab of the Survey's edit screen.|,
|
||||
},
|
||||
'do after timelimit hoverHelp' => {
|
||||
message => q|Select what happens after the time limit for finishing the survey has expired.|,
|
||||
lastUpdated => 1231193335,
|
||||
context => q|description of the 'do after timelimit' field on the Properties tab of the Survey's edit
|
||||
screen|,
|
||||
},
|
||||
'exit url label' =>{
|
||||
message => q|Exit URL|,
|
||||
lastUpdated => 0,
|
||||
context => q|Label for the 'exit url' option of the 'do after timelimit' field on the Properties tab of the
|
||||
Survey's edit screen|,
|
||||
},
|
||||
'restart survey label' =>{
|
||||
message => q|Restart Survey|,
|
||||
lastUpdated => 0,
|
||||
context => q|Label for the 'restart survey' option of the 'do after timelimit' field on the Properties tab of the
|
||||
Survey's edit screen|,
|
||||
},
|
||||
'restart message' =>{
|
||||
message => q|The survey was restarted because the time limit for completing the survey was reached.|,
|
||||
lastUpdated => 0,
|
||||
context => q|The message shown to the user taking the survey when the survey is restarted after reaching
|
||||
the time limit for completing the survey. This message is in the 'take survey' template.|,
|
||||
},
|
||||
'Show user their progress' => {
|
||||
message => q|Show user their progress?|,
|
||||
lastUpdated => 0,
|
||||
|
|
@ -489,6 +534,36 @@ our $I18N = {
|
|||
message => q|When the user finishes the surevey, they will be sent to this URL. Leave blank if no special forwarding is required. The gateway setting from the config file will be automatically added to the URL for you.|,
|
||||
lastUpdated => 1233714385,
|
||||
},
|
||||
|
||||
'Overview Report Template' => {
|
||||
message => q|Overview Report Template|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Overview Report Template help' => {
|
||||
message => q|The template used to display the Overview Report.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Grabebook Report Template' => {
|
||||
message => q|Grabebook Report Template|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Grabebook Report Template help' => {
|
||||
message => q|The template used to display the Gradebook Report|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Survey Edit Template' => {
|
||||
message => q|Survey Edit Template|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Survey Edit Template help' => {
|
||||
message => q|The template used to display the Survey Edit screen.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Max user responses' => {
|
||||
message => q|Max user responses|,
|
||||
|
|
@ -523,17 +598,6 @@ our $I18N = {
|
|||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'Response Template' => {
|
||||
message => q|Response Template|,
|
||||
context => q|The template for displaying responses to the survey.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'Response Template help' => {
|
||||
message => q|The template for displaying responses to the survey.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'Edit Survey Template' => {
|
||||
message => q|Edit Survey Template|,
|
||||
context => q|The template for displaying the screen for editing the survey.|,
|
||||
|
|
@ -552,7 +616,7 @@ our $I18N = {
|
|||
},
|
||||
|
||||
'Take Survey Template help' => {
|
||||
message => q|The template for displaying the screen where a user takes the survey.|,
|
||||
message => q|The template used to control the initial Take Survey screen, from which responses are dynamically loaded into.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
|
|
@ -563,7 +627,7 @@ our $I18N = {
|
|||
},
|
||||
|
||||
'Questions Template help' => {
|
||||
message => q|The template for rendering questions in the survey.|,
|
||||
message => q|The template used to display individual questions, which are dynamically loaded into the Take Survey page.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
|
|
@ -574,7 +638,7 @@ our $I18N = {
|
|||
},
|
||||
|
||||
'Section Edit Template help' => {
|
||||
message => q|The template for adding or editing sections.|,
|
||||
message => q|The template used to display the Section Edit dialog on the Edit Survey page.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
|
|
@ -585,7 +649,7 @@ our $I18N = {
|
|||
},
|
||||
|
||||
'Question Edit Template help' => {
|
||||
message => q|The template for adding or editing questions.|,
|
||||
message => q|The template used to display the Question Edit dialog on the Edit Survey page.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
|
|
@ -596,7 +660,7 @@ our $I18N = {
|
|||
},
|
||||
|
||||
'Answer Edit Template help' => {
|
||||
message => q|The template for adding or editing answers.|,
|
||||
message => q|The template used to display the Answer Edit dialog on the Edit Survey page.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
|
|
@ -860,9 +924,27 @@ directly inside the answer_loop for other types of questions.|,
|
|||
},
|
||||
|
||||
'templateId' => {
|
||||
message => q|The ID of the template to show the Survey.|,
|
||||
message => q|The ID of the template to show the front page of the Survey.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168639537,
|
||||
lastUpdated => 1236891448,
|
||||
},
|
||||
|
||||
'gradebookTemplateId' => {
|
||||
message => q|The ID of the template used to show the gradebook screen.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168643669,
|
||||
},
|
||||
|
||||
'responseTemplateId' => {
|
||||
message => q|The ID of the template used to show the Survey Response screen.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168643669,
|
||||
},
|
||||
|
||||
'overviewTemplateId' => {
|
||||
message => q|The ID of the template used to show the overview screen.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168643669,
|
||||
},
|
||||
|
||||
'groupToTakeSurvey' => {
|
||||
|
|
@ -883,24 +965,6 @@ directly inside the answer_loop for other types of questions.|,
|
|||
lastUpdated => 1168643566,
|
||||
},
|
||||
|
||||
'overviewTemplateId' => {
|
||||
message => q|The ID of the template used to show the overview screen.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168643669,
|
||||
},
|
||||
|
||||
'gradebookTemplateId' => {
|
||||
message => q|The ID of the template used to show the gradebook screen.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168643669,
|
||||
},
|
||||
|
||||
'responseTemplateId' => {
|
||||
message => q|The ID of the template used to show the Survey Response screen.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 1168643669,
|
||||
},
|
||||
|
||||
'survey questions template title' => {
|
||||
message => q|Survey Questions Template|,
|
||||
context => q|The title of a template Help page.|,
|
||||
|
|
@ -1227,18 +1291,6 @@ section/answer.|,
|
|||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'min' => {
|
||||
message => q|The min value of this answer for slider type questions.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'max' => {
|
||||
message => q|The max value of this answer for slider type questions..|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'step' => {
|
||||
message => q|The step value of this answer for slider type questions..|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
|
|
@ -1252,13 +1304,13 @@ section/answer.|,
|
|||
},
|
||||
|
||||
'textCols' => {
|
||||
message => q|The number of columns for textarea answers.|,
|
||||
message => q|The number of columns for TextArea questions.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'textRows' => {
|
||||
message => q|The number of rows for textarea answers.|,
|
||||
message => q|The number of rows for TextArea questions.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
|
@ -1281,6 +1333,18 @@ section/answer.|,
|
|||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'min' => {
|
||||
message => q|The min value of this answer for slider type questions.|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'max' => {
|
||||
message => q|The max value of this answer for slider type questions..|,
|
||||
context => q|Description of a template variable for a template Help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use strict;
|
|||
our $I18N = {
|
||||
|
||||
'from user preface' => {
|
||||
message => q|You were sent a message from |,
|
||||
message => q|You were sent a message from %s|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
};
|
||||
|
|
|
|||
183
lib/WebGUI/i18n/English/PassiveAnalytics.pm
Normal file
183
lib/WebGUI/i18n/English/PassiveAnalytics.pm
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
package WebGUI::i18n::English::PassiveAnalytics;
|
||||
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
|
||||
'Summarize Passive Analytics' => {
|
||||
message => q|Summarize Passive Analytics|,
|
||||
context => q|The name of this workflow activity.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'pause interval' => {
|
||||
message => q|Pause threshold|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'pause interval help' => {
|
||||
message => q|Set the time between clicks that is interpreted as the user reading the page, as opposed to beginning a new browsing session, or leaving the site.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'default pause interval' => {
|
||||
message => q|Default Pause Threshold|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'default pause interval help' => {
|
||||
message => q|Set the default pause interval displayed the user sees in the Passive Analytics screen.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'other' => {
|
||||
message => q|Other|,
|
||||
lastUpdated => 0,
|
||||
context => q|Meaning not like anything in a set. This, that and the other one. Also, a catch all.|
|
||||
},
|
||||
|
||||
'Bucket Passive Analytics' => {
|
||||
message => q|Bucket Passive Analytics|,
|
||||
lastUpdated => 0,
|
||||
context => q|Name of the activity that puts log entries into buckets for analysis.|
|
||||
},
|
||||
|
||||
'Bucket Name' => {
|
||||
message => q|Bucket Name|,
|
||||
lastUpdated => 0,
|
||||
context => q|To name a container, or bucket.|
|
||||
},
|
||||
|
||||
'Bucket Name help' => {
|
||||
message => q|Pick a unique, descriptive short name for this bucket.|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'regexp' => {
|
||||
message => q|Regular expression|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'regexp help' => {
|
||||
message => q|Define a regular expression to pick log entries for this bucket.<br />
|
||||
^ = beginning of url<br />
|
||||
$ = end of url<br />
|
||||
. = any character<br />
|
||||
* = any amount<br />
|
||||
+ = 1 or more<br />
|
||||
? = 0 or 1<br />
|
||||
Meta characters should be backslash-escaped if you want to match them as ordinary text, e.g.<br />
|
||||
home\?func=match, or<br />
|
||||
|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Passive Analytics' => {
|
||||
message => q|Passive Analytics|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Passive Analytics Settings' => {
|
||||
message => q|Passive Analytics Settings|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Edit Rule' => {
|
||||
message => q|Edit Rule|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Add a bucket' => {
|
||||
message => q|Add a bucket|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'User' => {
|
||||
message => q|User|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'User help' => {
|
||||
message => q|The user who will recieve an email when bucket processing is done.|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Begin analysis' => {
|
||||
message => q|Begin analysis|,
|
||||
lastUpdated => 0,
|
||||
context => q|Button label to begin analyzing the logs.|
|
||||
},
|
||||
|
||||
'Delete Delta Table?' => {
|
||||
message => q|Delete Delta Table?|,
|
||||
lastUpdated => 0,
|
||||
context => q|Button label to begin analyzing the logs.|
|
||||
},
|
||||
|
||||
'Delete Delta Table? help' => {
|
||||
message => q|Should the delta table be cleaned up after the Passive Analytics analyzer is done?|,
|
||||
lastUpdated => 0,
|
||||
context => q|Button label to begin analyzing the logs.|
|
||||
},
|
||||
|
||||
'Enabled?' => {
|
||||
message => q|Enable Passive Analytics?|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Enabled? help' => {
|
||||
message => q|Passive Analytics will do no logging until enabled.|,
|
||||
lastUpdated => 0,
|
||||
context => q||
|
||||
},
|
||||
|
||||
'Regular Expression Error:' => {
|
||||
message => q|Regular Expression Error:|,
|
||||
lastUpdated => 0,
|
||||
context => q|Error displayed when a user enters in a bad regular expression. This label will be followed by the error from perl.|
|
||||
},
|
||||
|
||||
'Export bucket data' => {
|
||||
message => q|Export bucket data|,
|
||||
lastUpdated => 0,
|
||||
context => q|URL label to export data in CSV format|,
|
||||
},
|
||||
|
||||
'Export delta data' => {
|
||||
message => q|Export delta data|,
|
||||
lastUpdated => 0,
|
||||
context => q|URL label to export data in CSV format|,
|
||||
},
|
||||
|
||||
'Export raw logs' => {
|
||||
message => q|Export raw logs|,
|
||||
lastUpdated => 0,
|
||||
context => q|URL label to raw log data in CSV format|,
|
||||
},
|
||||
|
||||
'confirm delete rule' => {
|
||||
message => q|Are you sure that you want to delete this rule?|,
|
||||
lastUpdated => 0,
|
||||
context => q|Confirm label in deleting a rule.|,
|
||||
},
|
||||
|
||||
'manage ruleset' => {
|
||||
message => q|Manage Ruleset|,
|
||||
lastUpdated => 0,
|
||||
context => q|Admin console submenu label. Ruleset is a set of rules.|,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
|
|
@ -555,6 +555,12 @@ our $I18N = {
|
|||
context => q|admin function label|
|
||||
},
|
||||
|
||||
'vendor payouts' => {
|
||||
message => q|Vendor payouts|,
|
||||
lastUpdated => 0,
|
||||
context => q|admin function label|
|
||||
},
|
||||
|
||||
'update' => {
|
||||
message => q|Update|,
|
||||
lastUpdated => 0,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
package WebGUI::i18n::English::Workflow_Activity_ExpireIncompleteSurveyResponses;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
'name' => {
|
||||
message => q|ExpireIncompleteSurveyResponses|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'Delete expired survey responses' => {
|
||||
message => q|Delete expired survey responses|,
|
||||
context => q|the hover help for the delete responses field|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'delete expired' => {
|
||||
message => q|When ran, every survey response which is expired will be completely removed from the database.|,
|
||||
context => q|the hover help for the delete responses field|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'Email users that responses were deleted' => {
|
||||
message => q|Email users that responses were deleted|,
|
||||
context => q|the hover help for the email users field|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'email users' => {
|
||||
message => q|When a survey response is deleted, should the user be informed of this via email?|,
|
||||
context => q|the hover help for the email users field|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'email template' => {
|
||||
message => q|When an email is sent updating the user that their response has been deleted, this is the text that is sent to them.|,
|
||||
context => q|the hover help for the email template field|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'from' => {
|
||||
message => q|Email from field|,
|
||||
context => q||,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'from mouse over' => {
|
||||
message => q|This is the from field that will show up in the sent email.|,
|
||||
context => q||,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'subject' => {
|
||||
message => q|Email subject field|,
|
||||
context => q||,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'subject mouse over' => {
|
||||
message => q|This is the subject field that will show up in the sent email.|,
|
||||
context => q||,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'Email template sent to user' => {
|
||||
message => q|The template for the email|,
|
||||
context => q||,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
'email template' => {
|
||||
message => q|This is the email template that will be sent to the user|,
|
||||
context => q||,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -120,6 +120,7 @@ checkModule("List::MoreUtils", "0.22" );
|
|||
checkModule("File::Path", "2.04" );
|
||||
checkModule("Module::Find", "0.06" );
|
||||
checkModule("Class::C3", "0.19" );
|
||||
checkModule("Params::Validate", "0.81" );
|
||||
|
||||
failAndExit("Required modules are missing, running no more checks.") if $missingModule;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ my $session = WebGUI::Test->session;
|
|||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
|
||||
my $tests = 53;
|
||||
my $tests = 55;
|
||||
plan tests => 1 + $tests;
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -149,6 +149,7 @@ SKIP: {
|
|||
isa_ok($soda, 'WebGUI::Asset::Sku::Product');
|
||||
is($soda->getTitle(), 'Sweet Soda-bottled in Oregon', 'Title set correctly for soda');
|
||||
is($soda->get('url'), 'sweet-soda-bottled-in-oregon', 'URL for new product from the title');
|
||||
is($soda->get('menuTitle'), $soda->getTitle, 'menuTitle is the same as title');
|
||||
my $sodaCollateral = $soda->getAllCollateral('variantsJSON');
|
||||
cmp_deeply(
|
||||
$sodaCollateral,
|
||||
|
|
@ -317,7 +318,8 @@ SKIP: {
|
|||
is($count, 3, 'still have 3 products, nothing new added');
|
||||
|
||||
$soda = WebGUI::Asset::Sku->newBySku($session, 'soda');
|
||||
is($soda->getTitle(), 'Sweet Soda-totally organic', 'Title updated correctly for soda');
|
||||
is($soda->getTitle(), 'Sweet Soda-totally organic', 'Title updated correctly for soda');
|
||||
is($soda->get('menuTitle'), 'Sweet Soda-totally organic', 'menuTitle updated correctly for soda');
|
||||
is($soda->get('url'), 'sweet-soda-bottled-in-oregon', 'URL for updated product from the original title, not the updated title');
|
||||
$shirt = WebGUI::Asset::Sku->newBySku($session, 't-shirt');
|
||||
$shirtCollateral = $shirt->getAllCollateral('variantsJSON');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ my $session = WebGUI::Test->session;
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
my $tests = 1;
|
||||
my $tests = 11;
|
||||
plan tests => $tests + 1;
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -37,6 +37,61 @@ $import_node = WebGUI::Asset->getImportNode($session);
|
|||
$survey = $import_node->addChild( { className => 'WebGUI::Asset::Wobject::Survey', } );
|
||||
isa_ok($survey, 'WebGUI::Asset::Wobject::Survey');
|
||||
|
||||
# Load bare-bones survey, containing a single section (S0)
|
||||
$survey->surveyJSON_update([0], { variable => 'S0' });
|
||||
|
||||
# Add 2 questions to S0
|
||||
$survey->surveyJSON_newObject([0]); # S0Q0
|
||||
$survey->surveyJSON_update([0,0], { variable => 'S0Q0' });
|
||||
$survey->surveyJSON_newObject([0]); # S0Q1
|
||||
$survey->surveyJSON_update([0,1], { variable => 'S0Q1' });
|
||||
|
||||
# Add a new section (S1)
|
||||
$survey->surveyJSON_newObject([]); # S1
|
||||
$survey->surveyJSON_update([1], { variable => 'S1' });
|
||||
|
||||
# Add 2 questions to S1
|
||||
$survey->surveyJSON_newObject([1]); # S1Q0
|
||||
$survey->surveyJSON_update([1,0], { variable => 'S1Q0' });
|
||||
$survey->surveyJSON_newObject([1]); # S1Q1
|
||||
$survey->surveyJSON_update([1,1], { variable => 'S1Q1' });
|
||||
|
||||
# Now start a response as admin user
|
||||
$session->user( { userId =>3 } );
|
||||
$survey->responseIdCookies(0);
|
||||
|
||||
my $responseId = $survey->responseId;
|
||||
my $s = WebGUI::Asset::Wobject::Survey->newByResponseId($session, $responseId);
|
||||
is($s->getId, $survey->getId, 'newByResponseId returns same Survey');
|
||||
|
||||
#for my $address (@{ $survey->responseJSON->surveyOrder }) {
|
||||
# diag (Dumper $address);
|
||||
#}
|
||||
|
||||
# www_jumpTo
|
||||
{
|
||||
# Check a simple www_jumpTo request
|
||||
WebGUI::Test->getPage( $survey, 'www_jumpTo', { formParams => {id => '0'} } );
|
||||
is( $session->http->getStatus, '201', 'Page request ok' ); # why is "201 - created" status used??
|
||||
is($survey->responseJSON->nextResponse, 0, 'S0 is the first response');
|
||||
|
||||
tie my %expectedSurveyOrder, 'Tie::IxHash';
|
||||
%expectedSurveyOrder = (
|
||||
'undefined' => 0,
|
||||
'0' => 0,
|
||||
'0-0' => 0,
|
||||
'0-1' => 1,
|
||||
'1' => 2,
|
||||
'1-0' => 2,
|
||||
'1-1' => 3,
|
||||
);
|
||||
while (my ($id, $index) = each %expectedSurveyOrder) {
|
||||
WebGUI::Test->getPage( $survey, 'www_jumpTo', { formParams => {id => $id} } );
|
||||
is($survey->responseJSON->nextResponse, $index, "jumpTo($id) sets nextResponse to $index");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ use lib "$FindBin::Bin/../../../lib";
|
|||
use Test::More;
|
||||
use Test::Deep;
|
||||
use Test::MockObject::Extends;
|
||||
use Test::Exception;
|
||||
use Data::Dumper;
|
||||
use List::Util qw/shuffle/;
|
||||
use WebGUI::Test; # Must use this before any other WebGUI modules
|
||||
use WebGUI::Session;
|
||||
use WebGUI::Asset::Wobject::Survey::SurveyJSON;
|
||||
|
|
@ -20,7 +22,7 @@ my $session = WebGUI::Test->session;
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
my $tests = 52;
|
||||
my $tests = 79;
|
||||
plan tests => $tests + 1;
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -40,17 +42,16 @@ skip $tests, "Unable to load ResponseJSON" unless $usedOk;
|
|||
####################################################
|
||||
|
||||
my $newTime = time();
|
||||
$responseJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new('{}', $session->log);
|
||||
$responseJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(buildSurveyJSON($session), '{}');
|
||||
isa_ok($responseJSON , 'WebGUI::Asset::Wobject::Survey::ResponseJSON');
|
||||
|
||||
is($responseJSON->lastResponse(), -1, 'new: default lastResponse is -1');
|
||||
is($responseJSON->{questionsAnswered}, 0, 'new: questionsAnswered is 0 by default');
|
||||
cmp_ok((abs$responseJSON->{startTime} - $newTime), '<=', 2, 'new: by default startTime set to time');
|
||||
is($responseJSON->questionsAnswered, 0, 'new: questionsAnswered is 0 by default');
|
||||
cmp_ok((abs$responseJSON->startTime - $newTime), '<=', 2, 'new: by default startTime set to time');
|
||||
is_deeply( $responseJSON->responses, {}, 'new: by default, responses is an empty hashref');
|
||||
is_deeply( $responseJSON->surveyOrder, [], 'new: by default, responses is an empty arrayref');
|
||||
|
||||
my $now = time();
|
||||
my $rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(qq!{ "startTime": $now }!, $session->log);
|
||||
my $rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(buildSurveyJSON($session), qq!{ "startTime": $now }!);
|
||||
cmp_ok(abs($rJSON->startTime() - $now), '<=', 2, 'new: startTime set using JSON');
|
||||
|
||||
####################################################
|
||||
|
|
@ -81,13 +82,13 @@ ok( ! $rJSON->hasTimedOut(4*60), 'hasTimedOut, limit check');
|
|||
|
||||
####################################################
|
||||
#
|
||||
# createSurveyOrder
|
||||
# initSurveyOrder
|
||||
#
|
||||
####################################################
|
||||
|
||||
$rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(q!{}!, $session->log, buildSurveyJSON($session));
|
||||
$rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(buildSurveyJSON($session), q!{}!);
|
||||
|
||||
$rJSON->createSurveyOrder();
|
||||
#$rJSON->initSurveyOrder();
|
||||
cmp_deeply(
|
||||
$rJSON->surveyOrder,
|
||||
[
|
||||
|
|
@ -101,7 +102,7 @@ cmp_deeply(
|
|||
[ 3, 1, [0, 1, 2, 3, 4, 5, 6] ],
|
||||
[ 3, 2, [0] ],
|
||||
],
|
||||
'createSurveyOrder, enumerated all sections, questions and answers'
|
||||
'initSurveyOrder, enumerated all sections, questions and answers'
|
||||
);
|
||||
|
||||
####################################################
|
||||
|
|
@ -118,38 +119,39 @@ cmp_deeply(
|
|||
|
||||
####################################################
|
||||
#
|
||||
# createSurveyOrder, part 2
|
||||
# initSurveyOrder, part 2
|
||||
#
|
||||
####################################################
|
||||
|
||||
{
|
||||
no strict "refs";
|
||||
no warnings;
|
||||
my $rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(q!{}!, $session->log, buildSurveyJSON($session));
|
||||
$rJSON->survey->section([0])->{randomizeQuestions} = 0;
|
||||
my $shuffleName = "WebGUI::Asset::Wobject::Survey::ResponseJSON::shuffle";
|
||||
my $shuffleCalled = 0;
|
||||
my $shuffleRef = \&$shuffleName;
|
||||
*$shuffleName = sub {
|
||||
$shuffleCalled = 1;
|
||||
goto &$shuffleRef;
|
||||
};
|
||||
$rJSON->createSurveyOrder();
|
||||
is($shuffleCalled, 0, 'createSurveyOrder did not call shuffle on a section');
|
||||
my $rJSON = WebGUI::Asset::Wobject::Survey::ResponseJSON->new(buildSurveyJSON($session), q!{}!);
|
||||
|
||||
$rJSON->survey->section([0])->{randomizeQuestions} = 0;
|
||||
$rJSON->initSurveyOrder();
|
||||
my @question_order = map {$_->[1]} grep {$_->[0] == 0} @{$rJSON->surveyOrder};
|
||||
cmp_deeply(\@question_order, [0,1,2], 'initSurveyOrder did not shuffle questions');
|
||||
|
||||
$shuffleCalled = 0;
|
||||
$rJSON->survey->section([0])->{randomizeQuestions} = 1;
|
||||
$rJSON->createSurveyOrder();
|
||||
is($shuffleCalled, 1, 'createSurveyOrder called shuffle on a section');
|
||||
srand(42); # Make shuffle predictable
|
||||
$rJSON->initSurveyOrder();
|
||||
@question_order = map {$_->[1]} grep {$_->[0] == 0} @{$rJSON->surveyOrder};
|
||||
srand(42);
|
||||
my @expected_order = shuffle(0,1,2);
|
||||
cmp_deeply(\@question_order, \@expected_order, 'initSurveyOrder shuffled questions in first section');
|
||||
|
||||
$shuffleCalled = 0;
|
||||
$rJSON->survey->section([0])->{randomizeQuestions} = 0;
|
||||
$rJSON->survey->question([0,0])->{randomizeAnswers} = 1;
|
||||
$rJSON->createSurveyOrder();
|
||||
is($shuffleCalled, 1, 'createSurveyOrder called shuffle on a question');
|
||||
|
||||
##Restore the subroutine to the original
|
||||
*$shuffleName = &$shuffleRef;
|
||||
$rJSON->survey->question([0,0])->{randomizeAnswers} = 0;
|
||||
$rJSON->initSurveyOrder();
|
||||
my @answer_order = map {@{$_->[2]}} grep {$_->[0] == 3 && $_->[1] == 1} @{$rJSON->surveyOrder};
|
||||
cmp_deeply(\@answer_order, [0,1,2,3,4,5,6], 'initSurveyOrder did not shuffle answers');
|
||||
|
||||
$rJSON->survey->question([3,1])->{randomizeAnswers} = 1;
|
||||
srand(42); # Make shuffle predictable
|
||||
$rJSON->initSurveyOrder();
|
||||
@answer_order = map {@{$_->[2]}} grep {$_->[0] == 3 && $_->[1] == 1} @{$rJSON->surveyOrder};
|
||||
srand(42); # Make shuffle predictable
|
||||
@expected_order = shuffle(0..6);
|
||||
cmp_deeply(\@answer_order, \@expected_order, 'initSurveyOrder shuffled answers');
|
||||
}
|
||||
|
||||
####################################################
|
||||
|
|
@ -169,51 +171,51 @@ ok( $rJSON->surveyEnd(), 'surveyEnd, with 9 elements, 20 >= end of survey');
|
|||
|
||||
####################################################
|
||||
#
|
||||
# nextSectionId, nextSection, currentSection
|
||||
# nextResponseSectionIndex, nextResponseSection, lastResponseSectionIndex
|
||||
#
|
||||
####################################################
|
||||
|
||||
$rJSON->lastResponse(0);
|
||||
is($rJSON->nextSectionId(), 0, 'nextSectionId, lastResponse=0, nextSectionId=0');
|
||||
is($rJSON->nextResponseSectionIndex, 0, 'nextResponseSectionIndex, lastResponse=0, nextResponseSectionIndex=0');
|
||||
cmp_deeply(
|
||||
$rJSON->nextSection,
|
||||
$rJSON->nextResponseSection,
|
||||
$rJSON->survey->section([0]),
|
||||
'lastResponse=0, nextSection = section 0'
|
||||
'lastResponse=0, nextResponseSection = section 0'
|
||||
);
|
||||
cmp_deeply(
|
||||
$rJSON->currentSection,
|
||||
$rJSON->survey->section([0]),
|
||||
'lastResponse=0, currentSection = section 0'
|
||||
is(
|
||||
$rJSON->lastResponseSectionIndex,
|
||||
0,
|
||||
'lastResponse=0, lastResponseSectionIndex = 0'
|
||||
);
|
||||
|
||||
$rJSON->lastResponse(2);
|
||||
is($rJSON->nextSectionId(), 1, 'nextSectionId, lastResponse=2, nextSectionId=1');
|
||||
is($rJSON->nextResponseSectionIndex(), 1, 'nextResponseSectionIndex, lastResponse=2, nextResponseSectionIndex=1');
|
||||
cmp_deeply(
|
||||
$rJSON->nextSection,
|
||||
$rJSON->nextResponseSection,
|
||||
$rJSON->survey->section([1]),
|
||||
'lastResponse=2, nextSection = section 1'
|
||||
'lastResponse=2, nextResponseSection = section 1'
|
||||
);
|
||||
cmp_deeply(
|
||||
$rJSON->currentSection,
|
||||
$rJSON->survey->section([0]),
|
||||
'lastResponse=2, currentSection = section 0'
|
||||
is(
|
||||
$rJSON->lastResponseSectionIndex,
|
||||
0,
|
||||
'lastResponse=2, lastResponseSectionIndex = 0'
|
||||
);
|
||||
|
||||
$rJSON->lastResponse(6);
|
||||
is($rJSON->nextSectionId(), 3, 'nextSectionId, lastResponse=6, nextSectionId=3');
|
||||
is($rJSON->nextResponseSectionIndex(), 3, 'nextResponseSectionIndex, lastResponse=6, nextResponseSectionIndex=3');
|
||||
cmp_deeply(
|
||||
$rJSON->nextSection,
|
||||
$rJSON->nextResponseSection,
|
||||
$rJSON->survey->section([3]),
|
||||
'lastResponse=0, nextSection = section 3'
|
||||
'lastResponse=0, nextResponseSection = section 3'
|
||||
);
|
||||
cmp_deeply(
|
||||
$rJSON->currentSection,
|
||||
$rJSON->survey->section([3]),
|
||||
'lastResponse=6, currentSection = section 3'
|
||||
$rJSON->lastResponseSectionIndex,
|
||||
3,
|
||||
'lastResponse=6, lastResponseSectionIndex = 3'
|
||||
);
|
||||
|
||||
$rJSON->lastResponse(20);
|
||||
is($rJSON->nextSectionId(), undef, 'nextSectionId, lastResponse > surveyEnd, nextSectionId=undef');
|
||||
is($rJSON->nextResponseSectionIndex(), undef, 'nextResponseSectionIndex, lastResponse > surveyEnd, nextResponseSectionIndex=undef');
|
||||
|
||||
####################################################
|
||||
#
|
||||
|
|
@ -223,14 +225,14 @@ is($rJSON->nextSectionId(), undef, 'nextSectionId, lastResponse > surveyEnd, nex
|
|||
|
||||
$rJSON->lastResponse(20);
|
||||
ok($rJSON->surveyEnd, 'nextQuestions: lastResponse indicates end of survey');
|
||||
is_deeply($rJSON->nextQuestions, [], 'nextQuestions returns an empty array ref if there are no questions available');
|
||||
is_deeply([$rJSON->nextQuestions], [], 'nextQuestions returns an empty array if there are no questions available');
|
||||
$rJSON->survey->section([0])->{questionsPerPage} = 2;
|
||||
$rJSON->survey->section([1])->{questionsPerPage} = 2;
|
||||
$rJSON->survey->section([2])->{questionsPerPage} = 2;
|
||||
$rJSON->survey->section([3])->{questionsPerPage} = 2;
|
||||
$rJSON->lastResponse(-1);
|
||||
cmp_deeply(
|
||||
$rJSON->nextQuestions(),
|
||||
[$rJSON->nextQuestions],
|
||||
[
|
||||
superhashof({
|
||||
sid => 0,
|
||||
|
|
@ -262,7 +264,7 @@ cmp_deeply(
|
|||
|
||||
$rJSON->lastResponse(1);
|
||||
cmp_deeply(
|
||||
$rJSON->nextQuestions(),
|
||||
[$rJSON->nextQuestions],
|
||||
[
|
||||
superhashof({
|
||||
sid => 0,
|
||||
|
|
@ -286,9 +288,9 @@ cmp_deeply(
|
|||
|
||||
$rJSON->lastResponse(4);
|
||||
cmp_deeply(
|
||||
$rJSON->nextQuestions(),
|
||||
undef,
|
||||
'nextQuestions: returns undef if the next section is empty'
|
||||
[$rJSON->nextQuestions],
|
||||
[],
|
||||
'nextQuestions: returns an empty array if the next section is empty'
|
||||
);
|
||||
|
||||
####################################################
|
||||
|
|
@ -310,15 +312,90 @@ $rJSON->survey->question([3,1])->{variable} = 'goto 3-0'; ##Intentional duplica
|
|||
$rJSON->survey->question([3,2])->{variable} = 'goto 3-2';
|
||||
|
||||
$rJSON->lastResponse(0);
|
||||
$rJSON->goto('goto 80');
|
||||
$rJSON->processGoto('goto 80');
|
||||
is($rJSON->lastResponse(), 0, 'goto: no change in lastResponse if the variable cannot be found');
|
||||
$rJSON->goto('goto 1');
|
||||
$rJSON->processGoto('goto 1');
|
||||
is($rJSON->lastResponse(), 2, 'goto: works on existing section');
|
||||
$rJSON->goto('goto 0-1');
|
||||
$rJSON->processGoto('goto 0-1');
|
||||
is($rJSON->lastResponse(), 0, 'goto: works on existing question');
|
||||
$rJSON->goto('goto 3-0');
|
||||
$rJSON->processGoto('goto 3-0');
|
||||
is($rJSON->lastResponse(), 5, 'goto: finds first if there are duplicates');
|
||||
|
||||
####################################################
|
||||
#
|
||||
# processGotoExpression
|
||||
#
|
||||
####################################################
|
||||
throws_ok { $rJSON->parseGotoExpression() } 'WebGUI::Error::InvalidParam', 'processGotoExpression takes exception to empty arguments';
|
||||
is($rJSON->parseGotoExpression(q{}),
|
||||
undef, '.. and undef with empty expression');
|
||||
is($rJSON->parseGotoExpression('blah-dee-blah-blah'),
|
||||
undef, '.. and undef with duff expression');
|
||||
is($rJSON->parseGotoExpression(':'),
|
||||
undef, '.. and undef with missing target');
|
||||
is($rJSON->parseGotoExpression('t1:'),
|
||||
undef, '.. and undef with missing expression');
|
||||
cmp_deeply($rJSON->parseGotoExpression('t1: 1'),
|
||||
{ target => 't1', expression => '1'}, 'works for simple numeric expression');
|
||||
cmp_deeply($rJSON->parseGotoExpression('t1: 1 - 23 + 456 * (78 / 9.0)'),
|
||||
{ target => 't1', expression => '1 - 23 + 456 * (78 / 9.0)'}, 'works for expression using all algebraic tokens');
|
||||
is($rJSON->parseGotoExpression('t1: 1 + &'), undef, '.. but disallows expression containing non-whitelisted token');
|
||||
cmp_deeply($rJSON->parseGotoExpression('t1: 1 = 3'),
|
||||
{ target => 't1', expression => '1 == 3'}, 'converts single = to ==');
|
||||
cmp_deeply($rJSON->parseGotoExpression('t1: 1 != 3 <= 4 >= 5'),
|
||||
{ target => 't1', expression => '1 != 3 <= 4 >= 5'}, q{..but doesn't mess with other ops containing =});
|
||||
cmp_deeply($rJSON->parseGotoExpression('t1: q1 + q2 * q3 - 4', { q1 => 11, q2 => 22, q3 => 33}),
|
||||
{ target => 't1', expression => '11 + 22 * 33 - 4'}, 'substitues q for value');
|
||||
cmp_deeply($rJSON->parseGotoExpression('t1: a silly var name * 10 + another var name', { 'a silly var name' => 345, 'another var name' => 456}),
|
||||
{ target => 't1', expression => '345 * 10 + 456'}, '..it even works for vars with spaces in their names');
|
||||
is($rJSON->parseGotoExpression('t1: qX + 3', { q1 => '7'}),
|
||||
undef, q{..but doesn't like invalid var names});
|
||||
|
||||
####################################################
|
||||
#
|
||||
# gotoExpression
|
||||
#
|
||||
####################################################
|
||||
|
||||
$rJSON->survey->section([0])->{variable} = 's0';
|
||||
$rJSON->survey->section([2])->{variable} = 's2';
|
||||
$rJSON->survey->question([1,0])->{variable} = 's1q0';
|
||||
$rJSON->survey->answer([1,0,0])->{value} = 3;
|
||||
|
||||
$rJSON->lastResponse(2);
|
||||
$rJSON->recordResponses({
|
||||
'1-0comment' => 'Section 1, question 0 comment',
|
||||
'1-0-0' => 'First answer',
|
||||
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
|
||||
});
|
||||
is($rJSON->processGotoExpression('blah-dee-blah-blah'), undef, 'invalid gotoExpression is false');
|
||||
ok($rJSON->processGotoExpression('s0: s1q0 = 3'), '3 == 3 is true');
|
||||
ok(!$rJSON->processGotoExpression('s0: s1q0 = 4'), '3 == 4 is false');
|
||||
ok($rJSON->processGotoExpression('s0: s1q0 != 2'), '3 != 2 is true');
|
||||
ok(!$rJSON->processGotoExpression('s0: s1q0 != 3'), '3 != 3 is false');
|
||||
ok($rJSON->processGotoExpression('s0: s1q0 > 2'), '3 > 2 is true');
|
||||
ok($rJSON->processGotoExpression('s0: s1q0 < 4'), '3 < 2 is true');
|
||||
ok(!$rJSON->processGotoExpression('s0: s1q0 >= 4'), '3 >= 4 is false');
|
||||
ok(!$rJSON->processGotoExpression('s0: s1q0 <= 2'), '3 >= 4 is false');
|
||||
|
||||
cmp_deeply($rJSON->processGotoExpression(<<"END_EXPRESSION"), {target => 's2', expression => '3 == 3'}, 'first true expression wins');
|
||||
s0: s1q0 <= 2
|
||||
s2: s1q0 = 3
|
||||
END_EXPRESSION
|
||||
|
||||
ok(!$rJSON->processGotoExpression(<<"END_EXPRESSION"), 'but multiple false expressions still false');
|
||||
s0: s1q0 <= 2
|
||||
s2: s1q0 = 345
|
||||
END_EXPRESSION
|
||||
|
||||
$rJSON->processGotoExpression('s0: s1q0 = 3');
|
||||
is($rJSON->lastResponse(), -1, '.. lastResponse changed to -1 due to processGoto(s0)');
|
||||
$rJSON->processGotoExpression('s2: s1q0 = 3');
|
||||
is($rJSON->lastResponse(), 4, '.. lastResponse changed to 4 due to processGoto(s2)');
|
||||
|
||||
$rJSON->responses({});
|
||||
$rJSON->questionsAnswered(-1 * $rJSON->questionsAnswered);
|
||||
|
||||
####################################################
|
||||
#
|
||||
# recordResponses
|
||||
|
|
@ -328,7 +405,7 @@ is($rJSON->lastResponse(), 5, 'goto: finds first if there are duplicates');
|
|||
$rJSON->lastResponse(4);
|
||||
my $terminals;
|
||||
cmp_deeply(
|
||||
$rJSON->recordResponses($session, {}),
|
||||
$rJSON->recordResponses({}),
|
||||
[ 0, undef ],
|
||||
'recordResponses, if section has no questions, returns terminal info in the section. With no terminal info, returns [0, undef]',
|
||||
);
|
||||
|
|
@ -339,7 +416,7 @@ $rJSON->survey->section([2])->{terminalUrl} = '/terminal';
|
|||
|
||||
$rJSON->lastResponse(4);
|
||||
cmp_deeply(
|
||||
$rJSON->recordResponses($session, {}),
|
||||
$rJSON->recordResponses({}),
|
||||
[ 1, '/terminal' ],
|
||||
'recordResponses, if section has no questions, returns terminal info in the section.',
|
||||
);
|
||||
|
|
@ -350,7 +427,7 @@ $rJSON->survey->question([1,0])->{terminalUrl} = 'question 1-0 terminal';
|
|||
|
||||
$rJSON->lastResponse(2);
|
||||
cmp_deeply(
|
||||
$rJSON->recordResponses($session, {
|
||||
$rJSON->recordResponses({
|
||||
'1-0comment' => 'Section 1, question 0 comment',
|
||||
'1-0-0' => 'First answer',
|
||||
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
|
||||
|
|
@ -358,6 +435,7 @@ cmp_deeply(
|
|||
[ 1, 'question 1-0 terminal' ],
|
||||
'recordResponses: question terminal overrides section terminal',
|
||||
);
|
||||
|
||||
is($rJSON->lastResponse(), 4, 'lastResponse advanced to next page of questions');
|
||||
is($rJSON->questionsAnswered, 1, 'questionsAnswered=1, answered one question');
|
||||
|
||||
|
|
@ -370,7 +448,7 @@ cmp_deeply(
|
|||
'1-0-0' => {
|
||||
comment => 'Section 1, question 0, answer 0 comment',
|
||||
'time' => num(time(), 3),
|
||||
value => 1,
|
||||
value => 1, # 'recordedAnswer' value used because question is multi-choice
|
||||
},
|
||||
'1-1' => {
|
||||
comment => undef,
|
||||
|
|
@ -379,14 +457,44 @@ cmp_deeply(
|
|||
'recordResponses: recorded responses correctly, two questions, one answer, comments, values and time'
|
||||
);
|
||||
|
||||
|
||||
# Repeat with non multi-choice question, to check that submitted answer value is used
|
||||
# instead of recordedValue
|
||||
$rJSON->survey->question([1,0])->{questionType} = 'Text';
|
||||
$rJSON->lastResponse(2);
|
||||
$rJSON->questionsAnswered(-1 * $rJSON->questionsAnswered);
|
||||
$rJSON->recordResponses({
|
||||
'1-0comment' => 'Section 1, question 0 comment',
|
||||
'1-0-0' => 'First answer',
|
||||
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
|
||||
});
|
||||
cmp_deeply(
|
||||
$rJSON->responses,
|
||||
{
|
||||
'1-0' => {
|
||||
comment => 'Section 1, question 0 comment',
|
||||
},
|
||||
'1-0-0' => {
|
||||
comment => 'Section 1, question 0, answer 0 comment',
|
||||
'time' => num(time(), 3),
|
||||
value => 'First answer', # submitted answer value used this time because non-mc
|
||||
},
|
||||
'1-1' => {
|
||||
comment => undef,
|
||||
}
|
||||
},
|
||||
'recordResponses: recorded responses correctly, two questions, one answer, comments, values and time'
|
||||
);
|
||||
$rJSON->survey->question([1,0])->{questionType} = 'Multiple Choice'; # revert change
|
||||
|
||||
$rJSON->survey->question([1,0,0])->{terminal} = 1;
|
||||
$rJSON->survey->question([1,0,0])->{terminalUrl} = 'answer 1-0-0 terminal';
|
||||
$rJSON->{responses} = {};
|
||||
$rJSON->responses({});
|
||||
$rJSON->lastResponse(2);
|
||||
$rJSON->questionsAnswered(-1 * $rJSON->questionsAnswered);
|
||||
|
||||
cmp_deeply(
|
||||
$rJSON->recordResponses($session, {
|
||||
$rJSON->recordResponses({
|
||||
'1-0comment' => 'Section 1, question 0 comment',
|
||||
'1-0-0' => "\t\t\t\n\n\n\t\t\t", #SOS in whitespace
|
||||
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
|
||||
|
|
@ -408,6 +516,9 @@ cmp_deeply(
|
|||
'recordResponses: if the answer is all whitespace, it is skipped over'
|
||||
);
|
||||
is($rJSON->questionsAnswered, 0, 'question was all whitespace, not answered');
|
||||
#delete $rJSON->{_session};
|
||||
#delete $rJSON->survey->{_session};
|
||||
#diag(Dumper($rJSON));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +530,7 @@ is($rJSON->questionsAnswered, 0, 'question was all whitespace, not answered');
|
|||
|
||||
sub buildSurveyJSON {
|
||||
my $session = shift;
|
||||
my $sjson = WebGUI::Asset::Wobject::Survey::SurveyJSON->new(undef, $session->log);
|
||||
my $sjson = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session);
|
||||
##Build 4 sections. Remembering that one is created by default when you make an empty SurveyJSON object
|
||||
$sjson->newObject([]);
|
||||
$sjson->newObject([]);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ my $session = WebGUI::Test->session;
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
my $tests = 96;
|
||||
my $tests = 132;
|
||||
plan tests => $tests + 1 + 3;
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -126,10 +126,10 @@ skip $tests, "Unable to load SurveyJSON" unless $usedOk;
|
|||
#
|
||||
####################################################
|
||||
|
||||
$surveyJSON = WebGUI::Asset::Wobject::Survey::SurveyJSON->new('{}', $session->log);
|
||||
$surveyJSON = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session, '{}');
|
||||
isa_ok($surveyJSON, 'WebGUI::Asset::Wobject::Survey::SurveyJSON');
|
||||
|
||||
my $sJSON2 = WebGUI::Asset::Wobject::Survey::SurveyJSON->new(undef, $session->log);
|
||||
my $sJSON2 = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session);
|
||||
isa_ok($sJSON2, 'WebGUI::Asset::Wobject::Survey::SurveyJSON', 'even with absolutely no JSON');
|
||||
undef $sJSON2;
|
||||
|
||||
|
|
@ -173,9 +173,8 @@ cmp_deeply(
|
|||
'new: empty JSON in constructor causes 1 new, default section to be created',
|
||||
);
|
||||
|
||||
$surveyJSON = WebGUI::Asset::Wobject::Survey::SurveyJSON->new(
|
||||
$surveyJSON = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session,
|
||||
'{ "sections" : [], "survey" : {} }',
|
||||
$session->log,
|
||||
);
|
||||
|
||||
cmp_deeply(
|
||||
|
|
@ -188,16 +187,14 @@ cmp_deeply(
|
|||
|
||||
lives_ok
|
||||
{
|
||||
my $foo = WebGUI::Asset::Wobject::Survey::SurveyJSON->new(
|
||||
qq!{ "survey" : "on 16\x{201d} hand-crocheted Cord" }!,
|
||||
$session->log
|
||||
my $foo = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session,
|
||||
encode_json({survey => "on 16\x{201d}" }),
|
||||
);
|
||||
}
|
||||
'new handles wide characters';
|
||||
|
||||
$sJSON2 = WebGUI::Asset::Wobject::Survey::SurveyJSON->new(
|
||||
$sJSON2 = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session,
|
||||
'{ "sections" : [ { "type" : "section" } ], "survey" : {} }',
|
||||
$session->log,
|
||||
);
|
||||
|
||||
cmp_deeply(
|
||||
|
|
@ -276,7 +273,7 @@ cmp_deeply(
|
|||
#
|
||||
####################################################
|
||||
|
||||
$surveyJSON = WebGUI::Asset::Wobject::Survey::SurveyJSON->new('{}', $session->log);
|
||||
$surveyJSON = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session, '{}');
|
||||
{
|
||||
my $section = $surveyJSON->section([0]);
|
||||
$section->{title} = 'Section 0';
|
||||
|
|
@ -2003,18 +2000,81 @@ cmp_deeply(
|
|||
'updateQuestionAnswers: Dual Slider - Range'
|
||||
);
|
||||
|
||||
####################################################
|
||||
#
|
||||
# totalSections
|
||||
#
|
||||
####################################################
|
||||
{
|
||||
my $s = WebGUI::Asset::Wobject::Survey::SurveyJSON->new($session, '{}');
|
||||
is($s->totalSections, 1, 'a');
|
||||
is($s->totalQuestions, 0, 'a');
|
||||
is($s->totalAnswers, 0, 'a');
|
||||
|
||||
# Add a new section
|
||||
my $address = $s->newObject([]);
|
||||
is($s->totalSections, 2, 'Now there are 2 sections');
|
||||
is($s->totalQuestions, 0, '..but still no questions');
|
||||
is($s->totalAnswers, 0, '..and no answers');
|
||||
|
||||
# Add a question to first section
|
||||
$address = $s->newObject([0]);
|
||||
is($s->totalSections, 2, 'Still 2 sections');
|
||||
is($s->totalQuestions, 1, '..and now 1 question');
|
||||
is($s->totalQuestions([0]), 1, '..in the intended section');
|
||||
is($s->totalAnswers, 0, '..but still no answers');
|
||||
|
||||
# Add a question to second section
|
||||
$address = $s->newObject([1]);
|
||||
is($s->totalSections, 2, 'Still 2 sections');
|
||||
is($s->totalQuestions, 2, '..and now 2 questions overall');
|
||||
is($s->totalQuestions([0]), 1, '..one in the first section');
|
||||
is($s->totalQuestions([1]), 1, '..and one in the second section');
|
||||
is($s->totalAnswers, 0, '..but still no answers');
|
||||
|
||||
# Add another question to second section
|
||||
$address = $s->newObject([1]);
|
||||
is($s->totalSections, 2, 'Still 2 sections');
|
||||
is($s->totalQuestions, 3, '..and now 3 questions overall');
|
||||
is($s->totalQuestions([0]), 1, '..one in the first section');
|
||||
is($s->totalQuestions([1]), 2, '..and two in the second section');
|
||||
is($s->totalAnswers, 0, '..but still no answers');
|
||||
|
||||
# Add an answer to second section, first question
|
||||
$address = $s->newObject([1,0]);
|
||||
is($s->totalSections, 2, 'Still 2 sections');
|
||||
is($s->totalQuestions, 3, '..and 3 questions');
|
||||
is($s->totalAnswers, 1, '..and now 1 answer overall');
|
||||
is($s->totalAnswers([0,0]), 0, '..0 in first question');
|
||||
is($s->totalAnswers([1,0]), 1, '..1 in second question');
|
||||
is($s->totalAnswers([1,1]), 0, '..0 in third question');
|
||||
|
||||
# Add an answer to second section, second question
|
||||
$address = $s->newObject([1,1]);
|
||||
is($s->totalSections, 2, 'Still 2 sections');
|
||||
is($s->totalQuestions, 3, '..and 3 questions');
|
||||
is($s->totalAnswers, 2, '..and now 2 answer overall');
|
||||
is($s->totalAnswers([0,0]), 0, '..0 in first question');
|
||||
is($s->totalAnswers([1,0]), 1, '..1 in second question');
|
||||
is($s->totalAnswers([1,1]), 1, '..1 in third question');
|
||||
|
||||
# Add a second answer to second section, second question
|
||||
$address = $s->newObject([1,1]);
|
||||
is($s->totalSections, 2, 'Still 2 sections');
|
||||
is($s->totalQuestions, 3, '..and 3 questions');
|
||||
is($s->totalAnswers, 3, '..and now 3 answer overall');
|
||||
is($s->totalAnswers([0,0]), 0, '..0 in first question');
|
||||
is($s->totalAnswers([1,0]), 1, '..1 in second question');
|
||||
is($s->totalAnswers([1,1]), 2, '..2 in third question');
|
||||
}
|
||||
|
||||
####################################################
|
||||
#
|
||||
# log
|
||||
#
|
||||
####################################################
|
||||
|
||||
WebGUI::Test->interceptLogging;
|
||||
|
||||
my $logger = $surveyJSON->log("Everyone in here is innocent");
|
||||
is ($WebGUI::Test::logger_warns, undef, 'Did not log a warn');
|
||||
is ($WebGUI::Test::logger_info, undef, 'Did not log an info');
|
||||
is ($WebGUI::Test::logger_error, "Everyone in here is innocent", 'Logged an error');
|
||||
isa_ok($surveyJSON->session, 'WebGUI::Session', 'session() accessor works');
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2030,7 +2090,7 @@ is ($WebGUI::Test::logger_error, "Everyone in here is innocent", 'Logged an erro
|
|||
sub summarizeSectionSkeleton {
|
||||
my ($skeleton) = @_;
|
||||
my $summary = [];
|
||||
foreach my $section (@{ $skeleton->{sections} }) {
|
||||
foreach my $section (@{ $skeleton->{_sections} }) {
|
||||
my $summarySection = {
|
||||
title => $section->{title},
|
||||
questions => [],
|
||||
|
|
@ -2091,6 +2151,7 @@ sub getBareSkeletons {
|
|||
terminal => 0,
|
||||
terminalUrl => '',
|
||||
goto => '',
|
||||
gotoExpression => '',
|
||||
timeLimit => 0,
|
||||
type => 'section',
|
||||
questions => [],
|
||||
|
|
@ -2111,6 +2172,8 @@ sub getBareSkeletons {
|
|||
textInButton => 0,
|
||||
type => 'question',
|
||||
answers => [],
|
||||
goto => '',
|
||||
gotoExpression => '',
|
||||
},
|
||||
{
|
||||
text => '',
|
||||
|
|
@ -2118,6 +2181,7 @@ sub getBareSkeletons {
|
|||
textCols => 10,
|
||||
textRows => 5,
|
||||
goto => '',
|
||||
gotoExpression => '',
|
||||
recordedAnswer => '',
|
||||
isCorrect => 1,
|
||||
min => 1,
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ is( $mime->parts(0)->as_string =~ m/\n/, $newlines,
|
|||
#----------------------------------------------------------------------------
|
||||
# Test addHtml
|
||||
$mail = WebGUI::Mail::Send->create( $session );
|
||||
my $text = <<'EOF';
|
||||
$text = <<'EOF';
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Suspendisse eu lacus ut ligula fringilla elementum. Cras condimentum, velit commodo pretium semper, odio ante accumsan orci, a ultrices risus justo a nulla. Aliquam erat volutpat.
|
||||
EOF
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ $mime = $mail->getMimeEntity;
|
|||
# TODO: Test that addHtml creates a body with the right content type
|
||||
|
||||
# addHtml should add newlines after 78 characters
|
||||
my $newlines = length $text / 78;
|
||||
$newlines = length $text / 78;
|
||||
is( $mime->parts(0)->as_string =~ m/\n/, $newlines,
|
||||
"addHtml should add newlines after 78 characters",
|
||||
);
|
||||
|
|
@ -107,7 +107,7 @@ is( $mime->parts(0)->as_string =~ m/\n/, $newlines,
|
|||
#----------------------------------------------------------------------------
|
||||
# Test addHtmlRaw
|
||||
$mail = WebGUI::Mail::Send->create( $session );
|
||||
my $text = <<'EOF';
|
||||
$text = <<'EOF';
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Suspendisse eu lacus ut ligula fringilla elementum. Cras condimentum, velit commodo pretium semper, odio ante accumsan orci, a ultrices risus justo a nulla. Aliquam erat volutpat.
|
||||
EOF
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ $mime = $mail->getMimeEntity;
|
|||
# TODO: Test that addHtmlRaw doesn't add an HTML wrapper
|
||||
|
||||
# addHtmlRaw should add newlines after 78 characters
|
||||
my $newlines = length $text / 78;
|
||||
$newlines = length $text / 78;
|
||||
is( $mime->parts(0)->as_string =~ m/\n/, $newlines,
|
||||
"addHtmlRaw should add newlines after 78 characters",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ my $outputBuffer;
|
|||
open my $outputHandle, '>', \$outputBuffer or die "Unable to create scalar filehandle: $!\n";
|
||||
$newSession->output->setHandle($outputHandle);
|
||||
WEBGUI_FATAL: {
|
||||
$newSession->log->fatal();
|
||||
$newSession->log->fatal('Bad things are happenning');
|
||||
}
|
||||
ok(1, 'fatal: recovered from fatal okay');
|
||||
TODO: {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use FindBin;
|
|||
use strict;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use Test::More;
|
||||
use Scalar::Util qw/refaddr/;
|
||||
use WebGUI::Test; # Must use this before any other WebGUI modules
|
||||
use WebGUI::Session;
|
||||
use WebGUI::Asset;
|
||||
|
|
@ -32,7 +33,7 @@ my $i18n = WebGUI::International->new($session, "Shop");
|
|||
#----------------------------------------------------------------------------
|
||||
# Tests
|
||||
|
||||
plan tests => 21; # Increment this number for each test you create
|
||||
plan tests => 23; # Increment this number for each test you create
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# put your tests here
|
||||
|
|
@ -91,6 +92,23 @@ isa_ok($cart->getAddressBook, "WebGUI::Shop::AddressBook", "can get an address b
|
|||
$cart->empty;
|
||||
is($session->db->quickScalar("select count(*) from cartItem where cartId=?",[$cart->getId]), 0, "Items are removed from cart.");
|
||||
|
||||
my $session2 = WebGUI::Session->open(WebGUI::Test->root, WebGUI::Test->file);
|
||||
$session2->user({userId => 3});
|
||||
my $cart2 = WebGUI::Shop::Cart->newBySession($session2);
|
||||
isnt(
|
||||
refaddr $cart->getAddressBook,
|
||||
refaddr $cart2->getAddressBook,
|
||||
'Different carts with different sessions have different AddressBooks'
|
||||
);
|
||||
$cart2->delete;
|
||||
|
||||
my $cart3 = WebGUI::Shop::Cart->newBySession($session);
|
||||
isnt(
|
||||
refaddr $cart->getAddressBook,
|
||||
refaddr $cart3->getAddressBook,
|
||||
'Different carts with same sessions will each have different AddressBooks since no book has been assigned yet.'
|
||||
);
|
||||
$cart3->delete;
|
||||
|
||||
$cart->delete;
|
||||
is($cart->delete, undef, "Can destroy cart.");
|
||||
|
|
@ -101,5 +119,5 @@ $product->purge;
|
|||
#----------------------------------------------------------------------------
|
||||
# Cleanup
|
||||
END {
|
||||
|
||||
$session2->close;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -287,8 +287,6 @@ my $tempStor = WebGUI::Storage->createTemp($session);
|
|||
|
||||
isa_ok( $tempStor, "WebGUI::Storage", "createTemp creates WebGUI::Storage object");
|
||||
is (substr($tempStor->getPathFrag, 0, 5), 'temp/', 'createTemp puts stuff in the temp directory');
|
||||
use Data::Dumper;
|
||||
diag Dumper $tempStor->getErrors();
|
||||
ok (-e $tempStor->getPath(), 'createTemp: directory was created');
|
||||
|
||||
####################################################
|
||||
|
|
|
|||
5
t/User.t
5
t/User.t
|
|
@ -20,7 +20,7 @@ use WebGUI::Cache;
|
|||
use WebGUI::User;
|
||||
use WebGUI::ProfileField;
|
||||
|
||||
use Test::More tests => 143; # increment this value for each test you create
|
||||
use Test::More tests => 144; # increment this value for each test you create
|
||||
use Test::Deep;
|
||||
|
||||
my $session = WebGUI::Test->session;
|
||||
|
|
@ -577,7 +577,8 @@ undef $neighborClone;
|
|||
################################################################
|
||||
|
||||
$friend->profileField('allowPrivateMessages', 'all');
|
||||
is ($friend->acceptsPrivateMessages(1), 1, 'acceptsPrivateMessages: when allowPrivateMessages=all, anyone can send messages');
|
||||
is ($friend->acceptsPrivateMessages($neighbor->userId), 1, 'acceptsPrivateMessages: when allowPrivateMessages=all, anyone can send messages');
|
||||
is ($friend->acceptsPrivateMessages(1), 0, 'acceptsPrivateMessages: when allowPrivateMessages=all, visitor can\'t send messages');
|
||||
$friend->profileField('allowPrivateMessages', 'none');
|
||||
is ($friend->acceptsPrivateMessages($friend->userId), 0, 'acceptsPrivateMessages: when allowPrivateMessages=none, no one can send messages');
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ is_deeply($wf->getCrons, [], 'workflow has no crons');
|
|||
isa_ok(WebGUI::Workflow->getList($session), 'HASH', 'getList returns a hashref');
|
||||
|
||||
ok(!isIn($wfId, keys %{WebGUI::Workflow->getList($session)}), 'workflow not in enabled list');
|
||||
is(scalar keys %{WebGUI::Workflow->getList($session)}, 10, 'There are ten default workflows, of all types, shipped with WebGUI');
|
||||
is(scalar keys %{WebGUI::Workflow->getList($session)}, 11, 'There are eleven default workflows, of all types, shipped with WebGUI');
|
||||
|
||||
$wf->set({enabled => 1});
|
||||
ok($wf->get('enabled'), 'workflow is enabled');
|
||||
|
|
|
|||
101
t/Workflow/Activity/BucketPassiveAnalytics.t
Normal file
101
t/Workflow/Activity/BucketPassiveAnalytics.t
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
|
||||
use FindBin;
|
||||
use strict;
|
||||
use lib "$FindBin::Bin/../../lib";
|
||||
#use DB;
|
||||
|
||||
use WebGUI::Test;
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::PassiveAnalytics::Rule;
|
||||
use WebGUI::Workflow::Activity::BucketPassiveAnalytics;
|
||||
use WebGUI::Text;
|
||||
|
||||
use Test::More;
|
||||
|
||||
plan tests => 1; # increment this value for each test you create
|
||||
|
||||
my $session = WebGUI::Test->session;
|
||||
$session->user({userId => 3});
|
||||
|
||||
my $workflow = WebGUI::Workflow->new($session, 'PassiveAnalytics000001');
|
||||
my $activities = $workflow->getActivities();
|
||||
##Note, they're in order, and the order is known.
|
||||
$activities->[0]->set('deltaInterval', 100);
|
||||
$activities->[1]->set('userId', 0); ##To disable sending emails
|
||||
|
||||
my $instance = WebGUI::Workflow::Instance->create($session,
|
||||
{
|
||||
workflowId => $workflow->getId,
|
||||
skipSpectreNotification => 1,
|
||||
priority => 1,
|
||||
}
|
||||
);
|
||||
##Rule label, url, and regexp
|
||||
my @ruleSets = (
|
||||
['home', '/home', '^\/home' ],
|
||||
['one', '/one', '^\/one$' ],
|
||||
['two', '/two', '^\/two$' ],
|
||||
['three', '/three', '^\/three$' ],
|
||||
['end', '/blah/blah/end', 'end$' ],
|
||||
['casa', '/home/casa', 'casa$' ],
|
||||
['uno', '/one/uno', 'uno$' ],
|
||||
['dos', '/two/dos', 'dos$' ],
|
||||
['tres', '/three/tres', 'tres$' ],
|
||||
['alpha', '/alpha/aee', '.alpha.aee' ],
|
||||
['beta', '/beta/bee', '.beta.bee' ],
|
||||
['gamma', '/gamma/cee', '.gamma.cee' ],
|
||||
['delta', '/delta/dee', '.delta.dee' ],
|
||||
['eee', '/epsilon/eee', 'eee$' ],
|
||||
['thingy1', '/thingy?thingId=1', '^.thingy\?thingId=1' ],
|
||||
['rogerRoger', '/roger/roger', '(?:\/roger){2}' ],
|
||||
['roger', '/roger', '^\/roger' ],
|
||||
['thingy2', '/thingy?thingId=2', '^.thingy\?thingId=2' ],
|
||||
['beet', '/beta/beet', '.beta.beet' ],
|
||||
['zero', '/yelnats', 'yelnats' ],
|
||||
);
|
||||
|
||||
my @url2 = @ruleSets;
|
||||
while (my $spec = shift @url2) {
|
||||
my ($bucket, undef, $regexp) = @{ $spec };
|
||||
WebGUI::PassiveAnalytics::Rule->create($session, { bucketName => $bucket, regexp => $regexp });
|
||||
}
|
||||
|
||||
my @urls = map {$_->[1]} @ruleSets;
|
||||
loadLogData($session, @urls);
|
||||
|
||||
##Build rulesets
|
||||
|
||||
##Now, run it and wait for it to finish
|
||||
my $counter = 0;
|
||||
#DB::enable_profile();
|
||||
PAUSE: while (my $retval = $instance->run()) {
|
||||
last PAUSE if $retval eq 'done';
|
||||
last PAUSE if $counter++ >= 16;
|
||||
}
|
||||
#DB::disable_profile();
|
||||
|
||||
ok(1, 'One test');
|
||||
|
||||
END {
|
||||
$session->db->write('delete from passiveLog');
|
||||
$session->db->write('delete from analyticRule');
|
||||
$instance->delete;
|
||||
}
|
||||
|
||||
sub loadLogData {
|
||||
my ($session, @urls) = @_;
|
||||
$session->db->write('delete from passiveLog');
|
||||
my $insert = $session->db->prepare(
|
||||
q!insert into passiveLog (userId, sessionId, timeStamp, url, assetId) VALUES (?,?,?,?,'assetId')!
|
||||
);
|
||||
my $logCount = 15000;
|
||||
my $counter;
|
||||
my $startTime = 1000;
|
||||
my $numUrls = scalar @urls;
|
||||
while ($counter++ < $logCount) {
|
||||
my $index = int rand($numUrls);
|
||||
my $url = $urls[$index];
|
||||
$insert->execute([2, 25, $startTime, $url]);
|
||||
$startTime += int(rand(10))+1;
|
||||
}
|
||||
}
|
||||
223
www/extras/VendorPayout/vendorPayout.js
Normal file
223
www/extras/VendorPayout/vendorPayout.js
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
if (typeof WebGUI == "undefined" || !WebGUI) {
|
||||
var WebGUI = {};
|
||||
}
|
||||
|
||||
WebGUI.VendorPayout = function ( containerId ) {
|
||||
var obj = this;
|
||||
this.container = document.getElementById( containerId );
|
||||
|
||||
// Vendors data table
|
||||
this.vendorList = document.createElement('div');
|
||||
this.container.appendChild( this.vendorList );
|
||||
|
||||
// (De)schedule buttons
|
||||
this.buttonDiv = document.createElement('div');
|
||||
this.container.appendChild( this.buttonDiv );
|
||||
this.scheduleAllButton = new YAHOO.widget.Button({ label: 'Schedule all', container: this.buttonDiv });
|
||||
this.descheduleAllButton = new YAHOO.widget.Button({ label: 'Deschedule all', container: this.buttonDiv });
|
||||
|
||||
// Submit button
|
||||
this.submitPayoutsButton = new YAHOO.widget.Button({ label: 'Submit Scheduled Payouts', container: this.buttonDiv });
|
||||
this.submitPayoutsButton.on( 'click', function () {
|
||||
YAHOO.util.Connect.asyncRequest( 'GET', '/?shop=vendor;method=submitScheduledPayouts', {
|
||||
success: obj.initialize,
|
||||
scope: obj
|
||||
} );
|
||||
} );
|
||||
|
||||
// Payout details data table
|
||||
this.payoutDetails = document.createElement('div');
|
||||
this.container.appendChild( this.payoutDetails );
|
||||
|
||||
|
||||
this.itemBaseUrl = '/?shop=vendor;method=payoutDataAsJSON;';
|
||||
|
||||
// Initialise tables
|
||||
this.initialize();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
WebGUI.VendorPayout.prototype.initialize = function () {
|
||||
this.initVendorList();
|
||||
this.initPayoutDetails();
|
||||
this.initButtons();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
WebGUI.VendorPayout.prototype.initVendorList = function () {
|
||||
var obj = this;
|
||||
this.vendorSchema = [
|
||||
{ key: 'vendorId' },
|
||||
{ key: 'name' },
|
||||
{ key: 'Scheduled' },
|
||||
{ key: 'NotPaid' }
|
||||
];
|
||||
|
||||
// setup data source
|
||||
var url = '/?shop=vendor;method=vendorTotalsAsJSON;';
|
||||
this.vendorDataSource = new YAHOO.util.DataSource( url );
|
||||
this.vendorDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
|
||||
this.vendorDataSource.responseSchema = {
|
||||
resultsList : 'vendors',
|
||||
fields : this.vendorSchema
|
||||
};
|
||||
|
||||
// initialize data table
|
||||
this.vendorDataTable = new YAHOO.widget.DataTable( this.vendorList, this.vendorSchema, this.vendorDataSource, {
|
||||
selectionMode : 'single'
|
||||
} );
|
||||
|
||||
// add handlers for rowhighlighting/selection
|
||||
this.vendorDataTable.subscribe( "rowClickEvent", this.vendorDataTable.onEventSelectRow );
|
||||
this.vendorDataTable.subscribe( "rowMouseoverEvent", this.vendorDataTable.onEventHighlightRow );
|
||||
this.vendorDataTable.subscribe( "rowMouseoutEvent", this.vendorDataTable.onEventUnhighlightRow );
|
||||
|
||||
// add an additional row click handler that fetches this vendor's data for the payout details table
|
||||
this.vendorDataTable.subscribe( "rowClickEvent", function (e) {
|
||||
var record = this.getRecord( e.target );
|
||||
obj.currentVendorId = record.getData( 'vendorId' );
|
||||
obj.currentVendorRow = record;
|
||||
|
||||
obj.refreshItemDataTable();
|
||||
} );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
WebGUI.VendorPayout.prototype.refreshItemDataTable = function () {
|
||||
// Set the url here so pagination keeps working...
|
||||
this.itemDataSource.liveData = this.itemBaseUrl + 'vendorId=' + this.currentVendorId +';';
|
||||
|
||||
this.itemDataSource.sendRequest( '', {
|
||||
success : this.itemDataTable.onDataReturnInitializeTable, //ReplaceRows,
|
||||
scope : this.itemDataTable
|
||||
} );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
WebGUI.VendorPayout.prototype.refreshVendorRow = function () {
|
||||
var obj = this;
|
||||
this.vendorDataSource.sendRequest( 'vendorId=' + this.currentVendorId, {
|
||||
// onDataReturnUpdateRows is not available in yui 2.6.0...
|
||||
success : function ( req, response , payload ) {
|
||||
this.updateRow( obj.currentVendorRow, response.results[0] );
|
||||
},
|
||||
scope : this.vendorDataTable
|
||||
} );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
WebGUI.VendorPayout.prototype.initPayoutDetails = function () {
|
||||
var obj = this;
|
||||
this.itemSchema = [
|
||||
{ key: 'itemId' },
|
||||
{ key: 'configuredTitle' },
|
||||
{ key: 'price' },
|
||||
{ key: 'quantity' },
|
||||
{ key: 'vendorPayoutAmount' },
|
||||
{ key: 'vendorPayoutStatus' }
|
||||
]
|
||||
|
||||
// Create a row formatter to highlight Scheduled payouts
|
||||
var rowFormatter = function ( tr, record ) {
|
||||
if (record.getData('vendorPayoutStatus') === 'Scheduled') {
|
||||
YAHOO.util.Dom.addClass( tr, 'scheduled' );
|
||||
}
|
||||
else {
|
||||
YAHOO.util.Dom.removeClass( tr, 'scheduled' );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Instanciate the datasource.
|
||||
this.itemDataSource = new YAHOO.util.DataSource( this.itemBaseUrl );
|
||||
this.itemDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
|
||||
this.itemDataSource.responseSchema = {
|
||||
resultsList : 'results',
|
||||
fields : this.itemSchema,
|
||||
metaFields : { totalRecords : 'totalRecords' }
|
||||
};
|
||||
|
||||
// Instanciate the DataTable.
|
||||
this.itemDataTable = new YAHOO.widget.DataTable( this.payoutDetails, this.itemSchema, this.itemDataSource, {
|
||||
dynamicData : true,
|
||||
formatRow : rowFormatter,
|
||||
paginator : new YAHOO.widget.Paginator({ rowsPerPage:10 } ) //, updateOnChange: true })
|
||||
});
|
||||
this.itemDataTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
|
||||
// For some reason oPayload is undefined when we're switch vendors. This is a hack to
|
||||
// still set the paginator correctly.
|
||||
if ( !oPayload ) {
|
||||
oPayload = this;
|
||||
var paginator = this.get('paginator');
|
||||
paginator.set( 'totalRecords', parseInt( oResponse.meta.totalRecords,10) );
|
||||
}
|
||||
oPayload.totalRecords = oResponse.meta.totalRecords;
|
||||
return oPayload;
|
||||
};
|
||||
|
||||
// Add event handlers for mouseover highlighting
|
||||
this.itemDataTable.subscribe( "rowMouseoverEvent", this.itemDataTable.onEventHighlightRow );
|
||||
this.itemDataTable.subscribe( "rowMouseoutEvent", this.itemDataTable.onEventUnhighlightRow );
|
||||
|
||||
// Add a row click handler which takes care of switching between Scheduled and NotPaid.
|
||||
this.itemDataTable.subscribe( "rowClickEvent", function (e) {
|
||||
var record = this.getRecord( e.target );
|
||||
var callback = {
|
||||
scope : this,
|
||||
success : function ( o ) {
|
||||
var status = o.responseText;
|
||||
if ( status.match(/^error/) ) {
|
||||
alert( status );
|
||||
return;
|
||||
}
|
||||
|
||||
// Update status cell contents
|
||||
this.updateCell( record, 'vendorPayoutStatus', status );
|
||||
|
||||
// Update row higlighting
|
||||
rowFormatter( this.getTrEl( record ), record );
|
||||
|
||||
// Update vendor row
|
||||
obj.refreshVendorRow();
|
||||
}
|
||||
};
|
||||
|
||||
var status = record.getData( 'vendorPayoutStatus' ) === 'NotPaid' ? 'Scheduled' : 'NotPaid';
|
||||
var url = '/?shop=vendor;method=setPayoutStatus' + ';itemId=' + record.getData( 'itemId' ) + ';status=' + status;
|
||||
YAHOO.util.Connect.asyncRequest( 'post', url, callback );
|
||||
} );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
WebGUI.VendorPayout.prototype.initButtons = function () {
|
||||
var obj = this;
|
||||
|
||||
var updateAll = function ( status ) {
|
||||
// TODO: Make this range based.
|
||||
var records = obj.itemDataTable.getRecordSet().getRecords();
|
||||
var itemIds = new Array;
|
||||
for (i = 0; i < records.length; i++) {
|
||||
itemIds.push( 'itemId=' + records[i].getData( 'itemId' ) );
|
||||
}
|
||||
|
||||
var postdata = itemIds.join('&');
|
||||
var url = '/?shop=vendor&method=setPayoutStatus&status=' + status;
|
||||
var callback = {
|
||||
success: function (o) {
|
||||
this.refreshItemDataTable();
|
||||
this.refreshVendorRow();
|
||||
},
|
||||
scope: obj
|
||||
};
|
||||
|
||||
YAHOO.util.Connect.asyncRequest( 'POST', url, callback, postdata );
|
||||
}
|
||||
|
||||
this.scheduleAllButton.on( 'click', function () { updateAll( 'Scheduled' ) } );
|
||||
this.descheduleAllButton.on( 'click', function () { updateAll( 'NotPaid' ) } );
|
||||
|
||||
}
|
||||
|
||||
BIN
www/extras/adminConsole/assetHistory.gif
Normal file
BIN
www/extras/adminConsole/assetHistory.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
www/extras/adminConsole/passiveAnalytics.png
Normal file
BIN
www/extras/adminConsole/passiveAnalytics.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
BIN
www/extras/adminConsole/small/assetHistory.gif
Normal file
BIN
www/extras/adminConsole/small/assetHistory.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1 KiB |
BIN
www/extras/adminConsole/small/passiveAnalytics.png
Normal file
BIN
www/extras/adminConsole/small/passiveAnalytics.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 966 B |
|
|
@ -1,4 +1,4 @@
|
|||
function EAL(){this.version="0.7.2.2";date=new Date();this.start_time=date.getTime();this.win="loading";this.error=false;this.baseURL="";this.template="";this.lang=new Object();this.load_syntax=new Object();this.syntax=new Object();this.loadedFiles=new Array();this.waiting_loading=new Object();this.scripts_to_load=new Array();this.sub_scripts_to_load=new Array();this.resize=new Array();this.hidden=new Object();this.default_settings={debug:false ,smooth_selection:true ,font_size:"10" ,font_family:"monospace" ,start_highlight:false ,autocompletion:false ,toolbar:"search,go_to_line,fullscreen,|,undo,redo,|,select_font,|,change_smooth_selection,highlight,reset_highlight,|,help" ,begin_toolbar:"" ,end_toolbar:"" ,is_multi_files:false ,allow_resize:"both" ,show_line_colors:false ,min_width:400 ,min_height:125 ,replace_tab_by_spaces:false ,allow_toggle:true ,language:"en" ,syntax:"" ,syntax_selection_allow:"basic,brainfuck,c,coldfusion,cpp,css,html,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml" ,display:"onload" ,max_undo:30 ,browsers:"known" ,plugins:"" ,gecko_spellcheck:false ,fullscreen:false ,is_editable:true ,wrap_text:false ,load_callback:"" ,save_callback:"" ,change_callback:"" ,submit_callback:"" ,EA_init_callback:"" ,EA_delete_callback:"" ,EA_load_callback:"" ,EA_unload_callback:"" ,EA_toggle_on_callback:"" ,EA_toggle_off_callback:"" ,EA_file_switch_on_callback:"" ,EA_file_switch_off_callback:"" ,EA_file_close_callback:"" };this.advanced_buttons=[ ['new_document','newdocument.gif','new_document',false],['search','search.gif','show_search',false],['go_to_line','go_to_line.gif','go_to_line',false],['undo','undo.gif','undo',true],['redo','redo.gif','redo',true],['change_smooth_selection','smooth_selection.gif','change_smooth_selection_mode',true],['reset_highlight','reset_highlight.gif','resync_highlight',true],['highlight','highlight.gif','change_highlight',true],['help','help.gif','show_help',false],['save','save.gif','save',false],['load','load.gif','load',false],['fullscreen','fullscreen.gif','toggle_full_screen',false],['autocompletion','autocompletion.gif','toggle_autocompletion',true] ];ua=navigator.userAgent;this.nav=new Object();this.nav['isMacOS']=(ua.indexOf('Mac OS')!=-1);this.nav['isIE']=(navigator.appName=="Microsoft Internet Explorer");if(this.nav['isIE']){this.nav['isIE']=ua.replace(/^.*?MSIE ([0-9\.]*).*$/,"$1");if(this.nav['isIE']<6)this.has_error();}if(this.nav['isNS']=ua.indexOf('Netscape/')!=-1){this.nav['isNS']=ua.substr(ua.indexOf('Netscape/')+9);if(this.nav['isNS']<8||!this.nav['isIE'])this.has_error();}if(this.nav['isOpera']=(ua.indexOf('Opera')!=-1)){this.nav['isOpera']=ua.replace(/^.*?Opera.*?([0-9\.]+).*$/i,"$1");if(this.nav['isOpera']<9)this.has_error();this.nav['isIE']=false;}this.nav['isGecko']=(ua.indexOf('Gecko')!=-1);if(this.nav['isFirefox'] =(ua.indexOf('Firefox')!=-1))this.nav['isFirefox']=ua.replace(/^.*?Firefox.*?([0-9\.]+).*$/i,"$1");if(this.nav['isIceweasel'] =(ua.indexOf('Iceweasel')!=-1))this.nav['isFirefox']=this.nav['isIceweasel']=ua.replace(/^.*?Iceweasel.*?([0-9\.]+).*$/i,"$1");if(this.nav['GranParadiso'] =(ua.indexOf('GranParadiso')!=-1))this.nav['isFirefox']=this.nav['isGranParadiso']=ua.replace(/^.*?GranParadiso.*?([0-9\.]+).*$/i,"$1");if(this.nav['isCamino'] =(ua.indexOf('Camino')!=-1))this.nav['isCamino']=ua.replace(/^.*?Camino.*?([0-9\.]+).*$/i,"$1");if(this.nav['isChrome'] =(ua.indexOf('Chrome')!=-1))this.nav['isChrome']=ua.replace(/^.*?Chrome.*?([0-9\.]+).*$/i,"$1");if(this.nav['isSafari'] =(ua.indexOf('Safari')!=-1))this.nav['isSafari']=ua.replace(/^.*?Version\/([0-9]+\.[0-9]+).*$/i,"$1");if(this.nav['isIE']>=6||this.nav['isOpera']>=9||this.nav['isFirefox']||this.nav['isChrome']||this.nav['isCamino']||this.nav['isSafari']>=3)this.nav['isValidBrowser']=true;
|
||||
function EAL(){this.version="0.7.2.2";date=new Date();this.start_time=date.getTime();this.win="loading";this.error=false;this.baseURL="";this.template="";this.lang=new Object();this.load_syntax=new Object();this.syntax=new Object();this.loadedFiles=new Array();this.waiting_loading=new Object();this.scripts_to_load=new Array();this.sub_scripts_to_load=new Array();this.resize=new Array();this.hidden=new Object();this.default_settings={debug:false ,smooth_selection:true ,font_size:"10" ,font_family:"monospace" ,start_highlight:false ,autocompletion:false ,toolbar:"search,go_to_line,fullscreen,|,undo,redo,|,select_font,|,change_smooth_selection,highlight,reset_highlight,|,help" ,begin_toolbar:"" ,end_toolbar:"" ,is_multi_files:false ,allow_resize:"both" ,show_line_colors:false ,min_width:400 ,min_height:125 ,replace_tab_by_spaces:false ,allow_toggle:true ,language:"en" ,syntax:"" ,syntax_selection_allow:"basic,c,coldfusion,cpp,css,html,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml" ,display:"onload" ,max_undo:30 ,browsers:"known" ,plugins:"" ,gecko_spellcheck:false ,fullscreen:false ,is_editable:true ,wrap_text:false ,load_callback:"" ,save_callback:"" ,change_callback:"" ,submit_callback:"" ,EA_init_callback:"" ,EA_delete_callback:"" ,EA_load_callback:"" ,EA_unload_callback:"" ,EA_toggle_on_callback:"" ,EA_toggle_off_callback:"" ,EA_file_switch_on_callback:"" ,EA_file_switch_off_callback:"" ,EA_file_close_callback:"" };this.advanced_buttons=[ ['new_document','newdocument.gif','new_document',false],['search','search.gif','show_search',false],['go_to_line','go_to_line.gif','go_to_line',false],['undo','undo.gif','undo',true],['redo','redo.gif','redo',true],['change_smooth_selection','smooth_selection.gif','change_smooth_selection_mode',true],['reset_highlight','reset_highlight.gif','resync_highlight',true],['highlight','highlight.gif','change_highlight',true],['help','help.gif','show_help',false],['save','save.gif','save',false],['load','load.gif','load',false],['fullscreen','fullscreen.gif','toggle_full_screen',false],['autocompletion','autocompletion.gif','toggle_autocompletion',true] ];ua=navigator.userAgent;this.nav=new Object();this.nav['isMacOS']=(ua.indexOf('Mac OS')!=-1);this.nav['isIE']=(navigator.appName=="Microsoft Internet Explorer");if(this.nav['isIE']){this.nav['isIE']=ua.replace(/^.*?MSIE ([0-9\.]*).*$/,"$1");if(this.nav['isIE']<6)this.has_error();}if(this.nav['isNS']=ua.indexOf('Netscape/')!=-1){this.nav['isNS']=ua.substr(ua.indexOf('Netscape/')+9);if(this.nav['isNS']<8||!this.nav['isIE'])this.has_error();}if(this.nav['isOpera']=(ua.indexOf('Opera')!=-1)){this.nav['isOpera']=ua.replace(/^.*?Opera.*?([0-9\.]+).*$/i,"$1");if(this.nav['isOpera']<9)this.has_error();this.nav['isIE']=false;}this.nav['isGecko']=(ua.indexOf('Gecko')!=-1);if(this.nav['isFirefox'] =(ua.indexOf('Firefox')!=-1))this.nav['isFirefox']=ua.replace(/^.*?Firefox.*?([0-9\.]+).*$/i,"$1");if(this.nav['isIceweasel'] =(ua.indexOf('Iceweasel')!=-1))this.nav['isFirefox']=this.nav['isIceweasel']=ua.replace(/^.*?Iceweasel.*?([0-9\.]+).*$/i,"$1");if(this.nav['GranParadiso'] =(ua.indexOf('GranParadiso')!=-1))this.nav['isFirefox']=this.nav['isGranParadiso']=ua.replace(/^.*?GranParadiso.*?([0-9\.]+).*$/i,"$1");if(this.nav['isCamino'] =(ua.indexOf('Camino')!=-1))this.nav['isCamino']=ua.replace(/^.*?Camino.*?([0-9\.]+).*$/i,"$1");if(this.nav['isChrome'] =(ua.indexOf('Chrome')!=-1))this.nav['isChrome']=ua.replace(/^.*?Chrome.*?([0-9\.]+).*$/i,"$1");if(this.nav['isSafari'] =(ua.indexOf('Safari')!=-1))this.nav['isSafari']=ua.replace(/^.*?Version\/([0-9]+\.[0-9]+).*$/i,"$1");if(this.nav['isIE']>=6||this.nav['isOpera']>=9||this.nav['isFirefox']||this.nav['isChrome']||this.nav['isCamino']||this.nav['isSafari']>=3)this.nav['isValidBrowser']=true;
|
||||
else this.nav['isValidBrowser']=false;this.set_base_url();for(var i=0;i<this.scripts_to_load.length;i++){setTimeout("eAL.load_script('"+this.baseURL+this.scripts_to_load[i]+".js');",1);this.waiting_loading[this.scripts_to_load[i]+".js"]=false;}this.add_event(window,"load",EAL.prototype.window_loaded);};EAL.prototype ={has_error:function(){this.error=true;for(var i in EAL.prototype){EAL.prototype[i]=function(){};}},window_loaded:function(){eAL.win="loaded";if (document.forms){for (var i=0;i<document.forms.length;i++){var form=document.forms[i];form.edit_area_replaced_submit=null;try{form.edit_area_replaced_submit=form.onsubmit;form.onsubmit="";}catch (e){}eAL.add_event(form,"submit",EAL.prototype.submit);eAL.add_event(form,"reset",EAL.prototype.reset);}}eAL.add_event(window,"unload",function(){for(var i in eAs){eAL.delete_instance(i);}});},init_ie_textarea:function(id){var t=document.getElementById(id);try{if(t&&typeof(t.focused)=="undefined"){t.focus();t.focused=true;t.selectionStart=t.selectionEnd=0;get_IE_selection(t);eAL.add_event(t,"focus",IE_textarea_focus);eAL.add_event(t,"blur",IE_textarea_blur);}}catch(ex){}},init:function(settings){if(!settings["id"])this.has_error();if(this.error)return;if(eAs[settings["id"]])eAL.delete_instance(settings["id"]);for(var i in this.default_settings){if(typeof(settings[i])=="undefined")settings[i]=this.default_settings[i];}if(settings["browsers"]=="known"&&this.nav['isValidBrowser']==false){return;}if(settings["begin_toolbar"].length>0)settings["toolbar"]=settings["begin_toolbar"] +","+settings["toolbar"];if(settings["end_toolbar"].length>0)settings["toolbar"]=settings["toolbar"] +","+settings["end_toolbar"];settings["tab_toolbar"]=settings["toolbar"].replace(/ /g,"").split(",");settings["plugins"]=settings["plugins"].replace(/ /g,"").split(",");for(var i=0;i<settings["plugins"].length;i++){if(settings["plugins"][i].length==0)settings["plugins"].splice(i,1);}this.get_template();this.load_script(this.baseURL+"langs/"+settings["language"]+".js");if(settings["syntax"].length>0){settings["syntax"]=settings["syntax"].toLowerCase();this.load_script(this.baseURL+"reg_syntax/"+settings["syntax"]+".js");}eAs[settings["id"]]={"settings":settings};eAs[settings["id"]]["displayed"]=false;eAs[settings["id"]]["hidden"]=false;eAL.start(settings["id"]);},delete_instance:function(id){eAL.execCommand(id,"EA_delete");if(window.frames["frame_"+id]&&window.frames["frame_"+id].editArea){if(eAs[id]["displayed"])eAL.toggle(id,"off");window.frames["frame_"+id].editArea.execCommand("EA_unload");}var span=document.getElementById("EditAreaArroundInfos_"+id);if(span)span.parentNode.removeChild(span);var iframe=document.getElementById("frame_"+id);if(iframe){iframe.parentNode.removeChild(iframe);try{delete window.frames["frame_"+id];}catch (e){}}delete eAs[id];},start:function(id){if(this.win!="loaded"){setTimeout("eAL.start('"+id+"');",50);return;}for(var i in eAL.waiting_loading){if(eAL.waiting_loading[i]!="loaded"&&typeof(eAL.waiting_loading[i])!="function"){setTimeout("eAL.start('"+id+"');",50);return;}}if(!eAL.lang[eAs[id]["settings"]["language"]]||(eAs[id]["settings"]["syntax"].length>0&&!eAL.load_syntax[eAs[id]["settings"]["syntax"]])){setTimeout("eAL.start('"+id+"');",50);return;}if(eAs[id]["settings"]["syntax"].length>0)eAL.init_syntax_regexp();if(!document.getElementById("EditAreaArroundInfos_"+id)&&(eAs[id]["settings"]["debug"]||eAs[id]["settings"]["allow_toggle"])){var span=document.createElement("span");span.id="EditAreaArroundInfos_"+id;var html="";if(eAs[id]["settings"]["allow_toggle"]){checked=(eAs[id]["settings"]["display"]=="onload")?"checked":"";html+="<div id='edit_area_toggle_"+i+"'>";html+="<input id='edit_area_toggle_checkbox_"+id +"' class='toggle_"+id +"' type='checkbox' onclick='eAL.toggle(\""+id +"\");' accesskey='e' "+checked+" />";html+="<label for='edit_area_toggle_checkbox_"+id +"'>{$toggle}</label></div>";}if(eAs[id]["settings"]["debug"])html+="<textarea id='edit_area_debug_"+id +"' style='z-index:20;width:100%;height:120px;overflow:auto;border:solid black 1px;'></textarea><br />";html=eAL.translate(html,eAs[id]["settings"]["language"]);span.innerHTML=html;var father=document.getElementById(id).parentNode;var next=document.getElementById(id).nextSibling;if(next==null)father.appendChild(span);
|
||||
else father.insertBefore(span,next);}if(!eAs[id]["initialized"]){this.execCommand(id,"EA_init");if(eAs[id]["settings"]["display"]=="later"){eAs[id]["initialized"]=true;return;}}if(this.nav['isIE']){eAL.init_ie_textarea(id);}var html_toolbar_content="";area=eAs[id];for(var i=0;i<area["settings"]["tab_toolbar"].length;i++){html_toolbar_content+=this.get_control_html(area["settings"]["tab_toolbar"][i],area["settings"]["language"]);}if(!this.iframe_script){this.iframe_script="";for(var i=0;i<this.sub_scripts_to_load.length;i++)this.iframe_script+='<script language="javascript" type="text/javascript" src="'+this.baseURL+this.sub_scripts_to_load[i] +'.js"></script>';}for(var i=0;i<area["settings"]["plugins"].length;i++){if(!eAL.all_plugins_loaded)this.iframe_script+='<script language="javascript" type="text/javascript" src="'+this.baseURL+'plugins/'+area["settings"]["plugins"][i]+'/'+area["settings"]["plugins"][i] +'.js"></script>';this.iframe_script+='<script language="javascript" type="text/javascript" src="'+this.baseURL+'plugins/'+area["settings"]["plugins"][i]+'/langs/'+area["settings"]["language"] +'.js"></script>';}if(!this.iframe_css){this.iframe_css="<link href='"+this.baseURL +"edit_area.css' rel='stylesheet' type='text/css' />";}var template=this.template.replace(/\[__BASEURL__\]/g,this.baseURL);template=template.replace("[__TOOLBAR__]",html_toolbar_content);template=this.translate(template,area["settings"]["language"],"template");template=template.replace("[__CSSRULES__]",this.iframe_css);template=template.replace("[__JSCODE__]",this.iframe_script);template=template.replace("[__EA_VERSION__]",this.version);area.textarea=document.getElementById(area["settings"]["id"]);eAs[area["settings"]["id"]]["textarea"]=area.textarea;if(typeof(window.frames["frame_"+area["settings"]["id"]])!='undefined')delete window.frames["frame_"+area["settings"]["id"]];var father=area.textarea.parentNode;var content=document.createElement("iframe");content.name="frame_"+area["settings"]["id"];content.id="frame_"+area["settings"]["id"];content.style.borderWidth="0px";setAttribute(content,"frameBorder","0");content.style.overflow="hidden";content.style.display="none";var next=area.textarea.nextSibling;if(next==null)father.appendChild(content);
|
||||
else father.insertBefore(content,next);var frame=window.frames["frame_"+area["settings"]["id"]];frame.document.open();frame.eAs=eAs;frame.area_id=area["settings"]["id"];frame.document.area_id=area["settings"]["id"];frame.document.write(template);frame.document.close();},toggle:function(id,toggle_to){if(!toggle_to)toggle_to=(eAs[id]["displayed"]==true)?"off":"on";if(eAs[id]["displayed"]==true &&toggle_to=="off"){this.toggle_off(id);}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
function EAL(){this.version="0.7.2.2";date=new Date();this.start_time=date.getTime();this.win="loading";this.error=false;this.baseURL="";this.template="";this.lang=new Object();this.load_syntax=new Object();this.syntax=new Object();this.loadedFiles=new Array();this.waiting_loading=new Object();this.scripts_to_load=new Array();this.sub_scripts_to_load=new Array();this.resize=new Array();this.hidden=new Object();this.default_settings={debug:false ,smooth_selection:true ,font_size:"10" ,font_family:"monospace" ,start_highlight:false ,autocompletion:false ,toolbar:"search,go_to_line,fullscreen,|,undo,redo,|,select_font,|,change_smooth_selection,highlight,reset_highlight,|,help" ,begin_toolbar:"" ,end_toolbar:"" ,is_multi_files:false ,allow_resize:"both" ,show_line_colors:false ,min_width:400 ,min_height:125 ,replace_tab_by_spaces:false ,allow_toggle:true ,language:"en" ,syntax:"" ,syntax_selection_allow:"basic,brainfuck,c,coldfusion,cpp,css,html,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml" ,display:"onload" ,max_undo:30 ,browsers:"known" ,plugins:"" ,gecko_spellcheck:false ,fullscreen:false ,is_editable:true ,wrap_text:false ,load_callback:"" ,save_callback:"" ,change_callback:"" ,submit_callback:"" ,EA_init_callback:"" ,EA_delete_callback:"" ,EA_load_callback:"" ,EA_unload_callback:"" ,EA_toggle_on_callback:"" ,EA_toggle_off_callback:"" ,EA_file_switch_on_callback:"" ,EA_file_switch_off_callback:"" ,EA_file_close_callback:"" };this.advanced_buttons=[ ['new_document','newdocument.gif','new_document',false],['search','search.gif','show_search',false],['go_to_line','go_to_line.gif','go_to_line',false],['undo','undo.gif','undo',true],['redo','redo.gif','redo',true],['change_smooth_selection','smooth_selection.gif','change_smooth_selection_mode',true],['reset_highlight','reset_highlight.gif','resync_highlight',true],['highlight','highlight.gif','change_highlight',true],['help','help.gif','show_help',false],['save','save.gif','save',false],['load','load.gif','load',false],['fullscreen','fullscreen.gif','toggle_full_screen',false],['autocompletion','autocompletion.gif','toggle_autocompletion',true] ];ua=navigator.userAgent;this.nav=new Object();this.nav['isMacOS']=(ua.indexOf('Mac OS')!=-1);this.nav['isIE']=(navigator.appName=="Microsoft Internet Explorer");if(this.nav['isIE']){this.nav['isIE']=ua.replace(/^.*?MSIE ([0-9\.]*).*$/,"$1");if(this.nav['isIE']<6)this.has_error();}if(this.nav['isNS']=ua.indexOf('Netscape/')!=-1){this.nav['isNS']=ua.substr(ua.indexOf('Netscape/')+9);if(this.nav['isNS']<8||!this.nav['isIE'])this.has_error();}if(this.nav['isOpera']=(ua.indexOf('Opera')!=-1)){this.nav['isOpera']=ua.replace(/^.*?Opera.*?([0-9\.]+).*$/i,"$1");if(this.nav['isOpera']<9)this.has_error();this.nav['isIE']=false;}this.nav['isGecko']=(ua.indexOf('Gecko')!=-1);if(this.nav['isFirefox'] =(ua.indexOf('Firefox')!=-1))this.nav['isFirefox']=ua.replace(/^.*?Firefox.*?([0-9\.]+).*$/i,"$1");if(this.nav['isIceweasel'] =(ua.indexOf('Iceweasel')!=-1))this.nav['isFirefox']=this.nav['isIceweasel']=ua.replace(/^.*?Iceweasel.*?([0-9\.]+).*$/i,"$1");if(this.nav['GranParadiso'] =(ua.indexOf('GranParadiso')!=-1))this.nav['isFirefox']=this.nav['isGranParadiso']=ua.replace(/^.*?GranParadiso.*?([0-9\.]+).*$/i,"$1");if(this.nav['isCamino'] =(ua.indexOf('Camino')!=-1))this.nav['isCamino']=ua.replace(/^.*?Camino.*?([0-9\.]+).*$/i,"$1");if(this.nav['isChrome'] =(ua.indexOf('Chrome')!=-1))this.nav['isChrome']=ua.replace(/^.*?Chrome.*?([0-9\.]+).*$/i,"$1");if(this.nav['isSafari'] =(ua.indexOf('Safari')!=-1))this.nav['isSafari']=ua.replace(/^.*?Version\/([0-9]+\.[0-9]+).*$/i,"$1");if(this.nav['isIE']>=6||this.nav['isOpera']>=9||this.nav['isFirefox']||this.nav['isChrome']||this.nav['isCamino']||this.nav['isSafari']>=3)this.nav['isValidBrowser']=true;
|
||||
function EAL(){this.version="0.7.2.2";date=new Date();this.start_time=date.getTime();this.win="loading";this.error=false;this.baseURL="";this.template="";this.lang=new Object();this.load_syntax=new Object();this.syntax=new Object();this.loadedFiles=new Array();this.waiting_loading=new Object();this.scripts_to_load=new Array();this.sub_scripts_to_load=new Array();this.resize=new Array();this.hidden=new Object();this.default_settings={debug:false ,smooth_selection:true ,font_size:"10" ,font_family:"monospace" ,start_highlight:false ,autocompletion:false ,toolbar:"search,go_to_line,fullscreen,|,undo,redo,|,select_font,|,change_smooth_selection,highlight,reset_highlight,|,help" ,begin_toolbar:"" ,end_toolbar:"" ,is_multi_files:false ,allow_resize:"both" ,show_line_colors:false ,min_width:400 ,min_height:125 ,replace_tab_by_spaces:false ,allow_toggle:true ,language:"en" ,syntax:"" ,syntax_selection_allow:"basic,c,coldfusion,cpp,css,html,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml" ,display:"onload" ,max_undo:30 ,browsers:"known" ,plugins:"" ,gecko_spellcheck:false ,fullscreen:false ,is_editable:true ,wrap_text:false ,load_callback:"" ,save_callback:"" ,change_callback:"" ,submit_callback:"" ,EA_init_callback:"" ,EA_delete_callback:"" ,EA_load_callback:"" ,EA_unload_callback:"" ,EA_toggle_on_callback:"" ,EA_toggle_off_callback:"" ,EA_file_switch_on_callback:"" ,EA_file_switch_off_callback:"" ,EA_file_close_callback:"" };this.advanced_buttons=[ ['new_document','newdocument.gif','new_document',false],['search','search.gif','show_search',false],['go_to_line','go_to_line.gif','go_to_line',false],['undo','undo.gif','undo',true],['redo','redo.gif','redo',true],['change_smooth_selection','smooth_selection.gif','change_smooth_selection_mode',true],['reset_highlight','reset_highlight.gif','resync_highlight',true],['highlight','highlight.gif','change_highlight',true],['help','help.gif','show_help',false],['save','save.gif','save',false],['load','load.gif','load',false],['fullscreen','fullscreen.gif','toggle_full_screen',false],['autocompletion','autocompletion.gif','toggle_autocompletion',true] ];ua=navigator.userAgent;this.nav=new Object();this.nav['isMacOS']=(ua.indexOf('Mac OS')!=-1);this.nav['isIE']=(navigator.appName=="Microsoft Internet Explorer");if(this.nav['isIE']){this.nav['isIE']=ua.replace(/^.*?MSIE ([0-9\.]*).*$/,"$1");if(this.nav['isIE']<6)this.has_error();}if(this.nav['isNS']=ua.indexOf('Netscape/')!=-1){this.nav['isNS']=ua.substr(ua.indexOf('Netscape/')+9);if(this.nav['isNS']<8||!this.nav['isIE'])this.has_error();}if(this.nav['isOpera']=(ua.indexOf('Opera')!=-1)){this.nav['isOpera']=ua.replace(/^.*?Opera.*?([0-9\.]+).*$/i,"$1");if(this.nav['isOpera']<9)this.has_error();this.nav['isIE']=false;}this.nav['isGecko']=(ua.indexOf('Gecko')!=-1);if(this.nav['isFirefox'] =(ua.indexOf('Firefox')!=-1))this.nav['isFirefox']=ua.replace(/^.*?Firefox.*?([0-9\.]+).*$/i,"$1");if(this.nav['isIceweasel'] =(ua.indexOf('Iceweasel')!=-1))this.nav['isFirefox']=this.nav['isIceweasel']=ua.replace(/^.*?Iceweasel.*?([0-9\.]+).*$/i,"$1");if(this.nav['GranParadiso'] =(ua.indexOf('GranParadiso')!=-1))this.nav['isFirefox']=this.nav['isGranParadiso']=ua.replace(/^.*?GranParadiso.*?([0-9\.]+).*$/i,"$1");if(this.nav['isCamino'] =(ua.indexOf('Camino')!=-1))this.nav['isCamino']=ua.replace(/^.*?Camino.*?([0-9\.]+).*$/i,"$1");if(this.nav['isChrome'] =(ua.indexOf('Chrome')!=-1))this.nav['isChrome']=ua.replace(/^.*?Chrome.*?([0-9\.]+).*$/i,"$1");if(this.nav['isSafari'] =(ua.indexOf('Safari')!=-1))this.nav['isSafari']=ua.replace(/^.*?Version\/([0-9]+\.[0-9]+).*$/i,"$1");if(this.nav['isIE']>=6||this.nav['isOpera']>=9||this.nav['isFirefox']||this.nav['isChrome']||this.nav['isCamino']||this.nav['isSafari']>=3)this.nav['isValidBrowser']=true;
|
||||
else this.nav['isValidBrowser']=false;this.set_base_url();for(var i=0;i<this.scripts_to_load.length;i++){setTimeout("eAL.load_script('"+this.baseURL+this.scripts_to_load[i]+".js');",1);this.waiting_loading[this.scripts_to_load[i]+".js"]=false;}this.add_event(window,"load",EAL.prototype.window_loaded);};EAL.prototype ={has_error:function(){this.error=true;for(var i in EAL.prototype){EAL.prototype[i]=function(){};}},window_loaded:function(){eAL.win="loaded";if (document.forms){for (var i=0;i<document.forms.length;i++){var form=document.forms[i];form.edit_area_replaced_submit=null;try{form.edit_area_replaced_submit=form.onsubmit;form.onsubmit="";}catch (e){}eAL.add_event(form,"submit",EAL.prototype.submit);eAL.add_event(form,"reset",EAL.prototype.reset);}}eAL.add_event(window,"unload",function(){for(var i in eAs){eAL.delete_instance(i);}});},init_ie_textarea:function(id){var t=document.getElementById(id);try{if(t&&typeof(t.focused)=="undefined"){t.focus();t.focused=true;t.selectionStart=t.selectionEnd=0;get_IE_selection(t);eAL.add_event(t,"focus",IE_textarea_focus);eAL.add_event(t,"blur",IE_textarea_blur);}}catch(ex){}},init:function(settings){if(!settings["id"])this.has_error();if(this.error)return;if(eAs[settings["id"]])eAL.delete_instance(settings["id"]);for(var i in this.default_settings){if(typeof(settings[i])=="undefined")settings[i]=this.default_settings[i];}if(settings["browsers"]=="known"&&this.nav['isValidBrowser']==false){return;}if(settings["begin_toolbar"].length>0)settings["toolbar"]=settings["begin_toolbar"] +","+settings["toolbar"];if(settings["end_toolbar"].length>0)settings["toolbar"]=settings["toolbar"] +","+settings["end_toolbar"];settings["tab_toolbar"]=settings["toolbar"].replace(/ /g,"").split(",");settings["plugins"]=settings["plugins"].replace(/ /g,"").split(",");for(var i=0;i<settings["plugins"].length;i++){if(settings["plugins"][i].length==0)settings["plugins"].splice(i,1);}this.get_template();this.load_script(this.baseURL+"langs/"+settings["language"]+".js");if(settings["syntax"].length>0){settings["syntax"]=settings["syntax"].toLowerCase();this.load_script(this.baseURL+"reg_syntax/"+settings["syntax"]+".js");}eAs[settings["id"]]={"settings":settings};eAs[settings["id"]]["displayed"]=false;eAs[settings["id"]]["hidden"]=false;eAL.start(settings["id"]);},delete_instance:function(id){eAL.execCommand(id,"EA_delete");if(window.frames["frame_"+id]&&window.frames["frame_"+id].editArea){if(eAs[id]["displayed"])eAL.toggle(id,"off");window.frames["frame_"+id].editArea.execCommand("EA_unload");}var span=document.getElementById("EditAreaArroundInfos_"+id);if(span)span.parentNode.removeChild(span);var iframe=document.getElementById("frame_"+id);if(iframe){iframe.parentNode.removeChild(iframe);try{delete window.frames["frame_"+id];}catch (e){}}delete eAs[id];},start:function(id){if(this.win!="loaded"){setTimeout("eAL.start('"+id+"');",50);return;}for(var i in eAL.waiting_loading){if(eAL.waiting_loading[i]!="loaded"&&typeof(eAL.waiting_loading[i])!="function"){setTimeout("eAL.start('"+id+"');",50);return;}}if(!eAL.lang[eAs[id]["settings"]["language"]]||(eAs[id]["settings"]["syntax"].length>0&&!eAL.load_syntax[eAs[id]["settings"]["syntax"]])){setTimeout("eAL.start('"+id+"');",50);return;}if(eAs[id]["settings"]["syntax"].length>0)eAL.init_syntax_regexp();if(!document.getElementById("EditAreaArroundInfos_"+id)&&(eAs[id]["settings"]["debug"]||eAs[id]["settings"]["allow_toggle"])){var span=document.createElement("span");span.id="EditAreaArroundInfos_"+id;var html="";if(eAs[id]["settings"]["allow_toggle"]){checked=(eAs[id]["settings"]["display"]=="onload")?"checked":"";html+="<div id='edit_area_toggle_"+i+"'>";html+="<input id='edit_area_toggle_checkbox_"+id +"' class='toggle_"+id +"' type='checkbox' onclick='eAL.toggle(\""+id +"\");' accesskey='e' "+checked+" />";html+="<label for='edit_area_toggle_checkbox_"+id +"'>{$toggle}</label></div>";}if(eAs[id]["settings"]["debug"])html+="<textarea id='edit_area_debug_"+id +"' style='z-index:20;width:100%;height:120px;overflow:auto;border:solid black 1px;'></textarea><br />";html=eAL.translate(html,eAs[id]["settings"]["language"]);span.innerHTML=html;var father=document.getElementById(id).parentNode;var next=document.getElementById(id).nextSibling;if(next==null)father.appendChild(span);
|
||||
else father.insertBefore(span,next);}if(!eAs[id]["initialized"]){this.execCommand(id,"EA_init");if(eAs[id]["settings"]["display"]=="later"){eAs[id]["initialized"]=true;return;}}if(this.nav['isIE']){eAL.init_ie_textarea(id);}var html_toolbar_content="";area=eAs[id];for(var i=0;i<area["settings"]["tab_toolbar"].length;i++){html_toolbar_content+=this.get_control_html(area["settings"]["tab_toolbar"][i],area["settings"]["language"]);}if(!this.iframe_script){this.iframe_script="";for(var i=0;i<this.sub_scripts_to_load.length;i++)this.iframe_script+='<script language="javascript" type="text/javascript" src="'+this.baseURL+this.sub_scripts_to_load[i] +'.js"></script>';}for(var i=0;i<area["settings"]["plugins"].length;i++){if(!eAL.all_plugins_loaded)this.iframe_script+='<script language="javascript" type="text/javascript" src="'+this.baseURL+'plugins/'+area["settings"]["plugins"][i]+'/'+area["settings"]["plugins"][i] +'.js"></script>';this.iframe_script+='<script language="javascript" type="text/javascript" src="'+this.baseURL+'plugins/'+area["settings"]["plugins"][i]+'/langs/'+area["settings"]["language"] +'.js"></script>';}if(!this.iframe_css){this.iframe_css="<link href='"+this.baseURL +"edit_area.css' rel='stylesheet' type='text/css' />";}var template=this.template.replace(/\[__BASEURL__\]/g,this.baseURL);template=template.replace("[__TOOLBAR__]",html_toolbar_content);template=this.translate(template,area["settings"]["language"],"template");template=template.replace("[__CSSRULES__]",this.iframe_css);template=template.replace("[__JSCODE__]",this.iframe_script);template=template.replace("[__EA_VERSION__]",this.version);area.textarea=document.getElementById(area["settings"]["id"]);eAs[area["settings"]["id"]]["textarea"]=area.textarea;if(typeof(window.frames["frame_"+area["settings"]["id"]])!='undefined')delete window.frames["frame_"+area["settings"]["id"]];var father=area.textarea.parentNode;var content=document.createElement("iframe");content.name="frame_"+area["settings"]["id"];content.id="frame_"+area["settings"]["id"];content.style.borderWidth="0px";setAttribute(content,"frameBorder","0");content.style.overflow="hidden";content.style.display="none";var next=area.textarea.nextSibling;if(next==null)father.appendChild(content);
|
||||
else father.insertBefore(content,next);var frame=window.frames["frame_"+area["settings"]["id"]];frame.document.open();frame.eAs=eAs;frame.area_id=area["settings"]["id"];frame.document.area_id=area["settings"]["id"];frame.document.write(template);frame.document.close();},toggle:function(id,toggle_to){if(!toggle_to)toggle_to=(eAs[id]["displayed"]==true)?"off":"on";if(eAs[id]["displayed"]==true &&toggle_to=="off"){this.toggle_off(id);}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ function EditAreaLoader(){
|
|||
,allow_toggle: true // true or false
|
||||
,language: "en"
|
||||
,syntax: ""
|
||||
,syntax_selection_allow: "basic,brainfuck,c,coldfusion,cpp,css,html,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml"
|
||||
,syntax_selection_allow: "basic,c,coldfusion,cpp,css,html,js,pas,perl,php,python,ruby,robotstxt,sql,tsql,vb,xml"
|
||||
,display: "onload" // onload or later
|
||||
,max_undo: 30
|
||||
,browsers: "known" // all or known
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
,language: "en"
|
||||
,syntax: "html"
|
||||
,toolbar: "search, go_to_line, |, undo, redo, |, select_font, |, syntax_selection, |, change_smooth_selection, highlight, reset_highlight, |, help"
|
||||
,syntax_selection_allow: "css,html,js,php,python,vb,xml,c,cpp,sql,basic,pas,brainfuck"
|
||||
,syntax_selection_allow: "css,html,js,php,python,vb,xml,c,cpp,sql,basic,pas"
|
||||
,is_multi_files: true
|
||||
,EA_load_callback: "editAreaLoaded"
|
||||
,show_line_colors: true
|
||||
|
|
|
|||
|
|
@ -8,49 +8,29 @@ if (typeof Survey === "undefined") {
|
|||
var CLASS_INVALID = 'survey-invalid'; // For elements that fail input validation
|
||||
var CLASS_INVALID_MARKER = 'survey-invalid-marker'; // For default '*' invalid field marker
|
||||
|
||||
var multipleChoice = {
|
||||
'Multiple Choice': 1,
|
||||
'Gender': 1,
|
||||
'Yes/No': 1,
|
||||
'True/False': 1,
|
||||
'Ideology': 1,
|
||||
'Race': 1,
|
||||
'Party': 1,
|
||||
'Education': 1,
|
||||
'Scale': 1,
|
||||
'Agree/Disagree': 1,
|
||||
'Oppose/Support': 1,
|
||||
'Importance': 1,
|
||||
'Likelihood': 1,
|
||||
'Certainty': 1,
|
||||
'Satisfaction': 1,
|
||||
'Confidence': 1,
|
||||
'Effectiveness': 1,
|
||||
'Concern': 1,
|
||||
'Risk': 1,
|
||||
'Threat': 1,
|
||||
'Security': 1
|
||||
};
|
||||
var text = {
|
||||
// All specially-handled question types are listed here
|
||||
// (anything else is assumed to be a multi-choice bundle)
|
||||
var TEXT_TYPES = {
|
||||
'Text': 1,
|
||||
'Email': 1,
|
||||
'Phone Number': 1,
|
||||
'Text Date': 1,
|
||||
'Currency': 1
|
||||
'Currency': 1,
|
||||
'TextArea': 1
|
||||
};
|
||||
var slider = {
|
||||
var SLIDER_TYPES = {
|
||||
'Slider': 1,
|
||||
'Dual Slider - Range': 1,
|
||||
'Multi Slider - Allocate': 1
|
||||
};
|
||||
var dateType = {
|
||||
var DATE_TYPES = {
|
||||
'Date': 1,
|
||||
'Date Range': 1
|
||||
};
|
||||
var fileUpload = {
|
||||
var UPLOAD_TYPES = {
|
||||
'File Upload': 1
|
||||
};
|
||||
var hidden = {
|
||||
var HIDDEN_TYPES = {
|
||||
'Hidden': 1
|
||||
};
|
||||
|
||||
|
|
@ -65,8 +45,10 @@ if (typeof Survey === "undefined") {
|
|||
function formsubmit(event){
|
||||
var submit = 1;//boolean for if all was good or not
|
||||
for (var i in toValidate) {
|
||||
console.log(toValidate);
|
||||
if (YAHOO.lang.hasOwnProperty(toValidate, i)) {
|
||||
var answered = 0;
|
||||
console.log(toValidate[i].type);
|
||||
if (toValidate[i].type === 'Multi Slider - Allocate') {
|
||||
var total = 0;
|
||||
for (var z in toValidate[i].answers) {
|
||||
|
|
@ -94,6 +76,7 @@ if (typeof Survey === "undefined") {
|
|||
}
|
||||
}
|
||||
var node = document.getElementById(i + 'required');
|
||||
|
||||
var q_parent_node = YAHOO.util.Dom.getAncestorByClassName(node, 'question');
|
||||
if (!answered) {
|
||||
submit = 0;
|
||||
|
|
@ -229,7 +212,7 @@ if (typeof Survey === "undefined") {
|
|||
var step = Math.round(q.answers[i].step);
|
||||
var min = Math.round(parseFloat(q.answers[i].min));
|
||||
var distance = Math.round(parseFloat(q.answers[i].max) + (-1 * min));
|
||||
var scale = Math.round(sliderWidth / distance);
|
||||
var scale = Math.floor(sliderWidth / distance);
|
||||
var id = a.id;
|
||||
var s = YAHOO.widget.Slider.getHorizSlider(id + 'slider-bg', id + 'slider-thumb', 0, sliderWidth, (scale * step));
|
||||
s.scale = scale;
|
||||
|
|
@ -353,7 +336,6 @@ if (typeof Survey === "undefined") {
|
|||
if (lastSection !== s.id || s.everyPageText === '1') {
|
||||
document.getElementById('headertext').style.display = 'block';
|
||||
}
|
||||
|
||||
if (lastSection !== s.id && s.questionsOnSectionPage !== '1') {
|
||||
var span = document.createElement("div");
|
||||
span.innerHTML = "<input type=button id='showQuestionsButton' value='Continue'>";
|
||||
|
|
@ -385,11 +367,16 @@ if (typeof Survey === "undefined") {
|
|||
Survey.Form.addWidgets(qs);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
addWidgets: function(qs){
|
||||
hasFile = false;
|
||||
for (var i = 0; i < qs.length; i++) {
|
||||
var q = qs[i];
|
||||
if (!q || !q.answers) {
|
||||
// gracefully handle q with no answers
|
||||
continue;
|
||||
}
|
||||
|
||||
var verts = '';
|
||||
for (var x in q.answers) {
|
||||
if (YAHOO.lang.hasOwnProperty(q.answers, x)) {
|
||||
|
|
@ -403,106 +390,108 @@ if (typeof Survey === "undefined") {
|
|||
}
|
||||
}
|
||||
|
||||
//Check if this question should be validated
|
||||
if (q.required) {
|
||||
//Check if this question should be validated.
|
||||
//Sliders can't really be not answered, so requiring them makes little sense.
|
||||
if (q.required == true && q.questionType != 'Slider') {
|
||||
toValidate[q.id] = [];
|
||||
toValidate[q.id].type = q.questionType;
|
||||
toValidate[q.id].answers = [];
|
||||
}
|
||||
|
||||
|
||||
if (multipleChoice[q.questionType]) {
|
||||
var butts = [];
|
||||
verb = 0;
|
||||
for (var j = 0; j < q.answers.length; j++) {
|
||||
var a = q.answers[j];
|
||||
if (DATE_TYPES[q.questionType]) {
|
||||
for (var k = 0; k < q.answers.length; k++) {
|
||||
var ans = q.answers[k];
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].answers[a.id] = 1;
|
||||
toValidate[q.id].answers[ans.id] = 1;
|
||||
}
|
||||
var b = document.getElementById(a.id + 'button');
|
||||
/*
|
||||
b = new YAHOO.widget.Button({ type: "checkbox", label: a.answerText, id: a.id+'button', name: a.id+'button',
|
||||
value: a.id,
|
||||
container: a.id+"container", checked: false });
|
||||
*/
|
||||
// b.on("click", buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]);
|
||||
// YAHOO.util.Event.addListener(a.id+'button', "click", buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]);
|
||||
if (a.verbatim) {
|
||||
verb = 1;
|
||||
}
|
||||
YAHOO.util.Event.addListener(a.id + 'button', "click", buttonChanged, [b, a.id, q.maxAnswers, butts, qs.length, a.id]);
|
||||
b.hid = a.id;
|
||||
butts.push(b);
|
||||
var calid = ans.id + 'container';
|
||||
var c = new YAHOO.widget.Calendar(calid, {
|
||||
title: 'Choose a date:',
|
||||
close: true
|
||||
});
|
||||
c.selectEvent.subscribe(selectCalendar, [c, ans.id], true);
|
||||
c.render();
|
||||
c.hide();
|
||||
var btn = new YAHOO.widget.Button({
|
||||
label: "Select Date",
|
||||
id: "pushbutton" + ans.id,
|
||||
container: ans.id + 'button'
|
||||
});
|
||||
btn.on("click", showCalendar, [c]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (dateType[q.questionType]) {
|
||||
for (var k = 0; k < q.answers.length; k++) {
|
||||
var ans = q.answers[k];
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].answers[ans.id] = 1;
|
||||
|
||||
if (SLIDER_TYPES[q.questionType]) {
|
||||
//First run through and put up the span placeholders and find the max value for an answer, to know how big the allocation points will be.
|
||||
var max = 0;
|
||||
if (q.questionType === 'Dual Slider - Range') {
|
||||
handleDualSliders(q);
|
||||
}
|
||||
else {
|
||||
for (var s in q.answers) {
|
||||
if (YAHOO.lang.hasOwnProperty(q.answers, s)) {
|
||||
var a1 = q.answers[s];
|
||||
YAHOO.util.Event.addListener(a1.id, "blur", sliderTextSet);
|
||||
if (a1.max - a1.min > max) {
|
||||
max = a1.max - a1.min;
|
||||
}
|
||||
}
|
||||
var calid = ans.id + 'container';
|
||||
var c = new YAHOO.widget.Calendar(calid, {
|
||||
title: 'Choose a date:',
|
||||
close: true
|
||||
});
|
||||
c.selectEvent.subscribe(selectCalendar, [c, ans.id], true);
|
||||
c.render();
|
||||
c.hide();
|
||||
var btn = new YAHOO.widget.Button({
|
||||
label: "Select Date",
|
||||
id: "pushbutton" + ans.id,
|
||||
container: ans.id + 'button'
|
||||
});
|
||||
btn.on("click", showCalendar, [c]);
|
||||
}
|
||||
}
|
||||
if (q.questionType === 'Multi Slider - Allocate') {
|
||||
//sliderManagers[sliderManagers.length] = new this.sliderManager(q,max);
|
||||
for (var x1 = 0; x1 < q.answers.length; x1++) {
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].total = q.answers[x1].max;
|
||||
toValidate[q.id].answers[q.answers[x1].id] = 1;
|
||||
}
|
||||
}
|
||||
sliderManager(q, max);
|
||||
}
|
||||
else
|
||||
if (slider[q.questionType]) {
|
||||
//First run through and put up the span placeholders and find the max value for an answer, to know how big the allocation points will be.
|
||||
var max = 0;
|
||||
if (q.questionType === 'Dual Slider - Range') {
|
||||
handleDualSliders(q);
|
||||
}
|
||||
else {
|
||||
for (var s in q.answers) {
|
||||
if (YAHOO.lang.hasOwnProperty(q.answers, s)) {
|
||||
var a1 = q.answers[s];
|
||||
YAHOO.util.Event.addListener(a1.id, "blur", sliderTextSet);
|
||||
if (a1.max - a1.min > max) {
|
||||
max = a1.max - a1.min;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (q.questionType === 'Multi Slider - Allocate') {
|
||||
//sliderManagers[sliderManagers.length] = new this.sliderManager(q,max);
|
||||
for (var x1 = 0; x1 < q.answers.length; x1++) {
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].total = q.answers[x1].max;
|
||||
toValidate[q.id].answers[q.answers[x1].id] = 1;
|
||||
}
|
||||
}
|
||||
sliderManager(q, max);
|
||||
}
|
||||
else
|
||||
if (q.questionType === 'Slider') {
|
||||
handleSliders(q);
|
||||
}
|
||||
if (q.questionType === 'Slider') {
|
||||
handleSliders(q);
|
||||
}
|
||||
|
||||
else
|
||||
if (fileUpload[q.questionType]) {
|
||||
hasFile = true;
|
||||
}
|
||||
|
||||
else
|
||||
if (text[q.questionType]) {
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].answers[q.answers[x].id] = 1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (UPLOAD_TYPES[q.questionType]) {
|
||||
hasFile = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TEXT_TYPES[q.questionType]) {
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].answers[q.answers[x].id] = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Must be a multi-choice bundle
|
||||
var butts = [];
|
||||
verb = 0;
|
||||
for (var j = 0; j < q.answers.length; j++) {
|
||||
var a = q.answers[j];
|
||||
if (toValidate[q.id]) {
|
||||
toValidate[q.id].answers[a.id] = 1;
|
||||
}
|
||||
var b = document.getElementById(a.id + 'button');
|
||||
/*
|
||||
b = new YAHOO.widget.Button({ type: "checkbox", label: a.answerText, id: a.id+'button', name: a.id+'button',
|
||||
value: a.id,
|
||||
container: a.id+"container", checked: false });
|
||||
*/
|
||||
// b.on("click", buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]);
|
||||
// YAHOO.util.Event.addListener(a.id+'button', "click", buttonChanged,[b,a.id,q.maxAnswers,butts,qs.length,a.id]);
|
||||
if (a.verbatim) {
|
||||
verb = 1;
|
||||
}
|
||||
YAHOO.util.Event.addListener(a.id + 'button', "click", buttonChanged, [b, a.id, q.maxAnswers, butts, qs.length, a.id]);
|
||||
b.hid = a.id;
|
||||
butts.push(b);
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.addListener("submitbutton", "click", formsubmit);
|
||||
}
|
||||
|
|
@ -514,4 +503,4 @@ if (typeof Survey === "undefined") {
|
|||
YAHOO.util.Event.onDOMReady(function(){
|
||||
// Survey.Comm.setUrl('/' + document.getElementById('assetPath').value);
|
||||
Survey.Comm.callServer('', 'loadQuestions');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ var Dom = YAHOO.util.Dom;
|
|||
var Event = YAHOO.util.Event;
|
||||
var DDM = YAHOO.util.DragDropMgr;
|
||||
|
||||
var currentDest;
|
||||
|
||||
Survey.DDList = function(id, sGroup, config) {
|
||||
|
||||
Survey.DDList.superclass.constructor.call(this, id, sGroup, config);
|
||||
|
|
@ -61,30 +63,10 @@ YAHOO.extend(Survey.DDList, YAHOO.util.DDProxy, {
|
|||
a.animate();
|
||||
},
|
||||
|
||||
onInvalidDrop: function(e, id) {
|
||||
Survey.Data.dragDrop(this.getEl());
|
||||
},
|
||||
onDragDrop: function(e, id) {
|
||||
|
||||
// If there is one drop interaction, the li was dropped either on the list,
|
||||
// or it was dropped on the current location of the source element.
|
||||
if (DDM.interactionInfo.drop.length === 1) {
|
||||
|
||||
// The position of the cursor at the time of the drop (YAHOO.util.Point)
|
||||
var pt = DDM.interactionInfo.point;
|
||||
|
||||
// The region occupied by the source element at the time of the drop
|
||||
var region = DDM.interactionInfo.sourceRegion;
|
||||
|
||||
// Check to see if we are over the source element's location. We will
|
||||
// append to the bottom of the list once we are sure it was a drop in
|
||||
// the negative space (the area of the list without any list items)
|
||||
if (!region.intersect(pt)) {
|
||||
var destEl = Dom.get(id);
|
||||
var destDD = DDM.getDDById(id);
|
||||
destEl.appendChild(this.getEl());
|
||||
destDD.isEmpty = false;
|
||||
DDM.refreshCache();
|
||||
}
|
||||
|
||||
}
|
||||
Survey.Data.dragDrop(this.getEl());
|
||||
},
|
||||
|
||||
|
|
@ -110,6 +92,8 @@ YAHOO.extend(Survey.DDList, YAHOO.util.DDProxy, {
|
|||
// We are only concerned with list items, we ignore the dragover
|
||||
// notifications for the list.
|
||||
if (destEl.nodeName.toLowerCase() == "li") {
|
||||
currentDest = destEl;
|
||||
console.log(destEl);
|
||||
var orig_p = srcEl.parentNode;
|
||||
var p = destEl.parentNode;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,134 +1,154 @@
|
|||
if (typeof Survey == "undefined") {
|
||||
/*global Survey, YAHOO */
|
||||
if (typeof Survey === "undefined") {
|
||||
var Survey = {};
|
||||
}
|
||||
|
||||
Survey.Data = new function(){
|
||||
Survey.Data = (function(){
|
||||
|
||||
var lastDataSet = {};
|
||||
var focus;
|
||||
var lastId = -1;
|
||||
|
||||
// Keep references to widgets here so that we can destory any instances before
|
||||
// creating new ones (to avoid memory leaks)
|
||||
var autoComplete;
|
||||
var sButton, qButton, aButton;
|
||||
|
||||
this.dragDrop = function(did){
|
||||
var type;
|
||||
YAHOO.log('In drag drop');
|
||||
if(did.className.match("section")){type = 'section';}
|
||||
else if(did.className.match("question")){type = 'question';}
|
||||
else{ type = 'answer';}
|
||||
|
||||
var first = {id:did.id,type:type};
|
||||
var before = document.getElementById(did.id).previousSibling;
|
||||
|
||||
while(1){
|
||||
if( before == undefined || (before.id != undefined && before.id != '') ){
|
||||
break;
|
||||
}
|
||||
var before = before.previousSibling;
|
||||
}
|
||||
|
||||
var data = {id:'',type:''};
|
||||
|
||||
if(before != undefined && before.id != undefined && before.id != ''){
|
||||
if(before.className.match("section")){type = 'section';}
|
||||
else if(before.className.match("question")){type = 'question';}
|
||||
else{ type = 'answer';}
|
||||
data = {id:before.id,type:type};
|
||||
}
|
||||
YAHOO.log(first.id+' '+data.id);
|
||||
Survey.Comm.dragDrop(first,data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.clicked = function(){
|
||||
Survey.Comm.loadSurvey(this.id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.loadData = function(d){
|
||||
focus = d.address;//What is the current highlighted item.
|
||||
var showEdit = 1;
|
||||
if(lastId.toString() == d.address.toString()){
|
||||
showEdit = 0;
|
||||
lastId = -1;
|
||||
}else{
|
||||
lastId = d.address;
|
||||
}
|
||||
document.getElementById('sections').innerHTML=d.ddhtml;
|
||||
|
||||
//add event handlers for if a tag is clicked
|
||||
for(var x in d.ids){
|
||||
YAHOO.log('adding handler for '+ d.ids[x]);
|
||||
YAHOO.util.Event.addListener(d.ids[x], "click", this.clicked);
|
||||
new Survey.DDList(d.ids[x],"sections");
|
||||
}
|
||||
|
||||
//add the add object buttons
|
||||
// if(d.buttons['section']){
|
||||
document.getElementById('addSection').innerHTML = '';
|
||||
document.getElementById('addQuestion').innerHTML = '';
|
||||
document.getElementById('addAnswer').innerHTML = '';
|
||||
var button = new YAHOO.widget.Button({ label:"Add Section", id:"addsection", container:"addSection" });
|
||||
button.on("click", this.addSection);
|
||||
// }
|
||||
// if(d.buttons['question']){
|
||||
var button = new YAHOO.widget.Button({ label:"Add Question", id:"addquestion", container:"addQuestion" });
|
||||
button.on("click", this.addQuestion,d.buttons['question']);
|
||||
// }
|
||||
if(d.buttons['answer']){
|
||||
var button = new YAHOO.widget.Button({ label:"Add Answer", id:"addanswer", container:"addAnswer" });
|
||||
button.on("click", this.addAnswer,d.buttons['answer']);
|
||||
}
|
||||
|
||||
if(showEdit == 1){
|
||||
this.loadObjectEdit(d.edithtml,d.type);
|
||||
}else{
|
||||
document.getElementById('edit').innerHTML = "";
|
||||
}
|
||||
lastDataSet = d;
|
||||
}
|
||||
|
||||
this.addSection = function(){
|
||||
Survey.Comm.newSection();
|
||||
}
|
||||
|
||||
|
||||
this.addQuestion = function(e,id){
|
||||
Survey.Comm.newQuestion(id);
|
||||
}
|
||||
|
||||
this.addAnswer = function(e,id){
|
||||
Survey.Comm.newAnswer(id);
|
||||
}
|
||||
|
||||
this.loadObjectEdit = function(edit,type){
|
||||
if(edit){
|
||||
Survey.ObjectTemplate.loadObject(edit,type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.loadLast = function(){
|
||||
this.loadData(lastDataSet);
|
||||
}
|
||||
}();
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
// Initialize survey
|
||||
//
|
||||
//----------------------------------------------------------------
|
||||
Survey.OnLoad = function() {
|
||||
var e = YAHOO.util.Event;
|
||||
return {
|
||||
init: function() {
|
||||
e.onDOMReady(this.initHandler);
|
||||
},
|
||||
initHandler: function(){
|
||||
new YAHOO.util.DDTarget("sections","sections");
|
||||
Survey.Comm.loadSurvey();
|
||||
},
|
||||
}
|
||||
}();
|
||||
dragDrop: function(did){
|
||||
|
||||
Survey.OnLoad.init();
|
||||
YAHOO.log('In drag drop');
|
||||
var type = did.className.match("section") ? 'section'
|
||||
: did.className.match("question") ? 'question'
|
||||
: 'answer';
|
||||
|
||||
var first = {
|
||||
id: did.id, // pre-drag index of item
|
||||
type: type
|
||||
};
|
||||
var before = YAHOO.util.Dom.getPreviousSiblingBy( document.getElementById(did.id), function(node){
|
||||
return node.id; // true iff node has a non-empty id
|
||||
});
|
||||
|
||||
var data = {
|
||||
id: '',
|
||||
type: ''
|
||||
};
|
||||
|
||||
if (before) {
|
||||
type = before.className.match("section") ? 'section'
|
||||
: before.className.match("question") ? 'question'
|
||||
: 'answer';
|
||||
data = {
|
||||
id: before.id,
|
||||
type: type
|
||||
};
|
||||
}
|
||||
YAHOO.log(first.id + ' ' + data.id);
|
||||
Survey.Comm.dragDrop(first, data);
|
||||
},
|
||||
|
||||
clicked: function(){
|
||||
Survey.Comm.loadSurvey(this.id);
|
||||
},
|
||||
|
||||
loadData: function(d){
|
||||
focus = d.address;//What is the current highlighted item.
|
||||
var showEdit = 1;
|
||||
if (lastId.toString() === d.address.toString()) {
|
||||
showEdit = 0;
|
||||
lastId = -1;
|
||||
}
|
||||
else {
|
||||
lastId = d.address;
|
||||
}
|
||||
|
||||
// First purge any event handlers bound to sections node..
|
||||
YAHOO.util.Event.purgeElement('sections', true);
|
||||
|
||||
// Now we can re-write its innerHTML without fear of memory leaks
|
||||
document.getElementById('sections').innerHTML = d.ddhtml;
|
||||
|
||||
//add event handlers for if a tag is clicked
|
||||
for (var x in d.ids) {
|
||||
if (YAHOO.lang.hasOwnProperty(d.ids, x)) {
|
||||
YAHOO.log('adding handler for ' + d.ids[x]);
|
||||
YAHOO.util.Event.addListener(d.ids[x], "click", this.clicked);
|
||||
var _s = new Survey.DDList(d.ids[x], "sections");
|
||||
}
|
||||
}
|
||||
|
||||
sButton && sButton.destroy();
|
||||
sButton = new YAHOO.widget.Button({
|
||||
label: "Add Section",
|
||||
id: "addsection",
|
||||
container: "addSection"
|
||||
});
|
||||
sButton.on("click", this.addSection);
|
||||
|
||||
qButton && qButton.destroy();
|
||||
qButton = new YAHOO.widget.Button({
|
||||
label: "Add Question",
|
||||
id: "addquestion",
|
||||
container: "addQuestion"
|
||||
});
|
||||
qButton.on("click", this.addQuestion, d.buttons.question);
|
||||
|
||||
if (d.buttons.answer) {
|
||||
aButton && aButton.destroy();
|
||||
aButton = new YAHOO.widget.Button({
|
||||
label: "Add Answer",
|
||||
id: "addanswer",
|
||||
container: "addAnswer"
|
||||
});
|
||||
aButton.on("click", this.addAnswer, d.buttons.answer);
|
||||
}
|
||||
|
||||
if (showEdit == 1) {
|
||||
this.loadObjectEdit(d.edithtml, d.type);
|
||||
|
||||
// build the goto auto-complete widget
|
||||
if (d.gotoTargets && document.getElementById('goto')) {
|
||||
var ds = new YAHOO.util.LocalDataSource(d.gotoTargets);
|
||||
autoComplete = new YAHOO.widget.AutoComplete('goto', 'goto-yui-ac-container', ds);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Survey.ObjectTemplate.unloadObject();
|
||||
if (autoComplete) {
|
||||
autoComplete.destroy();
|
||||
autoComplete = null;
|
||||
}
|
||||
}
|
||||
lastDataSet = d;
|
||||
},
|
||||
|
||||
addSection: function(){
|
||||
Survey.Comm.newSection();
|
||||
},
|
||||
|
||||
addQuestion: function(e, id){
|
||||
Survey.Comm.newQuestion(id);
|
||||
},
|
||||
|
||||
addAnswer: function(e, id){
|
||||
Survey.Comm.newAnswer(id);
|
||||
},
|
||||
|
||||
loadObjectEdit: function(edit, type){
|
||||
if (edit) {
|
||||
Survey.ObjectTemplate.loadObject(edit, type);
|
||||
}
|
||||
},
|
||||
|
||||
loadLast: function(){
|
||||
this.loadData(lastDataSet);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// Initialize survey
|
||||
YAHOO.util.Event.onDOMReady(function(){
|
||||
var ddTarget = new YAHOO.util.DDTarget("sections", "sections");
|
||||
Survey.Comm.loadSurvey();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
if (typeof Survey == "undefined") {
|
||||
var Survey = {};
|
||||
}
|
||||
|
||||
Survey.AnswerTemplate = new function(){
|
||||
this.params;
|
||||
this.loadAnswer = function(params){
|
||||
for(var p in params){
|
||||
if(params[p] == undefined){params[p] = '';}
|
||||
}
|
||||
|
||||
var html = "\
|
||||
<div id='answer'>\
|
||||
<div class='hd'>Please enter answer information</div>\
|
||||
<div class='bd'>\
|
||||
\
|
||||
<form name='form' method='POST' action='?func=submitAnswerEdit'>\
|
||||
\
|
||||
<p>Answer Number: "+params.sequenceNumber + "\
|
||||
\
|
||||
<input type='hidden' name='Survey_sectionId' value='"+params.Survey_sectionId+"'>\
|
||||
<input type='hidden' name='Survey_questionId' value='"+params.Survey_questionId+"'>\
|
||||
<input type='hidden' name='Survey_answerId' value='"+params.Survey_answerId+"'>";
|
||||
html = html + "<p>Answer Text:\n<textarea name='answerText'>"+params.answerText+"</textArea>\n";
|
||||
html = html + "<p>Recorded Answer\n<textarea name='recordedAnswer'>"+params.recordedAnswer+"</textArea>\n";
|
||||
html = html + "<p>Jump to:<input type=text value='"+params.gotoQuestion+"' name=gotoQuestion size=4>";
|
||||
html = html + "<span id='textParams'><p>Text Answer Cols:<input type=text size=2 value='"+params.textCols+"' name=textCols> Rows: \
|
||||
<input type=text size=2 value='"+params.textRows+"' name=textRows> </p></span>";
|
||||
html = html + "<p>Is this the correct answer:\n" +
|
||||
this.makeRadio('isCorrect',[{text:'Yes',value:1},{text:'No',value:0}],params.isCorrect);
|
||||
html = html + "<p>Min:<input type=text value='"+params.min+"' name=min size=2>";
|
||||
html = html + "<p>Max:<input type=text value='"+params.max+"' name=max size=2>";
|
||||
html = html + "<p>Step:<input type=text value='"+params.step+"' name=step size=2>";
|
||||
html = html + "<p>Verbatim:\n" +
|
||||
this.makeRadio('verbatim',[{text:'Yes',value:1},{text:'No',value:0}],params.verbatim);
|
||||
document.getElementById('edit').innerHTML = html;
|
||||
|
||||
var butts = [{ text:"Submit", handler:function(){this.submit();}, isDefault:true },{ text:"Cancel", handler:function(){this.cancel();}} ];
|
||||
if(params.Survey_answerId != ''){
|
||||
butts[2] = { text:"Delete", handler:function(){Survey.Comm.deleteAnswer(Survey.AnswerTemplate.params.Survey_answerId);}};
|
||||
}
|
||||
|
||||
var form = new YAHOO.widget.Dialog("answer",
|
||||
{ width : "500px",
|
||||
fixedcenter : true,
|
||||
visible : false,
|
||||
constraintoviewport : true,
|
||||
buttons : butts
|
||||
});
|
||||
|
||||
form.callback = Survey.Comm.callback;
|
||||
form.render();
|
||||
form.show();
|
||||
this.params = params;
|
||||
};
|
||||
|
||||
this.makeRadio = function(name,values,checked){
|
||||
var html = '';
|
||||
for(var i in values){
|
||||
if(checked == values[i]['value']){
|
||||
html = html+ "<input type='radio' name='" + name + "' value='" + values[i]['value'] + "' checked>" + values[i]['text'];
|
||||
}else{
|
||||
html = html+ "<input type='radio' name='" + name + "' value='" + values[i]['value'] + "' >" + values[i]['text'];
|
||||
}
|
||||
}
|
||||
html = html + "\n";
|
||||
return html;
|
||||
}
|
||||
}();
|
||||
|
|
@ -6,6 +6,7 @@ Survey.Comm = new function(){
|
|||
var callMade = 0;
|
||||
|
||||
var request = function(sUrl,callback,postData){
|
||||
YAHOO.util.Dom.setStyle('mask-all','display','block');
|
||||
if(callMade == 1){
|
||||
alert("Waiting on previous request");
|
||||
}else{
|
||||
|
|
@ -15,10 +16,12 @@ Survey.Comm = new function(){
|
|||
}
|
||||
this.callback = {
|
||||
success:function(o){
|
||||
YAHOO.util.Dom.setStyle('mask-all','display','none');
|
||||
callMade = 0;
|
||||
Survey.Data.loadData(YAHOO.lang.JSON.parse(o.responseText));
|
||||
},
|
||||
failure: function(o){
|
||||
YAHOO.util.Dom.setStyle('mask-all','display','none')
|
||||
callMade = 0;
|
||||
alert("Last request failed");
|
||||
Survey.Data.loadLast();
|
||||
|
|
|
|||
|
|
@ -1,33 +1,118 @@
|
|||
if (typeof Survey == "undefined") {
|
||||
|
||||
/*global Survey, YAHOO */
|
||||
if (typeof Survey === "undefined") {
|
||||
var Survey = {};
|
||||
}
|
||||
|
||||
Survey.ObjectTemplate = new function(){
|
||||
Survey.ObjectTemplate = (function(){
|
||||
|
||||
this.loadObject = function(html,type){
|
||||
// Keep references to widgets here so that we can destory any instances before
|
||||
// creating new ones (to avoid memory leaks)
|
||||
var dialog;
|
||||
var editor;
|
||||
|
||||
document.getElementById('edit').innerHTML = html;
|
||||
return {
|
||||
|
||||
unloadObject: function(){
|
||||
// First destory the editor..
|
||||
if (editor) {
|
||||
editor.destroy();
|
||||
editor = null;
|
||||
}
|
||||
|
||||
// And then the Dialog that contains it.
|
||||
if (dialog) {
|
||||
dialog.destroy();
|
||||
dialog = null;
|
||||
}
|
||||
},
|
||||
|
||||
var butts = [
|
||||
{ text:"Submit", handler:function(){this.submit();}, isDefault:true },
|
||||
{ text:"Copy", handler:function(){document.getElementById('copy').value = 1; this.submit();}},
|
||||
{ text:"Cancel", handler:function(){this.cancel(); Survey.Comm.loadSurvey('-');}},
|
||||
{ text:"Delete", handler:function(){document.getElementById('delete').value = 1; this.submit();}}
|
||||
];
|
||||
loadObject: function(html, type){
|
||||
// Make sure we purge any event listeners before overwrite innerHTML..
|
||||
YAHOO.util.Event.purgeElement('edit', true);
|
||||
document.getElementById('edit').innerHTML = html;
|
||||
|
||||
var btns = [{
|
||||
text: "Submit",
|
||||
handler: function(){
|
||||
editor.saveHTML();
|
||||
this.submit();
|
||||
},
|
||||
isDefault: true
|
||||
}, {
|
||||
text: "Copy",
|
||||
handler: function(){
|
||||
document.getElementById('copy').value = 1;
|
||||
this.submit();
|
||||
}
|
||||
}, {
|
||||
text: "Cancel",
|
||||
handler: function(){
|
||||
this.cancel();
|
||||
Survey.Comm.loadSurvey('-');
|
||||
}
|
||||
}, {
|
||||
text: "Delete",
|
||||
handler: function(){
|
||||
document.getElementById('delete').value = 1;
|
||||
this.submit();
|
||||
}
|
||||
}, {
|
||||
text: "Preview",
|
||||
handler: function(){
|
||||
if (type === 'answer') {
|
||||
alert('Sorry, preview is only supported for Sections and Questions, not Answers');
|
||||
}
|
||||
else {
|
||||
var msg = 'This will delete any Survey responses you have made under this ' +
|
||||
'user account and redirect you to the Take Survey page starting at the selected item. ' +
|
||||
"\n\nAre you sure you want to continue?";
|
||||
if (confirm(msg)) {
|
||||
window.location.search = 'func=jumpTo;id=' + dialog.getData().id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
dialog = new YAHOO.widget.Dialog(type, {
|
||||
width: "600px",
|
||||
context: [document.body, 'tr', 'tr'],
|
||||
visible: false,
|
||||
constraintoviewport: true,
|
||||
buttons: btns
|
||||
});
|
||||
|
||||
dialog.callback = Survey.Comm.callback;
|
||||
dialog.render();
|
||||
|
||||
var form = new YAHOO.widget.Dialog(type,
|
||||
{
|
||||
width : "500px",
|
||||
fixedcenter : true,
|
||||
visible : false,
|
||||
constraintoviewport : true,
|
||||
buttons : butts
|
||||
} );
|
||||
var resizeGotoExpression = new YAHOO.util.Resize('resize_gotoExpression_formId');
|
||||
resizeGotoExpression.on('resize', function(ev) {
|
||||
YAHOO.util.Dom.setStyle('gotoExpression_formId', 'width', (ev.width - 6) + "px");
|
||||
YAHOO.util.Dom.setStyle('gotoExpression_formId', 'height', (ev.height - 6) + "px");
|
||||
});
|
||||
|
||||
var textareaId = type + 'Text';
|
||||
var textarea = YAHOO.util.Dom.get(textareaId);
|
||||
|
||||
var height = YAHOO.util.Dom.getStyle(textarea, 'height');
|
||||
if (!height) {
|
||||
height = '300px';
|
||||
}
|
||||
|
||||
form.callback = Survey.Comm.callback;
|
||||
form.render();
|
||||
form.show();
|
||||
initHoverHelp(type);
|
||||
}
|
||||
}();
|
||||
// N.B. SimpleEditor has a memory leak so this eats memory on every instantiation
|
||||
editor = new YAHOO.widget.SimpleEditor(textareaId, {
|
||||
height: height,
|
||||
width: '100%',
|
||||
dompath: false //Turns on the bar at the bottom
|
||||
});
|
||||
|
||||
if (editor.get('toolbar')) {
|
||||
editor.get('toolbar').titlebar = false;
|
||||
}
|
||||
editor.render();
|
||||
|
||||
dialog.show();
|
||||
initHoverHelp(type);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue