// 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; import com.google.common.collect.Lists; 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.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiFactory; 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.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Anchor; 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.DeckPanel; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; 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.view.widgets.ProjectFavoriteStar; import com.google.testing.testify.risk.frontend.client.view.widgets.PageHeaderWidget; import com.google.testing.testify.risk.frontend.model.Project; import com.google.testing.testify.risk.frontend.shared.rpc.ProjectRpcAsync; import com.google.testing.testify.risk.frontend.shared.rpc.TestProjectCreatorRpc; import com.google.testing.testify.risk.frontend.shared.rpc.TestProjectCreatorRpcAsync; import com.google.testing.testify.risk.frontend.shared.rpc.UserRpc.ProjectAccess; import com.google.testing.testify.risk.frontend.shared.rpc.UserRpcAsync; import java.util.List; /** * Home page widget for Test Analytics. * * @author jimr@google.com (Jim Reardon) */ public class HomePage extends Composite { /** * Used to wire parent class to associated UI Binder. */ interface HomePageUiBinder extends UiBinder<Widget, HomePage> {} private static final HomePageUiBinder uiBinder = GWT.create(HomePageUiBinder.class); @UiField protected ListBox userProjectsListBox; @UiField protected CheckBox justMyProjectsCheckbox; @UiField protected Grid projectsGrid; @UiField protected Button createProjectButton; @UiField protected Button createTestProjectButton; @UiField protected Button createDataSourcesButton; @UiField protected DeckPanel newProjectPanel; @UiField protected TextBox newProjectName; @UiField protected Button newProjectOkButton; @UiField protected Button newProjectCancelButton; @UiField public VerticalPanel adminPanel; private List<Project> allProjects; private List<Long> starredProjects; private final ProjectRpcAsync projectService; private final UserRpcAsync userService; private TestProjectCreatorRpcAsync creatorService = null; private static final int GRID_COLUMNS = 3; // The widgets that are a part of the DeckPanel are created through the UI binder, in this order. private static final int DECK_WIDGET_NEW_BUTTON = 0; private static final int DECK_WIDGET_NAME_PANEL = 1; /** * Constructs a HomePage object. */ public HomePage(ProjectRpcAsync projectService, UserRpcAsync userService) { this.projectService = projectService; this.userService = userService; initWidget(uiBinder.createAndBindUi(this)); newProjectPanel.setAnimationEnabled(true); // The widgets that are a part of the DeckPanel are created through the UI binder. newProjectPanel.showWidget(DECK_WIDGET_NEW_BUTTON); justMyProjectsCheckbox.setValue(false); loadProjectList(); setAdminPanelVisibleIfAdmin(); } @UiFactory public PageHeaderWidget createPageHeaderWidget() { return new PageHeaderWidget(userService); } @UiHandler("createDataSourcesButton") public void onCreateDataSourcesClicked(ClickEvent event) { if (creatorService == null) { creatorService = GWT.create(TestProjectCreatorRpc.class); } creatorService.createStandardDataSources(TaCallback.getNoopCallback()); } @UiHandler("justMyProjectsCheckbox") void onJustMyProjectsCheckboxClicked(ClickEvent event) { updateProjectsList(); } @UiHandler("newProjectName") protected void onNewProjectEnter(KeyDownEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { doCreateProject(newProjectName.getText()); } } @UiHandler("newProjectOkButton") protected void onNewProjectOkClicked(ClickEvent event) { doCreateProject(newProjectName.getText()); } @UiHandler("newProjectCancelButton") protected void onNewProjectCancelClicked(ClickEvent event) { newProjectName.setText(""); newProjectPanel.showWidget(DECK_WIDGET_NEW_BUTTON); } @UiHandler("createProjectButton") void onCreateProjectButtonClicked(ClickEvent event) { newProjectPanel.showWidget(DECK_WIDGET_NAME_PANEL); newProjectName.setFocus(true); } @UiHandler("userProjectsListBox") void onSelectNewProject(ChangeEvent event) { int selectedIndex = userProjectsListBox.getSelectedIndex(); gotoProject(userProjectsListBox.getValue(selectedIndex)); } private void loadProjectList() { userService.getStarredProjects( new TaCallback<List<Long>>("querying starred projects") { @Override public void onSuccess(List<Long> result) { starredProjects = result; updateProjectsList(); } }); displayMessageInGrid("Loading project list..."); projectService.query("", new TaCallback<List<Project>>("querying projects") { @Override public void onSuccess(List<Project> result) { allProjects = result; updateProjectsList(); } }); } private void setAdminPanelVisibleIfAdmin() { userService.hasAdministratorAccess(new AsyncCallback<Boolean>() { @Override public void onSuccess(Boolean result) { if (result) { adminPanel.setVisible(true); } } @Override public void onFailure(Throwable caught) { return; } }); userService.isDevMode(new AsyncCallback<Boolean>() { @Override public void onSuccess(Boolean result) { if (result) { adminPanel.setVisible(true); } } @Override public void onFailure(Throwable caught) { return; } }); } private void doCreateProject(String projectName) { projectName = projectName.trim(); if (projectName.length() < 1) { Window.alert("Enter a valid project name."); return; } final Project newProject = new Project(); newProject.setName(projectName); projectService.createProject(newProject, new TaCallback<Long>("creating new project") { @Override public void onSuccess(Long result) { newProject.setProjectId(result); gotoProject(result.toString()); } }); } @UiHandler("createTestProjectButton") void onCreateTestProjectButtonClicked(ClickEvent event) { if (creatorService == null) { creatorService = GWT.create(TestProjectCreatorRpc.class); } creatorService.createTestProject( new TaCallback<Project>("creating new project") { @Override public void onSuccess(Project result) { gotoProject(result.getProjectId().toString()); } }); } /** * Displays a single message in place of the projects grid. */ private void displayMessageInGrid(String message) { projectsGrid.clear(); projectsGrid.resize(1, 1); projectsGrid.setWidget(0, 0, new Label(message)); } /** * Fills the list of projects on the HomePage widget with the given projects. Also replaces the * label describing the projects with the provided text. */ private void updateProjectsList() { if (allProjects != null && starredProjects != null) { List<Project> userProjects = Lists.newArrayList(); List<Project> publicProjects = Lists.newArrayList(); for (Project p : allProjects) { if (p.getCachedAccessLevel().hasAccess(ProjectAccess.EXPLICIT_VIEW_ACCESS)) { userProjects.add(p); } else if (starredProjects.contains(p.getProjectId())) { userProjects.add(p); } else { publicProjects.add(p); } } // Update drop-down. userProjectsListBox.clear(); userProjectsListBox.addItem("", ""); for (Project p : userProjects) { userProjectsListBox.addItem(p.getName(), p.getProjectId().toString()); } userProjectsListBox.setSelectedIndex(0); // Update the grid. if (justMyProjectsCheckbox.getValue().equals(false)) { userProjects.addAll(publicProjects); } // Special case for zero projects. if (userProjects.size() < 1) { displayMessageInGrid("No projects to display."); return; } projectsGrid.clear(); int rows = ((userProjects.size() - 1) / GRID_COLUMNS) + 1; projectsGrid.resize(rows, GRID_COLUMNS); for (int projectIndex = 0; projectIndex < userProjects.size(); projectIndex++) { final Project project = userProjects.get(projectIndex); ProjectFavoriteStar favoriteStar = new ProjectFavoriteStar(); favoriteStar.attachToProject(project.getProjectId()); if (starredProjects.contains(project.getProjectId())) { favoriteStar.setStarredStatus(true); } Anchor nameWidget = new Anchor(project.getName()); nameWidget.addStyleName("tty-HomePageProjectsGridProjectName"); HorizontalPanel projectWidget = new HorizontalPanel(); projectWidget.add(favoriteStar); projectWidget.add(nameWidget); projectWidget.addStyleName("tty-HomePageProjectsGridProject"); nameWidget.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { gotoProject(project.getProjectId().toString()); } }); int targetColumn = projectIndex % GRID_COLUMNS; int targetRow = projectIndex / GRID_COLUMNS; projectsGrid.setWidget(targetRow, targetColumn, projectWidget); } } } private void gotoProject(String projectId) { History.newItem("/" + projectId + "/project-details"); } }