Files
ayanova7/source/Plugins/AyaNova.Plugin.V8/V8.cs
2020-05-02 15:05:54 +00:00

1834 lines
67 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using AyaNova.PlugIn;
using GZTW.AyaNova.BLL;
using System.IO;
using System.IO.Compression;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
//using HtmlAgilityPack;
//using ReverseMarkdown;
namespace AyaNova.PlugIn.V8
{
class V8 : IAyaNovaPlugin
{
#region Plugin interface
System.Resources.ResourceManager resman = null;
private static List<RootObjectTypes> ObjectsWeCanDealWith = null;
public string PluginName
{
get { return "Export to V8"; }
}
public string PluginVersion
{
get { return "7.6 (patch 3)"; }
}
public string About
{
get
{
return "AyaNova V8 export plugin\r\n" +
"Built " + AyaNova.PlugIn.V8.Timestamp.BuildAt.ToString() + "\r\n" +
"Copyright 2020 Ground Zero Tech-Works Inc.";
}
}
public Guid PluginID
{
get { return new Guid("{73D7B77F-C96A-4198-9449-6529AFB6AA5B}"); }
}
public System.Drawing.Image PluginSmallIcon
{
get { return Resource1.Dump16; }
}
public System.Drawing.Image PluginLargeIcon
{
get { return Resource1.Dump32; }
}
public System.Resources.ResourceManager AyaNovaResourceManager
{
set { resman = value; }
get { return resman; }
}
public bool Initialize(Version AyaNovaVersion, LocalizedTextTable localizedText)
{
if (AyaNovaVersion.Major < 7)
{
MessageBox.Show("The V8 export plugin requires AyaNova version 7.6 or newer");
return false;
}
if (AyaNovaVersion.Minor < 6)
{
MessageBox.Show("The V8 export plugin requires AyaNova version 7.6 or newer");
return false;
}
util.LocaleText = localizedText;
ObjectsWeCanDealWith = new List<RootObjectTypes>();
ObjectsWeCanDealWith.Add(RootObjectTypes.Nothing);
return true;
}
public void Close()
{
;
}
public bool SingleObjectMenuShow(RootObjectTypes objectType)
{
return (ObjectsWeCanDealWith.Contains(objectType));
}
public bool MultipleObjectsMenuShow(RootObjectTypes objectType)
{
return false;
}
public List<AyaNovaPluginMenuItem> SingleObjectMenuOptions(RootObjectTypes objectType, object ayaNovaObject)
{
if (!ObjectsWeCanDealWith.Contains(objectType)) return null;
List<AyaNovaPluginMenuItem> list = new List<AyaNovaPluginMenuItem>();
list.Add(new AyaNovaPluginMenuItem("V8 Export", "Export to AyaNova 8 server", null, null));
return list;
}
public List<AyaNovaPluginMenuItem> MultipleObjectsMenuOptions(RootObjectTypes objectType)
{
return null;
}
public bool CommandSelectedForList(string commandKey, RootObjectTypes objectType, List<Guid> objectIDList, object listObject)
{
return false;
}
public void CommandSelectedForSingleObject(string commandKey, RootObjectTypes objectType, object ayaNovaObject)
{
if (!User.CurrentUserIsAnAdministrator)
{
MessageBox.Show("This action can only be done by the AyaNova Administrator account");
return;
}
#if(!DEBUG)
if (!AyaBizUtils.AyaNovaConnectionSetting.SingleUserConnection)
{
MessageBox.Show("** WARNING: before proceeding ensure no other users are logged into AyaNova to ensure the integrity of your exported data. Failing to do so *will* result in damaged data. ***");
MessageBox.Show("** WARNING: before proceeding make sure your AyaNova Generator service is STOPPED to ensure the integrity of your exported data. Failing to do so *will* result in damaged data. ***");
}
#endif
Auth d = new Auth();
var res = d.ShowDialog(); ;
if (res == DialogResult.Cancel)
{
return;
}
Opt dOpt = new Opt();
var ro = dOpt.ShowDialog();
if (ro == DialogResult.Cancel)
{
return;
}
ExportAssignedDocs = dOpt.ExportAssignedDocs;
//here because we logged in fine and can proceed
//MessageBox.Show("Login successful! JWT is " + util.JWT);
//Only one command
DoExport();
}
#endregion
private Dictionary<Guid, long> Map = new Dictionary<Guid, long>();
private Dictionary<Guid, string> TagMap = new Dictionary<Guid, string>();
private Dictionary<string, long> LocaleMap = new Dictionary<string, long>();
private string ImportTag = "v7-import";
private bool ExportAssignedDocs = false;
/// <summary>
/// Dump the objects into a temporary directory as a series of JSON files
/// then zip it all up into a single archive file and then erase the temporary folder
/// </summary>
private async void DoExport()
{
//Show progress form
ProgressForm progress = new ProgressForm();
progress.Show();
progress.StartedImport();
progress.Append("Exporting data to AyaNova server @ " + util.ApiBaseUrl);
try
{
progress.Op("Preparing to export....");
Map.Clear();
TagMap.Clear();
LocaleMap.Clear();
//admin user (not exported but is there already)
Map.Add(User.AdministratorID, 1);
//not sure if this is a good idea or not because in some cases would want to know if something is unexpectedly empty but will see for now
//Map.Add(Guid.Empty, 0);
/*
TODO:
* todo: once have moved beyond what's in the v8 import stuff then need to remove all that, though maybe comment out some bits as some may be useful for import / export??
* todo: make up stub versions of all the core biz objects so can test a full wiki, attachment etc import
todo: export docs, settle on "Export" and edit all references to Import to switch it around as it's probably confusing artifact from dbdump days
* TODO: User: headofficeid, clientid vendorid, phone1, phone2, pagermaxtext
*
*
*
*
*
*/
//if (progress.KeepGoing)
// await ExportLocales(progress);
//return;
//Export in correct order:
//ERASE DB
progress.Op("Erasing AyaNova 8 data");
var a = await util.PostAsync("License/PermanentlyEraseAllData", "\"I understand\"");
//TAGS
progress.Op("Compiling tags");
if (progress.KeepGoing)
ExportUnitModelCategories(progress);
if (progress.KeepGoing)
ExportUnitServiceTypes(progress);
if (progress.KeepGoing)
ExportWorkorderItemTypes(progress);
if (progress.KeepGoing)
ExportRegions(progress);
if (progress.KeepGoing)
ExportClientGroups(progress);
if (progress.KeepGoing)
ExportWorkorderCategories(progress);
if (progress.KeepGoing)
ExportPartCategories(progress);
if (progress.KeepGoing)
ExportScheduleableUserGroups(progress);
if (progress.KeepGoing)
ExportDispatchZones(progress);
if (progress.KeepGoing)
ExportUserSkills(progress);
if (progress.KeepGoing)
ExportUserCertifications(progress);
progress.Op("Exporting objects");
//BIZ objects
//if (progress.KeepGoing)
// await ExportLocales(progress);
if (progress.KeepGoing)
await ExportUsers(progress);
//dumpGlobalSettings(tempArchiveFolder, progress);
//dumpSeedNumbers(tempArchiveFolder, progress);
//dumpClients(tempArchiveFolder, progress);
//dumpHeadOffices(tempArchiveFolder, progress);
//
//NOTE: when get to PRIORITY, or WORKORDER STATUS be sure to add color code as per already done in USER export
if (progress.KeepGoing)
{
progress.Append("Export completed");
progress.Op("");
goto End;
}
progress.Append("Export cancelled before completing");
progress.Op("");
End:
;
}
catch (Exception ex)
{
progress.Append("ERROR, During operation: " + progress.LastOp + "\n" + progress.LastSubOp);
progress.Append("\n************\nExport failed with error:");
progress.Append(ex.Message);
progress.Append("stack:\n" + ex.StackTrace);
}
finally
{
progress.FinishedImport();
}
//-----------------------------------
//endof method
}
#region BIZ OBJECT Export methods
#region users
private async System.Threading.Tasks.Task ExportUsers(ProgressForm progress)
{
//Step 1: export the CustomFields to FormCustom if applicable so that when doing individual items we can export their custom data too
var ocf = ObjectHasCustomFieldDataToExport("User");
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, "User", "User");
//Step 2: export the users
UserPickList pl = UserPickList.GetList(false);
progress.Append("Exporting " + pl.Count.ToString() + " Users");
#region Export administrator wiki and attached files if present
{
User admin = User.GetItem(User.AdministratorID);
progress.Op("Administrator account");
var adminTid=new TypeAndID(RootObjectTypes.User, User.AdministratorID);
//Attachments and wiki
string AdminWikiContent = null;
var hasWiki = WikiPage.HasWiki(User.AdministratorID);
if (hasWiki)
{
await ExportAttachments(adminTid, progress);
AdminWikiContent = GetWikiContent(adminTid);
}
string adminCustomFields = null;
//Custom fields?
if (ShouldExportCustom)
{
adminCustomFields = CustomFieldData(admin, DateCustomFields);
}
//check if we need to do anything with the manager account itself
if (hasWiki || adminCustomFields != null)
{
//yes, so fetch it and modify it and put it back again
var a = await util.GetAsync("User/1");
dynamic d = a.ObjectResponse["data"];
d.wiki = AdminWikiContent;
d.customFields = CustomFieldData(admin, DateCustomFields);
await util.PutAsync("User/1", d.ToString());
}
}
#endregion admin export
foreach (UserPickList.UserPickListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
//skip administrator user fields
//but do export administrator
if (i.ID == User.AdministratorID) continue;
User c = User.GetItem(i.ID);
var UserTID=new TypeAndID(RootObjectTypes.User, c.ID);
dynamic d = new JObject();
d.name = c.FirstName + " " + c.LastName;
progress.Op("User " + d.name);
d.userType = (int)c.UserType;
//if special 3rd party user type then set their parent object id to -1 to signify will fill in later and satisfy biz rules at server
switch (c.UserType)
{
case UserTypes.Client:
d.customerId = -1;
break;
case UserTypes.HeadOffice:
d.headOfficeId = -1;
break;
}
if (c.VendorID != Guid.Empty)
{
d.userType = 7;//7 is the RAVEN user type for subcontractor
d.subVendorId = -1;
}
d.active = false;//all imported users are inactive to start
d.roles = 0;//todo: try to determine role from v7 member of group? or is that even possible?
d.login = util.RandomString();
d.password = util.RandomString();
d.employeeNumber = c.EmployeeNumber;
d.notes = c.Notes;
Tagit(c.RegionID, tags);
Tagit(c.DispatchZoneID, tags);
foreach (UserSkillAssigned skill in c.UserSkills)
{
Tagit(skill.UserSkillID, tags);
}
foreach (UserCertificationAssigned cert in c.UserCertifications)
{
Tagit(cert.UserCertificationID, tags);
}
SetTags(d, tags);
//Attachments and wiki
var hasWiki = WikiPage.HasWiki(c.ID);
if (hasWiki)
{
await ExportAttachments(UserTID, progress);
d.wiki = GetWikiContent(UserTID);
}
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var a = await util.PostAsync("User", d.ToString());
long RavenId = util.IdFromResponse(a);
Map.Add(c.ID, RavenId);
//USER OPTIONS
if (c.ScheduleBackColor != 0 || !string.IsNullOrWhiteSpace(c.EmailAddress))
{
a = await util.GetAsync("UserOptions/" + RavenId.ToString());
d = a.ObjectResponse["data"];
d.uiColor = System.Drawing.ColorTranslator.ToHtml(System.Drawing.Color.FromArgb(c.ScheduleBackColor));
d.emailAddress = string.IsNullOrWhiteSpace(c.EmailAddress) ? null : c.EmailAddress;
d.translationId = LocaleMap[c.DefaultLanguage];
await util.PutAsync("UserOptions/" + RavenId.ToString(), d.ToString());
}
//Attachments / FILES
await ExportAttachments(UserTID, progress);
//docs
await ExportDocs(UserTID, c.Docs, progress);
}
//EVENT LOG
//Because this is the User's we need to do the event log *after* they have all been posted as event log requires all user's id
foreach (UserPickList.UserPickListInfo i in pl)
{
if (!progress.KeepGoing) return;
User c = User.GetItem(i.ID);
var newId = Map[c.ID];
var creator = Map[c.Creator];
var modifier = Map[c.Modifier];
await util.EventLog(3, newId, creator, modifier, c.Created, c.Modified);
}
}
#endregion clients
#region locales
private async System.Threading.Tasks.Task ExportLocales(ProgressForm progress)
{
progress.Append("Exporting customized Locales");
//checksum locales
//if a recognized checksum then don't import because it means it wasn't modified from stock
/*
Stock fresh trial db (fb) values:
Locale: Custom English hash code: 740187325
Locale: Deutsch hash code: -257973661
Locale: English hash code: 740187325
Locale: Español hash code: -373723947
Locale: Français hash code: -224208815
*/
List<int> StockLocaleHashes = new List<int>();
StockLocaleHashes.Add(-257973661);
StockLocaleHashes.Add(740187325);
StockLocaleHashes.Add(-373723947);
StockLocaleHashes.Add(-224208815);
//Get a list of RAVEN translations and ID's
var a = await util.GetAsync("Translation/List");
JArray ja = (JArray)a.ObjectResponse["data"];
var RavenLanguageList = ja.ToObject<List<util.NameIdItem>>();
LocaleList l = LocaleList.GetList();
foreach (LocaleList.LocaleListInfo i in l)
{
if (!progress.KeepGoing) return;
LocalizedTextTable lt = LocalizedTextTable.Load(i.Locale);
progress.Op("Checking if locale " + i.Locale + " is customized");
//calculate hash
List<string> allStrings = new List<string>();
foreach (var entry in lt.LT)
allStrings.Add(entry.Value);
int CurrentLocaleHash = util.GetOrderIndependentHashCode<string>(allStrings);
allStrings.Clear();
if (StockLocaleHashes.Contains(CurrentLocaleHash)) continue;
progress.Op("Locale " + i.Locale + " is customized");
//collection to hold items sent to server
List<UpdateTranslationItem> exportItems = new List<UpdateTranslationItem>();
//Iterate all RAVEN languages
for (int x = 1; x < 5; x++)//first four translations are the stock ones
{
//get raven name of locale
var RavenLocaleName = RavenLanguageList.Find(m => m.Id == x).Name;
//add stock locale mappings in case users are set to a stock one in v7
//so can set them later
switch (RavenLocaleName)
{
case "en":
LocaleMap.Add("English", x);
break;
case "fr":
LocaleMap.Add("Français", x);
break;
case "de":
LocaleMap.Add("Deutsch", x);
break;
case "es":
LocaleMap.Add("Español", x);
break;
}
//MAKE A DUPLICATE
//name like this: "My custom (Espanol)" etc one for each target stock language
var exportName = i.Locale + " (" + RavenLocaleName + ")";
progress.SubOp("");
progress.Op("Exporting " + i.Locale + " to " + exportName);
var t = new util.NameIdItem { Name = exportName, Id = x };
a = await util.PostAsync("Translation/Duplicate", JObject.FromObject(t).ToString());
var targetTranslationId = util.IdFromResponse(a);
var ctoken = util.CTokenFromResponse(a);
//add to maps so can set user to it on export
//going to default to the English based one because
//that's the majority of the users
if (RavenLocaleName == "en")
LocaleMap.Add(i.Locale, targetTranslationId);
//Ok, have our target locale created, not we need to insert our custom translations one by one
var trans = ((JArray)a.ObjectResponse["data"]["translationItems"]).ToObject<List<TranslationItem>>();
//SET MATCHING KEYS TO OUR TEXT
//iterate v7 locale items
foreach (var v7item in lt.LT)
{
progress.SubOp("Processing key: " + v7item.Key);
var v8key = Translatev7TranslationKey(v7item.Key);
if (v8key == "**SKIP**") continue;
System.Diagnostics.Debug.WriteLine("v7key:" + v7item.Key + " -> v8key: " + v8key);
TranslationItem v8TransItem = trans.FirstOrDefault(m => m.Key == v8key);
if (v8TransItem == null)
{
throw new ArgumentOutOfRangeException("On exporting custom locale " + i.Locale + " source key " + v7item.Key + ", destination key " + v8key + " was not found.");
}
//collect
exportItems.Add(new UpdateTranslationItem
{
Id = v8TransItem.Id,
ConcurrencyToken = v8TransItem.ConcurrencyToken,
NewText = v7item.Value
});
}
//update it
progress.SubOp("Posting translation " + exportName + " to server ");
await util.PutAsync("Translation/UpdateTranslationItemsDisplayText",
JArray.FromObject(exportItems).ToString());
}
}
progress.Op("");
progress.SubOp("");
}
#region locale utility
public class TranslationItem
{
public long Id { get; set; }
public uint ConcurrencyToken { get; set; }
public string Key { get; set; }
public string Display { get; set; }
public long TranslationId { get; set; }
}
public class UpdateTranslationItem
{
public long Id { get; set; }
public uint ConcurrencyToken { get; set; }
public string NewText { get; set; }
}
/// <summary>
/// Used by import, translate the old v7 translation key name into the new shorter version
/// </summary>
/// <param name="oldKey"></param>
/// <returns></returns>
public string Translatev7TranslationKey(string oldKey)
{
//skip keys definitely not in destination
//swaths:
if (oldKey.StartsWith("UI.ToolBar.")) return "**SKIP**";
if (oldKey.StartsWith("UI.Toolbar.")) return "**SKIP**";
// Custom English source key UI.Toolbar.ClientsToolBar, destination key ToolbarClientsToolBar was not found.
switch (oldKey)
{
// case "XXXX":
case "O.WikiPage": //skip over wikipage it's been dropped as it's an international term
case "UI.Command.LocalizedTextDesign":
case "O.WorkorderItemOutsideService":
case "O.WorkorderService.CloseByDate":
case "UI.Label.CurrentUserName":
case "UI.Go.Search":
return "**SKIP**";
}
string s = oldKey.Replace(".Label.", ".");
if (s.StartsWith("O."))
s = s.Replace("O.", "");
s = s.Replace(".ToolBar.", ".");
s = s.Replace(".Go.", ".");
s = s.Replace(".Command.", ".");
s = s.Replace(".Error.", ".");
s = s.Replace(".Object.", ".");
if (s.StartsWith("UI."))
s = s.Replace("UI.", "");
s = s.Replace(".", "");
s = s.Replace("AddressAddress", "Address");
s = s.Replace("ContactPhoneContactPhone", "ContactPhone");
s = s.Replace("ContactPhonePhone", "ContactPhone");
s = s.Replace("PurchaseOrderPurchaseOrder", "PurchaseOrder");
s = s.Replace("WorkorderItemMiscExpenseExpense", "WorkorderItemMiscExpense");
s = s.Replace("WorkorderItemTravelTravel", "WorkorderItemTravel");
s = s.Replace("DashboardDashboard", "Dashboard");
//ScheduleMarkers -> Reminder
s = s.Replace("ScheduleMarkerScheduleMarker", "ScheduleMarker");
s = s.Replace("ScheduleMarker", "Reminder");
s = s.Replace("ScheduleMarkerARGB", "ReminderARGB");
s = s.Replace("ScheduleMarkerColor", "ReminderColor");
s = s.Replace("ScheduleMarkerCompleted", "ReminderCompleted");
s = s.Replace("ScheduleMarkerEventCreated", "ReminderEventCreated");
s = s.Replace("ScheduleMarkerEventPendingAlert", "ReminderEventPendingAlert");
s = s.Replace("ScheduleMarkerFollowUp", "ReminderFollowUp");
s = s.Replace("ScheduleMarkerList", "ReminderList");
s = s.Replace("ScheduleMarkerName", "ReminderName");
s = s.Replace("ScheduleMarkerNotes", "ReminderNotes");
s = s.Replace("ScheduleMarkerRecurrence", "ReminderRecurrence");
s = s.Replace("ScheduleMarkerScheduleMarkerSourceType", "ReminderSourceType");
s = s.Replace("ScheduleMarkerSourceID", "ReminderSourceID");
s = s.Replace("ScheduleMarkerStartDate", "ReminderStartDate");
s = s.Replace("ScheduleMarkerStopDate", "ReminderStopDate");
s = s.Replace("ScheduleEditScheduleMarker", "ScheduleEditReminder");
s = s.Replace("ScheduleNewScheduleMarker", "ScheduleNewReminder");
//Custom fields were 0 to 9, now 1 to 16
s = s.Replace("Custom9", "Custom10");
s = s.Replace("Custom8", "Custom9");
s = s.Replace("Custom7", "Custom8");
s = s.Replace("Custom6", "Custom7");
s = s.Replace("Custom5", "Custom6");
s = s.Replace("Custom4", "Custom5");
s = s.Replace("Custom3", "Custom4");
s = s.Replace("Custom2", "Custom3");
if (!s.EndsWith("Custom10"))
s = s.Replace("Custom1", "Custom2");
s = s.Replace("Custom0", "Custom1");
//separate code will handle adding the new keys that didn't exist in v7 (custom 11 - 16)
//CommonActive CommonID etc remove Common
s = s.Replace("Common", "");
//Misc
s = s.Replace("FormFieldDataType", "UiFieldDataType");
s = s.Replace("UserUserType", "UserType");
s = s.Replace("UserTypesUtilityNotification", "UserTypesUtility");
//Localized -> Translation
s = s.Replace("LocaleCustomizeText", "TranslationCustomizeText");
s = s.Replace("LocaleExport", "TranslationExport");
s = s.Replace("LocaleImport", "TranslationImport");
s = s.Replace("LocaleList", "TranslationList");
s = s.Replace("LocaleLocaleFile", "TranslationFile");
s = s.Replace("LocaleUIDestLocale", "TranslationDest");
s = s.Replace("LocaleUISourceLocale", "TranslationSource");
s = s.Replace("LocaleWarnLocaleLocked", "TranslationWarnLocked");
s = s.Replace("LocalizedTextDisplayText", "TranslationDisplayText");
s = s.Replace("LocalizedTextDisplayTextCustom", "TranslationDisplayTextCustom");
s = s.Replace("LocalizedTextKey", "TranslationKey");
s = s.Replace("LocalizedTextLocale", "Translation");
s = s.Replace("LocalizedText", "TranslatedText");
//items that came up after moving this to v8 export plugin
s = s.Replace("DateRangeInTheLastYear", "DateRangePastYear");
s = s.Replace("ToolbarCustomizeDialog", "CustomizeDialog");
//FUTURE
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
return s;
}
#endregion locale utility
#endregion locales
#region TAG ITEMS
#region Unitmodelcategories
private void ExportUnitModelCategories(ProgressForm progress)
{
UnitModelCategories l = UnitModelCategories.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Unit model categories");
foreach (UnitModelCategory i in l) TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "unitmodelcategory"));
}
#endregion
#region Unitservicetypes
private void ExportUnitServiceTypes(ProgressForm progress)
{
UnitServiceTypes l = UnitServiceTypes.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Unit service types");
foreach (UnitServiceType i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "unitservicetype"));
}
#endregion
#region WorkorderItemTypes
private void ExportWorkorderItemTypes(ProgressForm progress)
{
WorkorderItemTypes l = WorkorderItemTypes.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Workorder item types");
foreach (WorkorderItemType i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "workorderitemtype"));
}
#endregion
#region REGIONS
private void ExportRegions(ProgressForm progress)
{
RegionList l = RegionList.GetList(string.Empty);
progress.Append("Compiling " + l.Count.ToString() + " Regions");
foreach (RegionList.RegionListInfo i in l)
TagMap.Add(i.LT_Region_Label_Name.Value, util.NormalizeTag(i.LT_Region_Label_Name.Display + "." + "region"));
}
#endregion
#region Client groups
private void ExportClientGroups(ProgressForm progress)
{
ClientGroups l = ClientGroups.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Client groups");
foreach (ClientGroup i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "clientgroup"));
}
#endregion
#region Workorder categories
private void ExportWorkorderCategories(ProgressForm progress)
{
WorkorderCategories l = WorkorderCategories.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Workorder categories");
foreach (WorkorderCategory i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "workordercategory"));
}
#endregion
#region Part categories
private void ExportPartCategories(ProgressForm progress)
{
PartCategories l = PartCategories.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Part categories");
foreach (PartCategory i in l) TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "partcategory"));
}
#endregion
#region ScheduleableUserGroups
private void ExportScheduleableUserGroups(ProgressForm progress)
{
ScheduleableUserGroupPickList pl = ScheduleableUserGroupPickList.GetList();
progress.Append("Compiling " + pl.Count.ToString() + " Scheduleable user groups");
foreach (ScheduleableUserGroupPickList.ScheduleableUserGroupPickListInfo i in pl)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "partcategory"));
}
#endregion clients
#region Dispatch zones
private void ExportDispatchZones(ProgressForm progress)
{
DispatchZones l = DispatchZones.GetItems(false);
progress.Append("Compiling " + l.Count.ToString() + " Dispatch zones");
foreach (DispatchZone i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "dispatchzone"));
}
#endregion
private void ExportUserSkills(ProgressForm progress)
{
UserSkills l = UserSkills.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " User skills");
foreach (UserSkill i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "user-skill"));
}
private void ExportUserCertifications(ProgressForm progress)
{
UserCertifications l = UserCertifications.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " User certifications");
foreach (UserCertification i in l)
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "user-certification"));
}
#endregion TAG ITEMS
//--------------------------------------------
#endregion object export
#region Custom fields exporter
//export objects custom field data into jobject string
private string CustomFieldData(object biz, List<int> dateFields)
{
dynamic d = new JObject();
for (int x = 0; x < 10; x++)
{
object o = (object)biz.GetType().GetProperty("Custom" + x.ToString()).GetValue(biz, null);
string s = o.ToString();
if (string.IsNullOrWhiteSpace(s))
{
s = null;
}
if (s != null && dateFields.Contains(x))
{
//parse out to UTC date
DateTime dt = new DateTime();
if (DateTime.TryParse(s, out dt))
{
s = dt.ToUniversalTime().ToString("s");
}
}
if (!string.IsNullOrWhiteSpace(s))
d["c" + (x + 1).ToString()] = s;
}
return d.ToString();
}
static public ObjectCustomFields ObjectHasCustomFieldDataToExport(string sObject)
{
ObjectCustomFields ocf = ObjectCustomFields.GetItems(sObject);
if (ocf.Count == 0)
{
return null;
}
foreach (ObjectCustomField f in ocf)
{
if (f.Visible)
return ocf;
}
return null;
}
private async System.Threading.Tasks.Task<List<int>> ExportCustomFieldSchema(ObjectCustomFields ocf, string v7CustomFieldObjectName, string RavenCustomTranslationKeyObjectName)
{
var ret = new List<int>();
//NOTE: this code inspired by winforApp::Util.cs PrepareCustomFieldsGrid method
dynamic d = new JObject();
d.formkey = RavenCustomTranslationKeyObjectName;
dynamic dtemplate = new JArray();
foreach (ObjectCustomField f in ocf)
{
if (f.Visible)
{
int n = Convert.ToInt32(f.FieldName.Replace("Custom", "")) + 1;//raven custom fields are 1 based, v7 are zero based
//CustomFieldLocaleKeys.Add(RavenCustomTranslationKeyObjectName + n.ToString(),
// util.LocaleText.GetLocalizedText(v7CustomFieldObjectName + ".Label." + f.FieldName));
dynamic dt = new JObject();
dt.fld = RavenCustomTranslationKeyObjectName + "Custom" + n.ToString();
dt.hide = false;
dt.required = false;
switch (f.FieldType)
{
case FormFieldDataTypes.Currency:
dt.type = util.AyaUiFieldDataType.Currency;
break;
case FormFieldDataTypes.DateOnly:
dt.type = util.AyaUiFieldDataType.Date;
ret.Add(n - 1);
break;
case FormFieldDataTypes.DateTime:
dt.type = util.AyaUiFieldDataType.DateTime;
ret.Add(n - 1);
break;
case FormFieldDataTypes.Number:
dt.type = util.AyaUiFieldDataType.Decimal;
break;
case FormFieldDataTypes.Text:
dt.type = util.AyaUiFieldDataType.Text;
break;
case FormFieldDataTypes.TimeOnly:
dt.type = util.AyaUiFieldDataType.Time;
ret.Add(n - 1);
break;
case FormFieldDataTypes.TrueFalse:
dt.type = util.AyaUiFieldDataType.Bool;
break;
default:
dt.type = util.AyaUiFieldDataType.Text;
break;
}
dtemplate.Add(dt);
}
}
d.template = dtemplate.ToString();
//ok, were here because there *are* custom fields available
var a = await util.GetAsync("FormCustom/" + RavenCustomTranslationKeyObjectName);
var ctoken = util.CTokenFromResponse(a);
d.concurrencyToken = ctoken;
await util.PutAsync("FormCustom/" + RavenCustomTranslationKeyObjectName, d.ToString());
return ret;
}
#endregion custom fields
#region Attachments exporter
private async System.Threading.Tasks.Task ExportAttachments(TypeAndID tid, ProgressForm progress)
{
if (!WikiPage.HasWiki(tid.ID)) return;
WikiPage w = WikiPage.GetItem(tid);
AyaFileList fl = AyaFileList.GetList(w.ID);
if (fl.Count == 0) return;
//iterate the files
foreach (AyaFileList.AyaFileListInfo i in fl)
{
if (!progress.KeepGoing) return;
var af = AyaFile.GetItem(i.LT_O_AyaFile.Value);
if (af == null) continue;
progress.SubOp("Wikifile: \"" + af.Name + "\" " + AyaBizUtils.FileSizeDisplay((decimal)af.FileSize));
//Compile the FileData property
var sDate = i.LT_Common_Label_Created.ToString();
DateTimeOffset dtLastModified = DateTime.UtcNow;
if (sDate != null)
{
//parse out to UTC date
DateTime dt = new DateTime();
if (DateTime.TryParse(sDate, out dt))
{
dtLastModified = dt.ToUniversalTime();
}
}
dynamic dFileData = new JArray();
dynamic dFile = new JObject();
dFile.name = af.Name;
dFile.lastModified = dtLastModified.ToUnixTimeMilliseconds();
dFileData.Add(dFile);
//Upload
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
//Form data like the bizobject type and id
formDataContent.Add(new StringContent(util.RootObjectToAyaType(tid.RootObjectType).ToString()), name: "AttachToObjectType");
formDataContent.Add(new StringContent(Map[tid.ID].ToString()), name: "AttachToObjectId");
formDataContent.Add(new StringContent(ImportTag), name: "Notes");
formDataContent.Add(new StringContent(dFileData.ToString()), name: "FileData");
StreamContent AttachmentFile = new StreamContent(af.GetContent());
AttachmentFile.Headers.ContentType = new MediaTypeHeaderValue(af.mimeType);
AttachmentFile.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
AttachmentFile.Headers.ContentDisposition.FileName = af.Name;
AttachmentFile.Headers.ContentDisposition.ModificationDate = dtLastModified;
formDataContent.Add(AttachmentFile);
//Upload
var a = await util.PostFormDataAsync("Attachment", formDataContent);
//Map it for later processing of wiki
var ravenId = a.ObjectResponse["data"][0]["id"].Value<long>();
Map.Add(af.ID, ravenId);
}
progress.SubOp("");
}
#endregion attachments
#region Assigned docs exporter
private async System.Threading.Tasks.Task<List<string>> ExportDocs(TypeAndID tid, AssignedDocs docs, ProgressForm progress)
{
List<string> NonFileUrls = new List<string>();
if (!ExportAssignedDocs) return NonFileUrls;
if (docs.Count == 0) return NonFileUrls;
//iterate the files
foreach (AssignedDoc doc in docs)
{
if (!progress.KeepGoing) return NonFileUrls;
//is it a local file?
if (!new Uri(doc.URL).IsFile)
{
NonFileUrls.Add(doc.Description + "("+ImportTag+ ")\n" + doc.URL+"\n");
continue;
}
//can we see it?
if (!File.Exists(doc.URL))
{
NonFileUrls.Add(ImportTag + " - Assigned doc. file not found:\n" + doc.Description + "\n" + doc.URL + "\n");
continue;
}
progress.SubOp("Wikifile: \"" + af.Name + "\" " + AyaBizUtils.FileSizeDisplay((decimal)af.FileSize));
//Compile the FileData property
var sDate = i.LT_Common_Label_Created.ToString();
DateTimeOffset dtLastModified = DateTime.UtcNow;
if (sDate != null)
{
//parse out to UTC date
DateTime dt = new DateTime();
if (DateTime.TryParse(sDate, out dt))
{
dtLastModified = dt.ToUniversalTime();
}
}
dynamic dFileData = new JArray();
dynamic dFile = new JObject();
dFile.name = af.Name;
dFile.lastModified = dtLastModified.ToUnixTimeMilliseconds();
dFileData.Add(dFile);
//Upload
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
//Form data like the bizobject type and id
formDataContent.Add(new StringContent(util.RootObjectToAyaType(tid.RootObjectType).ToString()), name: "AttachToObjectType");
formDataContent.Add(new StringContent(Map[tid.ID].ToString()), name: "AttachToObjectId");
formDataContent.Add(new StringContent(ImportTag), name: "Notes");
formDataContent.Add(new StringContent(dFileData.ToString()), name: "FileData");
StreamContent AttachmentFile = new StreamContent(af.GetContent());
AttachmentFile.Headers.ContentType = new MediaTypeHeaderValue(af.mimeType);
AttachmentFile.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
AttachmentFile.Headers.ContentDisposition.FileName = af.Name;
AttachmentFile.Headers.ContentDisposition.ModificationDate = dtLastModified;
formDataContent.Add(AttachmentFile);
//Upload
var a = await util.PostFormDataAsync("Attachment", formDataContent);
//Map it for later processing of wiki
var ravenId = a.ObjectResponse["data"][0]["id"].Value<long>();
Map.Add(af.ID, ravenId);
}
progress.SubOp("");
return NonFileUrls;
}
#endregion assigned docs
#region WIKI page exporter
//WIKI
#region Wikiable objects reference
/*
Find all "Util.OpenWikiPage", Whole word, Subfolders, Keep modified files open, Find Results 1, Entire Solution, ""
C:\data\ayanova\source\WinFormApp\ClientInfoForm.cs(1579): Util.OpenWikiPage(RootObjectTypes.Client, mClient.ID,false);
C:\data\ayanova\source\WinFormApp\ContractInfoForm.cs(687): Util.OpenWikiPage(RootObjectTypes.Contract, mContract.ID, false);
C:\data\ayanova\source\WinFormApp\Form1.cs(3713): Util.OpenWikiPage(RootObjectTypes.Global, Address.GlobalAddressID, false);
C:\data\ayanova\source\WinFormApp\Form1.cs(3856): Util.OpenWikiPage(RootObjectTypes.User, User.CurrentThreadUserID, false);
C:\data\ayanova\source\WinFormApp\Form1.cs(3867): // Util.OpenWikiPage(RootObjectTypes.User,User.CurrentThreadUserID,false);
C:\data\ayanova\source\WinFormApp\HeadOfficeInfoForm.cs(1402): Util.OpenWikiPage(RootObjectTypes.HeadOffice, mHeadOffice.ID,false);
C:\data\ayanova\source\WinFormApp\LoanItemInfoForm.cs(860): Util.OpenWikiPage(RootObjectTypes.LoanItem, mLoanItem.ID, false);
C:\data\ayanova\source\WinFormApp\PartInfoForm.cs(1111): Util.OpenWikiPage(RootObjectTypes.Part, mPart.ID, false);
C:\data\ayanova\source\WinFormApp\ProjectInfoForm.cs(712): Util.OpenWikiPage(RootObjectTypes.Project, mProject.ID, false);
C:\data\ayanova\source\WinFormApp\PurchaseOrderInfoForm.cs(1010): Util.OpenWikiPage(RootObjectTypes.PurchaseOrder, mPurchaseOrder.ID, false);
C:\data\ayanova\source\WinFormApp\RegionInfoForm.cs(1186): Util.OpenWikiPage(RootObjectTypes.Region, mRegion.ID, false);
C:\data\ayanova\source\WinFormApp\UnitInfoForm.cs(1280): Util.OpenWikiPage(RootObjectTypes.Unit, mUnit.ID, false);
C:\data\ayanova\source\WinFormApp\UnitModelInfoForm.cs(926): Util.OpenWikiPage(RootObjectTypes.UnitModel, mUnitModel.ID, false);
C:\data\ayanova\source\WinFormApp\UserInfoForm.cs(1395): Util.OpenWikiPage(RootObjectTypes.User, mUser.ID, false);
C:\data\ayanova\source\WinFormApp\VendorInfoForm.cs(1193): Util.OpenWikiPage(RootObjectTypes.Vendor, mVendor.ID, false);
C:\data\ayanova\source\WinFormApp\WorkorderForm.cs(10332): Util.OpenWikiPage(mWorkorder.RootObjectType, mWorkorder.ID, false);//case 1584 was RootObjectTypes.Workorder
C:\data\ayanova\source\WBI\maingrid.aspx.cs(1277): Util.OpenWikiPage(this.Page, new TypeAndID(RootObjectTypes.Global, Address.GlobalAddressID));
C:\data\ayanova\source\WBI\schedule.aspx.cs(187): Util.OpenWikiPage(this.Page, new TypeAndID(RootObjectTypes.Global, Address.GlobalAddressID));
Matching lines: 18 Matching files: 16 Total files searched: 1769
*/
#endregion
private string GetWikiContent(TypeAndID tid)
{
//may not exist
// if (!WikiPage.HasWiki(tid.ID)) return null;
WikiPage w = WikiPage.GetItem(tid);
var content = w.GetContentAsString;
if (string.IsNullOrWhiteSpace(content)) return null;
//TODO: fixup internal urls using MAP of file attachment uploads
MatchCollection mc = AyaBizUtils.rxAyaImageTags.Matches(content);
foreach (Match m in mc)
{
var RavenId = Map[new Guid(m.Groups["guid"].Value)];
content = content.Replace(m.Value, "<img src=\"" + "[ATTACH:" + RavenId.ToString() + "]" + "\">");
}
//todo: fixup font size, try to convert to heading tags instead
//figure out how to remove the inline style tag as it comes through for some reason
//TODO: Convert to Markdown format
//found 2 likely candidate libs to do this
//https://www.nuget.org/packages/Html2Markdown/
//https://www.nuget.org/packages/ReverseMarkdown/
//Not much difference at first glance, very similar stats, reverse markdown is a little more widely used and seems to have more config options
//built in, the other has to make some kind of processor for some stuff maybe so going with reverse for now
//NOTE: for this to work had to add an assembly redirect in app.config for ayanova project as it was looking for a really old version of
//the HtmlAgilityPack
var config = new ReverseMarkdown.Config
{
UnknownTags = ReverseMarkdown.Config.UnknownTagsOption.Bypass,
GithubFlavored = true, // generate GitHub flavoured markdown, supported for BR, PRE and table tags
RemoveComments = true, // will ignore all comments, (narrator: "It doesn't")
SmartHrefHandling = true // remove markdown output for links where appropriate
};
var converter = new ReverseMarkdown.Converter(config);
string res = converter.Convert(content);
//strip out comment and style chunk that is left behind by above tool
//style is an artifact of the rtf2html converter used by v7
int nStart = res.IndexOf("<!--");
int nEnd = res.IndexOf("-->");
if (nStart != -1 && nEnd != -1)
{
res = res.Substring(0, nStart) + res.Substring(nEnd + 3);
// res = newRes;
}
return res;
}
#region sample before and after
/*
* INPUT
* <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Untitled document</title>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css">
<!--
span.st1
{
font-family: Arial;
font-size: 39pt;
color: #000000;
}
span.st2
{
font-family: Arial;
font-size: 8pt;
color: #000000;
}
span.st3
{
font-family: Arial;
font-size: 6pt;
color: #000000;
}
span.st4
{
font-family: Arial;
font-size: 150pt;
color: #000000;
}
span.st5
{
font-family: Arial;
font-size: 8pt;
color: #ff0000;
}
span.st6
{
font-family: Arial;
font-size: 8pt;
color: #00ff00;
}
span.st7
{
font-family: Arial;
font-size: 8pt;
color: #000080;
}
span.st8
{
font-family: Symbol;
font-size: 8pt;
color: #000080;
}
span.st9
{
font-family: Consolas;
font-size: 8pt;
color: #000000;
}
span.st10
{
font-family: Comic Sans MS;
font-size: 8pt;
color: #000000;
}
span.st11
{
font-family: Comic Sans MS;
font-size: 16pt;
color: #000000;
}
span.st12
{
font-family: Arial;
font-size: 32pt;
color: #000000;
}
span.st13
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}
-->
</style>
</head>
<body>
<div><span class="st1"><b><u>Here is a title</u></b></span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2">This document has all possible options on it except for picking every single font size so instead</span><span class="st3"> here is the smallest font size which is 6</span></div>
<div><span class="st3">and here is the</span><span class="st4"> largest font size which is 150</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st2"><i>italics </i>and <u>underlined </u>and <b>bold</b></span></div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span><span class="st5"><b>red </b></span></div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st6"><b>green </b></span></div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span><span class="st7"><b>blue</b></span></div>
<div><span class="st7"><b></b></span>&nbsp;</div>
<div><span class="st7"><b></b></span></div>
<ul style="list-style-type: none">
<li><span class="st8"><b>·&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></span><span class="st7"><b>List one</b></span></li>
<li><span class="st7"><b></b></span><span class="st8"><b>·&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></span><span class="st7"><b>list two </b></span></li>
<li><span class="st7"><b></b></span><span class="st8"><b>·&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></span><span class="st7"><b>list three</b></span></li>
</ul><div><span class="st7"><b></b></span></div>
<div><span class="st7"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2">Arial font</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span><span class="st9">Consolas font</span></div>
<div><span class="st9"></span>&nbsp;</div>
<div><span class="st9"></span><span class="st10">Comic &nbsp;sans</span></div>
<div><span class="st10"></span>&nbsp;</div>
<div><span class="st10"></span><span class="st11">font size 16 double default size whih is 8 </span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span><span class="st12">font size 32 which is quadruple default of 8</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2">This block is</span></div>
<div><span class="st2">left aligned</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div align="center"><span class="st2">this block is </span></div>
<div align="center"><span class="st2">center aligned</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div align="right"><span class="st2">This block is </span></div>
<div align="right"><span class="st2">right aligned</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"> &nbsp;<img src="[ATTACH:4]"></span><span class="st13">Wiki page - User: AyaNova Administrator</span></div>
<div><span class="st13"></span>&nbsp;</div>
<div><span class="st13">and more:</span></div>
<div><span class="st13"></span><span class="st2"> <img src="[ATTACH:4]"></span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2">and more</span></div>
<div><span class="st2"> &nbsp;<img src="[ATTACH:4]"></span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st13"></span></div></body>
</html>
========================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Untitled document</title>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css">
<!--
span.st1
{
font-family: Times New Roman;
font-size: 20pt;
color: #000000;
}
span.st2
{
font-family: Times New Roman;
font-size: 18pt;
color: #000000;
}
span.st3
{
font-family: Times New Roman;
font-size: 10pt;
color: #000000;
}
span.st4
{
font-family: Times New Roman;
font-size: 24pt;
color: #000000;
}
span.st5
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}
-->
</style>
</head>
<body>
<div><span class="st1">Wiki page - User: Eva Alexander - ALL REGIONS</span></div>
<div><span class="st2"></span><span class="st3">Here is some under title text</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st3"></span><span class="st4">Here is another title</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st3">Here is some more under title text.</span></div>
<div><span class="st3">Some more lines</span></div>
<div><span class="st3">like this one</span></div>
<div><span class="st3">and this one</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st5"></span></div></body>
</html>
=-=-=-==-
*
*
*
output
* Untitled document<!--<br>span.st1
{
font-family: Arial;
font-size: 39pt;
color: #000000;
}<br>span.st2
{
font-family: Arial;
font-size: 8pt;
color: #000000;
}<br>span.st3
{
font-family: Arial;
font-size: 6pt;
color: #000000;
}<br>span.st4
{
font-family: Arial;
font-size: 150pt;
color: #000000;
}<br>span.st5
{
font-family: Arial;
font-size: 8pt;
color: #ff0000;
}<br>span.st6
{
font-family: Arial;
font-size: 8pt;
color: #00ff00;
}<br>span.st7
{
font-family: Arial;
font-size: 8pt;
color: #000080;
}<br>span.st8
{
font-family: Symbol;
font-size: 8pt;
color: #000080;
}<br>span.st9
{
font-family: Consolas;
font-size: 8pt;
color: #000000;
}<br>span.st10
{
font-family: Comic Sans MS;
font-size: 8pt;
color: #000000;
}<br>span.st11
{
font-family: Comic Sans MS;
font-size: 16pt;
color: #000000;
}<br>span.st12
{
font-family: Arial;
font-size: 32pt;
color: #000000;
}<br>span.st13
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}<br>-->
**Here is a title**
This document has all possible options on it except for picking every single font size so instead here is the smallest font size which is 6
and here is the largest font size which is 150
*italics*and underlined and **bold**
**red**
**green**
**blue**
- **·****List one**
- **·****list two**
- **·****list three**
Arial font
Consolas font
Comic  sans
font size 16 double default size whih is 8
font size 32 which is quadruple default of 8
This block is
left aligned
this block is
center aligned
This block is
right aligned
![]([ATTACH:4])Wiki page - User: AyaNova Administrator
and more:
![]([ATTACH:4])
and more
![]([ATTACH:4])
=========================
Untitled document<!--<br>span.st1
{
font-family: Times New Roman;
font-size: 20pt;
color: #000000;
}<br>span.st2
{
font-family: Times New Roman;
font-size: 18pt;
color: #000000;
}<br>span.st3
{
font-family: Times New Roman;
font-size: 10pt;
color: #000000;
}<br>span.st4
{
font-family: Times New Roman;
font-size: 24pt;
color: #000000;
}<br>span.st5
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}<br>-->
Wiki page - User: Eva Alexander - ALL REGIONS
Here is some under title text
Here is another title
Here is some more under title text.
Some more lines
like this one
and this one
*
*/
#endregion sample
#endregion wiki
#region TAGS
private void Tagit(Guid g, List<string> tags)
{
if (g == Guid.Empty) return;
if (!TagMap.ContainsKey(g)) return;
var t = TagMap[g];
if (!string.IsNullOrWhiteSpace(t))
{
tags.Add(t);
}
}
private void SetTags(dynamic d, List<string> tags)
{
dynamic dtags = new JArray();
foreach (string s in tags)
dtags.Add(s);
d.tags = dtags;
}
#endregion tags
#region OLD JSON EXPORT STUFF
#region Global settings
private void ExportGlobalSettings(ProgressForm progress)
{
progress.Append("STUB: Dumping Global Settings");
////DumpObjectToFolder(tempArchiveFolder, AyaBizUtils.GlobalSettings, "globalsettings", objectExcludeProperties, new TypeAndID(RootObjectTypes.Global, Address.GlobalAddressID));
}
#endregion globalsettings
#region Seeds
private class GZSeeds
{
public int InventoryAdjustmentStartSeed = 1;
public int PurchaseOrderStartSeed = 1;
public int QuoteNumberStartSeed = 1;
public int WorkorderNumberStartSeed = 1;
public int PreventiveMaintenanceNumberStartSeed = 1;
}
private void ExportSeedNumbers(ProgressForm progress)
{
// List<string> objectExcludeProperties = new List<string>(standardExcludePropertiesList);
progress.Append("Dumping seeds");
//create a new object with the id numbers in it and then dump it
WorkorderPMList pml = WorkorderPMList.GetList("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"yes\"?> \r\n" +
"<GRIDCRITERIA> \r\n" +
" <COLUMNITEM CM=\"aWorkorderPreventiveMaintenance.aPreventiveMaintenanceNumber\" UI=\"LT_O_WorkorderPreventiveMaintenance\" PIN=\"0\" WIDTH=\"150\" SORT=\"DESC\" /> \r\n" +
"</GRIDCRITERIA> ");
int PMStartSeed = 0;
if (pml.Count > 0)
{
PMStartSeed = int.Parse(pml[0].LT_O_WorkorderPreventiveMaintenance.Display);
}
var seeds = new GZSeeds();
seeds.InventoryAdjustmentStartSeed = AyaBizUtils.GlobalSettings.InventoryAdjustmentStartSeed + 1;
seeds.PurchaseOrderStartSeed = AyaBizUtils.GlobalSettings.PurchaseOrderStartSeed + 1;
seeds.QuoteNumberStartSeed = AyaBizUtils.GlobalSettings.QuoteNumberStartSeed + 1;
seeds.WorkorderNumberStartSeed = AyaBizUtils.GlobalSettings.WorkorderNumberStartSeed + 1;
seeds.PreventiveMaintenanceNumberStartSeed = PMStartSeed + 1;
//DumpObjectToFolder(tempArchiveFolder, seeds, "seeds", objectExcludeProperties, TypeAndID.Empty, "GZTW.AyaNova.BLL.Seed");
}
#endregion globalsettings
#region clients
private void ExportClients(ProgressForm progress)
{
ClientPickList pl = ClientPickList.GetList();
progress.Append("Dumping " + pl.Count.ToString() + " Clients");
foreach (ClientPickList.ClientPickListInfo i in pl)
{
Client c = Client.GetItem(i.ID);
//DumpObjectToFolder(tempArchiveFolder, c, "client." + c.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.Client, c.ID));
}
}
#endregion clients
#region headoffices
private void ExportHeadOffices(ProgressForm progress)
{
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "headoffice");
progress.Append("Dumping " + pl.Count.ToString() + " Head offices");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
HeadOffice c = HeadOffice.GetItem(i.ID);
//DumpObjectToFolder(tempArchiveFolder, c, "headoffice." + c.ID.ToString(), excludes, new TypeAndID(RootObjectTypes.HeadOffice, c.ID));
}
}
#endregion clients
#region contract resolver
//public class ExcludeNamedPropertiesContractResolver : DefaultContractResolver
//{
// private readonly List<string> _excludeProperties;
// public ExcludeNamedPropertiesContractResolver(List<string> excludeProperties)
// {
// _excludeProperties = excludeProperties;
// }
// protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
// {
// IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
// // only serializer properties that start with the specified character
// //properties = properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();
// properties = properties.Where(p => !_excludeProperties.Contains(p.PropertyName)).ToList();
// return properties;
// }
//}
#endregion contract resolver
//private static string EnsureValidFileName(string fileName)
//{
// //make lower and replace spaces with dashes
// fileName = fileName.ToLowerInvariant().Replace(" ", "-");
// //ensure each character is a valid path character
// foreach (char c in System.IO.Path.GetInvalidFileNameChars())
// {
// fileName = fileName.Replace(c, '_');
// }
// return fileName;
//}
//private static void makeFolderIfNotExist(string fldr, bool shouldNotExist = false)
//{
// if (Directory.Exists(fldr))
// {
// if (shouldNotExist)
// throw new System.Exception("Error: path already exists and shouldn't:\r\n" + fldr);
// return;
// }
// Directory.CreateDirectory(fldr);
//}
//private List<string> standardExcludePropertiesList
//{
// get
// {
// return new List<string>()
// {
// "CanWiki",
// "CanDuplicate",
// "IsValid",
// "IsDirty",
// "CurrentUserID",
// "IsEditing",
// "IsNew",
// "IsDeleted",
// "IsSavable",
// "Notify",
// "BrokenRulesText",
// "Docs",
// "MapQuestURL",
// "FullAddress"
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX",
// //"XXX"
// };
// }
//}
#endregion old
//eoc
}
//eons
}