1. Inherit from EnsPortal.MessageViewer
  2. Copy searchPane from EnsPortal.Template.filteredViewer
  3. In searchPane, TimeFormat node replace attribute  value="12" with value="999"
  4. 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.

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
}

Check where in ParseZU49Info it takes field 14 and what property does it fills with that information.  Check %syDatabase.inc for more information.

#; Pieces of return value from $zu(49)
#define mountpiece 1
#define blksizpiece 2
#define uicpiece 3
#define filsizpiece 4
#define expandpiece 5
#define maxblkpiece 6
#define glodirpiece 7
#define gloptrpiece 8
#define rdirpiece 9
#define rgrpiece 10
#define glogrpiece 11
#define freezepiece 12
#define colpiece 13
#define sfnpiece 14
#define totvolpiece 15
#define formatpiece 16
#define attribpiece 17
#define statuspiece 18
#define exptimepiece 19
#define nojrnpiece 20
#define bigdbpiece 21
#define curblkspiece 22
#define blkspermappiece 23
#define curmapspiece 24
#define resourcepiece 25
#define enckeyidpiece 26

-  where can I get cache.node? The link in the Intersystmes documentation  http://globalsdb.org/downloads/  doesn't work. I found cache0100.node and cache0120.node  in my Cache instance's  \bin directory. But I am not sure if I can use them or not.

Cache instance's  \bin directory is the correct path.

Can anyone recommend any tutorial or code example with installation instructions?

Samples are provided in <CacheDir>\dev\node.js\samples directory. Installation instructions are located in settings.js file.

These changes fixed it:

  • Removed highlited part of storage definition
  • Made invalid property Transient
  • Added 0 default to $Get
Class Wendy.LTCodes Extends %Persistent [ StorageStrategy = LTCStorage ]
{

Property Code As %String;

Property Description As %String;

Property Invalid As %Library.Boolean [ SqlComputeCode = { set {*} = ##class(Wendy.LTCodes).GetInvalid({Code})}, SqlComputed, Transient ];

Index CodeIndex On Code [ IdKey, PrimaryKey, Unique ];

ClassMethod GetInvalid(WSCode) As %Boolean
{
    Quit $G(^LTCODES(WSCode,"INVALID"),0)
}

Method InvalidGet() As %Boolean
{
    Quit ..GetInvalid(i%Code)
}

Method InvalidSet(value As %Boolean) As %Status
{
    Set ^LTCODES(i%Code,"INVALID")=value
    quit $$$OK
}

/// Do ##class(Wendy.LTCodes).SetData()
ClassMethod SetData()
{
    kill ^LTCODES
    S ^LTCODES("N001")="ANYOLD DESC"
    S ^LTCODES("N001","INVALID")=1
    S ^LTCODES("N002")="C5 REPEAT 1"
    S ^LTCODES("N111")="SPECIMEN COMMENT"
    S ^LTCODES("N200")="MSUD SCREEN|MSUD"
    S ^LTCODES("N500")="Sickle Cell Screen"
}

Storage LTCStorage
{
<SQLMap name="LTCMap">
<Data name="Description">
<Delimiter>"|"</Delimiter>
<Piece>1</Piece>
</Data>
<Global>^LTCODES</Global>
<Subscript name="1">
<Expression>{Code}</Expression>
</Subscript>
<Type>data</Type>
</SQLMap>
<StreamLocation>^Wendy.LTCodesS</StreamLocation>
<Type>%CacheSQLStorage</Type>
}

}

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  Invalid
N001N001ANYOLD DESC1
N002N002C5 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

I removed InvalidGet method and object access to the property stopped working.

Class Utils.GlobalProp Extends %Persistent
{

Parameter InvalidGLVN = "^Utils.GlobalPropP";

Property Invalid As %String [ SqlComputeCode = {set {*} = ##class(Utils.GlobalProp).InvalidStatic()}, SqlComputed, Transient ];

ClassMethod InvalidStatic() As %String
{
    Return $Get(@..#InvalidGLVN)
}

Method InvalidSet(val As %String) As %Status
{
    Set @..#InvalidGLVN = val
    Return $$$OK
}

/// Do ##class(Utils.GlobalProp).Test()
ClassMethod Test()
{
    Do ..%KillExtent()
    Set obj = ..%New()
    Write "Invalid old: " _ obj.Invalid,!
    Set obj.Invalid = $Random(100)
    Write "Invalid new: " _ obj.Invalid,!
    Do obj.%Save()
    Kill obj
    &sql(SELECT Invalid INTO :invalid FROM Utils.GlobalProp WHERE Id = 1)
    Write "SQLCODE: " _ SQLCODE,!
    Write "Invalid sql: " _ invalid,!
}

Outputs:

Invalid old:
Invalid new:
SQLCODE: 0
Invalid sql: 65

Related Int code:

zInvalidCompute(%id)
    New %tException,%val set %val = ""
    try {
    set %val = ##class(Utils.GlobalProp).InvalidStatic()
    } catch %tException { throw %tException }
    Quit %val
zInvalidGet() public {
    If i%Invalid = "" { Set ..Invalid=..InvalidCompute($listget(i%"%%OID")) } Quit i%Invalid }
zInvalidSQLCompute()
    // Compute code for field Invalid
 set %d(2) = ##class(Utils.GlobalProp).InvalidStatic()
 QUIT

    Do $System.Status.DisplayError(tStatus)
        Write !
    }
    Quit
}
}