go to post Jochen Roese · Mar 20, 2023 The <DIRECTORY> error means that the directory or file couldn't be found. Make sure IRIS has access to this file.
go to post Jochen Roese · Aug 3, 2020 I'm not sure if I'm correct here but I think you can eliminate 2 for-loops and the call to getArticle(): In SD031 there should be only one key for "x" (should be a 1:1 relationship), also try to avoid setting up a list just to .count() to see if "dataExists". You should use something like $data (in ^SB02906 there could be one dataset for every item you sale, for every customer). That should speed everything up a little. My approach: set a = $order(^SD031S("0","7",x,a)) if (a '="") { set b = $order(^SD031S("0","7",x,a,b)) if (b '= "") { if ($piece($get(^SD031("0",a,b,1)),Y,9) = x) { set c = a set d = "" for { set d = $order(^FA060S("0","22",c,b,c,d)) if (d = "") { quit } if ($piece($get(^FA060("0",c,d,2),""),Y,25) = b) { #dim innerObject = ##class(%ZEN.proxyObject).%New() set innerObject.d = d set innerObject.c = c set k = $o(^SB02906("0",c,d,"")) if (k'="") { set innerObject.dataExist = ($d(^SB02906("0",c,d,k,"EUR","0","1"))'=0) } else { set innerObject.dataExist = 0 } do responseList.Insert(innerObject) } } } } } Also that caching problem should not exist in production because FA060 and SD031 are read for almost everything in your ERP so it stays in the cache. Otherwise you probably need to create a background-job that reads a few global-nodes every 5-10 minutes to get it cached.
go to post Jochen Roese · Aug 28, 2019 I reinstalled my machine. Somehow Windows Updates didn't installed as well before. I wish I could check these Kaspersky-Logs, but now it's too late. Maybe it's really something that they prevented. Nevertheless our group-policy should've uninstalled it months ago. Didn't work either. So a clean install of Windows 10 was a good solution here.
go to post Jochen Roese · Aug 27, 2019 I already saw that post. I should've scrolled further. There was a msiexec.exe But now I have the "Cache initialisation finished-problem"Edit on post coming as soon as I have the error.
go to post Jochen Roese · Mar 8, 2019 Would be nice to have it. $$$TOE(sc, method()) gives a warning "Consider inlining/replacing this macro to make the code more readable".It is more readable but I want to use the macro: set sc = method() if ('sc) { throw ##class(%Exception.StatusException).CreateFromStatus(sc) } It's just a rule to eliminate macros in my opinion :/ Other example: Method has too many lines (93 > 50). Am I not allowed to write methods bigger 50 lines? Method declares too many variables? Also a rule I can't understand. Sure you need to minimize but it's not always possible. I really like sonarlint but I can't use it at 100% because I can't disable specific rules in specific circumstances,
go to post Jochen Roese · Mar 8, 2019 I think that should work much better. Didn't test but that is how I would do it with CSP-Method #call / #serverIt's also asynch so you browser still reacts while getting the data. I'm using innerHTML instead of the table-functions. innerHTML is the fastest way to render HTML actually. It's faster than jQueries $('query').html('htmlcontent'); <!--Demo of (re-)loading a table dynamically in a page--> <html> <head> <title> Cache Server Page To Demo Table Re-Render</title> </head> <body> <table id="TEST" border="1"> <thead> <tr> <td>SSN</td><td>Name</td> </tr> </thead> <tbody id="tablebody"> </tbody> </table> <hr> <!-- changed to call bc asynchronous --> <input type="Button" name="render" value="Create Table" OnClick="#call(..renderTable())#;"> <script language = Cache method = renderTable arguments = ""> #dim data = [] #dim sql = "SELECT SSN,Name FROM Sample.Person" #dim rset AS %SQL.StatmentResult = ##class(%SQL.Statement).%ExecDirect(, sql) while (rset.%Next()) { d data.%Push({ "SSN": (rset.%GetData(1)), "Name": (rset.%GetData(2)) }); } // create callback-function for rendering &js< function cb(data) { var tableBody = document.getElementById("tablebody"); // clear tablebody var html = []; tableBody.innerHTML = html.join(''); for (var i in data) { html.push('<tr><td>'+data[i].SNN+'</td><td>'+data[i].Name+'</td></tr>'); } // innerHTML is way faster than using the functions from table or creating javascript objects like HTMLTableRow or innerText tableBody.innerHTML = html.join(''); }; > // calling the cb with data w !,"cb("_data.%ToJSON()_")" </script> </body> </html>
go to post Jochen Roese · Mar 5, 2019 Any way to suppress warnings without sonarQube?//@SupressWarnings("cachequality:OS0001")//@SupressWarnings("all")or //NOSONARis not working
go to post Jochen Roese · May 4, 2018 Hi, this should give you an idea on how to achieve "popups" in HTML. This code is untested but it should give you a start.First of all you need 2 containers (DIV) at the end of your document: <div id="backdrop" class="backdrop"></div> <div id="popup" class="popup"> <div id="popup_container"></div> <button id="popup_btn1"></button> <button id="popup_btn2"></button> </div> in css you need 4 classes: .backdrop { position: fixed; opacity: 0.3; background-color: rgb(0,0,0); top: 0; left: 0; width:100%; height: 100% display: none; } .backdrop.active { display: block; } .popup.active { display:block; } .popup { display:none; <!-- add your styling here --> } In Javascript you need something like this: function showConfirm(message, callback) { showPopup(message, "Yes", "No", callback); } function showPopup(content, button1desc, button2desc, callback) { $('#popup').addClass("active"); $('#backdrop').addClass("active"); $('#popup_container').html(content); $('#popup_btn1').html(button1desc); if (button2desc) { $('#popup_btn2').html(button2desc).show(); } else { //If we don't get a 2nd description it's a alert-message with one button $('#popup_btn2').hide(); } $('#popup_btn1').off().on('click', function() { disable(); //First disable our popup if (callback) callback(0); //Returns the index of the button clicked }); $('#popup_btn2').off().on('click', function() { disable(); if (callback) callback(1); }); var disable = function() { $('#popup').removeClass("active"); $('#backdrop').removeClass("active"); $('#popup_container').html(''); } } //Example of calling the confirm-message showConfirm("Do you really want to delete?", function(choice) { if (choice===0) alert("You pressed yes"); } else { alert("You pressed no"); } }); Edit: You can achieve this also by using native-javascript: document.getElementById("popup_container").innerHTML = content; for example
go to post Jochen Roese · Feb 28, 2018 Hei, if you want to use Darkest-Dark theme: Go to <eclipse-workspace>/.metadata/.plugin/org.eclipse.core.runtime/.settings/com.intersys.eclipse.studio.ui.prefs and add this. I didn't found all colors but It's a good start. Edit theme in preferences if you find a color that you don't like or maybe isn't set by me. You can also reset to default-settings by removing every Studio_Color-Setting. I also tweaked the colors for specific things because using the theme strictly results in too much blue ($-commands was blue etc.) Studio_Color_BG_false=0,0,0 Studio_Color_BG_true=37,37,37 Studio_Color_brace=255,255,255 Studio_Color_bracket=255,255,255 Studio_Color_classmethodname=189,214,255 Studio_Color_classname=210,81,81 Studio_Color_collationname=189,214,255 Studio_Color_cosBitlogicOperator=210,81,81 Studio_Color_cosClassName=239,191,143 Studio_Color_cosCommandWordDeprecated=210,81,81 Studio_Color_cosCommandword=210,81,81 Studio_Color_cosDollarName=210,81,81 Studio_Color_cosDollarNameDeprecated=210,81,81 Studio_Color_cosEmbedDelim=0,128,0 Studio_Color_cosEmbeddingStartOrEnd=210,81,81 Studio_Color_cosExtrinsic=210,81,81 Studio_Color_cosGlobalname=141,203,226 Studio_Color_cosGlobalname_bold=true Studio_Color_cosIOFormat=255,255,255 Studio_Color_cosJsonBrace=255,255,255 Studio_Color_cosJsonBracket=255,255,255 Studio_Color_cosJsonKeyword=210,81,81 Studio_Color_cosKeyword=210,81,81 Studio_Color_cosLabel=210,81,81 Studio_Color_cosLabelname=141,203,226 Studio_Color_cosLocalname=136,214,255 Studio_Color_cosMacroArgsAnything=136,214,255 Studio_Color_cosMacroCall=210,81,81 Studio_Color_cosOperator=255,255,255 Studio_Color_cosPPCommand=141,203,226 Studio_Color_cosPPFunc=210,81,81 Studio_Color_cosPattern=210,81,81 Studio_Color_cosSQLFieldName=210,81,81 Studio_Color_cosstring=255,198,0 Studio_Color_csqlIdentifier=255,198,0 Studio_Color_delim=255,255,255 Studio_Color_foreignkeyname=121,171,255 Studio_Color_htmlAttributeName=121,171,255 Studio_Color_htmlAttributeValue=255,255,255 Studio_Color_indexname=189,214,255 Studio_Color_indexpropertyname=255,255,255 Studio_Color_jsKeyword=141,203,226 Studio_Color_jsOperator=255,255,255 Studio_Color_jsString=255,198,0 Studio_Color_jsonString=255,198,0 Studio_Color_methodname=255,255,255 Studio_Color_name=255,255,255 Studio_Color_number=129,180,71 Studio_Color_parameter=121,171,255 Studio_Color_parametername=189,214,255 Studio_Color_paren=255,255,255 Studio_Color_propertyname=189,214,255 Studio_Color_queryname=189,214,255 Studio_Color_sqlstring=255,255,128 Studio_Color_storagename=189,214,255 Studio_Color_triggername=189,214,255 Studio_Color_udlDocComment=201,222,12 Studio_Color_udlKeyword=80,175,226 Studio_Color_udlMCKeywordName=255,255,255 Studio_Color_udlMCKeywordValue=129,180,71 Studio_Color_udlNumericLiteral=129,180,71 Studio_Color_udlStringLiteral=255,198,0 Studio_Color_xdataname=189,214,255 Studio_Color_xmlAttributeName=255,255,255
go to post Jochen Roese · Nov 9, 2017 That's not garbage. It's the ZIP-File itself I think. It's in binary and compressed. You need to decompress it. I would do it like that:s sc=$zf(-1, "sftp command here &>/dev/null; unzip cmd here &>/dev/null")
go to post Jochen Roese · Aug 25, 2016 I prefer REST. The built-in transportation is good way for ZEN but the fact that the most plugins can't handle it well is a good reason to use REST. Some plugins just want an URL to do a simple jQuery-AJAX-Call and parsing that into a callback function. I some cases you can submit a function serving the data instead of an URL but working that around that is a bit harsh and not really comfortable in my opinion (Typeahead for example). Let's assume that you code a ZEN-App working with Cordova and in the Browser as well. The data comes from the built-in feature of ZEN-Mojo. Everything works fine. Now a new iOS or Android-Update is distributed that have new security guidelines and Cordova dies out of it (maybe some stuff in the webview are not allowed anymore but is needed). That's why I keep my data-transportation as flexible as possible. Always thinking of "This 3rd party tool is maybe not supported anymore in the future. What are my alternatives?". In this case a native app without ZEN. You can still use the built-in feature by calling the methods that the REST calls. You are in the CSP-Enviroment in both cases.
go to post Jochen Roese · Jun 2, 2016 We are using Hashtags to load the templates. Thats the URL for example:www(.)mypage.com/myzenapp/mojoclass.cls#Login?r=Dashboardorwww(.)mypage.com/myzenapp/mojoclass.cls#Dashboardorwww(.)mypage.com/myzenapp/mojoclass.clsOur custom-script CAJAXNavigation uses onHashChange-Callback (that we bound to zenPage.onHashChanged). There we change the layout with pop and push document. This works very well with the browser history stack. The browser manages hashtag-changes automatically.With this concept we are changing the layout by simply clicking an anchor with href="#MyLayout" <mojo:documentView id="mainView"ongetdata="return zenPage.getContent('data',key,criteria);"ongetlayout="return zenPage.getContent('layout',key,criteria);"developerMode="false"effectsEnabled="false"maxPanels="2"onload="zen('mainView').setDocumentKey(CAJAXNavigation.GetInstance().GetCurrentPage() || 'Home');zen('mainView').setLayoutKey(CAJAXNavigation.GetInstance().GetCurrentPage() || 'Home')">
go to post Jochen Roese · May 27, 2016 Hi Fabio, in template dispatch mode you can have a super layout class where you can have a collection of clientmethods implemented in every layout extending from it. Our menu is initialized by every layout each time it loads. You can define a method that initialize the menuitems as active for example or load dynamic data.I'm sure that there is a better way of handling menus with onepage-concepts. Menus in general are difficult in client oriented template systems.We implemented a way to display two layouts in a single pane; a detail part in a modal for example. I think this technique can be used to display a dynamic-menu. Just create a menu-layout that just provide the layout by criteria-parameters. In your superclass add a method that calls this layout and injects it into a div provided by every layout. Example:Content-Layout:var that = this;return {...,children:[{type:'$div',id:'menu'}], $executeCodeAfterChildren: function() { that.initMenu({"parm":"value"}) }}Super-Layout:ClientMethod initMenu(view, criteria) [ language = "javascript] { var layout = zenPage.getContent("layout","Menu",criteria) view = view || zen('mainView'); var menucontainer = view.getComponentById("menu"); ***** //Empty all children-elements first before refresh and add the layout menucontainer.$children = menucontainer.children = layout.children; //rerenders menu menucontainer.$refresh();}***** I added following code in createLayoutObjects before return in bootstrap-plugin to get layout-elements by id instead of index: var mainView = instance.$documentView; //zen('mainView');if (typeof mainView._IDIndex === "undefined") {mainView._IDIndex = [];}if (instance && instance.id) {mainView._IDIndex[instance.id]=instance;}if (!mainView.getComponentById) {mainView.getComponentById = function(id) {return this._IDIndex[id] || null;}}
go to post Jochen Roese · Apr 29, 2016 Can you post the original SQL? Maybe I can find some joins that missbehaviours. In some cases a select to a specific field in joins let the query-optimizer run the false index. My experience is that the query-opt. somehow decides to use the extend-index instead of an property-index.
go to post Jochen Roese · Apr 21, 2016 Ahhh. That's why I never changed a namespace with $namespace. I always used ZNDoes it revert the namespace after the method finished?
go to post Jochen Roese · Apr 21, 2016 It's to change the namespace later back to the namespace you're comming from.ClassMethod DoIt() As %Status{ //Current Namespace = "A" Do ..MethodThatChangesNamespace() //Namespace is now "B" Do ##class(Class).AnotherMethod() //Results in "NOT FOUND"} Edit: I don't know if "new $namespace" results in changing back the namespace. I got some problems changing namespaces in methods. Maybe it's changed since Version 2008.
go to post Jochen Roese · Apr 21, 2016 Here is an example how you should code in ObjectScript: ClassMethod listClasses(ns As %String = {$namespace}, projectName As %String) As %Status{ #dim tSC As %Status = $$$OK #dim tException As %Exception.StatusException = $$$NULLOREF #dim tOrigNS = $namespace try { // Switch namespaces to the new one set $namespace = ns // Grab our project, by name; fail otherwise // TODO: failing is CRUDE at this point... #dim project as %Studio.Project #dim status as %Status // TODO: note sure what the "concurrency" parameter is; leave the default which is -1 set project = ##class(%Studio.Project).%OpenId(projectName,, .status) if ($$$ISERR(status)) { Throw ##class(%Exception.StatusException).CreateFromStatus(status) } #dim item as %Studio.ProjectItem #dim key = "" while (project.Items.GetNext(key)'="") { set key = project.Items.GetNext(key) set item = project.Items.GetAt(key) if ($IsObject(item)) { write "Name: " _ item.Name _ ", type: " _ item.Type, ! } } } catch (tException) { Set tSC = tException.AsStatus() } set $namespace = tOrigNS quit tSC}
go to post Jochen Roese · Apr 15, 2016 Hi,you need to re-render all components of header and footer on each layout-change. But there is a way to initialize the header and footer once and outside of the zen-pane.In your zenPage create a ClientMethod that pushes html-code outside of the panes:ClientMethod InitHeader(force) [ language = javascript ]{ if (force || !zenPage._zHeaderInit) { var head_html = []; var footer_html = []; head_html.push('<div id="header">'); head_html.push('...things...') head_html.push('</div>'); footer_html.push('<div id="header">...things...</div>') $('#zen1').html(head_html.join('') + $('#zen1').html() + footer_html.join('')); //init client-code here like onclick $('#header').find('a').each(function() { $(this).on('click',function() { //I clicked a emnu-item }) }); zenPage._zHeaderInit = true; }}In $executeCodeAfterChildren in getLayout() you can execute zenPage.InitHeader()
go to post Jochen Roese · Mar 23, 2016 Hi Daniel,use bootstrap and javascript. There are a lot of frameworks out there. You can use ZEN-Mojo as framework for example. I wouldn't try to work with angular.js because it's more expert-level Javascript and templating. But when you do it correctly it could be the best option out there.Responsive apps need a lot of CSS and Javascript-Knowledge. Bootstrap gives you an idea and a good basic on how to achieve that. Maybe it's enough to redesign your old CSP-Pages to bootstrap to make it responsive enough.The easiest way to work with an REST-API is jQuery-ajax (for http-requests in general)I also use a Java-Class like structure for my scripts. Here is an example:function MyClass(initParm, initListener) { var m_PrivateProperty = initParm || null; var m_EventListener = (typeof initListener === "function" ? initListener : new MyClass.OnEventListener()) this.PublicProperty = "Hello World"; this.getOnEventListener = function() { return m_EventListener; } this.setOnEventListener = function(EventListener) { m_EventListener = EventListener; } var privateFunc = function(parms) { return stuff; } this.publicFunction = function(parms) { return privateFunc(stuff) } this.getPrivateProperty = function() { return m_PrivateProperty; } this.setPrivateProperty = function(PrivateProperty) { m_PrivateProperty; } this.sendToServer = function() { var that = this; jQuery.ajax("/rest/do/things/", { method : "GET", asynch : true, data : { parm1 : this.getPrivateProperty() } }).done(function(a,b,c) { //we need "that" here. "this" is not MyClass anymore; could be jqXHR-Object or window that.getOnEventListener().OnThingsListener(a); }).error(function(a,b,c) { //read jquery-doc }) } }MyClass.OnEventListener = function() { this.OnClickListener = function(parms) { }; this.OnThingsListener = function(parms) { };} var a = new MyClass(parm1,parm2)