/*
* Copyright (c) 2009-2011 Lockheed Martin Corporation
*
* Licensed 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.eurekastreams.web.client.ui.pages.settings;
import org.eurekastreams.commons.client.ActionProcessor;
import org.eurekastreams.server.domain.Page;
import org.eurekastreams.server.domain.SystemSettings;
import org.eurekastreams.server.domain.dto.MembershipCriteriaDTO;
import org.eurekastreams.web.client.events.EventBus;
import org.eurekastreams.web.client.events.MembershipCriteriaAddedEvent;
import org.eurekastreams.web.client.events.MembershipCriteriaRemovedEvent;
import org.eurekastreams.web.client.events.Observer;
import org.eurekastreams.web.client.events.ShowNotificationEvent;
import org.eurekastreams.web.client.events.data.GotSystemSettingsResponseEvent;
import org.eurekastreams.web.client.events.data.MembershipCriteriaPersistedEvent;
import org.eurekastreams.web.client.events.data.UpdatedSystemSettingsResponseEvent;
import org.eurekastreams.web.client.history.CreateUrlRequest;
import org.eurekastreams.web.client.model.SystemSettingsModel;
import org.eurekastreams.web.client.ui.Session;
import org.eurekastreams.web.client.ui.common.form.FormBuilder;
import org.eurekastreams.web.client.ui.common.form.FormBuilder.Method;
import org.eurekastreams.web.client.ui.common.form.elements.ActivityExpirationFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.BasicCheckBoxFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.BasicTextBoxFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.HideableRichTextAreaFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.HideableTextAreaFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.PersonModelViewLookupFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.TermsOfServicePromptIntervalFormElement;
import org.eurekastreams.web.client.ui.common.form.elements.userassociation.UserAssociationFormElement;
import org.eurekastreams.web.client.ui.common.notification.SendNotificationWidget;
import org.eurekastreams.web.client.ui.common.notifier.Notification;
import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
// TODO form needs to handle return input from action. it is not displaying errors back to the user. example.
// add more then 255 char into the TOS or a String where it should be an Int.
/**
* SystemSettings panel.
*
*/
public class SystemSettingsPanelComposite extends FlowPanel
{
/**
* Maximum email length.
*/
private static final int MAX_SITELABEL = 2000;
/**
* Maximum content warning length.
*/
private static final int MAX_CONTENT_WARNING = 2000;
/**
* Maximum group name length.
*/
private static final int MAX_GROUP_NAME = 50;
/**
* the processor.
*/
private final ActionProcessor processor;
/**
* the site Label CheckBox.
*/
private HideableTextAreaFormElement hideableSiteLabel;
/**
* The content Warning element.
*/
private HideableTextAreaFormElement hideableContentWarning;
/**
* The content Warning element.
*/
private HideableRichTextAreaFormElement hideablePluginWarning;
/**
* The activity expiration element.
*/
private ActivityExpirationFormElement activityExp;
/**
* The TOS text element.
*/
private HideableRichTextAreaFormElement tosElement;
/**
* The extra CL to hide the prompt Int form element.
*/
private final ClickListener hideTOSIntPanel;
/**
* The membership refresh button.
*/
private Label membershipRefreshButton;
/**
* The ToS prompt interval form element.
*/
private TermsOfServicePromptIntervalFormElement promptInterval;
/**
* Constructor.
*
* @param inProcessor
* The action processor.
*/
public SystemSettingsPanelComposite(final ActionProcessor inProcessor)
{
processor = inProcessor;
addStyleName(StaticResourceBundle.INSTANCE.coreCss().systemSettings());
hideTOSIntPanel = new ClickListener()
{
public void onClick(final Widget arg0)
{
if (tosElement.isChecked())
{
promptInterval.setVisible(true);
}
else
{
promptInterval.setVisible(false);
}
}
};
addObservers();
getSystemSettingsData();
}
/**
* Add event bus observers.
*/
private void addObservers()
{
EventBus eventBus = Session.getInstance().getEventBus();
eventBus.addObserver(MembershipCriteriaAddedEvent.class, new Observer<MembershipCriteriaAddedEvent>()
{
public void update(final MembershipCriteriaAddedEvent event)
{
if (event.isNew())
{
// TODO: Refactor to use new client models
processor.makeRequest("addMembershipCriteria", event.getMembershipCriteria(),
new AsyncCallback<Long>()
{
public void onFailure(final Throwable caught)
{
}
public void onSuccess(final Long persistedItemId)
{
SystemSettingsModel.getInstance().clearCache();
Session.getInstance()
.getEventBus()
.notifyObservers(
new ShowNotificationEvent(new Notification("Access List Saved")));
History.newItem(History.getToken());
MembershipCriteriaDTO result = event.getMembershipCriteria();
result.setId(persistedItemId);
Session.getInstance().getEventBus()
.notifyObservers(new MembershipCriteriaPersistedEvent(result));
}
});
}
}
});
eventBus.addObserver(MembershipCriteriaRemovedEvent.class, new Observer<MembershipCriteriaRemovedEvent>()
{
public void update(final MembershipCriteriaRemovedEvent event)
{
processor.makeRequest("removeMembershipCriteria", event.getMembershipCriteria().getId(),
new AsyncCallback<SystemSettings>()
{
public void onFailure(final Throwable caught)
{
}
public void onSuccess(final SystemSettings systemSettings)
{
// TODO: Refactor to use new client models
SystemSettingsModel.getInstance().clearCache();
Session.getInstance().getEventBus()
.notifyObservers(new ShowNotificationEvent(new Notification("Item Deleted")));
History.newItem(History.getToken());
}
});
}
});
}
/**
* Gets the system settings data and then builds the form.
*/
private void getSystemSettingsData()
{
processor.setQueueRequests(false);
Session.getInstance().getEventBus()
.addObserver(GotSystemSettingsResponseEvent.class, new Observer<GotSystemSettingsResponseEvent>()
{
public void update(final GotSystemSettingsResponseEvent event)
{
// Got the system settings - make sure it's the response with the system administrators loaded.
// If it's not, then it's the general settings response.
if (event.getResponse().getSystemAdministrators() != null)
{
// this is the response we were waiting for - unhook and generate the form
Session.getInstance().getEventBus()
.removeObserver(GotSystemSettingsResponseEvent.class, this);
generateForm(event.getResponse());
}
}
});
SystemSettingsModel.getInstance().fetch(new Boolean(true), false);
}
/**
* method to clear all retained data from elements.
*/
private void clearRetainedValues()
{
hideableSiteLabel.clearRetainedValue();
hideableContentWarning.clearRetainedValue();
activityExp.clearRetainedValue();
tosElement.clearRetainedValue();
if (!tosElement.isChecked())
{
promptInterval.setValue(1);
}
}
/**
* Builds the form.
*
* @param systemSettingValues
* The system settings to use when preloading the form.
*/
private void generateForm(final SystemSettings systemSettingValues)
{
this.clear();
final FormBuilder form = new FormBuilder("", SystemSettingsModel.getInstance(), Method.UPDATE);
Session.getInstance()
.getEventBus()
.addObserver(UpdatedSystemSettingsResponseEvent.class,
new Observer<UpdatedSystemSettingsResponseEvent>()
{
public void update(final UpdatedSystemSettingsResponseEvent arg1)
{
form.onSuccess();
Session.getInstance()
.getEventBus()
.notifyObservers(new ShowNotificationEvent(new Notification("Settings saved")));
clearRetainedValues();
}
});
form.setOnCancelHistoryToken(Session.getInstance().generateUrl(new CreateUrlRequest(Page.START)));
form.turnOffChangeCheck();
hideableSiteLabel = new HideableTextAreaFormElement(MAX_SITELABEL, "Site Labeling", "siteLabel",
systemSettingValues.getSiteLabel(), "I would like to add a label to the system.",
"The site label will be displayed above the global navigation bar and below the "
+ "footer on all pages in the system. If disabled, no label area will "
+ "appear on your pages.", true);
hideablePluginWarning = new HideableRichTextAreaFormElement("Plugin Configuration Warning", "pluginWarning",
systemSettingValues.getPluginWarning(),
"I would like to setup a plugin configuration warning for the system.",
"This text will be displayed everytime a user configures a plugin for an individual or group", true);
hideableContentWarning = new HideableTextAreaFormElement(MAX_CONTENT_WARNING, "Content Warning",
"contentWarningText", systemSettingValues.getContentWarningText(),
"I would like to add a warning to Activity Stream post boxes.",
"This text will be displayed on the Activity Stream post boxes throughout the system.", true);
activityExp = new ActivityExpirationFormElement(systemSettingValues.getContentExpiration(),
"contentExpiration", true);
tosElement = new HideableRichTextAreaFormElement("Terms Of Service", "termsOfService",
systemSettingValues.getTermsOfService(), "I would like to setup the Terms of Service for the system.",
"Users will be prompted to agree or disagree with a Terms of Service message "
+ "on an interval of your choice. You can also add a link to the full "
+ "Terms of Service document.", true);
tosElement.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hideableTextarea());
form.addFormElement(new PersonModelViewLookupFormElement("Eureka Administrators", "Add Administrator", "",
"admins", systemSettingValues.getSystemAdministrators(), true));
form.addFormDivider();
Integer promptVal = systemSettingValues.getTosPromptInterval();
if (null == promptVal)
{
promptVal = 1;
}
promptInterval = new TermsOfServicePromptIntervalFormElement(promptVal, "tosPromptInterval");
form.addFormElement(new UserAssociationFormElement(systemSettingValues));
BasicCheckBoxFormElement sendEmails = new BasicCheckBoxFormElement("", "sendWelcomeEmails",
"Send email invitations to new users as their accounts are created.", false,
systemSettingValues.getSendWelcomeEmails());
sendEmails.addStyleName(StaticResourceBundle.INSTANCE.coreCss().welcomeEmailCheckbox());
membershipRefreshButton = initializeRefreshButton();
FlowPanel clearPanel = new FlowPanel();
clearPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().clear());
sendEmails.add(membershipRefreshButton);
form.addFormElement(sendEmails);
form.addFormDivider();
form.addWidget(new SendNotificationWidget());
form.addFormDivider();
form.addFormElement(hideableSiteLabel);
form.addFormDivider();
form.addFormElement(hideableContentWarning);
form.addFormDivider();
form.addFormElement(hideablePluginWarning);
form.addFormDivider();
form.addFormElement(tosElement);
form.addFormElement(promptInterval);
form.addFormDivider();
// Help Page
form.addFormElement(new BasicTextBoxFormElement(MAX_GROUP_NAME, false, "Support Stream",
"supportStreamGroupShortName", systemSettingValues.getSupportStreamGroupShortName(),
"Enter the name of the stream you want to display on the help page", false));
form.addFormDivider();
form.addFormElement(activityExp);
form.addFormDivider();
BasicCheckBoxFormElement groupCreationPolicy = new BasicCheckBoxFormElement("New Group Moderation",
"allUsersCanCreateGroups", "Enable Moderation.",
"By enabling moderation, system administrators will be required to review new group requests. "
+ "Groups pending approval will be listed under the pending tab of system settings.", false,
!systemSettingValues.getAllUsersCanCreateGroups());
// The key is true for "allowing group creation" and the checkbox displays "allowing moderation". Since
// these are opposites, the value needs to be reversed when the form gets submitted.
groupCreationPolicy.setReverseValue(true);
form.addFormElement(groupCreationPolicy);
form.addFormDivider();
if (!tosElement.isChecked())
{
promptInterval.setVisible(false);
}
this.add(form);
tosElement.addCheckBoxClickListener(hideTOSIntPanel);
}
/**
* Setup for refresh button.
*
* @return newly configured label/button.
*/
private Label initializeRefreshButton()
{
Label button = new Label();
button.addStyleName(StaticResourceBundle.INSTANCE.coreCss().accessListRefreshButton());
button.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
processor.makeRequest("updateMembershipTaskHandler", null, new AsyncCallback<String>()
{
public void onFailure(final Throwable caught)
{
Session.getInstance()
.getEventBus()
.notifyObservers(
new ShowNotificationEvent(new Notification(
"An error occurred refreshing Access List")));
History.newItem(History.getToken());
}
public void onSuccess(final String value)
{
}
});
Session.getInstance()
.getEventBus()
.notifyObservers(
new ShowNotificationEvent(new Notification("Access List Refresh is now processing")));
History.newItem(History.getToken());
}
});
return button;
}
}