diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index ac3656147..f265b1297 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,4 +1,5 @@ 7.7.7 + - Added EMS Schedule table - rfe #10061: Use email as username at registration - Added WebGUI community statistics question to the site setup wizard. - Added Ogone payment plugin ( Martin Kamerbeek / Oqapi ) diff --git a/docs/upgrades/packages-7.7.7/root_import_ems_ems-badge-listing-default.wgpkg b/docs/upgrades/packages-7.7.7/root_import_ems_ems-badge-listing-default.wgpkg new file mode 100644 index 000000000..05eda7467 Binary files /dev/null and b/docs/upgrades/packages-7.7.7/root_import_ems_ems-badge-listing-default.wgpkg differ diff --git a/docs/upgrades/packages-7.7.7/root_import_ems_ems-schedule-listing-default2.wgpkg b/docs/upgrades/packages-7.7.7/root_import_ems_ems-schedule-listing-default2.wgpkg new file mode 100644 index 000000000..7ba249800 Binary files /dev/null and b/docs/upgrades/packages-7.7.7/root_import_ems_ems-schedule-listing-default2.wgpkg differ diff --git a/docs/upgrades/upgrade_7.7.6-7.7.7.pl b/docs/upgrades/upgrade_7.7.6-7.7.7.pl index 6ceea00a8..d42232047 100644 --- a/docs/upgrades/upgrade_7.7.6-7.7.7.pl +++ b/docs/upgrades/upgrade_7.7.6-7.7.7.pl @@ -36,6 +36,7 @@ alterVATNumberTable( $session ); addRedirectAfterLoginUrlToSettings( $session ); addSurveyTestResultsTemplateColumn( $session ); fixSMSUserProfileI18N($session); +addEmsScheduleColumns ($session); addMapAsset( $session ); installFilePumpHandler($session); installFilePumpTable($session); @@ -122,6 +123,18 @@ sub installFilePumpAdminGroup { #} print "Done.\n" unless $quiet; } +#---------------------------------------------------------------------------- +sub addEmsScheduleColumns { + my $session = shift; + print "\tAdding columns for the EMS Schedule table..." unless $quiet; + + $session->db->write( 'alter table EventManagementSystem add column scheduleTemplateId char(22)' ); + $session->db->write( 'alter table EventManagementSystem add column scheduleColumnsPerPage integer' ); + + print "Done\n" unless $quiet; + +} + #---------------------------------------------------------------------------- sub installFilePumpHandler { diff --git a/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm b/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm index 3e3a05df9..b37066451 100644 --- a/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm +++ b/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm @@ -32,6 +32,7 @@ use WebGUI::HTMLForm; use WebGUI::International; use WebGUI::Utility; use WebGUI::Workflow::Instance; +use Tie::IxHash; @@ -53,12 +54,27 @@ sub definition { }, templateId => { fieldType => 'template', - defaultValue => '2rC4ErZ3c77OJzJm7O5s3w', + defaultValue => '2rC4ErZ3c77OJzJm7O5s3w', tab => 'display', label => $i18n->get('main template'), hoverHelp => $i18n->get('main template help'), namespace => 'EMS', }, + scheduleTemplateId => { + fieldType => 'template', + defaultValue => 'S2_LsvVa95OSqc66ITAoig', + tab => 'display', + label => $i18n->get('schedule template'), + hoverHelp => $i18n->get('schedule template help'), + namespace => 'EMS', + }, + scheduleColumnsPerPage => { + fieldType => 'Integer', + defaultValue => '5', + tab => 'display', + label => $i18n->get('schedule number of columns'), + hoverHelp => $i18n->get('schedule number of columns help'), + }, badgeBuilderTemplateId => { fieldType => 'template', defaultValue => 'BMybD3cEnmXVk2wQ_qEsRQ', @@ -257,6 +273,35 @@ sub getEventFieldsForImport { return \@fields; } +#------------------------------------------------------------------- + +=head2 getLocations () + +Returns an array of all locations for this EMS +SQL optimized for quick access + +=cut + +sub getLocations { + my $self = shift; + + my %hash; + my $tickets = $self->getTickets; + for my $ticket ( @$tickets ) { + my $name = $ticket->get('location'); + next if not defined $name; + $hash{$name} = 1; + } + my @locations = sort keys %hash; +# @locations = $self->session->db->read(q{ +# select distinct(EMSTicket.location) +# from EMSTicket join asset using (assetId) +# where asset.parentId = ? +# order by EMSTicket.location +# },[$self->getId])->array; + + return @locations; +} #------------------------------------------------------------------- @@ -410,6 +455,7 @@ sub view { my %var = ( addBadgeUrl => $self->getUrl('func=add;class=WebGUI::Asset::Sku::EMSBadge'), buildBadgeUrl => $self->getUrl('func=buildBadge'), + viewScheduleUrl => $self->getUrl('func=viewSchedule'), manageBadgeGroupsUrl=> $self->getUrl('func=manageBadgeGroups'), getBadgesUrl => $self->getUrl('func=getBadgesAsJson'), canEdit => $self->canEdit, @@ -1085,6 +1131,103 @@ sub www_getRibbonsAsJson { } +#------------------------------------------------------------------- + +=head2 www_getScheduleDataJSON () + +returns the JSON data for a page of the schedule table + +=cut + + +sub www_getScheduleDataJSON { + my $self = shift; + my $session = $self->session; + # the following two are expected to be configurable... + my $locationsPerPage = $self->get('scheduleColumnsPerPage'); + + my ($db, $form) = $session->quick(qw(db form)); + my $pageNumber = $form->get('pageNumber') || 1; + my @ticketLocations = $self->getLocations(); + # the total number of pages is the number of locations divided by the number of locations per page + my $numberOfPages = int( .9 + scalar(@ticketLocations) / $locationsPerPage ); + # skip everything else if there are no locations/pages + return JSON->new->encode( { + records => [ ], totalRecords => 0, recordsReturned => 0, startIndex => 0, + currentPage => 0, totalPages => 0, + sort => undef, dir => 'asc', pageSize => 0, + }) if $numberOfPages == 0; + # now we pick out the locations to be displayed on this page + my $indexFirstLocation = ($pageNumber-1)*$locationsPerPage; + my $indexLastLocation = $pageNumber*$locationsPerPage - 1; + @ticketLocations = @ticketLocations[$indexFirstLocation..$indexLastLocation]; + my $tickets = $db->read( q{ + select assetData.assetId, sku.description, assetData.title, EMSTicket.startDate, EMSTicket.location + from EMSTicket + join sku using (assetId,revisionDate) + join assetData using (assetId,revisionDate) + join asset using (assetId) + where asset.parentId = ? + and EMSTicket.location in ( } . + join( ',', (map { $db->quote($_) } (@ticketLocations))) . + q{ ) + and assetData.revisionDate = ( + select max(revisionDate) + from assetData + where assetData.assetId=asset.assetId + and ( assetData.status = 'approved' + or assetData.tagId = ? ) + ) + order by EMSTicket.startDate + },[ $self->getId, + $session->scratch->get("versionTag") + ]); + my %hash; + tie %hash, 'Tie::IxHash'; + while( my $row = $tickets->hashRef ) { + $row->{type} = 'ticket'; + $hash{$row->{startDate}}{$row->{location}} = $row; + } + my %results = (); + $results{records} = []; ##Initialize to an empty array + my $ctr = 0; + my %locationMap = map { 'col' . ++$ctr , $_ } @ticketLocations; + # fill out the columns in the table + while( $ctr < $locationsPerPage ) { $locationMap{ 'col' . ++$ctr } = '' }; + push @{$results{records}}, { colDate => '' , map { $_ , { type => 'label', title => $locationMap{$_} || '' } } ( keys %locationMap ) }; + for my $startDate ( keys %hash ) { + my $row = { colDate => $startDate }; + my $empty = 1; + for my $col ( keys %locationMap ) { + my $location = $locationMap{$col}; + if( exists $hash{$startDate}{$location} ) { + $row->{$col} = $hash{$startDate}{$location}; + $empty = 0; + } else { + $row->{$col} = { type => 'empty' }; + } + } + next if $empty; + push @{$results{records}}, $row; + } + + my $rowCount = scalar(@{$results{records}}); + $results{totalRecords} = $rowCount; + $results{recordsReturned} = $rowCount; + $results{rowsPerPage} = $rowCount; + $results{startIndex} = 0; + $results{sort} = undef; + $results{dir} = "asc"; + $results{pageSize} = 10; + # these next two are used to configure the paginator + $results{totalPages} = $numberOfPages; + $results{currentPage} = $pageNumber; + $session->http->setMimeType('application/json'); + return JSON->new->encode(\%results); +} + + + #------------------------------------------------------------------- =head2 www_getTicketsAsJson () @@ -1240,6 +1383,7 @@ className='WebGUI::Asset::Sku::EMSTicket' and state='published' and revisionDate } + #------------------------------------------------------------------- =head2 www_getTokensAsJson () @@ -1872,4 +2016,36 @@ sub www_toggleRegistrantCheckedIn { } +#------------------------------------------------------------------- + +=head2 www_viewSchedule () + +view the schedule table + +=cut + +sub www_viewSchedule { + my $self = shift; + my $db = $self->session->db; + my $rowsPerPage = 25; + my $locationsPerPage = $self->get('scheduleColumnsPerPage'); + + my @columnNames = map { "'col" . $_ . "'" } ( 1..$locationsPerPage ); + my $fieldList = join ',', @columnNames; + my $dataColumns = join ",\n", map { + '{key:' . $_ . ',sortable:false,label:"",formatter:formatViewScheduleItem}' + } @columnNames; + + return $self->processStyle( + $self->processTemplate({ + backUrl => $self->getUrl, + rowsPerPage => $rowsPerPage, + dataColumns => $dataColumns, + fieldList => $fieldList, + dataSourceUrl => $self->getUrl('func=getScheduleDataJSON'), + },$self->get('scheduleTemplateId'))); + +} + 1; + diff --git a/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm b/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm index ba84b9a36..af3edcedd 100644 --- a/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm +++ b/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm @@ -80,6 +80,18 @@ our $I18N = { context => q|a link label|, }, + 'view schedule' => { + message => q|Schedule|, + lastUpdated => 0, + context => q|a link label:Brings up the schedule for the event.|, + }, + + 'schedule back link' => { + message => q|Back|, + lastUpdated => 0, + context => q|a link label:goes back to the main Event Manager form|, + }, + 'view tickets' => { message => q|View Tickets|, lastUpdated => 0, @@ -1842,6 +1854,30 @@ normal templates.|, context => q|Event data field|, }, + 'schedule template' => { + message => q|Schedule Template|, + lastUpdated => 1147050475, + context => q|Select a template to display the schedule tables.|, + }, + + 'schedule template help' => { + message => q|This template is used to display the schedule for events|, + lastUpdated => 1147050475, + context => q|Help text for the Schedule Template field|, + }, + + 'schedule number of columns' => { + message => q|Number of columns per page|, + lastUpdated => 1147050475, + context => q|the number of columns per page in the schedule table|, + }, + + 'schedule number of columns help' => { + message => q|This controls how many event locations will be displayed per page in the schedule. If your event only has a few locations then set this to that number; for ten to twenty locations: use half or a third of the number; for a large number of locations use the default|, + lastUpdated => 1147050475, + context => q|help text for the columns per page field|, + }, + }; 1; diff --git a/t/Asset/Wobject/EventManagementSystem.t b/t/Asset/Wobject/EventManagementSystem.t index d5f21e63a..5fa427fa5 100644 --- a/t/Asset/Wobject/EventManagementSystem.t +++ b/t/Asset/Wobject/EventManagementSystem.t @@ -19,6 +19,8 @@ use lib "$FindBin::Bin/../../lib"; use Test::More; use WebGUI::Test; # Must use this before any other WebGUI modules use WebGUI::Session; +use JSON; +use Test::Deep; #use Data::Dumper; #---------------------------------------------------------------------------- @@ -35,7 +37,7 @@ $versionTag->set({name=>"EventManagementSystem Test"}); #---------------------------------------------------------------------------- # Tests -plan tests => 22; # Increment this number for each test you create +plan tests => 30 ; # Increment this number for each test you create #---------------------------------------------------------------------------- @@ -132,8 +134,187 @@ ok($ems->can('getRibbons'), 'Can get ribbons'); my $ribbons = $ems->getRibbons; ok(scalar(@$ribbons) == 2, 'Two ribbons exist'); -#---------------------------------------------------------------------------- -# Cleanup +ok( $ems->can('www_getScheduleDataJSON'), 'Can call get Schedule data' ); +ok( $ems->can('www_viewSchedule'), 'Can call view Schedule' ); +my $html = $ems->www_viewSchedule(); +ok( $html !~ /REPLACE/, 'tags were successfully replaced'); +# print 'html={', $html, "}\n"; +my $data = $ems->www_getScheduleDataJSON(); +cmp_deeply( JSON::from_json($data), + { + 'totalPages' => 0, + 'records' => [], + 'pageSize' => 0, + 'dir' => 'asc', + 'recordsReturned' => 0, + 'currentPage' => 0, + 'sort' => undef, + 'startIndex' => 0, + 'totalRecords' => 0 + }, + 'empty set: schedule data looks good' ); + +my @tickets= ( + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 1 room a 10 am', + eventNumber => 1, + startDate => '2009-01-01 10:00:00', + location => 'a', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 2 room b 10 am', + eventNumber => 2, + startDate => '2009-01-01 10:00:00', + location => 'b', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 3 room c 10 am', + eventNumber => 3, + startDate => '2009-01-01 10:00:00', + location => 'c', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 4 room a 11 am', + eventNumber => 4, + startDate => '2009-01-01 11:00:00', + location => 'a', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 5 room b 11 am', + eventNumber => 5, + startDate => '2009-01-01 11:00:00', + location => 'b', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 6 room c 11 am', + eventNumber => 6, + startDate => '2009-01-01 11:00:00', + location => 'c', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 7 room d 12 am', + eventNumber => 7, + startDate => '2009-01-01 12:00:00', + location => 'd', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 8 room a 1 pm', + eventNumber => 8, + startDate => '2009-01-01 13:00:00', + location => 'a', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 9 room b 1 pm', + eventNumber => 9, + startDate => '2009-01-01 13:00:00', + location => 'b', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 10 room c 1 pm', + eventNumber => 10, + startDate => '2009-01-01 13:00:00', + location => 'c', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 11 room e 2 pm', + eventNumber => 11, + startDate => '2009-01-01 14:00:00', + location => 'e', + }), + $ems->addChild({ + className => "WebGUI::Asset::Sku::EMSTicket", + title => 'lecture 12 room f 2 pm', + eventNumber => 12, + startDate => '2009-01-01 14:00:00', + location => 'f', + }), +); +is( scalar(@tickets), 12, 'created tickets for ems'); +my $tickets = $ems->getTickets; +is(scalar(@$tickets), 14, 'Fourteen tickets exist'); +my $locations = [ $ems->getLocations ]; +cmp_deeply($locations, [ 'a','b','c','d','e','f' ], 'get locations returns all expected locations'); +# print 'locations=[', join( ',', @$locations ),"]\n"; + +$data = $ems->www_getScheduleDataJSON(); +# print 'json:',$data, "\n"; +sub ticketInfo { my $tk = shift; return { + type => 'ticket', + title => $tk->get('title'), + assetId => $tk->get('assetId'), + description => $tk->get('description'), + location => $tk->get('location'), + startDate => $tk->get('startDate'), +}; } +cmp_deeply( JSON::from_json($data), { + records => [ + { colDate => '', + col1 => { type => 'label', title => 'a' }, + col2 => { type => 'label', title => 'b' }, + col3 => { type => 'label', title => 'c' }, + col4 => { type => 'label', title => 'd' }, + col5 => { type => 'label', title => 'e' }, + }, + { colDate => $tickets[0]->get('startDate'), + col1 => ticketInfo( $tickets[0] ), + col2 => ticketInfo( $tickets[1] ), + col3 => ticketInfo( $tickets[2] ), + col4 => { type => 'empty' }, + col5 => { type => 'empty' }, + }, + { colDate => $tickets[3]->get('startDate'), + col1 => ticketInfo( $tickets[3] ), + col2 => ticketInfo( $tickets[4] ), + col3 => ticketInfo( $tickets[5] ), + col4 => { type => 'empty' }, + col5 => { type => 'empty' }, + }, + { colDate => $tickets[6]->get('startDate'), + col1 => { type => 'empty' }, + col2 => { type => 'empty' }, + col3 => { type => 'empty' }, + col4 => ticketInfo( $tickets[6] ), + col5 => { type => 'empty' }, + }, + { colDate => $tickets[7]->get('startDate'), + col1 => ticketInfo( $tickets[7] ), + col2 => ticketInfo( $tickets[8] ), + col3 => ticketInfo( $tickets[9] ), + col4 => { type => 'empty' }, + col5 => { type => 'empty' }, + }, + { colDate => $tickets[10]->get('startDate'), + col1 => { type => 'empty' }, + col2 => { type => 'empty' }, + col3 => { type => 'empty' }, + col4 => { type => 'empty' }, + col5 => ticketInfo( $tickets[10] ), + }, + ], + totalRecords => 6, + recordsReturned => 6, + startIndex => 0, + sort => undef, + dir => 'asc', + totalPages => 2, + pageSize => 10, + currentPage => 1, + rowsPerPage => 6, + }, + 'twelve tickets: schedule data looks good' ); + +#---------------------------------------------------------------------------# Cleanup END { $ems->purge;