ingo@4: package de.intevation.flys.client.client.ui;
ingo@4:
sascha@3473: import com.google.gwt.core.client.GWT;
ingo@226: import com.google.gwt.i18n.client.DateTimeFormat;
ingo@585: import com.google.gwt.user.client.Timer;
ingo@97: import com.google.gwt.user.client.rpc.AsyncCallback;
christian@4184:
ingo@226: import com.smartgwt.client.types.Alignment;
christian@3709: import com.smartgwt.client.types.Autofit;
ingo@597: import com.smartgwt.client.types.ListGridEditEvent;
ingo@226: import com.smartgwt.client.types.ListGridFieldType;
christian@3709: import com.smartgwt.client.types.Overflow;
ingo@606: import com.smartgwt.client.types.SelectionStyle;
ingo@606: import com.smartgwt.client.types.SortArrow;
ingo@226: import com.smartgwt.client.types.SortDirection;
sascha@3473: import com.smartgwt.client.types.VerticalAlignment;
ingo@606: import com.smartgwt.client.util.BooleanCallback;
ingo@220: import com.smartgwt.client.util.SC;
ingo@4: import com.smartgwt.client.widgets.Canvas;
rrenkert@5144: import com.smartgwt.client.widgets.IconButton;
ingo@4: import com.smartgwt.client.widgets.Label;
rrenkert@5144: import com.smartgwt.client.widgets.events.ClickEvent;
bjoern@4605: import com.smartgwt.client.widgets.events.VisibilityChangedEvent;
bjoern@4605: import com.smartgwt.client.widgets.events.VisibilityChangedHandler;
ingo@226: import com.smartgwt.client.widgets.grid.CellFormatter;
ingo@606: import com.smartgwt.client.widgets.grid.HoverCustomizer;
ingo@4: import com.smartgwt.client.widgets.grid.ListGrid;
ingo@4: import com.smartgwt.client.widgets.grid.ListGridField;
ingo@97: import com.smartgwt.client.widgets.grid.ListGridRecord;
ingo@597: import com.smartgwt.client.widgets.grid.events.CellClickEvent;
ingo@597: import com.smartgwt.client.widgets.grid.events.CellClickHandler;
ingo@253: import com.smartgwt.client.widgets.grid.events.CellDoubleClickEvent;
ingo@253: import com.smartgwt.client.widgets.grid.events.CellDoubleClickHandler;
ingo@597: import com.smartgwt.client.widgets.grid.events.EditCompleteEvent;
ingo@597: import com.smartgwt.client.widgets.grid.events.EditCompleteHandler;
sascha@3473: import com.smartgwt.client.widgets.grid.events.HeaderDoubleClickEvent;
sascha@3473: import com.smartgwt.client.widgets.grid.events.HeaderDoubleClickHandler;
ingo@220: import com.smartgwt.client.widgets.grid.events.RowContextClickEvent;
ingo@220: import com.smartgwt.client.widgets.grid.events.RowContextClickHandler;
bjoern@4559: import com.smartgwt.client.widgets.layout.HLayout;
ingo@4: import com.smartgwt.client.widgets.layout.VLayout;
ingo@220: import com.smartgwt.client.widgets.menu.Menu;
ingo@220: import com.smartgwt.client.widgets.menu.MenuItem;
sascha@778: import com.smartgwt.client.widgets.menu.MenuItemSeparator;
sascha@3473: import com.smartgwt.client.widgets.menu.events.ClickHandler;
sascha@3473: import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;
ingo@4:
ingo@97: import de.intevation.flys.client.client.Config;
ingo@225: import de.intevation.flys.client.client.FLYS;
ingo@211: import de.intevation.flys.client.client.FLYSConstants;
ingo@97: import de.intevation.flys.client.client.event.CollectionChangeEvent;
ingo@97: import de.intevation.flys.client.client.event.CollectionChangeHandler;
sascha@3473: import de.intevation.flys.client.client.event.FilterHandler;
sascha@3473: import de.intevation.flys.client.client.event.RangeFilterEvent;
sascha@3473: import de.intevation.flys.client.client.event.StringFilterEvent;
felix@3380: import de.intevation.flys.client.client.services.AddArtifactService;
felix@3380: import de.intevation.flys.client.client.services.AddArtifactServiceAsync;
raimund@887: import de.intevation.flys.client.client.services.ArtifactService;
raimund@887: import de.intevation.flys.client.client.services.ArtifactServiceAsync;
felix@3380: import de.intevation.flys.client.client.services.CreateCollectionService;
felix@3380: import de.intevation.flys.client.client.services.CreateCollectionServiceAsync;
ingo@598: import de.intevation.flys.client.client.services.DeleteCollectionService;
ingo@598: import de.intevation.flys.client.client.services.DeleteCollectionServiceAsync;
felix@3380: import de.intevation.flys.client.client.services.DescribeCollectionService;
felix@3380: import de.intevation.flys.client.client.services.DescribeCollectionServiceAsync;
felix@3380: import de.intevation.flys.client.client.services.GetArtifactService;
felix@3380: import de.intevation.flys.client.client.services.GetArtifactServiceAsync;
ingo@598: import de.intevation.flys.client.client.services.SetCollectionNameService;
ingo@598: import de.intevation.flys.client.client.services.SetCollectionNameServiceAsync;
ingo@598: import de.intevation.flys.client.client.services.SetCollectionTTLService;
ingo@598: import de.intevation.flys.client.client.services.SetCollectionTTLServiceAsync;
ingo@97: import de.intevation.flys.client.client.services.UserCollectionsService;
ingo@97: import de.intevation.flys.client.client.services.UserCollectionsServiceAsync;
sascha@3473: import de.intevation.flys.client.shared.model.Artifact;
sascha@3473: import de.intevation.flys.client.shared.model.Collection;
sascha@3473: import de.intevation.flys.client.shared.model.CollectionItem;
sascha@3473: import de.intevation.flys.client.shared.model.CollectionRecord;
sascha@3473: import de.intevation.flys.client.shared.model.Recommendation;
sascha@3473: import de.intevation.flys.client.shared.model.User;
sascha@3473:
sascha@3473: import java.util.ArrayList;
sascha@3473: import java.util.Date;
sascha@3473: import java.util.List;
sascha@3473: import java.util.Map;
sascha@3473: import java.util.MissingResourceException;
sascha@3473:
ingo@4:
ingo@4: /**
ingo@4: * The project list shows a list of projects of a specific user.
ingo@4: *
ingo@4: * @author Ingo Weinzierl
ingo@4: */
ingo@97: public class ProjectList
ingo@97: extends VLayout
bjoern@4605: implements CollectionChangeHandler, EditCompleteHandler, FilterHandler,
bjoern@4605: VisibilityChangedHandler
ingo@97: {
ingo@585: /** Interval to refresh the user's projects.*/
ingo@585: public static final int UPDATE_INTERVAL = 30000;
ingo@585:
ingo@585: /** Min Interval to refresh the user's projects.*/
ingo@585: public static final int MIN_UPDATE_INTERVAL = 5000;
ingo@585:
ingo@606: /** The initial width of this panel.*/
ingo@606: public static final int MIN_WIDTH = 300;
ingo@606:
ingo@613: /** The max length for new project names.*/
ingo@613: public static final int MAX_NAME_LENGTH = 50;
ingo@613:
ingo@606: public static final String COLUMN_DATE_WIDTH = "100px";
ingo@606:
ingo@606: public static final String COLUMN_TITLE_WIDTH = "*";
ingo@606:
ingo@606: public static final String COLUMN_FAVORITE_WIDTH = "75px";
ingo@606:
ingo@4: /** The interface that provides i18n messages. */
christian@3501: private final FLYSConstants messages = GWT.create(FLYSConstants.class);
ingo@4:
ingo@97: /** The UserService used to retrieve information about the current user. */
ingo@97: protected UserCollectionsServiceAsync userCollectionsService =
ingo@97: GWT.create(UserCollectionsService.class);
ingo@97:
ingo@598: /** The service used to set the name of a project.*/
ingo@598: protected SetCollectionNameServiceAsync nameService =
ingo@598: GWT.create(SetCollectionNameService.class);
ingo@598:
ingo@598: /** The service used to set the name of a project.*/
ingo@598: protected SetCollectionTTLServiceAsync ttlService =
ingo@598: GWT.create(SetCollectionTTLService.class);
ingo@598:
ingo@598: /** The service used to set the name of a project.*/
ingo@598: protected DeleteCollectionServiceAsync deleteService =
ingo@598: GWT.create(DeleteCollectionService.class);
ingo@598:
raimund@887: /** The DescribeCollectionService used to update the existing collection. */
raimund@887: protected DescribeCollectionServiceAsync describeCollectionService =
raimund@887: GWT.create(DescribeCollectionService.class);
raimund@887:
raimund@887: /** The ArtifactService used to communicate with the Artifact server. */
raimund@887: protected ArtifactServiceAsync createArtifactService =
raimund@887: GWT.create(ArtifactService.class);
raimund@887:
raimund@887: /** The ArtifactService used to communicate with the Artifact server. */
raimund@887: protected CreateCollectionServiceAsync createCollectionService =
raimund@887: GWT.create(CreateCollectionService.class);
raimund@887:
raimund@887: /** The AddArtifactService used to add an artifact to a collection. */
raimund@887: protected AddArtifactServiceAsync addArtifactService =
raimund@887: GWT.create(AddArtifactService.class);
raimund@887:
felix@3380: /** The GetArtifactService used to open an existing collection. */
felix@3380: protected GetArtifactServiceAsync getArtifactService =
felix@3380: GWT.create(GetArtifactService.class);
felix@3380:
ingo@225: /** A pointer to the FLYS instance.*/
ingo@225: protected FLYS flys;
ingo@225:
ingo@4: /** The user whose projects should be displayed.*/
ingo@4: protected User user;
ingo@4:
ingo@4: /** The grid that contains the project rows.*/
ingo@4: protected ListGrid grid;
ingo@4:
raimund@885: /** All user collections.*/
raimund@885: protected List collections;
raimund@885:
raimund@887: /** The collection to clone*/
raimund@887: protected Collection cloneCollection;
raimund@887:
felix@3380: /** The message class that provides i18n strings.*/
felix@3380: protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
felix@3380:
bjoern@4691: private String filter;
bjoern@4691:
felix@3380:
ingo@4: /**
ingo@4: * The default constructor that creates a new ProjectList for a specific
ingo@4: * user.
ingo@4: *
ingo@4: * @param user The user.
ingo@4: */
ingo@225: public ProjectList(FLYS flys, User user) {
felix@3531: super();
ingo@225: this.flys = flys;
ingo@4: this.user = user;
ingo@4:
christian@3501: collections = new ArrayList();
ingo@226: grid = new ListGrid();
ingo@4: initGrid();
ingo@97: init();
ingo@585: initTimer();
ingo@4:
ingo@597: grid.addEditCompleteHandler(this);
ingo@597:
bjoern@4605: addVisibilityChangedHandler(this);
bjoern@4605:
ingo@97: updateUserCollections();
ingo@4: }
ingo@4:
ingo@4:
ingo@4: protected void initGrid() {
ingo@606: grid.setWidth100();
christian@3709: grid.setAutoFitData(Autofit.VERTICAL);
ingo@606: grid.setAutoFitMaxWidth(500);
ingo@4: grid.setEmptyMessage(messages.no_projects());
ingo@4: grid.setLoadingDataMessage(messages.load_projects());
ingo@606: grid.setCanEdit(false);
ingo@606: grid.setEditEvent(ListGridEditEvent.NONE);
ingo@606: grid.setShowHeaderContextMenu(false);
ingo@606: grid.setShowSortArrow(SortArrow.NONE);
ingo@226: grid.setSortDirection(SortDirection.DESCENDING);
ingo@226: grid.setSortField(0);
ingo@606: grid.setSelectionType(SelectionStyle.SINGLE);
raimund@877: grid.setCanReorderFields(false);
ingo@2446: grid.setLeaveScrollbarGap(false);
christian@3709: grid.setBorder("0px");
ingo@4:
ingo@226: ListGridField date = buildDateField();
ingo@226: ListGridField name = buildNameField();
ingo@587: ListGridField fav = buildFavoriteField();
ingo@4:
ingo@587: grid.setFields(date, name, fav);
ingo@220:
raimund@1391: grid.addHeaderDoubleClickHandler(new HeaderDoubleClickHandler() {
christian@3501: @Override
raimund@1391: public void onHeaderDoubleClick(HeaderDoubleClickEvent event) {
felix@3380: // Cancel the event.
raimund@1391: return;
raimund@1391: }
raimund@1391: });
raimund@1391:
felix@3380: // Add a handler to set / unset the favorite state of a project.
ingo@597: grid.addCellClickHandler(new CellClickHandler() {
christian@3501: @Override
ingo@597: public void onCellClick(CellClickEvent event) {
ingo@597: if (event.getColNum() != 2) {
ingo@597: return;
ingo@597: }
ingo@597:
ingo@597: CollectionRecord r = (CollectionRecord) event.getRecord();
ingo@597: Collection c = r.getCollection();
ingo@597:
ingo@597: c.setTTL(c.getTTL() == 0 ? -1 : 0);
ingo@597: updateCollectionTTL(c);
ingo@597: }
ingo@597: });
ingo@597:
felix@3380: // Add a handler to open a project.
ingo@253: grid.addCellDoubleClickHandler(new CellDoubleClickHandler() {
christian@3501: @Override
ingo@253: public void onCellDoubleClick(CellDoubleClickEvent e) {
ingo@253: CollectionRecord record = (CollectionRecord) e.getRecord();
ingo@253: String uuid = record != null
ingo@253: ? record.getCollection().identifier()
ingo@253: : "";
ingo@253: getFlys().openProject(uuid);
ingo@253: }
ingo@253: });
ingo@253:
felix@3380: // Add a handler to open a context menu.
ingo@220: grid.addRowContextClickHandler(new RowContextClickHandler() {
christian@3501: @Override
ingo@220: public void onRowContextClick(RowContextClickEvent event) {
ingo@220: CollectionRecord record = (CollectionRecord) event.getRecord();
ingo@220:
ingo@220: Menu menu = createContextMenu(record);
ingo@220: grid.setContextMenu(menu);
ingo@220: menu.showContextMenu();
ingo@220:
ingo@220: event.cancel();
ingo@220: }
ingo@220: });
ingo@220: }
ingo@220:
ingo@220:
ingo@585: /**
ingo@585: * Initializes a repeating timer that updates the user's collections. The
ingo@585: * interval is specified by the constant UPDATE_INTERVAL.
ingo@585: */
ingo@585: protected void initTimer() {
ingo@585: Config config = Config.getInstance();
ingo@585: int interval = config.getProjectListUpdateInterval();
ingo@585:
ingo@585: interval = interval > MIN_UPDATE_INTERVAL ? interval : UPDATE_INTERVAL;
ingo@585:
ingo@585: GWT.log("Update project list every " + interval + " milliseconds.");
ingo@585:
ingo@585: Timer t = new Timer() {
ingo@585: @Override
ingo@585: public void run() {
ingo@585: updateUserCollections();
ingo@585: }
ingo@585: };
ingo@585:
ingo@585: t.scheduleRepeating(interval);
ingo@585: }
ingo@585:
ingo@585:
ingo@225: public FLYS getFlys() {
ingo@225: return flys;
ingo@225: }
ingo@225:
ingo@225:
ingo@220: /**
ingo@220: * Creates a new context menu that interacts with a CollectionRecord.
ingo@220: *
ingo@220: * @param record The selected record.
ingo@220: *
ingo@220: * @return the context menu with operations that interact with
ingo@220: * record.
ingo@220: */
ingo@220: protected Menu createContextMenu(final CollectionRecord record) {
ingo@220: Menu menu = new Menu();
ingo@220:
ingo@220: MenuItem open = new MenuItem(messages.open_project());
ingo@220: open.addClickHandler(new ClickHandler() {
christian@3501: @Override
ingo@220: public void onClick(MenuItemClickEvent evt) {
ingo@225: getFlys().openProject(record.getCollection().identifier());
ingo@220: }
ingo@220: });
ingo@220:
ingo@220: MenuItem del = new MenuItem(messages.delete_project());
ingo@220: del.addClickHandler(new ClickHandler() {
christian@3501: @Override
ingo@220: public void onClick(MenuItemClickEvent evt) {
ingo@606: SC.ask(messages.really_delete(), new BooleanCallback() {
christian@3501: @Override
ingo@606: public void execute(Boolean value) {
ingo@606: if (value) {
ingo@606: deleteCollection(record.getCollection());
ingo@606: }
ingo@606: }
ingo@606: });
ingo@220: }
ingo@220: });
ingo@220:
ingo@597: MenuItem rename = new MenuItem(messages.rename_project());
ingo@597: rename.addClickHandler(new ClickHandler() {
christian@3501: @Override
ingo@597: public void onClick(MenuItemClickEvent evt) {
ingo@597: int row = grid.getRecordIndex(record);
ingo@597: grid.startEditing(row, 1, false);
ingo@597: }
ingo@597: });
ingo@597:
raimund@887: MenuItem clone = new MenuItem(messages.clone_project());
raimund@887: clone.addClickHandler(new ClickHandler() {
christian@3501: @Override
raimund@887: public void onClick(MenuItemClickEvent evt) {
raimund@887: cloneProject(record.getCollection());
raimund@887: }
raimund@887: });
raimund@887:
ingo@220: menu.addItem(open);
sascha@778: menu.addItem(rename);
raimund@887: menu.addItem(clone);
sascha@778: menu.addItem(new MenuItemSeparator());
ingo@220: menu.addItem(del);
ingo@220:
ingo@220: return menu;
ingo@4: }
ingo@4:
ingo@4:
ingo@4: /**
ingo@4: * The init() method handles the layout stuff for this widget.
ingo@4: */
ingo@4: protected void init() {
ingo@606: setWidth(MIN_WIDTH);
ingo@606: setMinWidth(MIN_WIDTH);
ingo@4: setHeight100();
ingo@4: setShowResizeBar(true);
ingo@4: setShowEdges(false);
ingo@4: setLayoutMargin(0);
raimund@79: setLayoutAlign(VerticalAlignment.TOP);
christian@3709: setOverflow(Overflow.AUTO);
ingo@4:
ingo@4: Label title = new Label(messages.projects());
ingo@4: title.setHeight("20");
ingo@4: title.setMargin(5);
ingo@4: title.setWidth100();
bjoern@4559: title.setStyleName("projectHeader");
ingo@4:
bjoern@4559: HLayout buttonWrapper = new HLayout();
bjoern@4559:
rrenkert@5144: IconButton addButton = new IconButton("");
rrenkert@5144: addButton.setIcon(messages.projectListAdd());
rrenkert@5144: addButton.setTooltip(messages.new_project());
bjoern@4559: addButton.setWidth("30px");
bjoern@4559:
rrenkert@5144: IconButton closeButton = new IconButton("");
rrenkert@5144: closeButton.setIcon(messages.projectListMin());
rrenkert@5144: closeButton.setTooltip(messages.projectlist_close());
bjoern@4559: closeButton.setWidth("30px");
bjoern@4559:
bjoern@4559: buttonWrapper.addMember(addButton);
bjoern@4559: buttonWrapper.addMember(closeButton);
bjoern@4559: buttonWrapper.setAlign(Alignment.RIGHT);
bjoern@4559: buttonWrapper.setAutoWidth();
bjoern@4559:
bjoern@4559: HLayout titleWrapper = new HLayout();
bjoern@4559: titleWrapper.setStyleName("bgBlueMid");
ingo@4: titleWrapper.setWidth100();
raimund@79: titleWrapper.setHeight("20px");
bjoern@4559: titleWrapper.addMember(title);
bjoern@4559: titleWrapper.addMember(buttonWrapper);
ingo@4:
ingo@4: Canvas gridWrapper = new Canvas();
ingo@4: gridWrapper.setPadding(0);
ingo@4: titleWrapper.setWidth100();
ingo@4: gridWrapper.addChild(grid);
ingo@4:
bjoern@4692: TableFilter filterpanel = new TableFilter();
bjoern@4692: filterpanel.setHeight("30px");
bjoern@4692: filterpanel.addFilterHandler(this);
bjoern@4692: filterpanel.setBorder("1px solid gray");
raimund@885:
ingo@4: addMember(titleWrapper);
ingo@4: addMember(gridWrapper);
bjoern@4692: addMember(filterpanel);
bjoern@4559:
bjoern@4559: addButton.addClickHandler(
rrenkert@5144: new com.smartgwt.client.widgets.events.ClickHandler() {
bjoern@4559:
bjoern@4559: @Override
bjoern@4559: public void onClick(ClickEvent ev) {
bjoern@4559: flys.newProject();
bjoern@4559: }
bjoern@4559: });
bjoern@4559:
bjoern@4559: closeButton.addClickHandler(
rrenkert@5144: new com.smartgwt.client.widgets.events.ClickHandler() {
bjoern@4559:
bjoern@4559: @Override
bjoern@4559: public void onClick(ClickEvent ev) {
bjoern@4559: hide();
bjoern@4559: }
bjoern@4559: });
raimund@885: }
raimund@885:
raimund@885:
christian@3501: @Override
raimund@885: public void onFilterCriteriaChanged(StringFilterEvent event) {
raimund@885: String search = event.getFilter();
bjoern@4691: // Filter the records.
bjoern@4691: setFilter(search);
bjoern@4691: updateGrid();
ingo@4: }
ingo@97:
ingo@97:
christian@3501: @Override
raimund@1534: public void onFilterCriteriaChanged(RangeFilterEvent event) {
raimund@1534: //Empty. No Ranges to filter.
raimund@1534: }
raimund@1534:
raimund@1534:
felix@3531: /** On collection change, update list (probably name change or similar). */
christian@3501: @Override
ingo@97: public void onCollectionChange(CollectionChangeEvent event) {
ingo@585: if (event.getOldValue() == null) {
ingo@585: updateUserCollections();
ingo@585: }
ingo@97: }
ingo@97:
ingo@97:
christian@3501: @Override
ingo@597: public void onEditComplete(EditCompleteEvent event) {
ingo@597: if (event.getColNum() != 1) {
ingo@597: return;
ingo@597: }
ingo@597:
ingo@597: int row = event.getRowNum();
ingo@597:
ingo@597: CollectionRecord r = (CollectionRecord) grid.getRecord(row);
ingo@597: Collection c = r.getCollection();
ingo@597:
christian@3501: Map, ?> newValues = event.getNewValues();
ingo@597: String name = (String) newValues.get("name");
ingo@597:
ingo@613: int maxLength = getMaxNameLength();
ingo@613: int length = name != null ? name.length() : 0;
ingo@613:
ingo@613: if (length <= 0 || length > maxLength) {
ingo@613: String msg = messages.project_name_too_long();
ingo@613: msg = msg.replace("$LEN", String.valueOf(maxLength));
ingo@613: SC.warn(msg);
ingo@613:
ingo@613: ListGridRecord[] rs = grid.getRecords();
ingo@613: rs[row] = (ListGridRecord) event.getOldRecord();
ingo@613: grid.setRecords(rs);
ingo@613:
ingo@613: return;
ingo@613: }
ingo@613:
bjoern@4693: updateCollectionName(c, name);
ingo@597: }
ingo@597:
ingo@597:
ingo@597: /**
ingo@597: * Set the name of the collection c to a new value. If the update
ingo@597: * process succeeded, the project list is refreshed.
ingo@597: *
ingo@597: * @param c The Collection with a new name.
bjoern@4693: * @param name Name to set on the collection
ingo@597: */
bjoern@4693: private void updateCollectionName(final Collection c, String name) {
ingo@597: if (c == null) {
ingo@597: return;
ingo@597: }
ingo@597:
bjoern@4693: c.setName(name);
bjoern@4693:
ingo@597: GWT.log("Update Collection name: " + c.identifier());
ingo@597: GWT.log("=> New name = " + c.getName());
ingo@597:
raimund@1425: nameService.setName(c, new AsyncCallback(){
christian@3501: @Override
ingo@598: public void onFailure(Throwable caught) {
ingo@598: String msg = caught.getMessage();
ingo@598:
ingo@598: try {
ingo@598: SC.warn(messages.getString(msg));
ingo@598: }
ingo@598: catch (MissingResourceException mre) {
ingo@598: SC.warn(msg);
ingo@598: }
ingo@598: }
ingo@598:
christian@3501: @Override
ingo@598: public void onSuccess(Void v) {
ingo@598: updateUserCollections();
raimund@896: if(flys.getWorkspace().hasView(c.identifier())) {
raimund@896: flys.getWorkspace().updateTitle(c.identifier(), c.getName());
raimund@896: }
ingo@598: }
ingo@598: });
ingo@597: }
ingo@597:
ingo@597:
ingo@597: /**
ingo@597: * Set the ttl of the collection c to a new value. If the update
ingo@597: * process succeeded, the project list is refreshed.
ingo@597: *
ingo@597: * @param c The Collection with a new ttl.
ingo@597: */
ingo@597: protected void updateCollectionTTL(Collection c) {
ingo@597: if (c == null) {
ingo@597: return;
ingo@597: }
ingo@597:
ingo@597: GWT.log("Update Collection TTL: " + c.identifier());
ingo@597: GWT.log("=> New ttl = " + c.getTTL());
ingo@597:
raimund@1425: ttlService.setTTL(c, new AsyncCallback() {
christian@3501: @Override
ingo@598: public void onFailure(Throwable caught) {
ingo@598: String msg = caught.getMessage();
ingo@598:
ingo@598: try {
ingo@598: SC.warn(messages.getString(msg));
ingo@598: }
ingo@598: catch (MissingResourceException mre) {
ingo@598: SC.warn(msg);
ingo@598: }
ingo@598: }
ingo@598:
christian@3501: @Override
ingo@598: public void onSuccess(Void v) {
ingo@598: updateUserCollections();
ingo@598: }
ingo@598: });
ingo@598: }
ingo@598:
ingo@598:
ingo@598: /**
ingo@598: * Delete the collection c.
ingo@598: *
ingo@598: * @param c The Collection that should be deleted.
ingo@598: */
christian@3501: public void deleteCollection(final Collection c) {
ingo@598: if (c == null) {
ingo@598: return;
ingo@598: }
ingo@598:
ingo@598: GWT.log("Delete Collection: " + c.identifier());
ingo@598:
raimund@1425: deleteService.delete(c, new AsyncCallback(){
christian@3501: @Override
ingo@598: public void onFailure(Throwable caught) {
ingo@598: String msg = caught.getMessage();
ingo@598:
ingo@598: try {
ingo@598: SC.warn(messages.getString(msg));
ingo@598: }
ingo@598: catch (MissingResourceException mre) {
ingo@598: SC.warn(msg);
ingo@598: }
ingo@598: }
ingo@598:
christian@3501: @Override
ingo@598: public void onSuccess(Void v) {
ingo@600: flys.getWorkspace().destroyProject(c.identifier());
ingo@598: updateUserCollections();
ingo@598: }
ingo@598: });
ingo@597: }
ingo@597:
ingo@597:
bjoern@4140: public void updateUserCollections() {
ingo@585: GWT.log("==> ProjectList updates user collections!");
ingo@585:
ingo@97: Config config = Config.getInstance();
ingo@229: String locale = config.getLocale();
ingo@97:
ingo@1493: userCollectionsService.getUserCollections(locale, user.identifier(),
ingo@97: new AsyncCallback() {
christian@3501: @Override
ingo@97: public void onFailure(Throwable caught) {
ingo@598: String msg = caught.getMessage();
ingo@598:
ingo@598: try {
ingo@598: SC.warn(messages.getString(msg));
ingo@598: }
ingo@598: catch (MissingResourceException mre) {
ingo@598: SC.warn(msg);
ingo@598: }
ingo@97: }
ingo@97:
christian@3501: @Override
ingo@97: public void onSuccess(Collection[] collections) {
ingo@97: int num = collections != null ? collections.length : 0;
ingo@97:
ingo@97: GWT.log("Received " + num + " user collections.");
ingo@97:
raimund@885: updateGridDataSource(collections);
ingo@97: }
ingo@97: }
ingo@97: );
ingo@97: }
ingo@97:
felix@3380:
raimund@885: /**
raimund@885: * Delete all entries in the ListGrid.
raimund@885: */
bjoern@4694: private void clearGrid() {
ingo@97: ListGridRecord[] records = grid.getRecords();
ingo@97:
ingo@97: for (ListGridRecord record: records) {
ingo@97: grid.removeData(record);
ingo@97: }
ingo@97: }
ingo@97:
ingo@97:
raimund@885: /**
raimund@885: * Update the collections data source.
raimund@885: *
raimund@885: * First removes all collections to avoid duplicates, then add new entries.
raimund@885: *
raimund@885: * @param c Collections to set to the data source.
raimund@885: */
bjoern@4694: private void updateGridDataSource(Collection[] c) {
raimund@885: collections.clear();
raimund@889: if(c == null) {
raimund@889: clearGrid();
raimund@889: return;
raimund@889: }
raimund@885: for (Collection coll : c) {
raimund@885: this.collections.add(coll);
raimund@885: }
bjoern@4691: updateGrid();
raimund@885: }
raimund@885:
raimund@885:
raimund@885: /**
raimund@885: * Updates the ListGrid.
raimund@885: */
bjoern@4694: private void updateGrid() {
ingo@97: clearGrid();
ingo@97:
bjoern@4695: if (collections == null || collections.isEmpty()) {
ingo@599: return;
ingo@599: }
ingo@599:
bjoern@4691: for (Collection col: collections) {
raimund@885: String name;
raimund@885:
bjoern@4691: name = col.getDisplayName().toLowerCase();
raimund@885:
raimund@885: // Add a collection to the filtered list if the search string
raimund@885: // matches.
bjoern@4691: if (filter == null || filter.isEmpty() ||
bjoern@4691: name.contains(filter.toLowerCase())) {
bjoern@4691: grid.addData(new CollectionRecord(col));
raimund@885: }
raimund@885: }
raimund@885: }
raimund@885:
ingo@613: public int getMaxNameLength() {
ingo@613: return MAX_NAME_LENGTH;
ingo@613: }
ingo@613:
ingo@613:
ingo@226: /**
ingo@226: * Builds the field in the grid that displays the creation time of a
ingo@226: * project.
ingo@226: *
ingo@226: * @return the grid field.
ingo@226: */
ingo@226: protected ListGridField buildDateField() {
ingo@606: ListGridField date = new ListGridField(
ingo@606: "creationTime", messages.projectlist_creationTime());
ingo@606:
ingo@226: date.setType(ListGridFieldType.DATE);
ingo@597: date.setCanEdit(false);
ingo@226:
ingo@226: date.setCellFormatter(new CellFormatter() {
christian@3501: @Override
ingo@226: public String format(Object value, ListGridRecord rec, int r, int c) {
ingo@226: if (value == null) {
ingo@226: return null;
ingo@226: }
ingo@226:
ingo@226: DateTimeFormat dtf = DateTimeFormat.getFormat(
ingo@226: messages.datetime_format());
ingo@226:
ingo@226: return dtf.format((Date)value);
ingo@226: }
ingo@226: });
ingo@226:
ingo@606: date.setWidth(COLUMN_DATE_WIDTH);
ingo@606: date.setAlign(Alignment.CENTER);
ingo@226:
ingo@226: return date;
ingo@226: }
ingo@226:
ingo@226:
ingo@226: /**
ingo@226: * Builds the field in the grid that displays the name of a project.
ingo@226: *
ingo@226: * @return the grid field.
ingo@226: */
ingo@226: protected ListGridField buildNameField() {
ingo@606: ListGridField name = new ListGridField(
ingo@606: "name", messages.projectlist_title());
ingo@606:
ingo@226: name.setType(ListGridFieldType.TEXT);
ingo@606: name.setShowHover(true);
ingo@606: name.setHoverCustomizer(new HoverCustomizer() {
christian@3501: @Override
ingo@606: public String hoverHTML(
ingo@606: Object value,
ingo@606: ListGridRecord record,
ingo@606: int row,
ingo@606: int col)
ingo@606: {
ingo@606: CollectionRecord r = (CollectionRecord) record;
ingo@606: Collection c = r.getCollection();
ingo@606:
ingo@607: String name = r.getName();
ingo@606:
ingo@606: return name != null && name.length() > 0
ingo@606: ? name
ingo@606: : c.identifier();
ingo@606: }
ingo@606: });
ingo@226:
ingo@606: name.setWidth(COLUMN_TITLE_WIDTH);
ingo@226: name.setAlign(Alignment.LEFT);
ingo@226:
ingo@226: return name;
ingo@226: }
ingo@587:
ingo@587:
ingo@587: protected ListGridField buildFavoriteField() {
ingo@606: ListGridField fav = new ListGridField(
ingo@606: "ttl", messages.projectlist_favorite());
ingo@606:
ingo@587: fav.setType(ListGridFieldType.IMAGE);
ingo@587: String base = GWT.getHostPageBaseURL();
ingo@587: fav.setImageURLPrefix(base + "images/");
ingo@587: fav.setImageURLSuffix(".png");
ingo@606: fav.setWidth(COLUMN_FAVORITE_WIDTH);
ingo@606: fav.setAlign(Alignment.CENTER);
ingo@597: fav.setCanEdit(false);
ingo@587:
ingo@587: return fav;
ingo@587: }
raimund@887:
raimund@887:
raimund@887: protected void cloneProject(Collection c) {
raimund@887: Config config = Config.getInstance();
raimund@887: String locale = config.getLocale();
raimund@887:
raimund@887: cloneCollection = c;
raimund@887:
raimund@1425: describeCollectionService.describe(c.identifier(), locale,
raimund@887: new AsyncCallback() {
christian@3501: @Override
raimund@887: public void onFailure(Throwable caught) {
raimund@887: GWT.log("Could not DESCRIBE collection.");
raimund@887: SC.warn(messages.getString(caught.getMessage()));
raimund@887: }
raimund@887:
raimund@887:
christian@3501: @Override
raimund@887: public void onSuccess(Collection newCollection) {
raimund@887: GWT.log("Successfully DESCRIBED collection.");
raimund@887: String uuid = getMasterArtifact(newCollection);
felix@3380: cloneArtifact(uuid, newCollection);
raimund@887: }
raimund@887: }
raimund@887: );
raimund@887: }
raimund@887:
raimund@887:
felix@3380: /** Get master artifacts UUID of a collection. */
raimund@887: protected String getMasterArtifact(Collection newCollection) {
raimund@887: String uuid = newCollection.getItem(0).identifier();
raimund@887: // The master artifact uuid.
raimund@887: return uuid;
raimund@887: }
raimund@887:
raimund@887:
felix@3380: /** Clone artifact/create collection, using the refArtifacts factory. */
felix@3380: protected void cloneArtifact(String uuid, Artifact refArtifact,
felix@3380: final String locale) {
raimund@887: Recommendation recommendation = new Recommendation(
felix@3380: refArtifact.getName(),
raimund@887: null,
raimund@887: uuid,
raimund@887: null);
raimund@887:
raimund@887: String factory = recommendation.getFactory();
raimund@887: createArtifactService.create(
raimund@1425: locale, factory, recommendation,
raimund@887: new AsyncCallback() {
christian@3501: @Override
raimund@887: public void onFailure(Throwable caught) {
raimund@887: GWT.log("Error loading recommendations: " +
raimund@887: caught.getMessage());
raimund@887: }
raimund@887:
christian@3501: @Override
raimund@887: public void onSuccess(Artifact artifact) {
raimund@887: GWT.log("Created new artifact: " + artifact.getUuid());
bjoern@4696: createClonedCollection(artifact);
raimund@887: }
raimund@887: }
raimund@887: );
raimund@887: }
raimund@887:
raimund@887:
felix@3380: /**
felix@3380: * Clone a project (collection).
felix@3380: */
bjoern@4694: private void cloneArtifact(final String uuid, Collection newCollection) {
felix@3380: Config config = Config.getInstance();
felix@3380: final String locale = config.getLocale();
felix@3380:
felix@3380: // Find out which factory to use for cloning.
felix@3380: CollectionItem master = newCollection.getItem(0);
felix@3380: getArtifactService.getArtifact(
felix@3380: locale,
felix@3380: master.identifier(),
felix@3380: master.hash(),
felix@3380: new AsyncCallback() {
christian@3501: @Override
felix@3380: public void onFailure(Throwable caught) {
felix@3380: SC.warn(MSG.getString(caught.getMessage()));
felix@3380: }
felix@3380:
christian@3501: @Override
felix@3380: public void onSuccess(Artifact artifact) {
felix@3380: cloneArtifact(uuid, artifact, locale);
felix@3380: }
felix@3380: });
felix@3380: }
felix@3380:
felix@3380:
bjoern@4696: /**
bjoern@4696: * Creates a {@link Collection} with the passed {@link Artifact}
bjoern@4696: * @param artifact {@link Artifact} to add to the new {@link Collection}
bjoern@4696: */
bjoern@4696: private void createClonedCollection(final Artifact artifact) {
raimund@887: Config config = Config.getInstance();
raimund@887: final String locale = config.getLocale();
raimund@887: final String ownerid = user.identifier();
raimund@887:
raimund@887: createCollectionService.create(
raimund@1425: locale,
raimund@1425: ownerid,
raimund@887: new AsyncCallback() {
christian@3501: @Override
raimund@887: public void onFailure(Throwable caught) {
raimund@887: GWT.log("Could not create the new collection.");
raimund@887: SC.warn(messages.getString(caught.getMessage()));
raimund@887: }
raimund@887:
christian@3501: @Override
raimund@887: public void onSuccess(Collection collection) {
raimund@887: GWT.log("Successfully created a new collection.");
bjoern@4696: addArtifactToClonedCollection(artifact, collection);
raimund@887: }
raimund@887: }
raimund@887: );
raimund@887: }
raimund@887:
raimund@887:
bjoern@4696: private void addArtifactToClonedCollection(Artifact a, Collection c) {
ingo@1493: Config config = Config.getInstance();
ingo@1493: final String locale = config.getLocale();
raimund@887:
raimund@887: addArtifactService.add(
raimund@1425: c, a, locale,
raimund@887: new AsyncCallback() {
christian@3501: @Override
raimund@887: public void onFailure(Throwable caught) {
raimund@887: GWT.log("An error occured while adding artifact.");
raimund@887: SC.warn(messages.getString(caught.getMessage()));
raimund@887: }
raimund@887:
christian@3501: @Override
raimund@887: public void onSuccess(Collection newColl) {
raimund@887: String name = cloneCollection.getName();
raimund@887: if(name == null || name.equals("")) {
raimund@887: name = cloneCollection.identifier();
raimund@887: }
raimund@887:
bjoern@4696: String colname = messages.copy_of() + ": " + name;
raimund@887:
bjoern@4694: updateCollectionName(newColl, colname);
raimund@887: if(cloneCollection.getTTL() == 0) {
raimund@887: newColl.setTTL(0);
raimund@887: updateCollectionTTL(newColl);
raimund@887: }
raimund@887: }
raimund@887: }
raimund@887: );
raimund@887: }
bjoern@4605:
bjoern@4605:
bjoern@4605: @Override
bjoern@4605: public void onVisibilityChanged(VisibilityChangedEvent event) {
bjoern@4605: if (event.getIsVisible()) {
bjoern@4605: this.flys.hideHeaderProjectButton();
bjoern@4605: }
bjoern@4605: else {
bjoern@4605: this.flys.shoHeaderProjectButton();
bjoern@4605: }
bjoern@4605: }
bjoern@4691:
bjoern@4691: private void setFilter(String filter) {
bjoern@4691: this.filter = filter;
bjoern@4691: }
ingo@4: }
ingo@4: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :