GeneXus: Websession's contents will not be preserved between calls to Refresh - smart-device

I need to refill my grid each time the user sets a new date (data from a WebService).
According to event triggering order, I was thinking of:
(1) Action Event: call a procedure to get the data, transform it, fill the SDT and put it on a WebSession var.
(2) Refresh Event: re-build the local SDT with the new values.
(3) Load Event: Load the grid.
However, when I build this, I can see a warning saying:
spc0185: Websession's contents will not be preserved between calls to Refresh event.
And I can confirm that the behaviour is a bit odd (the grid is only refreshed the fist time user changes the date).
Event &myDate.ControlValueChanged
composite
setGridJson(&mydate)
Refresh
endcomposite
Endevent
Event Refresh
&mydate = ctod(&websession.get('newDate')) //to refresh the date var
&myJSON = &websession.get('GridJSON')
&mySDT.FromJson(&myJSON)
Endevent
Event Load
for &mySDTItem in &mySDT
&field1 = &mySDTItem.field1
&field2 = &mySDTItem.field2
&field3 = &mySDTItem.field3
LOAD
endfor
Endevent
Is there any workaround for this? How can I refill the grid each time the &myDate var changes?
Thanks

Related

Why is the server response after a Drag&Drop so large and slow

I'm having some performance issues dragging cards between grids. From a backend perspective, storing the data from the grids after a change takes about 200ms.
But then, when the backend work seems to be done, it takes another 2,5 seconds for the frontend to get the response from the request. The request that's taking so long contact 2 rpc events: grid-drop and grid-dragend.
The response is also unusually large I think. Just to give you an idea, see screenshot ... notice the tiny scrollbar at the right. 🙂
TTFB is 2,42s, download size about half a MB.
Any ideas what's going on here and how I can eliminate this?
I'm using Vaadin 21.0.4, spring boot 2.5.4.
Steps I've taken to optimise performance:
Optimize db query + indexing
Use #cacheable where possible
Implemented the cards using LitElement
This is the drop listener:
ComponentEventListener<GridDropEvent<Task>> dropListener = event -> {
if (dragSource != null) {
// The item ontop or below where the source item is dropped. Used to calculate the index of the newly dropped item(s)
Optional<Task> targetItem = event.getDropTargetItem();
// if the item is dropped on an existing row and the dragged item contains the same items that's being dropped.
if (targetItem.isPresent() && draggedItems.contains(targetItem.get())) {
return;
}
// Add dragged items to the grid of the target room
Grid<Task> targetGrid = event.getSource();
Optional<Room> room = dayPlanningView.getRoomForGrid(targetGrid);
// The items of the target Grid. Using listdataview so this would not retrigger the query
List<Task> targetItems = targetGrid.getListDataView().getItems().toList();
// Calculate the position of the dropped item
int index = targetItem.map(task -> targetItems.indexOf(task)
+ (event.getDropLocation() == GridDropLocation.BELOW ? 1 : 0))
.orElse(0);
room.ifPresent(r -> service.plan(draggedItems, r, index, dayPlanningView.getSelectedDate()));
// send event to update other users
Optional<ScheduleUpdatedEvent> scheduleUpdatedEvent = room.map(r -> new ScheduleUpdatedEvent(PlanningMasterDetailView.this, r.getId()));
scheduleUpdatedEvent.ifPresent(Broadcaster::broadcast);
// remove items from the source grid. using list provider so items can be removed without DB round-trip.
productionOrderGrid.getListDataView().removeItems(draggedItems);
}
};
I'm a bit stuck now, as I'm kinda out of ideas 😦
Thanks
You should use the TemplateRenderer/LitRenderer instead of the ComponentRenderer because the generated server-side components are affecting the performance:
Read more here: https://vaadin.com/blog/top-5-most-common-vaadin-performance-pitfalls-and-how-to-avoid-them

Delphi and ADODataset.Cancel

I'm using Dephi 10.1 Berlin and Access 2013.
My problem is related to TADODataSet.Cancel().
I want to show my user a message box asking for a confirmation before posting, in case data has been modified.
In the TADODataSet.BeforePost event, I added the following code:
if Application.MessageBox('Save changes?', '', 52) = idNo then
ADODataSet1.Cancel;
If the user click on btnNo, something unexpected happens.
Changes are canceled from the current record, but a new record with all fields empty is created.
The only field with some data is the one that was previously modified by the user.
If I cancel the modification via the cancel button of TDBNavigator, everything is fine.
If I simulate a click of the Cancel button of the TDBNnavigator in the BeforePost event:
if Application.MessageBox('Save changes?', '', 52) = idNo then
DBNavigator1.BtnClick(nbCancel);
I have the same behaviour, so a new empty record is created.
Any suggestion?
The help for TADODataSet.BeforePost says in part:
call Abort to cancel the Post operation (Delphi) or throw an exception (C++).
So:
if Application.MessageBox('Save changes?', '', 52) = idNo then
abort;
Note this is meant for preventing changes that don't pass validation (the common use for BeforePost) from being posted. It doesn't reset the edit buffers like cancel does. Usually that is a separate function in the UI so the user doesn't have to reenter all the changed data in the edits each time posting is rejected by calling abort in BeforePost.

Viewers (per Link) jump to current date when they open file

I have a table in Google Sheets in the format:
A B C
Day Date inventory demand
Day2 Date2 inventory demand
etc.
Others are required to fill in inventory and demand every day. Thus, it would be helpful if they open the sheet they jump always to the current date. This could be done over HYPERLINK or code. However, as I am informed onOpen works for the editor, however not for viewers. As this is currently the case. When I open the file I jump to the current date, however people viewing and editing the file per link do not.
Could somebody please help me? Thank you.
I also do not understand, why creating a cell that jumps to the current date as an alternative does not work.
I tried various variations of
=HYPERLINK("l i n k&range=B"&MATCH("TODAY",B1:B1500,0),"Jump to today")
or
=HyperLink("LINK&range=B" &Match(Today(),B6:B,1),"JUMP to Today")
// jump to current date
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("B:B");
var values = range.getValues();
var day = 24*3600*1000;
var today = parseInt((new Date().setHours(0,0,0,0))/day);
var ssdate;
for (var i=0; i<values.length; i++) {
try {
ssdate = values[i][0].getTime()/day;
}
catch(e) {
}
if (ssdate && Math.floor(ssdate) == today) {
sheet.setActiveRange(range.offset(i,0,1,1));
break;
}
}
}
try like this:
=HYPERLINK("#gid=0&range=B"&MATCH(TODAY(); B6:B; 0)+5; "zu heute")
I found the options: Edit Triggers
To manually create an installable trigger through a dialog in the script editor, follow these steps:
From the script editor, choose Edit > Current project's triggers.
Click the link that says: No triggers set up. Click here to add one now.
Under Run, select the name of function you want to trigger.
Under Events, select either Time-driven or the Google App that the script is bound to (for example, From spreadsheet).
Select and configure the type of trigger you want to create (for example, an Hour timer that runs Every hour or an On open trigger).
Optionally, click Notifications to configure how and when you are contacted by email if your triggered function fails.
Click Save.
Google Explanation

Limit the frequency of calls to onEdit

I wrote some scripts using the script editor to automate some google spread-sheet tasks.
I would like to do a few things after the user interacts with my users sheets, .e.g update some background sheets that start with _.
I wrote the following:
function onEdit(e){
var range = e.range;
if (e.source.getActiveSheet().getName()[0]!='_'){
//It is an user edit!
UpdateOtherHiddenTables()
}
};
My problem is that UpdateOtherHiddenTables() takes quite a while, like 2 mins, and it is triggered on any user edit so it is not ideal.
How would you make sure that after a user has interacted with a sheet, that UpdateOtherHiddenTables() is called, but not too often?
I would use Script properties in combination with a timed trigger. The on-Edit trigger only records the fact that the Spreadsheet was edited:
function recordEdit() {
var sp = PropertiesService.getScriptProperties();
sp.setProperty("edited", "yes");
}
This function needs to be run by an installable trigger, simple onEdit won't provide the authorization necessary to modify script properties.
The UpdateOtherHiddenTables function is set to run every 10 minutes, or every hour, or whatever interval you want. It checks whether a refresh is needed.
function UpdateOtherHiddenTables() {
var sp = PropertiesService.getScriptProperties();
if (sp.getProperty("edited") == "yes") {
// update stuff
sp.setProperty("edited", "no");
}
}
By the way: onEdit is only triggered by user edits. A script changing the values in a spreadsheet will not fire that trigger.
I'm using string values instead of Boolean, because Properties stringifies everything. Storing false gets you back the string "false", which is truthy...

bacon.js how to combine stream with another based on first ?

I have a stream daysFromApi$ with data (days with meals) from API. When a 'delete' button is clicked, I push mealId to this.deleteBus$. I want to have a new value in the stream: daysAfterDelete$. My problem is that 'first' event is always triggered, but 'done' never triggers, flatMapLatest does not work, map neither.
const daysAfterDelete$ = this.deleteBus$
.log('first') // triggers when new mealId is pushed to deleteBus(a button is clicked)
.flatMapLatest(mealId => Bacon.combineAsArray(daysFromApi$, mealId))
.log('done'); // never triggers
I want to get following flow:
daysFromApi$ : A B C
deleteBus$ : 1 2 3
daysAfterDelete$: (1,A) (2,B) (3,B)
Not quite sure what you want to achieve, but if you want to get the latest value of "days" when the delete is clicked, you can use sampledBy. https://www.webpackbin.com/bins/-Ki3lTzM8PM4zeJKK9C0

Resources