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 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(); 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 SingleObjectMenuOptions(RootObjectTypes objectType, object ayaNovaObject) { if (!ObjectsWeCanDealWith.Contains(objectType)) return null; List list = new List(); list.Add(new AyaNovaPluginMenuItem("V8 Export", "Export to AyaNova 8 server", null, null)); return list; } public List MultipleObjectsMenuOptions(RootObjectTypes objectType) { return null; } public bool CommandSelectedForList(string commandKey, RootObjectTypes objectType, List 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; } //here because we logged in fine and can proceed //MessageBox.Show("Login successful! JWT is " + util.JWT); //Only one command DoExport(); } #endregion private Dictionary Map = new Dictionary(); private Dictionary TagMap = new Dictionary(); private Dictionary CustomFieldLocaleKeys = new Dictionary();//holds custom field Raven as key and v7 custom text for that field for later export private string ImportTag = "v7-import"; /// /// 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 /// private async void DoExport() { Cursor.Current = Cursors.WaitCursor; //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(); CustomFieldLocaleKeys.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: * * wiki / attached docs * locales * * * * */ //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"); ExportUnitModelCategories(progress); ExportUnitServiceTypes(progress); ExportWorkorderItemTypes(progress); ExportRegions(progress); ExportClientGroups(progress); ExportWorkorderCategories(progress); ExportPartCategories(progress); ExportScheduleableUserGroups(progress); ExportDispatchZones(progress); ExportUserSkills(progress); ExportUserCertifications(progress); progress.Op("Exporting objects"); //BIZ objects await ExportUsers(progress); // await ExportLocales(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 progress.Append("Export completed"); progress.Op(""); } 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(); Cursor.Current = Cursors.Default; } //----------------------------------- //endof method } #region 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"); //Attachments and wiki string AdminWikiContent = null; var hasWiki = WikiPage.HasWiki(User.AdministratorID); if (hasWiki) { await ExportAttachments(new TypeAndID(RootObjectTypes.User, User.AdministratorID), progress); AdminWikiContent = GetWikiContent(new TypeAndID(RootObjectTypes.User, admin.ID)); } string adminCustomFields = null; //Custom fields? if (ShouldExportCustom) { adminCustomFields = CustomFieldData(admin, DateCustomFields); } //check if we need to do anything with the manager account 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) { List tags = new List(); tags.Add(ImportTag); //skip administrator user fields //but do export administrator if (i.ID == User.AdministratorID) continue; User c = User.GetItem(i.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(new TypeAndID(RootObjectTypes.User, c.ID), progress); d.wiki = GetWikiContent(new TypeAndID(RootObjectTypes.User, c.ID)); } //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; await util.PutAsync("UserOptions/" + RavenId.ToString(), d.ToString()); } //Attachments / FILES await ExportAttachments(new TypeAndID(RootObjectTypes.User, c.ID), 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) { 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); } //todo fixup post import progress.Append("TODO: User, fixup translationID, headofficeid, clientid vendorid, phone1, phone2, pagermaxtext"); } #endregion clients #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 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> ExportCustomFieldSchema(ObjectCustomFields ocf, string v7CustomFieldObjectName, string RavenCustomTranslationKeyObjectName) { var ret = new List(); //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) { 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(); Map.Add(af.ID, ravenId); } progress.SubOp(""); } #endregion attachments #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, ""); } //todo: fixup font size, try to convert to heading tags instead //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 SmartHrefHandling = true // remove markdown output for links where appropriate }; var converter = new ReverseMarkdown.Converter(config); string res = converter.Convert(content); return res; } #endregion wiki #region TAGS private void Tagit(Guid g, List 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 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 locales private void ExportLocales(ProgressForm progress) { // List objectExcludeProperties = new List(standardExcludePropertiesList); //Skip stock locales already handled in Raven List SkipLocales = new List(); SkipLocales.Add("Deutsch"); SkipLocales.Add("English"); SkipLocales.Add("Español"); SkipLocales.Add("Français"); LocaleList l = LocaleList.GetList(); progress.Append("Dumping " + l.Count.ToString() + " Locales"); foreach (LocaleList.LocaleListInfo i in l) { if (!SkipLocales.Contains(i.Locale)) { LocalizedTextTable lt = LocalizedTextTable.Load(i.Locale); //DumpObjectToFolder(tempArchiveFolder, lt.LT, "translation." + EnsureValidFileName(i.Locale), objectExcludeProperties, TypeAndID.Empty, "GZTW.AyaNova.BLL.Translation"); } } } #endregion locales #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 objectExcludeProperties = new List(standardExcludePropertiesList); progress.Append("Dumping seeds"); //create a new object with the id numbers in it and then dump it WorkorderPMList pml = WorkorderPMList.GetList(" \r\n" + " \r\n" + " \r\n" + " "); 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 _excludeProperties; // public ExcludeNamedPropertiesContractResolver(List excludeProperties) // { // _excludeProperties = excludeProperties; // } // protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) // { // IList 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 standardExcludePropertiesList //{ // get // { // return new List() // { // "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 }