'.$msg if($preface ne "");
+ $mail->addHtml($msg);
+ $mail->addFooter;
$mail->queue;
}
$self->{_session} = $session;
diff --git a/lib/WebGUI/Storage.pm b/lib/WebGUI/Storage.pm
index 6432e33ac..af39508a0 100644
--- a/lib/WebGUI/Storage.pm
+++ b/lib/WebGUI/Storage.pm
@@ -678,6 +678,32 @@ sub generateThumbnail {
#-------------------------------------------------------------------
+=head2 getSize ( filename )
+
+Returns width and height of image.
+
+=head3 filename
+
+The file to generate a thumbnail for.
+
+=cut
+
+sub getSize {
+ my $self = shift;
+ my $filename = shift;
+ my $image = Image::Magick->new;
+ my $error = $image->Read($self->getPath($filename));
+ if ($error) {
+ $self->session->errorHandler->error("Couldn't read image for size reading: ".$error);
+ return 0;
+ }
+ my ($x, $y) = $image->Get('width','height');
+
+ return($x, $y);
+}
+
+#-------------------------------------------------------------------
+
=head2 getErrorCount ( )
Returns the number of errors that have been generated on this object instance.
@@ -1054,6 +1080,203 @@ sub renameFile {
#-------------------------------------------------------------------
+=head2 crop ( filename [, width, height ] )
+
+Resizes the specified image by the specified height and width. If either is omitted the iamge will be scaleed proportionately to the non-omitted one.
+
+=head3 filename
+
+The name of the file to resize.
+
+=head3 width
+
+The new width of the image in pixels.
+
+=head3 height
+
+The new height of the image in pixels.
+
+=head3 x
+
+The top of the image in pixels.
+
+=head3 y
+
+The top of the image in pixels.
+
+=cut
+
+# TODO: Make this take a hash reference with width, height, and density keys.
+
+sub crop {
+ my $self = shift;
+ my $filename = shift;
+ my $width = shift;
+ my $height = shift;
+ my $x = shift;
+ my $y = shift;
+ unless (defined $filename) {
+ $self->session->errorHandler->error("Can't resize when you haven't specified a file.");
+ return 0;
+ }
+ unless ($self->isImage($filename)) {
+ $self->session->errorHandler->error("Can't resize something that's not an image.");
+ return 0;
+ }
+ unless ($width || $height || $x || $y) {
+ $self->session->errorHandler->error("Can't resize with no resizing parameters.");
+ return 0;
+ }
+ my $image = Image::Magick->new;
+ my $error = $image->Read($self->getPath($filename));
+ if ($error) {
+ $self->session->errorHandler->error("Couldn't read image for resizing: ".$error);
+ return 0;
+ }
+
+ # Next, resize dimensions
+ if ( $width || $height || $x || $y ) {
+ $self->session->errorHandler->info( "Resizing $filename to w:$width h:$height x:$x y:$y" );
+ $image->Crop( height => $height, width => $width, x => $x, y => $y );
+ }
+
+ # Write our changes to disk
+ $error = $image->Write($self->getPath($filename));
+ if ($error) {
+ $self->session->errorHandler->error("Couldn't resize image: ".$error);
+ return 0;
+ }
+
+ return 1;
+}
+
+#-------------------------------------------------------------------
+
+=head2 annotate ( filename [ text ] )
+
+Adds annotation text to the image.
+
+=head3 filename
+
+The name of the file to annotate.
+
+=head3 text
+
+Text to add.
+
+=cut
+
+sub annotate {
+ my $self = shift;
+ my $filename = shift;
+ my $asset = shift;
+ my $form = shift;
+ unless (defined $filename) {
+ $self->session->errorHandler->error("Can't rotate when you haven't specified a file.");
+ return 0;
+ }
+ unless ($self->isImage($filename)) {
+ $self->session->errorHandler->error("Can't rotate something that's not an image.");
+ return 0;
+ }
+ # unless ($annotate_text) {
+ # $self->session->errorHandler->error("Can't annotate with no text.");
+ # return 0;
+ # }
+ # unless ($annotate_top && $annotate_left && $annotate_width && $annotate_height) {
+ # $self->session->errorHandler->error("Can't annotate with no dimensions.");
+ # return 0;
+ # }
+
+ my $annotate = $asset->get('annotations');
+ my $save_annotate = "";
+ my @pieces = split(/\n/, $annotate);
+ for (my $i = 0; $i < $#pieces; $i += 3) {
+ my $top_left = $pieces[$i];
+ my $width_height = $pieces[$i + 1];
+ my $note = $pieces[$i + 2];
+
+ # warn("i: $i: ", $form->process("delAnnotate$i"));
+ next if $form->process("delAnnotate$i");
+
+ if ($save_annotate) {
+ $save_annotate .= "\n";
+ }
+ $save_annotate .= "$top_left\n$width_height\n$note";
+ }
+
+ my $annotate_text = $form->process("annotate_text");
+ my $annotate_top = $form->process("annotate_top");
+ my $annotate_left = $form->process("annotate_left");
+ my $annotate_width = $form->process("annotate_width");
+ my $annotate_height = $form->process("annotate_height");
+ # warn(qq(unless ($annotate_top && $annotate_left && $annotate_width && $annotate_height && $annotate_text !~ /^\s*$/)));
+ if (defined $annotate_top && defined $annotate_left && defined $annotate_width && defined $annotate_height && $annotate_text !~ /^\s*$/) {
+ if ($save_annotate) {
+ $save_annotate .= "\n";
+ }
+ # warn(qq($save_annotate .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n'$annotate_text'"));
+ $save_annotate .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n$annotate_text";
+ }
+ # warn($save_annotate);
+
+ $asset->update({ annotations => $save_annotate });
+ $save_annotate = $asset->get('annotations');
+ # warn($save_annotate);
+
+ return 1;
+}
+
+#-------------------------------------------------------------------
+
+=head2 rotate ( filename [ degrees ] )
+
+Rotates the image by the specified degrees.
+
+=head3 filename
+
+The name of the file to resize.
+
+=head3 width
+
+Number of degrees to rotate.
+
+=cut
+
+sub rotate {
+ my $self = shift;
+ my $filename = shift;
+ my $degree = shift || 0;
+ unless (defined $filename) {
+ $self->session->errorHandler->error("Can't rotate when you haven't specified a file.");
+ return 0;
+ }
+ unless ($self->isImage($filename)) {
+ $self->session->errorHandler->error("Can't rotate something that's not an image.");
+ return 0;
+ }
+ my $image = Image::Magick->new;
+ my $error = $image->Read($self->getPath($filename));
+ if ($error) {
+ $self->session->errorHandler->error("Couldn't read image for resizing: ".$error);
+ return 0;
+ }
+
+ $self->session->errorHandler->info( "Rotating $filename by $degree degrees" );
+ $image->Rotate( $degree );
+
+ # Write our changes to disk
+ $error = $image->Write($self->getPath($filename));
+ if ($error) {
+ $self->session->errorHandler->error("Couldn't rotate image: ".$error);
+ return 0;
+ }
+
+ return 1;
+}
+
+#-------------------------------------------------------------------
+
=head2 resize ( filename [, width, height ] )
Resizes the specified image by the specified height and width. If either is omitted the iamge will be scaleed proportionately to the non-omitted one.
diff --git a/lib/WebGUI/i18n/English/Asset_Image.pm b/lib/WebGUI/i18n/English/Asset_Image.pm
index 026b1529d..6ed0c5b2f 100644
--- a/lib/WebGUI/i18n/English/Asset_Image.pm
+++ b/lib/WebGUI/i18n/English/Asset_Image.pm
@@ -77,6 +77,54 @@ shown here.|,
lastUpdated => 1106765841
},
+ 'annotate' => {
+ message => q|Annotate|,
+ context => q|label to annotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'annotate image' => {
+ message => q|Annotate Image|,
+ context => q|label to annotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'annotate image description' => {
+ message => q|Text Around the Image|,
+ context => q|label to annotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'degree' => {
+ message => q|Degrees to Rotate|,
+ context => q|label to rotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'rotate image label' => {
+ message => q|Please click to rotate image|,
+ context => q|label to rotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'rotate image' => {
+ message => q|Rotate Image|,
+ context => q|label to rotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'rotate image label' => {
+ message => q|Please click to rotate image|,
+ context => q|label to rotate the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'crop image' => {
+ message => q|Crop Image|,
+ context => q|label to crop the image|,
+ lastUpdated => 1106765841
+ },
+
'new width' => {
message => q|New Width|,
context => q|label to resize the image|,
@@ -101,6 +149,42 @@ shown here.|,
lastUpdated => 1130538987
},
+ 'undo image' => {
+ message => q|Undo Image|,
+ context => q|undo editing operations|,
+ lastUpdated => 1106765841
+ },
+
+ 'delete' => {
+ message => q|Delete|,
+ context => q|label to delete annotation|,
+ lastUpdated => 1106765841
+ },
+
+ 'height' => {
+ message => q|Height|,
+ context => q|label to resize the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'width' => {
+ message => q|Width|,
+ context => q|label to resize the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'top' => {
+ message => q|Top|,
+ context => q|label to resize the image|,
+ lastUpdated => 1106765841
+ },
+
+ 'left' => {
+ message => q|Left|,
+ context => q|label to resize the image|,
+ lastUpdated => 1106765841
+ },
+
'image template title' => {
message => q|Image Template Variables|,
lastUpdated => 1184820779,
diff --git a/lib/WebGUI/i18n/English/Asset_Matrix.pm b/lib/WebGUI/i18n/English/Asset_Matrix.pm
index f7ace67ae..a8b5b5bf9 100644
--- a/lib/WebGUI/i18n/English/Asset_Matrix.pm
+++ b/lib/WebGUI/i18n/English/Asset_Matrix.pm
@@ -427,6 +427,17 @@ listing,|,
lastUpdated => 1235681965,
},
+ 'statistics cache timeout label' => {
+ message => q|Statistics Cache Timeout|,
+ lastUpdated => 0,
+ },
+
+ 'statistics cache timeout description' => {
+ message => q|Since all users will see the matrix statistics the same way, we can cache them for some time
+to increase performance. How long should we cache them?|,
+ lastUpdated => 0,
+ },
+
'rating timeout description' => {
message => q|Set a timeout so that users are prevented from rating a given listing too often.|,
lastUpdated => 1135271460,
diff --git a/lib/WebGUI/i18n/English/Asset_Navigation.pm b/lib/WebGUI/i18n/English/Asset_Navigation.pm
index 2dae4d4f6..00866ad42 100644
--- a/lib/WebGUI/i18n/English/Asset_Navigation.pm
+++ b/lib/WebGUI/i18n/English/Asset_Navigation.pm
@@ -136,10 +136,10 @@ all of the classes of pages that should be included:
The current page.
Siblings
Pages at the same level as the current URL.
-
Descendents
+
Descendants
Pages lower than the current page in the tree.
Pedigree
-
When using a different start page, this option selects the Ancestors, Siblings and Descendents of that page.
+
When using a different start page, this option selects the Ancestors, Siblings and Descendants of that page.
|,
lastUpdated => 1146456217,
},
@@ -372,7 +372,7 @@ the Navigation Template to determine who can see them in the menu.
lastUpdated => 1163720148,
},
- 'page.isDescendent' => {
+ 'page.isDescendant' => {
message => q|A conditional indicating whether this page is a descendant of the current page.|,
lastUpdated => 1163720154,
},
@@ -393,7 +393,7 @@ the Navigation Template to determine who can see them in the menu.
},
'page.inBranch' => {
- message => q|A conditional that is the logical OR of isAncestor, isSibling, isBasepage and isDescendent.|,
+ message => q|A conditional that is the logical OR of isAncestor, isSibling, isBasepage and isDescendant.|,
lastUpdated => 1157647394,
},
diff --git a/lib/WebGUI/i18n/English/Asset_RSSCapable.pm b/lib/WebGUI/i18n/English/Asset_RSSCapable.pm
index 36e4fcd23..58c803c82 100644
--- a/lib/WebGUI/i18n/English/Asset_RSSCapable.pm
+++ b/lib/WebGUI/i18n/English/Asset_RSSCapable.pm
@@ -5,6 +5,8 @@ our $I18N =
{
'rssEnabled label' => { message => 'Enable RSS', lastUpdate => 1162487361 },
'rssEnabled hoverHelp' => { message => q|Whether or not to enable the RSS feed for this asset. If enabled, an RSS From Parent asset will be created and managed as an extra child for this purpose. If not enabled, no such child will be created and the existing one will be deleted.|, lastUpdate => 1162487361 },
+ 'rssLimit label' => { message => 'RSS Display limit', lastUpdate => 1162487361 },
+ 'rssLimit hoverHelp' => { message => q|How many RSS items to display|, lastUpdate => 1162487361 },
'rssTemplateId label' => { message => 'RSS Template', lastUpdate => 1162487361 },
'rssTemplateId hoverHelp' => { message => q|The template to use for the RSS feed of this asset.|, lastUpdate => 1162487361 },
diff --git a/lib/WebGUI/i18n/English/Asset_Thingy.pm b/lib/WebGUI/i18n/English/Asset_Thingy.pm
index 3c7a987eb..96cce408a 100644
--- a/lib/WebGUI/i18n/English/Asset_Thingy.pm
+++ b/lib/WebGUI/i18n/English/Asset_Thingy.pm
@@ -652,47 +652,68 @@ Braces, quotes and all. You simply replace "key1"/"value1" with your own name/v
'canEditThings' => {
message => q|Is true if the current user can view the Things that are defined for this Thingy Asset|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'things_loop' => {
message => q|A loop containing the Things that are defined for this Thingy Asset, with links to management
functions for those Things|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'thing_editIcon' => {
message => q|An icon with a link to the edit screen for this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_editUrl' => {
message => q|A link to the edit screen for this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
+ },
+
+ 'thing_copyIcon' => {
+ message => q|An icon with a link to copy this Thing|,
+ lastUpdated => 0,
+ context => q|Description of a tmpl_var for the template help.|,
+ },
+
+ 'thing_copyUrl' => {
+ message => q|A link to copy this Thing|,
+ lastUpdated => 0,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_viewIcon' => {
message => q|An icon with a link to default screen for this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_searchUrl' => {
message => q|A link to the search screen for this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_addUrl' => {
message => q|A link to the add screen for this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_deleteIcon' => {
message => q|An icon with a link to delete this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_deleteUrl' => {
message => q|A link to delete this Thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'thing_label' => {
@@ -708,31 +729,37 @@ functions for those Things|,
'manage_url' => {
message => q|This Url will lead to a screen to manage the Things in this Thingy Asset.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'addThing_url' => {
message => q|This Url leads to the screen to add a new Thing to this Thingy Asset.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'delete_url' => {
message => q|The Url to delete the current thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'delete_confirm' => {
message => q|This contains an onclick property for the delete link that adds a javascript confirmation|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'search_url' => {
message => q|Url that leads to the search screen|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'add_url' => {
message => q|Url to the add screen for this thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'editScreenTitle' => {
@@ -749,16 +776,19 @@ functions for those Things|,
message => q|A loop containing error information, for instance if someone doesn't fill out a required
field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'error_message' => {
message => q|An error message indicating what the user might have done wrong.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_loop' => {
message => q|A loop containing the visible fields for this thing|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'listOfThings' => {
@@ -788,73 +818,87 @@ field.|,
'field_isHidden' => {
message => q|A conditional indicating whether this field is supposed to be hidden.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_isRequired' => {
message => q|A conditional indicating whether this field is required.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_isVisible' => {
message => q|A conditional indicating whether this field is supposed to be visible but not editable.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_form' => {
message => q|The form element for this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_name' => {
message => q|The name of the form element for this field|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_label' => {
message => q|The label of this field|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_url' => {
message => q|An optional url that this field should link to, used i.e. for fields in other things.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_value' => {
message => q|The value of this field|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_pretext' => {
message => q|An extra description of the field so that users know what to put in the field. To be
displayed above/before the form element.|,
lastUpdated => 1224518799,
+ context => q|Description of a tmpl_var for the template help.|,
},
'field_subtext' => {
message => q|A description of the field so that users know what to put in the field. To be displayed
below/after the form element.|,
lastUpdated => 1224518799,
+ context => q|Description of a tmpl_var for the template help.|,
},
'form_start' => {
message => q|The start tag of the form|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'form_submit' => {
message => q|A form button to submit the form data.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'form_end' => {
message => q|The end of the form|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'edit_url' => {
message => q|Url to the current things edit screen.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'viewScreenTitle' => {
@@ -865,12 +909,14 @@ below/after the form element.|,
'import_url' => {
message => q|Url to import data into this Thing from a csv file|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'export_url' => {
message => q|Url to export the data in a search result into a csv file. This is only available after a
search has been done.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchScreenTitle' => {
@@ -886,86 +932,103 @@ search has been done.|,
'searchFields_loop' => {
message => q|A loop that contains the fields that are searchable|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'searchFields_label' => {
message => q|The label of a searchable field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchFields_fieldId' => {
message => q|The fieldId of a searchable field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchFields_form' => {
message => q|A form element corresponding to this fields fieldType to search this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchFields_textForm' => {
message => q|A text input to search this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchFields_is__fieldType__' => {
message => q|A boolean indicating wether this field is of type __fieldType__. The first letter of __fieldType__ is always uppercase. Example: for a select box the value of <tmpl_var searchFields_isSelectBox> is true.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'displayInSearchFields_loop' => {
message => q|A loop containing the fields that are displayed in the search results.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'displayInSearchFields_orderByUrl' => {
message => q|Url to order the search results by this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'displayInSearchFields_label' => {
message => q|The label of this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'displayInSearchFields_fieldId' => {
message => q|The fieldId of this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchResult_loop' => {
message => q|A loop containing the search results.|,
lastUpdated => 1206472126,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'searchResult_id' => {
message => q|The id of a search result.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchResult_view_url' => {
message => q|Url to the view screen of this search result|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchResult_edit_icon' => {
message => q|Edit icon that links to the edit screen of this search result.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchResult_delete_icon' => {
message => q|Delete icon to delete this search result.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'searchResult_field_loop' => {
message => q|A loop containing the fields that are to be displayed for this search result.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_loop for the template help.|,
},
'field_id' => {
message => q|The id of this field.|,
lastUpdated => 1104630516,
+ context => q|Description of a tmpl_var for the template help.|,
},
'no field values message' => {
@@ -1011,6 +1074,7 @@ search has been done.|,
'view_url' => {
message => q|The URL that will take the user back to the Thingy default view.|,
lastUpdated => 1227737813,
+ context => q|Description of a tmpl_var for the template help.|,
},
'other thing field missing message' => {
diff --git a/lib/WebGUI/i18n/English/AuthWebGUI.pm b/lib/WebGUI/i18n/English/AuthWebGUI.pm
index 39ec97a98..e15756d17 100644
--- a/lib/WebGUI/i18n/English/AuthWebGUI.pm
+++ b/lib/WebGUI/i18n/English/AuthWebGUI.pm
@@ -65,7 +65,7 @@ our $I18N = {
'account activation template title' => {
message => q|WebGUI Authentication Account Activation Mail Template|,
lastUpdated => 1230600500,
- context => q|The title of the help page for the webgui auth welcome message template.|,
+ context => q|The title of the help page for the webgui auth account activition mail template.|,
},
'account activation template' => {
@@ -84,7 +84,33 @@ our $I18N = {
message => q|The url to activate the newly created account.|,
lastUpdated => 1230600500,
},
-
+
+ 'welcome message template title' => {
+ message => q|WebGUI Authentication Welcome Message Template|,
+ lastUpdated => 0,
+ context => q|The title of the help page for the webgui auth welcome message template.|,
+ },
+
+ 'welcome message template' => {
+ message => q|Welcome Message Template|,
+ lastUpdated => 0,
+ context => q|The label for the 'welcome message template' field on the Authentication tab of the Settings
+screen.|,
+ },
+
+ 'welcome message template help' => {
+ message => q|Select a template for the welcome message that is sent to new users.|,
+ lastUpdated => 0,
+ context => q|The description of the 'welcome message template' field on the Authentication tab of the
+Settings screen, displayed as hoverhelp.|,
+ },
+
+ 'welcomeMessage' => {
+ message => q|The welcome message as defined in the authentication settings.|,
+ lastUpdated => 0,
+ context => q|Description of the welcomeMessage tmpl_var for the template help.|,
+ },
+
'use captcha' => {
message => q|Use captcha image?|,
lastUpdated => 1078852836
@@ -764,6 +790,12 @@ our $I18N = {
message => 'Username of registering user',
},
+ 'newUser_password' => {
+ message => q|The password for the newly created account.|,
+ lastUpdated => 0,
+ context => q|Description of the newUser_password tmpl_var for the template help.|,
+ },
+
};
1;
diff --git a/t/Asset/File/Image.t b/t/Asset/File/Image.t
index bad2c80d4..90307548d 100644
--- a/t/Asset/File/Image.t
+++ b/t/Asset/File/Image.t
@@ -20,6 +20,7 @@ BEGIN {
$mocker->fake_new('WebGUI::Form::Image');
}
+use File::Copy;
use WebGUI::Test;
use WebGUI::Session;
use WebGUI::Image;
@@ -29,23 +30,23 @@ use WebGUI::Form::File;
use Test::More; # increment this value for each test you create
use Test::Deep;
-plan tests => 7;
+plan tests => 11;
my $session = WebGUI::Test->session;
-my $square = WebGUI::Image->new($session, 100, 100);
-$square->setBackgroundColor('#0000FF');
+my $rectangle = WebGUI::Image->new($session, 100, 200);
+$rectangle->setBackgroundColor('#0000FF');
##Create a storage location
my $storage = WebGUI::Storage->create($session);
##Save the image to the location
-$square->saveToStorageLocation($storage, 'square.png');
+$rectangle->saveToStorageLocation($storage, 'blue.png');
##Do a file existance check.
ok((-e $storage->getPath and -d $storage->getPath), 'Storage location created and is a directory');
-cmp_bag($storage->getFiles, ['square.png'], 'Only 1 file in storage with correct name');
+cmp_bag($storage->getFiles, ['blue.png'], 'Only 1 file in storage with correct name');
##Initialize an Image Asset with that filename and storage location
@@ -68,9 +69,29 @@ is($asset->get('storageId'), $asset->getStorageLocation->getId, 'Image Asset sto
$asset->update({
storageId => $storage->getId,
- filename => 'square.png',
+ filename => 'blue.png',
});
+my $filename = $asset->getStorageLocation->getPath . "/" . $asset->get("filename");
+
+my @stat_before = stat($filename);
+$asset->getStorageLocation->rotate($asset->get("filename"), 90);
+my @stat_after = stat($filename);
+is(isnt_array(\@stat_before, \@stat_after), 1, 'Image is different after rotation');
+
+@stat_before = stat($filename);
+$asset->getStorageLocation->resize($asset->get("filename"), 200, 300);
+my @stat_after = stat($filename);
+is(isnt_array(\@stat_before, \@stat_after), 1, 'Image is different after resize');
+
+@stat_before = stat($filename);
+$asset->getStorageLocation->crop($asset->get("filename"), 100, 125, 10, 25);
+my @stat_after = stat($filename);
+is(isnt_array(\@stat_before, \@stat_after), 1, 'Image is different after crop');
+
+my $sth = $session->db->read('describe imageAsset annotations');
+isnt($sth->hashRef, undef, 'Annotations column is defined');
+
is($storage->getId, $asset->get('storageId'), 'Asset updated with correct new storageId');
is($storage->getId, $asset->getStorageLocation->getId, 'Cached Asset storage location updated with correct new storageId');
@@ -81,3 +102,13 @@ END {
$versionTag->rollback;
}
}
+
+sub isnt_array {
+ my ($a, $b) = @_;
+
+ for (my $i = 0; $i < @{ $a }; ++$i) {
+ return 1 if @{ $a }[$i] ne @{ $b }[$i];
+ }
+
+ return 0;
+}
diff --git a/t/Asset/Wobject/Collaboration.t b/t/Asset/Wobject/Collaboration.t
index ef7039417..cbd8c91a9 100644
--- a/t/Asset/Wobject/Collaboration.t
+++ b/t/Asset/Wobject/Collaboration.t
@@ -32,7 +32,7 @@ use WebGUI::Asset::Wobject::Collaboration;
use WebGUI::Asset::Post;
use WebGUI::Asset::Wobject::Layout;
use Data::Dumper;
-use Test::More tests => 4; # increment this value for each test you create
+use Test::More tests => 8; # increment this value for each test you create
my $session = WebGUI::Test->session;
@@ -60,6 +60,38 @@ ok(defined $collab->get('groupToEditPost'), 'groupToEditPost field is defined');
# Verify sane defaults
cmp_ok($collab->get('groupToEditPost'), 'eq', $collab->get('groupIdEdit'), 'groupToEditPost defaults to groupIdEdit correctly');
+is($collab->get('rssCapableRssLimit'), 10, 'rssCapableRssLimit is set to the default');
+
+# finally, add the post to the collaboration system
+my $props = {
+ className => 'WebGUI::Asset::Post::Thread',
+ content => 'hello, world!',
+};
+my $post = $collab->addChild($props,
+ undef,
+ undef,
+ {
+ skipAutoCommitWorkflows => 1,
+ });
+
+# Test for a sane object type
+isa_ok($post, 'WebGUI::Asset::Post::Thread');
+
+$props = {
+ className => 'WebGUI::Asset::Post::Thread',
+ content => 'jello, world!',
+};
+$post = $collab->addChild($props,
+ undef,
+ undef,
+ {
+ skipAutoCommitWorkflows => 1,
+ });
+
+my $rssitems = $collab->getRssItems();
+is($rssitems, 2, 'rssitems set to number of posts added');
+
+is($collab->get('rssCapableRssLimit'), 10, 'rssCapableRssLimit is set to the default');
TODO: {
local $TODO = "Tests to make later";
diff --git a/t/Asset/Wobject/GalleryAlbum/rss.t b/t/Asset/Wobject/GalleryAlbum/rss.t
index c5433ea23..383d81711 100644
--- a/t/Asset/Wobject/GalleryAlbum/rss.t
+++ b/t/Asset/Wobject/GalleryAlbum/rss.t
@@ -74,7 +74,11 @@ $oldSettings{ specialState } = $session->setting->get( 'specialState' );
$session->setting->set( 'specialState', '' );
my ( $mech );
-my $baseUrl = 'http://' . $session->config->get('sitename')->[0];
+my $config_port;
+if ($session->config->get('webServerPort')) {
+ $config_port = $session->config->get('webServerPort') || 80;
+}
+my $baseUrl = 'http://' . $session->config->get('sitename')->[0] . ":$config_port";
#----------------------------------------------------------------------------
# Tests
diff --git a/t/Asset/Wobject/Thingy.t b/t/Asset/Wobject/Thingy.t
index 9902a1c5f..ed5ad0a40 100644
--- a/t/Asset/Wobject/Thingy.t
+++ b/t/Asset/Wobject/Thingy.t
@@ -17,7 +17,7 @@ use lib "$FindBin::Bin/../../lib";
use WebGUI::Test;
use WebGUI::Session;
use WebGUI::PseudoRequest;
-use Test::More tests => 16; # increment this value for each test you create
+use Test::More tests => 17; # increment this value for each test you create
use Test::Deep;
use JSON;
use WebGUI::Asset::Wobject::Thingy;
@@ -192,6 +192,14 @@ my ($fieldLabel, $columnType, $Null, $Key, $Default, $Extra) = $session->db->qui
is($fieldLabel,"field_".$fieldId,"A column for the new field Field_$fieldId exists.");
is($columnType,"longtext","The columns is the right type");
+# Test duplicating a Thing
+
+my $copyThingId = $thingy->duplicateThing($thingId);
+
+$isValidId = $session->id->valid($copyThingId);
+
+is($isValidId,1,"duplicating a Thing: duplicateThing returned a valid id: ".$copyThingId);
+
# Test adding, editing, getting and deleting thing data
my ($newThingDataId,$errors) = $thingy->editThingDataSave($thingId,'new',{"field_".$fieldId => 'test value'});
diff --git a/www/extras/wobject/Matrix/matrixSearch.js b/www/extras/wobject/Matrix/matrixSearch.js
index 077beec5d..e4d36c871 100644
--- a/www/extras/wobject/Matrix/matrixSearch.js
+++ b/www/extras/wobject/Matrix/matrixSearch.js
@@ -55,7 +55,8 @@ YAHOO.util.Event.addListener(window, "load", function() {
var attributeSelects = YAHOO.util.Dom.getElementsByClassName('attributeSelect','select');
var newUri = "func=getCompareFormData;search=1";
for (var i = attributeSelects.length; i--; ) {
- if(attributeSelects[i].value != 'blank'){
+ var selectedIndex = attributeSelects[i].selectedIndex;
+ if(attributeSelects[i].value != 'blank' && !(attributeSelects[i].value == '0' && attributeSelects[i][selectedIndex].text == 'No')){
newUri = newUri + ';search_' + attributeSelects[i].id + '=' + attributeSelects[i].value;
}
}
diff --git a/www/extras/wobject/Survey/administersurvey.js b/www/extras/wobject/Survey/administersurvey.js
index 61d707f3e..86486347a 100644
--- a/www/extras/wobject/Survey/administersurvey.js
+++ b/www/extras/wobject/Survey/administersurvey.js
@@ -23,6 +23,9 @@ if (typeof Survey === "undefined") {
'Dual Slider - Range': 1,
'Multi Slider - Allocate': 1
};
+ var DATE_SHORT = {
+ 'Year Month': 1
+ };
var DATE_TYPES = {
'Date': 1,
'Date Range': 1
@@ -62,6 +65,16 @@ if (typeof Survey === "undefined") {
alert("Please allocate the remaining " + amountLeft + ".");
}
}
+ else if (toValidate[i].type === 'Year Month') {
+ answered = 1;//set to true, then let a single failure set it back to false.
+ for (var z1 in toValidate[i].answers) {
+ var m = document.getElementById(z1+'-month').value;
+ var y = document.getElementById(z1+'-year').value;
+ if(m == ''){ answered = 0; }
+ if(y.length != 4) { answered = 0; }
+ if(answered == 1){ document.getElementById(z1).value = m + "-" + y; }
+ }
+ }
else {
for (var z1 in toValidate[i].answers) {
if (YAHOO.lang.hasOwnProperty(toValidate[i].answers, z1)) {
@@ -395,7 +408,17 @@ if (typeof Survey === "undefined") {
toValidate[q.id].type = q.questionType;
toValidate[q.id].answers = [];
}
-
+
+ if (DATE_SHORT[q.questionType]) {
+ for (var k = 0; k < q.answers.length; k++) {
+ var ans = q.answers[k];
+ if (toValidate[q.id]) {
+ toValidate[q.id].type = q.questionType;
+ toValidate[q.id].answers[ans.id] = 1;
+ }
+ }
+ continue;
+ }
if (DATE_TYPES[q.questionType]) {
for (var k = 0; k < q.answers.length; k++) {
diff --git a/www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css b/www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css
new file mode 100644
index 000000000..73d3216f9
--- /dev/null
+++ b/www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+.yui-crop{position:relative;}.yui-crop .yui-crop-mask{position:absolute;top:0;left:0;height:100%;width:100%;}.yui-crop .yui-resize{position:absolute;top:10px;left:10px;border:0;}.yui-crop .yui-crop-resize-mask{position:absolute;top:0;left:0;height:100%;width:100%;background-position:-10px -10px;overflow:hidden;}.yui-skin-sam .yui-crop .yui-crop-mask{background-color:#000;opacity:.5;filter:alpha(opacity=50);}.yui-skin-sam .yui-crop .yui-resize{border:1px dashed #fff;}