468 lines
23 KiB
VB.net
468 lines
23 KiB
VB.net
Imports System
|
|
Imports System.Collections.Generic
|
|
Imports System.Text
|
|
|
|
Imports AyaNova.PlugIn
|
|
'Required Plugin interface definition
|
|
Imports GZTW.AyaNova.BLL
|
|
'Required to interact with the business object library
|
|
Imports System.Drawing
|
|
'Required for icon and image handling even if you don't use them
|
|
Imports System.Windows.Forms
|
|
'Required only if you want a Windows Forms UI for your plugin
|
|
Namespace VBSamplePlugin
|
|
''' <summary>
|
|
''' This is an example to show the minimal required code to implement a plugin
|
|
''' with a UI
|
|
'''
|
|
''' Your class must implement IAyaNovaPlugin defined in AyaNova.PlugIn.dll
|
|
'''
|
|
''' References that were added
|
|
''' --------------------------
|
|
''' From the AyaNova program file directory:
|
|
''' AyaNova.PlugIn.dll - Required plugin interface definition
|
|
''' GZTW.AyaNova.BLL.dll - Required AyaNova business object library fully documented here: http://api.ayanova.com/
|
|
''' CSLA - required by the business object library
|
|
''' CSLA.Core.Bindablebase- required by the business object library
|
|
''' CSLA.Server.DataPortal- required by the business object library
|
|
''' CSLA.Server.ServicedDataPortal- required by the business object library
|
|
'''
|
|
''' System.Windows.Forms - Required only if your plugin requires a windows user interface
|
|
''' --------------------------
|
|
'''
|
|
''' Distributing your plugin
|
|
''' =-=-=-=-=-=-=-=-=-=-=-=-
|
|
''' Note that *none* of the above referenced assemblies need to be included with your plugin when it is distributed
|
|
''' as, at runtime, your plugin will use the assemblies installed with AyaNova.
|
|
'''
|
|
''' So, for example, this sample plugin will generate a file called CSSamplePlugin.dll.
|
|
''' To use it in AyaNova, copy that single file anywhere in the plugins folder or in a subdirectory beneath (recommended)
|
|
''' in the AyaNova program files folder.
|
|
'''
|
|
''' AyaNova will look for any files in the plugins folder and subfolders that end in .dll and check if they implement IAyaNovaPlugin
|
|
'''
|
|
''' If your plugin needs to persist data please note that the AyaNova business object library contains three objects for exactly that purpose
|
|
''' you can use the "Integration" object to store overall data, you can use the IntegrationMaps object to map data between an external programs database
|
|
''' and specific AyaNova objects and the IntegrationLog object is provided for logging purposes.
|
|
'''
|
|
''' </summary>
|
|
Public Class Class1
|
|
Implements IAyaNovaPlugin
|
|
|
|
|
|
#Region "Properties / general"
|
|
|
|
'OPTIONAL: Currently unused in AyaNova UI but may be in future
|
|
'so you really should return a string here
|
|
Public ReadOnly Property About() As String Implements IAyaNovaPlugin.About
|
|
Get
|
|
Return "My plugin, copyright my company 2009 etc etc"
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' REQUIRED: This must be a unique Guid value and is required.
|
|
'''
|
|
''' Normally you would not change this value even upon new releases of your
|
|
''' plugin, it's simply used to uniquely identify the plugin during runtime by
|
|
''' AyaNova.
|
|
'''
|
|
''' (do not use Guid.Empty and don't use the sample value provided here
|
|
''' that's just asking for trouble :) )
|
|
''' </summary>
|
|
Public ReadOnly Property PluginID() As Guid Implements IAyaNovaPlugin.PluginID
|
|
Get
|
|
Return New Guid("{20D02B14-664E-4174-AA35-EBEE2972FD80}")
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' REQUIRED: Will be displayed in various areas but most importantly
|
|
''' it's used to display the menu item in the root level Plugin menu
|
|
''' for activating your plugin
|
|
''' </summary>
|
|
Public ReadOnly Property PluginName() As String Implements IAyaNovaPlugin.PluginName
|
|
Get
|
|
Return "My VB.NET Plugin"
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' REQUIRED: Your plugin's version as a string
|
|
''' for display only
|
|
''' </summary>
|
|
Public ReadOnly Property PluginVersion() As String Implements IAyaNovaPlugin.PluginVersion
|
|
Get
|
|
Return "1.0alpha"
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' OPTIONAL: 32px icon that will be displayed beside the plugin name
|
|
''' on the root level plugin menu if the AyaNova User has chosen Large
|
|
''' icons on menus
|
|
''' </summary>
|
|
Public ReadOnly Property PluginLargeIcon() As System.Drawing.Image Implements IAyaNovaPlugin.PluginLargeIcon
|
|
'since this is meant to be a simple example
|
|
'we'll return null, but generally speaking you would
|
|
'add a resource to your plugin and embed your icons inside it
|
|
'and return them here like: return Resource.MyIcon;
|
|
Get
|
|
Return Nothing
|
|
End Get
|
|
End Property
|
|
|
|
|
|
|
|
''' <summary>
|
|
''' OPTIONAL: 16px icon that will be displayed beside the plugin name
|
|
''' on the root level plugin menu if the AyaNova User has chosen Small
|
|
''' icons on menus
|
|
''' </summary>
|
|
Public ReadOnly Property PluginSmallIcon() As System.Drawing.Image Implements IAyaNovaPlugin.PluginSmallIcon
|
|
Get
|
|
Return Nothing
|
|
End Get
|
|
End Property
|
|
|
|
|
|
|
|
''' <summary>
|
|
''' OPTIONAL: This will be set by AyaNova when the plugin is initialized
|
|
''' the resource manager contains the same icons and images used
|
|
''' in AyaNova itself and is useful for consistency if you want
|
|
''' your plugin's GUI to appear more integrated with AyaNova
|
|
''' </summary>
|
|
Public WriteOnly Property AyaNovaResourceManager() As System.Resources.ResourceManager Implements IAyaNovaPlugin.AyaNovaResourceManager
|
|
'Since this is a simple example, we'll ignore it when set.
|
|
'However if you wish to use it
|
|
'you can set a class variable (for example "resman") of ResourceManger to the value passed in here
|
|
'and get resources like this:
|
|
'Image i=(Image)resman.GetObject("ServiceWorkorder24");
|
|
'or
|
|
'Icon i=(Icon)resman.GetObject("Client16icon");
|
|
Set(ByVal value As System.Resources.ResourceManager)
|
|
|
|
|
|
End Set
|
|
End Property
|
|
#End Region
|
|
|
|
#Region "Initialize and close"
|
|
|
|
'this is a convenient way to deal with supported object types
|
|
Private Shared ObjectsWeCanDealWith As List(Of RootObjectTypes) = Nothing
|
|
|
|
''' <summary>
|
|
''' OPTIONAL: you don't need to do anything here, but it's a good idea.
|
|
'''
|
|
''' This is called immediately after login and is the first opportunity your plugin gets access to the business object library
|
|
''' to determine if it's prepared to work with the current AyaNova user / database / conditions
|
|
''' it finds itself in.
|
|
'''
|
|
''' Note that this is called for all plugins found, be a good citizen and don't consume a lot of time here
|
|
''' as it will block AyaNova between the moment the user has clicked login and they get the opening screen.
|
|
'''
|
|
''' Instead you should do "lazy" initialization; as late as possible, ideally only just in time to perform a user selected command
|
|
''' and cache your intialization when it's done.
|
|
'''
|
|
''' If you are familiar with using the AyaNova business object library you can treat a plugin as
|
|
''' all the code that takes place immediately after a user has initialized the AyaNova connection and logged in successfully.
|
|
'''
|
|
''' </summary>
|
|
''' <param name="AyaNovaVersion">The version of AyaNova calling</param>
|
|
''' <param name="localizedText">A localized text object if your plugin wants to
|
|
''' use the same localized text as AyaNova itself</param>
|
|
''' <returns>False if you don't want your plugin to be accessible, true if you do</returns>
|
|
Public Function Initialize(ByVal AyaNovaVersion As Version, ByVal localizedText As GZTW.AyaNova.BLL.LocalizedTextTable) As Boolean Implements IAyaNovaPlugin.Initialize
|
|
'This is a good place to check if the version of AyaNova being used is one you want your plugin to work
|
|
'with:
|
|
'if (AyaNovaVersion.Major != 5)
|
|
'{
|
|
' MessageBox.Show("My Plugin requires AyaNova version 5");
|
|
' return false;
|
|
'}
|
|
|
|
'or that the current user has sufficent rights to even use your plugin
|
|
'if(AyaBizUtils.Right(RootObjectTypes.Client)< (int)SecurityLevelTypes.ReadWrite) return false;
|
|
|
|
'or that the user is the right type to use your plugin
|
|
'if(!User.IsAdmin) return false;
|
|
|
|
'or that the environment your plugin finds itself in is suitable
|
|
'or that there is a license for your plugin if it's licensed
|
|
'etc
|
|
|
|
'This is also an excellent time to build a list of AyaNova RootObjectTypes your plugin supports:
|
|
|
|
'remember: Initialize might be called more than once if a user logs in and out
|
|
If ObjectsWeCanDealWith Is Nothing Then
|
|
ObjectsWeCanDealWith = New List(Of RootObjectTypes)()
|
|
End If
|
|
|
|
If ObjectsWeCanDealWith.Count = 0 Then
|
|
'AyaNova asks if a plugin can deal with the type Nothing
|
|
'when it's about to display the Plugins menu option in the main AyaNova screen
|
|
|
|
'This is useful for plugins that have commands that are not specific to a particular
|
|
'type of object such as an About dialog or a general setup form or a utility that
|
|
'acts in general on multiple AyaNova objects
|
|
'for this example we'll have an About dialog that we want to display from the main AyaNova form
|
|
ObjectsWeCanDealWith.Add(RootObjectTypes.[Nothing])
|
|
|
|
'For this example we want to deal with Client objects
|
|
ObjectsWeCanDealWith.Add(RootObjectTypes.Client)
|
|
End If
|
|
Return True
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' OPTIONAL: This is called after a user has just logged out of AyaNova.
|
|
''' Note that this is often when they are closing AyaNova, but not necessarily, they may
|
|
''' have logged out so another user can login.
|
|
'''
|
|
''' This is where you can release resources that are user specific if you have any.
|
|
'''
|
|
''' </summary>
|
|
Public Sub Close() Implements IAyaNovaPlugin.Close
|
|
|
|
End Sub
|
|
#End Region
|
|
|
|
#Region "Whether to particpate in a particular scenario"
|
|
|
|
'Note: these methods exist for the purposes of lazy initialization
|
|
'just because your plugin can deal with a particular type of object
|
|
'doesn't mean you have to necessarily do a time consuming startup for your
|
|
'plugin yet because the user may not select your plugin from the plugin list
|
|
'(99.9% of the time they are just opening a form to work in AyaNova)
|
|
|
|
|
|
''' <summary>
|
|
''' This is called by AyaNova when a single object is about to be opened in AyaNova
|
|
''' Here is where you decide if you support that type of object
|
|
''' or not.
|
|
'''
|
|
''' </summary>
|
|
''' <param name="objectType">The RootObjectTypes AyaNova object type</param>
|
|
''' <returns>true - display this plugin in the plugins menu, false - don't display this plugin as an option</returns>
|
|
Public Function SingleObjectMenuShow(ByVal objectType As GZTW.AyaNova.BLL.RootObjectTypes) As Boolean Implements IAyaNovaPlugin.SingleObjectMenuShow
|
|
'You could have a giant switch statement here but it's easier to just check a collection
|
|
Return ObjectsWeCanDealWith.Contains(objectType)
|
|
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' This is called by AyaNova when a list object is about to be opened in AyaNova
|
|
''' generally in a grid.
|
|
'''
|
|
''' Here is where you decide if you support that type of object
|
|
''' or not in multiples.
|
|
'''
|
|
''' </summary>
|
|
''' <param name="objectType">The RootObjectTypes AyaNova object type</param>
|
|
''' <returns>true - display this plugin in the plugins menu, false - don't display this plugin as an option</returns>
|
|
Public Function MultipleObjectsMenuShow(ByVal objectType As GZTW.AyaNova.BLL.RootObjectTypes) As Boolean Implements IAyaNovaPlugin.MultipleObjectsMenuShow
|
|
'for this example we'll deal with a selected list of client objects
|
|
'from the Clients grid display
|
|
Return ObjectsWeCanDealWith.Contains(objectType)
|
|
End Function
|
|
#End Region
|
|
|
|
#Region "What options to display"
|
|
'These methods are called when a user selects your plugin from the plugin menu
|
|
'they are used to build the popup menu of options your plugin supports
|
|
'If possible you should still defer initialization if it's time consuming
|
|
'even at this point if possible because the user may not actually select an option
|
|
'they may have just clicked on it in error or to see what's offered
|
|
|
|
''' <summary>
|
|
''' Here is where you provide a list of commands your plugin supports for the object type
|
|
''' (and possibly even the exact object) in question.
|
|
'''
|
|
''' The items you provide here will be displayed to the end user in a popup menu list immediately after
|
|
''' they have selected your plugin from the root plugins menu in a form in AyaNova where a single object
|
|
''' is being viewed / edited
|
|
''' </summary>
|
|
''' <param name="objectType">RootObjectType</param>
|
|
''' <param name="ayaNovaObject">A generic list of a type defined in AyaNova.PlugIn</param>
|
|
''' <returns></returns>
|
|
Public Function SingleObjectMenuOptions(ByVal objectType As GZTW.AyaNova.BLL.RootObjectTypes, ByVal ayaNovaObject As Object) As System.Collections.Generic.List(Of AyaNova.PlugIn.AyaNovaPluginMenuItem) Implements AyaNova.PlugIn.IAyaNovaPlugin.SingleObjectMenuOptions
|
|
|
|
'First off we can double check that this is an object type we support:
|
|
If Not ObjectsWeCanDealWith.Contains(objectType) Then
|
|
Return Nothing
|
|
End If
|
|
'Now we build the list:
|
|
'AyaNovaPluginMenuItem is a structure defined in AyaNova.PlugIn assembly
|
|
'and is the mechanism to convey your menu options to AyaNova so it
|
|
'can use them to build a popup menu
|
|
|
|
'Initialize a list of potential menu items
|
|
Dim list As New List(Of AyaNovaPluginMenuItem)()
|
|
|
|
'Add items to the list based on the object type
|
|
Select Case objectType
|
|
Case RootObjectTypes.[Nothing]
|
|
'Our main menu about box
|
|
list.Add(New AyaNovaPluginMenuItem("ABOUT", "About MyPlugin", Nothing, Nothing))
|
|
Exit Select
|
|
Case RootObjectTypes.Client
|
|
'Our command when in a single client editing form
|
|
list.Add(New AyaNovaPluginMenuItem("CLIENT_DO_SOMETHING", "Do something with this client", Nothing, Nothing))
|
|
Exit Select
|
|
End Select
|
|
Return list
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Same as single item, but the menu above a grid or list of AyaNova objects of the same type
|
|
''' If your plugin can't deal with a list of items then return null;
|
|
''' </summary>
|
|
''' <param name="objectType"></param>
|
|
''' <returns></returns>
|
|
Public Function MultipleObjectsMenuOptions(ByVal objectType As GZTW.AyaNova.BLL.RootObjectTypes) As System.Collections.Generic.List(Of AyaNova.PlugIn.AyaNovaPluginMenuItem) Implements AyaNova.PlugIn.IAyaNovaPlugin.MultipleObjectsMenuOptions
|
|
'First off we can double check that this is an object type we support:
|
|
If Not ObjectsWeCanDealWith.Contains(objectType) Then
|
|
Return Nothing
|
|
End If
|
|
|
|
'Initialize a list of potential menu items
|
|
Dim list As New List(Of AyaNovaPluginMenuItem)()
|
|
|
|
'Add items to the list based on the object type
|
|
Select Case objectType
|
|
Case RootObjectTypes.Client
|
|
'Our command when in a list of clients
|
|
list.Add(New AyaNovaPluginMenuItem("CLIENT_DO_SOMETHING", "Do something else with the selected Clients", Nothing, Nothing))
|
|
Exit Select
|
|
End Select
|
|
Return list
|
|
End Function
|
|
|
|
|
|
#End Region
|
|
|
|
#Region "Execute the chosen command"
|
|
'These methods are called when a user actually clicks on a command for your plugin from the popup menu
|
|
'This is the ideal place to do time consuming initialization if necessary and cache it for later
|
|
'because this is the first point you know the user actually needs to use your plugin
|
|
|
|
''' <summary>
|
|
''' A command was selected for a single object
|
|
''' </summary>
|
|
''' <param name="commandKey">command key you provided when you built the menu options list</param>
|
|
''' <param name="objectType">the type of the object</param>
|
|
''' <param name="ayaNovaObject">a pointer to the live object being edited or displayed</param>
|
|
Public Sub CommandSelectedForSingleObject(ByVal commandKey As String, ByVal objectType As GZTW.AyaNova.BLL.RootObjectTypes, ByVal ayaNovaObject As Object) Implements IAyaNovaPlugin.CommandSelectedForSingleObject
|
|
|
|
|
|
'Since we have used unique commands we don't need to double check the
|
|
'object type here
|
|
|
|
Select Case commandKey
|
|
Case "ABOUT"
|
|
Dim dlgAbout As New AboutBox1()
|
|
dlgAbout.ShowDialog()
|
|
Exit Select
|
|
|
|
Case "CLIENT_DO_SOMETHING"
|
|
'We want to do something with the client being edited
|
|
'we have the object in ayaNovaObject so we just need to cast it to
|
|
'the type of object we expect.
|
|
|
|
'let's do it defensively though; who knows what those crazy AyaNova programmers might have passed to us ;) ...
|
|
|
|
'Is it null for some reason?
|
|
If ayaNovaObject Is Nothing Then
|
|
Exit Sub
|
|
End If
|
|
'Yes so ignore the command
|
|
'Is it not the type of object we expected?
|
|
If Not (TypeOf ayaNovaObject Is GZTW.AyaNova.BLL.Client) Then
|
|
Exit Sub
|
|
End If
|
|
|
|
'Ok, seems safe to deal with so let's get a reference to it we can work with
|
|
'directly:
|
|
|
|
Dim c As GZTW.AyaNova.BLL.Client = DirectCast(ayaNovaObject, GZTW.AyaNova.BLL.Client)
|
|
|
|
'Now we can operate on it using any of the Client object method's and properties
|
|
'in the AyaNova business object API (http://api.ayanova.com/)
|
|
|
|
c.Notes = (((c.Notes & vbCr & vbLf & "Hello ") + c.Name & " from ") + PluginName & " @ ") + DateTime.Now.ToString()
|
|
|
|
'You will notice that after your plugin exits the client's "General Notes" are immediately updated
|
|
'in the AyaNova user interface, this is because your plugin is working with the live object
|
|
'that is bound to the AyaNova edit form controls so changes are immediate.
|
|
|
|
'NOTE: do not Save or Update a business object you modify here. Leave the regular AyaNova UI to deal with that
|
|
'properly.
|
|
|
|
|
|
|
|
Exit Select
|
|
|
|
End Select
|
|
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' A command was selected for a list of objects
|
|
''' </summary>
|
|
''' <param name="commandKey">Your plugins command key from the menu item</param>
|
|
''' <param name="objectType">The RootObjectTypes object type</param>
|
|
''' <param name="objectIDList">A list of Guid's of the AyaNova object type selected by the user. May be empty or null or zero selected.</param>
|
|
''' <param name="listObject">The unederlying AyaNova List object that is being displayed to the user from which they made their selections</param>
|
|
''' <returns>true if you want to trigger a refresh of the display of the list in AyaNova, false if not necessary (i.e. you didn't modify any of the objects displayed)</returns>
|
|
Public Function CommandSelectedForList(ByVal commandKey As String, ByVal objectType As GZTW.AyaNova.BLL.RootObjectTypes, ByVal objectIDList As List(Of Guid), ByVal listObject As Object) As Boolean Implements IAyaNovaPlugin.CommandSelectedForList
|
|
'We only have one command that could display for a list but we'll leave room for expansion later:
|
|
Select Case commandKey
|
|
Case "CLIENT_DO_SOMETHING"
|
|
'We want to do something with all the clients that were selected from the client list
|
|
|
|
'We let's see if any are selected first
|
|
If objectIDList Is Nothing OrElse objectIDList.Count = 0 Then
|
|
MessageBox.Show("Nothing to do, you didn't select any clients.")
|
|
Return False
|
|
End If
|
|
|
|
'Ok, we now know that 1 or more clients are selected and we have a list of their ID's
|
|
'so let's do something (non destructive) with them
|
|
Dim sb As System.Text.StringBuilder = New StringBuilder()
|
|
sb.Append("Selected clients website and email address" & vbCr & vbLf)
|
|
For Each id As Guid In objectIDList
|
|
'You don't want your plugin to crash right?
|
|
'use appropriate exception handling
|
|
Try
|
|
Dim c As Client = Client.GetItem(id)
|
|
|
|
sb.Append(c.Name)
|
|
sb.Append(" Email: ")
|
|
sb.Append(c.Email)
|
|
sb.Append(" Website: ")
|
|
sb.Append(c.WebAddress)
|
|
sb.Append(vbCr & vbLf)
|
|
Catch ex As Exception
|
|
sb.Append("Client ID: ")
|
|
sb.Append(id.ToString())
|
|
sb.Append(" Error: ")
|
|
sb.Append(ex.Message)
|
|
sb.Append(vbCr & vbLf)
|
|
End Try
|
|
Next
|
|
|
|
MessageBox.Show(sb.ToString())
|
|
|
|
Exit Select
|
|
|
|
End Select
|
|
|
|
Return False
|
|
End Function
|
|
#End Region
|
|
|
|
End Class
|
|
|
|
End Namespace |