Sunday, November 25, 2012

CDC Software Pivotal CRM 6.0: Using Pivotal Input Dialog.


Pivotal Input Dialog may be useful if you want to ask user some input parameters without creating a new client form.
I didn't find any documentation about how exactly to use Pivotal Input Dialog.
So I'm going to publish some code examples here how to use it.

Required dlls:

Pivotal.Engine.Client.Services.Interfaces.dll
Pivotal.Engine.UI.DataTypes.dll

// Get input dialog service
IInputDialogService inputDialogService = ClientContext.ClientAPIService.GetService<IInputDialogService>();
DialogParam dialogParameter = new DialogParam();
dialogParameter.FormParams = new CdcSoftware.Pivotal.Engine.UI.DataTypes.FormParams.InputParamsCollection();

// 1. Foreign Key
Table companyTable = this.SystemClient.UserProfile.GetMetaItem<Table>("Company");
InputParam foreignKeyInputParam = new InputParam()
{
    Label = "Company",
    Type = InputParamType.RForeignField,
    IsRequired = true,
    Enums = companyTable.Id
};
dialogParameter.FormParams.Add(foreignKeyInputParam);

// 2. Single value fields: Date, Boolean, Integer, Double and etc
InputParam dateInputParam = new InputParam() { Label = "Date", Type = InputParamType.Date };
dialogParameter.FormParams.Add(dateInputParam);

InputParam boolInputParam = new InputParam() { Label = "Boolean", Type = InputParamType.Boolean };
dialogParameter.FormParams.Add(boolInputParam);

InputParam intInputParam = new InputParam() { Label = "Integer", Type = InputParamType.Integer };
dialogParameter.FormParams.Add(intInputParam);

// 2. Combo, ListBox
object[] comboValues = new object[] { "value 1", "value 2" };
InputParam comboInputParam = new InputParam() { Label = "Date", Type = InputParamType.RCombo, Enums = comboValues };
dialogParameter.FormParams.Add(comboInputParam);

// Set dialog type
dialogParameter.DialogType = ModalDialogTypeEnum.modalDialogParamsAndDescription;

// Show dialog
inputDialogService.ShowDialog(dialogParameter, "Title");

// Get parameter values
if (foreignKeyInputParam.Value != null)
{
    Id companyId = Id.Create(foreignKeyInputParam.Value);
}

if (intInputParam.Value != null)
{
    int intValue = TypeConvert.ToInt32(intInputParam.Value);
}
You can discover other input parameters types by yourself.

Sunday, August 5, 2012

CDC Software Pivotal CRM 6.0: How to get acces to SearchView.SearchData.ResultsViewControl control.

We can't modify SearchView.SearchData.ResultsViewControl in a usual way because it has an internal get accessor.
But we can use reflection.

Here is an example how to change SearchView rows text color deppending on received data.

1. Add the following dll references to your project:
  • Pivotal.CommonControls.dll
  • CdcSoftware.Ios.UI.dll

2. Register "OnSearchCompleted" notification event handler:
[NotificationEvent("OnSearchCompleted", Table = "Support_Incident")]
public void OnSupportIncidentSearchCompleted(object notifyParams)
{
 ...
}

3. Get DataGridView control via reflection.
CdcSoftware.Pivotal.CommonControls.ResultsViewControl resultsViewControl = searchView.SearchData.GetType().GetProperty("ResultsViewControl").GetValue(searchView.SearchData, null) as CdcSoftware.Pivotal.CommonControls.ResultsViewControl;
if (resultsViewControl != null)
{
CdcSoftware.Pivotal.CommonControls.PivotalDataGridView dataGridView = resultsViewControl.GetType().GetField("_dataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(resultsViewControl) as CdcSoftware.Pivotal.CommonControls.PivotalDataGridView;
}

4. Modify you want.

The full code example:
[NotificationEvent("OnSearchCompleted", Table = "Support_Incident")]
        public void OnSupportIncidentSearchCompleted(object notifyParams)
        {
            ISearchView searchView = ClientContext.ClientAPIService.GetActiveContentObject() as ISearchView;
            if (searchView != null)
            {
                //Get ResultsViewControl
                CdcSoftware.Pivotal.CommonControls.ResultsViewControl resultsViewControl = searchView.SearchData.GetType().GetProperty("ResultsViewControl").GetValue(searchView.SearchData, null) as CdcSoftware.Pivotal.CommonControls.ResultsViewControl;

                if (resultsViewControl != null)
                {
                    //Get DataGridView control
                    CdcSoftware.Pivotal.CommonControls.PivotalDataGridView dataGridView = resultsViewControl.GetType().GetField("_dataGridView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(resultsViewControl) as CdcSoftware.Pivotal.CommonControls.PivotalDataGridView;
                    
                    //Attach RowPostPaint event
                    dataGridView.RowPostPaint += new DataGridViewRowPostPaintEventHandler((object sender, DataGridViewRowPostPaintEventArgs e) =>
                    {
                        CdcSoftware.Pivotal.CommonControls.PivotalDataGridView pivotalDataGridView = sender as CdcSoftware.Pivotal.CommonControls.PivotalDataGridView;
                        if (dataGridView.Columns.Contains("Status_Id@Rn_Descriptor"))
                        {
                            //Color closed incidents
                            string columnTextValue = Convert.ToString(pivotalDataGridView.Rows[e.RowIndex].Cells["Status_Id@Rn_Descriptor"].Value);
                            if (columnTextValue.Contains("Closed"))
                            {
                                pivotalDataGridView.Rows[e.RowIndex].DefaultCellStyle.ForeColor = System.Drawing.Color.Red;
                            }
                        }
                    });
                }
            }
        }

Regards,
Max Shafranski

Wednesday, August 1, 2012

Another way to preview reports and other file types in Pivotal Client.

Another trivial way to display reports and other file types saved in database in Pivotal Client.

Scenario: display report as PDF file in Pivotal Client by pressing Task Pad item.

Client Task (click event handler):
// Get file content from server
byte[] fileContent = Globals.SystemClient.ExecuteServerTask("Server Task Name", "GetReportContent", new Type[] { typeof(Id) }, new object[] { recordId }) as byte[];

// Create temp file name
string fileName = String.Format("{0}.{1}", Guid.NewGuid(), ".pdf");
string tempFilePath = Path.Combine(System.IO.Path.GetTempPath(), fileName);

using (MemoryStream stream = new MemoryStream(fileContent))
{
 using(FileStream fileStream = new FileStream(tempFilePath, FileMode.Create, System.IO.FileAccess.Write))
 {
  stream.WriteTo(fileStream);
  fileStream.Flush();
  fileStream.Close();
    
  // Open file using windows shell
  Process.Start(tempFilePath);
 }
}
Server Task:
[TaskExecute]
public byte[] GetReportContent(Id recordId)
{
 try
 {
  SystemReport report = this.SystemServer.GetMetaItem<SystemReport>("Report Name") as SystemReport;
  ReportRunner reportRunner = this.SystemServer.CreateReportRunner(report);
  reportRunner.ReportOutputFormat = ReportOutputFormat.Pdf;
  return reportRunner.Run(ReportFilter.SingleRow, recordId, null);
 }
 catch (Exception ex)
 {
  throw new PivotalApplicationCoreException(ex.Message, ex);
 }
}

How to send emails with styles and embedded images using Pivotal API.

A lot of work.
A lot of projects.
But I've got some free time for Pivotal.

Here is an example how to send formatted emails with styles and embedded images via Pivotal API:

Server Task code:
CdcSoftware.Pivotal.Engine.Mail.EmailMessage emailMessage =
   this.SystemServer.CreateMessage();
emailMessage.To.Add("myemail@email.com");
emailMessage.MimeHtmlBodyFileName = @"C:\Email.htm";
emailMessage.Subject = "Test";
emailMessage.Body = "";
emailMessage.Send();

Email.htm file content:
<html>
 <head>
  <style type="text/css">
   body { 
    background-color:Green;
    font-size: 3em;
   }
  </style>
 </head>
<body>
 Test email:
 <img src="image.jpg"/>
</body>
</html>

Of course, you can save html email templates in database, retrieve their content, save as temp file and then use the code above.
Also it is recommended to use SP 10 or later.

Tuesday, March 27, 2012

Using custom grids in Client Forms.

Sometimes we need to build our custom grid to display/manipulate different data.
We can use a standart DataGridView control from System.Windows.Forms.dll, but it doesn't match to Pivotal color scheme.
Therefore there is DataGridViewWithStyle pivotal control in CdcSoftware.Ios.UI.dll that looks like a common Pivotal secondary control.

Here is an example how to use it:

1. Add PivotalCustomControlContainer to a client form
2. Write some client code in form client task:

// Get container control
PivotalCustomControlContainer customGridContainer = this.FormControl.GetControlByName("CustomGridContainer") as PivotalCustomControlContainer;

// Declare custom grid properties and columns
DataGridViewWithStyle customGrid = new DataGridViewWithStyle();
customGrid.Dock = DockStyle.Fill;
customGrid.AllowUserToAddRows = false;
customGrid.AllowUserToDeleteRows = false;
customGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
customGrid.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Id", HeaderText = "Id", Visible = false });
customGrid.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Name", HeaderText = "Name", ReadOnly = true });
customGrid.Columns.Add(new DataGridViewTextBoxColumn() { Name = "Age", HeaderText = "Age", ReadOnly = true });

// Add custom grid to the container
customGridContainer.CustomControl = customGrid;

// Populate grid data
this.PopulateGrid(customGrid);

Thats all.

Regards,
Max Shafranski

Sunday, March 25, 2012

Pivotal CRM 6.0.10 Hot Fix 1 is released.

At last I found free time to blog some good news :)
We got Hot Fix 1 for Pivotal CRM 6.0.10 that brings us many features and bugs fixes.

New features:

  • Pivotal Thin Client support (The most powerful CRM web client).
  • OnFormNavigateAway - form event handler method to execute business logic before navigating away from a form.
  • GetMessageFileWithAttachments - New connector API.

And many bugs were fixed.

Regards,
Max Shafranski