// Copyright 2010 Google Inc. All Rights Reseved.
//
// 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 com.google.testing.testify.risk.frontend.client.view.impl;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.testing.testify.risk.frontend.client.event.DialogClosedEvent;
import com.google.testing.testify.risk.frontend.client.event.DialogClosedEvent.DialogResult;
import com.google.testing.testify.risk.frontend.client.event.DialogClosedHandler;
import com.google.testing.testify.risk.frontend.client.view.ProjectSettingsView;
import com.google.testing.testify.risk.frontend.client.view.widgets.PageSectionVerticalPanel;
import com.google.testing.testify.risk.frontend.client.view.widgets.StandardDialogBox;
import com.google.testing.testify.risk.frontend.model.Project;
import com.google.testing.testify.risk.frontend.shared.rpc.UserRpc.ProjectAccess;
import com.google.testing.testify.risk.frontend.shared.util.StringUtil;
import java.util.List;
/**
* A widget for controlling the settings of a project.
*
* @author chrsmith@google.com (Chris Smith)
*/
public class ProjectSettingsViewImpl extends Composite implements ProjectSettingsView {
interface ProjectSettingsViewImplUiBinder extends UiBinder<Widget, ProjectSettingsViewImpl> {}
private static final ProjectSettingsViewImplUiBinder uiBinder =
GWT.create(ProjectSettingsViewImplUiBinder.class);
@UiField
public TextBox projectName;
@UiField
public TextArea projectDescription;
@UiField
public CheckBox projectIsPublicCheckBox;
@UiField
public TextBox projectOwnersTextBox;
@UiField
public TextArea projectEditorsTextArea;
@UiField
public TextArea projectViewersTextArea;
@UiField
public Button updateProjectInfoButton;
@UiField
public HorizontalPanel savedPanel;
@UiField
public VerticalPanel publicPanel;
@UiField
public CheckBox deleteProjectCheckBox;
@UiField
PageSectionVerticalPanel deleteApplicationSection;
// Handle to the underlying Presenter corresponding to this View.
private Presenter presenter;
private List<String> currentOwners;
private List<String> currentEditors;
private List<String> currentViewers;
/**
* Constructs a ProjectSettings object.
*/
public ProjectSettingsViewImpl() {
initWidget(uiBinder.createAndBindUi(this));
}
@UiHandler("projectOwnersTextBox")
protected void onOwnersChange(ChangeEvent event) {
projectOwnersTextBox.setText(StringUtil.trimAndReformatCsv(projectOwnersTextBox.getText()));
}
@UiHandler("projectEditorsTextArea")
protected void onEditorsChange(ChangeEvent event) {
projectEditorsTextArea.setText(StringUtil.trimAndReformatCsv(projectEditorsTextArea.getText()));
}
@UiHandler("projectViewersTextArea")
protected void onViewersChange(ChangeEvent event) {
projectViewersTextArea.setText(StringUtil.trimAndReformatCsv(projectViewersTextArea.getText()));
}
/**
* Handler for the updateProjectInfoButton's click event.
*/
@UiHandler("updateProjectInfoButton")
protected void onUpdateProjectInfoButtonClicked(ClickEvent event) {
savedPanel.setVisible(false);
updateProjectInfoButton.setEnabled(false);
if (presenter != null) {
if (deleteProjectCheckBox.getValue()) {
presenter.removeProject();
reloadPage();
} else {
final List<String> newOwners = StringUtil.csvToList(projectOwnersTextBox.getText());
final List<String> newEditors = StringUtil.csvToList(projectEditorsTextArea.getText());
final List<String> newViewers = StringUtil.csvToList(projectViewersTextArea.getText());
if (newOwners.size() < 1) {
Window.alert("Error: The project must have at least one owner.");
return;
}
StringBuilder warning = new StringBuilder();
List<String> difference = StringUtil.subtractList(newOwners, currentOwners);
if (difference.size() > 0) {
warning.append("<br><br><b>Added owners:</b> ");
warning.append(SafeHtmlUtils.htmlEscape(StringUtil.listToCsv(difference)));
}
difference = StringUtil.subtractList(currentOwners, newOwners);
if (difference.size() > 0) {
warning.append("<br><br><b>Removed owners:</b> ");
warning.append(SafeHtmlUtils.htmlEscape(StringUtil.listToCsv(difference)));
}
difference = StringUtil.subtractList(newEditors, currentEditors);
if (difference.size() > 0) {
warning.append("<br><br><b>Added editors:</b> ");
warning.append(SafeHtmlUtils.htmlEscape(StringUtil.listToCsv(difference)));
}
difference = StringUtil.subtractList(currentEditors, newEditors);
if (difference.size() > 0) {
warning.append("<br><br><b>Removed editors:</b> ");
warning.append(SafeHtmlUtils.htmlEscape(StringUtil.listToCsv(difference)));
}
difference = StringUtil.subtractList(newViewers, currentViewers);
if (difference.size() > 0) {
warning.append("<br><br><b>Added viewers:</b> ");
warning.append(SafeHtmlUtils.htmlEscape(StringUtil.listToCsv(difference)));
}
difference = StringUtil.subtractList(currentViewers, newViewers);
if (difference.size() > 0) {
warning.append("<br><br><b>Removed viewers:</b> ");
warning.append(SafeHtmlUtils.htmlEscape(StringUtil.listToCsv(difference)));
}
// If there's a warning to save, then display it and require confirmation before saving.
// Otherwise, just save.
if (warning.length() > 0) {
StandardDialogBox box = new StandardDialogBox();
box.setTitle("Permission Changes");
box.add(new HTML("You are changing some of the permissions for this project."
+ warning.toString() + "<br><br>"));
box.addDialogClosedHandler(new DialogClosedHandler() {
@Override
public void onDialogClosed(DialogClosedEvent event) {
if (event.getResult().equals(DialogResult.OK)) {
presenter.onUpdateProjectInfoClicked(projectName.getText(),
projectDescription.getText(), newOwners, newEditors, newViewers,
projectIsPublicCheckBox.getValue());
currentOwners = newOwners;
currentEditors = newEditors;
currentViewers = newViewers;
} else {
updateProjectInfoButton.setEnabled(true);
}
}
});
StandardDialogBox.showAsDialog(box);
} else {
presenter.onUpdateProjectInfoClicked(projectName.getText(), projectDescription.getText(),
newOwners, newEditors, newViewers, projectIsPublicCheckBox.getValue());
}
}
}
}
@Override
public void showSaved() {
updateProjectInfoButton.setEnabled(true);
savedPanel.setVisible(true);
Timer timer = new Timer() {
@Override
public void run() {
savedPanel.setVisible(false);
}
};
// Make the saved item disappear after 10 seconds.
timer.schedule(10000);
}
/**
* Handler for the deleteProjectButton's click event. Deletes the project.
*/
@UiHandler("deleteProjectCheckBox")
void onDeleteProjectCheckBoxChecked(ClickEvent event) {
String warningMessage = "This will permanently delete your project when you click save."
+ " Are you sure?";
if (!Window.confirm(warningMessage)) {
deleteProjectCheckBox.setValue(false);
}
}
/**
* Reloads the current web page.
*/
public void reloadPage() {
History.newItem("/homepage");
}
/**
* Binds this View to the given Presenter.
*/
@Override
public void setPresenter(Presenter presenter) {
this.presenter = presenter;
}
/** Updates the view to enable editing project data given the access level. */
@Override
public void enableProjectEditing(ProjectAccess userAccessLevel) {
// Enable certain controls only if they have OWNER access.
if (userAccessLevel.hasAccess(ProjectAccess.OWNER_ACCESS)) {
projectOwnersTextBox.setEnabled(true);
deleteApplicationSection.setVisible(true);
publicPanel.setVisible(true);
}
// Enable other widgets only if they have EDIT access.
if (userAccessLevel.hasAccess(ProjectAccess.EDIT_ACCESS)) {
projectName.setEnabled(true);
projectDescription.setEnabled(true);
projectEditorsTextArea.setEnabled(true);
projectViewersTextArea.setEnabled(true);
updateProjectInfoButton.setEnabled(true);
}
}
/**
* Updates the UI with the given project information.
*/
@Override
public void setProjectSettings(Project projectInformation) {
currentOwners = projectInformation.getProjectOwners();
currentEditors = projectInformation.getProjectEditors();
currentViewers = projectInformation.getProjectViewers();
projectName.setText(projectInformation.getName());
projectDescription.setText(projectInformation.getDescription());
projectOwnersTextBox.setText(StringUtil.listToCsv(currentOwners));
projectEditorsTextArea.setText(StringUtil.listToCsv(currentEditors));
projectViewersTextArea.setText(StringUtil.listToCsv(currentViewers));
projectIsPublicCheckBox.setValue(projectInformation.getIsPubliclyVisible());
}
}