diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index e3c253b67..4eac7cfb8 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -5,6 +5,10 @@ - fixed #12106: CalendarUpdateFeeds activity does not handle time zones correctly - fixed #11213: Gooey on the Go format problem - mark makeUrlCompliant as deprecated. + - fixed #12059: WebGUI::Asset::Wobject::Map - Set Default Viewing Area button does not work. + - added: Setting MapPoint locations via address. + - added: Make Thing data searchable + - added: AssetProxy like macro for Thing data, ViewThingData 7.10.14 - fixed #12094: Cannot enter in Macros in URLs inside TinyMCE. diff --git a/docs/gotcha.txt b/docs/gotcha.txt index 077093ad7..c447314d8 100644 --- a/docs/gotcha.txt +++ b/docs/gotcha.txt @@ -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.10.15 +-------------------------------------------------------------------- + * WebGUI now depends on Geo::Coder::Googlev3 for it's Map asset + 7.10.13 -------------------------------------------------------------------- * WebGUI now depends on XML::FeedPP::MediaRSS. diff --git a/docs/upgrades/packages-7.10.15/home_map_map-templates.wgpkg b/docs/upgrades/packages-7.10.15/home_map_map-templates.wgpkg new file mode 100644 index 000000000..e7cf69efb Binary files /dev/null and b/docs/upgrades/packages-7.10.15/home_map_map-templates.wgpkg differ diff --git a/docs/upgrades/upgrade_7.10.14-7.10.15.pl b/docs/upgrades/upgrade_7.10.14-7.10.15.pl index a479efd41..ec2d3cc2a 100644 --- a/docs/upgrades/upgrade_7.10.14-7.10.15.pl +++ b/docs/upgrades/upgrade_7.10.14-7.10.15.pl @@ -22,7 +22,9 @@ use Getopt::Long; use WebGUI::Session; use WebGUI::Storage; use WebGUI::Asset; - +use WebGUI::AssetAspect::Installable; +use WebGUI::Asset::MapPoint; +use WebGUI::Asset::Wobject::Thingy; my $toVersion = '7.10.15'; my $quiet; # this line required @@ -31,6 +33,10 @@ my $quiet; # this line required my $session = start(); # this line required # upgrade functions go here +alterAssetIndexTable($session); +reindexAllThingys($session); +WebGUI::AssetAspect::Installable::upgrade("WebGUI::Asset::MapPoint",$session); +addRenderThingDataMacro($session); finish($session); # this line required @@ -44,6 +50,37 @@ finish($session); # this line required # print "DONE!\n" unless $quiet; #} +sub addRenderThingDataMacro { + my $session = shift; + print "\tAdd the new RenderThingData macro to the site config... " unless $quiet; + $session->config->addToHash('macros', 'RenderThingData', 'RenderThingData'); + print "DONE!\n" unless $quiet; +} + +sub alterAssetIndexTable { + my $session = shift; + print "\tExtend the assetIndex table so we can search things other than assets... " unless $quiet; + $session->db->write(<getIsa($session); + THINGY: while (1) { + my $thingy = eval { $get_thingy->() }; + next THINGY if Exception::Class->caught(); + last THINGY unless $thingy; + $thingy->indexContent; + } + print "DONE!\n" unless $quiet; +} # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- diff --git a/etc/WebGUI.conf.original b/etc/WebGUI.conf.original index 721372ed4..f85220d79 100644 --- a/etc/WebGUI.conf.original +++ b/etc/WebGUI.conf.original @@ -848,6 +848,7 @@ "PickLanguage" : "PickLanguage", "RandomAssetProxy" : "RandomAssetProxy", "RandomThread" : "RandomThread", + "RenderThingData" : "RenderThingData", "RootTitle" : "RootTitle", "r" : "r_printable", "Spacer" : "Spacer", diff --git a/lib/WebGUI/Asset/MapPoint.pm b/lib/WebGUI/Asset/MapPoint.pm index 3edd31b96..413bee2fd 100644 --- a/lib/WebGUI/Asset/MapPoint.pm +++ b/lib/WebGUI/Asset/MapPoint.pm @@ -18,6 +18,9 @@ use strict; use Tie::IxHash; use base 'WebGUI::Asset'; use WebGUI::Utility; +use Geo::Coder::Googlev3; +use Data::Dumper; + # To get an installer for your wobject, add the Installable AssetAspect # See WebGUI::AssetAspect::Installable and sbin/installClass.pl for more @@ -143,6 +146,12 @@ sub definition { hoverHelp => $i18n->get("storageIdPhoto description"), noFormPost => 1, }, + isGeocoded => { + fieldType => "yesNo", + tab => "properties", + label => $i18n->get("isGeocoded label"), + hoverHelp => $i18n->get("isGeocoded description"), + }, userDefined1 => { fieldType => "hidden", }, @@ -159,6 +168,7 @@ sub definition { fieldType => "hidden", }, ); + push @{$definition}, { assetName => $i18n->get('assetName'), icon => 'mappoint.png', @@ -212,6 +222,7 @@ AT LEAST the following keys: title - The title of the point content - HTML content to show details about the point url - The URL of the point + userDefined1-5 - The userDefined fields The following keys are optional @@ -227,7 +238,7 @@ sub getMapInfo { # Get asset properties $var->{ url } = $self->getUrl; $var->{ assetId } = $self->getId; - my @keys = qw( latitude longitude title ); + my @keys = qw( latitude longitude title userDefined1 userDefined2 userDefined3 userDefined4 userDefined5 isGeocoded ); for my $key ( @keys ) { $var->{ $key } = $self->get( $key ); } @@ -274,6 +285,15 @@ sub getTemplateVarsEditForm { my $session = $self->session; my $var = $self->getTemplateVars; + my $parent = $self->getParent; + #If it's a new point, we have to get the parent from the url + unless ($parent) { + my $url = $session->url->page; + $parent = WebGUI::Asset->newByUrl($session,$url); + } + + $var->{'can_edit_map'} = $parent->canEdit; + $var->{ form_header } = WebGUI::Form::formHeader( $session ) . WebGUI::Form::hidden( $session, { @@ -323,8 +343,25 @@ sub getTemplateVarsEditForm { name => "synopsis", value => $self->get("synopsis"), resizable => 0, - } ); + } ); + #Only allow people who can edit the parent to change isHidden + if($var->{'can_edit_map'}) { + my $isHidden = (defined $self->get("isHidden")) ? $self->get("isHidden") : 1; + $var->{ "form_isHidden" } + = WebGUI::Form::yesNo( $session, { + name => "isHidden", + value => $isHidden, + } ); + } + + my $isGeocoded = ( $self->getId ) ? $self->get("isGeocoded") : 1; + $var->{"form_isGeocoded"} + = WebGUI::Form::checkbox( $session, { + name => "isGeocoded", + value => 1, + checked => $isGeocoded + } ); # Fix storageIdPhoto because scripts do not get executed in ajax requests $var->{ "form_storageIdPhoto" } = ''; @@ -339,6 +376,35 @@ sub getTemplateVarsEditForm { #------------------------------------------------------------------- +=head2 indexContent ( ) + +Indexing the content of attachments and user defined fields. See WebGUI::Asset::indexContent() for additonal details. + +=cut + +sub indexContent { + my $self = shift; + my $indexer = $self->SUPER::indexContent; + $indexer->addKeywords($self->get("website")); + $indexer->addKeywords($self->get("address1")); + $indexer->addKeywords($self->get("address2")); + $indexer->addKeywords($self->get("city")); + $indexer->addKeywords($self->get("region")); + $indexer->addKeywords($self->get("zipCode")); + $indexer->addKeywords($self->get("country")); + $indexer->addKeywords($self->get("phone")); + $indexer->addKeywords($self->get("fax")); + $indexer->addKeywords($self->get("email")); + $indexer->addKeywords($self->get("userDefined1")); + $indexer->addKeywords($self->get("userDefined2")); + $indexer->addKeywords($self->get("userDefined3")); + $indexer->addKeywords($self->get("userDefined4")); + $indexer->addKeywords($self->get("userDefined5")); + return $indexer; +} + +#------------------------------------------------------------------- + =head2 processAjaxEditForm ( ) Process the Ajax Edit Form from the Map. If any errors occur, return @@ -367,6 +433,29 @@ sub processAjaxEditForm { $prop->{ synopsis } = $form->get('synopsis'); $prop->{ url } = $session->url->urlize( $self->getParent->getUrl . '/' . $prop->{title} ); $prop->{ ownerUserId } = $form->get('ownerUserId') || $session->user->userId; + #Only users who can edit the map can set this property + if($self->getParent->canEdit) { + $prop->{ isHidden } = $form->get('isHidden'); + } + $prop->{isGeocoded } = $form->get('isGeocoded') || 0; + if($prop->{isGeocoded} && + ( + ( $form->get("address1") ne $self->get("address1") ) + || ( $form->get("address2") ne $self->get("address2") ) + || ( $form->get("city") ne $self->get("city") ) + || ( $form->get("region") ne $self->get("region") ) + || ( $form->get("zipCode") ne $self->get("zipCode") ) + || ( $form->get("country") ne $self->get("country") ) + ) + ) { + my $geocoder = Geo::Coder::Googlev3->new; + my $address_str = $form->get("address1"); + $address_str .= " ".$form->get("address2") if($form->get("address2")); + $address_str .= ", ".$form->get("city").", ".$form->get("region").", ".$form->get("zipCode").", ".$form->get("country"); + my $location = $geocoder->geocode( location => $address_str ); + $prop->{latitude } = $location->{geometry}->{location}->{lat}; + $prop->{longitude} = $location->{geometry}->{location}->{lng}; + } $self->update( $prop ); @@ -420,6 +509,7 @@ sub www_view { return "redirect"; } + 1; #vim:ft=perl diff --git a/lib/WebGUI/Asset/Wobject/Map.pm b/lib/WebGUI/Asset/Wobject/Map.pm index d92ac69e5..2ba780023 100644 --- a/lib/WebGUI/Asset/Wobject/Map.pm +++ b/lib/WebGUI/Asset/Wobject/Map.pm @@ -18,6 +18,7 @@ use WebGUI::International; use WebGUI::Utility; use HTML::Entities qw(encode_entities); use base 'WebGUI::Asset::Wobject'; +use Data::Dumper; # To get an installer for your wobject, add the Installable AssetAspect # See WebGUI::AssetAspect::Installable and sbin/installClass.pl for more @@ -387,7 +388,9 @@ sub view { google.setOnLoadCallback( function() { var mapId = "%s"; var mapUrl = "%s"; - var map = new GMap2( document.getElementById("map_" + mapId) ); + var element = document.getElementById("map_" + mapId); + var map = new GMap2( element ); + element.mapObject = map; map.url = mapUrl; map.assetId = mapId; map.setCenter(new GLatLng(%s, %s), %s); @@ -395,6 +398,10 @@ sub view { map.extrasUrl = "%s"; var markermanager = new MarkerManager(map, {trackMarkers: true}); + map.markermanager = markermanager; + map.fancyClickHandler = null; + map.panOnClick = true; + map.clickToEdit = false; ENDHTML @@ -408,9 +415,9 @@ ENDHTML for my $pointId ( @{$pointIds} ) { my $point = WebGUI::Asset->newByDynamicClass( $session, $pointId ); next unless $point; - $mapHtml .= sprintf ' points.push(%s);'."\n", - JSON->new->encode($point->getMapInfo), - ; + my $buffer = JSON->new->encode( $point->getMapInfo ); + + $mapHtml .= sprintf ' points.push(%s);'."\n", $buffer; push @{$var->{ mapPoints }}, $point->getTemplateVars; } @@ -432,11 +439,11 @@ ENDHTML } # Script to control addPoint and setPoint buttons - $mapHtml .= <<'ENDHTML'; + $mapHtml .= sprintf <<'ENDHTML', $self->getUrl; if ( document.getElementById( "setCenter_" + mapId ) ) { var button = document.getElementById( "setCenter_" + mapId ); GEvent.addDomListener( button, "click", function () { - WebGUI.Map.setCenter( map ); + WebGUI.Map.setCenter( map, '%s' ); } ); } if ( document.getElementById( "addPoint_" + mapId ) ) { diff --git a/lib/WebGUI/Asset/Wobject/Search.pm b/lib/WebGUI/Asset/Wobject/Search.pm index fdd712229..4846e3c4f 100644 --- a/lib/WebGUI/Asset/Wobject/Search.pm +++ b/lib/WebGUI/Asset/Wobject/Search.pm @@ -213,30 +213,31 @@ sub view { ); my @results = (); - foreach my $data (@{$p->getPageData}) { - next unless ( + ENTRY: foreach my $data (@{$p->getPageData}) { + next ENTRY unless ( $user->userId eq $data->{ownerUserId} || $user->isInGroup($data->{groupIdView}) || $user->isInGroup($data->{groupIdEdit}) ); my $asset = WebGUI::Asset->new($session, $data->{assetId}, $data->{className}); - if (defined $asset) { - my $properties = $asset->get; - if ( $self->get("useContainers") && $asset->getContainer->canView ) { - $properties->{url} = $asset->isa('WebGUI::Asset::Post::Thread') ? $asset->getCSLinkUrl() - : $asset->getContainer->get("url"); - } - #Add highlighting - $properties->{'title' } = $hl->highlight($properties->{title} || ''); - $properties->{'title_nohighlight' } = $properties->{title}; - my $synopsis = $data->{'synopsis'} || ''; - WebGUI::Macro::process($self->session, \$synopsis); - $properties->{'synopsis' } = $hl->highlight($synopsis); - $properties->{'synopsis_nohighlight'} = $synopsis; - push(@results, $properties); - $var{results_found} = 1; - } + next ENTRY unless defined $asset; + my $properties = $asset->get; + ##Overlay the asset properties with the original data to handle sub-entries for assets + $properties = { %{ $properties }, %{ $data} }; + if ( $self->get("useContainers") && $asset->getContainer->canView ) { + $properties->{url} = $asset->isa('WebGUI::Asset::Post::Thread') ? $asset->getCSLinkUrl() + : $asset->getContainer->get("url"); + } + #Add highlighting + $properties->{'title' } = $hl->highlight($properties->{title} || ''); + $properties->{'title_nohighlight' } = $properties->{title}; + my $synopsis = $properties->{'synopsis'} || ''; + WebGUI::Macro::process($self->session, \$synopsis); + $properties->{'synopsis' } = $hl->highlight($synopsis); + $properties->{'synopsis_nohighlight'} = $synopsis; + push(@results, $properties); + $var{results_found} = 1; } $var{result_set} = \@results; diff --git a/lib/WebGUI/Asset/Wobject/Thingy.pm b/lib/WebGUI/Asset/Wobject/Thingy.pm index 5dcfdb795..8664621cd 100644 --- a/lib/WebGUI/Asset/Wobject/Thingy.pm +++ b/lib/WebGUI/Asset/Wobject/Thingy.pm @@ -279,6 +279,24 @@ sub definition { } +#------------------------------------------------------------------- + +=head2 deleteThingIndex ( $thingId ) + +Remove the entry about this Thing from the database, and for any rows for it that are indexed as well. + +=head3 $thingId + +The GUID of the Thing, used to pick out this record in the database. + +=cut + +sub deleteThingIndex { + my $self = shift; + my $thingId = shift; + $self->session->db->write(q|delete from assetIndex where assetId=? and subId like CONCAT(?,'%')|,[$self->getId, $thingId]); +} + #------------------------------------------------------------------- =head2 duplicate ( ) @@ -367,6 +385,8 @@ sub duplicateThing { $self->addField($field,0); } + $thingProperties->{thingId} = $newThingId; + $self->indexThing($thingProperties); return $newThingId; } @@ -418,6 +438,7 @@ sub deleteField { $db->write("ALTER TABLE ".$db->dbh->quote_identifier("Thingy_".$thingId)." DROP " .$db->dbh->quote_identifier("field_".$fieldId)); } + $self->reindexThings; $error->info("Deleted field: $fieldId in thing: $thingId."); return undef; } @@ -468,6 +489,7 @@ sub copyThingData { } ##Update the copy $self->setCollateral("Thingy_".$thingId, "thingDataId", $origCollateral, 0, 0); + $self->indexThingData($thingId, $origCollateral); return undef; } @@ -522,11 +544,30 @@ sub deleteThingData { $storage->delete; } + $self->deleteThingDataIndex($thingDataId); return undef; } #------------------------------------------------------------------- +=head2 deleteThingDataIndex ( $thingDataId ) + +Remove the entry about this Thing from the database, and for any rows for it that are indexed as well. + +=head3 $thingDataId + +The GUID of the thingData to remove, used to pick out this record in the database. + +=cut + +sub deleteThingDataIndex { + my $self = shift; + my $thingDataId = shift; + $self->session->db->write(q|delete from assetIndex where assetId=? and subId like CONCAT('%-',?)|,[$self->getId, $thingDataId]); +} + +#------------------------------------------------------------------- + =head2 deleteThing ( thingId ) Deletes a Thing and its fields from Collateral and drops the things table. @@ -549,6 +590,7 @@ sub deleteThing { $session->db->write("drop table if exists ".$session->db->dbh->quote_identifier("Thingy_".$thingId)); $error->info("Deleted thing: $thingId."); + $self->deleteThingIndex($thingId); return undef; } @@ -636,6 +678,7 @@ sub editThingDataSave { return ('', \@errors); } $newThingDataId = $self->setCollateral("Thingy_".$thingId,"thingDataId",\%thingData,0,0); + $self->indexThingData($thingId, \%thingData); # trigger workflow if($thingDataId eq "new"){ @@ -697,6 +740,7 @@ sub field_isa { my $session = $self->session; my $fieldType = shift; my $isa = shift; + $fieldType = ucfirst $fieldType; my $control = eval { WebGUI::Pluggable::instanciate("WebGUI::Form::".$fieldType, "new", [ $session, () ]) }; return ($control && $control->isa($isa)); } @@ -1286,6 +1330,7 @@ sub getViewThingVars { ); push(@viewScreenTitleFields,$value) if ($field{viewScreenTitle}); push(@field_loop, { map {("field_".$_ => $fieldProperties{$_})} keys(%fieldProperties) }); + $var->{ $field{label} } = $value; } $var->{viewScreenTitle} = join(" ",@viewScreenTitleFields); $var->{field_loop} = \@field_loop; @@ -1398,6 +1443,7 @@ sub importAssetCollateralData { # add new thing $self->addThing($thing,1); } + $self->indexThing($thing); } # delete deleted things my $thingsInDatabase = $self->getThings; @@ -1439,6 +1485,126 @@ sub importAssetCollateralData { } +#------------------------------------------------------------------- + +=head2 indexContent ( ) + +Extend the base class to handle reindexing every Thing, and every row in every Thing. We have +to do a complete rework because the URL may have changed, and that affects everything that has +been inserted into the AssetIndex. + +=cut + +sub indexContent { + my ($self) = @_; + my $session = $self->session; + $self->SUPER::indexContent(); + $self->reindexThings; +} + + +#------------------------------------------------------------------- + +=head2 indexThing ( $thing ) + +Add an entry about this Thing into the AssetIndex so it can be found for searches. + +=head3 $thing + +A hashref of Thing properties, as returned by getThing + +=cut + +sub indexThing { + my ($self, $thing) = @_; + return unless $thing; + my $index = WebGUI::Search::Index->new($self); + $index->addRecord( + url => $self->getUrl($self->getThingUrl($thing)), + groupIdView => $thing->{groupIdView}, + title => $thing->{label}, + subId => $thing->{thingId}, + keywords => join(' ', @{$thing}{qw/label editScreenTitle editInstructions searchScreenTitle searchDescription/}), + ); + ##Easy update of all thingData fields for this thing. This is in lieu of deleting all records + ##And rebuilding them all. + $self->session->db->write(q|update assetIndex set title=?, groupIdView=? where assetId=? and subId like CONCAT(?, '%')|, [$thing->{label}, $thing->{groupIdView}, $self->getId, $thing->{thingId}]); +} + + +#------------------------------------------------------------------- + +=head2 indexThingData ( $thingId, $thingData ) + +Add an entry about a row from this Thing into the AssetIndex so it can be found for searches. + +=head3 $thingId + +The GUID for a Thing. + +=head3 $thingData + +A hashref of ThingData properties + +=cut + +sub indexThingData { + my ($self, $thingId, $thingData) = @_; + my $session = $self->session; + return unless $thingId; + my $thing = $self->getThing($thingId); + my $index = WebGUI::Search::Index->new($self); + my $keywords; + ##Get the Thingy's fields + my $fields = $session->db->read('select * from Thingy_fields where assetId = ? and thingId = ?', + [$self->getId, $thingId]); + ##Walk the fields + my @viewScreenTitleFields = (); + FIELD: while (my %field = $fields->hash) { + my $fieldName = 'field_'.$field{fieldId}; + $field{value} = $thingData->{$fieldName} || $field{defaultValue}; + my $subkeywords = ''; + my $value = ''; + if ($self->field_isa($field{fieldType}, 'WebGUI::Form::File')) { + my $storage = WebGUI::Storage->get($session, $field{value}); + if ($storage) { + foreach my $file (@{$storage->getFiles()}) { + $subkeywords = $index->getKeywordsForFile($storage->getPath($file)); + } + } + } + else { + $value = $self->getFieldValue($field{value}, \%field); + ##If it's a file type, then get keywords from the file. + ##Accumulate keywords + $subkeywords = $value; + } + if ($value && $field{viewScreenTitle}) { + push @viewScreenTitleFields, $value; + } + ##We don't index date fields, since they're unix epochs and they'd be different for everyone based on timezone. + next FIELD if $field{fieldType} eq 'date' + || $field{fieldType} eq 'datetime' + || $field{fieldType} eq 'time'; + ##Don't show what shouldn't be shown + next FIELD unless $field{displayInSearch}; + $keywords = join ' ', $keywords, $subkeywords; + } + return unless $keywords; ##No sense indexing nothing; + my $title = join('', @viewScreenTitleFields) + || $thing->{label} + || $self->getTitle; + $index->addRecord( + assetId => $self->getId, + url => $self->getUrl('func=viewThingData;thingId='. $thing->{thingId} . ';thingDataId='. $thingData->{thingDataId}), + groupIdView => $thing->{groupIdView}, + title => $title, + subId => $thing->{thingId} . '-' . $thingData->{thingDataId}, + keywords => $keywords, + ); +} + + #------------------------------------------------------------------- =head2 prepareView ( ) @@ -1487,6 +1653,30 @@ sub purge { return $self->SUPER::purge; } +#------------------------------------------------------------------- + +=head2 reindexThings ( ) + +Reindex every Thing, and every row in every Thing. + +=cut + +sub reindexThings { + my ($self) = @_; + my $session = $self->session; + my $things = $self->getThings; + THING: while (my $thing = $things->hashRef) { + $self->deleteThingIndex($thing->{thingId}); + $self->indexThing($thing); + my $sth = $session->db->read('select * from '. $session->db->dbh->quote_identifier('Thingy_'.$thing->{thingId})); + while (my $thingData = $sth->hashRef) { + $self->indexThingData($thing->{thingId}, $thingData); + } + $sth->finish; + } +} + + #------------------------------------------------------------------- =head2 triggerWorkflow ( workflowId, thingId, thingDataId ) @@ -2222,44 +2412,44 @@ sub www_editThingSave { my $self = shift; return $self->session->privilege->insufficient() unless $self->canEdit; - my $form = $self->session->form; - my ($thingId, $fields); - $thingId = $self->session->form->process("thingId"); - - $fields = $self->getFields($thingId); + my $form = $self->session->form; + my $thingId = $self->session->form->process("thingId"); + my $fields = $self->getFields($thingId); + my $thing = { + thingId => $thingId, + label => $form->process("label"), + editScreenTitle => $form->process("editScreenTitle"), + editInstructions => $form->process("editInstructions"), + groupIdAdd => $form->process("groupIdAdd"), + groupIdEdit => $form->process("groupIdEdit"), + saveButtonLabel => $form->process("saveButtonLabel"), + afterSave => $form->process("afterSave"), + editTemplateId => $form->process("editTemplateId") || 1, + onAddWorkflowId => $form->process("onAddWorkflowId"), + onEditWorkflowId => $form->process("onEditWorkflowId"), + onDeleteWorkflowId => $form->process("onDeleteWorkflowId"), + groupIdView => $form->process("groupIdView"), + viewTemplateId => $form->process("viewTemplateId") || 1, + defaultView => $form->process("defaultView"), + searchScreenTitle => $form->process("searchScreenTitle"), + searchDescription => $form->process("searchDescription"), + groupIdSearch => $form->process("groupIdSearch"), + groupIdImport => $form->process("groupIdImport"), + groupIdExport => $form->process("groupIdExport"), + searchTemplateId => $form->process("searchTemplateId") || 1, + thingsPerPage => $form->process("thingsPerPage") || 25, + sortBy => $form->process("sortBy") || '', + exportMetaData => $form->process("exportMetaData") || '', + maxEntriesPerUser => $form->process("maxEntriesPerUser") || '', + }; + $self->setCollateral("Thingy_things", "thingId", $thing, 0, 1); + if($fields->rows < 1){ $self->session->log->warn("Thing failed to create because it had no fields"); my $i18n = WebGUI::International->new($self->session, "Asset_Thingy"); return $self->www_editThing($i18n->get("thing must have fields")); } - $self->setCollateral("Thingy_things","thingId",{ - thingId=>$thingId, - label=>$form->process("label"), - editScreenTitle=>$form->process("editScreenTitle"), - editInstructions=>$form->process("editInstructions"), - groupIdAdd=>$form->process("groupIdAdd"), - groupIdEdit=>$form->process("groupIdEdit"), - saveButtonLabel=>$form->process("saveButtonLabel"), - afterSave=>$form->process("afterSave"), - editTemplateId=>$form->process("editTemplateId") || 1, - onAddWorkflowId=>$form->process("onAddWorkflowId"), - onEditWorkflowId=>$form->process("onEditWorkflowId"), - onDeleteWorkflowId=>$form->process("onDeleteWorkflowId"), - groupIdView=>$form->process("groupIdView"), - viewTemplateId=>$form->process("viewTemplateId") || 1, - defaultView=>$form->process("defaultView"), - searchScreenTitle=>$form->process("searchScreenTitle"), - searchDescription=>$form->process("searchDescription"), - groupIdSearch=>$form->process("groupIdSearch"), - groupIdImport=>$form->process("groupIdImport"), - groupIdExport=>$form->process("groupIdExport"), - searchTemplateId=>$form->process("searchTemplateId") || 1, - thingsPerPage=>$form->process("thingsPerPage") || 25, - sortBy=>$form->process("sortBy") || '', - exportMetaData=>$form->process("exportMetaData") || '', - maxEntriesPerUser=>$form->process("maxEntriesPerUser") || '', - },0,1); while (my $field = $fields->hashRef) { my $display = $self->session->form->process("display_".$field->{fieldId}) || 0; @@ -2269,6 +2459,7 @@ sub www_editThingSave { $self->session->db->write("update Thingy_fields set display = ?, viewScreenTitle = ?, displayinSearch = ?, searchIn = ? where fieldId = ? and thingId = ?",[$display, $viewScreenTitle, $displayInSearch, $searchIn, $field->{fieldId}, $thingId]); } + $self->indexThing($thing); return $self->www_manage; } #------------------------------------------------------------------- @@ -3135,13 +3326,7 @@ sub www_manage { 'thing_searchUrl' => $session->url->append($url, 'func=search;thingId='.$thing->{thingId}), ); # set the url for the view icon to the things default view - my $viewParams; - if ($thing->{defaultView} eq "addThing") { - $viewParams = 'func=editThingData;thingId='.$thing->{thingId}.';thingDataId=new'; - } - else{ - $viewParams = 'func=search;thingId='.$thing->{thingId}; - } + my $viewParams = $self->getThingUrl($thing); $templateVars{'thing_viewIcon'} = $session->icon->view($viewParams); push (@things_loop, \%templateVars); } @@ -3602,6 +3787,11 @@ The unique id of a thing. The unique id of a row of thing data. +=head3 templateId + +Optional. The unique id or url of the template to be used. When specified, the style template is not used. +If omitted, the thing data view template and style will be used. + =cut sub www_viewThingData { @@ -3610,7 +3800,7 @@ sub www_viewThingData { my $session = $self->session; my $thingId = shift || $session->form->process('thingId'); my $thingDataId = shift || $session->form->process('thingDataId'); - + my $templateId = shift || $session->form->process('templateId'); my $var = $self->get; my $url = $self->getUrl; my $i18n = WebGUI::International->new($self->session, "Asset_Thingy"); @@ -3640,9 +3830,19 @@ sub www_viewThingData { $self->getViewThingVars($thingId,$thingDataId,$var); $self->appendThingsVars($var, $thingId); + + my $template; + if( $templateId ) + { + $template = WebGUI::Asset::Template->newByUrl( $session, $templateId ) || + WebGUI::Asset::Template->newByDynamicClass( $session, $templateId ); + } + return $self->processStyle( - $self->processTemplate($var,$thingProperties->{viewTemplateId}) - ); + $self->processTemplate($var,$thingProperties->{viewTemplateId}) + ) if !$template; + + return $self->processTemplate($var,$template->getId,$template); } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Help/Asset_Map.pm b/lib/WebGUI/Help/Asset_Map.pm new file mode 100644 index 000000000..8e0cea759 --- /dev/null +++ b/lib/WebGUI/Help/Asset_Map.pm @@ -0,0 +1,59 @@ +package WebGUI::Help::Asset_Map; +use strict; + +our $HELP = { + + 'view template' => { + title => 'view template', + body => '', + isa => [ + { namespace => 'Asset_Template', + tag => 'template variables' + }, + { namespace => 'Asset_Map', + tag => 'map asset template variables' + }, + ], + fields => [], + variables => [ + { name => 'canAddPoint', }, + { name => 'canEdit', }, + { name => 'mapPoints', required => 1, }, + { name => 'button_addPoint', required => 1, }, + { name => 'button_setCenter', required => 1, }, + { name => 'button_setCenter', selectPoint => 1, }, + ], + related => [] + }, + + 'map asset template variables' => { + private => 1, + title => 'map asset template variables', + body => '', + isa => [ + { namespace => 'Asset', + tag => 'asset template asset variables' + }, + ], + fields => [], + variables => [ + { name => 'groupIdAddPoint', }, + { name => 'mapApiKey', }, + { name => 'mapHeight', }, + { name => 'mapWidth', }, + { name => 'startLatitude', }, + { name => 'startLongitude', }, + { name => 'startZoom', }, + { name => 'templateIdEditPoint', }, + { name => 'templateIdView', }, + { name => 'templateIdViewPoint', }, + { name => 'workflowIdPoint', }, + { name => 'canAddPoint', }, + { name => 'canEdit', }, + ], + related => [] + }, + +}; + +1; diff --git a/lib/WebGUI/Help/Asset_MapPoint.pm b/lib/WebGUI/Help/Asset_MapPoint.pm index 3bf436463..d0960cc3c 100644 --- a/lib/WebGUI/Help/Asset_MapPoint.pm +++ b/lib/WebGUI/Help/Asset_MapPoint.pm @@ -10,6 +10,9 @@ our $HELP = { { namespace => 'Asset_Template', tag => 'template variables' }, + { namespace => 'Asset_MapPoint', + tag => 'map point asset template variables' + }, ], fields => [], variables => [ @@ -32,6 +35,8 @@ our $HELP = { { name => 'form_fax', }, { name => 'form_email', }, { name => 'user defined variables', }, + { name => 'form_isHidden', }, + { name => 'form_isGeocoded', }, ], related => [] }, diff --git a/lib/WebGUI/Help/Asset_Thingy.pm b/lib/WebGUI/Help/Asset_Thingy.pm index 25b131d38..457ec5863 100644 --- a/lib/WebGUI/Help/Asset_Thingy.pm +++ b/lib/WebGUI/Help/Asset_Thingy.pm @@ -152,6 +152,12 @@ our $HELP = { { 'name' => 'field_pretext' }, ], }, + { + 'name' => 'variables by label', + } + { + 'name' => 'fields', + } ], related => [ { tag => 'edit thing template', diff --git a/lib/WebGUI/Macro/RenderThingData.pm b/lib/WebGUI/Macro/RenderThingData.pm new file mode 100644 index 000000000..197291276 --- /dev/null +++ b/lib/WebGUI/Macro/RenderThingData.pm @@ -0,0 +1,66 @@ +package WebGUI::Macro::RenderThingData; + +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2011 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------- +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------- + +use strict; +use WebGUI::Group; +use WebGUI::Asset::Template; +use WebGUI::Asset::Wobject::Thingy; + +=head1 NAME + +Package WebGUI::Macro::RenderThingData + +=head1 DESCRIPTION + +Macro that allows users to render thing data. + +=head2 process ( thingURL, templateHint ) + +=head3 thingHint + +The URL from which to pull the thingId and thingDataId + +=head3 templateHint + +Optional. Specifies the templateId or template url to use. If omitted, the default thingy view template will be used. + +=cut + + +#------------------------------------------------------------------- +sub process { + my ($session, $thingDataUrl, $templateHint ) = @_; + + my $uri = URI->new( $thingDataUrl ); + + my $urlHash = { $uri->query_form }; + my $thingId = $urlHash->{'thingId'}; + my $thingDataId = $urlHash->{'thingDataId'}; + + my $thing = WebGUI::Asset::Wobject::Thingy->newByUrl( $session, $uri->path ); + + # TODO: i18n + return ( "Bad URL: " . $thingDataUrl ) if !$thing || !$thingId || !$thingDataId; + + # Render + my $output = $thing->www_viewThingData( $thingId, $thingDataId, $templateHint ); + + # FIX: Temporary solution (broken map due to template rendering