How to show a popup dialogue box AFTER a long running operation completes
I need some help here on finding a right way to do this.
I had originally asked this question about awaiting the completion of a long running operation. That question was answered, but it didn't solve the issue. I have a custom action that opens a Smart Panel to capture some data from the user, which is then passed into a long running operation to fetch physical inventory count data from Zoho and update the INPIReview document. This all works.
However, when processing the import, an important step is to record any items that were counted in Zoho, that do not exist on the Physical Inventory Review document so the user can be alerted that some additional items were counted. There won’t be many items, so we simply opted to write the details of those extra items to trace, and then notify the user with a dialogue box warning them that extra items were counted and they need to review the trace log. This also works - kind of.
After clicking “OK” on the dialogue box that pops up, the original Smart Panel pops up again. According to this article, “The ask method actually throws an error that the system then catches and displays the popup window. After the user interacts with it the system calls the same method except the call to Ask now returns the value from the user interaction.”
I’m wonding if this may be why the smart panel is being triggered again, but I’ve tried so many different things, and I can’t get it to behave properly.
I just want to call the dialogue box AFTER the long running operation is completely finished, if the value of my “didWriteToTrace” variable is true.
I also tried creating a class that implements the IPXCustomInfo interface and just triggering a PXException in the Complete() method. However, it still seems to execute prior to the completion of the process, and throwing the exception prevents it from completing correctly.
Am I on the right track here?
Page 1 / 1
Dialogs like this have gotten me all fuddled up in the past, and I still don’t really know exactly how they work, but I don’t suppose it would be as simple as encapsulating your first dialog like:
bool didWriteToTrace = false;
if (!didWriteToTrace) { CountParams.AskExt(...) }
if (didWriteToTrace) Base.PIHeader.Ask(...)
return adapter.Get();
I’m not sure if, when the method is hit the second time, didWriteToTrace will still be true (since the code is setting it to false initially), but maybe be worth a shot.
If that doesn’t work, you could try pulling your didWriteToTrace variable out of that method in hopes that it would remain true through the process.
@darylbowman ChatGPT actually suggested a similar thing, which I tried, but it doesn’t work. I even tried creating a private bool property like “ParamsCollected” to the graphExt which I set to true inside the IF statement, but that still didn’t work. It’s almost as though the entire graph is re-instantiated when the dialogue box is closed, because when I debugged it, the value was set to true after clicking OK on the smart panel popup, but then after the process was finished and the second pop-up opened and I clicked “OK” on it, the value of the property was reset to it’s original state.
I wonder if you need to check the .Ask value of Base.PIHeader.View like you do for the .AskExt call above?
if (didWriteToTrace) { if (Base.PIHeader.Ask(...) = WebDialogResult.Ok) {}; }
In another thread around dialogs Dmitrii Naumov said:
It is related to the way Web Dialogs work in the framework.
In fact, when you call a web dialog, it throws an exception and remembers the current method where the exception has been thrown from. It then sets ‘Dialog Answer’ variable to the view and executes the method again.
So, I think, the second .Ask triggers the dialog to appear and then the code is run again and since you’re not testing for the answer that the user gave, that makes the dialog appear the second time. I stress I think because, based on my theory, your main loop should also run a second time and I think you’d notice that happening.
@Django Unfortunately checking the .Ask value doesn’t make a difference. I’m still at a loss.
I know that the method is executed again, when the dialogue box closes, so it makes sense that it’s triggering the first pop-up again. And you are right, it would go through the loop again, except for the fact that it’s interrupted by the first pop-up, which I then just always close without clicking okay.
It just seems strange that there would be no good way to show the user a popup message at the end of a long running operation.
I did a very quick look in the source code for AskExt to see if there are any methods when there are two calls to .Ask. I stopped looking after finding about 10 .AskExt calls but I didn’t see any methods where it was called twice.
You might have better luck.
Now, another option might be to move your processing logic into a different method so that the “physical” mechanics of the dialog calls are segregated.
@Django I’m not sure I understand the first part of your reply. As far as separating the dialogue calls into separate methods, I’ve tried that and it didn’t make a difference.
You have access to large portions of the Acumatica source code and if you have a text editor (or alternative tool like grep) that allows you to search for text within multiple folders and sub-folders you can search through the code base to see how the Acumatica programmers implement their logic. I was hoping to find somewhere in the code where a routine or process had two calls to .Ask/AskExt that you could look at and see how they handled that. My concern was that there might not be any code that makes two calls to .Ask/AskExt because it doesn’t work like that.
You mentioned trying to set the didWriteToTrace as a variable at the graph level - did you try making it Static?
The other thing I was thinking you might do was to use the Warning tab/button on the processing screen instead of using the Trace. Then you don’t have to worry about directing the user to look at the Trace because it will be right there on the screen.
@MichaelShirk when you raise 2 dialogs in the same action, your action is actually called 3 times.
1 - throw Exception to draw pre-processing popup
2 - resume the work with the value received from the user, execute processing, then
throw Exception to draw post-processing popup
3 - finish the work with the value received from the user
The problem is - when your method is called for the third time, pre-processing Ask already forgot the answer from the user, so from its standpoint, it needs to draw popup to receive user’s decision, returning you to the point 1.
You can try to return custom message at the end of your PXLongOperation instead of smart panel:
PXLongOperation.StartOperation(this, () => { // your processing code
if(graphExt.UpdatePILinesWithZohoCount(graph, currentHeader, zohoCount)) throw new PXOperationCompletedWithWarningException(ExtraItemCounted); });
There are multiple exception you can use, pick one that suits you best:
throw new PXOperationCompletedException(ExtraItemCounted); throw new PXOperationCompletedSingleErrorException(ExtraItemCounted); throw new PXOperationCompletedWithErrorException(ExtraItemCounted); throw new PXOperationCompletedWithWarningException(ExtraItemCounted);
I was hoping to find somewhere in the code where a routine or process had two calls to .Ask/AskExt that you could look at and see how they handled that.
Oh, yeah I use DnSpy to review source code. I just wasn’t sure what it was you were searching for, but this makes sense.
@andriitkachenko You’re my hero!! This is exactly what I needed.