go to post Eduard Lebedyuk · Sep 19, 2016 IF we use cookies, they will be stored in the Session Cookie Path.Cookie has a property named path. Whed browser determines, does the cookie apply to a current page, it checks if the cookie path is less or equal to current URL.I'm thinking that this login cookie would be used somehow if the Login Cookie is selected? Or not used? It would be used, if checked.what does happen if the Login Cookie is selected in the web application?Login Cookies hold information about the most recently logged-in user. If you want to keep your users from having to log in too often, but you want your applications to remain distinct and unconnected, use Login Cookies. For Login Cookies, place each application in a separate session. Then authentication is shared only when an application is entered for the first time. Login Cookies applications do not form a group. So after login, changes in authentication in one application do not affect the other applications. Documentation.What could we store in a cookie? Can we possibly find out if a second tab has been opened by using a cookie?You can store text values in cookie. I suggest you read wiki article on them.
go to post Eduard Lebedyuk · Sep 12, 2016 Here are some thoughts:Write Source Control Hook that implemets OnAfterSave method and checks there (or maybe some other entry point). There are several sample source control hook classes, check them out.Use ^rINDEXCLASS global (key - class name in uppercase) - it contains some basic information such as modification time (1st position) and hash (13th position). You can monitor it and if time or hash changes then record the new class version.Use lock table to see what classes are currently being editedUse $$$defClassKeyGet macros (see %Dictionary.ClassDefinition/%Dictionary.CompiledClass definitions, they use these macros a lot) to get info about modification time/hash and the changes themselves%Compiler.UDL.TextServices to get the class textI would have done it like this:Background process monitors ^rINDEXCLASS globalUpon finding changes get the current class code via %Compiler.UDL.TextServices class, GetTextAsStream methodWrite this information into your own class (classname, timestamp, user, classtext, diff, previousversion)Modification of system classes is not a very good idea:They are lost on updateUser may not have access required to install these changesThat being said, the best solution in my opinion is to setup your critical/production systems in such a way, that developers do not have direct write access to them. Each of the developers have their own environment where they can do whatever and then commit it to source control system. Continuous integration solution (or one developer or a script) then uploads the code (after it passes the tests) to the production server. There are several source control/continuous integration systems available for Caché.It is a good idea that a change can only be done via source control commit. All other changes simply should not exist.
go to post Eduard Lebedyuk · Sep 6, 2016 There is a beforeunload HTTP event which is fired when the window, the document and its resources are about to be unloaded. Handle this event in your js code and from there you can send an HTTP request to a server (I usually use GET /webapp/logout), which would do something like this: ClassMethod logout() As %Status { #dim %session As %CSP.Session set st = %session.Logout(1) set %session.EndSession = 1 return st }
go to post Eduard Lebedyuk · Aug 31, 2016 I'd also love to see the web application's properties programmatically, if possible (such as the physical files path).Use Security.Application class directly, or preferably via %Installer manifest.but I honestly don't know why it's choosing that web application over the default of /csp/default-namespaceUncompile and compile ZEN classes after setting default web application. Or you can try to set HOMEPAGE parameter in the application class.My question is, if we go to using Group By ID (which is currently null) in the web application, will this fix the sharing of %session Data? (This is why I have to make sure I'm editing the correct web application!)If the user opens one web application in two tabs, they would be sharing a session (and namespace). Group By ID would only help if you have N different applications and would specify N different values for Group By ID property. In that case, they should use N different sessions.Finally, we have a web application for each namespace; will we need the Group By ID for each application defined for each namespace, and should it be the same ID?Depends, if you want to share %session or not.
go to post Eduard Lebedyuk · Aug 10, 2016 Then you need to specify MODE attribute as LOGICAL for that cspbind property. Documentation.
go to post Eduard Lebedyuk · Aug 10, 2016 Sure, execute this in a terminal to open a new terminal for an instance named cache: do $zf(-2,"cterm.exe /console=cn_ap:cache") $ZF(-2) docs, cterm docs.
go to post Eduard Lebedyuk · Aug 4, 2016 Simpliest way: Cache executes an operating system command via $zf(-1) function.Alternatively, you can load a dll with $zf(-4) (also 3, 5) functions.There is also CNA project - it provides an interface for using native C-compatible shared libraries without anything but Caché ObjectScript code. CNA is a wrapper for libffi. CNA consists of native library (libcna) and Caché class (CNA.CNA). It is a wrapper around $zf functions.That said, the most effective would be some kind of a library load with library written in either C or generated from some computational language. For example Mathlab can generate C code, which can be then compiled into a library.
go to post Eduard Lebedyuk · Aug 4, 2016 Something like this? I had a similar problem, but the check was required only for part of the properties. If you want all of them, remove the line with continue. Method IsEmpty() As %Boolean [ CodeMode = objectgenerator ] { For i = 1:1:%class.Properties.Count() { Set Prop = %class.Properties.GetAt(i) CONTINUE:(Prop.Internal || Prop.Calculated || Prop.ReadOnly || Prop.Private || Prop.Identity) Do %code.WriteLine(" Quit:.." _ Prop.Name _ "'="""" $$$NO") } Do %code.WriteLine(" Quit $$$YES") }
go to post Eduard Lebedyuk · Aug 3, 2016 Inherit from EnsPortal.MessageViewer Copy searchPane from EnsPortal.Template.filteredViewer In searchPane, TimeFormat node replace attribute value="12" with value="999" Compile. Your new class would have Complete as TimeFormat default value Alternatively, instead of 2-4 you can set TimeFormat value in your class by overriding some init callback ( %OnAfterCreatePage maybe, don't forget to call ##super() though) and setting it there. It would be a better solution. 2020 UPDATE. I think I found a better solution. 1. Extend EnsPortal.MsgFilter.Assistant class. 2. In this class redefine EnumerateExecute method to provide the desired format. Replace this line: Do ..addTerm(.aSelect,"{fn RIGHT(%EXTERNAL(head.TimeCreated),"_dateLen_" )} As TimeCreated") to provide the format you need. Alternatively redefine OnFinalizeSQL to replace {fn RIGHT(%EXTERNAL(head.TimeCreated),999)} with something else. 3. Set the global ^EnsPortal.Settings("MessageViewer","AssistantClass") to the value of your class. This looks like an official way to modify MessageViewer behavior.
go to post Eduard Lebedyuk · Aug 3, 2016 Sorry, I forgot that SYS.Database is deployed. You'll need to match $zu(49) to properties manually. But the macros usually have the same name. For example field 14 is sfnpiece macro ("piece" part of the name is irrelevant, so just sfn it is) and it corresponds to SFN property in SYS.Database. To test, you can write the following method: ClassMethod Test( Directory ) { Set db=##Class(SYS.Database).%OpenId(Directory) Write db.SFN = $p($zu(49),",",$$$sfnpiece) //14th piece // More checks }
go to post Eduard Lebedyuk · Jul 26, 2016 I imported your example, executed: Do ##class(Wendy.LTCodes).SetData() Then executed this sql: SELECT ID, Code, Description, Invalid FROM Wendy.LTCodes and received the following results: IDCodeDescription InvalidN001N001ANYOLD DESC1N002N002C5 REPEAT 1 N111N111SPECIMEN COMMENT N200N200MSUD SCREEN N500N500Sickle Cell Screen seems to be working. But then I didn't really understand the use of Parameter InvalidGLVN = "^Utils.GlobalPropP"; it's for use with indirection. Example: set ^Utils.GlobalPropP = 123 set glvn = "^Utils.GlobalPropP" write glvn > ^Utils.GlobalPropP write @glvn > 123
go to post Eduard Lebedyuk · Jul 26, 2016 Your error: <INVALID 0REF>zSrvGetData+2 Points to the line; set item = ..%GetComponentById("Item").value And means that the result of this call: ..%GetComponentById("Item") Is not an object, so you can't access a property "value".
go to post Eduard Lebedyuk · Jul 25, 2016 Why not use %Stream.FileBinary and %Stream.FileCharacter? It would store the file outside of the database.
go to post Eduard Lebedyuk · Jul 23, 2016 If our SVN repository already is storing discrete .cls files, does Atelier do any conversion when we load from SVN into our server instance?No, except maybe for repository structure. That depends is Atelier + EGit support repository structure you use. For how to use EGit with Atelier check this article.At what point would I see .udl files? I am thinking I would only see that if SVN was storing .xml and each of those would be converted to .udl.There are no .udl files. There are just cls/mac/inc etc files in udl format, meaning they are represented on disk as is and not in the xml format. The extension would be .cls and so on. Here's the sample repository created with Atelier.
go to post Eduard Lebedyuk · Jul 22, 2016 Here's the documentation detailing the process.Or do you have more specific questions?
go to post Eduard Lebedyuk · Jul 12, 2016 %Label is the way to go. Its fifth argument is a CSS applied to a cell. So the following MDX: SELECT NON EMPTY %LABEL([Measures].[%COUNT],,,,"width:100%") ON 1 FROM [HOLEFOODS] Would be displayed like this in analyzer: And its sixth argument is a CSS applied to the cell header: SELECT NON EMPTY %LABEL([Measures].[%COUNT],,,,,"width:80%") ON 1 FROM [HOLEFOODS] Alternatively you can use DeepSeeWeb to display dashboards with pivots. In there cells width can be easily modified.
go to post Eduard Lebedyuk · Jun 21, 2016 You can close the cursor and open it again: ClassMethod Test() { &sql( DECLARE C1 CURSOR FOR SELECT TOP 10 ID INTO :id FROM Sample.Person ) &sql(OPEN C1) &sql(FETCH C1) Set first = $$$YES While (SQLCODE = 0) { Write id,! &sql(FETCH C1) If id=9 && first { Set first = $$$NO &sql(CLOSE C1) &sql(OPEN C1) &sql(FETCH C1) } } &sql(CLOSE C1) }