Written by

Question Arto Alatalo · Mar 27, 2020

Management Portal: how to view globals in opposite order?

A simple question: View Global Data  page shows globals always in ascending subscript order. Very often I need to see latest page, is there any trick for this?

Update: I mean to see last subscripts in Management Portal, not using the code

Comments

Robert Cemper · Mar 27, 2020

just use a single liner from terminal for the last 10 lines  or any number you need

s g="^myGlobal("""")" f i=1:1:10  s g=$q(@g,-1,%) q:g=""  w !,g zw %
0
Arto Alatalo  Mar 27, 2020 to Robert Cemper

Updated my question. I mean to view them in Portal.

0
Robert Cemper · Mar 27, 2020

I don't know of reverse  order

BUT if you have some idea of the last subscript you may enter the starting  subscript.

instead of seeing the whole Global ^CONFIG

just one specific  subscript ^CONFIG("Telnet"

os starting from a specific subscript ^CONFIG("Telnet":

or from:to subscript ^CONFIG("ECP":"Journal"

or just the select subscript level with a closing bracket ^CONFIG("ECP":"Journal")

Basically it is the same behavior  of the ancient (not to say antique) routine ^%G

When it was written traversing a Global in reverse order was not implemented in Caché nor ist'S predecessors.
So no reverse display

It has a help function that tells you it's capabilities  DO HELP^%G

The %G utility displays global nodes. A "?" at the "Global ^" prompt
displays the global directory.
If you enter just the name of a global,
%G displays the entire global. You may also display a portion of the
global at different subscript levels or specific nodes.
 
A complete global reference, such as ^GLO(3,"BED",5) will display
only that particular node. You may specify a subtree, such as
^GLO(3,"BED", to display all descendants of that node. To display
both the node and its descendants, do not end your entry with a
comma or a right parenthesis.
 
You can leave a subscript field empty when you specify the subtree and
the %G utility displays any nodes matching the other subscripts:
^GLO(,"BED") will match any nodes with 'BED' as the second subscript.

 
You can specify a range of subscripts for a particular subscript
level by inserting a colon between the first and last subscript in the
range: ^PT(1,"ACC":"BIRTH"
 

You can use variables and simple expressions in a subscript
specification by assigning a value to the variable before calling %G.
For example SET ID=214 and enter something like ^PT(ID,0).

 
0
Arto Alatalo  Mar 27, 2020 to Robert Cemper

Thanks,  I'm aware of Search Mask functionality.

>... if you have some idea of the last subscript ...

That's the point: very often when viewing a global on production server via Portal, you just want to see a few latest records, not starting to search for last subscripts.

0
Robert Cemper  Mar 27, 2020 to Arto Alatalo

You don't have a great chance, but you may dig it down like this

And I assume once seen you get your display faster than this cycles where I had no idea on the subscript structure before

0
Arto Alatalo  Mar 27, 2020 to Robert Cemper

I've huge globals, so this way doesn't work for me.

>to estimate the age of ^%G take a look to copyright

oh ye :)

0
Robert Cemper  Mar 27, 2020 to Robert Cemper

to estimate the age of ^%G take a look to copyright

0
Peter N  Mar 28, 2020 to Robert Cemper

Thanks for the details!   And history wink

0
Arto Alatalo  Mar 27, 2020 to Evgeny Shvarov

What's ad-hoc portal page? Google has no idea

0
Evgeny Shvarov  Mar 27, 2020 to Arto Alatalo

I mean you develop this view by yourself and install every time (e.g. with ZPM). I believe @Eduard Lebedyuk did something like that for Interoperability.

0
Arto Alatalo  Mar 27, 2020 to Evgeny Shvarov

>you develop this view by yourself

yes, that's clear. But what is "ad-hoc portal page"? A way to extent Management Portal with custom pages?

0
Sergey Mikhailenko  Mar 27, 2020 to Evgeny Shvarov

Yes, this is implemented in my decision, since I also really need to watch the end of the aray

0
Arto Alatalo  Mar 27, 2020 to Sergey Mikhailenko

Can you say what min Cache version is supported? My Cache 217.2 fails to parse the xml.

0
Arto Alatalo  Mar 27, 2020 to Sergey Mikhailenko

Yes, now I can import it. But controls Direct View and the filter do not exist. And as just a side note, everything related to Ensable fails to compile on my Cache.

0
Robert Cemper  Mar 27, 2020 to Arto Alatalo

it is an IRIS export

<?xml version="1.0" encoding="UTF-8"?>

<Export generator="IRIS" version="26" zv="IRIS for Windows (x86-64) 2019.1.1 (Build 609U)" ts="2020-03-22 18:56:51">

 

while for Cache it ooks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">

 

it might be sufficient to change 26 to 25 to make your Caché happy

0
Arto Alatalo  Mar 27, 2020 to Evgeny Shvarov

Would be nice to have a way to extend Portal with custom pages. This way colleagues need not to learn and store links to the pages. 

0
Sergey Mikhailenko  Mar 27, 2020 to Arto Alatalo

You can store user pages in your favorites, with this command
Set tSC=##class(%SYS.Portal.Users).%AddFavorite("AppTools","/ apptools/App.LogInfo.cls")

0
Arto Alatalo  Mar 27, 2020 to Sergey Mikhailenko

Great! Thanks!  

0
Eduard Lebedyuk · Mar 27, 2020

Easy to do that.

Here's how.

First of all let's find out where we do the iteration. If we open UtilExpGlobalView.csp we see that it's essentially a wrapper over %CSP.UI.System.GlobalViewPane.

In %CSP.UI.System.GlobalViewPane there's a LoadGlobal method which has this promising line:

Set tRS = ##class(%ResultSet).%New("%Global:Get")

Next we follow the trail to %Library.Global class implementing  Get query, which has GetFetch method, which actually iterates over the global here:

Set idx=$Order($$$ISCQUERYTEMP(Index,idx),1,Row)

So now we wrap it up back.

We need a new query (GetFetch is copied as is with one change - inverse iteration order, bolded):

 

Test.Global class

 
Class Test.Global Extends %Global
{

ClassMethod GetFetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ Internal, PlaceAfter = GetExecute ]
{
    Set $zt="ERROR"
    Set idx=$p(qHandle,"^",2)
    Set Index=$p(qHandle,"^")
    Set idx=$Order($$$ISCQUERYTEMP(Index,idx),-1,Row)
    If idx="" {
        Set Namespace=qHandle("Namespace")
        Set SearchMask=qHandle("SearchMask")
        Set LastNode=qHandle("LastNode")
        Set NameFormat=qHandle("NameFormat")
        Set ValueFormat=qHandle("ValueFormat")
        Set OldNsp=$zu(5),%UI="CHUI",Count=100
        If Namespace'=OldNsp ZN Namespace
        Set data=$$page^%Wgdisp(SearchMask,LastNode,.Count,0,"","",1,NameFormat,ValueFormat)
        If $zu(5)'=OldNsp ZN OldNsp
        If 'Count Set AtEnd=1,Row="" Quit $$$OK
        ;
        Kill $$$ISCQUERYTEMP(Index)
        For i=1:1:Count {
            Set rec=$p(data,$$$del1,i),subs=$p(rec,$$$del2),val=$p(rec,$$$del2,2)
            Set nf=$p(rec,$$$del2,3),vf=$p(rec,$$$del2,4)
#;SML618+
#;Setup ^CacheTemp with a subroutine in case it overflows the $LB() list.
            d BuildCacheTemp
#;SML618-
        }
        Set qHandle("LastNode")=..Unquote(subs,1)
        Set qHandle=Index_"^"
        Quit ..GetFetch(.qHandle,.Row,.AtEnd)
    } Else {
#;SML618+
#;If there is extension of data then set them to Row array for %ResultSet to get them.
        if $d($$$ISCQUERYTEMP(Index,idx,1)) {
            Set Row(1)=$$$ISCQUERYTEMP(Index,idx,1)
            if $d($$$ISCQUERYTEMP(Index,idx,2)) {
                Set Row(2)=$$$ISCQUERYTEMP(Index,idx,2)
            }
        }
#;SML618-
        Set qHandle=Index_"^"_idx
    }
    Quit $$$OK
ERROR Set $zt=""
    If $g(OldNsp)'="",$zu(5)'=$g(OldNsp) ZN OldNsp
    Quit $$$ERROR($$$CacheError,$ze)
#;SML618+
#;Set the data extension to two or three pieces if it could not fit in one piece.
BuildCacheTemp s $zt="BuildErr1"
    i subs["(" {
        s sub1="("_$p(subs,"(",2,999)
    } else {
        s sub1=""
    }
    s Perm=$s(qHandle("GetPermissions")=0:"",1:$$GetGlobalPermission^%SYS.SECURITY(Namespace,$p(subs,"(",1),sub1,1))
    Set $$$ISCQUERYTEMP(Index,i)=$lb(subs,val,nf,vf,Perm)
    Q
BuildErr1 s $zt="BuildErr2"
    Set $$$ISCQUERYTEMP(Index,i)=$lb(subs,$e(val,1,$l(val)\2),nf,vf,$g(Perm))
    Set $$$ISCQUERYTEMP(Index,i,1)=$lb("",$e(val,$l(val)\2+1,$l(val)),"","","")
    Q
BuildErr2 s $zt=""
    Set $$$ISCQUERYTEMP(Index,i)=$lb(subs,$e(val,1,$l(val)\3),nf,vf,$g(Perm))
    Set $$$ISCQUERYTEMP(Index,i,1)=$lb("",$e(val,$l(val)\3+1,$l(val)\3*2),"","","")
    Set $$$ISCQUERYTEMP(Index,i,2)=$lb("",$e(val,$l(val)\3*2+1,$l(val)),"","","")
    Q
#;SML618-
}

}

Now we wrap it into a pane

 

Test.GlobalViewPane

And finally create a csp page

 

UtilExpGlobalViewR.csp

<AutoPage pagename="View Global Data" parentpage="UtilExpGlobalList.csp" stylesheet="intersystems.css" USENAMESPACE="1">

<Pane name="Title" type="%CSP.Util.SMTitlePane">
    <Text>View Global Data</Text>
</Pane>

<Pane name="Detail" type="Test.GlobalViewPane">
</Pane>

</AutoPage>

And done, add R to URL and see the global in reverse in SMP:

0
Arto Alatalo  Mar 27, 2020 to Eduard Lebedyuk

Wow! A really nice hack! :) Well done!

0
Robert Cemper  Mar 27, 2020 to Arto Alatalo

And keep the cooking description for your future updates

0
Evgeny Shvarov  Dec 30, 2020 to Eduard Lebedyuk

Make an OEX module from this? Great thing.

0
Eduard Lebedyuk  Dec 30, 2020 to Evgeny Shvarov

I don't think this snippet is suitable to be a standalone app tbqh.

0