diff --git a/source/Plugins/AyaNova.Plugin.V8/V8.cs b/source/Plugins/AyaNova.Plugin.V8/V8.cs index 4fb1bfb..545bec7 100644 --- a/source/Plugins/AyaNova.Plugin.V8/V8.cs +++ b/source/Plugins/AyaNova.Plugin.V8/V8.cs @@ -141,66 +141,54 @@ namespace AyaNova.PlugIn.V8 MessageBox.Show("Login successful! JWT is " + util.JWT); //Only one command - // DumpIt(); + DoExport(); } #endregion + private Dictionary Map = new Dictionary(); + private Dictionary TagMap = new Dictionary(); /// /// 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 void DumpIt() + private void DoExport() { + Map.Clear(); - string dumpname = "ayanova.data.dump." + DateTime.Now.ToString("yyyy-MM-d--HH-mm-ss"); - string dumpfolder = string.Empty; -#if(DEBUG) - dumpfolder = @"c:\temp"; -#else - MessageBox.Show("Select a location to dump AyaNova data"); - using (var folderDialog = new FolderBrowserDialog()) - { - if (folderDialog.ShowDialog() == DialogResult.OK) - { - dumpfolder = folderDialog.SelectedPath; - } - else - { - return; - } - } -#endif - //create a temporary folder to generate JSON in - string tempArchiveFolder = dumpfolder + Path.DirectorySeparatorChar + dumpname; - string zipName = dumpfolder + Path.DirectorySeparatorChar + dumpname + ".zip"; - makeFolderIfNotExist(tempArchiveFolder, true); //Show progress form ProgressForm progress = new ProgressForm(); progress.Show(); progress.StartedImport(); - progress.Append("Dumping data to " + tempArchiveFolder); + progress.Append("Exporting data to AyaNova server @ " + util.ApiBaseUrl); - //DUMP IT! + //Export in correct order: + + //TAGS + ExportUnitModelCategories(progress); + ExportUnitServiceTypes(progress); + ExportWorkorderItemTypes(progress); + ExportRegions(progress); + ExportClientGroups(progress); + ExportWorkorderCategories(progress); + ExportPartCategories(progress); + ExportScheduleableUserGroups(progress); + ExportDispatchZones(progress); + + + //dumpUsers(tempArchiveFolder, progress); + //dumpGlobalSettings(tempArchiveFolder, progress); + //dumpLocales(tempArchiveFolder, progress); + + //dumpSeedNumbers(tempArchiveFolder, progress); + //dumpClients(tempArchiveFolder, progress); + //dumpHeadOffices(tempArchiveFolder, progress); + // + - dumpUsers(tempArchiveFolder, progress); - dumpGlobalSettings(tempArchiveFolder, progress); - dumpLocales(tempArchiveFolder, progress); - dumpRegions(tempArchiveFolder, progress); - dumpSeedNumbers(tempArchiveFolder, progress); - dumpClients(tempArchiveFolder, progress); - dumpHeadOffices(tempArchiveFolder, progress); - dumpUnitModelCategories(tempArchiveFolder, progress); - dumpUnitServiceTypes(tempArchiveFolder, progress); - dumpWorkorderItemTypes(tempArchiveFolder, progress); - dumpClientGroups(tempArchiveFolder, progress); - dumpWorkorderCategories(tempArchiveFolder, progress); - dumpPartCategories(tempArchiveFolder, progress); - dumpScheduleableUserGroups(tempArchiveFolder, progress); - dumpDispatchZones(tempArchiveFolder, progress); //NOTE: when get to PRIORITY, or WORKORDER STATUS be sure to add color code as per already done in USER export @@ -223,10 +211,10 @@ namespace AyaNova.PlugIn.V8 - #region Object dump methods + #region Object Export methods #region Global settings - private void dumpGlobalSettings(string tempArchiveFolder, ProgressForm progress) + private void ExportGlobalSettings(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); progress.Append("Dumping Global Settings"); @@ -235,7 +223,7 @@ namespace AyaNova.PlugIn.V8 #endregion globalsettings #region locales - private void dumpLocales(string tempArchiveFolder, ProgressForm progress) + private void ExportLocales(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); @@ -260,7 +248,7 @@ namespace AyaNova.PlugIn.V8 #endregion locales #region REGIONS - private void dumpRegions(string tempArchiveFolder, ProgressForm progress) + private void ExportRegions(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); objectExcludeProperties.Add("ContractName"); @@ -271,7 +259,7 @@ namespace AyaNova.PlugIn.V8 { Region o = Region.GetItem(i.LT_Region_Label_Name.Value); - DumpObjectToFolder(tempArchiveFolder, o, "region." + o.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.Region,o.ID)); + DumpObjectToFolder(tempArchiveFolder, o, "region." + o.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.Region, o.ID)); } } @@ -286,7 +274,7 @@ namespace AyaNova.PlugIn.V8 public int WorkorderNumberStartSeed = 1; public int PreventiveMaintenanceNumberStartSeed = 1; } - private void dumpSeedNumbers(string tempArchiveFolder, ProgressForm progress) + private void ExportSeedNumbers(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); progress.Append("Dumping seeds"); @@ -314,7 +302,7 @@ namespace AyaNova.PlugIn.V8 #endregion globalsettings #region clients - private void dumpClients(string tempArchiveFolder, ProgressForm progress) + private void ExportClients(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); objectExcludeProperties.Add("ContractName"); @@ -324,14 +312,14 @@ namespace AyaNova.PlugIn.V8 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)); + DumpObjectToFolder(tempArchiveFolder, c, "client." + c.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.Client, c.ID)); } } #endregion clients #region headoffices - private void dumpHeadOffices(string tempArchiveFolder, ProgressForm progress) + private void ExportHeadOffices(ProgressForm progress) { List excludes = new List(standardExcludePropertiesList); //excludes.Add("ContractInEffect"); @@ -342,13 +330,13 @@ namespace AyaNova.PlugIn.V8 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)); + DumpObjectToFolder(tempArchiveFolder, c, "headoffice." + c.ID.ToString(), excludes, new TypeAndID(RootObjectTypes.HeadOffice, c.ID)); } } #endregion clients #region users - private void dumpUsers(string tempArchiveFolder, ProgressForm progress) + private void ExportUsers(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); @@ -376,50 +364,44 @@ namespace AyaNova.PlugIn.V8 JObject xtra = new JObject(); xtra.Add("hexaScheduleBackColor", System.Drawing.ColorTranslator.ToHtml(System.Drawing.Color.FromArgb(c.ScheduleBackColor))); - DumpObjectToFolder(tempArchiveFolder, c, "user." + c.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.User,c.ID), null, xtra); + DumpObjectToFolder(tempArchiveFolder, c, "user." + c.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.User, c.ID), null, xtra); } } #endregion clients #region Unitmodelcategories - private void dumpUnitModelCategories(string tempArchiveFolder, ProgressForm progress) + private void ExportUnitModelCategories(ProgressForm progress) { - List objectExcludeProperties = new List(standardExcludePropertiesList); - //objectExcludeProperties.Add("ContractName"); - //objectExcludeProperties.Add("uiHasTechNotes"); UnitModelCategories l = UnitModelCategories.GetItems(); - progress.Append("Dumping " + l.Count.ToString() + " Unit model categories"); + progress.Append("Exporting " + l.Count.ToString() + " Unit model categories"); + foreach (UnitModelCategory i in l) { - - DumpObjectToFolder(tempArchiveFolder, i, "unitmodelcategory." + i.ID.ToString(), objectExcludeProperties, TypeAndID.Empty); - + TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "unitmodelcategory")); } + } #endregion #region Unitservicetypes - private void dumpUnitServiceTypes(string tempArchiveFolder, ProgressForm progress) + private void ExportUnitServiceTypes(ProgressForm progress) { - List objectExcludeProperties = new List(standardExcludePropertiesList); - //objectExcludeProperties.Add("ContractName"); - //objectExcludeProperties.Add("uiHasTechNotes"); UnitServiceTypes l = UnitServiceTypes.GetItems(); progress.Append("Dumping " + l.Count.ToString() + " Unit service types"); foreach (UnitServiceType i in l) { - DumpObjectToFolder(tempArchiveFolder, i, "unitservicetype." + i.ID.ToString(), objectExcludeProperties, TypeAndID.Empty); + TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "unitservicetype")); } } #endregion #region WorkorderItemTypes - private void dumpWorkorderItemTypes(string tempArchiveFolder, ProgressForm progress) + private void ExportWorkorderItemTypes(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); //objectExcludeProperties.Add("ContractName"); @@ -437,7 +419,7 @@ namespace AyaNova.PlugIn.V8 #endregion #region Client groups - private void dumpClientGroups(string tempArchiveFolder, ProgressForm progress) + private void ExportClientGroups(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); //objectExcludeProperties.Add("ContractName"); @@ -455,7 +437,7 @@ namespace AyaNova.PlugIn.V8 #endregion #region Workorder categories - private void dumpWorkorderCategories(string tempArchiveFolder, ProgressForm progress) + private void ExportWorkorderCategories(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); //objectExcludeProperties.Add("ContractName"); @@ -473,7 +455,7 @@ namespace AyaNova.PlugIn.V8 #endregion #region Part categories - private void dumpPartCategories(string tempArchiveFolder, ProgressForm progress) + private void ExportPartCategories(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); //objectExcludeProperties.Add("ContractName"); @@ -491,7 +473,7 @@ namespace AyaNova.PlugIn.V8 #endregion #region ScheduleableUserGroups - private void dumpScheduleableUserGroups(string tempArchiveFolder, ProgressForm progress) + private void ExportScheduleableUserGroups(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); objectExcludeProperties.Add("ContractName"); @@ -508,7 +490,7 @@ namespace AyaNova.PlugIn.V8 #endregion clients #region Dispatch zones - private void dumpDispatchZones(string tempArchiveFolder, ProgressForm progress) + private void ExportDispatchZones(ProgressForm progress) { List objectExcludeProperties = new List(standardExcludePropertiesList); //objectExcludeProperties.Add("ContractName"); @@ -536,7 +518,7 @@ namespace AyaNova.PlugIn.V8 /// /// /// - private void DumpObjectToFolder(string tempArchiveFolder, object o, string objectFileName, List excludeProperties, + private void ExportObjectToFolder(object o, string objectFileName, List excludeProperties, TypeAndID tid, string forceTypeString = "", JObject jExtra = null) { @@ -612,69 +594,79 @@ namespace AyaNova.PlugIn.V8 */ #endregion - private void DumpWikiPageAndAttachments(TypeAndID tid, string wikiOutputPath) + private void ExportWikiPageAndAttachments(TypeAndID tid, string wikiOutputPath) { //may not exist if (!WikiPage.HasWiki(tid.ID)) return; - WikiPage w= WikiPage.GetItem(tid); - var content= w.GetContentAsString; - AyaFileList fl = AyaFileList.GetList(w.ID); + WikiPage w = WikiPage.GetItem(tid); + var content = w.GetContentAsString; + AyaFileList fl = AyaFileList.GetList(w.ID); - if (string.IsNullOrWhiteSpace(content) && fl.Count < 1) return; + if (string.IsNullOrWhiteSpace(content) && fl.Count < 1) return; - makeFolderIfNotExist(wikiOutputPath); + makeFolderIfNotExist(wikiOutputPath); - if (!string.IsNullOrWhiteSpace(content)) - { - //write out the html wiki page - File.WriteAllText(wikiOutputPath + Path.DirectorySeparatorChar + "w.html", content); - } + if (!string.IsNullOrWhiteSpace(content)) + { + //write out the html wiki page + File.WriteAllText(wikiOutputPath + Path.DirectorySeparatorChar + "w.html", content); + } //files - foreach (AyaFileList.AyaFileListInfo i in fl) - { - //WikiFileInfo fi = new WikiFileInfo(); - // fi.Id = i.LT_O_AyaFile.Value.ToString(); - // fi.Name = i.LT_O_AyaFile.Display; - // fi.Size = i.LT_AyaFile_Label_FileSize; - // fi.Creator = i.LT_Common_Label_Creator.Display; - // fi.Created = i.LT_Common_Label_Created.ToString(); - // ret.Add(fi); - - - - //save each file plus file info into their own folder by ayafile id this is because ayafiles can be dupe names and we need the wiki info to fixup the last created date etc - var filePath = wikiOutputPath + Path.DirectorySeparatorChar + i.LT_O_AyaFile.Value.ToString(); - makeFolderIfNotExist(filePath);//output/objectype/client.f861ec01-8bde-46e1-9849-fcee9b42f05e/files/d5461ec01-8bde-46e1-9849-fcee9b42f0ff34/ + foreach (AyaFileList.AyaFileListInfo i in fl) + { + //WikiFileInfo fi = new WikiFileInfo(); + // fi.Id = i.LT_O_AyaFile.Value.ToString(); + // fi.Name = i.LT_O_AyaFile.Display; + // fi.Size = i.LT_AyaFile_Label_FileSize; + // fi.Creator = i.LT_Common_Label_Creator.Display; + // fi.Created = i.LT_Common_Label_Created.ToString(); + // ret.Add(fi); - var af = AyaFile.GetItem(i.LT_O_AyaFile.Value); - if (af == null) continue; - af.WriteToDisk(filePath, af.Name); - var fileInfo = new { name = i.LT_O_AyaFile.Display, created = i.LT_Common_Label_Created, creator = i.LT_Common_Label_Creator.Value, - mimetype = af.mimeType, id = af.ID, size = af.FileSize, ayafiletype = af.FileType, rootobjectid = af.RootObjectID, rootobjecttype = af.RootObjectType }; - JsonSerializer serializer = new JsonSerializer(); - serializer.NullValueHandling = NullValueHandling.Include; - + //save each file plus file info into their own folder by ayafile id this is because ayafiles can be dupe names and we need the wiki info to fixup the last created date etc + var filePath = wikiOutputPath + Path.DirectorySeparatorChar + i.LT_O_AyaFile.Value.ToString(); + makeFolderIfNotExist(filePath);//output/objectype/client.f861ec01-8bde-46e1-9849-fcee9b42f05e/files/d5461ec01-8bde-46e1-9849-fcee9b42f0ff34/ + + var af = AyaFile.GetItem(i.LT_O_AyaFile.Value); + if (af == null) continue; + af.WriteToDisk(filePath, af.Name); + + var fileInfo = new + { + name = i.LT_O_AyaFile.Display, + created = i.LT_Common_Label_Created, + creator = i.LT_Common_Label_Creator.Value, + mimetype = af.mimeType, + id = af.ID, + size = af.FileSize, + ayafiletype = af.FileType, + rootobjectid = af.RootObjectID, + rootobjecttype = af.RootObjectType + }; + + JsonSerializer serializer = new JsonSerializer(); + serializer.NullValueHandling = NullValueHandling.Include; + #if(DEBUG) - serializer.Formatting = Formatting.Indented; -#endif - JObject jo = JObject.FromObject(fileInfo, serializer); - + serializer.Formatting = Formatting.Indented; +#endif + JObject jo = JObject.FromObject(fileInfo, serializer); - using (StreamWriter sw = new StreamWriter(filePath+Path.DirectorySeparatorChar+"meta.json")) - using (JsonWriter writer = new JsonTextWriter(sw)) - { - // serializer.Serialize(writer, o); - serializer.Serialize(writer, jo); - } + using (StreamWriter sw = new StreamWriter(filePath + Path.DirectorySeparatorChar + "meta.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { - } + // serializer.Serialize(writer, o); + serializer.Serialize(writer, jo); + } + + } } #endregion dump diff --git a/source/Plugins/AyaNova.Plugin.V8/util.cs b/source/Plugins/AyaNova.Plugin.V8/util.cs index 7a2a6de..8ed82c3 100644 --- a/source/Plugins/AyaNova.Plugin.V8/util.cs +++ b/source/Plugins/AyaNova.Plugin.V8/util.cs @@ -17,7 +17,7 @@ namespace AyaNova.PlugIn.V8 const string API_BASE_ROUTE = "api/v8/"; static HttpClient client = new HttpClient(); //url once known to be good - static string ApiBaseUrl { get; set; } + internal static string ApiBaseUrl { get; set; } internal static string JWT { get; set; } static bool Initialized { get; set; } @@ -183,6 +183,38 @@ namespace AyaNova.PlugIn.V8 } #endregion + #region Misc utils + + public static string NormalizeTag(string inObj) + { + //Must be lowercase per rules + //This may be naive when we get international customers but for now supporting utf-8 and it appears it's safe to do this with unicode + inObj = inObj.ToLowerInvariant(); + //No spaces in tags, replace with dashes + inObj = inObj.Replace(" ", "-"); + //Remove multiple dash sequences + inObj = System.Text.RegularExpressions.Regex.Replace(inObj, "-+", "-"); + //Ensure doesn't start or end with a dash + inObj = inObj.Trim('-'); + //No longer than 255 characters + inObj = MaxLength(inObj, 255); + return inObj; + } + + /// + /// Trim a string if necessary + /// + /// + /// + /// + public static string MaxLength(string s, int maxLength) + { + if (s.Length > maxLength) + s = s.Substring(0, maxLength); + return s; + } + + #endregion }//eoc