ingo@4: package de.intevation.flys.client.client.ui; ingo@4: sascha@3473: import com.google.gwt.core.client.GWT; bjoern@4559: import com.google.gwt.event.dom.client.ClickEvent; 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; bjoern@4559: import com.google.gwt.user.client.ui.Button; 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; ingo@4: import com.smartgwt.client.widgets.Label; 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 raimund@885: implements CollectionChangeHandler, EditCompleteHandler, FilterHandler 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@885: /** The collections visible in the grid.*/ raimund@885: protected List filteredCollections; 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: 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: filteredCollections = new ArrayList(); 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: 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: bjoern@4559: Button addButton = new Button("+"); bjoern@4559: addButton.setStyleName("projectsAddButton"); bjoern@4559: addButton.setTitle(messages.new_project()); bjoern@4559: addButton.setWidth("30px"); bjoern@4559: bjoern@4559: Button closeButton = new Button("X"); bjoern@4559: closeButton.setStyleName("projectsCloseButton"); bjoern@4559: closeButton.setTitle(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: raimund@885: TableFilter filter = new TableFilter(); raimund@885: filter.setHeight("30px"); raimund@885: filter.addFilterHandler(this); christian@3709: filter.setBorder("1px solid gray"); raimund@885: ingo@4: addMember(titleWrapper); ingo@4: addMember(gridWrapper); raimund@885: addMember(filter); bjoern@4559: bjoern@4559: addButton.addClickHandler( bjoern@4559: new com.google.gwt.event.dom.client.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( bjoern@4559: new com.google.gwt.event.dom.client.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(); raimund@885: if (search != null && search.length() > 0) { raimund@885: // Filter the records. raimund@885: filterCollections(search); raimund@885: } raimund@885: else { raimund@885: filteredCollections.clear(); raimund@885: for(int i = 0; i < collections.size(); i++) { raimund@885: filteredCollections.add(collections.get(i)); raimund@885: } raimund@885: updateGrid(); raimund@885: } 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: ingo@597: c.setName(name); ingo@597: updateCollectionName(c); 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. ingo@597: */ raimund@895: protected void updateCollectionName(final Collection c) { ingo@597: if (c == null) { ingo@597: return; ingo@597: } ingo@597: 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: */ ingo@97: protected 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: */ raimund@885: protected 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: } raimund@885: filterCollections(""); raimund@885: } raimund@885: raimund@885: raimund@885: /** raimund@885: * Updates the ListGrid. raimund@885: */ raimund@885: protected void updateGrid() { ingo@97: clearGrid(); ingo@97: raimund@885: if (filteredCollections == null || raimund@885: filteredCollections.size() == 0) { ingo@599: return; ingo@599: } ingo@599: raimund@885: for (Collection c: filteredCollections) { ingo@97: grid.addData(new CollectionRecord(c)); ingo@97: } ingo@97: } ingo@226: felix@3380: raimund@885: /** raimund@885: * Filter for the user collections. raimund@885: * raimund@885: * @param search String to search for in collection names. raimund@885: */ raimund@885: protected void filterCollections(String search) { raimund@885: // Clear the collection list. raimund@885: filteredCollections.clear(); raimund@885: raimund@885: // Filter the list. raimund@885: for (int i = 0; i < collections.size(); i++) { raimund@885: String name; raimund@885: raimund@885: // Get the collection name. raimund@885: if (collections.get(i).getName().equals("") || raimund@885: collections.get(i).getName() == null) { raimund@885: name = collections.get(i).identifier(); raimund@885: } raimund@885: else { raimund@885: name = collections.get(i).getName(); raimund@885: } raimund@885: raimund@889: name = name.toLowerCase(); raimund@885: // Add a collection to the filtered list if the search string raimund@885: // matches. raimund@889: if (name.contains(search.toLowerCase())) { raimund@885: filteredCollections.add(collections.get(i)); raimund@885: } raimund@885: } raimund@885: updateGrid(); raimund@885: } raimund@885: ingo@226: 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()); raimund@887: createCollection(artifact); raimund@887: } raimund@887: } raimund@887: ); raimund@887: } raimund@887: raimund@887: felix@3380: /** felix@3380: * Clone a project (collection). felix@3380: */ felix@3380: protected 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: raimund@887: protected void createCollection(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."); raimund@887: addArtifactToCollection(artifact, collection); raimund@887: } raimund@887: } raimund@887: ); raimund@887: } raimund@887: raimund@887: raimund@887: protected void addArtifactToCollection(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: raimund@889: newColl.setName(messages.copy_of() + ": " + name); raimund@887: raimund@887: updateCollectionName(newColl); raimund@887: if(cloneCollection.getTTL() == 0) { raimund@887: newColl.setTTL(0); raimund@887: updateCollectionTTL(newColl); raimund@887: } raimund@887: updateUserCollections(); raimund@887: } raimund@887: } raimund@887: ); raimund@887: } ingo@4: } ingo@4: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :