You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/09/03 14:32:15 UTC

[24/87] [abbrv] [partial] isis git commit: ISIS-1194: moving the wicket submodules to be direct children of core; removing the isis-viewer-wicket parent pom.

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java
new file mode 100644
index 0000000..0c17407
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/register/RegisterPanel.java
@@ -0,0 +1,194 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.wicket.ui.pages.accmngt.register;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.PasswordTextField;
+import org.apache.wicket.markup.html.form.RequiredTextField;
+import org.apache.wicket.markup.html.form.StatelessForm;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
+import org.apache.wicket.markup.html.form.validation.IFormValidator;
+import org.apache.wicket.markup.html.panel.GenericPanel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.isis.applib.services.userreg.UserDetails;
+import org.apache.isis.applib.services.userreg.UserRegistrationService;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.transaction.TransactionalClosureAbstract;
+import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
+import org.apache.isis.viewer.wicket.ui.pages.accmngt.AccountConfirmationMap;
+import org.apache.isis.viewer.wicket.ui.pages.accmngt.UsernameAvailableValidator;
+
+/**
+ * A panel with a form for self-registration of a user
+ */
+public abstract class RegisterPanel extends GenericPanel<UserDetails> {
+
+    protected static final String ID_REGISTER_FORM = "registerForm";
+    private static final String ID_USERNAME = "username";
+    private static final String ID_USERNAME_FORM_GROUP = "usernameFormGroup";
+    private static final String ID_PASSWORD = "password";
+    private static final String ID_PASSWORD_FORM_GROUP = "passwordFormGroup";
+    private static final String ID_CONFIRM_PASSWORD = "confirmPassword";
+    private static final String ID_CONFIRM_PASSWORD_FORM_GROUP = "confirmPasswordFormGroup";
+    private static final String ID_EMAIL = "email";
+
+    private final UserDetails userDetails;
+    private final String uuid;
+
+    public RegisterPanel(final String id, final UserDetails userDetails, final String uuid) {
+        super(id);
+        this.userDetails = userDetails;
+        this.uuid = uuid;
+    }
+
+    @Override
+    protected void onInitialize() {
+        super.onInitialize();
+
+        RegisterForm registerForm = new RegisterForm(ID_REGISTER_FORM, uuid, userDetails);
+        add(registerForm);
+
+        Component username = newUsernameField();
+        MarkupContainer password = newPasswordField();
+        MarkupContainer confirmPassword = newConfirmPasswordField();
+        registerForm.add(newEqualPasswordInputValidator(password, confirmPassword));
+        TextField<String> emailField = newEmailField(userDetails);
+
+        registerForm.add(username, password, confirmPassword, emailField);
+
+        registerForm.add(newExtraFieldsContainer("extraFieldsContainer"));
+    }
+
+    protected abstract MarkupContainer newExtraFieldsContainer(String id);
+
+
+    private IFormValidator newEqualPasswordInputValidator(MarkupContainer password, MarkupContainer confirmPassword) {
+        FormComponent passwordField = (FormComponent) password.get(ID_PASSWORD);
+        FormComponent confirmPasswordField = (FormComponent) confirmPassword.get(ID_CONFIRM_PASSWORD);
+        return new EqualPasswordInputValidator(passwordField, confirmPasswordField);
+    }
+
+    /**
+     * Register user form.
+     */
+    private static class RegisterForm extends StatelessForm<UserDetails>
+    {
+        private static final long serialVersionUID = 1L;
+
+        private final String uuid;
+
+        /**
+         * Constructor.
+         *
+         * @param id
+         *            id of the form component
+         * @param userDetails
+         */
+        public RegisterForm(final String id, final String uuid, UserDetails userDetails)
+        {
+            super(id, new CompoundPropertyModel<>(userDetails));
+
+            this.uuid = uuid;
+
+            String email = getEmail();
+
+            userDetails.setEmailAddress(email);
+        }
+
+        @Override
+        public final void onSubmit()
+        {
+            final UserDetails userDetails = getModelObject();
+
+            IsisContext.doInSession(new Runnable() {
+                @Override
+                public void run() {
+                    final UserRegistrationService userRegistrationService = IsisContext.getPersistenceSession().getServicesInjector().lookupService(UserRegistrationService.class);
+
+                    IsisContext.getTransactionManager().executeWithinTransaction(new TransactionalClosureAbstract() {
+                        @Override
+                        public void execute() {
+                            userRegistrationService.registerUser(userDetails);
+                            removeAccountConfirmation();
+                        }
+                    });
+                }
+            });
+
+            signIn(userDetails.getUsername(), userDetails.getPassword());
+            setResponsePage(getApplication().getHomePage());
+        }
+
+        private boolean signIn(String username, String password)
+        {
+            return AuthenticatedWebSession.get().signIn(username, password);
+        }
+
+        private String getEmail() {
+            AccountConfirmationMap accountConfirmationMap = getApplication().getMetaData(AccountConfirmationMap.KEY);
+            return accountConfirmationMap.get(uuid);
+        }
+
+        private void removeAccountConfirmation() {
+            AccountConfirmationMap accountConfirmationMap = getApplication().getMetaData(AccountConfirmationMap.KEY);
+            accountConfirmationMap.remove(uuid);
+        }
+    }
+
+    protected TextField<String> newEmailField(final UserDetails userDetails) {
+        // use readonly-ish model to prevent changing the email with manual form submits
+        TextField<String> emailField = new TextField<>(ID_EMAIL, new Model<String>() {
+            @Override
+            public String getObject() {
+                return userDetails.getEmailAddress();
+            }
+        });
+        return emailField;
+    }
+
+    protected MarkupContainer newConfirmPasswordField() {
+        PasswordTextField confirmPassword = new PasswordTextField(ID_CONFIRM_PASSWORD);
+        confirmPassword.setLabel(new ResourceModel("confirmPasswordLabel"));
+        FormGroup confirmPasswordFormGroup = new FormGroup(ID_CONFIRM_PASSWORD_FORM_GROUP, confirmPassword);
+        confirmPasswordFormGroup.add(confirmPassword);
+        return confirmPasswordFormGroup;
+    }
+
+    protected MarkupContainer newPasswordField() {
+        PasswordTextField password = new PasswordTextField(ID_PASSWORD);
+        password.setLabel(new ResourceModel("passwordLabel"));
+        FormGroup passwordFormGroup = new FormGroup(ID_PASSWORD_FORM_GROUP, password);
+        passwordFormGroup.add(password);
+        return passwordFormGroup;
+    }
+
+    protected MarkupContainer newUsernameField() {
+        RequiredTextField<String> username = new RequiredTextField<>(ID_USERNAME);
+        username.add(UsernameAvailableValidator.INSTANCE);
+        FormGroup usernameFormGroup = new FormGroup(ID_USERNAME_FORM_GROUP, username);
+        usernameFormGroup.add(username);
+        return usernameFormGroup;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.css
new file mode 100644
index 0000000..3727ba1
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.css
@@ -0,0 +1,100 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+
+#header .applicationName {
+	display:none;
+}
+ 
+ .loginPanel {
+	width:310px;
+	background-color:#FFFFFF;
+	padding:20px;
+	border-radius:4px;
+	-moz-border-radius:4px;
+	-webkit-border-radius:4px;
+	margin-bottom:1%;
+	position:absolute;
+	clear:both;
+	height:200px;
+	left:50%;
+	top:50%;
+	margin-left:-175px;
+	margin-top:-100px;
+ }
+ 
+ .loginPanel h2 {
+ 	color:#423D37;
+ 	font-size:1.6em;
+ 	letter-spacing:0px;
+ 	line-height:150%;
+ 	margin-bottom:10px;
+ }
+ 
+ .loginPanel table {
+ 	width:100%;
+}
+
+.loginPanel table tr td {
+	padding:5px 0px;
+	text-align:left !important;
+}
+
+.loginPanel form input[type=text],
+.loginPanel form input[type=password] {
+	border-radius:4px;
+	-moz-borer-radius:4px;
+	-webkit-border-radius:4px;
+	padding:6px;
+	background-color:#F0EFEA;
+	border:1px solid #F0EFEA;
+	border-top:1px solid #CCCBC7;
+}
+
+
+.loginPanel form input[type=submit] {
+    background-color: #20B5C2;
+    border: 0 none;
+    border-radius: 4px 4px 4px 4px;
+    color: #FFFFFF;
+    cursor: pointer;
+    display: inline-block;
+    font-size: 0.9em;
+    padding: 5px 10px;
+}
+
+.loginPanel form input[type=reset] {
+    background-color: #E4E4DB;
+    border: 0 none;
+    border-radius: 4px 4px 4px 4px;
+    color: #46423C;
+    cursor: pointer;
+    display: inline-block;
+    font-size: 0.9em;
+    padding: 5px 10px;
+    text-transform: uppercase;
+}
+
+.loginPanel table tr td {
+	color:#46423C;
+}
+
+.wicketSignInPanel .mainMessage {
+	margin-top: 550px;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.html
new file mode 100644
index 0000000..01d0358
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.html
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org"
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:extend>
+            <div class="row">
+                <div class="loginPanel col-sm-offset-4 col-sm-4">
+                    <h2><wicket:message key="signUpHeader"/></h2>
+                    <div wicket:id="registrationFormPanel"></div>
+                </div>
+            </div>
+        </wicket:extend>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.java
new file mode 100644
index 0000000..bc65037
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPage.java
@@ -0,0 +1,66 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.pages.accmngt.signup;
+
+import com.google.inject.Inject;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.isis.viewer.wicket.model.models.PageType;
+import org.apache.isis.viewer.wicket.ui.errors.ExceptionModel;
+import org.apache.isis.viewer.wicket.ui.pages.PageNavigationService;
+import org.apache.isis.viewer.wicket.ui.pages.accmngt.AccountManagementPageAbstract;
+import org.apache.isis.viewer.wicket.ui.pages.login.WicketSignInPage;
+
+/**
+ * A page for self-registering a new user after confirmation of her email account.
+ */
+public class RegistrationFormPage extends AccountManagementPageAbstract {
+    
+    private static final long serialVersionUID = 1L;
+
+    @Inject
+    private PageNavigationService pageNavigationService;
+
+    public RegistrationFormPage(final PageParameters parameters) {
+        this(parameters, getAndClearExceptionModelIfAny());
+    }
+
+    private RegistrationFormPage(final PageParameters parameters, ExceptionModel exceptionModel) {
+        super(parameters, exceptionModel);
+
+        boolean suppressSignUp = getConfiguration().getBoolean(WicketSignInPage.ISIS_VIEWER_WICKET_SUPPRESS_SIGN_UP, false);
+        if(suppressSignUp) {
+            pageNavigationService.interceptAndRestartAt(PageType.SIGN_IN);
+        }
+
+    }
+
+    @Override
+    protected void onInitialize() {
+        super.onInitialize();
+
+        addRegistrationFormPanel();
+    }
+
+    protected RegistrationFormPanel addRegistrationFormPanel() {
+        final RegistrationFormPanel registrationFormPanel = new RegistrationFormPanel("registrationFormPanel");
+        addOrReplace(registrationFormPanel);
+        return registrationFormPanel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.html
new file mode 100644
index 0000000..4914da8
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.html
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<html xmlns:wicket="http://wicket.apache.org">
+    <body>
+        <wicket:panel>
+            <span wicket:id="feedback"></span>
+
+            <form wicket:id="signUpForm" role="form">
+                <div class="form-group" wicket:id="formGroup">
+                    <label wicket:for="email" class="control-label"><wicket:message key="emailLabel"/></label>
+                    <input type="text" class="form-control" wicket:id="email" wicket:message="placeholder:emailPlaceholder"/>
+                </div>
+
+                <button type="submit" wicket:id="signUp" class="btn btn-primary"><wicket:message key="signUpButtonLabel"/></button>
+            </form>
+
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.java
new file mode 100644
index 0000000..c765777
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/accmngt/signup/RegistrationFormPanel.java
@@ -0,0 +1,127 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.pages.accmngt.signup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.apache.isis.applib.services.email.EmailService;
+import org.apache.isis.applib.services.userreg.EmailNotificationService;
+import org.apache.isis.applib.services.userreg.events.EmailRegistrationEvent;
+import org.apache.isis.viewer.wicket.model.models.PageType;
+import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
+import org.apache.isis.viewer.wicket.ui.pages.EmailVerificationUrlService;
+import org.apache.isis.viewer.wicket.ui.pages.PageNavigationService;
+import org.apache.isis.viewer.wicket.ui.pages.accmngt.AccountManagementPageAbstract;
+import org.apache.isis.viewer.wicket.ui.pages.accmngt.EmailAvailableValidator;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.RequiredTextField;
+import org.apache.wicket.markup.html.form.StatelessForm;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.util.cookies.CookieUtils;
+import org.apache.wicket.validation.validator.EmailAddressValidator;
+
+import com.google.inject.name.Named;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel;
+
+/**
+ * A panel with a form for creation of new users
+ */
+public class RegistrationFormPanel extends Panel {
+
+    /**
+     * Constructor
+     *
+     * @param id
+     *            the component id
+     */
+    public RegistrationFormPanel(final String id) {
+        super(id);
+
+        addOrReplace(new NotificationPanel("feedback"));
+
+        StatelessForm<Void> form = new StatelessForm<>("signUpForm");
+        addOrReplace(form);
+
+        final RequiredTextField<String> emailField = new RequiredTextField<>("email", Model.of(""));
+        emailField.setLabel(new ResourceModel("emailLabel"));
+        emailField.add(EmailAddressValidator.getInstance());
+        emailField.add(EmailAvailableValidator.DOESNT_EXIST);
+
+        FormGroup formGroup = new FormGroup("formGroup", emailField);
+        form.add(formGroup);
+
+        formGroup.add(emailField);
+
+        Button signUpButton = new Button("signUp") {
+            @Override
+            public void onSubmit() {
+                super.onSubmit();
+
+                String email = emailField.getModelObject();
+                String confirmationUrl = emailVerificationUrlService.createVerificationUrl(PageType.SIGN_UP_VERIFY, email);
+
+                /**
+                 * We have to init() the services here because the Isis runtime is not available to us
+                 * (guice will have instantiated a new instance of the service).
+                 *
+                 * We do it this way just so that the programming model for the EmailService is similar to regular Isis-managed services.
+                 */
+                emailNotificationService.init();
+                emailService.init();
+
+                final EmailRegistrationEvent emailRegistrationEvent = new EmailRegistrationEvent(email, confirmationUrl, applicationName);
+                boolean emailSent = emailNotificationService.send(emailRegistrationEvent);
+                if (emailSent) {
+                    Map<String, String> map = new HashMap<>();
+                    map.put("email", email);
+                    String emailSentMessage = getString("emailSentMessage", Model.ofMap(map));
+
+                    CookieUtils cookieUtils = new CookieUtils();
+                    cookieUtils.save(AccountManagementPageAbstract.FEEDBACK_COOKIE_NAME, emailSentMessage);
+                    pageNavigationService.navigateTo(PageType.SIGN_IN);
+                }
+            }
+        };
+
+        form.add(signUpButton);
+    }
+
+    @Inject
+    private EmailNotificationService emailNotificationService;
+    @Inject
+    private EmailService emailService;
+
+    @Inject
+    private EmailVerificationUrlService emailVerificationUrlService;
+
+    @Inject
+    private PageNavigationService pageNavigationService;
+
+    @Inject
+    @Named("applicationName")
+    private String applicationName;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.css
new file mode 100644
index 0000000..eaeea17
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.css
@@ -0,0 +1,18 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.html
new file mode 100644
index 0000000..4fd4f02
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.html
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+	<body>
+		<wicket:extend>
+			<div class="actionPromptPage">
+				<div wicket:id="bookmarks"></div>
+				<div class="row">
+					<div class="col-xs-offset-2 col-xs-8">
+						<div wicket:id="actionPrompt"></div>
+					</div>
+				</div>
+			</div>
+		</wicket:extend>
+	</body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.java
new file mode 100644
index 0000000..66d27ff
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/actionprompt/ActionPromptPage.java
@@ -0,0 +1,66 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.pages.actionprompt;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+
+/**
+ * Web page representing an action invocation.
+ */
+@AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER")
+public class ActionPromptPage extends PageAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * For use with {@link Component#setResponsePage(org.apache.wicket.Page)}
+     */
+    public ActionPromptPage(final ActionModel model) {
+        super(new PageParameters(), model.getActionMemento().getAction().getName(), ComponentType.ACTION_PROMPT);
+        addChildComponents(themeDiv, model);
+
+        if(model.isBookmarkable()) {
+            bookmarkPage(model);
+        }
+        addBookmarkedPages(themeDiv);
+    }
+
+    public ActionPromptPage(final PageParameters pageParameters) {
+        this(pageParameters, buildModel(pageParameters));
+    }
+    
+    public ActionPromptPage(final PageParameters pageParameters, final ActionModel model) {
+        super(pageParameters, model.getActionMemento().getAction().getName(), ComponentType.ACTION_PROMPT);
+        addChildComponents(themeDiv, model);
+        
+        // no need to bookmark because the ActionPanel will have done so for us
+        addBookmarkedPages(themeDiv);
+    }
+    
+    private static ActionModel buildModel(final PageParameters pageParameters) {
+        return ActionModel.createForPersistent(pageParameters);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-darkly.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-darkly.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-darkly.css
new file mode 100644
index 0000000..dae7b57
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-darkly.css
@@ -0,0 +1,23 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+.bootstrap-datetimepicker-widget {
+    background-color: #ffffff;
+    color: #000000;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css
new file mode 100644
index 0000000..626f843
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-flatly.css
@@ -0,0 +1,28 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+.select2-container.input-sm .select2-choice,
+.input-group-sm .select2-container .select2-choice {
+    height: 33px;
+}
+
+.select2-container.select2-container-disabled .select2-choice,
+.select2-container.select2-container-disabled .select2-choices {
+    background-color: #ecf0f1;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-sandstone.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-sandstone.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-sandstone.css
new file mode 100644
index 0000000..df9795b
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides-sandstone.css
@@ -0,0 +1,22 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+.input-group-sm > .input-group-addon {
+    padding: 0 11px;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
new file mode 100644
index 0000000..682ae6a
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
@@ -0,0 +1,723 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+body {
+    padding-top: 60px;
+}
+
+.table .form-control:disabled {
+    background-color: transparent;
+    border: none;
+    text-align: center;
+    height: 23px;
+    padding: 1px 0;
+    cursor: default;
+    outline: none;
+    -webkit-box-shadow: none;
+    -moz-box-shadow: none;
+    box-shadow: none;
+}
+
+.table > thead > tr > th, td {
+    text-align: left;
+    vertical-align: middle;
+}
+
+.navbar {
+    border-radius: 0;
+}
+
+#veil {
+    z-index: 40000;
+    background-image: none;
+    background-color: black;
+
+    display: none;
+    position:fixed;
+    top:0;
+    left:0;
+    height: 100%;
+    width: 100%;
+    opacity: 0.5;
+    filter: alpha(opacity=50);
+}
+
+.table .table td {
+    border: none;
+}
+
+.pagination {
+    margin: 0;
+}
+
+
+
+/* from ActionPromptHeaderPanel */
+
+.entityIconAndTitlePanel img {
+    width: 24px;
+    height: 24px;
+}
+
+.entityIconAndTitlePanel span.actionName {
+    font-size: 20px;
+    font-weight: bolder;
+}
+
+
+/* from SimpleClipboardPanel */
+
+.simpleClipboardPanel form {
+    margin: 20px;
+    background-color: white;
+}
+
+.simpleClipboardPanel div.inner {
+    margin: 20px;
+    width:640px;
+}
+
+.simpleClipboardPanel div.inner p.scalarName {
+    padding-top: 40px;
+    padding-bottom: 10px;
+}
+
+.simpleClipboardPanel form input.textField {
+    width:600px;
+    margin-bottom: 60px;
+}
+
+.simpleClipboardPanel form input.ok {
+    margin-bottom: 20px;
+}
+
+
+
+/* from CollectionContentsAsAjaxTablePanel.css */
+
+.collectionContentsAsAjaxTablePanel table.contents {
+    font-size: 0.9em;
+    width: 100%;
+    border-collapse:collapse;
+    margin-top:10px;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents caption { text-align: left; }
+.collectionContentsAsAjaxTablePanel table.contents tr {
+}
+
+
+.collectionContentsAsAjaxTablePanel table.contents tr td {
+    padding-left: 4px;
+    padding-right: 4px;
+}
+.collectionContentsAsAjaxTablePanel table.contents tr th,
+.collectionContentsAsAjaxTablePanel table.contents tr th a span {
+    text-align: left;
+    white-space: nowrap;
+    font-weight: bold;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents tr th a {
+    font-weight: normal;
+}
+.collectionContentsAsAjaxTablePanel table.contents #message {
+    padding-left: 3px;
+}
+.collectionContentsAsAjaxTablePanel table.contents caption {
+    padding-bottom: 2px;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents input:disabled {
+    background-color: transparent;
+    border: none;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents .javaMathBigDecimalPanel,
+.collectionContentsAsAjaxTablePanel table.contents .javaMathBigIntegerPanel,
+.collectionContentsAsAjaxTablePanel table.contents .bytePanel,
+.collectionContentsAsAjaxTablePanel table.contents .shortPanel,
+.collectionContentsAsAjaxTablePanel table.contents .integerPanel,
+.collectionContentsAsAjaxTablePanel table.contents .longPanel,
+.collectionContentsAsAjaxTablePanel table.contents .floatPanel,
+.collectionContentsAsAjaxTablePanel table.contents .doublePanel {
+    text-align: right;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents tbody td,
+.collectionContentsAsAjaxTablePanel table.contents thead th {
+    padding:5px;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents tr.navigation div.navigatorLabel {
+    float: left;
+}
+
+
+.collectionContentsAsAjaxTablePanel table.contents tr.navigation div.navigator {
+    float: right;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents img {
+    width: 16px;
+    height: 16px;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents tbody .togglebox-column {
+    width: 2%;
+}
+.collectionContentsAsAjaxTablePanel table.contents thead .title-column,
+.collectionContentsAsAjaxTablePanel table.contents tbody .title-column {
+    text-align: center;
+    width: 3%;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents a:hover {
+    text-decoration:underline;
+}
+
+.collectionContentsAsAjaxTablePanel table.contents .entityLinkSelect2Panel .entityImage {
+    padding-right:6px;
+}
+
+.collectionContentsAsAjaxTablePanel table tfoot {
+    margin-top:20px;
+}
+
+.collectionContentsAsAjaxTablePanel table tfoot tr td {
+    padding:20px 4px 0;
+    /*background-color:#FFFFFF !important;*/
+}
+
+.collectionContentsAsAjaxTablePanel .entityActions {
+    margin-top: -1px;
+    margin-bottom: -10px;
+    float: left;
+    padding:0 0;
+}
+
+/* bootstrap seems to set to 'pointer' */
+.collectionContentsAsAjaxTablePanel label:hover {
+    /*cursor: default;*/
+}
+
+.collectionContentsAsAjaxTablePanel div input[type=text][disabled] {
+    padding: 0;
+}
+
+.collectionContentsAsAjaxTablePanel table {
+    border: none;
+}
+
+.collectionContentsAsAjaxTablePanel table tr td:first-child,
+.collectionContentsAsAjaxTablePanel table tr th:first-child {
+    border-left: none;
+}
+
+.collectionContentsAsAjaxTablePanel table tr th:last-child,
+.collectionContentsAsAjaxTablePanel table tr td:last-child {
+    border-right: none;
+}
+
+.collectionContentsAsAjaxTablePanel .table-responsive {
+    overflow-x: auto;
+    padding-bottom: 10px;
+}
+
+.collectionContentsAsAjaxTablePanel table tbody tr:last-child td {
+    border-bottom: none;
+}
+
+.collectionContentsAsAjaxTablePanel table tfoot tr:first-child td {
+    border-top: none;
+    border-bottom: none;
+}
+
+.collectionContentsAsAjaxTablePanel .table {
+    margin-bottom: 0px;
+}
+
+
+/* from CollectionContentsMultipleViewsPanel.css */
+/* AND ALSO duplicated in from EntityLinksSelectorPanel.css */
+
+.linksSelectorPanel .viewLinks {
+    float:right;
+    display:block;
+}
+
+.linksSelectorPanel ul.dropdown-menu {
+    min-width: 0;
+}
+
+.linksSelectorPanel ul.dropdown-menu li.viewItem {
+    min-width: 0;
+}
+
+.linksSelectorPanel ul.viewList li.viewItem:first-child span {
+    border-radius:4px 0 0 4px;
+    -moz-border-radius:4px 0 0 4px;
+    -webkit-border-radius:4px 0 0 4px;
+}
+
+.linksSelectorPanel ul.viewList li.viewItem:last-child span {
+    border-radius:0 4px 4px 0;
+    -moz-border-radius:0 4px 4px 0;
+    -webkit-border-radius:0 4px 4px 0;
+}
+
+
+.linksSelectorPanel .link-selector-panel-invisible {
+    display:none;
+}
+
+.linksSelectorPanel .list-inline {
+    margin-left: 0;
+}
+
+.linksSelectorPanel .list-inline li {
+    padding-left: 0;
+}
+
+
+.collectionContentsLinksSelectorPanel select {
+    margin-bottom: 1em;
+}
+
+
+/* from CollectionContentsAsSummary */
+
+.collectionContentsAsSummary {
+    padding-top: 15px;
+}
+
+.collectionContentsAsSummary .propertyNameCell,
+.collectionContentsAsSummary .aggregatesCell {
+    vertical-align: middle;
+}
+
+.collectionContentsAsSummary .aggregateName {
+    font-style: normal;
+    text-align: left;
+    font-weight: bold !important;
+    font-size: 0.9em;
+    padding-left: 20px;
+    padding-right: 10px;
+    vertical-align: middle;
+}
+
+.collectionContentsAsSummary .numberValue {
+    text-align: right;
+    width: 80px;
+}
+
+.collectionContentsAsSummary .chart {
+    margin-left: 30px;
+    display: inline-block;
+    min-width: 720px;
+}
+
+/*
+a span.ViewLinkItem.summary {
+    background-image:url("./icon_summary_on.png");
+    background-position: center center;
+    background-repeat:no-repeat;
+}
+
+span.ViewLinkItem.summary {
+    background-image:url("./icon_summary_off.png");
+    background-position: center center;
+    background-repeat:no-repeat;
+}
+*/
+
+
+/* from EntityHeaderPanel.css */
+
+.entityHeaderPanel {
+    clear:both;
+    padding-top:10px;
+    display:block;
+}
+
+div.entityHeaderPanel .iconAndTitle{
+    float: left;
+    padding:0;
+    padding-bottom: 5px;
+    width: 100%;
+}
+
+div.entityHeaderPanel .iconAndTitleLabel {
+    float: left;
+}
+
+div.entityHeaderPanel .entityActions .cssMenuPanel .cssMenuItems:first-child {
+    float: left;
+    margin-top: 3px;
+    margin-left: 20px;
+}
+
+.entityHeaderPanel .entityImage {
+    width: 32px;
+    height: 32px;
+    vertical-align:text-bottom;
+}
+
+.entityHeaderPanel .entityTitle {
+    font-size: 1.8em;
+    font-weight:normal;
+    text-decoration:none;
+}
+
+
+/* from BreadcrumbPanel.css */
+
+.breadcrumbPanel {
+    display: inline-block;
+    width: 300px;
+}
+
+
+/* from ContainedButtonPanel */
+
+span.containedButtonPanel {
+    display: inline;
+}
+
+.containedButtonPanel form {
+    display: inline;
+}
+
+
+/* from ZeroClipboardPanel */
+
+.zeroClipboardPanel .subscribingLink {
+    display: none;
+}
+
+.zeroClipboardPanel a:hover {
+    text-decoration: none;
+}
+
+.copyLink {
+    visibility: hidden;
+}
+
+
+/* other */
+
+.mandatory.scalarName:after,
+.mandatory.collectionName:after {
+    content: "*";
+    font-weight:bold;
+    color: #c2270d;
+}
+
+
+.navbar .powered-by {
+    margin-right: 0px;
+}
+
+
+
+
+
+
+/* from entityPropertiesPanel */
+
+
+.entityPropertiesPanel .properties.panel-body {
+    padding-bottom: 5px;
+}
+.entityPropertiesPanel .collection.panel-body {
+    padding-bottom: 0px;
+}
+
+
+
+/* from additionalLinksPanel.css */
+
+span .fa {
+    padding-right: 2px;
+}
+
+.additionalLinkList {
+    float:left;
+    margin:0;
+    padding:0;
+    list-style:none;
+}
+
+ul.additionalLinkList,
+div.additionalLinkList {
+    padding-bottom: 10px;
+}
+
+.standaloneCollectionPanel div.additionalLinkList,
+.standaloneCollectionPanel ul.additionalLinkList,
+.entityCollectionsPanel div.additionalLinkList,
+.entityCollectionsPanel ul.additionalLinkList {
+    padding-bottom: 0px;
+}
+
+
+
+
+
+
+
+
+
+.entityPropertiesPanel .additionalLinks,
+.entityCollectionsPanel .additionalLinksAndSelectorDropDown {
+    margin-top: -4px;
+}
+
+.collection.panel-body {
+    padding-top: 0px;
+}
+
+.collectionPanel .well {
+    background-color: transparent;
+    margin-bottom: 0px;
+}
+
+
+
+.nav > li > a {
+    padding-left: 10px;
+    padding-right: 10px;
+}
+
+/* fix for Firefox */
+th > a > div > strong {
+    float: left;
+}
+
+/* Labels on the left/top/none START */
+
+.form-group {
+    margin-bottom: 0;
+}
+
+
+div.label-left.form-group {
+    width: 100%;
+}
+
+div.label-left label.control-label {
+    width: 30%;
+    float: left;
+    padding-top: 2px;
+    text-align: left;
+}
+
+.actionParametersForm .label-left label.control-label {
+    padding-left: 10px;
+}
+
+div.label-top label.control-label {
+    padding-left: 10px;
+    padding-bottom: 4px;
+}
+
+div.label-none label.control-label {
+    display: none;
+}
+
+div.label-left .scalarValueWrapper {
+    width: 70%;
+    float: left;
+}
+
+div.label-left.actions-right .scalarValueWrapper {
+    width: 62%;
+}
+
+.actions-right .additionalLinkListDropDown {
+    float:right;
+    /*width: 3%;*/
+}
+
+
+div.label-top .scalarValueWrapper,
+div.label-none .scalarValueWrapper {
+    width: 99.5%;
+    display: block;
+    padding-left: 8px;
+    padding-right: 20px;
+}
+
+.modal-body div.label-top .scalarValueWrapper,
+.modal-body div.label-none .scalarValueWrapper {
+    padding-right: 14px;
+}
+
+div.label-left .scalarValueWrapper .form-control {
+    width: 100%;
+}
+
+.file-preview-thumbnails {
+    overflow: auto;
+}
+
+div.label-left .scalarValueWrapper .input-group {
+    width: 100%;
+}
+
+div.label-left .scalarValueWrapper .input-group .input-group-addon {
+    width: 1%;
+}
+
+div.label-left .choicesPlaceholder {
+    display: inline-block;
+    width: 100%;
+    vertical-align: -webkit-baseline-middle;
+    vertical-align: middle;
+}
+
+div.label-right .scalarValueWrapper {
+    padding-left: 28.5%;
+}
+
+div.label-right .scalarValueWrapper .control-label{
+    vertical-align: sub;
+}
+/* Labels on the left/top/none END */
+
+
+.form-horizontal.actionParametersForm .form-group {
+    margin-left: -5px;
+}
+
+.form-horizontal.inputForm .form-group {
+    margin-left: 0px;
+    margin-right: -25px;
+}
+
+.form-horizontal.inputForm .form-group.label-none,
+.form-horizontal.inputForm .form-group.label-top {
+    margin-left: -10px;
+}
+
+
+.scalarValueWrapper textarea {
+    resize: vertical;
+}
+
+
+.standaloneCollectionPanel .additionalLinkList {
+    margin-left: 50px;
+    margin-bottom: 0px;
+    margin-top: -4px;
+}
+.standaloneCollectionPanel .selectorDropdown {
+    margin-top: -4px;
+}
+.standaloneCollectionPanel div.iconAndTitle {
+    min-height: 45px;
+}
+
+div.referencePanel.scalarNameAndValueComponentType {
+    margin-bottom: 4px;
+}
+
+.referencePanel .entityLinkSelect2Panel .entityImage {
+    width: 20px;
+    height: 20px;
+}
+
+.referencePanel .form-group.label-left .scalarName.control-label {
+    padding-right: 10px;
+}
+
+.referencePanel .form-group.label-left .scalarValueWrapper .entityLinkSelect2Panel{
+    padding-top: 4px;
+    padding-bottom: 3px;
+}
+
+.prototype {
+    font-style: italic;
+}
+
+.actionParametersForm .buttons {
+    padding-top: 20px;
+}
+
+.entityCollectionsPanel .panel-heading {
+    padding-bottom: 10px;
+}
+.standaloneCollectionPanel .panel-heading {
+    padding-bottom: 5px; /* different from entityCollectionsPanel because of display-inline ? of additionalLinks */
+}
+
+#body {
+    padding-top: 20px;
+}
+
+.additionalLinks.pull-right {
+    margin-right: 5px;
+}
+
+.additionalLinks.pull-right div {
+    display: inline-block;
+    margin-left: 5px;
+}
+
+
+.scalarValueWrapper ul.additionalLinkList {
+    padding-bottom: 5px;
+}
+
+.scalarValueWrapper ul.additionalLinkListInline li.additionalLinkItem {
+    padding-bottom: 5px;
+}
+
+.scalarValueWrapper .help-block {
+    margin-bottom: 5px;
+}
+
+.scalarValueWrapper .help-block ul {
+    margin-bottom: 0px;
+}
+
+.scalarValueWrapper .help-block .alert {
+    margin-bottom: 0px;
+}
+
+.navbar-header a.navbar-brand {
+    margin-top: -2px;
+}
+
+.valueChoicesSelect2Panel .scalarValueWrapper .choicesPlaceholder {
+    height: 33px;
+}
+
+.ui-draggable .modal-header {
+    cursor: move;
+}
+
+.navigatorLabel .btn-link {
+    margin-top: -2px;
+    text-decoration: underline;
+}
+
+tr.headers th form input {
+    margin-left: -8px;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png
new file mode 100644
index 0000000..e9473c8
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/copy-26.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
new file mode 100644
index 0000000..eaeea17
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
@@ -0,0 +1,18 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
new file mode 100644
index 0000000..1caad01
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org"
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:extend>
+            <div class="entityPage" wicket:id="entityPageContainer">
+                <div wicket:id="bookmarks"></div>
+                <div wicket:id="entity"></div>
+            </div>
+        </wicket:extend>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
new file mode 100644
index 0000000..69dc4b6
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
@@ -0,0 +1,247 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.pages.entity;
+
+import java.util.List;
+import org.apache.wicket.Application;
+import org.apache.wicket.RestartResponseException;
+import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.model.AbstractReadOnlyModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.util.string.Strings;
+
+import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
+import org.apache.isis.core.metamodel.consent.InteractionResult;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
+import org.apache.isis.core.metamodel.interactions.InteractionUtils;
+import org.apache.isis.core.metamodel.interactions.ObjectVisibilityContext;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.runtime.system.DeploymentType;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.common.PageParametersUtils;
+import org.apache.isis.viewer.wicket.model.hints.IsisUiHintEvent;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.components.widgets.breadcrumbs.BreadcrumbModel;
+import org.apache.isis.viewer.wicket.ui.components.widgets.breadcrumbs.BreadcrumbModelProvider;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+/**
+ * Web page representing an entity.
+ */
+@AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER")
+public class EntityPage extends PageAbstract {
+
+    private static final long serialVersionUID = 1L;
+    
+    private final EntityModel model;
+
+    /**
+     * Called reflectively, in support of 
+     * {@link BookmarkablePageLink bookmarkable} links.
+     */
+    public EntityPage(final PageParameters pageParameters) {
+        this(pageParameters, createEntityModel(pageParameters));
+    }
+
+    /**
+     * Creates an EntityModel from the given page parameters.
+     * Redirects to the application home page if there is no OID in the parameters.
+     *
+     * @param parameters The page parameters with the OID
+     * @return An EntityModel for the requested OID
+     */
+    private static EntityModel createEntityModel(final PageParameters parameters) {
+        String oid = EntityModel.oidStr(parameters);
+        if (Strings.isEmpty(oid)) {
+            throw new RestartResponseException(Application.get().getHomePage());
+        }
+        return new EntityModel(parameters);
+    }
+
+    private EntityPage(final PageParameters pageParameters, final EntityModel entityModel) {
+        this(pageParameters, entityModel, null);
+    }
+
+    public EntityPage(final ObjectAdapter adapter) {
+        this(adapter, null);
+    }
+
+    /**
+     * Ensure that any {@link ConcurrencyException} that might have occurred already
+     * (eg from an action invocation) is show.
+     */
+    public EntityPage(final ObjectAdapter adapter, final ConcurrencyException exIfAny) {
+        this(PageParametersUtils.newPageParameters(), newEntityModel(adapter, exIfAny));
+    }
+
+    private static EntityModel newEntityModel(
+            final ObjectAdapter adapter,
+            final ConcurrencyException exIfAny) {
+        final EntityModel model = new EntityModel(adapter);
+        model.setException(exIfAny);
+        return model;
+    }
+
+    private EntityPage(
+            final PageParameters pageParameters,
+            final EntityModel entityModel,
+            final String titleString) {
+        super(pageParameters, titleString, ComponentType.ENTITY);
+
+        this.model = entityModel;
+
+        final ObjectAdapter objectAdapter;
+        try {
+            // check object still exists
+            objectAdapter = entityModel.getObject();
+        } catch(final RuntimeException ex) {
+            removeAnyBookmark(model);
+            removeAnyBreadcrumb(model);
+
+            // we throw an authorization exception here to avoid leaking out information as to whether the object exists or not.
+            throw new ObjectMember.AuthorizationException(ex);
+        }
+
+        // check that the entity overall can be viewed.
+        if(!isVisible(objectAdapter)) {
+            throw new ObjectMember.AuthorizationException();
+        }
+
+        // belt-n-braces: check that at least one property of the entity can be viewed.
+        final AuthenticationSession session = getAuthenticationSession();
+        final ObjectSpecification specification = objectAdapter.getSpecification();
+        final List<ObjectAssociation> visibleAssociation = specification.getAssociations(Contributed.INCLUDED, ObjectAssociation.Filters.dynamicallyVisible(session, objectAdapter, Where.NOWHERE));
+
+        if(visibleAssociation.isEmpty()) {
+            final List<ObjectAssociation> anyAssociations = specification.getAssociations(Contributed.INCLUDED);
+            if(anyAssociations.isEmpty()) {
+                throw new NonRecoverableException(String.format(
+                        "No properties are defined for this entity type (%s); this is probably a programming error", specification.getFullIdentifier()));
+            }
+            throw new ObjectMember.AuthorizationException();
+        }
+
+
+        // the next bit is a work-around for JRebel integration...
+        // ... even though the IsisJRebelPlugin calls invalidateCache, it seems that there is 
+        // some caching elsewhere in the Wicket viewer meaning that stale metadata is referenced.
+        // doing an additional call here seems to be sufficient, though not exactly sure why... :-(
+        if(!getDeploymentType().isProduction()) {
+            getSpecificationLoader().invalidateCacheFor(objectAdapter.getObject());
+        }
+
+        if(titleString == null) {
+            final String titleStr = objectAdapter.titleString(null);
+            setTitle(titleStr);
+        }
+
+        WebMarkupContainer entityPageContainer = new WebMarkupContainer("entityPageContainer");
+        entityPageContainer.add(new CssClassAppender(new AbstractReadOnlyModel<String>() {
+            @Override
+            public String getObject() {
+                ObjectAdapter adapter = entityModel.getObject();
+                return adapter.getObject().getClass().getSimpleName();
+            }
+        }));
+        themeDiv.addOrReplace(entityPageContainer);
+
+        addChildComponents(entityPageContainer, model);
+        
+        // bookmarks and breadcrumbs
+        bookmarkPage(model);
+        addBreadcrumb(entityModel);
+
+        addBookmarkedPages(entityPageContainer);
+
+
+        // TODO mgrigorov: Zero Clipboard has been moved to EntityIconAndTitlePanel where the entity model is available.
+        // Is this still needed for something else ?!
+        //
+        // ensure the copy link holds this page.
+        send(this, Broadcast.BREADTH, new IsisUiHintEvent(entityModel, null));
+    }
+
+    private boolean isVisible(final ObjectAdapter input) {
+        final InteractionResult visibleResult = InteractionUtils.isVisibleResult(input.getSpecification(), createVisibleInteractionContext(input));
+        return visibleResult.isNotVetoing();
+    }
+
+    private VisibilityContext<?> createVisibleInteractionContext(final ObjectAdapter objectAdapter) {
+        return new ObjectVisibilityContext(
+                getDeploymentCategory(),
+                getAuthenticationSession(),
+                InteractionInvocationMethod.BY_USER,
+                objectAdapter,
+                objectAdapter.getSpecification().getIdentifier(),
+                Where.OBJECT_FORMS);
+    }
+
+
+
+    private void addBreadcrumb(final EntityModel entityModel) {
+        final BreadcrumbModelProvider session = (BreadcrumbModelProvider) getSession();
+        final BreadcrumbModel breadcrumbModel = session.getBreadcrumbModel();
+        breadcrumbModel.visited(entityModel);
+    }
+
+    private void removeAnyBreadcrumb(final EntityModel entityModel) {
+        final BreadcrumbModelProvider session = (BreadcrumbModelProvider) getSession();
+        final BreadcrumbModel breadcrumbModel = session.getBreadcrumbModel();
+        breadcrumbModel.remove(entityModel);
+    }
+
+    /**
+     * A rather crude way of intercepting the redirect-and-post strategy.
+     * 
+     * <p>
+     * Performs eager loading of corresponding {@link EntityModel}, with
+     * {@link ConcurrencyChecking#NO_CHECK no} concurrency checking.
+     */
+    @Override
+    protected void onBeforeRender() {
+        this.model.load(ConcurrencyChecking.NO_CHECK);
+        super.onBeforeRender();
+    }
+
+    private DeploymentType getDeploymentType() {
+        return IsisContext.getDeploymentType();
+    }
+
+    protected DeploymentCategory getDeploymentCategory() {
+        return getDeploymentType().getDeploymentCategory();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
new file mode 100644
index 0000000..5412494
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
@@ -0,0 +1,21 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
new file mode 100644
index 0000000..3c7a1ca
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:extend>
+            <div class="errorPage">
+                <div wicket:id="bookmarks"></div>
+                <div wicket:id="exceptionStackTrace"></div>
+            </div>
+        </wicket:extend>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
new file mode 100644
index 0000000..ef22601
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.pages.error;
+
+import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.isis.viewer.wicket.model.common.PageParametersUtils;
+import org.apache.isis.viewer.wicket.ui.errors.ExceptionModel;
+import org.apache.isis.viewer.wicket.ui.errors.ExceptionStackTracePanel;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+
+/**
+ * Web page representing the home page (showing a welcome message).
+ */
+@AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER")
+public class ErrorPage extends PageAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_EXCEPTION_STACK_TRACE = "exceptionStackTrace";
+
+
+    public ErrorPage(ExceptionModel exceptionModel) {
+        super(PageParametersUtils.newPageParameters(), null);
+
+        addBookmarkedPages(themeDiv);
+
+        themeDiv.add(new ExceptionStackTracePanel(ID_EXCEPTION_STACK_TRACE, exceptionModel));
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.css
new file mode 100644
index 0000000..eaeea17
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.css
@@ -0,0 +1,18 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
new file mode 100644
index 0000000..a63f302
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.html
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:extend>
+            <div class="homePage">
+                <div wicket:id="bookmarks"></div>
+                <div wicket:id="welcome"></div>
+                <div class="row">
+                    <div class="col-xs-offset-2 col-xs-8">
+                        <div wicket:id="actionPrompt"></div>
+                    </div>
+                </div>
+            </div>
+        </wicket:extend>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
new file mode 100644
index 0000000..56a5ab4
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/home/HomePage.java
@@ -0,0 +1,109 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.pages.home;
+
+import java.util.List;
+import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+
+/**
+ * Web page representing the home page (showing a welcome message).
+ */
+@AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER")
+public class HomePage extends PageAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    public HomePage(final PageParameters parameters) {
+        super(parameters, null);
+        
+        addChildComponents(themeDiv, null);
+        buildGui();
+
+        addBookmarkedPages(themeDiv);
+    }
+
+    private void buildGui() {
+        final ObjectAndAction objectAndAction = lookupHomePageAction();
+        if(objectAndAction != null) {
+            Components.permanentlyHide(themeDiv, ComponentType.WELCOME); 
+            final IModel<?> actionModel = ActionModel.create(objectAndAction.objectAdapter, objectAndAction.action);
+            getComponentFactoryRegistry().addOrReplaceComponent(themeDiv, ComponentType.ACTION_PROMPT, actionModel);
+        } else {
+            Components.permanentlyHide(themeDiv, ComponentType.ACTION_PROMPT);
+            getComponentFactoryRegistry().addOrReplaceComponent(themeDiv, ComponentType.WELCOME, null);
+        }
+    }
+
+    private static class ObjectAndAction {
+        ObjectAndAction(final ObjectAdapter serviceAdapter, final ObjectAction objectAction) {
+            this.objectAdapter = serviceAdapter;
+            action = objectAction;
+        }
+        ObjectAdapter objectAdapter;
+        ObjectAction action;
+    }
+    
+    private ObjectAndAction lookupHomePageAction() {
+        final List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
+        for (final ObjectAdapter serviceAdapter : serviceAdapters) {
+            final ObjectSpecification serviceSpec = serviceAdapter.getSpecification();
+            final List<ObjectAction> objectActions = serviceSpec.getObjectActions(Contributed.EXCLUDED);
+            for (final ObjectAction objectAction : objectActions) {
+                final ObjectAndAction oaa = objectAndActionIfHomePageAndUsable(serviceAdapter, objectAction);
+                if(oaa != null) {
+                    return oaa;
+                }
+            }
+        }
+        return null;
+    }
+
+    private ObjectAndAction objectAndActionIfHomePageAndUsable(ObjectAdapter serviceAdapter, ObjectAction objectAction) {
+        if (!objectAction.containsDoOpFacet(HomePageFacet.class)) {
+            return null;
+        }
+
+        final Consent visibility = objectAction.isVisible(getAuthenticationSession(), serviceAdapter, Where.ANYWHERE);
+        if (visibility.isVetoed()) {
+            return null;
+        }
+
+        final Consent usability = objectAction.isUsable(getAuthenticationSession(), serviceAdapter, Where.ANYWHERE);
+        if (usability.isVetoed()) {
+            return  null;
+        }
+
+        return new ObjectAndAction(serviceAdapter, objectAction);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/bg_header_brown.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/bg_header_brown.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/bg_header_brown.png
new file mode 100644
index 0000000..402a311
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/bg_header_brown.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/icon_appuser.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/icon_appuser.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/icon_appuser.png
new file mode 100644
index 0000000..cdf4f49
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/icon_appuser.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.pdn
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.pdn b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.pdn
new file mode 100644
index 0000000..4d7e169
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.pdn differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.png
new file mode 100644
index 0000000..ed41531
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/images/logo.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/animated-overlay.gif
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/animated-overlay.gif b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/animated-overlay.gif
new file mode 100644
index 0000000..d441f75
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/animated-overlay.gif differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_0_aaaaaa_40x100.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_0_aaaaaa_40x100.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..6f92c98
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_0_aaaaaa_40x100.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_75_ffffff_40x100.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_75_ffffff_40x100.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000..1751a49
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_flat_75_ffffff_40x100.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_55_40c0cb_1x400.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_55_40c0cb_1x400.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_55_40c0cb_1x400.png
new file mode 100644
index 0000000..e057450
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_55_40c0cb_1x400.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_65_ffffff_1x400.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_65_ffffff_1x400.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000..0e62fc1
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_65_ffffff_1x400.png differ

http://git-wip-us.apache.org/repos/asf/isis/blob/99094b7e/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_75_dadada_1x400.png
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_75_dadada_1x400.png b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000..887b2a0
Binary files /dev/null and b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/isis-wicket-theme/images/ui-bg_glass_75_dadada_1x400.png differ