Merge commit 'v7.10.15' into 8
Conflicts: docs/gotcha.txt docs/previousVersion.sql docs/templates.txt lib/WebGUI.pm lib/WebGUI/Asset.pm lib/WebGUI/Asset/Event.pm lib/WebGUI/Asset/File.pm lib/WebGUI/Asset/MapPoint.pm lib/WebGUI/Asset/RichEdit.pm lib/WebGUI/Asset/Sku/Product.pm lib/WebGUI/Asset/Snippet.pm lib/WebGUI/Asset/Story.pm lib/WebGUI/Asset/Template.pm lib/WebGUI/Asset/Template/TemplateToolkit.pm lib/WebGUI/Asset/Wobject/Calendar.pm lib/WebGUI/Asset/Wobject/Carousel.pm lib/WebGUI/Asset/Wobject/Collaboration.pm lib/WebGUI/Asset/Wobject/Dashboard.pm lib/WebGUI/Asset/Wobject/DataForm.pm lib/WebGUI/Asset/Wobject/Folder.pm lib/WebGUI/Asset/Wobject/Map.pm lib/WebGUI/Asset/Wobject/Search.pm lib/WebGUI/Asset/Wobject/Shelf.pm lib/WebGUI/Asset/Wobject/StockData.pm lib/WebGUI/Asset/Wobject/StoryTopic.pm lib/WebGUI/Asset/Wobject/SyndicatedContent.pm lib/WebGUI/Asset/Wobject/Thingy.pm lib/WebGUI/Asset/Wobject/WeatherData.pm lib/WebGUI/AssetClipboard.pm lib/WebGUI/AssetCollateral/DataForm/Entry.pm lib/WebGUI/AssetExportHtml.pm lib/WebGUI/AssetLineage.pm lib/WebGUI/AssetMetaData.pm lib/WebGUI/AssetTrash.pm lib/WebGUI/AssetVersioning.pm lib/WebGUI/Auth.pm lib/WebGUI/Cache/CHI.pm lib/WebGUI/Content/AssetManager.pm lib/WebGUI/Fork/ProgressBar.pm lib/WebGUI/Form/JsonTable.pm lib/WebGUI/Form/TimeField.pm lib/WebGUI/Form/Zipcode.pm lib/WebGUI/Group.pm lib/WebGUI/International.pm lib/WebGUI/Macro/AssetProxy.pm lib/WebGUI/Macro/FileUrl.pm lib/WebGUI/Operation/SSO.pm lib/WebGUI/Operation/User.pm lib/WebGUI/Role/Asset/Subscribable.pm lib/WebGUI/Shop/Cart.pm lib/WebGUI/Shop/Transaction.pm lib/WebGUI/Shop/TransactionItem.pm lib/WebGUI/Test.pm lib/WebGUI/URL/Content.pm lib/WebGUI/URL/Uploads.pm lib/WebGUI/User.pm lib/WebGUI/Workflow/Activity/ExtendCalendarRecurrences.pm lib/WebGUI/Workflow/Activity/SendNewsletters.pm lib/WebGUI/i18n/English/Asset.pm lib/WebGUI/i18n/English/WebGUI.pm sbin/installClass.pl sbin/rebuildLineage.pl sbin/search.pl sbin/testEnvironment.pl t/Asset/Asset.t t/Asset/AssetClipboard.t t/Asset/AssetLineage.t t/Asset/AssetMetaData.t t/Asset/Event.t t/Asset/File.t t/Asset/File/Image.t t/Asset/Post/notification.t t/Asset/Sku.t t/Asset/Story.t t/Asset/Template.t t/Asset/Wobject/Collaboration/templateVariables.t t/Asset/Wobject/Collaboration/unarchiveAll.t t/Asset/Wobject/Shelf.t t/Auth.t t/Macro/EditableToggle.t t/Macro/FilePump.t t/Shop/Cart.t t/Shop/Transaction.t t/Storage.t t/User.t t/Workflow.t
This commit is contained in:
commit
277faae8a1
783 changed files with 32041 additions and 25495 deletions
|
|
@ -27,6 +27,7 @@ use WebGUI::Storage;
|
|||
use Test::Deep::NoTest qw(eq_deeply);
|
||||
use DateTime::Event::ICal;
|
||||
use DateTime::Set;
|
||||
use Data::ICal::Entry::Event;
|
||||
|
||||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
|
|
@ -212,6 +213,54 @@ override addRevision => sub {
|
|||
return $newRev;
|
||||
};
|
||||
|
||||
####################################################################
|
||||
|
||||
=head2 add_to_calendar ($iCal)
|
||||
|
||||
Build a Data::ICal::Entry::Event object that contains the information for this
|
||||
event and add it to the Data::ICal calendar
|
||||
|
||||
=head3 $iCal
|
||||
|
||||
A Data::ICal object, representing the top-level calendar instance.
|
||||
|
||||
=cut
|
||||
|
||||
sub add_to_calendar {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $calendar = shift;
|
||||
my $event = Data::ICal::Entry::Event->new();
|
||||
$event->add_properties(
|
||||
'last-modified' => WebGUI::DateTime->new($session, $event->get("revisionDate"))->toIcal,
|
||||
created => WebGUI::DateTime->new($session, $event->get("creationDate"))->toIcal,
|
||||
sequence => $self->get('iCalSequenceNumber'),
|
||||
summary => $self->get('title'),
|
||||
description => $self->get('description'),
|
||||
location => $self->get('location'),
|
||||
uid => $self->get('feedUid')
|
||||
? $self->get('feedUid')
|
||||
: $self->get('assetId') . '@'. $session->config->get("sitename")->[0],
|
||||
);
|
||||
##WebGUI Specific fields
|
||||
foreach my $prop (qw/groupIdView groupIdEdit url menuTitle timeZone/) {
|
||||
$event->add_property( 'x-webgui-'.lc($prop) => $self->get($prop));
|
||||
}
|
||||
my $eventStart = $self->getIcalStart;
|
||||
my $start_parameters = {};
|
||||
if (! $eventStart =~ /T/) {
|
||||
$start_parameters->{VALUE} = 'DATE';
|
||||
}
|
||||
$event->add_property(dtstart => [ $eventStart, $start_parameters ]);
|
||||
my $eventEnd = $self->getIcalEnd;
|
||||
my $end_parameters = {};
|
||||
if (! $eventEnd =~ /T/) {
|
||||
$end_parameters->{VALUE} = 'DATE';
|
||||
}
|
||||
$event->add_property(dtend => [ $eventEnd, $end_parameters ]);
|
||||
$calendar->add_entry($event);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
my %dayNamesToICal = (
|
||||
|
|
@ -411,6 +460,14 @@ sub duplicate {
|
|||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
my $newStorage = $self->getStorageLocation->copy;
|
||||
$newAsset->update({storageId=>$newStorage->getId});
|
||||
my $links = $self->getRelatedLinks();
|
||||
my $id = $self->session->id;
|
||||
foreach my $link (@{ $links }) {
|
||||
$link->{new_event} = 1;
|
||||
$link->{eventlinkId} = $id->generate;
|
||||
$link->{linkurl} = $link->{linkURL};
|
||||
}
|
||||
$newAsset->setRelatedLinks($links);
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
|
|
@ -434,13 +491,12 @@ sub generateRecurrence {
|
|||
WHERE recurId = ? AND startDate = ?
|
||||
};
|
||||
my $db = $self->session->db;
|
||||
unless ($db->quickScalar($sql, [$self->recurId, $sdb])) {
|
||||
my $child = $self->get;
|
||||
$child->{startDate} = $sdb;
|
||||
$child->{endDate} = $edb;
|
||||
$self->getParent->addChild(
|
||||
$child, undef, undef, { skipAutoCommitWorkflows => 1 }
|
||||
);
|
||||
unless ($db->quickScalar($sql, [$self->get('recurId'), $sdb])) {
|
||||
my $child = $self->duplicate({skipAutoCommitWorkflows => 1});
|
||||
$child->update({
|
||||
startDate => $sdb,
|
||||
endDate => $edb,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1374,9 +1430,18 @@ override processEditForm => sub {
|
|||
|
||||
### Verify the form was filled out correctly...
|
||||
my @errors;
|
||||
# If the start date is after the end date
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Event');
|
||||
if ($self->startDate gt $self->endDate) {
|
||||
|
||||
# Verify we got valid dates
|
||||
if ( !eval{ $self->getDateTimeStart; 1 } ) {
|
||||
push @errors, $i18n->get('invalid start date');
|
||||
}
|
||||
if ( !eval{ $self->getDateTimeEnd; 1 } ) {
|
||||
push @errors, $i18n->get('invalid end date');
|
||||
}
|
||||
|
||||
# If the start date is after the end date
|
||||
if ($self->get("startDate") gt $self->get("endDate")) {
|
||||
push @errors, $i18n->get("The event end date must be after the event start date.");
|
||||
}
|
||||
|
||||
|
|
@ -1605,13 +1670,17 @@ Extent the method from the super class to delete all storage locations.
|
|||
|
||||
override purge => sub {
|
||||
my $self = shift;
|
||||
my $sth = $self->session->db->read("select storageId from Event where assetId=?",[$self->getId]);
|
||||
while (my ($storageId) = $sth->array) {
|
||||
my $storage = WebGUI::Storage->get($self->session,$storageId);
|
||||
my $id = $self->getId;
|
||||
my $session = $self->session;
|
||||
my @storageIds = $session->db->buildArray("select storageId from Event where assetId=?",[$id]);
|
||||
my $success = $self->SUPER::purge;
|
||||
return 0 unless $success;
|
||||
foreach my $storageId (@storageIds) {
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->delete if defined $storage;
|
||||
}
|
||||
$sth->finish;
|
||||
return super();
|
||||
$session->db->write('delete from Event_relatedlink where assetId=?',[$id]);
|
||||
return 1;
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -2235,20 +2304,24 @@ sub www_edit {
|
|||
# End
|
||||
$var->{"formRecurEnd"}
|
||||
= q|
|
||||
<div><input type="radio" name="recurEndType" id="recurEndType_none" value="none" |.(!$recur->{endDate} && !$recur->{endAfter} ? 'checked="checked"' : '').q|/>
|
||||
<label for="recurEndType_none">|. $i18n->get('No end'). q|</label><br />
|
||||
<div><input type="radio" name="recurEndType" id="recurEndType_none" value="none" |.(!$recur->{endDate} && !$recur->{endAfter} ? 'checked="checked"' : '').q| onclick="toggleRecurEnd()"/>
|
||||
<label for="recurEndType_none">|. $i18n->get('No end'). q|</label>
|
||||
|
||||
<input type="radio" name="recurEndType" id="recurEndType_date" value="date" |.($recur->{endDate} ? 'checked="checked"' : '' ).q| />
|
||||
<label for="recurEndType_date">|. $i18n->get('By date'). q| </label>|
|
||||
<input type="radio" name="recurEndType" id="recurEndType_date" value="date" |.($recur->{endDate} ? 'checked="checked"' : '' ).q| onclick="toggleRecurEnd()"/>
|
||||
<label for="recurEndType_date">|. $i18n->get('By date'). q| </label>
|
||||
<div id="recurEndPattern_date"> |
|
||||
. WebGUI::Form::date($session,{ name => "recurEndDate", value => $recur->{endDate}, defaultValue => $recur->{endDate} })
|
||||
. q|
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<input type="radio" name="recurEndType" id="recurEndType_after" value="after" |.($recur->{endAfter} ? 'checked="checked"' : '' ).q| />
|
||||
<input type="radio" name="recurEndType" id="recurEndType_after" value="after" |.($recur->{endAfter} ? 'checked="checked"' : '' ).q| onclick="toggleRecurEnd()"/>
|
||||
<label for="recurEndType_after">|. $i18n->get('After'). q| </label>
|
||||
<div id="recurEndPattern_after">
|
||||
<input type="text" size="3" name="recurEndAfter" value="|.$recur->{endAfter}.q|" />
|
||||
|. $i18n->get('occurences'). q|.
|
||||
</div>
|
||||
</div>
|
||||
|;
|
||||
|
||||
# Include
|
||||
|
|
@ -2310,7 +2383,19 @@ sub www_edit {
|
|||
document.getElementById("recurPattern_yearly").style.display = "block";
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.onAvailable("recurPattern",function(e) { toggleRecur(); });
|
||||
|
||||
function toggleRecurEnd() {
|
||||
document.getElementById("recurEndPattern_date").style.display = "none";
|
||||
document.getElementById("recurEndPattern_after").style.display = "none";
|
||||
|
||||
if (document.getElementById("recurEndType_date").checked) {
|
||||
document.getElementById("recurEndPattern_date").style.display = "block";
|
||||
}
|
||||
else if (document.getElementById("recurEndType_after").checked) {
|
||||
document.getElementById("recurEndPattern_after").style.display = "block";
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.onAvailable("recurPattern",function(e) { toggleRecur(); toggleRecurEnd(); });
|
||||
</script>
|
||||
ENDJS
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,24 @@ sub setPrivileges {
|
|||
);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 commit ( )
|
||||
|
||||
Override commit to remove all privileges for previous revisions' storage
|
||||
locations
|
||||
|
||||
=cut
|
||||
|
||||
sub commit {
|
||||
my ( $self, @args ) = @_;
|
||||
|
||||
for my $rev ( grep { $_->get("revisionDate") < $self->get("revisionDate") } @{$self->getRevisions} ) {
|
||||
$rev->getStorageLocation->trash;
|
||||
}
|
||||
|
||||
return $self->SUPER::commit( @args );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -401,7 +419,6 @@ override processEditForm => sub {
|
|||
return undef;
|
||||
};
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge
|
||||
|
|
@ -450,6 +467,20 @@ override purgeRevision => sub {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 restore ( )
|
||||
|
||||
Override trash restore to restore storage location
|
||||
|
||||
=cut
|
||||
|
||||
sub restore {
|
||||
my ( $self, @args ) = @_;
|
||||
$self->setPrivileges;
|
||||
return $self->SUPER::restore( @args );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 setFile ( [pathtofile] )
|
||||
|
||||
Tells the asset to do all the postprocessing on the file (setting privs, thubnails, or whatever).
|
||||
|
|
@ -535,6 +566,23 @@ sub setStorageLocation {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 trash ( )
|
||||
|
||||
Override to put the attached file in the trash too
|
||||
|
||||
=cut
|
||||
|
||||
sub trash {
|
||||
my ( $self, @args ) = @_;
|
||||
my $return = $self->SUPER::trash( @args );
|
||||
|
||||
$self->getStorageLocation->trash;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 updatePropertiesFromStorage ( )
|
||||
|
||||
Updates the asset properties from the file tracked by this asset. Should be
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ package WebGUI::Asset::MapPoint;
|
|||
use strict;
|
||||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
use Geo::Coder::Googlev3;
|
||||
|
||||
extends 'WebGUI::Asset';
|
||||
define assetName => ['assetName', 'Asset_MapPoint'];
|
||||
define icon => 'mappoint.png';
|
||||
|
|
@ -121,6 +123,12 @@ property userDefined5 => (
|
|||
fieldType => "hidden",
|
||||
noFormPost => 1,
|
||||
);
|
||||
property isGeocoded => (
|
||||
fieldType => "yesNo",
|
||||
tab => "properties",
|
||||
label => ["isGeocoded label",'Asset_MapPoint'],
|
||||
hoverHelp => ["isGeocoded description",'Asset_MapPoint'],
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -184,6 +192,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
|
||||
|
||||
|
|
@ -199,7 +208,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->$key;
|
||||
}
|
||||
|
|
@ -246,6 +255,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, {
|
||||
|
|
@ -293,8 +311,25 @@ sub getTemplateVarsEditForm {
|
|||
name => "synopsis",
|
||||
value => $self->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" }
|
||||
= '<input type="file" name="storageIdPhoto" />';
|
||||
|
|
@ -309,6 +344,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
|
||||
|
|
@ -336,6 +400,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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -235,12 +235,16 @@ Returns a boolean indicating whether the user can view the current post.
|
|||
|
||||
sub canView {
|
||||
my $self = shift;
|
||||
if (($self->status eq "approved" || $self->status eq "archived") && $self->getThread->getParent->canView) {
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
$self->session->log->info( "$userId " . $self->status );
|
||||
if (($self->status eq "approved" || $self->status eq "archived") && $self->getThread->getParent->canView( $userId )) {
|
||||
$self->session->log->info( "CAN VIEW" );
|
||||
return 1;
|
||||
} elsif ($self->canEdit) {
|
||||
} elsif ($self->canEdit( $userId )) {
|
||||
$self->session->log->info( "CAN EDIT" );
|
||||
return 1;
|
||||
} else {
|
||||
$self->getThread->getParent->canEdit;
|
||||
return $self->getThread->getParent->canEdit( $userId );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,6 +366,26 @@ sub disqualifyAsLastPost {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate ( )
|
||||
|
||||
Extend the base method to handle duplicate storage locations and groups.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $copy = $self->SUPER::duplicate(@_);
|
||||
if ($self->get('storageId')) {
|
||||
my $storage = $self->getStorageLocation;
|
||||
my $copied_storage = $storage->copy;
|
||||
$copy->update({storageId => $copied_storage->getId});
|
||||
}
|
||||
return $copy;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 DESTROY
|
||||
|
||||
Extend the base method to delete the locally cached thread object.
|
||||
|
|
|
|||
|
|
@ -247,6 +247,27 @@ sub DEMOLISH {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate
|
||||
|
||||
Extends the base method to handle creating a new subscription group.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $copy = $self->SUPER::duplicate(@_);
|
||||
if ($self->get('subscriptionGroupId')) {
|
||||
my $group = WebGUI::Group->new($session, $self->get('subscriptionGroupId'));
|
||||
my $copied_group = WebGUI::Group->new($session, 'new');
|
||||
$copied_group->addUsers($group->getUsers('withoutExpired'));
|
||||
$copy->update({subscriptionGroupId => $copied_group->getId});
|
||||
}
|
||||
return $copy;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAdjacentThread ( )
|
||||
|
||||
Given a field and an order, returns the nearest thread when sorting by those.
|
||||
|
|
|
|||
|
|
@ -326,7 +326,140 @@ override getEditForm => sub {
|
|||
return $f;
|
||||
};
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getAllButtons ( )
|
||||
|
||||
Get a list of all the buttons in this MCE
|
||||
|
||||
=cut
|
||||
|
||||
sub getAllButtons {
|
||||
my ( $self ) = @_;
|
||||
my @toolbarRows = map{[split "\n", $self->get("toolbarRow$_")]} (1..3);
|
||||
my @toolbarButtons = map{ @{$_} } @toolbarRows;
|
||||
return @toolbarButtons;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getConfig ( )
|
||||
|
||||
Get a hashref of configuration to create this MCE. You must run the code
|
||||
from getLoadPlugins before you can successfully initialize an MCE. You
|
||||
must also specify the "elements" key so TinyMCE knows what textarea to
|
||||
replace.
|
||||
|
||||
=cut
|
||||
|
||||
sub getConfig {
|
||||
my ($self) = @_;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_RichEdit');
|
||||
my @plugins;
|
||||
push @plugins, "safari";
|
||||
push @plugins, "paste";
|
||||
push @plugins, "contextmenu"
|
||||
if $self->enableContextMenu;
|
||||
push @plugins, "inlinepopups"
|
||||
if $self->inlinePopups;
|
||||
push @plugins, "media"
|
||||
if $self->allowMedia;
|
||||
|
||||
my @toolbarRows = map{[split "\n", $self->get("toolbarRow$_")]} (1..3);
|
||||
my @toolbarButtons = map{ @{$_} } @toolbarRows;
|
||||
my %config = (
|
||||
mode => 'exact',
|
||||
theme => "advanced",
|
||||
relative_urls => JSON::false(),
|
||||
remove_script_host => JSON::true(),
|
||||
auto_reset_designmode => JSON::true(),
|
||||
cleanup_callback => "tinyMCE_WebGUI_Cleanup",
|
||||
urlconverter_callback => "tinyMCE_WebGUI_URLConvertor",
|
||||
theme_advanced_resizing => JSON::true(),
|
||||
( map { "theme_advanced_buttons" . ( $_ + 1 ) => ( join ',', @{ $toolbarRows[$_] } ) } ( 0 .. $#toolbarRows ) ),
|
||||
|
||||
ask => JSON::false(),
|
||||
preformatted => $self->preformatted ? JSON::true() : JSON::false(),
|
||||
force_br_newlines => $self->useBr ? JSON::true() : JSON::false(),
|
||||
force_p_newlines => $self->useBr ? JSON::false() : JSON::true(),
|
||||
$self->useBr ? ( forced_root_block => JSON::false() ) : (),
|
||||
remove_linebreaks => $self->removeLineBreaks ? JSON::true() : JSON::false(),
|
||||
nowrap => $self->nowrap ? JSON::true() : JSON::false(),
|
||||
directionality => $self->directionality,
|
||||
theme_advanced_toolbar_location => $self->toolbarLocation,
|
||||
theme_advanced_statusbar_location => "bottom",
|
||||
valid_elements => $self->validElements,
|
||||
wg_userIsVisitor => $self->session->user->isVisitor ? JSON::true() : JSON::false(),
|
||||
paste_postprocess => 'tinyMCE_WebGUI_paste_postprocess',
|
||||
);
|
||||
foreach my $button (@toolbarButtons) {
|
||||
if ( $button eq "spellchecker" && $self->session->config->get('availableDictionaries') ) {
|
||||
push( @plugins, "-wgspellchecker" );
|
||||
$config{spellchecker_rpc_url} = $self->session->url->gateway( '', "op=spellCheck" );
|
||||
$config{spellchecker_languages} = join( ',',
|
||||
map { ( $_->{default} ? '+' : '' ) . $_->{name} . '=' . $_->{id} }
|
||||
@{ $self->session->config->get('availableDictionaries') } );
|
||||
}
|
||||
push( @plugins, "table" ) if ( $button eq "tablecontrols" );
|
||||
push( @plugins, "save" ) if ( $button eq "save" );
|
||||
push( @plugins, "advhr" ) if ( $button eq "advhr" );
|
||||
push( @plugins, "fullscreen" ) if ( $button eq "fullscreen" );
|
||||
if ( $button eq "advimage" ) {
|
||||
push( @plugins, "advimage" );
|
||||
$config{external_link_list_url} = "";
|
||||
}
|
||||
if ( $button eq "advlink" ) {
|
||||
$config{external_image_list_url} = "";
|
||||
$config{file_browser_callback} = "mcFileManager.filebrowserCallBack";
|
||||
push( @plugins, "advlink" );
|
||||
}
|
||||
push( @plugins, "emotions" ) if ( $button eq "emotions" );
|
||||
push( @plugins, "iespell" ) if ( $button eq "iespell" );
|
||||
$config{gecko_spellcheck} = 'true' if ( $button eq "iespell" );
|
||||
if ( $button eq "paste" || $button eq "pastetext" || $button eq "pasteword" ) {
|
||||
push( @plugins, "paste" );
|
||||
}
|
||||
if ( $button eq "insertdate" || $button eq "inserttime" || $button eq "insertdatetime" ) {
|
||||
$config{plugin_insertdate_dateFormat} = "%Y-%m-%d";
|
||||
$config{plugin_insertdate_timeFormat} = "%H:%M:%S";
|
||||
push( @plugins, "insertdatetime" );
|
||||
}
|
||||
push( @plugins, "preview" ) if ( $button eq "preview" );
|
||||
if ( $button eq "media" ) {
|
||||
push( @plugins, "media" );
|
||||
}
|
||||
push( @plugins, "searchreplace" )
|
||||
if ( $button eq "search" || $button eq "replace" || $button eq "searchreplace" );
|
||||
push( @plugins, "print" ) if ( $button eq "print" );
|
||||
if ( $button eq "wginsertimage" ) {
|
||||
push @plugins, "-wginsertimage";
|
||||
}
|
||||
if ( $button eq "wgpagetree" ) {
|
||||
push @plugins, "-wgpagetree";
|
||||
}
|
||||
if ( $button eq "wgmacro" ) {
|
||||
push @plugins, "-wgmacro";
|
||||
}
|
||||
if ( $button eq "code" ) {
|
||||
$config{theme_advanced_source_editor_width} = $self->sourceEditorWidth
|
||||
if ( $self->sourceEditorWidth > 0 );
|
||||
$config{theme_advanced_source_editor_height} = $self->sourceEditorHeight
|
||||
if ( $self->sourceEditorHeight > 0 );
|
||||
}
|
||||
} ## end foreach my $button (@toolbarButtons)
|
||||
my $language = $i18n->getLanguage( '', "languageAbbreviation" );
|
||||
unless ($language) {
|
||||
$language = $i18n->getLanguage( "English", "languageAbbreviation" );
|
||||
}
|
||||
$config{language} = $language;
|
||||
$config{content_css} = $self->cssFile
|
||||
|| $self->session->url->extras('tinymce-webgui/defaultcontent.css');
|
||||
$config{width} = $self->editorWidth if ( $self->editorWidth > 0 );
|
||||
$config{height} = $self->editorHeight if ( $self->editorHeight > 0 );
|
||||
$config{plugins} = join( ",", @plugins );
|
||||
|
||||
return \%config;
|
||||
} ## end sub getConfig
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -354,6 +487,40 @@ my $sql = "select asset.assetId, assetData.revisionDate from RichEdit left join
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getLoadPlugins ( )
|
||||
|
||||
Get the JS code to load the plugins for this MCE. Needs to be called once
|
||||
on the page this MCE will be on
|
||||
|
||||
=cut
|
||||
|
||||
sub getLoadPlugins {
|
||||
my ( $self ) = @_;
|
||||
my %loadPlugins;
|
||||
for my $button ( $self->getAllButtons ) {
|
||||
if ( $button eq 'spellchecker' ) {
|
||||
$loadPlugins{wgspellchecker} = $self->session->url->extras("tinymce-webgui/plugins/wgspellchecker/editor_plugin.js");
|
||||
}
|
||||
if ( $button eq 'wginsertimage' ) {
|
||||
$loadPlugins{wginsertimage} = $self->session->url->extras("tinymce-webgui/plugins/wginsertimage/editor_plugin.js");
|
||||
}
|
||||
if ( $button eq 'wgpagetree' ) {
|
||||
$loadPlugins{wgpagetree} = $self->session->url->extras("tinymce-webgui/plugins/wgpagetree/editor_plugin.js");
|
||||
}
|
||||
if ( $button eq 'wgmacro' ) {
|
||||
$loadPlugins{wgmacro} = $self->session->url->extras("tinymce-webgui/plugins/wgmacro/editor_plugin.js");
|
||||
}
|
||||
}
|
||||
|
||||
my $out = '';
|
||||
while (my ($plugin, $path) = each %loadPlugins) {
|
||||
$out .= "tinymce.PluginManager.load('$plugin', '$path');\n";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRichEditor ( $nameId )
|
||||
|
||||
Return the javascript needed to make the Rich Editor.
|
||||
|
|
@ -369,119 +536,16 @@ sub getRichEditor {
|
|||
my $self = shift;
|
||||
return '' if ($self->disableRichEditor);
|
||||
my $nameId = shift;
|
||||
my @plugins;
|
||||
my %loadPlugins;
|
||||
push @plugins, "safari";
|
||||
push @plugins, "contextmenu"
|
||||
if $self->enableContextMenu;
|
||||
push @plugins, "inlinepopups"
|
||||
if $self->inlinePopups;
|
||||
push @plugins, "media"
|
||||
if $self->allowMedia;
|
||||
|
||||
my @toolbarRows = map{[split "\n", $self->get("toolbarRow$_")]} (1..3);
|
||||
my @toolbarButtons = map{ @{$_} } @toolbarRows;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_RichEdit');
|
||||
my $ask = $self->askAboutRichEdit;
|
||||
my %config = (
|
||||
mode => $ask ? "none" : "exact",
|
||||
elements => $nameId,
|
||||
theme => "advanced",
|
||||
relative_urls => JSON::false(),
|
||||
remove_script_host => JSON::true(),
|
||||
auto_reset_designmode => JSON::true(),
|
||||
cleanup_callback => "tinyMCE_WebGUI_Cleanup",
|
||||
urlconverter_callback => "tinyMCE_WebGUI_URLConvertor",
|
||||
theme_advanced_resizing => JSON::true(),
|
||||
(map { "theme_advanced_buttons".($_+1) => (join ',', @{$toolbarRows[$_]}) }
|
||||
(0..$#toolbarRows)),
|
||||
#ask => $self->getValue("askAboutRichEdit") ? JSON::true() : JSON::false(),
|
||||
ask => JSON::false(),
|
||||
preformatted => $self->preformatted ? JSON::true() : JSON::false(),
|
||||
force_br_newlines => $self->useBr ? JSON::true() : JSON::false(),
|
||||
force_p_newlines => $self->useBr ? JSON::false() : JSON::true(),
|
||||
$self->useBr ? ( forced_root_block => JSON::false() ) : (),
|
||||
remove_linebreaks => $self->removeLineBreaks ? JSON::true() : JSON::false(),
|
||||
nowrap => $self->nowrap ? JSON::true() : JSON::false(),
|
||||
directionality => $self->directionality,
|
||||
theme_advanced_toolbar_location => $self->toolbarLocation,
|
||||
theme_advanced_statusbar_location => "bottom",
|
||||
valid_elements => $self->validElements,
|
||||
wg_userIsVisitor => $self->session->user->isVisitor ? JSON::true() : JSON::false(),
|
||||
);
|
||||
# if ($ask) {
|
||||
# $config{oninit} = 'turnOffTinyMCE_'.$nameId;
|
||||
# }
|
||||
foreach my $button (@toolbarButtons) {
|
||||
if ($button eq "spellchecker" && $self->session->config->get('availableDictionaries')) {
|
||||
push(@plugins,"-wgspellchecker");
|
||||
$loadPlugins{wgspellchecker} = $self->session->url->extras("tinymce-webgui/plugins/wgspellchecker/editor_plugin.js");
|
||||
$config{spellchecker_rpc_url} = $self->session->url->gateway('', "op=spellCheck");
|
||||
$config{spellchecker_languages} =
|
||||
join(',', map { ($_->{default} ? '+' : '').$_->{name}.'='.$_->{id} } @{$self->session->config->get('availableDictionaries')});
|
||||
}
|
||||
push(@plugins,"table") if ($button eq "tablecontrols");
|
||||
push(@plugins,"save") if ($button eq "save");
|
||||
push(@plugins,"advhr") if ($button eq "advhr");
|
||||
push(@plugins,"fullscreen") if ($button eq "fullscreen");
|
||||
if ($button eq "advimage") {
|
||||
push(@plugins,"advimage");
|
||||
$config{external_link_list_url} = "";
|
||||
}
|
||||
if ($button eq "advlink") {
|
||||
$config{external_image_list_url} = "";
|
||||
$config{file_browser_callback} = "mcFileManager.filebrowserCallBack";
|
||||
push(@plugins,"advlink");
|
||||
}
|
||||
push(@plugins,"emotions") if ($button eq "emotions");
|
||||
push(@plugins,"iespell") if ($button eq "iespell");
|
||||
$config{gecko_spellcheck} = 'true' if ($button eq "iespell");
|
||||
if ($button eq "paste" || $button eq "pastetext" || $button eq "pasteword") {
|
||||
push(@plugins,"paste");
|
||||
}
|
||||
if ($button eq "insertdate" || $button eq "inserttime" || $button eq "insertdatetime") {
|
||||
$config{plugin_insertdate_dateFormat} = "%Y-%m-%d";
|
||||
$config{plugin_insertdate_timeFormat} = "%H:%M:%S";
|
||||
push(@plugins,"insertdatetime");
|
||||
}
|
||||
push(@plugins,"preview") if ($button eq "preview");
|
||||
if ($button eq "media") {
|
||||
push(@plugins,"media");
|
||||
}
|
||||
push(@plugins,"searchreplace") if ($button eq "search" || $button eq "replace" || $button eq "searchreplace");
|
||||
push(@plugins,"print") if ($button eq "print");
|
||||
if ($button eq "wginsertimage") {
|
||||
push @plugins, "-wginsertimage";
|
||||
$loadPlugins{wginsertimage} = $self->session->url->extras("tinymce-webgui/plugins/wginsertimage/editor_plugin.js");
|
||||
}
|
||||
if ($button eq "wgpagetree") {
|
||||
push @plugins, "-wgpagetree";
|
||||
$loadPlugins{wgpagetree} = $self->session->url->extras("tinymce-webgui/plugins/wgpagetree/editor_plugin.js");
|
||||
}
|
||||
if ($button eq "wgmacro") {
|
||||
push @plugins, "-wgmacro";
|
||||
$loadPlugins{wgmacro} = $self->session->url->extras("tinymce-webgui/plugins/wgmacro/editor_plugin.js");
|
||||
}
|
||||
if ($button eq "code") {
|
||||
$config{theme_advanced_source_editor_width} = $self->sourceEditorWidth if ($self->sourceEditorWidth > 0);
|
||||
$config{theme_advanced_source_editor_height} = $self->sourceEditorHeight if ($self->sourceEditorHeight > 0);
|
||||
}
|
||||
}
|
||||
my $language = $i18n->getLanguage('' ,"languageAbbreviation");
|
||||
unless ($language) {
|
||||
$language = $i18n->getLanguage("English","languageAbbreviation");
|
||||
}
|
||||
$config{language} = $language;
|
||||
$config{content_css} = $self->cssFile || $self->session->url->extras('tinymce-webgui/defaultcontent.css');
|
||||
$config{width} = $self->editorWidth || "100%";
|
||||
$config{height} = $self->editorHeight || "100%";
|
||||
$config{plugins} = join(",",@plugins);
|
||||
|
||||
$self->richedit_headTags;
|
||||
my $out = '';
|
||||
if ($ask) {
|
||||
$out = q|<a style="display: block;" href="javascript:toggleEditor('|.$nameId.q|')">|.$i18n->get('Toggle editor').q|</a>|;
|
||||
}
|
||||
$self->richedit_headTags;
|
||||
$out .= qq|<script type="text/javascript">\n|;
|
||||
if ($ask) {
|
||||
$out .= <<"EOHTML1";
|
||||
|
|
@ -498,11 +562,16 @@ EOHTML1
|
|||
# }
|
||||
#}
|
||||
#YAHOO.util.Event.onDOMReady(turnOffTinyMCE_$nameId);
|
||||
}
|
||||
|
||||
my $config = $self->getConfig;
|
||||
$config->{ elements } = $nameId;
|
||||
if ( $ask ) {
|
||||
$config->{mode} = "none";
|
||||
}
|
||||
while (my ($plugin, $path) = each %loadPlugins) {
|
||||
$out .= "tinymce.PluginManager.load('$plugin', '$path');\n";
|
||||
}
|
||||
$out .= "\ttinyMCE.init(" . JSON->new->pretty->encode(\%config) . " );\n";
|
||||
|
||||
$out .= $self->getLoadPlugins;
|
||||
$out .= "\ttinyMCE.init(" . JSON->new->pretty->encode( $config ) . " );\n";
|
||||
$out .= "</script>";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -637,7 +637,8 @@ sub getShortcutByCriteria {
|
|||
|
||||
my $replacement = $expression; # We don't want to modify $expression.
|
||||
# We need it later.
|
||||
push(@joins," left join metaData_values ".$counter."_v on a.assetId=".$counter."_v.assetId ");
|
||||
my $alias = $counter . '_v';
|
||||
push(@joins," left join metaData_values $alias on a.assetId=$alias.assetId and d.revisionDate = $alias.revisionDate ");
|
||||
# Get the field (State) and the value (Wisconsin) from the $expression.
|
||||
$expression =~ /($attribute)\s*($operator)\s*($attribute)/gi;
|
||||
my $field = $1;
|
||||
|
|
@ -670,7 +671,12 @@ sub getShortcutByCriteria {
|
|||
}
|
||||
|
||||
my $sql = "select a.assetId from asset a
|
||||
".join("\n", @joins)."
|
||||
left join assetData d on a.assetId = d.assetId
|
||||
and d.revisionDate=(
|
||||
select max(revisionDate)
|
||||
from assetData d2
|
||||
where d2.assetId = a.assetId
|
||||
) ".join("\n", @joins)."
|
||||
where a.className = ".$db->quote($self->getShortcutDefault->get("className"));
|
||||
# Add constraint only if it has been modified.
|
||||
$sql .= " and ".$constraint if (($constraint ne $criteria) && $constraint ne "");
|
||||
|
|
|
|||
|
|
@ -528,7 +528,9 @@ The WebGUI::Shop::TransactionItem being refunded.
|
|||
|
||||
sub onRefund {
|
||||
my ($self, $item) = @_;
|
||||
$self->onCancelRecurring($item);
|
||||
if ($self->isRecurring) {
|
||||
$self->onCancelRecurring($item);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1792,34 +1792,42 @@ sub view {
|
|||
$var{'addaccessory_url'} = $self->getUrl('func=addAccessory');
|
||||
$var{'addaccessory_label'} = $i18n->get(36);
|
||||
##Need an id for collateral operations, and an assetId for asset instantiation.
|
||||
foreach my $collateral ( @{ $self->getAllCollateral('accessoryJSON') } ) {
|
||||
ACCESSORY: foreach my $collateral ( @{ $self->getAllCollateral('accessoryJSON') } ) {
|
||||
my $id = $collateral->{accessoryAssetId};
|
||||
$segment = $self->session->icon->delete('func=deleteAccessoryConfirm&aid='.$id,$self->get('url'),$i18n->get(2))
|
||||
. $self->session->icon->moveUp('func=moveAccessoryUp&aid='.$id,$self->get('url'))
|
||||
. $self->session->icon->moveDown('func=moveAccessoryDown&aid='.$id,$self->get('url'));
|
||||
my $accessory_vars = {
|
||||
accessory_title => $i18n->get('Lost'),
|
||||
accessory_controls => $segment,
|
||||
};
|
||||
my $accessory = WebGUI::Asset->newById($session, $collateral->{accessoryAssetId});
|
||||
push(@accessoryloop,{
|
||||
'accessory_URL' => $accessory->getUrl,
|
||||
'accessory_title' => $accessory->getTitle,
|
||||
'accessory_controls' => $segment,
|
||||
});
|
||||
if ( $accessory ) {
|
||||
$accessory_vars->{ accessory_URL } = $accessory->getUrl;
|
||||
$accessory_vars->{ accessory_title } = $accessory->getTitle;
|
||||
}
|
||||
push(@accessoryloop, $accessory_vars);
|
||||
}
|
||||
$var{accessory_loop} = \@accessoryloop;
|
||||
|
||||
#---related
|
||||
$var{'addrelatedproduct_url'} = $self->getUrl('func=addRelated');
|
||||
$var{'addrelatedproduct_label'} = $i18n->get(37);
|
||||
foreach my $collateral ( @{ $self->getAllCollateral('relatedJSON')} ) {
|
||||
RELATED: foreach my $collateral ( @{ $self->getAllCollateral('relatedJSON')} ) {
|
||||
my $id = $collateral->{relatedAssetId};
|
||||
$segment = $self->session->icon->delete('func=deleteRelatedConfirm&rid='.$id, $self->get('url'),$i18n->get(4))
|
||||
. $self->session->icon->moveUp('func=moveRelatedUp&rid='.$id, $self->get('url'))
|
||||
. $self->session->icon->moveDown('func=moveRelatedDown&rid='.$id, $self->get('url'));
|
||||
my $related_vars = {
|
||||
relatedproduct_title => $i18n->get('Lost'),
|
||||
relatedproduct_controls => $segment,
|
||||
};
|
||||
my $related = WebGUI::Asset->newById($session, $collateral->{relatedAssetId});
|
||||
push(@relatedloop,{
|
||||
'relatedproduct_URL' => $related->getUrl,
|
||||
'relatedproduct_title' => $related->getTitle,
|
||||
'relatedproduct_controls' => $segment,
|
||||
});
|
||||
if ($related) {
|
||||
$related_vars->{ relatedproduct_URL } = $related->getUrl;
|
||||
$related_vars->{ relatedproduct_title } = $related->getTitle;
|
||||
}
|
||||
push(@relatedloop, $related_vars);
|
||||
}
|
||||
$var{relatedproduct_loop} = \@relatedloop;
|
||||
|
||||
|
|
|
|||
|
|
@ -91,13 +91,6 @@ property cacheTimeout => (
|
|||
label => ["cache timeout",'Asset_Snippet'],
|
||||
hoverHelp => ["cache timeout help",'Asset_Snippet'],
|
||||
);
|
||||
property processAsTemplate => (
|
||||
fieldType => 'yesNo',
|
||||
label => ['process as template','Asset_Snippet'],
|
||||
hoverHelp => ['process as template description','Asset_Snippet'],
|
||||
tab => "properties",
|
||||
default => 0,
|
||||
);
|
||||
property mimeType => (
|
||||
tab => "properties",
|
||||
hoverHelp => ['mimeType description','Asset_Snippet'],
|
||||
|
|
@ -105,6 +98,15 @@ property mimeType => (
|
|||
fieldType => 'mimeType',
|
||||
default => 'text/html',
|
||||
);
|
||||
property templateParser => (
|
||||
fieldType => 'templateParser',
|
||||
allowNone => 1,
|
||||
label => ['parser','Asset_Template'],
|
||||
hoverHelp => ['parser description','Asset_Template'],
|
||||
tab => 'properties',
|
||||
defaultValue => '',
|
||||
);
|
||||
|
||||
has '+uiLevel' => (
|
||||
default => 5,
|
||||
);
|
||||
|
|
@ -247,13 +249,15 @@ sub view {
|
|||
my $out = $session->cache->get( $cacheKey );
|
||||
return $out if $out;
|
||||
}
|
||||
my $output = $self->usePacked
|
||||
? $self->snippetPacked
|
||||
: $self->snippet
|
||||
;
|
||||
my $output = $self->get('usePacked')
|
||||
? $self->get("snippetPacked")
|
||||
: $self->get('snippet')
|
||||
;
|
||||
$output = $self->getToolbar.$output if ($session->isAdminOn && !$calledAsWebMethod);
|
||||
if ($self->processAsTemplate) {
|
||||
$output = WebGUI::Asset::Template->processRaw($session, $output, $self->get);
|
||||
if (my $parser = $self->templateParser) {
|
||||
$output = WebGUI::Asset::Template->processRaw(
|
||||
$session, $output, $self->get, $parser
|
||||
);
|
||||
}
|
||||
WebGUI::Macro::process($session,\$output);
|
||||
unless ($noCache) {
|
||||
|
|
|
|||
|
|
@ -207,6 +207,26 @@ sub exportAssetData {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportGetRelatedAssetIds
|
||||
|
||||
Overriden to include any topics in which this story would appear.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportGetRelatedAssetIds {
|
||||
my $self = shift;
|
||||
my $rel = $self->SUPER::exportGetRelatedAssetIds(@_);
|
||||
push @$rel, @{
|
||||
WebGUI::Keyword->new($self->session)->getMatchingAssets({
|
||||
keywords => WebGUI::Keyword::string2list($self->get('keywords')),
|
||||
isa => 'WebGUI::Asset::Wobject::StoryTopic',
|
||||
})
|
||||
};
|
||||
return $rel;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 formatDuration ( $lastUpdated )
|
||||
|
||||
Format the time since this story was last updated. If it is longer than 1 week, then
|
||||
|
|
@ -396,6 +416,9 @@ sub getEditForm {
|
|||
value => $i18n->get('save and add another photo'),
|
||||
}),
|
||||
};
|
||||
if ($session->setting->get('metaDataEnabled')) {
|
||||
$var->{metadata} = $self->getMetaDataAsFormFields;
|
||||
}
|
||||
$var->{ photo_form_loop } = [];
|
||||
##Provide forms for the existing photos, if any
|
||||
##Existing photos get a delete Yes/No.
|
||||
|
|
@ -405,12 +428,16 @@ sub getEditForm {
|
|||
foreach my $photoIndex (1..$numberOfPhotos) {
|
||||
my $photo = $photoData->[$photoIndex-1];
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $filename = $storage->getFiles->[0];
|
||||
my $filename = $storage && $storage->getFiles->[0];
|
||||
push @{ $var->{ photo_form_loop } }, {
|
||||
hasPhoto => $filename ? 1 : 0,
|
||||
imgThumb => $filename ? $storage->getThumbnailUrl($filename) : '',
|
||||
imgUrl => $filename ? $storage->getUrl($filename) : '',
|
||||
imgFilename => $filename ? $filename : '',
|
||||
imgRemoteUrlForm => WebGUI::Form::text($session, {
|
||||
name => 'imgRemoteUrl'.$photoIndex,
|
||||
value => $photo->{remoteUrl},
|
||||
}),
|
||||
newUploadForm => WebGUI::Form::file($session, {
|
||||
name => 'newPhoto' . $photoIndex,
|
||||
maxAttachments => 1,
|
||||
|
|
@ -442,6 +469,9 @@ sub getEditForm {
|
|||
};
|
||||
}
|
||||
push @{ $var->{ photo_form_loop } }, {
|
||||
imgRemoteUrlForm => WebGUI::Form::text($session, {
|
||||
name => 'imgRemoteUrl',
|
||||
}),
|
||||
newUploadForm => WebGUI::Form::image($session, {
|
||||
name => 'newPhoto',
|
||||
maxAttachments => 1,
|
||||
|
|
@ -580,16 +610,20 @@ sub processEditForm {
|
|||
PHOTO: foreach my $photoIndex (1..$numberOfPhotos) {
|
||||
##TODO: Deletion check and storage cleanup
|
||||
my $storageId = $photoData->[$photoIndex-1]->{storageId};
|
||||
my $storage = $storageId && WebGUI::Storage->get($session, $storageId);
|
||||
my $remote = $form->process("imgRemoteUrl$photoIndex");
|
||||
if ($form->process('deletePhoto'.$photoIndex, 'yesNo')) {
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->delete if $storage;
|
||||
splice @{ $photoData }, $photoIndex-1, 1;
|
||||
next PHOTO;
|
||||
}
|
||||
##Process photos with urls that replace existing photos
|
||||
if ($remote) {
|
||||
$storage->delete() if $storage;
|
||||
}
|
||||
##Process uploads that replace existing photos
|
||||
if (my $uploadId = $form->process('newPhoto'.$photoIndex,'File')) {
|
||||
elsif (my $uploadId = $form->process('newPhoto'.$photoIndex,'File')) {
|
||||
my $upload = WebGUI::Storage->get($session, $uploadId);
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->clear;
|
||||
my $filename = $upload->getFiles->[0];
|
||||
$storage->addFileFromFilesystem($upload->getPath($filename));
|
||||
|
|
@ -600,31 +634,43 @@ sub processEditForm {
|
|||
$upload->delete;
|
||||
}
|
||||
my $newPhoto = {
|
||||
storageId => $storageId,
|
||||
caption => $form->process('imgCaption'.$photoIndex, 'text'),
|
||||
alt => $form->process('imgAlt' .$photoIndex, 'text'),
|
||||
title => $form->process('imgTitle' .$photoIndex, 'text'),
|
||||
byLine => $form->process('imgByline' .$photoIndex, 'text'),
|
||||
url => $form->process('imgUrl' .$photoIndex, 'url' ),
|
||||
};
|
||||
if ($remote) {
|
||||
$newPhoto->{remoteUrl} = $remote;
|
||||
}
|
||||
else {
|
||||
$newPhoto->{storageId} = $storageId;
|
||||
}
|
||||
splice @{ $photoData }, $photoIndex-1, 1, $newPhoto;
|
||||
}
|
||||
my $newStorageId = $form->process('newPhoto', 'image');
|
||||
if ($newStorageId) {
|
||||
my $newStorage = WebGUI::Storage->get($session, $newStorageId);
|
||||
my $photoName = $newStorage->getFiles->[0];
|
||||
my ($width, $height) = $newStorage->getSizeInPixels($photoName);
|
||||
if ($width > $self->getArchive->photoWidth) {
|
||||
$newStorage->resize($photoName, $self->getArchive->photoWidth);
|
||||
}
|
||||
push @{ $photoData }, {
|
||||
my $newRemote = $form->process('imgRemoteUrl');
|
||||
if ($newStorageId || $newRemote) {
|
||||
my $newPhoto = {
|
||||
caption => $form->process('newImgCaption', 'text'),
|
||||
alt => $form->process('newImgAlt', 'text'),
|
||||
title => $form->process('newImgTitle', 'text'),
|
||||
byLine => $form->process('newImgByline', 'text'),
|
||||
url => $form->process('newImgUrl', 'url'),
|
||||
storageId => $newStorageId,
|
||||
};
|
||||
if ($newRemote) {
|
||||
$newPhoto->{remoteUrl} = $newRemote;
|
||||
}
|
||||
else {
|
||||
my $newStorage = WebGUI::Storage->get($session, $newStorageId);
|
||||
my $photoName = $newStorage->getFiles->[0];
|
||||
my ($width, $height) = $newStorage->getSizeInPixels($photoName);
|
||||
if ($width > $self->getArchive->get('photoWidth')) {
|
||||
$newStorage->resize($photoName, $self->getArchive->get('photoWidth'));
|
||||
}
|
||||
$newPhoto->{storageId} = $newStorageId;
|
||||
}
|
||||
push @{ $photoData }, $newPhoto;
|
||||
}
|
||||
$self->setPhotoData($photoData);
|
||||
$self->{_parent} = $archive; ##Restore archive, for URL and other calculations
|
||||
|
|
@ -666,8 +712,9 @@ Remove the storage locations for this revision of the Asset.
|
|||
override purgeRevision => sub {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
foreach my $photo ( @{ $self->getPhotoData} ) {
|
||||
my $storage = WebGUI::Storage->get($session, $self-$photo->{storageId});
|
||||
PHOTO: foreach my $photo ( @{ $self->getPhotoData} ) {
|
||||
my $id = $photo->{storageId} or next PHOTO;
|
||||
my $storage = WebGUI::Storage->get($session, $id);
|
||||
$storage->delete if $storage;
|
||||
}
|
||||
return super();
|
||||
|
|
@ -832,13 +879,23 @@ sub viewTemplateVariables {
|
|||
}
|
||||
}
|
||||
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $keywords = $key->getKeywordsForAsset( { asArrayRef => 1, asset => $self });
|
||||
my $isExporting = $session->scratch->get('isExporting');
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $keywords = $key->getKeywordsForAsset( { asArrayRef => 1, asset => $self });
|
||||
$var->{keyword_loop} = [];
|
||||
my $parent = $self->getParent;
|
||||
my $upwards = $parent->isa('WebGUI::Asset::Wobject::StoryArchive')
|
||||
? '' #In parallel with the Keywords files
|
||||
: '../' #Keywords files are one level up
|
||||
;
|
||||
foreach my $keyword (@{ $keywords }) {
|
||||
my $keyword_url = $isExporting
|
||||
? $upwards . $archive->getKeywordFilename($keyword)
|
||||
: $archive->getUrl("func=view;keyword=".$session->url->escape($keyword))
|
||||
;
|
||||
push @{ $var->{keyword_loop} }, {
|
||||
keyword => $keyword,
|
||||
url => $archive->getUrl("func=view;keyword=".$session->url->escape($keyword)),
|
||||
url => $keyword_url,
|
||||
};
|
||||
}
|
||||
$var->{updatedTime} = $self->formatDuration();
|
||||
|
|
@ -849,11 +906,19 @@ sub viewTemplateVariables {
|
|||
$var->{photo_loop} = [];
|
||||
my $photoCounter = 0;
|
||||
PHOTO: foreach my $photo (@{ $photoData }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $file = $storage->getFiles->[0];
|
||||
next PHOTO unless $file;
|
||||
my $imageUrl = $storage->getUrl($file);
|
||||
my $imageUrl;
|
||||
if (my $remote = $photo->{remoteUrl}) {
|
||||
$imageUrl = $remote;
|
||||
}
|
||||
elsif (my $id = $photo->{storageId}) {
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $file = $storage->getFiles->[0];
|
||||
next PHOTO unless $file;
|
||||
$imageUrl = $storage->getUrl($file);
|
||||
}
|
||||
else {
|
||||
next PHOTO;
|
||||
}
|
||||
push @{ $var->{photo_loop} }, {
|
||||
imageUrl => $imageUrl,
|
||||
imageCaption => $photo->{caption},
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ use List::MoreUtils qw{ any };
|
|||
use Tie::IxHash;
|
||||
use Clone qw/clone/;
|
||||
use HTML::Packer;
|
||||
use JSON qw{ to_json };
|
||||
use JSON qw{ to_json from_json };
|
||||
use Try::Tiny;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -227,6 +228,8 @@ around cut => sub {
|
|||
return $returnValue;
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addRevision ( )
|
||||
|
||||
Override the master addRevision to copy attachments
|
||||
|
|
@ -324,19 +327,22 @@ Returns the WebGUI::FormBuilder object that will be used in generating the edit
|
|||
override getEditForm => sub {
|
||||
my $self = shift;
|
||||
my $tabform = super();
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_Template');
|
||||
my $session = $self->session;
|
||||
my ( $url, $style ) = $session->quick(qw( url style ));
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Template');
|
||||
my $returnUrl = $session->form->get("returnUrl");
|
||||
$tabform->addField( "hidden",
|
||||
name=>"returnUrl",
|
||||
value=>$self->session->form->get("returnUrl")
|
||||
value=>$returnUrl,
|
||||
);
|
||||
if ($self->namespace eq "") {
|
||||
my $namespaces = $self->session->dbSlave->buildHashRef("select distinct(namespace) from template order by namespace");
|
||||
my $namespaces = $session->dbSlave->buildHashRef("select distinct(namespace) from template order by namespace");
|
||||
$tabform->getTab("properties")->addField( "combo",
|
||||
name=>"namespace",
|
||||
options=>$namespaces,
|
||||
label=>$i18n->get('namespace'),
|
||||
hoverHelp=>$i18n->get('namespace description'),
|
||||
value=>[$self->session->form->get("namespace")]
|
||||
value=>[$session->form->get("namespace")]
|
||||
);
|
||||
} else {
|
||||
$tabform->getTab("meta")->addField( "ReadOnly",
|
||||
|
|
@ -346,14 +352,68 @@ override getEditForm => sub {
|
|||
value=>$self->namespace
|
||||
);
|
||||
}
|
||||
if($self->session->config->get("templateParsers")){
|
||||
my @temparray = @{$self->session->config->get("templateParsers")};
|
||||
|
||||
my $previewButtons
|
||||
= $tabform->getTab('properties')->addField( "ButtonGroup",
|
||||
name => 'previewButtons',
|
||||
label => $i18n->get('Preview'),
|
||||
);
|
||||
$previewButtons->addButton( 'Button' => { id => 'preview', value => $i18n->get('Preview') } );
|
||||
$previewButtons->addButton( 'Button' => { id => 'previewConfig', value => $i18n->get('Configure') } );
|
||||
my $cform = WebGUI::HTMLForm->new($session);
|
||||
$cform->yesNo(
|
||||
id => 'previewRaw',
|
||||
name => 'previewRaw',
|
||||
label => $i18n->get('Plain Text?'),
|
||||
hoverHelp => $i18n->get('Plain Text hoverHelp'),
|
||||
);
|
||||
$cform->text(
|
||||
id => 'previewFetchUrl',
|
||||
label => $i18n->get('URL'),
|
||||
hoverHelp => $i18n->get('URL hoverHelp'),
|
||||
defaultValue => $returnUrl,
|
||||
);
|
||||
$cform->button(
|
||||
id => 'previewFetch',
|
||||
label => $i18n->get('Fetch Variables'),
|
||||
hoverHelp => $i18n->get('Fetch Variables hoverHelp'),
|
||||
value => $i18n->get('Fetch'),
|
||||
);
|
||||
$cform->codearea(
|
||||
id => 'previewVars',
|
||||
label => $i18n->get('Variables'),
|
||||
hoverHelp => $i18n->get('Variables hoverHelp'),
|
||||
);
|
||||
|
||||
$cform->hidden(id => 'previewId', value => $self->getId);
|
||||
$cform->hidden(id => 'previewGateway', value => $url->gateway);
|
||||
$tabform->getTab('properties')->addField("ReadOnly",
|
||||
name => 'previewDialog',
|
||||
value => qq(
|
||||
<div id='previewConfigForm'>
|
||||
<div class='hd'>${\ $i18n->get('Configure Preview') }</div>
|
||||
<table class='bd'>${\ $cform->printRowsOnly }</table>
|
||||
<div class='ft' style='margin:0 auto; text-align: center'>
|
||||
<button id='previewConfigClose'>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
);
|
||||
|
||||
$style->setScript($url->extras($_)) for qw(
|
||||
yui/build/json/json-min.js
|
||||
yui/build/container/container-min.js
|
||||
templatePreview.js
|
||||
);
|
||||
|
||||
if($session->config->get("templateParsers")){
|
||||
my @temparray = @{$session->config->get("templateParsers")};
|
||||
tie my %parsers, 'Tie::IxHash';
|
||||
while(my $a = shift @temparray){
|
||||
$parsers{$a} = $self->getParser($self->session, $a)->getName();
|
||||
$parsers{$a} = $self->getParser($session, $a)->getName();
|
||||
}
|
||||
my $value = [$self->parser];
|
||||
$value = \[$self->session->config->get("defaultTemplateParser")] if(!$self->parser);
|
||||
$value = \[$session->config->get("defaultTemplateParser")] if(!$self->parser);
|
||||
$tabform->getTab("properties")->addField( "SelectBox",
|
||||
name=>"parser",
|
||||
options=>\%parsers,
|
||||
|
|
@ -501,6 +561,22 @@ sub getParser {
|
|||
return $parser->new($session);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
#
|
||||
# See the warning about using this on processVariableHeaders(). If no
|
||||
# variables were captured, we'll return the empty string.
|
||||
|
||||
sub getVariableJson {
|
||||
my ($class, $session) = @_;
|
||||
my ($show, $vars, $json);
|
||||
|
||||
return ($show = $session->stow->get('showTemplateVars'))
|
||||
&& ($vars = $show->{vars})
|
||||
&& ($json = eval { JSON::encode_json($vars) })
|
||||
&& ($show->{startDelimiter} . $json . $show->{endDelimiter})
|
||||
or '';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 importAssetCollateralData ( data )
|
||||
|
|
@ -631,6 +707,15 @@ sub process {
|
|||
return to_json( $self->param );
|
||||
}
|
||||
|
||||
my $stow = $session->stow;
|
||||
my $show = $stow->get('showTemplateVars');
|
||||
if ( $show && $show->{assetId} eq $self->getId && $self->canEdit ) {
|
||||
# This will never be true again, cause we're getting rid of assetId
|
||||
delete $show->{assetId};
|
||||
$show->{vars} = $vars;
|
||||
$stow->set( showTemplateVars => $show );
|
||||
}
|
||||
|
||||
$self->prepare unless ($self->{_prepared});
|
||||
my $parser = $self->getParser($session, $self->parser);
|
||||
my $template = $self->usePacked
|
||||
|
|
@ -653,6 +738,59 @@ sub process {
|
|||
return $output;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# Used for debugging and the template test renderer.
|
||||
|
||||
# WARNING: Please do not rely on this behavior. It's a bit of a hack, and
|
||||
# should not be considered part of the core API. Eventually, we will have
|
||||
# introspectable template objects so that you can more easily (and
|
||||
# efficiently) get this kind of information.
|
||||
|
||||
# If the first value for the 'X-Webgui-Template-Variables' header is our
|
||||
# assetId, then in addition to processing the template, append add a json
|
||||
# representation of our template variables to the response. The headers
|
||||
# "X-Webgui-Template-Variables-Start" and "X-Webgui-Template-Variables-End"
|
||||
# will contain the delimiters for the start and end of this content so that
|
||||
# the user agent (who had to have stuck the header in in the first place) can
|
||||
# parse it out. The delimiters will make the whole thing look like an xml
|
||||
# comment (<!-- ... -->) just in case.
|
||||
|
||||
# We would just send the vars in the header, but different webservers have
|
||||
# different limits on header field size and it's impossible to say whether our
|
||||
# data will fit inside them or not.
|
||||
|
||||
# This is intended to be called earlier in the request cycle (in the Content
|
||||
# URL handler) so that the headers get sent before any chunked content starts
|
||||
# being set up. We set the stow here and check it during process() to see
|
||||
# whether we need to include the delimited json. Later on, Content will call
|
||||
# call getVariableJson to get the results.
|
||||
|
||||
{
|
||||
my $head = 'X-Webgui-Template-Variables';
|
||||
my @chr = ('0'..'9', 'a'..'z', 'A'..'Z');
|
||||
|
||||
sub processVariableHeaders {
|
||||
my ($class, $session) = @_;
|
||||
my $r = $session->request;
|
||||
if (my $id = $r->headers->header($head)) {
|
||||
my $rnd = join('', map { $chr[int(rand($#chr))] } (1..32));
|
||||
my $out = {};
|
||||
my $st = "<!-- $rnd ";
|
||||
my $end = " $rnd -->";
|
||||
$out->{"$head-Start"} = $st;
|
||||
$out->{"$head-End"} = $end;
|
||||
$session->response->headers( $out );
|
||||
$session->stow->set(
|
||||
showTemplateVars => {
|
||||
assetId => $id,
|
||||
startDelimiter => $st,
|
||||
endDelimiter => $end,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -921,6 +1059,42 @@ sub www_manage {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_preview
|
||||
|
||||
Rendes this template with the given variables (posted as JSON)
|
||||
|
||||
=cut
|
||||
|
||||
sub www_preview {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient unless $self->canEdit;
|
||||
|
||||
my $form = $session->form;
|
||||
my $http = $session->http;
|
||||
|
||||
try {
|
||||
my $output = $self->processRaw(
|
||||
$session,
|
||||
$form->get('template'),
|
||||
from_json($form->get('variables')),
|
||||
$form->get('parser'),
|
||||
);
|
||||
if ($form->get('plainText')) {
|
||||
$http->setMimeType('text/plain');
|
||||
}
|
||||
elsif ($output !~ /<html>/) {
|
||||
$output = $session->style->userStyle($output);
|
||||
}
|
||||
return $output;
|
||||
} catch {
|
||||
$http->setMimeType('text/plain');
|
||||
$_[0];
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
Override the default behavior. When a template is viewed, it redirects you
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package WebGUI::Asset::Template::TemplateToolkit;
|
|||
use strict;
|
||||
use base 'WebGUI::Asset::Template::Parser';
|
||||
use Template;
|
||||
use WebGUI::Template::Provider;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _rewriteVars { # replace dots with underscrores in keys (except in keys that aren't usable as variables (URLs etc.))
|
||||
|
|
@ -81,12 +82,30 @@ sub process {
|
|||
my $vars = $self->addSessionVars(shift);
|
||||
my ($t,$output);
|
||||
eval {
|
||||
$t = Template->new({
|
||||
INTERPOLATE => 1, # expand "$var" in plain text
|
||||
POST_CHOMP => 1, # cleanup whitespace
|
||||
EVAL_PERL => 0, # evaluate Perl code blocks
|
||||
});
|
||||
$t->process( \$template, _rewriteVars($vars),\$output) || $self->session->log->error($t->error());
|
||||
my $config = $self->session->config->get( 'template' ) || {};
|
||||
$config->{INTERPOLATE} //= 1; # expand "$var" in plain text
|
||||
$config->{POST_CHOMP} //= 1; # cleanup whitespace
|
||||
$config->{EVAL_PERL} //= 0; # evaluate Perl code blocks
|
||||
# Add WebGUI::Template::Plugin to PLUGIN_BASE
|
||||
if ( defined $config->{PLUGIN_BASE} && !ref $config->{PLUGIN_BASE} ) {
|
||||
$config->{PLUGIN_BASE} = [ $config->{PLUGIN_BASE} ];
|
||||
}
|
||||
elsif ( !defined $config->{PLUGIN_BASE} ) {
|
||||
$config->{PLUGIN_BASE} = [];
|
||||
}
|
||||
push @{$config->{PLUGIN_BASE}}, 'WebGUI::Template::Plugin';
|
||||
|
||||
# Allow WebGUI assets to be included in templates
|
||||
$config->{LOAD_TEMPLATES} = [ WebGUI::Template::Provider->new( $self->session, $config ) ];
|
||||
|
||||
$t = Template->new( $config );
|
||||
$vars = _rewriteVars($vars);
|
||||
$vars->{_session} = $self->session;
|
||||
unless ($t->process( \$template, $vars, \$output)) {
|
||||
my $e = $t->error;
|
||||
$self->session->log->error($e);
|
||||
die $e;
|
||||
}
|
||||
};
|
||||
if ($@) {
|
||||
WebGUI::Error::Template->throw( error => $@ );
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use Moose;
|
|||
use Tie::IxHash;
|
||||
use WebGUI::Definition::Asset;
|
||||
extends 'WebGUI::Asset::Wobject';
|
||||
with 'WebGUI::Role::Asset::JSONCollateral';
|
||||
|
||||
define assetName => ['assetName', 'Asset_Calendar'];
|
||||
define icon => 'calendar.gif';
|
||||
|
|
@ -260,7 +261,7 @@ property icalFeeds => (
|
|||
label => ['Feed URL','Asset_Calendar'],
|
||||
},
|
||||
{
|
||||
name => 'status',
|
||||
name => 'lastResult',
|
||||
type => 'readonly',
|
||||
label => ['434','WebGUI'],
|
||||
},
|
||||
|
|
@ -303,6 +304,7 @@ use WebGUI::Search;
|
|||
use WebGUI::Form;
|
||||
use WebGUI::HTML;
|
||||
use WebGUI::DateTime;
|
||||
use WebGUI::ICal;
|
||||
|
||||
use DateTime;
|
||||
use JSON;
|
||||
|
|
@ -348,10 +350,6 @@ The date this feed was added, or edited last.
|
|||
|
||||
The results of what happened the last time this feed was accessed to pull iCal.
|
||||
|
||||
=head4 feedType
|
||||
|
||||
What kind of feed this is.
|
||||
|
||||
=cut
|
||||
|
||||
sub addFeed {
|
||||
|
|
@ -860,6 +858,17 @@ override processEditForm => sub {
|
|||
$self->createSubscriptionGroup();
|
||||
}
|
||||
|
||||
my @feeds = @{ $self->getFeeds };
|
||||
foreach my $feed (@feeds) {
|
||||
if ($feed->{lastUpdated} eq 'new') {
|
||||
$feed->{lastUpdated} = 'never';
|
||||
}
|
||||
if ($feed->{lastResult} eq 'new') {
|
||||
$feed->{lastResult} = '';
|
||||
}
|
||||
$self->setFeed($feed->{feedId}, $feed);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -1706,97 +1715,20 @@ sub www_ical {
|
|||
$dt_end = $dt_start->clone->add( seconds => $self->icalInterval );
|
||||
}
|
||||
|
||||
my $ical = WebGUI::ICal->new();
|
||||
|
||||
# Get all the events we're going to display
|
||||
my @events = $self->getEventsIn($dt_start->toMysql,$dt_end->toMysql);
|
||||
|
||||
|
||||
my $ical = qq{BEGIN:VCALENDAR\r\n}
|
||||
. qq{PRODID:WebGUI }.$WebGUI::VERSION."-".$WebGUI::STATUS.qq{\r\n}
|
||||
. qq{VERSION:2.0\r\n};
|
||||
|
||||
# VEVENT:
|
||||
EVENT: for my $event (@events) {
|
||||
next EVENT unless $event->canView();
|
||||
$ical .= qq{BEGIN:VEVENT\r\n};
|
||||
|
||||
### UID
|
||||
# Use feed's UID to prevent over-propagation
|
||||
if ($event->feedUid) {
|
||||
$ical .= qq{UID:}.$event->feedUid."\r\n";
|
||||
}
|
||||
# Create a UID for feeds native to this calendar
|
||||
else {
|
||||
my $domain = $session->config->get("sitename")->[0];
|
||||
$ical .= qq{UID:}.$event->assetId.'@'.$domain."\r\n";
|
||||
}
|
||||
|
||||
# LAST-MODIFIED (revisionDate)
|
||||
$ical .= qq{LAST-MODIFIED:}
|
||||
. WebGUI::DateTime->new($self->session, $event->revisionDate)->toIcal
|
||||
. "\r\n";
|
||||
|
||||
# CREATED (creationDate)
|
||||
$ical .= qq{CREATED:}
|
||||
. WebGUI::DateTime->new($self->session, $event->creationDate)->toIcal
|
||||
. "\r\n";
|
||||
|
||||
# SEQUENCE
|
||||
my $sequenceNumber = $event->iCalSequenceNumber;
|
||||
if (defined $sequenceNumber) {
|
||||
$ical .= qq{SEQUENCE:}
|
||||
. $event->iCalSequenceNumber
|
||||
. "\r\n";
|
||||
}
|
||||
|
||||
# DTSTART
|
||||
my $eventStart = $event->getIcalStart;
|
||||
$ical .= 'DTSTART';
|
||||
if ($eventStart !~ /T/) {
|
||||
$ical .= ';VALUE=DATE';
|
||||
}
|
||||
$ical .= ":$eventStart\r\n";
|
||||
|
||||
# DTEND
|
||||
my $eventEnd = $event->getIcalEnd;
|
||||
$ical .= 'DTEND';
|
||||
if ($eventEnd !~ /T/) {
|
||||
$ical .= ';VALUE=DATE';
|
||||
}
|
||||
$ical .= ":$eventEnd\r\n";
|
||||
|
||||
# Summary (the title)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("SUMMARY:".$event->title)."\r\n";
|
||||
|
||||
# Description (the text)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("DESCRIPTION:".$event->description)."\r\n";
|
||||
|
||||
# Location (the text)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("LOCATION:".$event->location)."\r\n";
|
||||
|
||||
# X-WEBGUI lines
|
||||
if ($event->groupIdView) {
|
||||
$ical .= "X-WEBGUI-GROUPIDVIEW:".$event->groupIdView."\r\n";
|
||||
}
|
||||
if ($event->get("groupIdEdit")) {
|
||||
$ical .= "X-WEBGUI-GROUPIDEDIT:".$event->groupIdEdit."\r\n";
|
||||
}
|
||||
$ical .= "X-WEBGUI-URL:".$event->get("url")."\r\n";
|
||||
$ical .= "X-WEBGUI-MENUTITLE:".$event->menuTitle."\r\n";
|
||||
|
||||
$ical .= qq{END:VEVENT\r\n};
|
||||
$event->add_to_calendar($ical);
|
||||
}
|
||||
# ENDVEVENT
|
||||
|
||||
$ical .= qq{END:VCALENDAR\r\n};
|
||||
|
||||
|
||||
# Set mime of text/icalendar
|
||||
$self->session->response->header( 'Content-Disposition' => qq{attachment; filename="feed.ics"});
|
||||
$self->session->response->content_type("text/calendar");
|
||||
return $ical;
|
||||
#$self->session->http->setMimeType("text/plain");
|
||||
$self->session->http->setFilename("feed.ics","text/calendar");
|
||||
return $ical->as_string;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -48,6 +48,20 @@ property items => (
|
|||
noFormPost => 1,
|
||||
fieldType => 'text',
|
||||
);
|
||||
property autoPlay => (
|
||||
fieldType => 'yesNo',
|
||||
defaultValue => 0,
|
||||
tab => "properties",
|
||||
hoverHelp => ['carousel autoPlay description', 'Asset_Carousel' ],
|
||||
label => ['carousel autoPlay label', 'Asset_Carousel' ],
|
||||
);
|
||||
property autoPlayInterval => (
|
||||
fieldType => 'Integer',
|
||||
defaultValue => 4,
|
||||
tab => 'properties',
|
||||
hoverHelp => ['carousel autoPlayInterval description', 'Asset_Carousel'],
|
||||
label => ['carousel autoPlayInterval label', 'Asset_Carousel'],
|
||||
);
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -63,16 +77,30 @@ override getEditForm => sub {
|
|||
my $tabform = super();
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_Carousel");
|
||||
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/editor/editor-min.js'));
|
||||
$self->session->style->setCss($self->session->url->extras('yui/build/editor/assets/skins/sam/editor.css'));
|
||||
$self->session->style->setScript($self->session->url->extras('wobject/Carousel/carousel.js'));
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/element/element-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/tabview/tabview-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/editor/editor-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/json/json-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setLink($self->session->url->extras('yui/build/editor/assets/skins/sam/editor.css'), {type
|
||||
=>'text/css', rel=>'stylesheet'});
|
||||
$self->session->style->setLink($self->session->url->extras('yui/build/tabview/assets/skins/sam/tabview.css'), {type
|
||||
=>'text/css', rel=>'stylesheet'});
|
||||
$self->session->style->setScript($self->session->url->extras('wobject/Carousel/carousel.js'), {type =>
|
||||
'text/javascript'});
|
||||
|
||||
my $tableRowStart =
|
||||
'<tr id="items_row">'
|
||||
.' <td class="formDescription" valign="top" style="width: 180px;"><label for="item1">'
|
||||
.$i18n->get("items label").'</label><div class="wg-hoverhelp">'.$i18n->get("items description").'</div></td>'
|
||||
.' <td id="items_td" valign="top" class="tableData">'
|
||||
.' <input type="button" value="Add item" onClick="javascript:addItem()"></input><br />'
|
||||
.' <input type="hidden" id="items_formId" name="items" />'
|
||||
.' <input type="button" value="Add item" onclick="window.carouselEditor.addTab()"></input><br />'
|
||||
." <br />\n";
|
||||
|
||||
$tabform->getTab("properties")->addField('ReadOnly', value => $tableRowStart);
|
||||
|
|
@ -122,6 +150,27 @@ onClick='javascript:deleteItem(this.id)'></input>\n"
|
|||
."</script>\n";
|
||||
$tabform->getTab("properties")->addField('ReadOnly', value => $itemHTML);
|
||||
}
|
||||
|
||||
|
||||
$self->session->log->warn('richedit:' .$self->get('richEditor'));
|
||||
my $richEditId = $self->get('richEditor') || "PBrichedit000000000001";
|
||||
my $richedit = WebGUI::Asset->newById( $self->session, $richEditId );
|
||||
my $config = JSON->new->encode( $richedit->getConfig );
|
||||
my $loadMcePlugins = $richedit->getLoadPlugins;
|
||||
my $items = $self->get('items') ? JSON->new->decode($self->get('items'))->{items} : [];
|
||||
$items = JSON->new->encode( $items );
|
||||
my $i18nJson = JSON->new->encode( { "delete" => $i18n->get("delete") } );
|
||||
|
||||
$tabform->getTab('properties')->raw(<<"ENDHTML");
|
||||
<div id="carouselEditor"></div>
|
||||
<script type="text/javascript">
|
||||
$loadMcePlugins
|
||||
YAHOO.util.Event.onDOMReady( function() {
|
||||
window.carouselEditor = new WebGUI.Carousel.Editor( "carouselEditor", $config, $items, $i18nJson );
|
||||
} );
|
||||
</script>
|
||||
ENDHTML
|
||||
|
||||
my $tableRowEnd = qq|
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -165,32 +214,9 @@ Used to process properties from the form posted.
|
|||
override processEditForm => sub {
|
||||
my $self = shift;
|
||||
my $form = $self->session->form;
|
||||
my (@items,$items);
|
||||
super();
|
||||
|
||||
foreach my $param ($form->param) {
|
||||
if ($param =~ m/^item_/){
|
||||
my $sequenceNumber = $param;
|
||||
$sequenceNumber =~ s/^item_//;
|
||||
if($form->process('itemId_'.$sequenceNumber)){
|
||||
push(@items,{
|
||||
sequenceNumber => $sequenceNumber,
|
||||
text => $form->process($param),
|
||||
itemId => $form->process('itemId_'.$sequenceNumber),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @sortedItems = sort { $a->{sequenceNumber} cmp $b->{sequenceNumber} } @items;
|
||||
@items = ();
|
||||
for (my $i=0; $i<scalar @sortedItems; $i++) {
|
||||
$sortedItems[$i]->{sequenceNumber} = $i + 1;
|
||||
push(@items,$sortedItems[$i]);
|
||||
}
|
||||
|
||||
$items = JSON->new->encode({items => \@items});
|
||||
$self->update({items => $items});
|
||||
my $items = JSON->new->decode( $form->get("items") );
|
||||
$self->update({ items => JSON->new->encode({ items => $items }) });
|
||||
return undef;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -879,19 +879,19 @@ override commit => sub {
|
|||
unless (defined $cron) {
|
||||
$cron = WebGUI::Workflow::Cron->create($self->session, {
|
||||
title=>$self->getTitle." ".$i18n->get("mail"),
|
||||
minuteOfHour=>"*/".($self->getMailInterval/60),
|
||||
className=>(ref $self),
|
||||
methodName=>"new",
|
||||
parameters=>$self->getId,
|
||||
workflowId=>"csworkflow000000000001"
|
||||
workflowId=>"csworkflow000000000001",
|
||||
$self->getCronIntervals,
|
||||
});
|
||||
$self->update({getMailCronId=>$cron->getId});
|
||||
}
|
||||
if ($self->getMail) {
|
||||
$cron->set({enabled=>1,title=>$self->getTitle." ".$i18n->get("mail"), minuteOfHour=>"*/".($self->getMailInterval/60)});
|
||||
} else {
|
||||
$cron->set({enabled=>0,title=>$self->getTitle." ".$i18n->get("mail"), minuteOfHour=>"*/".($self->getMailInterval/60)});
|
||||
}
|
||||
$cron->set({
|
||||
enabled => $self->get('getMail') ? 1 : 0,
|
||||
title => $self->getTitle." ".$i18n->get("mail"),
|
||||
$self->getCronIntervals(),
|
||||
});
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -931,11 +931,11 @@ sub duplicate {
|
|||
my $i18n = WebGUI::International->new($self->session, "Asset_Collaboration");
|
||||
my $newCron = WebGUI::Workflow::Cron->create($self->session, {
|
||||
title=>$self->getTitle." ".$i18n->get("mail"),
|
||||
minuteOfHour=>"*/".($self->get("getMailInterval")/60),
|
||||
className=>(ref $self),
|
||||
methodName=>"new",
|
||||
parameters=>$self->getId,
|
||||
workflowId=>"csworkflow000000000001"
|
||||
workflowId=>"csworkflow000000000001",
|
||||
$self->getCronIntervals(),
|
||||
});
|
||||
$newAsset->update({getMailCronId=>$newCron->getId});
|
||||
$newAsset->incrementReplies('','');
|
||||
|
|
@ -959,6 +959,87 @@ sub duplicateBranch {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getCronIntervals
|
||||
|
||||
Translate the settings for getCsMailInterval into options for Spectre's Cron,
|
||||
minuteOfHour, hourOfDay and so on.
|
||||
|
||||
Returns a hash of those options that can be folded into a hash of property settings for the
|
||||
Cron job.
|
||||
|
||||
=cut
|
||||
|
||||
sub getCronIntervals {
|
||||
my $self = shift;
|
||||
my $interval = $self->get('getMailInterval');
|
||||
##My kingdom for a switch statement!
|
||||
if ($interval eq 'every minute') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/1',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every other minute') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/2',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 5 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/5',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 10 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/10',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 15 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/15',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 20 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/20',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 30 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/30',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every hour') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '0',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every other hour') {
|
||||
return(
|
||||
hourOfDay => '*/2',
|
||||
minuteOfHour => '0',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'once per day') {
|
||||
return(
|
||||
hourOfDay => '7',
|
||||
minuteOfHour => '0',
|
||||
);
|
||||
}
|
||||
return(
|
||||
minuteOfHour => '*/10',
|
||||
);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getHelpers ( )
|
||||
|
||||
Add the collaboration-specific asset helpers
|
||||
|
|
@ -1282,6 +1363,35 @@ sub getViewTemplateVars {
|
|||
return \%var;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
=head2 groupIdView ( [newvalue] )
|
||||
|
||||
Override the existing accessor to update the subscription group if the value
|
||||
changes.
|
||||
|
||||
=cut
|
||||
|
||||
around groupIdView => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
my ( $newValue ) = @_;
|
||||
my $oldValue = $self->$orig;
|
||||
my $return = $self->$orig(@_);
|
||||
# Update the subscription group so if they can't see the collab, they don't get e-mailed
|
||||
if ( $newValue && $newValue != $oldValue ) {
|
||||
my $instance_data = {
|
||||
workflowId => 'xR-_GRRbjBojgLsFx3dEMA',
|
||||
className => 'WebGUI::Asset',
|
||||
methodName => 'newById',
|
||||
parameters => $self->getId,
|
||||
};
|
||||
my $instance = WebGUI::Workflow::Instance->create($self->session, $instance_data);
|
||||
$instance->start('skipRealtime');
|
||||
}
|
||||
return $return;
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 incrementReplies ( lastPostDate, lastPostId )
|
||||
|
|
@ -1586,7 +1696,6 @@ sub unsubscribe {
|
|||
$group->deleteUsers([$user->userId]);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view
|
||||
|
|
|
|||
|
|
@ -320,13 +320,17 @@ override purge => sub {
|
|||
|
||||
=head2 view
|
||||
|
||||
Render the dashboard.
|
||||
Render the dashboard. Of all the positions for content, position1 is reserved for hidden content
|
||||
or content to be placed. Deleting content causes it to go into position1.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my %vars = %{$self->get()};
|
||||
$vars{canEdit} = $self->canEdit;
|
||||
$vars{fullUrl} = $self->getUrl;
|
||||
|
||||
$self->session->style->setScript( $self->session->url->extras('yui/build/utilities/utilities.js'));
|
||||
|
||||
|
|
@ -356,60 +360,85 @@ sub view {
|
|||
|
||||
my @found;
|
||||
my $newStuff;
|
||||
my $showPerformance = $self->session->log->performanceLogger();
|
||||
my $user = $self->session->user;
|
||||
foreach my $position (@positions) {
|
||||
my @assets = split(",",$position);
|
||||
foreach my $asset (@assets) {
|
||||
foreach my $child (@{$children}) {
|
||||
CHILD: foreach my $child (@{$children}) {
|
||||
if ($asset eq $child->getId) {
|
||||
unless ($asset ~~ @hidden || !$child->canView) {
|
||||
$self->session->style->setRawHeadTags($child->getExtraHeadTags);
|
||||
$child->{_properties}{title} = $child->getTitle;
|
||||
$child->{_properties}{title} = $child->getShortcut->getTitle if (ref $child eq 'WebGUI::Asset::Shortcut');
|
||||
if ($i == 1 || $i > $numPositions) {
|
||||
push(@{$vars{"position1_loop"}},{
|
||||
id=>$child->getId,
|
||||
content=>'', #so things in the New Content bar don't display.
|
||||
dashletTitle=>$child->{_properties}{title},
|
||||
shortcutUrl=>$child->getUrl,
|
||||
canPersonalize=>$self->canPersonalize,
|
||||
showReloadIcon=>$child->{_properties}{showReloadIcon},
|
||||
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
|
||||
});
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
|
||||
} else {
|
||||
$child->prepareView;
|
||||
push(@{$vars{"position".$i."_loop"}},{
|
||||
id=>$child->getId,
|
||||
content=>$child->view,
|
||||
dashletTitle=>$child->{_properties}{title},
|
||||
shortcutUrl=>$child->getUrl,
|
||||
canPersonalize=>$self->canPersonalize,
|
||||
showReloadIcon=>$child->{_properties}{showReloadIcon},
|
||||
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
|
||||
});
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
}
|
||||
}
|
||||
push(@found, $child->getId);
|
||||
}
|
||||
##Filter based on visibility
|
||||
next CHILD unless $child->canView;
|
||||
next CHILD if isIn($asset, @hidden);
|
||||
##Detect child types
|
||||
my $is_shortcut = $child->isa('WebGUI::Asset::Shortcut');
|
||||
my $is_dashlet = $child->can('getOverrideFormDefinition');
|
||||
$self->session->style->setRawHeadTags($child->getExtraHeadTags);
|
||||
##Override the title for shortcuts
|
||||
if ($is_shortcut) {
|
||||
$child->{_properties}{title} = $child->getShortcut->getTitle;
|
||||
}
|
||||
##Fetch dashlet options from the database
|
||||
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $child->getId]);
|
||||
if (!($i == 1 || $i > $numPositions)) {
|
||||
$child->prepareView;
|
||||
}
|
||||
my $spot = $i > $numPositions ? 1 : $i;
|
||||
my $canMove = $self->canPersonalize && !$options->{isStatic};
|
||||
my $editFormUrl = ($is_shortcut && $child->getPrefsFieldToShow) ? $child->getUrl('func=getUserPrefsForm')
|
||||
: ($is_dashlet && $child->getOverrideFormDefinition) ? $self->getUrl('func=customizeDashlet;dashletAssetId='.$child->getId)
|
||||
: ''
|
||||
;
|
||||
my $canEditUserPrefs = $user->isRegistered && $editFormUrl;
|
||||
|
||||
push(@{$vars{"position".$spot."_loop"}},{
|
||||
id => $child->getId,
|
||||
content => $child->view,
|
||||
dashletTitle => $child->get('title'),
|
||||
shortcutUrl => ($is_shortcut ? $child->getUrl : ''),
|
||||
editFormUrl => $editFormUrl,
|
||||
dashletUrl => ($is_dashlet ? $child->getUrl : ''),
|
||||
canDelete => $self->canPersonalize && !$options->{isRequired},
|
||||
canMove => $canMove,
|
||||
canPersonalize => $self->canPersonalize,
|
||||
showReloadIcon => $is_shortcut && $child->get('showReloadIcon'),
|
||||
canEditUserPrefs => $canEditUserPrefs,
|
||||
});
|
||||
if ($canMove) {
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
# deal with unplaced children
|
||||
# deal with unplaced children, they go into position 1
|
||||
foreach my $child (@{$children}) {
|
||||
unless ($child->getId ~~ @found || $child->getId ~~ @hidden) {
|
||||
if ($child->canView) {
|
||||
$child->{_properties}{title} = $child->getShortcut->title if (ref $child eq 'WebGUI::Asset::Shortcut');
|
||||
my $is_shortcut = $child->isa('WebGUI::Asset::Shortcut');
|
||||
my $is_dashlet = $child->can('getOverrideFormDefinition');
|
||||
my $title = $child->{_properties}{title} = $is_shortcut ? $child->getShortcut->getTitle : $child->getTitle;
|
||||
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $child->getId]);
|
||||
my $canMove = $self->canPersonalize && !$options->{isStatic};
|
||||
my $editFormUrl = ($is_shortcut && $child->getPrefFieldsToShow) ? $child->getUrl('func=getUserPrefsForm')
|
||||
: ($is_dashlet && $child->getOverrideFormDefinition) ? $self->getUrl('func=customizeDashlet;dashletAssetId='.$child->getId)
|
||||
: ''
|
||||
;
|
||||
my $canEditUserPrefs = $user->isRegistered && $editFormUrl;
|
||||
push(@{$vars{"position1_loop"}},{
|
||||
id=>$child->getId,
|
||||
content=>'',
|
||||
dashletTitle=>$child->getTitle,
|
||||
shortcutUrl=>$child->getUrl,
|
||||
showReloadIcon=>$child->{_properties}{showReloadIcon},
|
||||
canPersonalize=>$self->canPersonalize,
|
||||
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
|
||||
id => $child->getId,
|
||||
content => '',
|
||||
dashletTitle => $title,
|
||||
shortcutUrl => ($is_shortcut ? $child->getUrl : ''),
|
||||
editFormUrl => $editFormUrl,
|
||||
dashletUrl => ($is_dashlet ? $child->getUrl : ''),
|
||||
canDelete => $self->canPersonalize && !$options->{isRequired},
|
||||
canMove => $canMove,
|
||||
canPersonalize => $self->canPersonalize,
|
||||
showReloadIcon => $is_shortcut && $child->{_properties}{showReloadIcon},
|
||||
canEditUserPrefs => $canEditUserPrefs,
|
||||
});
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
}
|
||||
|
|
@ -418,9 +447,9 @@ sub view {
|
|||
$vars{showAdmin} = ($self->session->isAdminOn && $self->canEdit);
|
||||
$vars{"dragger.init"} = '
|
||||
<script type="text/javascript">
|
||||
dragable_init("'.$self->getUrl.'");
|
||||
var available_dashlets= new Array();
|
||||
'.$newStuff.'
|
||||
dragable_init("'.$self->getUrl.'");
|
||||
</script>
|
||||
';
|
||||
return $self->processTemplate(\%vars, $templateId);
|
||||
|
|
@ -428,6 +457,128 @@ sub view {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_customizeDashlet
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_customizeDashlet {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($session->user->isRegistered);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $dashlet = WebGUI::Asset->newById($session, $dashletAssetId);
|
||||
return $session->privilege->insufficient() unless ($dashlet && $dashlet->canView && $dashlet->can('getOverrideFormDefinition'));
|
||||
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Dashboard');
|
||||
|
||||
my $form = $session->form;
|
||||
my $html_form = WebGUI::HTMLForm->new($session, action => $self->getUrl, method => 'POST', );
|
||||
$html_form->hidden(name => 'func', value => 'customizeDashletSave', );
|
||||
$html_form->hidden(name => 'dashletAssetId', value => $dashletAssetId, );
|
||||
$html_form->readOnly(name => $i18n->get(), value => $dashlet->getTitle, );
|
||||
|
||||
my $overrides = $dashlet->fetchUserOverrides($self->getId);
|
||||
my @dashlet_properties = $dashlet->getOverrideFormDefinition;
|
||||
foreach my $property (@dashlet_properties) {
|
||||
my %properties = %{ $property };
|
||||
$properties{value} = $overrides->{$property->{name}} || $dashlet->get($property->{name});
|
||||
$html_form->dynamicField(%properties);
|
||||
}
|
||||
|
||||
$html_form->submit();
|
||||
return $html_form->print;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_customizeDashletSave
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_customizeDashletSave {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($session->user->isRegistered);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $dashlet = WebGUI::Asset->newById($session, $dashletAssetId);
|
||||
return $session->privilege->insufficient() unless ($dashlet && $dashlet->canView && $dashlet->can('getOverrideFormDefinition'));
|
||||
my $overrides = {};
|
||||
my @dashlet_properties = $dashlet->getOverrideFormDefinition;
|
||||
my $form = $session->form;
|
||||
foreach my $property (@dashlet_properties) {
|
||||
my $value = $form->process($property->{name}, $property->{fieldType}, $property->{value});
|
||||
$overrides->{$property->{name}} = $value;
|
||||
}
|
||||
$dashlet->storeUserOverrides($self->getId, $overrides);
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
##-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editDashlet
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editDashlet {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($self->canEdit);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $dashlet = WebGUI::Asset->newById($session, $dashletAssetId);
|
||||
return $session->privilege->insufficient() unless ($dashletAssetId);
|
||||
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Dashboard');
|
||||
|
||||
my $form = $session->form;
|
||||
my $html_form = WebGUI::HTMLForm->new($session, action => $self->getUrl, method => 'POST', );
|
||||
$html_form->hidden(name => 'func', value => 'editDashletSave', );
|
||||
$html_form->hidden(name => 'dashletAssetId', value => $dashletAssetId, );
|
||||
$html_form->readOnly(name => $i18n->get(), value => $dashlet->getTitle, );
|
||||
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $dashletAssetId]);
|
||||
$html_form->yesNo(
|
||||
name => 'isStatic',
|
||||
label => $i18n->get('Is static'),
|
||||
hoverHelp => $i18n->get('Is static help'),
|
||||
value => $form->get('isStatic') || $options->{isStatic},
|
||||
);
|
||||
$html_form->yesNo(
|
||||
name => 'isRequired',
|
||||
label => $i18n->get('Is required'),
|
||||
hoverHelp => $i18n->get('Is required help'),
|
||||
value => $form->get('isRequired') || $options->{isRequired},
|
||||
);
|
||||
$html_form->submit();
|
||||
return $html_form->print;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editDashletSave
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editDashletSave {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($self->canEdit);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $isStatic = $session->form->get('isStatic', 'yesNo');
|
||||
my $isRequired = $session->form->get('isRequired', 'yesNo');
|
||||
$session->db->write('DELETE FROM Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?',[$self->getId, $dashletAssetId, ]);
|
||||
$session->db->write('INSERT INTO Dashboard_dashlets (dashboardAssetId, dashletAssetId, isStatic, isRequired) VALUES (?,?,?,?)', [$self->getId, $dashletAssetId, $isStatic, $isRequired, ]);
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_setContentPositions
|
||||
|
||||
Web method for saving the positions of dashlets in the dashboard.
|
||||
|
|
|
|||
|
|
@ -320,12 +320,13 @@ sub _fieldAdminIcons {
|
|||
my $self = shift;
|
||||
my $fieldName = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
|
||||
my $mode = ";mode=" . $self->currentView;
|
||||
my $output;
|
||||
$output = $self->session->icon->delete('func=deleteFieldConfirm;fieldName='.$fieldName,$self->url,$i18n->get(19))
|
||||
$output = $self->session->icon->delete('func=deleteFieldConfirm;fieldName='.$fieldName.$mode,$self->get("url"),$i18n->get(19))
|
||||
unless $self->getFieldConfig($fieldName)->{isMailField};
|
||||
$output .= $self->session->icon->edit('func=editField;fieldName='.$fieldName,$self->url)
|
||||
. $self->session->icon->moveUp('func=moveFieldUp;fieldName='.$fieldName,$self->url)
|
||||
. $self->session->icon->moveDown('func=moveFieldDown;fieldName='.$fieldName,$self->url);
|
||||
$output .= $self->session->icon->edit('func=editField;fieldName='.$fieldName.$mode,$self->get("url"))
|
||||
. $self->session->icon->moveUp('func=moveFieldUp;fieldName='.$fieldName.$mode,$self->get("url"))
|
||||
. $self->session->icon->moveDown('func=moveFieldDown;fieldName='.$fieldName.$mode,$self->get("url"));
|
||||
return $output;
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -784,6 +785,7 @@ sub getListTemplateVars {
|
|||
'field.label' => $fieldConfig->{$_}{label},
|
||||
'field.isMailField' => $fieldConfig->{$_}{isMailField},
|
||||
'field.type' => $fieldConfig->{$_}{type},
|
||||
"field.controls" => $self->_fieldAdminIcons($fieldConfig->{$_}{name}),
|
||||
}
|
||||
} @{ $self->getFieldOrder };
|
||||
$var->{field_loop} = \@fieldLoop;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ Overridden to check the revision dates of children as well
|
|||
|
||||
sub getContentLastModified {
|
||||
my $self = shift;
|
||||
my $mtime = $self->revisionDate;
|
||||
my $mtime = $self->get("lastModified");
|
||||
my $childIter = $self->getLineageIterator(["children"]);
|
||||
while ( 1 ) {
|
||||
my $child;
|
||||
|
|
@ -119,6 +119,60 @@ sub getContentLastModified {
|
|||
return $mtime;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getContentLastModifiedBy
|
||||
|
||||
Overridden to check the updated dates of children as well
|
||||
|
||||
=cut
|
||||
|
||||
sub getContentLastModifiedBy {
|
||||
my $self = shift;
|
||||
my $mtime = $self->SUPER::getContentLastModified;
|
||||
my $userId = $self->get('revisedBy');
|
||||
my $childIter = $self->getLineageIterator(["children"]);
|
||||
while ( 1 ) {
|
||||
my $child;
|
||||
eval { $child = $childIter->() };
|
||||
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
|
||||
$self->session->log->error($x->full_message);
|
||||
next;
|
||||
}
|
||||
last unless $child;
|
||||
my $child_mtime = $child->getContentLastModified;
|
||||
if ($child_mtime > $mtime) {
|
||||
$mtime = $child_mtime;
|
||||
$userId = $child->get("revisedBy");
|
||||
}
|
||||
}
|
||||
return $userId;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getEditForm ( )
|
||||
|
||||
Returns the TabForm object that will be used in generating the edit page for this asset.
|
||||
|
||||
=cut
|
||||
|
||||
sub getEditForm {
|
||||
my $self = shift;
|
||||
my $tabform = $self->SUPER::getEditForm();
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Folder");
|
||||
if ($self->get("assetId") eq "new") {
|
||||
$tabform->getTab("properties")->whatNext(
|
||||
-options=>{
|
||||
view=>$i18n->get(823),
|
||||
"viewParent"=>$i18n->get(847)
|
||||
},
|
||||
-value=>"view"
|
||||
);
|
||||
}
|
||||
return $tabform;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplateVars ( )
|
||||
|
|
|
|||
|
|
@ -363,6 +363,36 @@ override getContentLastModified => sub {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getContentLastModifiedBy
|
||||
|
||||
Extend the base class to include the userid of the person that made last modification.
|
||||
|
||||
=cut
|
||||
|
||||
sub getContentLastModifiedBy {
|
||||
my $self = shift;
|
||||
my $mtime = $self->SUPER::getContentLastModified;
|
||||
my $userId = $self->get('revisedBy');
|
||||
my $childIter = $self->getLineageIterator(["children"],{excludeClasses=>['WebGUI::Asset::Wobject::Layout']});
|
||||
while ( 1 ) {
|
||||
my $child;
|
||||
eval { $child = $childIter->() };
|
||||
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
|
||||
$self->session->log->error($x->full_message);
|
||||
next;
|
||||
}
|
||||
last unless $child;
|
||||
my $child_mtime = $child->getContentLastModified;
|
||||
if ($child_mtime > $mtime) {
|
||||
$mtime = $child_mtime;
|
||||
$userId = $child->get("revisedBy");
|
||||
}
|
||||
}
|
||||
return $userId;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
Extend the base method to handle caching and ad rotation.
|
||||
|
|
|
|||
|
|
@ -371,7 +371,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);
|
||||
|
|
@ -379,6 +381,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
|
||||
|
||||
|
||||
|
|
@ -392,9 +398,9 @@ ENDHTML
|
|||
for my $pointId ( @{$pointIds} ) {
|
||||
my $point = WebGUI::Asset->newById( $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;
|
||||
}
|
||||
|
|
@ -416,11 +422,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 ) ) {
|
||||
|
|
|
|||
|
|
@ -175,30 +175,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->newById($session, $data->{assetId});
|
||||
if (defined $asset) {
|
||||
my $properties = $asset->get;
|
||||
if ($self->useContainers) {
|
||||
$properties->{url} = $asset->isa('WebGUI::Asset::Post::Thread') ? $asset->getCSLinkUrl()
|
||||
: $asset->getContainer->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;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use Number::Format ();
|
|||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
extends 'WebGUI::Asset::Wobject';
|
||||
with 'WebGUI::Role::Asset::Dashlet';
|
||||
define tableName => 'StockData';
|
||||
define icon => 'stockData.gif';
|
||||
define assetName => ["assetName", 'Asset_StockData'];
|
||||
|
|
@ -45,6 +46,7 @@ property defaultStocks => (
|
|||
tab => 'properties',
|
||||
label => ["default_stock_label", 'Asset_StockData'],
|
||||
hoverHelp => ["default_stock_label_description", 'Asset_StockData'],
|
||||
dashletOverridable => 1,
|
||||
);
|
||||
property source => (
|
||||
fieldType => "selectList",
|
||||
|
|
@ -208,9 +210,12 @@ sub _convertToEpoch {
|
|||
if($time =~ m/pm/i) {
|
||||
$hour += 12;
|
||||
}
|
||||
$hour ||= 0;
|
||||
$hour = $self->_appendZero($hour);
|
||||
$minute ||= 0;
|
||||
$minute = $self->_appendZero($minute);
|
||||
return $self->session->datetime->humanToEpoch("$year-$month-$day $hour:$minute:00");
|
||||
my $epoch = eval {$self->session->datetime->humanToEpoch("$year-$month-$day $hour:$minute:00")};
|
||||
return $epoch;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -226,21 +231,45 @@ List of stock symbols to find passed in as an array reference. Stock symbols sh
|
|||
=cut
|
||||
|
||||
sub _getStocks {
|
||||
my $self = shift;
|
||||
my $stocks = $_[0];
|
||||
my $self = shift;
|
||||
my $stocks = $_[0];
|
||||
my $session = $self->session;
|
||||
|
||||
# Create a new Finance::Quote object
|
||||
my $q = Finance::Quote->new;
|
||||
# Disable failover if specified
|
||||
unless ($self->failover) {
|
||||
$q->failover(0);
|
||||
}
|
||||
# Create a new Finance::Quote object
|
||||
my $q = Finance::Quote->new;
|
||||
# Disable failover if specified
|
||||
unless ($self->failover) {
|
||||
$q->failover(0);
|
||||
}
|
||||
# Hardcoded timeout for now.
|
||||
$q->timeout(15);
|
||||
|
||||
# Hardcoded timeout for now.
|
||||
$q->timeout(15);
|
||||
my $source = $self->source;
|
||||
my %stocks = ();
|
||||
my @stocks_to_fetch = ();
|
||||
STOCK: foreach my $stock (@{$stocks}) {
|
||||
$stock = uc $stock;
|
||||
my $value = $session->cache->get( join "", $self->getId, $source, $stock );
|
||||
if ($value) {
|
||||
%stocks = (%stocks, %{ $value });
|
||||
}
|
||||
else {
|
||||
push @stocks_to_fetch, $stock;
|
||||
}
|
||||
}
|
||||
|
||||
# Fetch the stock information and return the results
|
||||
return $q->fetch($self->source,@{$stocks});
|
||||
# Fetch the information for uncached stocks, cache them individually, and build the composite data.
|
||||
my %new_stocks = $q->fetch($source, @stocks_to_fetch);
|
||||
foreach my $stock (@stocks_to_fetch) {
|
||||
$stock = uc $stock;
|
||||
my @stock_keys = grep { /$stock\b/ } keys %new_stocks;
|
||||
my %slice;
|
||||
@slice{ @stock_keys } = @new_stocks{ @stock_keys };
|
||||
$slice{$stock,'last_fetch'} = time();
|
||||
$session->cache->set( join( "", $self->getId, $source, $stock ), \%slice, $self->get('cacheTimeout') );
|
||||
%stocks = (%stocks, %slice);
|
||||
}
|
||||
return \%stocks;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -330,7 +359,8 @@ sub view {
|
|||
$var->{'stock.display.url'} = $self->getUrl("func=displayStock;symbol=");
|
||||
|
||||
#Build list of stocks as an array
|
||||
my $defaults = $self->defaultStocks;
|
||||
my $overrides = $self->fetchUserOverrides($self->getParent->getId);
|
||||
my $defaults = $overrides->{defaultStocks} || $self->defaultStocks;
|
||||
#replace any windows newlines
|
||||
$defaults =~ s/\r//;
|
||||
my @array = split("\n",$defaults);
|
||||
|
|
|
|||
|
|
@ -171,38 +171,48 @@ sub viewTemplateVariables {
|
|||
rowsPerPage => $numberOfStories,
|
||||
});
|
||||
my $storyIds = $p->getPageData();
|
||||
$var->{story_loop} = [];
|
||||
|
||||
my $icon = $session->icon;
|
||||
my $userUiLevel = $session->user->get("uiLevel");
|
||||
my $uiLevels = $session->config->get('assetToolbarUiLevel');
|
||||
my $i18n = WebGUI::International->new($session);
|
||||
my $url = $session->url;
|
||||
|
||||
##Only build objects for the assets that we need
|
||||
STORY: foreach my $storyId (@{ $storyIds }) {
|
||||
my $story = WebGUI::Asset->newById($session, $storyId->{assetId}, $storyId->{revisionDate});
|
||||
next STORY unless $story;
|
||||
my $storyVars = {
|
||||
url => ( $exporting
|
||||
? $story->getUrl
|
||||
: $session->url->append($self->getUrl, 'func=viewStory;assetId='.$storyId->{assetId}) ),
|
||||
title => $story->getTitle,
|
||||
creationDate => $story->creationDate,
|
||||
};
|
||||
if ($story->canEdit && $userUiLevel >= $uiLevels->{delete} && !$exporting) {
|
||||
$storyVars->{deleteIcon} = $icon->delete('func=delete', $story->url, $i18n->get(43));
|
||||
$var->{story_loop} = [
|
||||
map {
|
||||
my $v = $_->viewTemplateVariables;
|
||||
if ($exporting) {
|
||||
$v->{url} = $_->getUrl;
|
||||
}
|
||||
else {
|
||||
my $params = "func=viewStory;assetId=$v->{assetId}";
|
||||
my $rawUrl = $v->{url};
|
||||
$v->{url} = $url->append($self->getUrl, $params);
|
||||
if ($v->{canEdit}) {
|
||||
if ($userUiLevel >= $uiLevels->{delete}) {
|
||||
$v->{deleteIcon} = $icon->delete('func=delete', $rawUrl, $i18n->get(43));
|
||||
}
|
||||
if ($userUiLevel >= $uiLevels->{edit}) {
|
||||
$v->{editIcon} = $icon->edit('func=edit', $rawUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
$v;
|
||||
}
|
||||
if ($story->canEdit && $userUiLevel >= $uiLevels->{edit} && !$exporting) {
|
||||
$storyVars->{editIcon} = $icon->edit('func=edit', $story->url);
|
||||
grep { $_ }
|
||||
map {
|
||||
WebGUI::Asset->newById( $session, $_->{assetId} )
|
||||
}
|
||||
push @{$var->{story_loop}}, $storyVars;
|
||||
}
|
||||
@{ $storyIds }
|
||||
];
|
||||
|
||||
if (@{ $storyIds }) {
|
||||
my $topStoryData = $storyIds->[0];
|
||||
my $topStoryVars = shift @{ $var->{story_loop} };
|
||||
##Note, this could have saved from the loop above, but this looks more clean and encapsulated to me.
|
||||
my $topStory = WebGUI::Asset->newById($session, $topStoryData->{assetId}, $topStoryData->{revisionDate});
|
||||
$var->{topStory} = $topStoryVars;
|
||||
$var->{topStoryTitle} = $topStory->getTitle;
|
||||
$var->{topStorySubtitle} = $topStory->subtitle;
|
||||
$var->{topStoryUrl} = $session->url->append($self->getUrl, 'func=viewStory;assetId='.$topStoryData->{assetId}),
|
||||
|
|
|
|||
|
|
@ -2336,12 +2336,12 @@ sub www_viewStatisticalOverview {
|
|||
}
|
||||
}
|
||||
else{
|
||||
my $responses = $db->read('select value,answerComment from Survey_tempReport'
|
||||
my $responses = $db->read('select answerValue,answerComment from Survey_tempReport'
|
||||
. ' where sectionNumber=? and questionNumber=?',
|
||||
[$sectionIndex,$questionIndex]);
|
||||
while (my $response = $responses->hashRef) {
|
||||
push @answerloop,{
|
||||
'answer_value' =>$response->{value},
|
||||
'answer_value' =>$response->{answerValue},
|
||||
'answer_comment' =>$response->{answerComment}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ has '+uiLevel' => (
|
|||
with 'WebGUI::Role::Asset::RssFeed';
|
||||
use WebGUI::Macro;
|
||||
use XML::FeedPP;
|
||||
use XML::FeedPP::MediaRSS;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -252,6 +253,7 @@ A reference to an XML::FeedPP object.
|
|||
|
||||
sub getTemplateVariables {
|
||||
my ($self, $feed) = @_;
|
||||
my $media = XML::FeedPP::MediaRSS->new($feed);
|
||||
my @items = $feed->get_item;
|
||||
my %var;
|
||||
$var{channel_title} = WebGUI::HTML::filter(scalar $feed->title, 'javascript');
|
||||
|
|
@ -268,6 +270,7 @@ sub getTemplateVariables {
|
|||
$var{channel_image_height} = WebGUI::HTML::filter($image[5], 'javascript');
|
||||
foreach my $object (@items) {
|
||||
my %item;
|
||||
$item{media} = [ map { { %$_ } } $media->for_item($object) ];
|
||||
$item{title} = WebGUI::HTML::filter(scalar $object->title, 'javascript');
|
||||
$item{date} = WebGUI::HTML::filter(scalar $object->get_pubDate_epoch, 'javascript');
|
||||
$item{category} = WebGUI::HTML::filter(scalar $object->category, 'javascript');
|
||||
|
|
|
|||
|
|
@ -260,6 +260,24 @@ sub badOtherThing {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=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 ( )
|
||||
|
||||
Duplicates a Thingy, including the definitions of the Things in this Thingy and their fields.
|
||||
|
|
@ -346,6 +364,8 @@ sub duplicateThing {
|
|||
$self->addField($field,0);
|
||||
}
|
||||
|
||||
$thingProperties->{thingId} = $newThingId;
|
||||
$self->indexThing($thingProperties);
|
||||
return $newThingId;
|
||||
|
||||
}
|
||||
|
|
@ -397,6 +417,7 @@ sub deleteField {
|
|||
$db->write("ALTER TABLE ".$db->quote_identifier("Thingy_".$thingId)." DROP "
|
||||
.$db->quote_identifier("field_".$fieldId));
|
||||
}
|
||||
$self->reindexThings;
|
||||
$log->info("Deleted field: $fieldId in thing: $thingId.");
|
||||
return undef;
|
||||
}
|
||||
|
|
@ -433,7 +454,7 @@ sub copyThingData {
|
|||
my @storage_field_ids = ();
|
||||
##Check to see if any of them are File or Image
|
||||
foreach my $field (@{ $fields }) {
|
||||
if ($field->{fieldType} eq 'File' or $field->{fieldType} eq 'Image') {
|
||||
if ($self->field_isa($field->{fieldType}, 'WebGUI::Form::File')) {
|
||||
push @storage_field_ids, $field->{fieldId};
|
||||
}
|
||||
}
|
||||
|
|
@ -447,6 +468,7 @@ sub copyThingData {
|
|||
}
|
||||
##Update the copy
|
||||
$self->setCollateral("Thingy_".$thingId, "thingDataId", $origCollateral, 0, 0);
|
||||
$self->indexThingData($thingId, $origCollateral);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
|
@ -491,7 +513,7 @@ sub deleteThingData {
|
|||
my @storage_field_ids = ();
|
||||
##Check to see if any of them are File or Image
|
||||
foreach my $field (@{ $fields }) {
|
||||
if ($field->{fieldType} eq 'File' or $field->{fieldType} eq 'Image') {
|
||||
if ($self->field_isa($field->{fieldType}, 'WebGUI::Form::File')) {
|
||||
push @storage_field_ids, $field->{fieldId};
|
||||
}
|
||||
}
|
||||
|
|
@ -501,11 +523,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.
|
||||
|
|
@ -528,6 +569,7 @@ sub deleteThing {
|
|||
$session->db->write("drop table if exists ".$session->db->quote_identifier("Thingy_".$thingId));
|
||||
|
||||
$log->info("Deleted thing: $thingId.");
|
||||
$self->deleteThingIndex($thingId);
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
|
@ -535,7 +577,9 @@ sub deleteThing {
|
|||
|
||||
=head2 editThingDataSave ( )
|
||||
|
||||
Saves a row of thing data and triggers the appropriate workflow triggers.
|
||||
Saves a row of thing data and triggers the appropriate workflow triggers. Returns the id of the row created in
|
||||
the database, and an array reference of errors from required fields and other sources. In there are errors, no data
|
||||
is saved in the database, and the id returned in the empty string.
|
||||
|
||||
=head3 thingId
|
||||
|
||||
|
|
@ -579,8 +623,7 @@ sub editThingDataSave {
|
|||
lastUpDated=>time(),
|
||||
);
|
||||
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId = ? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
my $fieldName = 'field_'.$field->{fieldId};
|
||||
my $fieldValue;
|
||||
|
|
@ -589,7 +632,7 @@ sub editThingDataSave {
|
|||
$fieldType = "" if ($fieldType =~ m/^otherThing/x);
|
||||
# Modify the defaultValue for certain field types. For most types we want to use
|
||||
# the default in the database, for these we want the last known value for this thingData
|
||||
if ( $fieldType eq "File" || $fieldType eq "Image" ) {
|
||||
if ($self->field_isa($fieldType, 'WebGUI::Form::File')) {
|
||||
$field->{ defaultValue } = $thingData{ "field_" . $field->{ fieldId } };
|
||||
}
|
||||
$fieldValue = $thingData->{$fieldName} || $session->form->process($fieldName,$fieldType,$field->{defaultValue},$field);
|
||||
|
|
@ -598,7 +641,6 @@ sub editThingDataSave {
|
|||
push (@errors,{
|
||||
"error_message"=>$field->{label}." ".$i18n->get('is required error').".",
|
||||
});
|
||||
#$hadErrors = 1;
|
||||
}
|
||||
if ($field->{status} eq "hidden") {
|
||||
$fieldValue = $field->{defaultValue};
|
||||
|
|
@ -611,7 +653,11 @@ sub editThingDataSave {
|
|||
$thingData{$fieldName} = $fieldValue;
|
||||
}
|
||||
|
||||
if (@errors) {
|
||||
return ('', \@errors);
|
||||
}
|
||||
$newThingDataId = $self->setCollateral("Thingy_".$thingId,"thingDataId",\%thingData,0,0);
|
||||
$self->indexThingData($thingId, \%thingData);
|
||||
|
||||
# trigger workflow
|
||||
if($thingDataId eq "new"){
|
||||
|
|
@ -653,6 +699,33 @@ override exportAssetData => sub {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 field_isa ( $fieldType, $isa )
|
||||
|
||||
Builds a form field and does an isa check on it.
|
||||
|
||||
=head2 $fieldType
|
||||
|
||||
This is the type of a field to build. It will have 'WebGUI::Form' prepended to it to form
|
||||
a complete classname.
|
||||
|
||||
=head2 $isa
|
||||
|
||||
This is the class name to check against.
|
||||
|
||||
=cut
|
||||
|
||||
sub field_isa {
|
||||
my $self = shift;
|
||||
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));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 _getDbDataType ( fieldType )
|
||||
|
||||
returns the database data type for a field based on the fieldType.
|
||||
|
|
@ -905,6 +978,23 @@ sub getEditFieldForm {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFields ( $thingId )
|
||||
|
||||
Returns a result set with all the fields in a thing in this Thingy.
|
||||
|
||||
=head3 $thingId
|
||||
|
||||
The GUID for a thing
|
||||
|
||||
=cut
|
||||
|
||||
sub getFields {
|
||||
my ($self, $thingId) = @_;
|
||||
return $self->session->db->read("select * from Thingy_fields where assetId=? and thingId=? order by sequenceNumber",[$self->getId, $thingId]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFieldValue ( value, field )
|
||||
|
||||
Processes the field value for date(Time) fields and Other Thing fields.
|
||||
|
|
@ -1153,6 +1243,29 @@ sub getThing {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getThingUrl ( thingData )
|
||||
|
||||
Returns a the URL to view a Thing in this Thingy
|
||||
|
||||
=head3 thingData
|
||||
|
||||
A hashref of properties for the Thing, as returned by getThing. This is needed to extract the defaultView,
|
||||
to get the right func, and the thingId.
|
||||
|
||||
=cut
|
||||
|
||||
sub getThingUrl {
|
||||
my ($self, $thing) = @_;
|
||||
if ($thing->{defaultView} eq "addThing") {
|
||||
return 'func=editThingData;thingId='.$thing->{thingId}.';thingDataId=new';
|
||||
}
|
||||
else{
|
||||
return 'func=search;thingId='.$thing->{thingId};
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getViewThingVars ( )
|
||||
|
||||
Returns the field values of a thing instance and the title for its view screen in a tmpl var hashref.
|
||||
|
|
@ -1171,8 +1284,7 @@ sub getViewThingVars {
|
|||
." where thingDataId = ?",[$thingDataId]);
|
||||
|
||||
if (%thingData) {
|
||||
my $fields = $db->read('select * from Thingy_fields where assetId = ? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
my $fields = $self->getFields($thingId);
|
||||
while (my %field = $fields->hash) {
|
||||
next unless ($field{display} eq '1');
|
||||
my $hidden = ($field{status} eq "hidden" && !$self->session->isAdminOn);
|
||||
|
|
@ -1207,6 +1319,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;
|
||||
|
|
@ -1314,7 +1427,7 @@ sub importAssetCollateralData {
|
|||
push(@importThings,$thing->{thingId});
|
||||
my ($thingIdExists) = $session->db->quickArray("select thingId from Thingy_things where thingId = ?",
|
||||
[$thing->{thingId}]);
|
||||
if ($assetExists && $thingIdExists){
|
||||
if ($thingIdExists){
|
||||
# update existing thing
|
||||
$log->info("Updating Thing, label: ".$thing->{label}.", id: ".$thing->{thingId});
|
||||
$self->setCollateral("Thingy_things","thingId",$thing,0,0);
|
||||
|
|
@ -1323,6 +1436,7 @@ sub importAssetCollateralData {
|
|||
# add new thing
|
||||
$self->addThing($thing,1);
|
||||
}
|
||||
$self->indexThing($thing);
|
||||
}
|
||||
# delete deleted things
|
||||
my $thingsInDatabase = $self->getThings;
|
||||
|
|
@ -1338,7 +1452,7 @@ sub importAssetCollateralData {
|
|||
push(@importFields,$field->{fieldId});
|
||||
my $dbDataType = $self->_getDbDataType($field->{fieldType});
|
||||
my ($fieldIdExists) = $session->db->quickArray("select fieldId from Thingy_fields where fieldId = ? and thingId = ? ",[$field->{fieldId},$field->{thingId}]);
|
||||
if ($assetExists && $fieldIdExists){
|
||||
if ($fieldIdExists){
|
||||
# update existing field
|
||||
$log->info("Updating Field, label: ".$field->{label}.", id: ".$field->{fieldId}.",seq :"
|
||||
.$field->{sequenceNumber});
|
||||
|
|
@ -1364,6 +1478,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 ( )
|
||||
|
|
@ -1412,6 +1646,30 @@ override purge => sub {
|
|||
return super();
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=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 )
|
||||
|
|
@ -1734,7 +1992,7 @@ sub www_editThing {
|
|||
exportMetaData=>undef,
|
||||
maxEntriesPerUser=>undef,
|
||||
);
|
||||
$thingId = $self->addThing(\%properties,0);
|
||||
$thingId = "new";
|
||||
}
|
||||
else{
|
||||
%properties = %{$self->getThing($thingId)};
|
||||
|
|
@ -1834,15 +2092,15 @@ sub www_editThing {
|
|||
." <td class='formDescription'>".$i18n->get('sort by label')."</td>\n"
|
||||
."</tr>\n";
|
||||
|
||||
$fields = $self->session->db->read('select * from Thingy_fields where assetId = '.$self->session->db->quote($self->getId).' and thingId = '.$self->session->db->quote($thingId).' order by sequenceNumber');
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
my $formElement;
|
||||
if ($field->{fieldType} eq "File"){
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
if ($field->{fieldType} eq "Image"){
|
||||
if ($self->field_isa($field->{fieldType}, 'WebGUI::Form::Image')) {
|
||||
$formElement = "<input type='file' name='image'>";
|
||||
}
|
||||
elsif ($self->field_isa($field->{fieldType}, 'WebGUI::Form::File')) {
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
else{
|
||||
$formElement = $self->getFormElement($field);
|
||||
}
|
||||
|
|
@ -1857,11 +2115,12 @@ sub www_editThing {
|
|||
."\n<table>\n<tr>\n"
|
||||
." <td style='width:100px;' valign='top' class='formDescription'>".$field->{label}."</td>\n"
|
||||
." <td style='width:370px;'>".$formElement."</td>\n"
|
||||
." <td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$self->session->url->page()
|
||||
."?func=editField;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}."')\" value='Edit' type='button'>"
|
||||
." <input onClick=\"editListItem('".$self->session->url->page()
|
||||
."?func=editField;copy=1;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}
|
||||
."','copy')\" value='Copy' type='button'>"
|
||||
." <td style='width:120px;' valign='top'> <input onClick=\"editListItem('"
|
||||
.$self->getUrl('func=editField;fieldId='.$field->{fieldId}.';thingId='.$thingId)
|
||||
."','".$field->{fieldId}."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
." <input onClick=\"editListItem('"
|
||||
.$self->getUrl('func=editField;copy=1;fieldId='.$field->{fieldId}.';thingId='.$thingId)
|
||||
."','".$field->{fieldId}."','copy')\" value='".$i18n->get('Copy','Icon')."' type='button'>"
|
||||
."<input onClick=\"deleteListItem('".$self->session->url->page()."','".$field->{fieldId}."','".$thingId."')\" "
|
||||
."value='".$i18n->get('Delete','Icon')."' type='button'></td>\n</tr>\n</table>\n</li>\n";
|
||||
|
||||
|
|
@ -2138,50 +2397,47 @@ database immediately.
|
|||
=cut
|
||||
|
||||
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");
|
||||
my $form = $self->session->form;
|
||||
my $thingId = $self->session->form->process("thingId");
|
||||
my $fields = $self->getFields($thingId);
|
||||
|
||||
$fields = $self->session->db->read('select * from Thingy_fields where assetId = '.$self->session->db->quote($self->getId).' and thingId = '.$self->session->db->quote($thingId).' order by sequenceNumber');
|
||||
|
||||
|
||||
$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);
|
||||
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"));
|
||||
}
|
||||
|
||||
|
||||
while (my $field = $fields->hashRef) {
|
||||
my $display = $self->session->form->process("display_".$field->{fieldId}) || 0;
|
||||
my $viewScreenTitle = $self->session->form->process("viewScreenTitle_".$field->{fieldId}) || 0;
|
||||
|
|
@ -2190,6 +2446,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;
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -2208,6 +2465,7 @@ sub www_editField {
|
|||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
$fieldId = $session->form->process("fieldId");
|
||||
$thingId = $session->form->process("thingId");
|
||||
|
||||
%properties = $session->db->quickHash("select * from Thingy_fields where thingId=? and fieldId=? and assetId=?",
|
||||
[$thingId,$fieldId,$self->getId]);
|
||||
if($session->form->process("copy")){
|
||||
|
|
@ -2248,6 +2506,8 @@ sub www_editFieldSave {
|
|||
if ($fieldType =~ m/^otherThing/){
|
||||
$defaultValue = $session->form->process("defaultFieldInThing");
|
||||
}
|
||||
|
||||
$thingId = $self->addThing({ thingId => 'new' },0) if $thingId eq 'new';
|
||||
|
||||
$fieldId = $session->form->process("fieldId");
|
||||
%properties = (
|
||||
|
|
@ -2285,12 +2545,12 @@ sub www_editFieldSave {
|
|||
$newFieldId = $self->setCollateral("Thingy_fields","fieldId",\%properties,1,1,"thingId",$thingId);
|
||||
}
|
||||
|
||||
if ($properties{fieldType} eq "File"){
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
elsif ($properties{fieldType} eq "Image"){
|
||||
if ($self->field_isa($properties{fieldType}, 'WebGUI::Form::Image')) {
|
||||
$formElement = "<input type='file' name='image'>";
|
||||
}
|
||||
elsif ($self->field_isa($properties{fieldType}, 'WebGUI::Form::File')) {
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
else{
|
||||
$formElement = $self->getFormElement(\%properties);
|
||||
}
|
||||
|
|
@ -2303,15 +2563,16 @@ sub www_editFieldSave {
|
|||
|
||||
$listItemHTML = "<table>\n<tr>\n<td style='width:100px;' valign='top' class='formDescription'>".$label."</td>\n"
|
||||
."<td style='width:370px;'>".$formElement."</td>\n"
|
||||
."<td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$session->url->page()
|
||||
."?func=editField;fieldId=".$newFieldId.";thingId=".$properties{thingId}."','".$newFieldId."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
."<td style='width:120px;' valign='top'> <input onClick=\"editListItem('"
|
||||
.$self->getUrl('func=editField;fieldId='.$newFieldId.';thingId='.$properties{thingId})
|
||||
."','".$newFieldId."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
."<input onClick=\"deleteListItem('".$session->url->page()."','".$newFieldId
|
||||
."','".$properties{thingId}."')\" value='".$i18n->get('Delete','Icon')."' type='button'></td>\n</tr>\n</table>";
|
||||
|
||||
# Make sure we send debug information along with the field.
|
||||
$log->preventDebugOutput;
|
||||
|
||||
$session->output->print($newFieldId.$listItemHTML);
|
||||
$session->output->print($thingId.$newFieldId.$listItemHTML);
|
||||
return "chunked";
|
||||
}
|
||||
|
||||
|
|
@ -2493,8 +2754,7 @@ sub editThingData {
|
|||
." where thingDataId = ?",[$thingDataId]);
|
||||
}
|
||||
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId = ? and thingId = ? order by sequenceNumber'
|
||||
,[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my %field = $fields->hash) {
|
||||
my $fieldName = 'field_'.$field{fieldId};
|
||||
$fieldValue = undef;
|
||||
|
|
@ -2656,13 +2916,13 @@ sub www_editThingDataSaveViaAjax {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_export ( )
|
||||
=head2 www_exportThing ( )
|
||||
|
||||
Exports search results as csv.
|
||||
Exports one entire Thing as CSV.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_export {
|
||||
sub www_exportThing {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my ($query,$sth,$out,$fields,@fields,$fileName,@fieldLabels);
|
||||
|
|
@ -2676,30 +2936,29 @@ sub www_export {
|
|||
$pb->start($i18n->get('export label').' '.$thingProperties->{label}, $session->url->extras('assets/thingy.gif'));
|
||||
$pb->update($i18n->get('Creating column headers'));
|
||||
my $tempStorage = WebGUI::Storage->createTemp($session);
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId =? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
if ($field->{displayInSearch}){
|
||||
push(@fields, {
|
||||
fieldId => $field->{fieldId},
|
||||
properties => $field,
|
||||
});
|
||||
push(@fieldLabels,$field->{label});
|
||||
}
|
||||
push(@fields, {
|
||||
fieldId => $field->{fieldId},
|
||||
properties => $field,
|
||||
});
|
||||
push(@fieldLabels,$field->{label});
|
||||
}
|
||||
|
||||
my @metaDataFields = ('thingDataId','dateCreated','createdById','updatedById','updatedByName','lastUpdated','ipAddress');
|
||||
if ($thingProperties->{exportMetaData}){
|
||||
push(@fieldLabels,@metaDataFields)
|
||||
}
|
||||
|
||||
$query = $session->cache->get("query_".$thingId);
|
||||
$query = 'select * from '.$session->db->dbh->quote_identifier("Thingy_".$thingId);
|
||||
$sth = $session->db->read($query);
|
||||
|
||||
### Loop through the returned structure and put it through Text::CSV
|
||||
# Column heads
|
||||
$self->session->log->warn("field labels: ". join ' ', @fieldLabels);
|
||||
my $csv_filename = 'export_'.$thingProperties->{label}.'.csv';
|
||||
$tempStorage->addFileFromScalar($csv_filename, WebGUI::Text::joinCSV(@fieldLabels));
|
||||
open my $CSV, '>', $tempStorage->getPath($csv_filename);
|
||||
print $CSV WebGUI::Text::joinCSV( @fieldLabels );
|
||||
|
||||
# Data lines
|
||||
$pb->update($i18n->get('Writing data'));
|
||||
|
|
@ -2712,11 +2971,11 @@ sub www_export {
|
|||
my $value = $self->getFieldValue($data->{"field_".$fieldId},$field->{properties},"%y-%m-%d","%y-%m-%d %j:%n:%s");
|
||||
push(@fieldValues, $value);
|
||||
}
|
||||
if ($thingProperties->{exportMetaData}) {
|
||||
foreach my $metaDataField (@metaDataFields){
|
||||
push(@fieldValues,$data->{$metaDataField});
|
||||
}
|
||||
}
|
||||
|
||||
if ($thingProperties->{exportMetaData}) {
|
||||
push(@fieldValues, @{$data}{@metaDataFields});
|
||||
}
|
||||
|
||||
print $CSV "\n".WebGUI::Text::joinCSV( @fieldValues );
|
||||
#if (! ++$rowCounter % 25) {
|
||||
$pb->update($i18n->get('Writing data'));
|
||||
|
|
@ -2724,7 +2983,7 @@ sub www_export {
|
|||
}
|
||||
close $CSV;
|
||||
|
||||
$pb->update(sprintf q|<a href="%s">%s</a>|, $self->getUrl, sprintf($i18n->get('Return to %s'), $thingProperties->{label}));
|
||||
$pb->update(sprintf q|<a href="%s">%s</a>|, $self->getUrl($self->getThingUrl($thingProperties)), sprintf($i18n->get('Return to %s'), $thingProperties->{label}));
|
||||
return $pb->finish($tempStorage->getUrl($csv_filename));
|
||||
}
|
||||
|
||||
|
|
@ -2758,8 +3017,7 @@ sub www_getThingViaAjax {
|
|||
$thingProperties->{groupIdView});
|
||||
|
||||
my @field_loop;
|
||||
my $fields = $session->db->read('select * from Thingy_fields where assetId=? and thingId=? order by sequenceNumber'
|
||||
,[$self->getId,$thingId]);
|
||||
my $fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
$field->{formElement} = $self->getFormElement($field);
|
||||
push(@field_loop,$field);
|
||||
|
|
@ -2992,8 +3250,7 @@ sub www_importForm {
|
|||
." <td>".$i18n->get("check duplicates label")."</td>"
|
||||
."</tr>";
|
||||
|
||||
$fields = $db->read('select label, fieldId from Thingy_fields where assetId =? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
$fieldOptions .= "<tr><td>".$field->{label}."</td><td>";
|
||||
$fieldOptions .= WebGUI::Form::Checkbox->new($self->session, {
|
||||
|
|
@ -3059,13 +3316,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);
|
||||
}
|
||||
|
|
@ -3240,13 +3491,12 @@ sub getSearchTemplateVars {
|
|||
my $session = $self->session;
|
||||
my $dbh = $session->db->dbh;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Thingy");
|
||||
my ($var,$url,$orderBy);
|
||||
my ($fields,@searchFields_loop,@displayInSearchFields_loop,$query,@constraints);
|
||||
my (@searchResult_loop,$searchResults,@searchResults,@displayInSearchFields,$paginatePage,$currentUrl,$p);
|
||||
my (@searchResult_loop,$searchResults,@searchResults,@displayInSearchFields,$paginatePage,$p);
|
||||
|
||||
$orderBy = $session->form->process("orderBy") || $thingProperties->{sortBy};
|
||||
$var = $self->get;
|
||||
$url = $self->getUrl;
|
||||
my $orderBy = $session->form->process("orderBy") || $thingProperties->{sortBy};
|
||||
my $var = $self->get;
|
||||
my $url = $self->getUrl;
|
||||
|
||||
$var->{canEditThings} = $self->canEdit;
|
||||
$var->{"addThing_url"} = $session->url->append($url, 'func=editThing;thingId=new');
|
||||
|
|
@ -3254,7 +3504,7 @@ sub getSearchTemplateVars {
|
|||
$var->{"thing_label"} = $thingProperties->{label};
|
||||
|
||||
if ($self->hasPrivileges($thingProperties->{groupIdExport})){
|
||||
$var->{"export_url"} = $session->url->append($url, 'func=export;thingId='.$thingId);
|
||||
$var->{"export_url"} = $session->url->append($url, 'func=exportThing;thingId='.$thingId);
|
||||
}
|
||||
if ($self->hasPrivileges($thingProperties->{groupIdImport})){
|
||||
$var->{"import_url"} = $session->url->append($url, 'func=importForm;thingId='.$thingId);
|
||||
|
|
@ -3265,21 +3515,17 @@ sub getSearchTemplateVars {
|
|||
$var->{searchScreenTitle} = $thingProperties->{searchScreenTitle};
|
||||
$var->{searchDescription} = $thingProperties->{searchDescription};
|
||||
|
||||
$currentUrl = $self->getUrl();
|
||||
foreach ($self->session->form->param) {
|
||||
# if we just saved data from an edit, we do not want to keep any of the params
|
||||
last if $_ eq 'func' and $self->session->form->process($_) eq 'editThingDataSave';
|
||||
|
||||
unless ($_ eq "pn" || $_ eq "op" || $_ =~ /identifier/xi || $_ =~ /password/xi || $_ eq "orderBy" ||
|
||||
$self->session->form->process($_) eq "") {
|
||||
$currentUrl = $self->session->url->append($currentUrl,$self->session->url->escape($_)
|
||||
.'='.$self->session->url->escape($self->session->form->process($_)));
|
||||
}
|
||||
my $currentUrl;
|
||||
my $func = $session->form->process('func');
|
||||
$func = 'search' if $func eq 'editThingDataSave';
|
||||
$currentUrl = $self->getUrl('func='.$func.';thingId='.$thingId);
|
||||
##Instead of blacklisting query params, they are whitelisted. List is currently empty.
|
||||
FORM: foreach my $form (qw//) {
|
||||
my $param = $session->form->process($form);
|
||||
next FORM unless defined $param;
|
||||
$currentUrl = $session->url->append($currentUrl, $form.'='.$param);
|
||||
}
|
||||
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId =
|
||||
'.$session->db->quote($self->getId).' and thingId = '.$session->db->quote($thingId).' order by
|
||||
sequenceNumber');
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
if ($field->{searchIn}){
|
||||
my $searchForm = $self->getFormPlugin($field, 1);
|
||||
|
|
@ -3332,7 +3578,8 @@ sequenceNumber');
|
|||
}
|
||||
$query .= join(", ",map {$dbh->quote_identifier('field_'.$_->{fieldId})} @displayInSearchFields);
|
||||
$query .= " from ".$dbh->quote_identifier("Thingy_".$thingId);
|
||||
if($session->form->process('func') eq 'search'){
|
||||
my $func = $session->form->process('func');
|
||||
if( $func eq 'search' || $func eq 'searchViaAjax' ){
|
||||
# Don't add constraints when the search screen is displayed as an 'after save' option.
|
||||
$query .= " where ".join(" and ",@constraints) if (scalar(@constraints) > 0);
|
||||
}
|
||||
|
|
@ -3345,9 +3592,6 @@ sequenceNumber');
|
|||
$noFields = 1;
|
||||
}
|
||||
|
||||
# store query in cache for thirty minutes
|
||||
$self->session->cache->set("query_".$thingId, $query, 30*60);
|
||||
|
||||
$paginatePage = $self->session->form->param('pn') || 1;
|
||||
$currentUrl = $self->session->url->append($currentUrl, "orderBy=".$orderBy) if $orderBy;
|
||||
|
||||
|
|
@ -3355,7 +3599,7 @@ sequenceNumber');
|
|||
|
||||
my @visibleResults;
|
||||
if (! $noFields) {
|
||||
my $sth = $self->session->db->read($query) if ! $noFields;
|
||||
my $sth = $self->session->db->read($query);
|
||||
while (my $result = $sth->hashRef){
|
||||
if ($self->canViewThingData($thingId,$result->{thingDataId})){
|
||||
push(@visibleResults,$result);
|
||||
|
|
@ -3532,6 +3776,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 {
|
||||
|
|
@ -3540,7 +3789,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");
|
||||
|
|
@ -3570,9 +3819,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->newById( $session, $templateId );
|
||||
}
|
||||
|
||||
return $self->processStyle(
|
||||
$self->processTemplate($var,$thingProperties->{viewTemplateId})
|
||||
);
|
||||
$self->processTemplate($var,$thingProperties->{viewTemplateId})
|
||||
) if !$template;
|
||||
|
||||
return $self->processTemplate($var,$template->getId,$template);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use WebGUI::International;
|
|||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
extends 'WebGUI::Asset::Wobject';
|
||||
with 'WebGUI::Role::Asset::Dashlet';
|
||||
define tableName => 'WeatherData';
|
||||
define assetName => ["assetName", 'Asset_WeatherData'];
|
||||
define icon => 'weatherData.gif';
|
||||
|
|
@ -57,6 +58,7 @@ property locations => (
|
|||
tab => "properties",
|
||||
hoverHelp => ["Your list of default weather locations", 'Asset_WeatherData'],
|
||||
label => ["Default Locations", 'Asset_WeatherData'],
|
||||
dashletOverridable => 1,
|
||||
);
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -93,49 +95,70 @@ to be displayed within the page style
|
|||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my %var;
|
||||
my $url = $self->session->url;
|
||||
|
||||
if ($self->partnerId ne "" && $self->licenseKey ne "") {
|
||||
foreach my $location (split("\n", $self->locations)) {
|
||||
my $weather = Weather::Com::Finder->new({
|
||||
'partner_id' => $self->partnerId,
|
||||
'license' => $self->licenseKey,
|
||||
'cache' => '/tmp',
|
||||
});
|
||||
next unless defined $weather;
|
||||
my $overrides = $self->fetchUserOverrides($self->getParent->getId);
|
||||
my $locations = $overrides->{locations} || $self->locations;
|
||||
foreach my $location (split("\n", $locations)) {
|
||||
my $loop_data;
|
||||
my $link_data = [];
|
||||
my $cached_data = $session->cache->get( join "", $self->getId, $location );
|
||||
if ($cached_data) {
|
||||
$loop_data = $cached_data->{locations};
|
||||
$link_data = $cached_data->{links} || [];
|
||||
}
|
||||
else {
|
||||
my $weather = Weather::Com::Finder->new({
|
||||
'partner_id' => $self->partnerId,
|
||||
'license' => $self->licenseKey,
|
||||
'cache' => '/tmp',
|
||||
});
|
||||
next unless defined $weather;
|
||||
|
||||
foreach my $foundLocation(@{$weather->find($location)}) {
|
||||
my $current_conditions = $foundLocation->current_conditions;
|
||||
my $conditions = $current_conditions->description;
|
||||
$conditions =~ s/\b(\w)/uc($1)/eg;
|
||||
my $tempC = $current_conditions->temperature;
|
||||
my $tempF;
|
||||
$tempF = sprintf("%.0f",(((9/5)*$tempC) + 32)) if($tempC);
|
||||
my $icon = $current_conditions->icon || "na";
|
||||
foreach my $foundLocation(@{$weather->find($location)}) {
|
||||
my $current_conditions = $foundLocation->current_conditions;
|
||||
my $conditions = $current_conditions->description;
|
||||
$conditions =~ s/\b(\w)/uc($1)/eg;
|
||||
my $tempC = $current_conditions->temperature;
|
||||
my $tempF;
|
||||
$tempF = sprintf("%.0f",(((9/5)*$tempC) + 32)) if($tempC);
|
||||
my $icon = $current_conditions->icon || "na";
|
||||
|
||||
push(@{$var{'ourLocations.loop'}}, {
|
||||
query => $location,
|
||||
cityState => $foundLocation->name || $location,
|
||||
sky => $conditions || 'N/A',
|
||||
tempF => (defined $tempF)?$tempF:'N/A',
|
||||
tempC => (defined $tempC)?$tempC:'N/A',
|
||||
smallIcon => $url->extras("wobject/WeatherData/small_icons/".$icon.".png"),
|
||||
mediumIcon => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
largeIcon => $url->extras("wobject/WeatherData/large_icons/".$icon.".png"),
|
||||
iconUrl => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
iconAlt => $conditions,
|
||||
});
|
||||
if (!$var{links_loop}) {
|
||||
$var{links_loop} = [];
|
||||
push @{$loop_data}, {
|
||||
query => $location,
|
||||
cityState => $foundLocation->name || $location,
|
||||
sky => $conditions || 'N/A',
|
||||
tempF => (defined $tempF)?$tempF:'N/A',
|
||||
tempC => (defined $tempC)?$tempC:'N/A',
|
||||
smallIcon => $url->extras("wobject/WeatherData/small_icons/".$icon.".png"),
|
||||
mediumIcon => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
largeIcon => $url->extras("wobject/WeatherData/large_icons/".$icon.".png"),
|
||||
iconUrl => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
iconAlt => $conditions,
|
||||
last_fetch => time(),
|
||||
};
|
||||
for my $lnk (@{$foundLocation->current_conditions->{WEATHER}{lnks}{link}} ) {
|
||||
push @{$var{links_loop}}, {
|
||||
link_url => $lnk->{l},
|
||||
link_title => $lnk->{t},
|
||||
};
|
||||
if (! $link_data) {
|
||||
push @{ $link_data }, {
|
||||
link_url => $lnk->{l},
|
||||
link_title => $lnk->{t},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
my $cached_data = {
|
||||
locations => $loop_data,
|
||||
links => $link_data,
|
||||
};
|
||||
$session->cache->set( join( "", $self->getId, $location ), $cached_data, $self->get('cacheTimeout'));
|
||||
}
|
||||
push @{$var{'ourLocations.loop'}}, @{ $loop_data };
|
||||
if (!$var{links_loop}) {
|
||||
$var{links_loop} = $link_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $self->processTemplate(\%var, undef, $self->{_viewTemplate});
|
||||
|
|
|
|||
|
|
@ -869,6 +869,8 @@ Return search results that match the keyword from the form variable C<keyword>.
|
|||
|
||||
sub www_byKeyword {
|
||||
my $self = shift;
|
||||
my $check = $self->checkView;
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
my $session = $self->session;
|
||||
my $keyword = $session->form->process("keyword");
|
||||
|
||||
|
|
@ -980,6 +982,8 @@ Render a search form and process the contents, returning the results.
|
|||
|
||||
sub www_search {
|
||||
my $self = shift;
|
||||
my $check = $self->checkView;
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_WikiMaster");
|
||||
my $queryString = $self->session->form->process('query', 'text');
|
||||
my $var = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue