go to post Timothy Leavitt · Sep 1, 2016 You can change namespace in Caché ObjectScript with: Set $Namespace = "SomeOtherNamespace" In methods that do that, it's typically good to start out with: New $Namespace To ensure that the namespace switches back once it's out of that context. Of course, you need to be sure that any code you call is available in the new namespace, and it would be good to think carefully about security implications. The management portal uses the $NAMESPACE parameter in the URL along with %request.Context to add it to other URLs so you stay in the same namespace across pages.
go to post Timothy Leavitt · Aug 24, 2016 Here's one option: ##class(%SYS.System).InstanceGUID() See the class reference.
go to post Timothy Leavitt · Aug 22, 2016 You can pass a stream to $fromJSON instead of a string: USER>set tStream = ##class(%Stream.TmpCharacter).%New() USER>d tStream.Write("{""a"":2}") USER>s obj = {}.$fromJSON(tStream) USER>w obj.a 2 In your case: Set RequestObj = ##class(%Object).$fromJSON(%request.Content) This is much easier than reading the stream into a string first, and avoids <MAXLENTH> issues.
go to post Timothy Leavitt · Aug 16, 2016 If you're talking about storing dynamic data along with the session, see the documentation on %session.Data. This is just a multidimensional property - so you can do something like: Set %session.Data("hello","world")=15 And then reference that data in a request later in the same session. For a more advanced approach - for example, if there's a large amount of data related to the session - you could use one or more tables instead, and clear data when appropriate by implementing OnEndSession in a subclass of %CSP.SessionEvents and configuring that class as the session events class for your web application (in the web application's security settings).
go to post Timothy Leavitt · Aug 12, 2016 One important note on I/O redirection, from the documentation:When a process performs I/O redirection, this redirection is performed using the user’s login $ROLES value, not the current $ROLES value.In other words, if the I/O redirection is happening in a CSP application or privileged routine application context, in which matching or application roles are added that grant permissions on resources protecting assets the I/O functions need, you might get an unexpected <PROTECT> error, with roles seeming to disappear in wstr()/etc.For the simple case of outputting to a string (as in this example) this is no big deal, but there may be issues with some types of streams, for example, if the stream implementation tries to set/kill globals. (This caught me by surprise the other day.)
go to post Timothy Leavitt · Aug 11, 2016 As written, the code in your post should work fine.If the parameter '1' is actually a COS variable name, then the "undefined" would be expected (since the variable with that name is not defined in JavaScript), and you could use something like:&js<zenPage.doReturn(#(..QuoteJS(myVariableName))#);>
go to post Timothy Leavitt · Jul 27, 2016 Note that INFORMATION_SCHEMA was introduced in Caché 2015.1.
go to post Timothy Leavitt · Jul 21, 2016 Here's the documentation on about configuring/implementing source control in Studio: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...
go to post Timothy Leavitt · Jul 21, 2016 Here's some documentation that might be helpful (if you're looking for a better solution): Packaging DeepSee Elements into Classes It's also possible to export .DFI files directly with $System.OBJ.Export and reload with $System.OBJ.Load, same as with classes/routines. Back to your actual question - what do you mean by "source code of a dashboard in udl format"? If you mean a file containing the same XML you see in Studio - e.g.: <?xml version="1.0"?> <pivot xmlns="http://www.intersystems.com/deepsee/library" name="test2" folderName="" title="" description="" keywords="" owner="" shared="true" public="false" locked="false" resource="" timeCreated="2016-07-21T12:43:26.593Z" createdBy="tleavitt" category="" bookCover="" mdx="" cellWidth="120" columnHeaderStyle="" rowHeaderStyle="" cellStyle="" rowLabelSpan="true" columnLabelSpan="true" cellHeight="22" showEmptyRows="false" showEmptyColumns="false" cubeName="" caption="" listing="" listingRows="" showStatus="true" pageSize="100" colorScale="" rowTotals="false" columnTotals="false" rowTotalAgg="sum" columnTotalAgg="sum" rowTotalSource="page" showZebra="false" showRowCaption="true" printTitle="" printSubtitle="" printSubtitleOn="" showUser="" printPageSize="" printOrientation="" printMarginTop="" printMarginLeft="" printMarginRight="" printMarginBottom="" printLabelWidth="" printCellWidth="" autoExecute="true" manualMode="false" userMDX="" chartMarginTop="" chartMarginLeft="" chartMarginRight="" chartMarginBottom="" maxRows="" borderLeftCell="" borderRightCell="" borderTopCell="" borderBottomCell="" borderLeftCol="" borderRightCol="" borderTopCol="" borderBottomCol="" borderLeftRow="" borderRightRow="" borderTopRow="" borderBottomRow="" fontFamilyCell="" fontSizeCell="" fontFamilyCol="" fontSizeCol="" fontFamilyRow="" fontSizeRow="" showFilters="" showListingFilters="" showDate="" listingFontSize="" showZebraStripes="" filterTableStyle="" filterTableCaptionStyle="" filterTableItemStyle="" nowDisplayFormat="" measureLocation="" hideMeasures="" backgroundImage="" backgroundOpacity=".12"> <rowAxisOptions spec="" key="" value="" text="" headEnabled="true" headCount="" filterEnabled="true" filterExpression="" orderEnabled="false" orderExpression="" orderDirection="BDESC" aggEnabled="false" aggFunction="" aggFunctionParm="" levelCaption="" levelFormat="" levelSummary="" levelType="" drillLevel="0" advanced="false" levelStyle="" levelHeaderStyle="" suppress8020="false" drilldownSpec="" enabled="true"> </rowAxisOptions> <columnAxisOptions spec="" key="" value="" text="" headEnabled="true" headCount="" filterEnabled="true" filterExpression="" orderEnabled="false" orderExpression="" orderDirection="BDESC" aggEnabled="false" aggFunction="" aggFunctionParm="" levelCaption="" levelFormat="" levelSummary="" levelType="" drillLevel="0" advanced="false" levelStyle="" levelHeaderStyle="" suppress8020="false" drilldownSpec="" enabled="true"> </columnAxisOptions> </pivot> You could import it using %DeepSee.UI.FolderItemDocument: Class User.DFIImport { /// Example use: /// Do ##class(User.DFIImport).ImportDFIXML("foldername-itemname.pivot.DFI","C:\Temp\somefile.xml") ClassMethod ImportDFIXML(pName As %String, pFilename As %String) As %Status { Set tSC = $$$OK Try { set tStream = ##class(%Stream.FileCharacter).%New() set tSC = tStream.LinkToFile(pFilename) If $$$ISERR(tSC) { Quit } set tDoc = ##class(%DeepSee.UI.FolderItemDocument).%New(pName) set tSC = tDoc.ImportFromXML(tStream) If $$$ISERR(tSC) { Quit } set tSC = tDoc.Save() If $$$ISERR(tSC) { Quit } } Catch e { Set tSC = e.AsStatus() } Quit tSC } } Note that the name specified for the %DeepSee.UI.FolderItemDocument will overwrite the "name" and "folderName" in the XML.
go to post Timothy Leavitt · Jul 20, 2016 If you're running on Caché 2016.1, the new JSON/Dynamic Object capabilities might help - see: https://community.intersystems.com/post/introducing-new-json-capabilitie...
go to post Timothy Leavitt · Jul 14, 2016 Another option might be "View Other":If ClassA generates ClassB and sets GeneratedBy = ClassA.CLS, then ClassB will show up under "View Other" for ClassA. (Studio works the same way.)
go to post Timothy Leavitt · Jul 10, 2016 This is a good use case for HAVING. Using Sample.Person as an example, the following queries are equivalent: SELECT a.Age,A.Name FROM Sample.Person a LEFT JOIN Sample.Person b on a.home_state = b.home_state and a.DOB < b.DOB WHERE b.ID is null Implemented with HAVING: SELECT Age,Name FROM Sample.Person GROUP BY Home_State HAVING Age = MIN(Age) The second is much more intuitive, and runs significantly faster too. I suspect your query would be expressed as: SELECT * FROM client_address GROUP BY client_id HAVING date_updated = MIN(date_updated)
go to post Timothy Leavitt · Jun 27, 2016 $get does what you're looking for. Note that it's 0-based, like JavaScript: USER>set arr = [1,2,3] USER>w arr.$get(0) 1 USER>w arr.$get(2) 3
go to post Timothy Leavitt · Jun 24, 2016 Yes: USER>set objFromJSON = {}.$fromJSON("{""a"":""1""}") USER>w objFromJSON.a 1
go to post Timothy Leavitt · Jun 17, 2016 The business operation's "Archive I/O" setting might do what you want, depending on what messages you're passing around. This will add some extra things to the message trace showing what the input to services or the output from operations is.You can enable I/O archiving in the business operation's settings on the production configuration page, at the end of the "Development and Debugging" section.
go to post Timothy Leavitt · Jun 16, 2016 Methods in Zen classes declared with "Method" or "ClassMethod" are all server-side. These may also have the ZenMethod keyword, which allows them to be called from javascript (e.g., zenPage.MethodName().)If you want to have a JavaScript method in a Zen class, the method should be declared as a ClientMethod with [Language = javascript].A useful convention you'll see in %ZEN is that server-side, non-ZenMethods have names starting with %, ZenMethods (Methods or ClassMethods with the ZenMethod keyword) start with capital letters, and ClientMethods start with lower case letters. It's useful to follow the same convention when you build your own Zen pages.
go to post Timothy Leavitt · Jun 16, 2016 Your last example is really close - probably just the typo in the component ID that's the problem. Class DC.ZenRadioOnLoad Extends %ZEN.Component.page { /// This XML block defines the contents of this page. XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen" title=""> <radioSet id="appRadio" name="appRadio" displayList="App One,App Two,App Three" valueList="One,Two,Three" /> </page> } /// This callback is called after the server-side page /// object and all of its children are created.<br/> /// Subclasses can override this to add, remove, or modify /// items within the page object model, or to provide values /// for controls. Method %OnAfterCreatePage() As %Status { Set ..%GetComponentById("appRadio").value = "Three" Quit $$$OK } }
go to post Timothy Leavitt · Jun 14, 2016 You could always use process private globals instead of local variable names if you want to avoid collisions in local variable names. ClassMethod GetVariables() As %List { Set ^||VariableNameList = "" Set ^||VariableName = "" Set ^||VariableName = $Order(@^||VariableName) While (^||VariableName '= "") { Set ^||VariableNameList = ^||VariableNameList_$ListBuild(^||VariableName) Set ^||VariableName = $Order(@^||VariableName) } Quit ^||VariableNameList } This might do some things you don't expect depending on variable scope, though - possibly relevant depending on the use case you have in mind. Class Demo.Variables { ClassMethod OuterMethod() { Set x = 5 Do ..InnerMethod() } ClassMethod InnerMethod() [ PublicList = y ] { Set y = 10 Write $ListToString(..GetVariables()) } ClassMethod NoPublicListMethod() { Set y = 10 Write $ListToString(..GetVariables()) } ClassMethod GetVariables() As %List { Set ^||VariableNameList = "" Set ^||VariableName = "" Set ^||VariableName = $Order(@^||VariableName) While (^||VariableName '= "") { Set ^||VariableNameList = ^||VariableNameList_$ListBuild(^||VariableName) Set ^||VariableName = $Order(@^||VariableName) } Quit ^||VariableNameList } } Results: SAMPLES>kill set z = 0 d ##class(Demo.Variables).OuterMethod() y,z SAMPLES>kill set z = 0 d ##class(Demo.Variables).NoPublicListMethod() z