Revision: 8092
Author: jlaba...@google.com
Date: Tue May 11 09:34:32 2010
Log: Fixes a bug where stale responses would update the ExpenseList. Also
changes the notes section of the Expense Details to be text unless the edit
button is clicked. Fixes the round trip validation associated with
updating the approval/denial for expenses.
Review by: j...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=8092
Added:
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/simplePagerLoading.gif
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/cellTreeLoadingClean.gif
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/pendingNotes.gif
Modified:
/branches/2.1/bikeshed/src/com/google/gwt/app/client/CellListPlacePickerView.java
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/SimplePager.java
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/CellTree.java
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/CellTreeClean.css
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.java
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.ui.xml
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.java
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/Expenses.java
/branches/2.1/user/src/com/google/gwt/view/client/ListViewAdapter.java
=======================================
--- /dev/null
+++
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/simplePagerLoading.gif
Tue May 11 09:34:32 2010
@@ -0,0 +1,25 @@
+GIF89a ò ÿÿÿ ÂÂÂBBB bbb‚‚‚’’’!ÿ NETSCAPE2.0 !þ Created with
ajaxload.info !ù
+ , 3 ºÜþ0ÊIk c : œ N˜f E±1º ™Á¶.`ÄÂqÐ-[ 9ݦ 9 JkçH !ù
+ , 4 ºÜþNŒ! „ »°æŠDqBQT`1 `LE[ ¨|
+µußía € × â†C ²%$* !ù
+ , 6 º2#+ÊAÈ Ì”V/
+c
+ ô NñIBa˜«p
+ð
+̳½
+ƨ+ Yí ü ƒÃ 2©d Ÿ¿ !ù
+ , 3 ºb%+Ê2†‘ìœV_
+‹¦
+! 1D‡a
+ ªF‚°Ñ bR]ó= 08, Ȥr9L !ù
+ , 2 ºr'+Jçd ð óL &vÃ`\bT”
+„¹
+hYB)ÏÊ@
+é< Ã&, ȤR’ !ù
+ , 3 º Â 9 ãtç¼Úž0 Ç
+à!.B¶ ÊW¬¢1 sa»°5÷• 0° ‰»Ÿm)J !ù
+ , 2 ºÜþð ÙœU]š îÚqp•`ˆÝaœÝ4–
+AFÅ0 `›¶
+ Â@ ›1€ÂÖΑ !ù
+ , 2 ºÜþ0ÊI«eBÔœ)×
+ Ã ŽÇq 10©Ê°®P Âa VÚ¥ ub ‚ž[ ;
=======================================
--- /dev/null
+++
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/cellTreeLoadingClean.gif
Tue May 11 09:34:32 2010
@@ -0,0 +1,25 @@
+GIF89a ò ÿÿÿnyŠÛÞâ“›¨nyŠ¥¬¶·½ÅÀÅÌ!ÿ NETSCAPE2.0 !þ Created with
ajaxload.info !ù
+ , 3 ºÜþ0ÊIk c : œ N˜f E±1º ™Á¶.`ÄÂqÐ-[ 9ݦ 9 JkçH !ù
+ , 4 ºÜþNŒ! „ »°æŠDqBQT`1 `LE[ ¨|
+µußía € × â†C ²%$* !ù
+ , 6 º2#+ÊAÈ Ì”V/
+c
+ ô NñIBa˜«p
+ð
+̳½
+ƨ+ Yí ü ƒÃ 2©d Ÿ¿ !ù
+ , 3 ºb%+Ê2†‘ìœV_
+‹¦
+! 1D‡a
+ ªF‚°Ñ bR]ó= 08, Ȥr9L !ù
+ , 2 ºr'+Jçd ð óL &vÃ`\bT”
+„¹
+hYB)ÏÊ@
+é< Ã&, ȤR’ !ù
+ , 3 º Â 9 ãtç¼Úž0 Ç
+à!.B¶ ÊW¬¢1 sa»°5÷• 0° ‰»Ÿm)J !ù
+ , 2 ºÜþð ÙœU]š îÚqp•`ˆÝaœÝ4–
+AFÅ0 `›¶
+ Â@ ›1€ÂÖΑ !ù
+ , 2 ºÜþ0ÊI«eBÔœ)×
+ Ã ŽÇq 10©Ê°®P Âa VÚ¥ ub ‚ž[ ;
=======================================
--- /dev/null
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/pendingNotes.gif
Tue May 11 09:34:32 2010
@@ -0,0 +1,32 @@
+GIF89a ó ÿÿÿKJJKJJ¦¦¦›ššÁÁÁÏÏÏÜÛÛççç³²²îî“ !þ Created
with ajaxload.info !ù
+ !ÿ NETSCAPE2.0 , + ÈI«½8OÁ»ÿÜ@ Æ `áXžWJš¨ ¾¬å®ñŒ·²
+ó GC, ” !ù
+ , + ÈI«½8OÁ»ÿ\‘ Ä `áXžWJš¨ ¾¬å®ñŒ·²
+ó GC, ” !ù
+ , + ÈI«½8OÁ»ÿÜa ...@`áxžwjš¨ ¾¬å®ñŒ·²
+ó GC, ” !ù
+ , 1 ÈI«½8OÁ»ÿœ‚
+F‘ „ Žå™V+i¢ª Ên}·4l³³ %Æ n...@ÈŽfÉl:) !ù
+ , 6 ÈI«½8OÁ»ÿœ¤ ‡Q$ A
+ÀXžé*ˆ¤‰ªÛÜÖ0.±.[,G{ÝdE¡ jz4ШtJ‰ !ù
+ , 6 ÈI«½8OÁ»ÿ
+¥ ‡Q$ !
+ÓXžé*ˆ¤‰ª +¹vœÏ § ð†2Úë& 9‹š¨tJ !ù
+ , 1 ÈI«½8OÁ»ÿœ¥ ‡Q$ Vcy¦+Õš¨*ˆ$
+ßlþÚ8w-6...@h fÉl:) !ù
+ , + ÈI«½8OÁ»ÿ
+¦ ‡± á5–gj&*ˆdìVp;«µN³2 ð¦) È !ù
+ , & ÈI«½8OÁ»ÿœ¶ C fcyb©)ˆ¤ «/ ¯W îžæÿÀ % !ù
+ , + ÈI«½8OÁ»ÿ
+¶ CR á5–gj&*ˆdìVp;«µN³2 ð¦) È !ù
+
+ , 1 ÈI«½8OÁ»ÿœµ CR Vcy¦+Õš¨*ˆ$
+ßlþÚ8w-6...@h fÉl:) !ù
+ , 6 ÈI«½8OÁ»ÿ
+µ CR "
+ÓXžé*ˆ¤‰ª +¹vœÏ § ð†2Úë& 9‹š¨tJ !ù
+ , 6 ÈI«½8OÁ»ÿœ´ CR B
+ÀXžé*ˆ¤‰ªÛÜÖ0.±.[,G{ÝdE¡ jz4ШtJ‰ !ù
+
+ , 1 ÈI«½8OÁ»ÿÜB Ia
+ˆ Žå™V+i¢ª Ên}·4l³³ %Æ n...@ÈŽfÉl:) ;
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/app/client/CellListPlacePickerView.java
Tue May 11 09:04:15 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/app/client/CellListPlacePickerView.java
Tue May 11 09:34:32 2010
@@ -53,7 +53,6 @@
initWidget(cellList);
cellList.setSelectionModel(smodel);
smodel.addSelectionChangeHandler(new SelectionChangeHandler() {
- @Override
public void onSelectionChange(SelectionChangeEvent event) {
if (listener != null) {
listener.placePicked(smodel.getSelectedObject());
@@ -80,7 +79,6 @@
cellList.setPageSize(size);
}
- @Override
public void setValues(List<P> places, Renderer<P> renderer) {
// Replace the current renderer.
this.renderer = renderer;
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/SimplePager.java
Thu May 6 19:50:57 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/list/client/SimplePager.java
Tue May 11 09:34:32 2010
@@ -22,10 +22,11 @@
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.client.UiConstructor;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.PagingListView;
/**
@@ -68,6 +69,11 @@
*/
ImageResource simplePagerLastPageDisabled();
+ /**
+ * The icon to use while the page is loading.
+ */
+ ImageResource simplePagerLoading();
+
/**
* The image used to go to the next page.
*/
@@ -126,9 +132,19 @@
}
private final Image firstPage;
- private final Label label = new Label();
+
+ /**
+ * We use an {...@link HTML} so we can embed the loading image.
+ */
+ private final HTML label = new HTML();
+
private final Image lastPage;
+ /**
+ * The html used to render the loading image.
+ */
+ private final String loadingImageHtml;
+
/**
* Set to true when the next and last buttons are disabled.
*/
@@ -187,6 +203,10 @@
this.style = resources.simplePagerStyle();
this.style.ensureInjected();
+ // Create the loading image.
+ AbstractImagePrototype loadingProto =
AbstractImagePrototype.create(resources.simplePagerLoading());
+ loadingImageHtml = loadingProto.getHTML();
+
// Create the buttons.
firstPage = new Image(resources.simplePagerFirstPage());
lastPage = new Image(resources.simplePagerLastPage());
@@ -288,6 +308,18 @@
}
}
}
+
+ /**
+ * Let the page know that the table is loading. Call this method to
clear all
+ * data from the table and hide the current range when new data is being
+ * loaded into the table.
+ */
+ public void startLoading() {
+ PagingListView<T> listView = getPagingListView();
+ listView.setDataSize(0, true);
+ onRangeOrSizeChanged(listView);
+ label.setHTML(loadingImageHtml);
+ }
/**
* Get the text to display in the pager that reflects the state of the
pager.
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/CellTree.java
Mon May 10 15:03:36 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/CellTree.java
Tue May 11 09:34:32 2010
@@ -358,6 +358,9 @@
@Source("cellTreeClosedArrow.png")
ImageResource cellTreeClosedItem();
+ @Source("cellTreeLoadingClean.gif")
+ ImageResource cellTreeLoading();
+
@Source("cellTreeOpenArrow.png")
ImageResource cellTreeOpenItem();
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/CellTreeClean.css
Mon May 10 06:16:12 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/bikeshed/tree/client/CellTreeClean.css
Tue May 11 09:34:32 2010
@@ -40,6 +40,7 @@
.topItemImageValue {
border-bottom: 1px solid #6f7277;
+ padding-bottom: 1px;
}
@sprite .selectedItem {
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.java
Mon May 10 15:03:36 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.java
Tue May 11 09:34:32 2010
@@ -29,8 +29,13 @@
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.SelectElement;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
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.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
@@ -43,6 +48,7 @@
import com.google.gwt.sample.expenses.gwt.request.ExpenseRecordChanged;
import com.google.gwt.sample.expenses.gwt.request.ExpensesRequestFactory;
import com.google.gwt.sample.expenses.gwt.request.ReportRecord;
+import com.google.gwt.sample.expenses.gwt.request.ReportRecordChanged;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
@@ -77,7 +83,7 @@
* including the list of expenses.
*/
public class ExpenseDetails extends Composite implements
- Receiver<List<ExpenseRecord>>, ExpenseRecordChanged.Handler {
+ ExpenseRecordChanged.Handler, ReportRecordChanged.Handler {
/**
* String indicating approval.
@@ -335,9 +341,21 @@
ExpensesRequestFactory expensesRequestFactory;
+ @UiField
+ Element notes;
+
@UiField
TextBox notesBox;
+ @UiField
+ Anchor notesEditLink;
+
+ @UiField
+ Element notesEditLinkWrapper;
+
+ @UiField
+ Element notesPending;
+
@UiField
Element reportName;
@@ -372,6 +390,11 @@
private Comparator<ExpenseRecord> lastComparator;
+ /**
+ * Keep track of the last receiver so we can ignore stale responses.
+ */
+ private Receiver<List<ExpenseRecord>> lastReceiver;
+
/**
* The current report being displayed.
*/
@@ -389,6 +412,38 @@
items.setKeyProvider(Expenses.EXPENSE_RECORD_KEY_PROVIDER);
table.setKeyProvider(items);
items.addView(table);
+
+ // Switch to edit notes.
+ notesEditLink.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ setNotesEditState(true, false, report.getNotes());
+ }
+ });
+
+ // Switch to view mode.
+ notesBox.addBlurHandler(new BlurHandler() {
+ public void onBlur(BlurEvent event) {
+ // The text box will be blurred on cancel, so only save the notes
if
+ // it is visible.
+ if (notesBox.isVisible()) {
+ saveNotes();
+ }
+ }
+ });
+ notesBox.addKeyUpHandler(new KeyUpHandler() {
+ public void onKeyUp(KeyUpEvent event) {
+ int keyCode = event.getNativeKeyCode();
+ switch (keyCode) {
+ case KeyCodes.KEY_ENTER:
+ saveNotes();
+ break;
+ case KeyCodes.KEY_ESCAPE:
+ // Cancel the edit.
+ setNotesEditState(false, false, report.getNotes());
+ break;
+ }
+ }
+ });
}
public Anchor getReportsLink() {
@@ -397,13 +452,20 @@
public void onExpenseRecordChanged(ExpenseRecordChanged event) {
ExpenseRecord newRecord = event.getRecord();
- String id = newRecord.getId();
+ Object newKey = items.getKey(newRecord);
int index = 0;
List<ExpenseRecord> list = items.getList();
for (ExpenseRecord r : list) {
- if (r.getId().equals(id)) {
+ if (items.getKey(r).equals(newKey)) {
list.set(index, newRecord);
+
+ // Update the view data if the approval has been updated.
+ ApprovalViewData avd = (ApprovalViewData)
approvalColumn.getViewData(newKey);
+ if (avd != null
+ && avd.getPendingApproval().equals(newRecord.getApproval())) {
+ syncCommit(newRecord, null);
+ }
}
index++;
}
@@ -414,11 +476,12 @@
}
}
- public void onSuccess(List<ExpenseRecord> newValues) {
- List<ExpenseRecord> list = new ArrayList<ExpenseRecord>(newValues);
- sortExpenses(list, lastComparator);
- items.setList(list);
- refreshCost();
+ public void onReportChanged(ReportRecordChanged event) {
+ ReportRecord changed = event.getRecord();
+ if (report != null && report.getId().equals(changed.getId())) {
+ report = changed;
+ setNotesEditState(false, false, changed.getNotes());
+ }
}
public void setExpensesRequestFactory(
@@ -437,10 +500,11 @@
EmployeeRecord employee) {
this.report = report;
reportName.setInnerText(report.getPurpose());
- notesBox.setText(report.getNotes());
costLabel.setInnerText("");
approvedLabel.setInnerText("");
unreconciledLabel.setInnerText("");
+ setNotesEditState(false, false, report.getNotes());
+ items.getList().clear();
totalApproved = 0;
// Update the breadcrumb.
@@ -683,8 +747,63 @@
* Request the expenses.
*/
private void requestExpenses() {
+ lastReceiver = new Receiver<List<ExpenseRecord>>() {
+ public void onSuccess(List<ExpenseRecord> newValues) {
+ if (this == lastReceiver) {
+ List<ExpenseRecord> list = new
ArrayList<ExpenseRecord>(newValues);
+ sortExpenses(list, lastComparator);
+ items.setList(list);
+ refreshCost();
+ }
+ }
+ };
expensesRequestFactory.expenseRequest().findExpensesByReport(
-
report.getRef(Record.id)).forProperties(getExpenseColumns()).to(this).fire();
+ report.getRef(Record.id)).forProperties(getExpenseColumns()).to(
+ lastReceiver).fire();
+ }
+
+ /**
+ * Save the notes that the user entered in the notes box.
+ */
+ private void saveNotes() {
+ // Early exit if the notes haven't changed.
+ final String pendingNotes = notesBox.getText();
+ if (pendingNotes.equals(report.getNotes())) {
+ setNotesEditState(false, false, pendingNotes);
+ return;
+ }
+
+ // Switch to the pending view.
+ setNotesEditState(false, true, pendingNotes);
+
+ // Submit the delta.
+ DeltaValueStore deltas =
expensesRequestFactory.getValueStore().spawnDeltaView();
+ deltas.set(ReportRecord.notes, report, pendingNotes);
+ expensesRequestFactory.syncRequest(deltas).to(
+ new Receiver<Set<SyncResult>>() {
+ public void onSuccess(Set<SyncResult> response) {
+ // We expect onReportChanged to be called.
+ }
+ }).fire();
+ }
+
+ /**
+ * Set the state of the notes section.
+ *
+ * @param editable true for edit state, false for view state
+ * @param pending true if changes are pending, false if not
+ * @param notesText the current notes
+ */
+ private void setNotesEditState(boolean editable, boolean pending,
+ String notesText) {
+ notesBox.setText(notesText);
+ notes.setInnerText(notesText);
+
+ notesBox.setVisible(editable && !pending);
+ setVisible(notes, !editable);
+ setVisible(notesEditLinkWrapper, !editable && !pending);
+ setVisible(notesPending, pending);
+ notesBox.setFocus(editable);
}
private void sortExpenses(List<ExpenseRecord> list,
@@ -706,12 +825,12 @@
if (avd != null) {
avd.reject(message);
}
-
- // Redraw the table so the changes are applied.
- table.redraw();
} else {
approvalColumn.setViewData(key, null);
}
+
+ // Redraw the table so the changes are applied.
+ table.redraw();
}
private void updateExpenseRecord(final ExpenseRecord record, String
approval,
@@ -748,9 +867,6 @@
syncCommit(record, errorMessage.length() > 0 ? errorMessage
: null);
}
-
- // Request the updated expenses.
- requestExpenses();
}
}).fire();
}
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.ui.xml
Tue May 11 03:34:50 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseDetails.ui.xml
Tue May 11 09:34:32 2010
@@ -1,14 +1,25 @@
<!DOCTYPE ui:UiBinder SYSTEM 'http://dl.google.com/gwt/DTD/xhtml.ent'>
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
+<ui:UiBinder
+ xmlns:ui='urn:ui:com.google.gwt.uibinder'
+ xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:l='urn:import:com.google.gwt.bikeshed.list.client'>
- <ui:style field='desktop' src='desktop.css' />
-
- <ui:image field='cornerTopRight' />
- <ui:image field='cornerTopLeft' />
- <ui:image field='cornerBottomRight' />
- <ui:image field='cornerBottomLeft' />
- <ui:image field='leftArrow' />
+ <ui:style
+ field='desktop'
+ src='desktop.css' />
+
+ <ui:image
+ field='cornerTopRight' />
+ <ui:image
+ field='cornerTopLeft' />
+ <ui:image
+ field='cornerBottomRight' />
+ <ui:image
+ field='cornerBottomLeft' />
+ <ui:image
+ field='leftArrow' />
+ <ui:image
+ field='pendingNotes' />
<ui:style>
.details {
@@ -20,20 +31,23 @@
gwt-image: 'leftArrow';
}
- .reportLink {
- margin-left: 5px;
+ .link {
text-decoration: underline;
color: black;
cursor: hand;
cursor: pointer;
}
- .reportLink:hover {
+ .link:hover {
text-decoration: underline;
color: black;
cursor: hand;
cursor: pointer;
}
+
+ .reportLink {
+ margin-left: 5px;
+ }
.label {
width: 250px;
@@ -51,69 +65,109 @@
.notesColumn {
width: 400px;
- padding-right: 100px;
+ padding-right: 100px;
}
- .notes {
- width: 400px;
+ .notesTextBox {
+ width: 350px;
border: 1px solid #d7dde8;
padding: 3px;
}
+
+ .notesEditLink {
+ font-weight: bold;
+ }
+
+ @sprite .pendingNotes {
+ gwt-image: 'pendingNotes';
+ margin-left: 10px;
+ }
</ui:style>
- <g:DockLayoutPanel unit='PX'>
- <g:north size='180'>
- <g:HTMLPanel styleName='{desktop.breadcrumbBar}'>
- <table align='center' width='100%' cellspacing='0' cellpadding='0'>
+ <g:DockLayoutPanel
+ unit='PX'>
+ <g:north
+ size='180'>
+ <g:HTMLPanel
+ styleName='{desktop.breadcrumbBar}'>
+ <table
+ align='center'
+ width='100%'
+ cellspacing='0'
+ cellpadding='0'>
<!-- Top of 9 box. -->
<tr>
- <td class='{desktop.breadcrumbCorner}'>
- <div class='{desktop.breadcrumbCornerTopLeft}' />
+ <td
+ class='{desktop.breadcrumbCorner}'>
+ <div
+ class='{desktop.breadcrumbCornerTopLeft}' />
</td>
- <td class='{desktop.breadcrumbBorder}'>
- <div class='{desktop.breadcrumbBorderInner}' />
+ <td
+ class='{desktop.breadcrumbBorder}'>
+ <div
+ class='{desktop.breadcrumbBorderInner}' />
</td>
- <td class='{desktop.breadcrumbCorner}'>
- <div class='{desktop.breadcrumbCornerTopRight}' />
+ <td
+ class='{desktop.breadcrumbCorner}'>
+ <div
+ class='{desktop.breadcrumbCornerTopRight}' />
</td>
</tr>
<tr>
<!-- Left of 9 box. -->
- <td class='{desktop.breadcrumbBorder}'>
- <div class='{desktop.breadcrumbBorderInner}' />
+ <td
+ class='{desktop.breadcrumbBorder}'>
+ <div
+ class='{desktop.breadcrumbBorderInner}' />
</td>
<!-- Breadcrumb. -->
- <td class='{desktop.breadcrumb} {desktop.breadcrumbBorder}'
+ <td
+ class='{desktop.breadcrumb} {desktop.breadcrumbBorder}'
ui:field='reportName'>
</td>
<!-- Right of 9 box. -->
- <td class='{desktop.breadcrumbBorder}'>
- <div class='{desktop.breadcrumbBorderInner}' />
+ <td
+ class='{desktop.breadcrumbBorder}'>
+ <div
+ class='{desktop.breadcrumbBorderInner}' />
</td>
</tr>
<!-- Bottom of 9 box. -->
<tr>
- <td class='{desktop.breadcrumbCorner}'>
- <div class='{desktop.breadcrumbCornerBottomLeft}' />
+ <td
+ class='{desktop.breadcrumbCorner}'>
+ <div
+ class='{desktop.breadcrumbCornerBottomLeft}' />
</td>
- <td class='{desktop.breadcrumbBorder}'>
- <div class='{desktop.breadcrumbBorderInner}' />
+ <td
+ class='{desktop.breadcrumbBorder}'>
+ <div
+ class='{desktop.breadcrumbBorderInner}' />
</td>
- <td class='{desktop.breadcrumbCorner}'>
- <div class='{desktop.breadcrumbCornerBottomRight}' />
+ <td
+ class='{desktop.breadcrumbCorner}'>
+ <div
+ class='{desktop.breadcrumbCornerBottomRight}' />
</td>
</tr>
<!-- Link back to report list. -->
<tr>
- <td colspan='3' style='padding-top:6px;'>
- <table cellpadding='0' cellspacing='0'>
+ <td
+ colspan='3'
+ style='padding-top:6px;'>
+ <table
+ cellpadding='0'
+ cellspacing='0'>
<tr>
<td>
- <div class='{style.leftArrow}' />
+ <div
+ class='{style.leftArrow}' />
</td>
<td>
- <g:Anchor styleName='{style.reportLink}'
ui:field='reportsLink' />
+ <g:Anchor
+ styleName='{style.reportLink} {style.link}'
+ ui:field='reportsLink' />
</td>
</tr>
</table>
@@ -122,36 +176,78 @@
</table>
<!-- Details about the Report. -->
- <table class='{style.details}' cellpadding='0' cellspacing='0'>
+ <table
+ class='{style.details}'
+ cellpadding='0'
+ cellspacing='0'>
<tr>
- <td class='{style.label}'>
+ <td
+ class='{style.label}'>
Cost:
</td>
- <td align='right' class='{style.amount}' ui:field='costLabel'>
+ <td
+ align='right'
+ class='{style.amount}'
+ ui:field='costLabel'>
</td>
- <td rowspan='3'>
+ <td
+ rowspan='3'>
</td>
- <td class='{style.label} {style.notesColumn}'>
- Notes:
+ <td
+ class='{style.notesColumn}'>
+ <table
+ cellspacing='0'
+ cellpadding='0'>
+ <tr>
+ <td>
+ Notes:
+ </td>
+ <td>
+ <div
+ class='{style.pendingNotes}'
+ ui:field='notesPending' />
+ </td>
+ </tr>
+ </table>
</td>
</tr>
<tr>
- <td class='{style.label} {style.dotted}'>
+ <td
+ class='{style.label} {style.dotted}'>
Approved:
</td>
- <td align='right' class='{style.amount} {style.dotted}'
+ <td
+ align='right'
+ class='{style.amount} {style.dotted}'
ui:field='approvedLabel'>
</td>
- <td rowspan='2' class='{style.notesColumn}' valign='top'>
- <g:TextBox styleName='{style.notes}' ui:field='notesBox' />
+ <td
+ rowspan='2'
+ class='{style.notesColumn}'
+ valign='top'>
+ <g:TextBox
+ styleName='{style.notesTextBox}'
+ ui:field='notesBox' />
+ <span
+ ui:field='notes' />
+ <span
+ ui:field='notesEditLinkWrapper'>
+ (<g:Anchor
+ styleName='{style.link} {style.notesEditLink}'
+ ui:field='notesEditLink'>edit</g:Anchor>)
+ </span>
</td>
</tr>
<tr>
- <td class='{style.label}'>
+ <td
+ class='{style.label}'>
<b>Un-reconciled:</b>
</td>
- <td align='right' class='{style.amount}'
style='font-weight:bold'
+ <td
+ align='right'
+ class='{style.amount}'
+ style='font-weight:bold'
ui:field='unreconciledLabel'>
</td>
</tr>
@@ -161,7 +257,9 @@
<g:center>
<g:ScrollPanel>
- <l:CellTable addStyleNames='{desktop.table}' width='100%'
+ <l:CellTable
+ addStyleNames='{desktop.table}'
+ width='100%'
ui:field='table' />
</g:ScrollPanel>
</g:center>
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.java
Mon May 10 15:03:36 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpenseList.java
Tue May 11 09:34:32 2010
@@ -66,7 +66,7 @@
* The list of expense reports on the left side of the app.
*/
public class ExpenseList extends Composite implements
- Receiver<List<ReportRecord>>, ReportRecordChanged.Handler {
+ ReportRecordChanged.Handler {
private static ExpenseListUiBinder uiBinder =
GWT.create(ExpenseListUiBinder.class);
@@ -232,6 +232,16 @@
*/
private String orderBy = ReportRecord.purpose.getName();
+ /**
+ * Keep track of the last receiver so that we know if a response is
stale.
+ */
+ private Receiver<List<ReportRecord>> lastDataReceiver;
+
+ /**
+ * Keep track of the last receiver so that we know if a response is
stale.
+ */
+ private Receiver<Long> lastDataSizeReceiver;
+
private Listener listener;
/**
@@ -310,10 +320,6 @@
i++;
}
}
-
- public void onSuccess(List<ReportRecord> newValues) {
- reports.updateViewData(table.getPageStart(), newValues.size(),
newValues);
- }
/**
* Set the current department and employee to filter on.
@@ -492,17 +498,30 @@
// Request the total data size.
if (isCountStale) {
isCountStale = false;
- requestFactory.reportRequest().countReportsBySearch(employeeId,
- startsWith).to(new Receiver<Long>() {
+ pager.startLoading();
+ lastDataSizeReceiver = new Receiver<Long>() {
public void onSuccess(Long response) {
- reports.updateDataSize(response.intValue(), true);
- }
- }).fire();
+ if (this == lastDataSizeReceiver) {
+ reports.updateDataSize(response.intValue(), true);
+ }
+ }
+ };
+ requestFactory.reportRequest().countReportsBySearch(employeeId,
+ startsWith).to(lastDataSizeReceiver).fire();
}
// Request reports in the current range.
+ lastDataReceiver = new Receiver<List<ReportRecord>>() {
+ public void onSuccess(List<ReportRecord> newValues) {
+ if (this == lastDataReceiver) {
+ reports.updateViewData(table.getPageStart(), newValues.size(),
+ newValues);
+ }
+ }
+ };
+ // TODO(jlabanca): Pass the department into the query.
requestFactory.reportRequest().findReportEntriesBySearch(employeeId,
startsWith, orderBy, range.getStart(),
range.getLength()).forProperties(
- reportColumns).to(this).fire();
+ reportColumns).to(lastDataReceiver).fire();
}
}
=======================================
---
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/Expenses.java
Thu May 6 12:36:08 2010
+++
/branches/2.1/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/Expenses.java
Tue May 11 09:34:32 2010
@@ -91,6 +91,8 @@
expenseList.setRequestFactory(requestFactory);
eventBus.addHandler(ReportRecordChanged.TYPE, expenseList);
+ // Forward change events to the expense details.
eventBus.addHandler(ExpenseRecordChanged.TYPE, expenseDetails);
+ eventBus.addHandler(ReportRecordChanged.TYPE, expenseDetails);
}
}
=======================================
--- /branches/2.1/user/src/com/google/gwt/view/client/ListViewAdapter.java
Wed May 5 13:18:30 2010
+++ /branches/2.1/user/src/com/google/gwt/view/client/ListViewAdapter.java
Tue May 11 09:34:32 2010
@@ -400,8 +400,7 @@
*/
public void setList(List<T> wrappee) {
listWrapper = new ListWrapper(wrappee);
- updateDataSize(listWrapper.size(), true);
- updateViewData(0, listWrapper.size(), listWrapper);
+ listWrapper.flush();
}
@Override
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors