So, continue the work:). Part 1 is here.
Part 2 сreate page, graph, DAC class extension and xml page for mobile
First of all, In project I create folder "DAC" and add two clasess:
- ActivityTypes.cs
This class need to filter types rows from table CRActivity(column name - Type). Client asked display all events for that Business Account of type "Phone Call", "Client Visit" and "Futile Visit" So for this I do next:

This constant types I will use in graph when will select all from table CRActivity.
2. CRActivityExtension.cs
This class need for correct show "Body"(Comments) from table CRActivity. Some fields include html tags. To show clear text I do next:
public class CRActivityExt : PXCacheExtension<CRActivity>
{
public abstract class bodyWithoutHtml : IBqlField, IBqlOperand
{
}
[PXUIField(DisplayName = "Activity Details")]
[PXString(IsUnicode = true)]
public virtual string BodyWithoutHtml { get; set; }
public abstract class usrBodyWithoutHtml : IBqlField, IBqlOperand
{
}
[PXUIField(DisplayName = "Activity Details Without Html")]
[PXDBString(IsUnicode = true)]
public virtual string UsrBodyWithoutHtml { get; set; }
}
Please pay attention that for string - UsrBodyWithoutHtml I use PXDBString atrribute, it`s mean that field will be in database CRActivity. This field is necessary for mobile application. I don't know why, but mobile application weren't able to display field that was created dynamically.
Next step - create graph , .aspx page and mobile site map:
1. ActivitiesMaint.cs
#region Selector
[PXViewName(PX.Objects.CR.Messages.BAccount)]
public PXSelect<BAccount,
Where2<Match<Current<AccessInfo.userName>>,
And<Where<BAccount.type, Equal<BAccountType.customerType>,
Or<BAccount.type, Equal<BAccountType.prospectType>,
Or<BAccount.type, Equal<BAccountType.combinedType>,
Or<BAccount.type, Equal<BAccountType.vendorType>>>>>>>>
BAccount;
public PXSelect<CRActivity,
Where2<Where<CRActivity.bAccountID, Equal<Current<BAccount.bAccountID>>>,
And<Where<CRActivity.type, Equal<ActivityTypes.fType>,
Or<CRActivity.type, Equal<ActivityTypes.mType>,
Or<CRActivity.type, Equal<ActivityTypes.pType>>>>>>,
OrderBy<Desc<CRActivity.startDate>>> Activities;
protected IEnumerable activities()
{
var result = new PXSelect<CRActivity,
Where2<Where<CRActivity.bAccountID, Equal<Current<BAccount.bAccountID>>>,
And<Where<CRActivity.type, Equal<ActivityTypes.fType>,
Or<CRActivity.type, Equal<ActivityTypes.mType>,
Or<CRActivity.type, Equal<ActivityTypes.pType>>>>>>,
OrderBy<Desc<CRActivity.startDate>>>(this).Select();
foreach (PXResult<CRActivity> boxedActivity in result)
{
var activity = boxedActivity.GetItem<CRActivity>();
string cutted = StripTagsCharArray(activity.Body);
PXDatabase.Update<CRActivity>(
new PXDataFieldRestrict<CRActivity.noteID>(activity.NoteID),
new PXDataFieldAssign<CRActivityExt.usrBodyWithoutHtml>(cutted)
);
}
var result2 = new PXSelectReadonly<CRActivity,
Where2<Where<CRActivity.bAccountID, Equal<Current<BAccount.bAccountID>>>,
And<Where<CRActivity.type, Equal<ActivityTypes.fType>,
Or<CRActivity.type, Equal<ActivityTypes.mType>,
Or<CRActivity.type, Equal<ActivityTypes.pType>>>>>>,
OrderBy<Desc<CRActivity.startDate>>>(this).Select();
return result2;
}
#endregion
#region ClearHtml
public static string StripTagsCharArray(string source)
{
string result2 = "";
if (source == null)
{
source = "";
}
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(source);
if (htmlDoc.ParseErrors != null && htmlDoc.ParseErrors.Count() > 0)
{
// Handle any parse errors as required
result2 = "Text not correct";
}
else
{
if (htmlDoc.DocumentNode != null)
{
HtmlAgilityPack.HtmlNode bodyNode = htmlDoc.DocumentNode.SelectSingleNode("//body");
if (bodyNode != null)
{
result2 = htmlDoc.DocumentNode.SelectSingleNode("//body").InnerText;
}
else
{
result2 = source;
}
}
}
return result2;
}
}
#endregion
Here I use 2 standart PXSelect from tables BAcount and CRActivity, and my IEnumerable method where I change text - strip html tags (StripTagsCharArray), and also use PXDatabase.Update for write text to column "UsrBodyWithoutHtml".
About this(PXDatabase.Update, PXDataFieldRestrict<>, Where2) and how it work read in my blog.
One more interesting part is Method StripTagsCharArray. That method uses external library HtmlAgilityPack in order to strip html tags from text.
2. AC601000.aspx page
After I go to web site and in folder Page create new folder "AC". In this folder I copy and paste structure of another .aspx page (becouse .aspx page include .aspx.cs file), rename to "AC601000" (Screenshot 6).
