/*
* Copyright (c) 2010, 2011 Mashery, Inc. All Rights Reserved.
*
* 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.mashery.examples.api.client;
import com.allen_sauer.gwt.dnd.client.DragContext;
import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.allen_sauer.gwt.dnd.client.drop.SimpleDropController;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.jsonp.client.JsonpRequestBuilder;
import com.google.gwt.maps.client.base.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.mashery.examples.api.client.etsy.EtsyService;
import com.mashery.examples.api.client.etsy.EtsyServiceAsync;
import com.mashery.examples.api.client.etsy.NotLoggedInException;
import com.mashery.examples.api.client.etsy.OAuthException;
import com.mashery.examples.api.client.etsy.User;
import com.mashery.examples.api.client.etsy.UserProfile;
import com.mashery.examples.api.client.etsy.jso.EtsyResponse;
import com.mashery.examples.api.client.etsy.jso.FavoriteListing;
import com.mashery.examples.api.client.etsy.jso.FeaturedListing;
import com.mashery.examples.api.client.etsy.jso.Listing;
import com.mashery.examples.api.client.etsy.jso.ListingImage;
import com.mashery.examples.api.client.etsy.jso.Shop;
public class EtsyExample extends Composite {
// private static final String ETSY_FEATURED_LISTINGS_ENDPOINT = "http://openapi.etsy.com/v2/sandbox/public/homepages/listings/.js?api_key=qu7u5h7bu7twn6s873mnqznz";
private static final String ETSY_FEATURED_LISTINGS_ENDPOINT = "http://openapi.etsy.com/v2/public/homepages/listings/.js?api_key=eqctc7pcj9w5mqqna3caby3h";
// private static final String ETSY_FAVORITE_LISTINGS_ENDPOINT = "http://openapi.etsy.com/v2/sandbox/public/users/${userId}/favorites/listings.js?api_key=qu7u5h7bu7twn6s873mnqznz";
private static final String ETSY_FAVORITE_LISTINGS_ENDPOINT = "http://openapi.etsy.com/v2/public/users/${userId}/favorites/listings.js?api_key=eqctc7pcj9w5mqqna3caby3h";
private static int COLS = 10;
private final PagedTable<EtsyResponse<FeaturedListing>> featuredListingsTable;
private final FavoriteListingsTable favoriteListingsTable;
private final DeckPanel bottomPanel;
private final InlineHTML userLabel;
private final PickupDragController dragController;
private final SimpleDropController dropController;
private final PopupPanel infoPanel;
private final Grid infoGrid;
private final Anchor mapListingLink;
private final Anchor deleteFavListingLink;
private final EtsyServiceAsync etsySvc;
private boolean initialized;
private User user;
private Listing selectedListing;
public EtsyExample(final PopupMapWidget mapWidget) {
AbsolutePanel rootPanel = new AbsolutePanel();
rootPanel.setSize("100%", "100%");
SplitLayoutPanel panel = new SplitLayoutPanel();
rootPanel.add(panel);
panel.setHeight("100%");
FlowPanel topPanel = new FlowPanel();
panel.addNorth(topPanel, 250d);
topPanel.add(new HTML("<h1>Featured Listings</h1>"));
dragController = new PickupDragController(rootPanel, false);
dragController.setBehaviorDragProxy(true);
dragController.setBehaviorMultipleSelection(false);
dragController.setBehaviorDragStartSensitivity(2);
featuredListingsTable = new FeaturedListingsTable(20);
topPanel.add(new ScrollPanel(featuredListingsTable));
DockLayoutPanel bottomPanelContainer = new DockLayoutPanel(Unit.PX);
panel.add(bottomPanelContainer);
bottomPanelContainer.addNorth(new HTML("<h1>Favorite Listings</h1>"), 50d);
bottomPanel = new DeckPanel();
bottomPanelContainer.add(bottomPanel);
bottomPanel.add(new HTML("Obtaining your Etsy account information..."));
favoriteListingsTable = new FavoriteListingsTable(20);
dropController = new SimpleDropController(favoriteListingsTable) {
public void onDrop(DragContext context) {
Image img = (Image) context.draggable;
String id = img.getElement().getId();
if (id != null && id.startsWith("listing_")) {
try {
int listingId = Integer.parseInt(id.substring("listing_".length()));
favoriteListingsTable.createUserFavoriteListing(listingId);
} catch (NumberFormatException e) {
GWT.log("Unable to parse listing id.", e);
}
}
}
};
dragController.registerDropController(dropController);
FlowPanel userPanel = new FlowPanel();
userPanel.add(userLabel = new InlineHTML());
userPanel.add(new InlineHTML(" "));
Anchor disconnectLink = new Anchor("Disconnect", "#");
userPanel.add(disconnectLink);
disconnectLink.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
event.preventDefault();
disconnectEtsyAccount();
}
});
userPanel.add(new InlineHTML(" | "));
Anchor mapProfileLink = new Anchor("Map Profile", "#");
userPanel.add(mapProfileLink);
mapProfileLink.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
event.preventDefault();
if (user != null) {
UserProfile profile = user.getProfile();
if (profile != null) {
MarkerOptions opt = new MarkerOptions();
opt.setTitle(profile.getLoginName());
opt.setPosition(new LatLng(profile.getLat(), profile.getLon()));
opt.setClickable(true);
opt.setVisible(true);
mapWidget.show(new Marker(opt));
}
}
}
});
mapWidget.addAutoHidePartner(mapProfileLink.getElement());
userPanel.add(new HTML());
userPanel.add(favoriteListingsTable);
bottomPanel.add(new ScrollPanel(userPanel));
bottomPanel.add(new HTML("You must be logged in in order to manage your favorite listings."));
bottomPanel.add(createOAuthPanel());
etsySvc = GWT.create(EtsyService.class);
infoPanel = new PopupPanel(true);
infoPanel.setAutoHideOnHistoryEventsEnabled(true);
infoGrid = new Grid(2, 1);
infoPanel.setWidget(infoGrid);
infoGrid.setWidth("240px");
mapListingLink = new Anchor("Map", "#");
mapListingLink.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
event.preventDefault();
if (selectedListing == null)
return;
Shop shop = selectedListing.getShop();
if (shop == null) {
Window.alert("No shop information available.");
return;
}
if (!shop.hasLatLon()) {
Window.alert("No location information available.");
return;
}
MarkerOptions opt = new MarkerOptions();
opt.setTitle(shop.getShopName());
opt.setPosition(new LatLng(shop.getLat(), shop.getLon()));
opt.setClickable(true);
opt.setVisible(true);
mapWidget.show(new Marker(opt));
}
});
mapWidget.addAutoHidePartner(mapListingLink.getElement());
deleteFavListingLink = new Anchor("Delete", "#");
deleteFavListingLink.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
event.preventDefault();
favoriteListingsTable.deleteUserFavoriteListing(selectedListing.getListingId());
infoPanel.hide();
}
});
initWidget(rootPanel);
bottomPanel.showWidget(0);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible && !initialized) {
initialized = true;
initialize();
}
}
private void initialize() {
featuredListingsTable.loadData();
etsySvc.getUser(new AsyncCallback<User>() {
@Override
public void onSuccess(User user) {
EtsyExample.this.user = user;
userLabel.setHTML("<strong>User:</strong> " + user.getLoginName());
bottomPanel.showWidget(1);
favoriteListingsTable.loadData(user.getUserId());
}
@Override
public void onFailure(Throwable caught) {
if (caught instanceof NotLoggedInException) {
bottomPanel.showWidget(2);
} else if (caught instanceof OAuthException) {
bottomPanel.showWidget(3);
} else {
Window.alert(caught.getLocalizedMessage());
}
}
});
}
private Widget createOAuthPanel() {
FlowPanel panel = new FlowPanel();
panel.add(new HTML("You are not connected to your Etsy account."));
final Anchor requestTokenLink = new Anchor("Connect to Your Etsy Account", "#");
panel.add(requestTokenLink);
requestTokenLink.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
String callbackURL = Window.Location.createUrlBuilder().buildString();
String requestTokenURL = "/examples/etsy/oauth/request_token?callbackURL=" + URL.encodeQueryString(callbackURL);
requestTokenLink.setHref(requestTokenURL);
}
});
return new ScrollPanel(panel);
}
private void disconnectEtsyAccount() {
etsySvc.deleteAccessTokens(new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
bottomPanel.showWidget(3);
EtsyExample.this.user = null;
}
@Override
public void onFailure(Throwable caught) {
Window.alert(caught.getLocalizedMessage());
}
});
}
private Image createFeaturedListingImg(final Listing listing) {
final Image img = createListingImg(listing);
if (img != null) {
img.getElement().setId("listing_" + listing.getListingId());
dragController.makeDraggable(img);
img.addMouseOverHandler(new MouseOverHandler() {
@Override
public void onMouseOver(MouseOverEvent event) {
onFeaturedListingSelected(img, listing);
}
});
}
return img;
}
private Image createFavoriteListingImg(final Listing listing) {
final Image img = createListingImg(listing);
if (img != null) {
img.addMouseOverHandler(new MouseOverHandler() {
@Override
public void onMouseOver(MouseOverEvent event) {
onFavoriteListingSelected(img, listing);
}
});
}
return img;
}
private Image createListingImg(Listing listing) {
JsArray<ListingImage> images = listing.getImages();
if (images != null && images.length() > 0) {
Image img = new Image(images.get(0).getURL75x75());
img.setPixelSize(75, 75);
img.getElement().getStyle().setMargin(2d, Unit.PX);
return img;
}
return null;
}
private void onFeaturedListingSelected(Image img, Listing listing) {
Shop shop = listing.getShop();
if (shop == null)
infoGrid.setText(1, 0, null);
else
infoGrid.setWidget(1, 0, mapListingLink);
onListingSelected(img, listing);
}
private void onFavoriteListingSelected(Image img, Listing listing) {
FlowPanel linkPanel = new FlowPanel();
linkPanel.add(deleteFavListingLink);
linkPanel.add(new InlineHTML(" | "));
linkPanel.add(mapListingLink);
infoGrid.setWidget(1, 0, linkPanel);
onListingSelected(img, listing);
}
private void onListingSelected(Image img, Listing listing) {
selectedListing = listing;
infoGrid.setHTML(0, 0, "<strong>" + listing.getTitle() + "</strong>");
infoPanel.showRelativeTo(img);
}
private class FeaturedListingsTable extends PagedTable<EtsyResponse<FeaturedListing>> {
public FeaturedListingsTable(int pageSize) {
super(pageSize);
table.setCellPadding(0);
table.setCellSpacing(0);
table.setText(0, 0, "No data");
table.getRowFormatter().removeStyleName(0, "gwt-PagedTableHeader");
}
@Override
protected void reloadData(Object... args) {
StringBuilder buf = new StringBuilder(ETSY_FEATURED_LISTINGS_ENDPOINT);
buf.append("&limit=").append(pageSize);
buf.append("&offset=").append(pageIndex * pageSize);
buf.append("&includes=Listing/Images,Listing/Shop");
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.setTimeout(60000);
jsonp.requestObject(buf.toString(), dataLoadedCallback);
}
@Override
protected void dataLoaded(EtsyResponse<FeaturedListing> response) {
if (response.isOk()) {
resultCount = response.getCount();
pageCount = ((resultCount - 1) / pageSize) + 1;
JsArray<FeaturedListing> listings = response.getResults();
FlowPanel panel = null;
for (int i = 0, n = listings.length(); i < n; ++i) {
if (i % COLS == 0) {
panel = new FlowPanel();
table.setWidget(i / COLS, 0, panel);
}
FeaturedListing featuredListing = listings.get(i);
Listing listing = featuredListing.getListing();
if (listing != null) {
Image img = createFeaturedListingImg(listing);
if (img != null)
panel.add(img);
}
}
for (int i = table.getRowCount() - 1, n = (listings.length() - 1) / COLS; i > n; --i) {
table.removeRow(i);
}
} else {
Window.alert(response.getError());
}
}
}
private class FavoriteListingsTable extends PagedTable<EtsyResponse<FavoriteListing>> {
public FavoriteListingsTable(int pageSize) {
super(pageSize);
table.setCellPadding(0);
table.setCellSpacing(0);
table.setText(0, 0, "No data");
table.getRowFormatter().removeStyleName(0, "gwt-PagedTableHeader");
}
@Override
protected void reloadData(Object... args) {
StringBuilder buf = new StringBuilder(ETSY_FAVORITE_LISTINGS_ENDPOINT.replace("${userId}", String.valueOf(args[0])));
buf.append("&limit=").append(pageSize);
buf.append("&offset=").append(pageIndex * pageSize);
buf.append("&includes=Listing/Images,Listing/Shop");
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.requestObject(buf.toString(), dataLoadedCallback);
}
@Override
protected void dataLoaded(EtsyResponse<FavoriteListing> response) {
if (response.isOk()) {
resultCount = response.getCount();
pageCount = ((resultCount - 1) / pageSize) + 1;
JsArray<FavoriteListing> listings = response.getResults();
FlowPanel panel = null;
for (int i = 0, n = listings.length(); i < n; ++i) {
if (i % COLS == 0) {
panel = new FlowPanel();
table.setWidget(i / COLS, 0, panel);
}
FavoriteListing favoriteListing = listings.get(i);
Listing listing = favoriteListing.getListing();
if (listing != null) {
Image img = createFavoriteListingImg(listing);
if (img != null)
panel.add(img);
}
}
for (int i = table.getRowCount() - 1, n = (listings.length() - 1) / COLS; i > n; --i) {
table.removeRow(i);
}
if (listings.length() == 0) {
table.setText(0, 0, "Drag and drop your favorite listing here.");
}
} else {
Window.alert(response.getError());
}
}
public void createUserFavoriteListing(int listingId) {
showLoading(true);
etsySvc.createUserFavoriteListing(listingId, new AsyncCallback<com.mashery.examples.api.client.etsy.FavoriteListing>() {
@Override
public void onSuccess(com.mashery.examples.api.client.etsy.FavoriteListing result) {
if (resultCount < 0)
resultCount = 0;
++resultCount;
pageCount = ((resultCount - 1) / pageSize) + 1;
pageIndex = 0;
showLoading(true);
reloadData(args);
}
@Override
public void onFailure(Throwable caught) {
showLoading(false);
Window.alert(caught.getLocalizedMessage());
}
});
}
public void deleteUserFavoriteListing(int listingId) {
showLoading(true);
etsySvc.deleteUserFavoriteListing(listingId, new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
if (resultCount < 0)
resultCount = 1;
--resultCount;
pageCount = ((resultCount - 1) / pageSize) + 1;
showLoading(true);
reloadData(args);
}
@Override
public void onFailure(Throwable caught) {
showLoading(false);
Window.alert(caught.getLocalizedMessage());
}
});
}
}
}