diff --git a/BodyshopUploader/BodyshopUploader.csproj b/BodyshopUploader/BodyshopUploader.csproj
index e1ee7c2..a34dea5 100644
--- a/BodyshopUploader/BodyshopUploader.csproj
+++ b/BodyshopUploader/BodyshopUploader.csproj
@@ -248,6 +248,8 @@
MSBuild:Compile
Designer
+
+
Resources.es-MX.resx
True
@@ -262,7 +264,11 @@
+
+ Component
+
+
@@ -334,9 +340,7 @@
-
-
-
+
False
diff --git a/BodyshopUploader/Models/DTO_Base.cs b/BodyshopUploader/Models/DTO_Base.cs
new file mode 100644
index 0000000..06dc769
--- /dev/null
+++ b/BodyshopUploader/Models/DTO_Base.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BodyshopUploader.Models
+{
+ public abstract class DTO_Base : INotifyPropertyChanged
+ {
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected bool SetProperty(ref T storage, T value, [CallerMemberName] String propertyName = null)
+ {
+ if (object.Equals(storage, value)) return false;
+
+ storage = value;
+ this.OnPropertyChanged(propertyName);
+ return true;
+ }
+ protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ var eventHandler = this.PropertyChanged;
+ if (eventHandler != null)
+ {
+ eventHandler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+ }
+}
+
diff --git a/BodyshopUploader/Models/DTO_QueueItem.cs b/BodyshopUploader/Models/DTO_QueueItem.cs
new file mode 100644
index 0000000..abf959e
--- /dev/null
+++ b/BodyshopUploader/Models/DTO_QueueItem.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BodyshopUploader.Models
+{
+ public class DTO_QueueItem : DTO_Base
+ {
+ public DTO_QueueItem()
+ {
+
+ }
+
+ private string _filePath;
+ public string FilePath
+ {
+ get { return _filePath; }
+ set { SetProperty(ref _filePath, value); }
+ }
+ }
+}
diff --git a/BodyshopUploader/Properties/Resources.Designer.cs b/BodyshopUploader/Properties/Resources.Designer.cs
index 8b7d30a..ab23683 100644
--- a/BodyshopUploader/Properties/Resources.Designer.cs
+++ b/BodyshopUploader/Properties/Resources.Designer.cs
@@ -114,6 +114,24 @@ namespace BodyshopUploader.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Start All Monitors.
+ ///
+ public static string Label_StartAllMonitors {
+ get {
+ return ResourceManager.GetString("Label_StartAllMonitors", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Stop All Monitors.
+ ///
+ public static string Label_StopAllMonitors {
+ get {
+ return ResourceManager.GetString("Label_StopAllMonitors", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Login.
///
diff --git a/BodyshopUploader/Properties/Resources.resx b/BodyshopUploader/Properties/Resources.resx
index 993bb3e..13594ef 100644
--- a/BodyshopUploader/Properties/Resources.resx
+++ b/BodyshopUploader/Properties/Resources.resx
@@ -135,6 +135,12 @@
Add Path
+
+ Start All Monitors
+
+
+ Stop All Monitors
+
Login
diff --git a/BodyshopUploader/Utils/CIECAMonitor.cs b/BodyshopUploader/Utils/CIECAMonitor.cs
new file mode 100644
index 0000000..1940f35
--- /dev/null
+++ b/BodyshopUploader/Utils/CIECAMonitor.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BodyshopUploader.Models;
+
+namespace BodyshopUploader.Utils
+{
+ public class CIECAMonitor : FileSystemWatcher
+ {
+ private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+
+ public CIECAMonitor()
+ {
+ Init();
+ }
+
+ public CIECAMonitor(String inDirectoryPath)
+ : base(inDirectoryPath)
+ {
+ Init();
+ }
+
+ public CIECAMonitor(String inDirectoryPath, string inFilter)
+ : base(inDirectoryPath, inFilter)
+ {
+ Init();
+ }
+
+
+ private void Init()
+ {
+ IncludeSubdirectories = false;
+ // Eliminate duplicates when timestamp doesn't change
+ Filter = "*.env";
+ NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
+ //NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size; // The default also has NotifyFilters.LastWrite
+ EnableRaisingEvents = true;
+ Created += Watcher_Created;
+ Changed += Watcher_Changed;
+ //Deleted += Watcher_Deleted;
+ //Renamed += Watcher_Renamed;
+ Error += Wathcer_Error;
+ logger.Debug("CIECA Folder watcher started for path: {0}", Path);
+ }
+
+ private void Wathcer_Error(object sender, ErrorEventArgs e)
+ {
+ logger.Error("CIECA monitor encountered an error. Trying to restart. {0}", e.ToString());
+ ((FileSystemWatcher)sender).EnableRaisingEvents = true;
+ }
+
+ public void Watcher_Created(object source, FileSystemEventArgs inArgs)
+ {
+ logger.Trace("New CIECA fileset detected | {0}", inArgs.FullPath, inArgs.ChangeType);
+ JobProcessingQueue.Enqueue(new DTO_QueueItem() { FilePath = inArgs.FullPath });
+ }
+
+ public void Watcher_Changed(object sender, FileSystemEventArgs inArgs)
+ {
+ logger.Trace("Updated CIECA fileset detected | {0}", inArgs.FullPath);
+ JobProcessingQueue.Enqueue(new DTO_QueueItem() { FilePath = inArgs.FullPath });
+ }
+ public void Watcher_Deleted(object sender, FileSystemEventArgs inArgs)
+ {
+ }
+
+ public void Watcher_Renamed(object sender, RenamedEventArgs inArgs)
+ {
+ }
+
+ private void InitializeComponent()
+ {
+ ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
+ //
+ // FolderMonitor
+ //
+ this.IncludeSubdirectories = false;
+ ((System.ComponentModel.ISupportInitialize)(this)).EndInit();
+
+ }
+ }
+}
diff --git a/BodyshopUploader/Utils/JobProcessingQueue.cs b/BodyshopUploader/Utils/JobProcessingQueue.cs
new file mode 100644
index 0000000..14cb41f
--- /dev/null
+++ b/BodyshopUploader/Utils/JobProcessingQueue.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using BodyshopUploader.Utils;
+using BodyshopUploader.Models;
+
+namespace BodyshopUploader.Utils
+{
+ public static class JobProcessingQueue
+ {
+ private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+ private static Queue _jobs = new Queue();
+ private static bool _delegateQueuedOrRunning = false;
+
+ public static void Enqueue(DTO_QueueItem item)
+ {
+ lock (_jobs)
+ {
+ //See if the job is already in the queue based on the file name. If it is, ignore it.
+ if (!(_jobs.Any(_ => _.FilePath == item.FilePath)))
+ {
+ logger.Debug("Adding job to the queue. | {0}", item.FilePath);
+ _jobs.Enqueue(item);
+ if (!_delegateQueuedOrRunning)
+ {
+ _delegateQueuedOrRunning = true;
+ ThreadPool.UnsafeQueueUserWorkItem(ProcessQueuedItems, null);
+ }
+ }
+ else
+ {
+ logger.Debug("Ignoring job {0}, it's already in the queue.", item.FilePath);
+ }
+ }
+ }
+
+ private static void ProcessQueuedItems(object ignored)
+ {
+ while (true)
+ {
+ DTO_QueueItem item;
+ lock (_jobs)
+ {
+ if (_jobs.Count == 0)
+ {
+ _delegateQueuedOrRunning = false;
+ break;
+ }
+ //Only peek at the first item in the queue so that it does not get added again while it is still getting processed.
+ item = _jobs.Peek();
+ }
+
+ 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
+ {
+ ThreadPool.UnsafeQueueUserWorkItem(ProcessQueuedItems, null);
+ throw;
+ }
+ }
+ }
+
+ private static void DecodeQueueItemJob(DTO_QueueItem item)
+ {
+ //Process the job.
+ logger.Info("Should process the job here. {0}", 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);
+
+ _jobs.Dequeue();
+ }
+
+ private static void MoveFile(string FullPath)
+ {
+ try
+ {
+ System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(FullPath) + @"\Processed\");
+ File.Move(FullPath, System.IO.Path.GetDirectoryName(FullPath) + @"\Processed\" + System.IO.Path.GetFileNameWithoutExtension(FullPath) + DateTime.Now.Ticks.ToString() + ".bak");
+
+ }
+ catch (Exception Ex)
+ {
+ logger.Error(Ex, "Can't move file {0} - it's gone!", FullPath);
+ }
+ }
+ }
+}
diff --git a/BodyshopUploader/Utils/TrayIcon.cs b/BodyshopUploader/Utils/TrayIcon.cs
index c2a8964..9f3c8de 100644
--- a/BodyshopUploader/Utils/TrayIcon.cs
+++ b/BodyshopUploader/Utils/TrayIcon.cs
@@ -11,8 +11,10 @@ namespace BodyshopUploader.Utils
{
public void Execute(object parameter)
{
- new Views.Main().Show();
- }
+ var m = App.Current.Windows.OfType().FirstOrDefault();
+ m?.Show();
+ m?.Focus();
+ }
public bool CanExecute(object parameter)
{
diff --git a/BodyshopUploader/ViewModels/MainViewModel.commands.cs b/BodyshopUploader/ViewModels/MainViewModel.commands.cs
index 01fa1e7..9598ebe 100644
--- a/BodyshopUploader/ViewModels/MainViewModel.commands.cs
+++ b/BodyshopUploader/ViewModels/MainViewModel.commands.cs
@@ -70,5 +70,37 @@ namespace BodyshopUploader.ViewModels
return _removeMonitoringPathCommand;
}
}
+
+ private ICommand _startFolderMonitorsCommand;
+ public ICommand StartFolderMonitorsCommand
+ {
+ get
+ {
+ if (_startFolderMonitorsCommand == null)
+ {
+ _startFolderMonitorsCommand = new RelayCommand(
+ p => MonitoringPaths.Count > 0,
+ p => StartAllFolderMonitors()
+ );
+ }
+ return _startFolderMonitorsCommand;
+ }
+ }
+
+ private ICommand _stopFolderMonitorsCommand;
+ public ICommand StopFolderMonitorsCommand
+ {
+ get
+ {
+ if (_stopFolderMonitorsCommand == null)
+ {
+ _stopFolderMonitorsCommand = new RelayCommand(
+ p => FolderMonitors.Count > 0,
+ p => StopAllFolderMonitors()
+ );
+ }
+ return _stopFolderMonitorsCommand;
+ }
+ }
}
}
diff --git a/BodyshopUploader/ViewModels/MainViewModel.cs b/BodyshopUploader/ViewModels/MainViewModel.cs
index a7b1e89..88b87c7 100644
--- a/BodyshopUploader/ViewModels/MainViewModel.cs
+++ b/BodyshopUploader/ViewModels/MainViewModel.cs
@@ -48,31 +48,51 @@ namespace BodyshopUploader.ViewModels
Properties.Settings.Default.Save();
}
+ public void StartAllFolderMonitors()
+ {
+ if (FolderMonitors.Count > 0)
+ foreach (var m in FolderMonitors)
+ {
+ m.Dispose();
+ }
+
+ foreach (var p in MonitoringPaths)
+ {
+ //Ensure the directory exists, then start monitoring for CIECA files.
+ System.IO.Directory.CreateDirectory(p);
+ FolderMonitors.Add(new Utils.CIECAMonitor(p));
+ }
+ }
+
+ public void StopAllFolderMonitors()
+ {
+ if (FolderMonitors.Count > 0)
+ foreach (var m in FolderMonitors)
+ {
+ m.Dispose();
+ }
+ }
+
public async Task TestGql()
{
- if (MonitoringPaths == null) MonitoringPaths = new ObservableCollection();
- MonitoringPaths.Add(@"C:\IMEX");
- Properties.Settings.Default.MonitoringPaths = MonitoringPaths;
- Properties.Settings.Default.Save();
+ var r = new GraphQLRequest
+ {
+ Query = @"
+ query {
+ jobs {
+ id
+ est_number
+ ro_number
+ }
+ }
+ "
+ };
- //var r = new GraphQLRequest
- //{
- // Query = @"
- // query {
- // jobs {
- // id
- // est_number
- // ro_number
- // }
- // }
- // "
- //};
-
- //using (var g = Utils.GraphQL.CreateGQLClient())
- //{
- // var graphQLResponse = await g.PostAsync(r);
- // logger.Info(graphQLResponse.Data.jobs);
- //}
+ using (var g = Utils.GraphQL.CreateGQLClient())
+ {
+ var graphQLResponse = await g.PostAsync(r);
+ logger.Info(graphQLResponse.Data.jobs);
+ }
}
}
}
diff --git a/BodyshopUploader/ViewModels/MainViewModel.props.cs b/BodyshopUploader/ViewModels/MainViewModel.props.cs
index a915376..363a33d 100644
--- a/BodyshopUploader/ViewModels/MainViewModel.props.cs
+++ b/BodyshopUploader/ViewModels/MainViewModel.props.cs
@@ -16,6 +16,13 @@ namespace BodyshopUploader.ViewModels
set { SetProperty(ref _progress, value); }
}
+ private ObservableCollection _folderMonitors = new ObservableCollection() ;
+ public ObservableCollection FolderMonitors
+ {
+ get { return _folderMonitors; }
+ set { SetProperty(ref _folderMonitors, value); }
+ }
+
private ObservableCollection _monitoringPaths = Properties.Settings.Default.MonitoringPaths ;
public ObservableCollection MonitoringPaths
{
diff --git a/BodyshopUploader/Views/Main.xaml b/BodyshopUploader/Views/Main.xaml
index 15dcfd5..9dcd139 100644
--- a/BodyshopUploader/Views/Main.xaml
+++ b/BodyshopUploader/Views/Main.xaml
@@ -20,15 +20,17 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{DynamicResource MaterialDesignFont}"
Loaded="Window_Loaded"
- xmlns:util="clr-namespace:BodyshopUploader.Utils">
+ xmlns:util="clr-namespace:BodyshopUploader.Utils"
+ Closing="Window_Closing">
-
+
-
-
+
-
+
-
-
+
+
+
+
+
+
@@ -72,12 +83,11 @@
-
-
-
+
+