diff --git a/docs/upgrades/packages-7.9.4/crystalx.wgpkg b/docs/upgrades/packages-7.9.4/crystalx.wgpkg
new file mode 100644
index 000000000..2449ad021
Binary files /dev/null and b/docs/upgrades/packages-7.9.4/crystalx.wgpkg differ
diff --git a/docs/upgrades/packages-7.9.4/greenportal.wgpkg b/docs/upgrades/packages-7.9.4/greenportal.wgpkg
new file mode 100644
index 000000000..7a4536376
Binary files /dev/null and b/docs/upgrades/packages-7.9.4/greenportal.wgpkg differ
diff --git a/docs/upgrades/packages-7.9.4/style-underground.wgpkg b/docs/upgrades/packages-7.9.4/style-underground.wgpkg
new file mode 100644
index 000000000..1ea3ae998
Binary files /dev/null and b/docs/upgrades/packages-7.9.4/style-underground.wgpkg differ
diff --git a/lib/WebGUI/Asset/Template.pm b/lib/WebGUI/Asset/Template.pm
index a1e87e543..2a71fffe9 100644
--- a/lib/WebGUI/Asset/Template.pm
+++ b/lib/WebGUI/Asset/Template.pm
@@ -407,6 +407,22 @@ sub getEditForm {
return $tabform;
}
+#-------------------------------------------------------------------
+
+=head2 getExampleImageUrl ( )
+
+Get the URL to the example image of this template, if any
+
+=cut
+
+sub getExampleImageUrl {
+ my ( $self ) = @_;
+ if ( my $storageId = $self->get('storageIdExample') ) {
+ my $storage = WebGUI::Storage->get( $self->session, $storageId );
+ return $storage->getUrl( $storage->getFiles->[0] );
+ }
+ return;
+}
#-------------------------------------------------------------------
diff --git a/lib/WebGUI/Wizard/HomePage.pm b/lib/WebGUI/Wizard/HomePage.pm
new file mode 100644
index 000000000..cb5f24806
--- /dev/null
+++ b/lib/WebGUI/Wizard/HomePage.pm
@@ -0,0 +1,367 @@
+package WebGUI::Wizard::HomePage;
+
+use strict;
+use base 'WebGUI::Wizard';
+
+=head1 NAME
+
+WebGUI::Wizard::HomePage - Create or replace a Home Page with new content
+
+=cut
+
+sub _get_steps {
+ return [ qw(
+ pickStyle
+ chooseContent
+ finalize
+ )
+ ];
+}
+
+#-------------------------------------------------------------------
+
+=head2 addAsset ( parent, properties )
+
+A helper to add assets with less code.
+
+=head3 parent
+
+The parent asset to add to.
+
+=head3 properties
+
+A hash ref of properties to attach to the asset. One must be className.
+
+=cut
+
+sub addAsset {
+ my $parent = shift;
+ my $properties = shift;
+ $properties->{url} = $parent->get("url") . "/" . $properties->{title};
+ $properties->{groupIdEdit} = $parent->get("groupIdEdit");
+ $properties->{groupIdView} = $parent->get("groupIdView");
+ $properties->{ownerUserId} = $parent->get("ownerUserId");
+ $properties->{styleTemplateId} = $parent->get("styleTemplateId");
+ $properties->{printableStyleTemplateId} = $parent->get("styleTemplateId");
+ return $parent->addChild($properties);
+}
+
+#-------------------------------------------------------------------
+
+=head2 addPage ( parent, title )
+
+Adds a page to a parent page.
+
+=head3 parent
+
+A parent page asset.
+
+=head3 title
+
+The title of the new page.
+
+=cut
+
+sub addPage {
+ my $parent = shift;
+ my $title = shift;
+ return addAsset( $parent, { title => $title, className => "WebGUI::Asset::Wobject::Layout", displayTitle => 0 } );
+}
+
+sub wrapStyle {
+ return WebGUI::Wizard::Setup::wrapStyle( @_ );
+}
+
+sub www_pickStyle {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $f = $self->getForm;
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ my $output = '
' . $i18n->get('1073') . '
';
+
+ my @styleIds
+ = $session->db->buildArray(
+ q{SELECT DISTINCT(assetId) FROM template WHERE namespace="style"}
+ );
+
+ # Verboten:
+ # PBtmpl0000000000000060
+ # PBtmpl0000000000000111
+ # PBtmpl0000000000000137
+ # PBtmpl0000000000000132
+
+ # Blank style:
+ # PBtmplBlankStyle000001
+ my @skipStyleIds = qw( PBtmpl0000000000000060 PBtmpl0000000000000111 PBtmpl0000000000000137
+ PBtmpl0000000000000132 PBtmplBlankStyle000001 );
+
+ # Instantiate the objects
+ my @styles;
+ for my $styleId ( @styleIds ) {
+ next if grep { $_ eq $styleId } @skipStyleIds;
+ my $style = WebGUI::Asset->newByDynamicClass( $session, $styleId );
+ push @styles, $style;
+ }
+
+ for my $style ( sort { $a->getTitle cmp $b->getTitle } @styles ) {
+ $f->raw(
+ ''
+ . '
'
+ );
+ }
+ $f->submit;
+
+ $output .= $f->print;
+
+ return $output . '
';
+}
+
+sub www_pickStyleSave {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my ( $form ) = $session->quick(qw( form ));
+
+ # Coming from initial setup:
+ if ( $form->get('initialSetup') ) {
+ $self->set({ initialSetup => 1 });
+ }
+
+ $self->set({ "styleTemplateId", $form->get('styleTemplateId') });
+
+ return;
+}
+
+sub www_chooseContent {
+ my ($self) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->http->setCacheControl("none");
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ my $output = '' . $i18n->get('Initial Pages') . '
';
+
+ my $f = $self->getForm;
+ $f->yesNo( name => "contactUs", label => $i18n->get('Contact Us') );
+ $f->yesNo( name => "calendar", label => $i18n->get( "assetName", 'Asset_Calendar' ) );
+ $f->yesNo( name => "wiki", label => $i18n->get( 'assetName', 'Asset_WikiMaster' ) );
+ $f->yesNo( name => "search", label => $i18n->get( "assetName", 'Asset_Search' ) );
+ $f->yesNo( name => "aboutUs", label => $i18n->get("About Us") );
+ $f->HTMLArea(
+ name => "aboutUsContent",
+ richEditId => "PBrichedit000000000002",
+ value => $i18n->get("Put your about us content here.")
+ );
+
+ if ( exists $session->config->get('assets')->{"WebGUI::Asset::Wobject::Collaboration"} ) {
+ $f->yesNo( name => "news", label => $i18n->get(357) );
+ $f->yesNo( name => "forums", label => $i18n->get("Forums") );
+ $f->textarea(
+ name => "forumNames",
+ subtext => $i18n->get("One forum name per line"),
+ value => $i18n->get("Support") . "\n" . $i18n->get("General Discussion")
+ );
+ }
+ $f->submit;
+ $output .= $f->print;
+
+ return $output;
+} ## end sub www_chooseContent
+
+sub www_chooseContentSave {
+ my ($self) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ my $home;
+ if ( $self->get('initialSetup') ) {
+ $home = WebGUI::Asset->getDefault($session);
+ }
+ else {
+ my $root = WebGUI::Asset->getRoot($session);
+ $home = addPage( $root, "New Home Page" );
+ }
+
+ # update default site style
+ foreach my $asset ( @{ $home->getLineage( [ "self", "descendants" ], { returnObjects => 1 } ) } ) {
+ if ( defined $asset ) {
+ $asset->update( { styleTemplateId => $self->get("styleTemplateId") } );
+ }
+ }
+
+ # add new pages
+ if ( $form->get("aboutUs") ) {
+ my $page = addPage( $home, $i18n->get("About Us") );
+ addAsset(
+ $page, {
+ title => $i18n->get("About Us"),
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::Article",
+ description => $form->get("aboutUsContent"),
+ }
+ );
+ }
+
+ # add forums
+ if ( $form->get("forums") ) {
+ my $page = addPage( $home, $i18n->get("Forums") );
+ my $board = addAsset(
+ $page, {
+ title => $i18n->get("Forums"),
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::MessageBoard",
+ description => $i18n->get("Discuss your ideas and get help from our community."),
+ }
+ );
+ my $forumNames = $form->get("forumNames");
+ $forumNames =~ s/\r//g;
+ foreach my $forumName ( split "\n", $forumNames ) {
+ next if $forumName eq "";
+ addAsset(
+ $board, {
+ title => $forumName,
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::Collaboration"
+ }
+ );
+ }
+ } ## end if ( $form->get("forums"...))
+
+ # add news
+ if ( $form->get("news") ) {
+ my $page = addPage( $home, $i18n->get(357) );
+ addAsset(
+ $page, {
+ title => $i18n->get(357),
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::Collaboration",
+ collaborationTemplateId => "PBtmpl0000000000000112",
+ allowReplies => 0,
+ attachmentsPerPost => 5,
+ postFormTemplateId => "PBtmpl0000000000000068",
+ threadTemplateId => "PBtmpl0000000000000067",
+ description => $i18n->get("All the news you need to know."),
+ }
+ );
+ } ## end if ( $form->get("news"...))
+
+ # add wiki
+ if ( $form->get("wiki") ) {
+ my $page = addPage( $home, $i18n->get( "assetName", 'Asset_WikiMaster' ) );
+ addAsset(
+ $page, {
+ title => $i18n->get( "assetName", 'Asset_WikiMaster' ),
+ isHidden => 1,
+ allowAttachments => 5,
+ className => "WebGUI::Asset::Wobject::WikiMaster",
+ description => $i18n->get("Welcome to our wiki. Here you can help us keep information up to date."),
+ }
+ );
+ }
+
+ # add calendar
+ if ( $form->get("calendar") ) {
+ my $page = addPage( $home, $i18n->get( 'assetName', "Asset_Calendar" ) );
+ addAsset(
+ $page, {
+ title => $i18n->get( 'assetName', "Asset_Calendar" ),
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::Calendar",
+ description => $i18n->get("Check out what is going on."),
+ }
+ );
+ }
+
+ # add contact us
+ if ( $form->get("contactUs") ) {
+ my $page = addPage( $home, $i18n->get("Contact Us") );
+ my $i18n2 = WebGUI::International->new( $session, "Asset_DataForm" );
+ my @fieldConfig = ( {
+ name => "from",
+ label => $i18n2->get( "Your Email Address", 'WebGUI' ),
+ status => "required",
+ isMailField => 1,
+ width => 0,
+ type => "email",
+ }, {name => "to",
+ label => $i18n2->get(11),
+ status => "hidden",
+ isMailField => 1,
+ width => 0,
+ type => "email",
+ defaultValue => $session->setting->get("companyEmail"),
+ }, {name => "cc",
+ label => $i18n2->get(12),
+ status => "hidden",
+ isMailField => 1,
+ width => 0,
+ type => "email",
+ }, {name => "bcc",
+ label => $i18n2->get(13),
+ status => "hidden",
+ isMailField => 1,
+ width => 0,
+ type => "email",
+ }, {name => "subject",
+ label => $i18n2->get(14),
+ status => "hidden",
+ isMailField => 1,
+ width => 0,
+ type => "text",
+ defaultValue => $i18n->get(2),
+ }, {name => "comments",
+ label => $i18n->get( "comments", 'VersionTag' ),
+ status => "required",
+ type => "textarea",
+ subtext => $i18n->get("Tell us how we can assist you."),
+ },
+ );
+ my $dataForm = addAsset(
+ $page, {
+ title => $i18n->get("Contact Us"),
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::DataForm",
+ description => $i18n->get("We welcome your feedback."),
+ acknowledgement =>
+ $i18n->get("Thanks for for your interest in ^c;. We will review your message shortly."),
+ mailData => 1,
+ fieldConfiguration => JSON->new->encode( \@fieldConfig ),
+ }
+ );
+ } ## end if ( $form->get("contactUs"...))
+
+ # add search
+ if ( $form->get("search") ) {
+ my $page = addPage( $home, $i18n->get( 'assetName', "Asset_Search" ) );
+ addAsset(
+ $page, {
+ title => $i18n->get( 'assetName', "Asset_Search" ),
+ isHidden => 1,
+ className => "WebGUI::Asset::Wobject::Search",
+ description => $i18n->get("Cannot find what you are looking for? Try our search."),
+ searchRoot => $home->getId,
+ }
+ );
+ }
+
+ # commit the working tag
+ my $working = WebGUI::VersionTag->getWorking($session);
+ $working->set( { name => "Home Page Wizard" } );
+ $working->commit;
+
+ return;
+} ## end sub www_chooseContentSave
+
+sub www_finalize {
+ my ($self) = @_;
+ my $session = $self->session;
+ $session->http->setCacheControl("none");
+ $session->http->setRedirect( $session->url->gateway );
+ return "redirect";
+}
+
+1;
diff --git a/lib/WebGUI/Wizard/Setup.pm b/lib/WebGUI/Wizard/Setup.pm
new file mode 100644
index 000000000..04460f02d
--- /dev/null
+++ b/lib/WebGUI/Wizard/Setup.pm
@@ -0,0 +1,305 @@
+package WebGUI::Wizard::Setup;
+
+use strict;
+use base 'WebGUI::Wizard';
+
+=head1 NAME
+
+WebGUI::Wizard::Setup -- Initial site setup
+
+=cut
+
+
+sub _get_steps {
+ return [qw(
+ adminAccount
+ companyInformation
+ siteStats
+ defaultStyle
+ finalize
+ )];
+}
+
+sub wrapStyle {
+ my ( $self, $output ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->http->setCacheControl("none");
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+ my $page = '
+
+
+ ' . $i18n->get('WebGUI Initial Configuration') . '
+
+
+' . $session->style->generateAdditionalHeadTags . '
+
+
+ ' . $output . '
+';
+ $session->http->setMimeType("text/html");
+ return $page;
+}
+
+
+sub www_adminAccount {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->http->setCacheControl("none");
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ my $legend = $i18n->get('admin account');
+ my $u = WebGUI::User->new( $session, '3' );
+ my $f = $self->getForm;
+ $f->text(
+ -name => "username",
+ -value => $u->username,
+ -label => $i18n->get(50),
+ -hoverHelp => $i18n->get('50 setup description'),
+ );
+ $f->text(
+ -name => "identifier",
+ -value => "123qwe",
+ -label => $i18n->get(51),
+ -hoverHelp => $i18n->get('51 description'),
+ -subtext => '(' . $i18n->get("password clear text") . ')
'
+ );
+ $f->email(
+ -name => "email",
+ -value => $u->profileField("email"),
+ -label => $i18n->get(56),
+ -hoverHelp => $i18n->get('56 description'),
+ );
+ $f->timeZone(
+ -name => "timeZone",
+ -value => $u->profileField("timeZone"),
+ -label => $i18n->get( 'timezone', 'DateTime' ),
+ -hoverHelp => $i18n->get('timezone help'),
+ );
+ $f->selectBox(
+ -name => "language",
+ -value => $u->profileField("language"),
+ -label => $i18n->get('304'),
+ -hoverHelp => $i18n->get('language help'),
+ -options => $i18n->getLanguages(),
+ );
+ $f->submit;
+ return '' . $legend . '
' . $f->print;
+}
+
+sub www_adminAccountSave {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+
+ my $timezone = $form->timeZone("timeZone");
+ my $language = $form->selectBox("language");
+
+ ##update Admin and Visitor users
+ my $u = WebGUI::User->new( $session, "3" );
+ $u->username( $form->process( "username", "text", "Admin" ) );
+ $u->profileField( "email", $form->email("email") );
+ $u->profileField( "timeZone", $timezone );
+ $u->profileField( "language", $language );
+ $u->identifier( Digest::MD5::md5_base64( $form->process( "identifier", "password", "123qwe" ) ) );
+
+ $u = WebGUI::User->new( $session, "1" );
+ $u->profileField( "timeZone", $timezone );
+ $u->profileField( "language", $language );
+
+ ##update ProfileField defaults so new users the get the defaults, too
+ my $properties;
+
+ my $zoneField = WebGUI::ProfileField->new( $session, 'timeZone' );
+ $properties = $zoneField->get();
+ $properties->{dataDefault} = $timezone;
+ $zoneField->set($properties);
+
+ my $languageField = WebGUI::ProfileField->new( $session, 'language' );
+ $properties = $languageField->get();
+ $properties->{dataDefault} = $language;
+ $languageField->set($properties);
+
+ return;
+}
+
+sub www_companyInformation {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->http->setCacheControl("none");
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ my $output = '' . $i18n->get('company information') . '
';
+
+ my $f = $self->getForm;
+ $f->hidden( name => "step", value => "3" );
+ $f->text(
+ name => "companyName",
+ value => $session->setting->get("companyName"),
+ label => $i18n->get(125),
+ hoverHelp => $i18n->get('125 description'),
+ );
+ $f->email(
+ name => "companyEmail",
+ value => $session->setting->get("companyEmail"),
+ label => $i18n->get(126),
+ hoverHelp => $i18n->get('126 description'),
+ );
+ $f->url(
+ name => "companyURL",
+ value => $session->setting->get("companyURL"),
+ label => $i18n->get(127),
+ hoverHelp => $i18n->get('127 description'),
+ );
+ $f->submit;
+ $output .= $f->print;
+
+ return $output;
+}
+
+sub www_companyInformationSave {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->setting->set( 'companyName', $form->text("companyName") ) if ( $form->get("companyName") );
+ $session->setting->set( 'companyURL', $form->url("companyURL") ) if ( $form->get("companyURL") );
+ $session->setting->set( 'companyEmail', $form->email("companyEmail") ) if ( $form->get("companyEmail") );
+ return;
+}
+
+sub www_siteStats {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->http->setCacheControl("none");
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ my $enableForm = $self->getForm;
+ $enableForm->hidden( name => "enableStats", value => 1 );
+ $enableForm->submit( value => $i18n->get( 'enable', 'Activity_SendWebguiStats' ) );
+
+ my $disableForm = $self->getForm;
+ $disableForm->hidden( name => "enableStats", value => 0 );
+ $disableForm->submit( value => $i18n->get( 'disable', 'Activity_SendWebguiStats' ) );
+
+ my $output = '' . $i18n->get( 'topicName', 'Activity_SendWebguiStats' ) . '
';
+ $output .= ' ' . $i18n->get( 'why to send', 'Activity_SendWebguiStats' ) . '
+ ' . $i18n->get( 'would you participate', 'Activity_SendWebguiStats' ) . '
+ ' . $enableForm->print . '
'
+ . $disableForm->print
+ . '
'
+ . '
'
+ ;
+
+ return $output;
+}
+
+sub www_siteStatsSave {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ WebGUI::Operation::Statistics::www_enableSendWebguiStats($session) if ( $form->get("enableStats") );
+ return;
+}
+
+sub www_defaultStyle {
+ return WebGUI::Wizard::HomePage::www_pickStyle( @_ );
+}
+
+sub www_defaultStyleSave {
+ my ( $self, @args ) = @_;
+ my $output = WebGUI::Wizard::HomePage::www_pickStyleSave( $self, @args );
+ # update default site style
+ my $home = WebGUI::Asset->getDefault( $self->session );
+ foreach my $asset ( @{ $home->getLineage( [ "self", "descendants" ], { returnObjects => 1 } ) } ) {
+ if ( defined $asset ) {
+ $asset->update( { styleTemplateId => $self->get("styleTemplateId") } );
+ }
+ }
+ return $output;
+}
+
+sub www_finalize {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my $form = $session->form;
+ $session->http->setCacheControl("none");
+ my $i18n = WebGUI::International->new( $session, "WebGUI" );
+
+ # Delete specialState
+ $session->setting->remove( "specialState" );
+
+ my $starterForm = WebGUI::HTMLForm->new( $session );
+ $starterForm->hidden( name => "op", value => "wizard" );
+ $starterForm->hidden( name => "wizard_class", value => "WebGUI::Wizard::HomePage" );
+ $starterForm->hidden( name => "wizard_step", value => "pickStyle" );
+ $starterForm->hidden( name => "initialSetup", value => 1 );
+ $starterForm->hidden( name => "styleTemplateId", value => $self->get('styleTemplateId') );
+ $starterForm->submit( value => $i18n->get( 'yes please' ) );
+
+ my $finishForm = $self->getForm;
+ $finishForm->hidden( name => "runStarter", value => 0 );
+ $finishForm->submit( value => $i18n->get( 'no thanks' ) );
+
+ my $output = '' . $i18n->get('site starter title') . '
';
+ $output .= ' ' . $i18n->get('site starter body') . '
'
+ . '' . $starterForm->print . '
'
+ . '' . $finishForm->print . '
'
+ . '
'
+ ;
+
+ return $output;
+}
+
+sub www_finalizeSave {
+ my ( $self ) = @_;
+ my $session = $self->session;
+ my ( $form ) = $session->quick(qw( form ));
+
+ $session->http->setRedirect( $session->url->gateway );
+}
+
+1;
diff --git a/www/extras/wg.gif b/www/extras/wg.gif
new file mode 100644
index 000000000..76ef8645e
Binary files /dev/null and b/www/extras/wg.gif differ