I am trying to open window in new browser tab in Acumatica.
It worked few versions ago, but now if i am trying to open window in new tab it don't.
I am using following code:
public PXAction<ARInvoice> ViewRevBatch;
[PXButton]
protected virtual void viewRevBatch()
{
if (ConnectedBatches.Current != null)
{
Batch batch = ConnectedBatches.Current;
JournalEntry journalentrygraph = PXGraph.CreateInstance<JournalEntry>();
journalentrygraph.BatchModule.Current = batch;
throw new PXRedirectRequiredException(journalentrygraph, true, "Journal Entry");
}
}
throw new PXRedirectRequiredException(journalentrygraph, false, "Journal Entry") { Mode = PXBaseRedirectException.WindowMode.New };
Related
I am trying to select "OK" button against my browser certificate pop-up using robot class. The same piece of code works well on windows but failing on ubuntu.
Code:
public void load() {
setUrl();
Thread threadNavigation = new Thread() {
#Override
public void run() {
driver.navigate().to(url);
}
};
Thread threadCertificateHandler = new Thread() {
#Override
public void run() {
try {
Thread.sleep(3000);
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.delay(2000);
robot.keyRelease(KeyEvent.VK_ENTER);
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
};
// Start the threads.
threadNavigation.start();
threadCertificateHandler.start();
// Wait for them both to finish
try {
threadNavigation.join();
threadCertificateHandler.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Code Explanation:
As soon as url is navigated using selenium, a certificate pop-up is displayed before page is loaded.
The approach I have used here - 1 thread used here to get application url and another thread is used to handle the pop-up.
Attaching screenshot of the pop-up.
Chromedriver Code:
public void getStandaloneHubNodeServerDriver(String browserType,String platformType, String url) throws MalformedURLException {
DesiredCapabilities caps = new DesiredCapabilities();
logger.log(Level.INFO, () -> "Setting browser address #: " + url);
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized"); // open Browser in maximized mode
options.addArguments("disable-infobars"); // disabling infobars
options.addArguments("--disable-extensions"); // disabling extensions
options.addArguments("--disable-dev-shm-usage"); // overcome limited resource problems
options.addArguments("--no-sandbox"); // Bypass OS security model
options.setAcceptInsecureCerts(true);
options.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.ACCEPT);
options.setExperimentalOption("excludeSwitches",Arrays.asList("disable-popup-blocking"));
//threadLocalDriver.set(new RemoteWebDriver(new URL(url),options));
driver = new RemoteWebDriver(new URL(url),options);
driver.manage().window().maximize();
}
Chrome Image Used:
docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.8.0-20230123
I am trying to add a new record to a grid during the persist logic. However, even though the record does get added to the grid in the UI, when the page gets refreshed, the new line disappears. It is not getting persisted in the DB.
I am using the Bills page as reference.
Code sample
protected virtual void APTran_RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
if (e.Row == null)
{
return;
}
APInvoice invoiceRow = this.Base.Document.Current;
if (invoiceRow != null)
{
APTran tranRow = new APTran();
tranRow = this.Base.Transactions.Insert(tranRow);
tranRow.InventoryID = 10043;
this.Base.Transactions.Update(tranRow);
tranRow.Qty = 3;
this.Base.Transactions.Update(tranRow);
}
}
Result after saving - Record is shown in the grid:
Result after cancelling - Record disappears from the grid:
Something like this I tend to override the Persist method and insert or update related records before calling base persist. Here is a possible example which goes inside your graph extension:
[PXOverride]
public virtual void Persist(Action del)
{
foreach(APInvoice invoiceRow in Base.Document.Cache.Inserted)
{
APTran tranRow = this.Base.Transactions.Insert();
tranRow.InventoryID = 10043;
tranRow = this.Base.Transactions.Update(tranRow);
tranRow.Qty = 3;
this.Base.Transactions.Update(tranRow);
}
del?.Invoke();
}
I have a completely custom screen with its own BLC and DACs, and I want to open it as a popup from a button placed on the Bills and Adjustments screen. I have coded it as follows:
public class APInvoiceEntryExt : PXGraphExtension<APInvoiceEntry>
{
public PXAction<APInvoice> LaunchOpenSource;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Open Source")]
protected void launchOpenSource()
{
APInvoice apinvoice = (APInvoice)Base.Document.Current;
if (apinvoice != null)
{
//var url = "http://localhost/AcumaticaDB2562/?ScreenId=AC302000&OpenSourceName=Bills+and+Adjustments&DataID=" + apinvoice.RefNbr;
OpenSourceDataMaint graph = PXGraph.CreateInstance<OpenSourceDataMaint>();
graph.OpenSourceDataHeader.Current = graph.OpenSourceDataHeader.Search<xTACOpenSourceHeader.openSourceName, xTACOpenSourceHeader.dataID>("Bills and Adjustments", apinvoice.RefNbr);
if (graph.OpenSourceDataHeader.Current != null)
{
throw new PXRedirectRequiredException(graph, "Open Source")
{
Mode = PXBaseRedirectException.WindowMode.NewWindow
};
}
}
}
}
I've included all the relevant DACs and BLC for my custom screen in the Class Library project I'm using to customize the 'Bills and Adjustments' screen where I'm adding the button.
The problem I'm having is that I get the following error message when launching the button:
I've set all the relevant permissions for the screen that uses the OpenSourceDataMaint BLC to 'Delete' in 'Access Right By Role', 'Access Rights By User', and 'Access Rights By Screen'. Nothing makes any difference.
Looks like DataSource is trying to find a node in SiteMap with GraphType equal to full name off your OpenSourceDataMaint class and fails:
public class PXBaseDataSource : DataSourceControl, IAttributeAccessor, INamingContainer, ICompositeControlDesignerAccessor, ICommandSource, IPXCallbackHandler, IPXScriptControl, IPXCallbackUpdatable, IPostBackDataHandler
{
...
private static string getFormUrl(Type graphType)
{
PXSiteMapNode node = getSiteMapNode(graphType);
if (node == null)
{
throw new PXException(string.Format(ErrorMessages.GetLocal(ErrorMessages.NotEnoughRightsToAccessObject), graphType.Name));
}
String url = node.Url;
//if (url.Contains("unum=")) url = PXUrl.IgnoreQueryParameter(url, "unum");
return PXUrl.TrimUrl(url);
}
...
}
Could you please check if TypeName is properly defined for PXDataSource inside your custom Aspx page? Also could you please check if your custom Aspx page also exists in Cst_Published folder and if values set for PXDataSource.TypeName property are identical inside Pages and Cst_Published folders?
One more thing to check, does the Site Map screen show the right GraphName for your custom screen? - would be beneficial if you can provide a screenshot for verification.
If possible, please provide your customization package, that can be published locally (even with compiled assembly) - this would greatly speed up the investigation process.
The solution, for me, was to put the code (shown below) in a customization window instead of a class library project in Visual Studio. Since the code needs to have a reference to another published customization, putting it inside an Acumatica code window takes care of this. There is no reference to the published custom screen customization in my class library project, and this obviously causes issues - and I'm not sure how to handle that.
public class APInvoiceEntryExt:PXGraphExtension<APInvoiceEntry>
{
public PXAction<APInvoice> LaunchOpenSource;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Open Source")]
protected void launchOpenSource()
{
APInvoice apinvoice = (APInvoice)Base.Document.Current;
if (apinvoice != null)
{
AssistantController.OpenSourceDataMaint graph = PXGraph.CreateInstance<AssistantController.OpenSourceDataMaint>();
graph.OpenSourceDataHeader.Current = graph.OpenSourceDataHeader.Search<AssistantController.xTACOpenSourceHeader.openSourceName
,AssistantController.xTACOpenSourceHeader.dataID>("Bills and Adjustments", apinvoice.RefNbr);
throw new PXRedirectRequiredException(graph, "Open Source")
{
Mode = PXBaseRedirectException.WindowMode.NewWindow
};
}
}
}
my web application offers a download. Javascript creats at the click the url (it depends on the user input) and the browser should open it, so that the page isn't reloaded.
For that, I think I have to alternatives:
// Alt1:
window.open(pathToFile);
// Alt2:
var downloadFrame = document.getElementById('downloads');
if (downloadFrame === null) {
downloadFrame = document.createElement('iframe');
downloadFrame.id = 'downloads';
downloadFrame.style.display = 'none';
document.body.appendChild(downloadFrame);
}
downloadFrame.src = pathToFile;
Both works under Firefox. Problem with open new window method: If the creation of the file at the server needs more time, the new empty tab will be closed late.
Problem with iframe: If there is an error at the server, no feedback is given.
I think at firefox the iframe is the better solution. But the web application must run with an JavaFX WebView, too. JavaFX haven't a download feature, I have to write it. One possible way is to listen on the location property:
final WebView webView = new WebView();
webView.getEngine().locationProperty().addListener(new ChangeListener<String>() {
#Override public void changed(ObservableValue<? extends String> observableValue, String oldLoc, String newLoc) {
if (newLoc.cotains("/download")) {
FileChooser chooser = new FileChooser();
chooser.setTitle("Save " + newLoc);
File saveFile = chooser.showSaveDialog(webView.getEngine().getScene().getWindow());
if (saveFile != null) {
BufferedInputStream is = null;
BufferedOutputStream os = null;
try {
is = new BufferedInputStream(new URL(newLoc).openStream());
os = new BufferedOutputStream(new FileOutputStream(saveFile));
while ((readBytes = is.read()) != -1) {
os.write(b);
}
} finally {
try { if (is != null) is.close(); } catch (IOException e) {}
try { if (os != null) os.close(); } catch (IOException e) {}
}
}
}
}
}
There are some problems:
The download start depends on a part of the url, because JafaFX supports no access to the http headers (that is bearable)
If the user starts the download with the same url two times, only the first download works (the change event only fires, if the url is new). I can crate unique urls (with #1, #2 and so on at the end). But this is ugly.
Only the "window.open(pathToFile);" method works. Loading an iframe don't fire the change location event of the website. That is expectable but I haven't found the right Listener.
Can someone help me to solve 2. or 3.?
Thank you!
PS: Sorry for my bad english.
edit:
For 2. I found a way. I don't know if it is a good one, if it is performant, if the new webview is deleted or is in the cache after download, ....
And the user don't get an feedback, when some a problem is raised:
webView.getEngine().setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() {
#Override public WebEngine call(PopupFeatures config) {
final WebView downloader = new WebView();
downloader.getEngine().locationProperty().addListener(/* The Listener from above */);
return downloader.getEngine();
}
}
I think you may just need to use copyURLtoFile to get the file...call that when the location changes or just call that using a registered java class. Something like this:
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
Using copyURLToFile the current page doesn't have to serve the file. I think registering the class is probably the easiest way to go... something like this:
PHP Code:
Download $filename
Java (in-line class in your javafx class/window... in this case my javafx window is inside of a jframe):
public class JavaApp {
JFrame cloudFrameREF;
JavaApp(JFrame cloudFrameREF)
{
this.cloudFrameREF = cloudFrameREF;
}
public void getfile(String filename) {
String newLoc = "http://your_web_site.com/send_file.php?filename=" + filename;
org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename));
}
}
This part would go in the main javafx class:
Platform.runLater(new Runnable() {
#Override
public void run() {
browser2 = new WebView();
webEngine = browser2.getEngine();
appREF = new JavaApp(cloudFrame);
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<State>() {
#Override public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject win
= (JSObject) webEngine.executeScript("window");
// this next line registers the JavaApp class with the page... you can then call it from javascript using "app.method_name".
win.setMember("app", appREF);
}
}
});
You may not need the frame reference... I was hacking some of my own code to test this out and the ref was useful for other things...
I am using LWUIT 1.5 tabs to show notifications. I have three Tabs and I fetch notifications from a php web service. I successfully fetched list of notifications for first Tab. But for next two Tabs I am failing to understand what code I should write to
Detect that second/third Tab is clicked. I know how to add commandListener to a Button. What commandListener is there for Tab selection?
How to refresh content of a Tab when new data is received from the server?
private void showNotificationList() {
try {
Form f = new Form("Notifications");
f.setScrollable(false);
f.setLayout(new BorderLayout());
final List list = new List(getNotifications()); //gets hashtables - notices
list.setRenderer(new GenericListCellRenderer(createGenericRendererContainer(), createGenericRendererContainer()));
list.setSmoothScrolling(true);
//System.out.println("adding list component to listview");
list.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
int i = list.getSelectedIndex();
noticeDetailsForm(notices[i]);
//Dialog. show( "title", notices[i].toString(), "ok", "exitt");
}
});
//Container c2 = new Container(new BoxLayout(BoxLayout.Y_AXIS));
//c2.addComponent(list);
Tabs tabs = new Tabs(Tabs.TOP);
tabs.addTab("Recent", list);
tabs.addTab("Urgent", new Label("urgent goes here"));
tabs.addTab("Favourites", new Label("favs goes here"));
//f.addComponent(tabs);
f.addComponent(BorderLayout.CENTER, tabs);
Command backComm = new Command("Back") {
public void actionPerformed(ActionEvent ev) {
Dashboard.dbInstance.setUpDashboard();
}
};
f.addCommand(backComm);
//System.out.println("showing lsit form");
f.show();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private Container createGenericRendererContainer() throws IOException { //System.out.println("container called");
//System.out.println("container called");
Container c = new Container(new BorderLayout());
c.setUIID("ListRenderer");
Label xname = new Label("");
Label description = new Label();
Label focus = new Label("");
Container cnt = new Container(new BoxLayout(BoxLayout.Y_AXIS));
xname.setName("Name");
xname.getStyle().setBgTransparency(0);
xname.getStyle().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
//description.setFocusable(true);
description.setName("Description");
cnt.addComponent(xname);
cnt.addComponent(description);
c.addComponent(BorderLayout.CENTER, cnt);
Button thumb = new Button(Image.createImage("/res/home-work.png"));
//Image img = Image.createImage("/res/home-work.png");
c.addComponent(BorderLayout.WEST, thumb);
return c;
}
private Hashtable[] getNotifications() {
int total = notices.length;
//System.out.println(total);
Hashtable[] data = new Hashtable[total];
//Hashtable[] data = new Hashtable[5];
/data[0] = new Hashtable();
data[0].put("Name", "Shai");
data[0].put("Surname", "Almog");
data[0].put("Selected", Boolean.TRUE);/
for (int i = 0; i < total; i++) {
data[i] = new Hashtable();
//System.out.println(notices[i].getName());
data[i].put("Name", notices[i].getName());
data[i].put("Description", notices[i].getDescription());
data[i].put("Id", Integer.toString(notices[i].getId()));
}
return data;
}
1)I had the same problem and I solved it by overriding Keyreleased of the Form not the Tab
and inside it I check for the component that is focused and if it is the Tab get "tab.selectedIndex" to detect in which Tab I am and load appropriate data .
Here is Sample code(this inside the my derived form that extends Form )
**
public void keyReleased(int keyCode) {
Component p=this.getFocused();
String str= p.getClass().getName();
if(str.toLowerCase().indexOf("radiobutton")!=-1){ // Radiobutton because when u
Here do tab specific work focus on the
tab it returns radiobutton.
lwuit understands tabs as list
of radiobuttons
}**
2)and about refreshing the data I did a solution and I don't Know if its right
I get the new data , create new List and remove the old one and attach the new one then
call Form.repaint();