This class is for internal InterSystems use only. The class is subject to change and should not be
used by user applications.
Template for portal pages which need to be able to interact with Source Control hooks.
This class implements various interfaces and behaviours into the standard Studio patterns used for
%Studio.SourceControl.Base. Note that the browser environment is inherently stateless,
so the object implementing the source control hooks needs to be created from scratch every time the
browser makes a request back to the server. Source control hooks written for the Studio environment
will need to adjust for this situation. To assist in this migration, the hooks can should override
the OnPortalCreate() callback that is inherited from %Studio.SourceControl.Base to ensure
that the Source Control object is correctly initialised whenever it is created.
Users should also modify the behaviour of any Studio templates invoked from their source control hooks.
It is critical that pages which extend this class implement a number of callbacks. The following
methods MUST be overridden:
It is also assumed that a Zen jsonProvider instance is used to represent the data model in the page.
The object used for the model MUST extend %CSP.Portal.AbstractPortalModelOR include a Timestamp property and a ReadOnly property as per the interface defined in
%CSP.Portal.AbstractPortalModel if custom JSON is sent from the server to the client. These two properties
are used to ensure that the client and server versions of the document model are synchronised.
Furthermore, the OnSubmitContent callback implemented in the page MUST perform a number of actions.
First, it must support two save modes. The first such mode is a standard save mode. The value of the
command string for this mode should be specified in the getSaveAction()() callback.
When this standard save mode is specified, the server method must check whether the timestamp of the model
on disk matches the Timestamp property of the submitted model. If they don't match, the error property of
the supplied jsonProvider instance should be set to the string "timestamp".
When the page sees this error, the user will be prompted to decide if they want to overwrite the data on the server.
If the user does choose to overwrite the data, then getSaveAction()() will be invoked to get the
force save action. In this case, the OnSubmitContent callback should NOT perform any timestamp checks --
the model should be saved to disk.
If the timestamps match, or the force command is supplied, and the model is saved to disk, the method should then
ensure that an updated model is sent back to the client in the output object argument of the callback. The updated model
should include both the new Timestamp for the document as well as a valid ReadOnly value. In this case, a valid ReadOnly value
should be determined as follows:
Call IsSourceControlReadOnly()() to determine whether the document is marked as read only by the current
source control hooks. If so, set the ReadOnly property to 2.
Otherwise check if the document has been locked by another user. If so, set the ReadOnly property to 1.
Otherwise set the ReadOnly property to 0.
A sample OnSubmitContent callback method could look like the following:
Method SubmitModel(
pCommand As %String,
pProvider As %ZEN.Auxiliary.jsonProvider,
pSubmitObject As %RegisteredObject,
ByRef pResponseObject As %RegisteredObject) As %Status
{
Set tSC = $$$OK
Try {
Set tReadOnly = 0
If (pCommand '= "forcesave") && ##class(%Dictionary.ClassDefinition).%ExistsId(..modelClassName) {
// Note that 1 is passed in for the pExclusiveOnly argument as we need an exclusive lock
Set tSC = ..LoadClassDefinition(..modelClassName,.tModelDef,.tReadOnly,1)
If $$$ISERR(tSC) Quit
If $zdatetime(tModelDef.TimeChanged,3,,6) '= pSubmitObject.Timestamp {
Set pProvider.error = "timestamp"
Quit
}
}
Set tSC = pSubmitObject.SaveToClass()
If $$$ISERR(tSC) Quit
// send up-to-date model back to client, this should include updated timestamp
Set pResponseObject = pSubmitObject
// correct the ReadOnly flag on the response object
If ..IsSourceControlReadOnly(..GetInternalName()) {
Set pResponseObject.ReadOnly = 2
}
Else {
Set pResponseObject.ReadOnly = tReadOnly
}
}
Catch(ex) {
Set tSC = ex.AsStatus()
}
Quit tSC
}
Indicator for why a document was marked as readOnly. When readOnly
is true, the updateDocumentState()() is responsible for ensuring that the
property should either have a value of "sourcecontrol" or "lock".
This is a helper method to render the default HTML for the source control options in the ribbon,
and should be called from the OnDrawRibbon() callback.
This content should be wrapped within a td element.
Return the internal name of the current document, including the three letter
extension in upper-case. For example, MyPackage.MyClass.CLS would be the internal name
for the class MyPackage.MyClass.
Subclasses MUST override this method.
classmethod GetSourceControlCommands(Output pDisplay As %Boolean, Output pCommands, Output pNeedProject As %Boolean, Output pServerOutput As %String) as %Status
Determine which source control commands should be drawn for the current context.
classmethod GetTimestamp(classname As %String = "") as %String [ ZenMethod ]
Load the named project in pProject using the source control object
supplied in pSourceControl. The pRedirect flag controls whether
a local redirect should be created.
method UpdateSCMenus(showMenu As %Boolean = 0) as %String [ ZenMethod ]
Update the _sourceControlMenu Javascript object representing the contents of the source control menus.
Server-side wrapper around the UserAction callback.
clientmethod appendServerOutput(data, first) [ Language = javascript ]
Render the server output from source control commands on the client.
clientmethod canUserModify(noAlert) [ Language = javascript ]
Helper method to indicate whether the user is allowed to make changes to the
current document. It should check whether the user is allowed to make changes in general
(which should be indicated by canEdit), as well as whether the current
document has been opened in read only mode (which should be indicated by canEdit).
noAlert is a flag to indicate that the check should not raise an alert.
clientmethod checkTextControls() [ Language = javascript ]
Helper method for event sequencing: the onmousedown event for the menu buttons and shapes in the SVG diagram
may be executed before the onchange event for controls in the editor pane. This helper function
will call the onchange event for any controls which have had their value changed. (There should only be one
such control in most cases as the onchange event would be triggered when shifting focus to a second control.)
clientmethod chooseSCMenu(menuName, commandName, saveFlags) [ Language = javascript ]
Handle a source control menu selection.
clientmethod chooseSCProject(projectName, isNew) [ Language = javascript ]
The user has selected on of the projects listed in the dropdown.
clientmethod clearSCOutput() [ Language = javascript ]
Clear the source control output on the server and update the content star.
clientmethod createSCMenuItem(parentItem, caption, onselect) [ Language = javascript ]
Helper method to create an item in the source control menu.
clientmethod createSCProject(projectName) [ Language = javascript ]
Create a new project on the server.
clientmethod createSCSubMenu(parentItem, caption) [ Language = javascript ]
Helper method to create a submenu in the source control menu.
clientmethod getClientModel() [ Language = javascript ]
Get the jsonProvider object on the client.
Subclasses MUST override this method to return the jsonProvider.
clientmethod getCurrentExtension() [ Language = javascript ]
Return the extension used by Studio for the class/object.
This is ".CLS" by default, but subclasses should override this method
if a different extension is in use.
clientmethod getCurrentName() [ Language = javascript ]
Return the current name of the class/object being modified.
Subclasses MUST override this method to return the correct name.
clientmethod getPageTitle() as %String [ Language = javascript ]
Get the title string to add to the locator row.
This should be implemented in a subclass.
clientmethod getReadOnlyReason() [ Language = javascript ]
Callback to get the text of the reason for the current document being loaded as readonly.
clientmethod getSaveAction(force) [ Language = javascript ]
Return the string used as the command when sending JSON content to the server.
The OnSubmitContent handler for the jsonProvider MUST support two action types.
clientmethod initializeSourceControl() [ Language = javascript ]
Function to initialize the source control hooks for a page.
The function should be called from the subclass's onloadHandler()() method.
clientmethod initializeTextMonitor() [ Language = javascript ]
Initialize the text monitor for the page.
clientmethod invokeAfterUserAction(input, userContext) [ Language = javascript ]
Client-side coordinator of calls to the AfterUserAction callback in
the core source control class.
clientmethod invokeSourceControl(action, isFramework) [ Language = javascript ]
Client-side coordinator of calls to the UserAction callback in
the core source control class.
clientmethod loadDocument() [ Language = javascript ]
Method to load document from the client and invoke the correct source control hooks.
clientmethod onDocumentLoad(when, documentName) [ Language = javascript ]
Callback invoked when a document is being loaded.
clientmethod onDocumentLoadComplete() [ Language = javascript ]
Callback method invoked after we have successfully loaded the current document.
clientmethod onDocumentSave(when, documentName) [ Language = javascript ]
Callback invoked when a document is being saved.
clientmethod onDocumentSaveComplete(contentModified) [ Language = javascript ]
Callback method invoked after we successfully save the current document.
clientmethod onloadHandler() [ Language = javascript ]
Add check to ensure that we correctly load documents on the client when source control hooks are in use.
clientmethod reloadDocument() [ Language = javascript ]
Reload the current document.
Returns a boolean to indicate whether a full page reload has been triggered.
clientmethod saveDocument(force) [ Language = javascript ]
Save the current document using the correct source control hooks.
clientmethod setReadOnly(readOnly) [ Language = javascript ]
Set readOnly to the value of readOnly.
Subclasses MUST implement this method to update the controls on the page
so that the page's behaviour actually matches the value of the readOnly flag.
clientmethod setSCProject(newProject) [ Language = javascript ]
Notify the server that a specific project has been chosen.
clientmethod showSCMenu() [ Language = javascript ]
Display the source control menu based on the contents of the _sourceControlMenu data
created by UpdateSCMenu()().
clientmethod showSCOutput() [ Language = javascript ]
Open a popup to display the current source control output.
clientmethod textControlKeyDown(zenControl) [ Language = javascript ]
Key handler to record the value of text fields before the keyboard event is processed.
Works in conjunction with textControlKeyUp()() to determine whether any text
fields are modified.
clientmethod textControlKeyUp(event, zenControl) [ Language = javascript ]
Key handler to work out whether user keys entered in controls have
changed the content of the text field. This is to deal with situations
where the onchange event for a text control is only triggered after the onmousedown
event for another shape has already occurred.
clientmethod updateDocumentState(alertOnReadOnly) [ Language = javascript ]
Helper method to ensure that the readOnly and
readOnlyReason properties are up to date on the client,
and that the user knows about any change that has rendered the document read only.
clientmethod updateSCIndicator(haveOutput) [ Language = javascript ]
Toggle the display of the star which indicates whether new
source control output is available.