diff --git a/BodyshopUploader/BodyshopUploader.csproj b/BodyshopUploader/BodyshopUploader.csproj
index a34dea5..e70a0f0 100644
--- a/BodyshopUploader/BodyshopUploader.csproj
+++ b/BodyshopUploader/BodyshopUploader.csproj
@@ -55,6 +55,9 @@
favicon.ico
+
+ ..\packages\DotNetDBF.6.0.0.3\lib\net35\DotNetDBF.dll
+
..\packages\FirebaseAuthentication.net.3.4.0\lib\netstandard1.1\Firebase.Auth.dll
@@ -267,7 +270,12 @@
Component
+
+
+ GrowlNotification.xaml
+
+
@@ -288,6 +296,10 @@
Main.xaml
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/BodyshopUploader/Models/DTO_QueueItem.cs b/BodyshopUploader/Models/DTO_QueueItem.cs
index abf959e..a4e08bd 100644
--- a/BodyshopUploader/Models/DTO_QueueItem.cs
+++ b/BodyshopUploader/Models/DTO_QueueItem.cs
@@ -13,6 +13,13 @@ namespace BodyshopUploader.Models
}
+ private dynamic _job;
+ public dynamic Job
+ {
+ get { return _job; }
+ set { SetProperty(ref _job, value); }
+ }
+
private string _filePath;
public string FilePath
{
diff --git a/BodyshopUploader/Utils/Decoder/EstimateDecoder.cs b/BodyshopUploader/Utils/Decoder/EstimateDecoder.cs
new file mode 100644
index 0000000..62b5e35
--- /dev/null
+++ b/BodyshopUploader/Utils/Decoder/EstimateDecoder.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using DotNetDBF;
+using Newtonsoft.Json.Linq;
+
+namespace BodyshopUploader.Utils.Decoder
+{
+ class EstimateDecoder
+ {
+ public static class CIECAEstimateImport
+ {
+ private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+
+ ///
+ /// Decode the set of estimate files based on the creation of an envelope file.
+ ///
+ /// Full path to the envelope file that was created/updated.
+ ///
+ public static dynamic DecodeEstimate(string FilePath)
+ {
+ //Sleep the thread so that all files can finish writing.
+ Thread.Sleep(1000);
+ dynamic ret = new JObject();
+
+ ret.CiecaId = Path.GetFileNameWithoutExtension(FilePath);
+
+ string _dir = Path.GetDirectoryName(FilePath) + @"\";
+
+ ParseAd1File(ref ret, _dir);
+ ParseVehFile(ref ret, _dir);
+ ParseStlFile(ref ret, _dir);
+ ParseTtlFile(ref ret, _dir);
+ ParseLinFile(ref ret, _dir);
+
+ return ret;
+ }
+
+ public static void ParseAd1File(ref dynamic j, string RootFilePath)
+ {
+ if (string.IsNullOrWhiteSpace(j.CiecaId.Value))
+ {
+ return;
+ }
+ logger.Trace(@"Parsing AD1 at: {0}{1}", RootFilePath, j.CiecaId.Value);
+
+ int retryNumber = 0;
+ while (retryNumber < 11)
+ {
+ try
+ {
+ using (Stream fis = File.Open(RootFilePath + j.CiecaId.Value + "A.ad1", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ var reader = new DBFReader(fis);
+ reader.SetSelectFields(new string[] { "INS_CO_NM", "CLM_NO", "OWNR_LN", "OWNR_FN", "OWNR_EA", "OWNR_PH1" });
+ var readValues = reader.NextRecord();
+ j.Claim_Source = readValues[0].ToString();
+ j.Claim_Number = readValues[1].ToString();
+ j.Owner_Ln = readValues[2].ToString();
+ j.Owner_Fn = readValues[3].ToString();
+ j.Owner_Email = readValues[4].ToString();
+ j.Owner_Phone = readValues[5].ToString();
+ return;
+ }
+ }
+ catch (IOException ex)
+ {
+ logger.Trace(ex, "Unable to open AD1 file. Retrying. ");
+ retryNumber++;
+ Thread.Sleep(3000);
+ }
+ }
+
+
+ }
+
+ public static void ParseVehFile(ref dynamic j, string RootFilePath)
+ {
+ if (string.IsNullOrWhiteSpace(j.CiecaId.Value)) { return; }
+
+ logger.Trace(@"Parsing Veh at: {0}{1}", RootFilePath, j.CiecaId.Value);
+
+ int retryNumber = 0;
+ while (retryNumber < 11)
+ {
+ try
+ {
+ using (Stream fis = File.Open(RootFilePath + j.CiecaId.Value + "v.veh", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ var reader = new DBFReader(fis);
+ reader.SetSelectFields(new string[] { "V_MODEL_YR", "V_MAKEDESC", "V_MODEL", "V_COLOR", "PLATE_NO", "V_VIN" });
+ var readValues = reader.NextRecord();
+ j.V_Model_Yr = readValues[0].ToString();
+ j.V_Make_Desc = readValues[1].ToString();
+ j.V_Model = readValues[2].ToString();
+ j.V_Color = readValues[3].ToString();
+ j.Lic_Plate = readValues[4].ToString();
+ j.V_Vin = readValues[5].ToString();
+
+ }
+ return;
+ }
+ catch (IOException ex)
+ {
+ logger.Trace(ex, "Unable to open VEH file. Retrying. ");
+ retryNumber++;
+ Thread.Sleep(3000);
+ }
+ }
+ }
+
+ public static void ParseTtlFile(ref dynamic j, string RootFilePath)
+ {
+ if (string.IsNullOrWhiteSpace(j.CiecaId.Value)) { return; }
+
+ logger.Trace(@"Parsing Ttl at: {0}{1}", RootFilePath, j.CiecaId.Value);
+
+
+
+ int retryNumber = 0;
+ while (retryNumber < 11)
+ {
+ try
+ {
+ using (Stream fis = File.Open(RootFilePath + j.CiecaId.Value + ".ttl", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ var reader = new DBFReader(fis);
+ reader.SetSelectFields(new string[] { "G_TTL_AMT" });
+ var readValues = reader.NextRecord();
+ j.Claim_Total = Convert.ToDecimal(readValues[0].ToString());
+ }
+ return;
+ }
+ catch (IOException ex)
+ {
+ logger.Trace(ex, "Unable to open TTL file. Retrying. ");
+ retryNumber++;
+ Thread.Sleep(3000);
+ }
+ }
+ }
+
+ public static void ParseStlFile(ref dynamic j, string RootFilePath)
+ {
+ if (string.IsNullOrWhiteSpace(j.CiecaId.Value)) { return; }
+
+ logger.Trace(@"Parsing Ttl at: {0}{1}", RootFilePath, j.CiecaId.Value);
+
+
+
+ int retryNumber = 0;
+ while (retryNumber < 11)
+ {
+ try
+ {
+ using (Stream fis = File.Open(RootFilePath + j.CiecaId.Value + ".stl", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ var reader = new DBFReader(fis);
+ reader.SetSelectFields(new string[] { "TTL_TYPECD", "T_HRS" });
+ var _rc = reader.RecordCount;
+ for (var i = 0; i < _rc; i++)
+ {
+ var readValues = reader.NextRecord();
+ switch (readValues[0])
+ {
+
+ //Labor Code
+ case "LAB":
+ j.BodyHrs = Convert.ToDecimal(readValues[1]);
+ break;
+ case "LAR":
+ j.RefHrs = Convert.ToDecimal(readValues[1]);
+ break;
+ }
+ }
+ }
+ return;
+ }
+ catch (IOException ex)
+ {
+ logger.Trace(ex, "Unable to open STL file. Retrying. ");
+ retryNumber++;
+ Thread.Sleep(3000);
+ }
+ }
+ }
+
+
+ public static void ParseLinFile(ref dynamic j, string RootFilePath)
+ {
+ if (string.IsNullOrWhiteSpace(j.CiecaId.Value)) { return; }
+
+ logger.Trace(@"Parsing Ttl at: {0}{1}", RootFilePath, j.CiecaId.Value);
+ //j.JobSublets = new List();
+
+ string _maxSupp = "";
+
+ int retryNumber = 0;
+ while (retryNumber < 11)
+ {
+ try
+ {
+ using (Stream fis = File.Open(RootFilePath + j.CiecaId.Value + ".lin", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ var reader = new DBFReader(fis);
+ reader.SetSelectFields(new string[] { "PART_TYPE", "LINE_DESC", "UNQ_SEQ", "LINE_IND" });
+ var _rc = reader.RecordCount;
+ for (var i = 0; i < _rc; i++)
+ {
+ var readValues = reader.NextRecord();
+ //Find Max Supplement Number
+ if (string.Compare(_maxSupp, readValues[3].ToString()) < 0)
+ {
+ _maxSupp = readValues[3].ToString();
+ }
+
+ switch (readValues[3])
+ {
+
+ //Labor Code
+ case "PAS":
+ case "PASL":
+ //j.JobSublets.Add(new JobSublet()
+ //{
+ // SubletDesc = readValues[1].ToString(),
+ // Unq_Seq = Convert.ToInt32(readValues[2])
+ //});
+ break;
+ }
+ }
+ }
+ j.MaxSupplement = _maxSupp;
+ return;
+ }
+ catch (IOException ex)
+ {
+ logger.Trace(ex, "Unable to open LIN file. Retrying. ");
+ retryNumber++;
+ Thread.Sleep(3000);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/BodyshopUploader/Utils/Growls/GrowlNotification.xaml b/BodyshopUploader/Utils/Growls/GrowlNotification.xaml
new file mode 100644
index 0000000..42dd3ea
--- /dev/null
+++ b/BodyshopUploader/Utils/Growls/GrowlNotification.xaml
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BodyshopUploader/Utils/Growls/GrowlNotification.xaml.cs b/BodyshopUploader/Utils/Growls/GrowlNotification.xaml.cs
new file mode 100644
index 0000000..6820078
--- /dev/null
+++ b/BodyshopUploader/Utils/Growls/GrowlNotification.xaml.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+
+namespace BodyshopUploader.Utils.Growls
+{
+ public partial class GrowlNotification
+ {
+ private const byte MAX_NOTIFICATIONS = 4;
+ private int count;
+ public Notifications Notifications = new Notifications();
+ private readonly Notifications buffer = new Notifications();
+ public ViewModels.MainViewModel ShellVm;
+ public GrowlNotification(ViewModels.MainViewModel shellViewModel)
+ {
+ InitializeComponent();
+ ShellVm = shellViewModel;
+ NotificationsControl.DataContext = Notifications;
+ var desktopWorkingArea = System.Windows.SystemParameters.WorkArea;
+ this.Left = desktopWorkingArea.Right - 425;
+ //this.Top = desktopWorkingArea.Bottom - 425;
+ this.Top = 50;
+ }
+
+ public void AddNotification(Notification notification)
+ {
+ notification.Id = count++;
+ if (Notifications.Count + 1 > MAX_NOTIFICATIONS)
+ buffer.Add(notification);
+ else
+ Notifications.Add(notification);
+ //Show window if there're notifications
+ if (Notifications.Count > 0 && !IsActive)
+ Show();
+ }
+ public void RemoveNotification(Notification notification)
+ {
+ if (Notifications.Contains(notification))
+ Notifications.Remove(notification);
+ if (buffer.Count > 0)
+ {
+ Notifications.Add(buffer[0]);
+ buffer.RemoveAt(0);
+ }
+ //Close window if there's nothing to show
+ if (Notifications.Count < 1)
+ Hide();
+ }
+ private void NotificationWindowSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (e.NewSize.Height != 0.0)
+ return;
+ var element = sender as Grid;
+ RemoveNotification(Notifications.First(
+ n => n.Id == Int32.Parse(element.Tag.ToString())));
+ }
+
+ private void NotificationWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ Notification n = (Notification)((Grid)sender).DataContext;
+ BringWindowToFront();
+ RemoveNotification(n);
+ }
+
+ static void BringWindowToFront()
+ {
+ var currentProcess = Process.GetCurrentProcess();
+ var processes = Process.GetProcessesByName(currentProcess.ProcessName);
+ var process = processes.FirstOrDefault(p => p.Id == currentProcess.Id);
+ if (process == null) return;
+
+ SetForegroundWindow(process.MainWindowHandle);
+ }
+
+ [DllImport("user32.dll")]
+ static extern bool SetForegroundWindow(IntPtr hWnd);
+ }
+}
diff --git a/BodyshopUploader/Utils/Growls/Notification.cs b/BodyshopUploader/Utils/Growls/Notification.cs
new file mode 100644
index 0000000..de38944
--- /dev/null
+++ b/BodyshopUploader/Utils/Growls/Notification.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BodyshopUploader.Utils.Growls
+{
+ public class Notification : INotifyPropertyChanged
+ {
+ private string message;
+ public string Message
+ {
+ get { return message; }
+
+ set
+ {
+ if (message == value) return;
+ message = value;
+ OnPropertyChanged("Message");
+ }
+ }
+
+ private int id;
+ public int Id
+ {
+ get { return id; }
+
+ set
+ {
+ if (id == value) return;
+ id = value;
+ OnPropertyChanged("Id");
+ }
+ }
+
+ private int threadid;
+ public int ThreadId
+ {
+ get { return threadid; }
+
+ set
+ {
+ if (threadid == value) return;
+ threadid = value;
+ OnPropertyChanged("ThreadId");
+ }
+ }
+
+ private string imageUrl;
+ public string ImageUrl
+ {
+ get { return imageUrl; }
+
+ set
+ {
+ if (imageUrl == value) return;
+ imageUrl = value;
+ OnPropertyChanged("ImageUrl");
+ }
+ }
+
+
+ private string title;
+ public string Title
+ {
+ get { return title; }
+
+ set
+ {
+ if (title == value) return;
+ title = value;
+ OnPropertyChanged("Title");
+ }
+ }
+
+ private string subtitle;
+ public string Subtitle
+ {
+ get { return subtitle; }
+
+ set
+ {
+ if (subtitle == value) return;
+ subtitle = value;
+ OnPropertyChanged("Subtitle");
+ }
+ }
+
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ var handler = PropertyChanged;
+ if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+
+ public class Notifications : ObservableCollection { }
+}
diff --git a/BodyshopUploader/Utils/JobProcessingQueue.cs b/BodyshopUploader/Utils/JobProcessingQueue.cs
index 14cb41f..3646e86 100644
--- a/BodyshopUploader/Utils/JobProcessingQueue.cs
+++ b/BodyshopUploader/Utils/JobProcessingQueue.cs
@@ -57,9 +57,7 @@ namespace BodyshopUploader.Utils
try
{
Thread.Sleep(1000);//Allow a small amount of time to pass before processing the queue item so that any writes can finish.
-
DecodeQueueItemJob(item);
-
UpsertQueueItem(item);
}
catch
@@ -74,12 +72,13 @@ namespace BodyshopUploader.Utils
{
//Process the job.
logger.Info("Should process the job here. {0}", item.FilePath);
+ item.Job = Utils.Decoder.EstimateDecoder.CIECAEstimateImport.DecodeEstimate(item.FilePath);
}
private static void UpsertQueueItem(DTO_QueueItem item)
{
//Save the job to the DB.
- logger.Info("Should upsert the job graphqlly here. {0}", item.FilePath);
+ logger.Info("Should upsert the job graphqlly here. {0}", item.Job);
_jobs.Dequeue();
}
diff --git a/BodyshopUploader/ViewModels/MainViewModel.commands.cs b/BodyshopUploader/ViewModels/MainViewModel.commands.cs
index 9598ebe..d538ebc 100644
--- a/BodyshopUploader/ViewModels/MainViewModel.commands.cs
+++ b/BodyshopUploader/ViewModels/MainViewModel.commands.cs
@@ -63,7 +63,7 @@ namespace BodyshopUploader.ViewModels
if (_removeMonitoringPathCommand == null)
{
_removeMonitoringPathCommand = new RelayCommand(
- p => true,
+ p => FolderMonitors.Count == 0,
p => RemoveFolderMonitoringPath(p as string)
);
}
diff --git a/BodyshopUploader/ViewModels/MainViewModel.cs b/BodyshopUploader/ViewModels/MainViewModel.cs
index 88b87c7..28eefe9 100644
--- a/BodyshopUploader/ViewModels/MainViewModel.cs
+++ b/BodyshopUploader/ViewModels/MainViewModel.cs
@@ -1,4 +1,5 @@
-using GraphQL.Client;
+using BodyshopUploader.Utils.Growls;
+using GraphQL.Client;
using GraphQL.Common.Request;
using System;
using System.Collections.Generic;
@@ -17,6 +18,7 @@ namespace BodyshopUploader.ViewModels
public MainViewModel()
{
logger.Trace("Main VM Created.");
+ Growler = new GrowlNotification(this);
//Create Variables
if (MonitoringPaths == null) MonitoringPaths = new ObservableCollection();
@@ -75,6 +77,17 @@ namespace BodyshopUploader.ViewModels
public async Task TestGql()
{
+ Notification _n = new Notification()
+ {
+ Id = 123,
+ ThreadId = 123,
+ Title = "This is a title",
+ Subtitle = "Subtitle",
+ Message = "Somethin"
+ };
+ Growler.AddNotification(_n);
+
+
var r = new GraphQLRequest
{
Query = @"
diff --git a/BodyshopUploader/ViewModels/MainViewModel.props.cs b/BodyshopUploader/ViewModels/MainViewModel.props.cs
index 363a33d..34370e8 100644
--- a/BodyshopUploader/ViewModels/MainViewModel.props.cs
+++ b/BodyshopUploader/ViewModels/MainViewModel.props.cs
@@ -4,17 +4,13 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using BodyshopUploader.Utils.Growls;
namespace BodyshopUploader.ViewModels
{
public partial class MainViewModel : BaseViewModel
{
- private int _progress = 5;
- public int Progress
- {
- get { return _progress; }
- set { SetProperty(ref _progress, value); }
- }
+ public GrowlNotification Growler;
private ObservableCollection _folderMonitors = new ObservableCollection() ;
public ObservableCollection FolderMonitors
diff --git a/BodyshopUploader/packages.config b/BodyshopUploader/packages.config
index e5b3837..7986984 100644
--- a/BodyshopUploader/packages.config
+++ b/BodyshopUploader/packages.config
@@ -1,5 +1,6 @@
+