This forum is closed to new posts and responses. Individual names altered for privacy purposes. The information contained in this website is provided for informational purposes only and should not be construed as a forum for customer support requests. Any customer support requests should be directed to the official HCL customer support channels below:

HCL Software Customer Support Portal for U.S. Federal Government clients
HCL Software Customer Support Portal


Mar 15, 2016, 7:59 PM
3 Posts

POFU views in outlines

  • Category: Domino Designer
  • Platform: All Platforms
  • Release: 9.0.1
  • Role: Developer
  • Tags:
  • Replies: 2

Hi Blake, the reason the POFU view doesn't highlight in the embedded outline, I believe, is because the outline points to the "model" for the POFU view, not the personal version created in either the person's desktop or the Db.

It looks like you need the POFU view link to be highlighted when a person 1st opens the Db.  In that case, you can remedy the highlighting problem with step 1 but I'd also recommend you do step 2 too:

1.  Create 2 outlines  --  I am not 100% sure you will need the 2 outlines, but if the outline entry for your POFU view is computed then you will.  But the trick to get the highlighting to work may be the "Other Folders" & "Other Private Folders" section (in your case "Views") -- see the bottom graphic.

   One outline will have the POFU entry computed, and the other will not.  The [OpenView] command in the computed entry will create the POFU folder/view if it doesn't exist:  

(aargh, that sucks!  only I can see the graphic...)  so let me include all the specifics ....

For the Outline with the Computed Entry, the formula for the entry is:

folderName := "Records - by Company";

@SetTargetFrame("Content");
@Command([OpenFrameset];"Frameset-SearchResults");

@SetTargetFrame("FolderView");  
@Command([OpenView];folderName) <<-- this creates the POFU folder/view if it doesn't exist

Then the "Other Folders" section has hide-when = @False

REM { Trick/Kludge:  This entry needs to be present but with an empty label & cannot be hidden, };
REM { so that the Private folders created from the Shared POFU ones can retain outline focus & display properly. };
REM { You DO need to have an outline entry for each Private folder beneath this outline entry, };
REM { and they should always be hidden & then also put them where you want them [see Reports] };
REM { CAVEAT:  The name that displays in the outline for these entries is the actual folder name, not the outline entry label. };
@False

& the Records - by Company outline entry is just Named Element / View / Records - by Company but HIDE ALWAYS

Then the "Other Private Folders" section has hide-when = @False

REM { Trick/Kludge:  This entry needs to be present but with an empty label & cannot be hidden, };
REM { so that the Private folders created from the Shared POFU ones can retain outline focus & display properly. };
REM { You DO need to have an outline entry for each Private folder beneath this outline entry, };
REM { and they should always be hidden & then also put them where you want them [see Reports] };
REM { CAVEAT:  The name that displays in the outline for these entries is the actual folder name, not the outline entry label. };
@False

& the Records - by Company outline entry is just Named Element / View / Records - by Company but HIDE ALWAYS

 

Computed outline entry    

For the Outline with the Named Element entry:

It's just a regular Named Element / View / Records - by Company

Then the "Other Folders" section has hide-when = @True

REM { Trick/Kludge:  This entry needs to be present but with an empty label & MUST be hidden, };
REM { so that the Private folders created from the Shared POFU ones can retain outline focus & display properly. };
REM { You DO need to have an outline entry for each Shared POFU/Private folder beneath this outline entry, };
REM { and they should always be hidden & then also put them where you want them [see Reports] };
REM { CAVEAT:  The name that displays in the outline for these entries is the actual folder name, not the outline entry label. };
@True

& the Records - by Company outline entry is just Named Element / View / Records - by Company but HIDE ALWAYS

Then the "Other Private Folders" section has hide-when = @False

REM { Trick/Kludge:  This entry needs to be present but with an empty label & cannot be hidden, };
REM { so that the Private folders created from the Shared POFU ones can retain outline focus & display properly. };
REM { You DO need to have an outline entry for each Private folder beneath this outline entry, };
REM { and they should always be hidden & then also put them where you want them [see Reports] };
REM { CAVEAT:  The name that displays in the outline for these entries is the actual folder name, not the outline entry label. };
@False

& the Records - by Company outline entry is just Named Element / View / Records - by Company but HIDE ALWAYS

not-computed

Then in the Page holding your embedded outline, you can use formula to determine which outline to load.  I had to keep track of the last view opened in an environment variable to get this to work:

REM { Load up the correct outline if the last-used view was actually a folder, otherwise, open up the default outline };

REM { This is needed because the outline entries that link to folders must open up a different frameset with a split frame
            than normal views which open up in a 1 frame frameset, and as a result each outline entry for a folder link is a Computed Action
            not just a standard Named Element link.  Doing things this way gets around a problem where Notes can't recognize
            a Computed Action link as the one that should be highlighted when the Db is first opened (Db Launch is set to   
            "Restore as last used by user").  Having separate Outlines for each folder that has just a Named Element / Folder
            as the outline entry will cause the appropriate folder link to be highlighted if that was the last one used by the user. };

viewOrFolder := @Environment("YOUR-DB-ViewOrFolder");
outlineName := @If( @Begins(viewOrFolder;"Records - "); "Outline-Folder: " + viewOrFolder; "Outline-Main" );
@If( @IsMember("[DBManager]";@UserRoles); @StatusBar("opening " + outlineName); "" );
outlineName

2.  Ensure stale POFU views/folders aren't being used

I'd suggest you store all the users' POFU views on the server if that's not too many.  That way you can have some code that runs once when a person opens the Db to compare their POFU view to the "model" POFU view & delete the user's POFU if it is stale.  This way you don't end up with obsolete versions of POFU views being used out in the wild & having no (easy) way of updating them.  For instance, I put this agent in the QueryOpen PostOpen of a BannerPage that only gets loaded once per session -- this code was modified slightly from something I found in the Ytria site's blog [ http://techlab.ytria.com/2381/tutorials/reveal-private-views-folders-agents-lotus-notes-applications/ ]:

REM { This agent only needs to run once at the beginning of each Db session } --> I do this at beginning of session, others say do it when user closes Db session (your pick);
@Command([ToolsRunMacro];"(Delete My Stale Private Views)")

Sub Initialize
    On Error GoTo HANDLE_ERROR        
    
    Dim s As New NotesSession
    Dim ws As New NotesUIWorkspace
    Dim db As NotesDatabase
    Dim OKtoRemove As Boolean 
    Dim forceDelete As Boolean 
    
    Set db = s.CurrentDatabase
    
    ' -  This will remove the current user's private folders if they are stale so they can be refreshed/rebuilt using the shared (model) folder
    ' -      If there are entries in a stale folder, the folder will be rebuilt from the model folder, then the entries restored to the rebuilt folder
    ' -  If there are no entries in the stale folder, the folder will just be deleted & will only be rebuilt as needed when search results are
    '      placed in it
    
    ' -  This has to be run by each user due to the $Readers fields on the private folders
    ' -  In the subroutine, [DBManager] will be able to override the deletion
    OKtoRemove = True
    ' -  You can force the private views/folders to be re-built even if they aren't stale but we don't want that in this case
    forceDelete = False 
    Call RemoveOldPrivateViews(db,OKtoRemove,forceDelete)
    
END_ROUTINE:
    Exit Sub
    
HANDLE_ERROR:
    Error Err, Error$ & Chr$(10) & " in subroutine " & GetThreadInfo(1) & " on line " & CStr(Erl)    
End Sub

Sub RemoveOldPrivateViews( pdb As NotesDatabase, OKtoRemove As Boolean, forceDelete As Boolean )
%REM
    SUBROUTINE: RemoveOldPrivateViews
    
    PURPOSE:      This code is a modified version of that found on the Ytria web site that will delete any private views stored in
    the database (Shared-Private-on-1st-Use) and remove them.  It is used to refresh the design of these POFU views
    when the template/model version of the view changes.  In order for private views to be stored in the Db on the server
    the user must have the ACL privilege = "Create personal folders/views" selected.
    
    It allows users with [DBManager] role to override the stale private view deletion for testing or trouble-shooting purposes.
    
    This routine is triggered from the PostOpen event on the Main Menu page, and optionally from view action button on views that
    only [DBManager] will see in the outline.
    
    With modification, this code could also be used to remove any personal views or folders that users create on their own
    that are stored in the Db on the server (ACL privilege = "Create personal folders/views").
    
    PARAMETERS:
    - pdb                            : current database
    - OKtoRemove        : Flag to switch deletion on/off of stale views.  Default = TRUE.
    - forceDelete        : Flag to force views to be deleted even if they aren't stale.  Default = FALSE.
    
    WRITTEN BY: 2013.08.01
    MODIFICATIONS:
    2013.08.01 (JLK) : *new* - Modified from original code posted by Ytria on their web site
    2014.03.26 (JLK) : copied & modified for use in this Db to delete POFU-Folders from the MasterDocLibOutline 
            page PostOpen event 
%END REM    
    Dim s As New NotesSession
    Dim ws As New NotesUIWorkspace 
    Dim uiDb As NotesUIDatabase 
    Dim nvPr As NotesView
    Dim nvFi As NotesView
    Dim nvecPr As NotesViewEntryCollection  ' the Private stored-in-Db views
    Dim nvePr As NotesViewEntry
    Dim nvecFi As NotesViewEntryCollection   ' the Shared POFU model views
    Dim nveFi As NotesViewEntry
    Dim lView List As String
    Dim nvTgt As NotesView
    Dim nfPr As NotesView 
    Dim doc As NotesDocument 
    Dim vec As NotesViewEntryCollection ' the entries in a Private stored-in-Db view
    Dim ve As NotesViewEntry 
    Dim dc As NotesDocumentCollection ' the documents for the vec above
    Dim curUIView As NotesUIView 
    Dim curViewName As String 
    Dim deletedViewNames As String 

    Dim userRoles As Variant 
    Dim isDBManager As Boolean 
    Dim oldViewCount As Integer 

    ' -  Keep track of the current view    & environment variables
    Set uiDb = ws.CurrentDatabase
    Set curUIView = ws.CurrentView
    If Not( curUIView Is Nothing ) Then
        curViewName = curUIView.ViewName 
    End If
    
    ' -  QueryAccessRoles will return all roles assigned if user in multiple groups, or all roles assigned
    '     to individual entry if user listed explicitly (group roles assigned ignored in that case)
    userRoles = pdb.QueryAccessRoles(s.Effectiveusername)
    ForAll aRole In userRoles
        If aRole = "[DBManager]" Then 
            isDBManager = True
            Exit ForAll 
        End If
    End ForAll
    
    Print "Getting the list of Views/Folders"
    Set nvPr = pdb.GetView("AllMyPrivateViews")    ' the private views stored on the server
    Call nvPr.Refresh()
    Set nvFi = pdb.GetView("AllPrivateFirstUseViews")   ' the shared (model) views that are POFU
    Call nvFi.Refresh()
    
    ' -  Loop through all the private views, see if there is a matching shared view with the same alias name
    ' -  If match found, check if the shared view has a newer Last-Modified date than the private view
    '         --> YES : save the NoteID of the private view for deletion 
    '        --> NO : private view is current, no need to delete it
    Set nvecPr = nvPr.AllEntries
    Set nvePr = nvecPr.GetFirstEntry()
    Do While Not nvePr Is Nothing
        Set nveFi = nvFi.GetEntryByKey( nvePr.ColumnValues(0), True )
        If Not nveFi Is Nothing Then
            If nveFi.ColumnValues(2) > nvePr.ColumnValues(4) Then
                Print "Update needed for View/Folder : "+nvePr.ColumnValues(1)+" ["+nvePr.NoteID+" / " +nvePr.Universalid+"]"
'                lView( nvePr.NoteID ) = nvePr.ColumnValues(0)   ' alias name
                lView( nvePr.NoteID ) = nvePr.ColumnValues(1)      ' regular view name            
                deletedViewNames = deletedViewNames + Chr$(13) + nvePr.ColumnValues(1)
                oldViewCount = oldViewCount + 1
            ElseIf forceDelete Then
                Print "View/Folder : "+nvePr.ColumnValues(1) +" is up-to-date  ["+nvePr.NoteID+" / " +nvePr.Universalid+"] but force delete is ON"
'                lView( nvePr.NoteID ) = nvePr.ColumnValues(0)
                lView( nvePr.NoteID ) = nvePr.ColumnValues(1)                
                oldViewCount = oldViewCount + 1
            Else 
                Print "View/Folder : "+nvePr.ColumnValues(1) +" is up-to-date ["+nvePr.NoteID+" / " +nvePr.Universalid+"]"
            End If
        End If
        Set nvePr = nvecPr.GetNextEntry( nvePr )
    Loop
    Print "Getting the list of Views/Folders - Done"
    
    ' -  If there are stale private views & current user is DBManager, prompt to override deletion
    If isDBManager And oldViewCount > 0 Then 
        OKtoRemove = ws.Prompt(PROMPT_YESNO,"Delete stale private views/folders?", + _
        "Prompt for DBManager Only --" + Chr$(13) + Chr$(13) + _
        "# of Out-of-date Private Views/Folders found = " + CStr(oldViewCount) + Chr$(13) + _
        "Delete the Private ones modelled on Shared-Personal-on-First-Use views/folders to refresh their design?" + Chr$(13) + Chr$(13) + _
        "( *NOTE* This will only delete YOUR private views/folders )")
    End If 
    
    If OKtoRemove Then 
        ForAll theView In lView
            
            Set nvTgt = Nothing
            On Error Resume Next    ' this will get around the "Index is not to be generated on server" error that will likely happen with GetView
            Set nvTgt = pdb.GetView( theView )   ' this IS getting the PRIVATE folder
            On Error GoTo 0   ' I think this will force the routine to continue on with removing the private view (bypass all errors)    
            ' -  Before deleting the private view/folder, get a count of all entries in it -- was never able to rebuild & re-populate
            '      the private folder successfully so this will have to do
            Set vec = nvTgt.AllEntries    ' this IS getting the entries in the PRIVATE folder
            Print "Removing View/Folder : "+nvTgt.Name+" ["+nvTgt.UniversalID+"] -- # entries = " + CStr(vec.Count) 
            Call nvTgt.Remove()

        End ForAll
        
        If oldViewCount > 0 Then
            MessageBox "The design of the following report folders has been updated:" + Chr$(13) + deletedViewNames + Chr$(13) + Chr$(13) +_
            "You will need to re-run your search using the [Run Again] button " + Chr$(13) + _
            "on the Query to refresh the report contents." + Chr$(13) + Chr$(13) +_
            "***  Please CLOSE & RE-OPEN the database to finalize this update ***", 0+64+0+0, "Report refreshed ..."
            ' -  To ensure Db doesn't try to open to one of the now-deleted private folders, delete the last-used environment variables
            Call s.SetEnvironmentVar("YOUR-DB-Frameset","")
            Call s.SetEnvironmentVar("YOUR-DB-ViewOrFolder","")
        End If
    End If   ' ...     If OKtoRemove Then 
    Erase lView 

    Print "Getting the list of Views/Folders - Done"
    
End Sub

The 2 views you'll need referenced above can be found in the original NSF here http://techlab.ytria.com/243/lotus-notes-code/case-private-views/

Hope this helps you or someone else confronted with this. 

Judy


This forum is closed to new posts and responses. Individual names altered for privacy purposes. The information contained in this website is provided for informational purposes only and should not be construed as a forum for customer support requests. Any customer support requests should be directed to the official HCL customer support channels below:

HCL Software Customer Support Portal for U.S. Federal Government clients
HCL Software Customer Support Portal