using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Data;
using Tango.BL;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.Core.DI;
using Tango.DragAndDrop;
using Tango.PPC.Common;
using Tango.PPC.Common.Messages;
using Tango.PPC.Jobs.Dialogs;
using Tango.PPC.Jobs.Messages;
using Tango.PPC.Jobs.Views;
using System.Data.Entity;
using Tango.BL.Builders;
using Tango.PPC.Jobs.NavigationObjects;
using Tango.PPC.Storage;
using Tango.Explorer;
using System.IO;
using Google.Protobuf;
using Tango.PMR.Exports;
using Tango.Settings;
using Tango.Integration.ExternalBridge;
using System.Windows.Media;
using Tango.PMR.TCC;
using Tango.Pulse;
using System.Windows.Media.Imaging;
using Tango.Touch.Components;
using Tango.PPC.Jobs.ViewContracts;
using Tango.Core.ExtensionMethods;
using Tango.PPC.Common.Synchronization;
using Tango.PPC.Jobs.NotificationItems;
using Tango.PPC.Storage.Models;
using Tango.BL.Helpers;
using Tango.ColorConversion;
using Tango.PPC.Jobs.Models;
using Tango.PPC.Shared.RemoteJobUpload;
using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.Notifications.NotificationItems;
namespace Tango.PPC.Jobs.ViewModels
{
///
/// Represents the jobs list view model.
///
///
public class JobsViewVM : PPCViewModel
{
private ObservablesContext _db; //Holds the db context for the job list.
private ObservableCollection _catalogs; //Holds the available color catalogs for the site.
private ObservableCollection _rmls; //Holds the available RML for the site.
private ObservableCollection _spoolTypes;
private List _colorSpaces; //Holds the available color spaces.
private bool _isJobsSynchronizationNotificationActive;
public enum JobsCategory
{
Draft,
History
}
#region Properties
private ObservableCollection _jobs;
///
/// Gets or sets the collection of jobs.
///
public ObservableCollection Jobs
{
get { return _jobs; }
set { _jobs = value; RaisePropertyChangedAuto(); }
}
private ICollectionView _draftJobsCollectionView;
///
/// Gets or sets the jobs collection view.
///
public ICollectionView DraftJobsCollectionView
{
get { return _draftJobsCollectionView; }
set
{
_draftJobsCollectionView = value;
RaisePropertyChangedAuto();
}
}
private ICollectionView _historyJobsCollectionView;
///
/// Gets or sets the jobs collection view.
///
public ICollectionView HistoryJobsCollectionView
{
get { return _historyJobsCollectionView; }
set
{
_historyJobsCollectionView = value;
RaisePropertyChangedAuto();
}
}
private ObservableCollection _selectedJobs;
///
/// Gets or sets the selected jobs.
///
public ObservableCollection SelectedJobs
{
get { return _selectedJobs; }
set { _selectedJobs = value; RaisePropertyChangedAuto(); }
}
private bool _isLoadingJobs;
///
/// Gets or sets a value indicating whether this instance is loading jobs.
///
public bool IsLoadingJobs
{
get { return _isLoadingJobs; }
set { _isLoadingJobs = value; RaisePropertyChangedAuto(); }
}
private bool _isMultiSelecting;
///
/// Gets or sets a value indicating whether this the jobs list is in multi select mode.
///
public bool IsMultiSelecting
{
get { return _isMultiSelecting; }
set { _isMultiSelecting = value; RaisePropertyChangedAuto(); }
}
private int _selectedCategoryIndex;
///
/// Gets or sets the index of the selected category.
///
public int SelectedCategoryIndex
{
get { return _selectedCategoryIndex; }
set
{
_selectedCategoryIndex = value;
RaisePropertyChangedAuto();
RaisePropertyChanged(nameof(SelectedCategory));
}
}
///
/// Gets or sets the selected category.
///
public JobsCategory SelectedCategory
{
get { return (JobsCategory)SelectedCategoryIndex; }
set
{
if (SelectedCategoryIndex != value.ToInt32())
{
SelectedCategoryIndex = value.ToInt32();
Filter = null;
}
}
}
private String _filter;
///
/// Gets or sets the search filter.
///
public String Filter
{
get { return _filter; }
set { _filter = value; RaisePropertyChangedAuto(); OnFilterChanged(); }
}
private ICollectionFilter _collectionFilter;
public ICollectionFilter CollectionFilter
{
get { return _collectionFilter; }
set { _collectionFilter = value; RaisePropertyChangedAuto(); }
}
private bool _selectAll;
public bool SelectAll
{
get { return _selectAll; }
set { _selectAll = value;
RaisePropertyChangedAuto();}
}
#endregion
#region Commands
///
/// Gets or sets the job selected command.
///
public RelayCommand JobSelectedCommand { get; set; }
///
/// Gets or sets the job drag and drop command.
///
public RelayCommand JobDragedDroppedCommand { get; set; }
///
/// Gets or sets the clear selection command.
///
public RelayCommand ClearSelectionCommand { get; set; }
///
/// Gets or sets the add job command.
///
public RelayCommand AddJobCommand { get; set; }
///
/// Gets or sets the delete jobs command.
///
public RelayCommand DeleteJobsCommand { get; set; }
///
/// Gets or sets the clone jobs command.
///
public RelayCommand CloneJobsCommand { get; set; }
///
/// Gets or sets the export job command.
///
public RelayCommand ExportJobCommand { get; set; }
///
/// Gets or sets the move to list ( History or Draft) jobs command.
///
public RelayCommand MoveToListJobsCommand { get; set; }
public RelayCommand SelectAllJobsCommand { get; set; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
public JobsViewVM()
{
Jobs = new ObservableCollection();
SelectedJobs = new ObservableCollection();
JobSelectedCommand = new RelayCommand((x) => SelectJob(x as Job));
JobDragedDroppedCommand = new RelayCommand((e) =>
{
Job draggedJob = e.Draggable.DataContext as Job;
Job droppedJob = e.Droppable.DataContext as Job;
DragAndDropJob(draggedJob, droppedJob);
});
ClearSelectionCommand = new RelayCommand(ClearSelection);
AddJobCommand = new RelayCommand(() => AddNewJob());
DeleteJobsCommand = new RelayCommand(() => DeleteJobs(SelectedJobs));
CloneJobsCommand = new RelayCommand(() => CloneJobs(SelectedJobs));
ExportJobCommand = new RelayCommand(ExportJob);
MoveToListJobsCommand = new RelayCommand(() => MoveToListJobs(SelectedJobs));
SelectAllJobsCommand = new RelayCommand(SelectAllJobs);
RegisterForMessage(HandleJobRemovedMessage);
RegisterForMessage(HandleJobSavedMessage);
RegisterForMessage((x) => Filter = null);
CollectionFilter = new DefaultCollectionFilter();
CollectionFilter.RegisterFilter(item =>
{
var job = item as Job;
if (job != null)
{
if (String.IsNullOrEmpty(Filter))
{
return true;
}
else
{
return (job.Name.ToLower().Contains(Filter.ToLower()) || (job.Customer != null && job.Customer.Name.ToLower().StartsWith(Filter.ToLower())));
}
}
else
{
return true;
}
});
}
#endregion
#region Drag & Drop
///
/// Called when a job has been dragged and dropped into another job.
///
/// The dragged job.
/// The dropped job.
private void DragAndDropJob(Job draggedJob, Job droppedJob)
{
LogManager.Log($"Job Drag & Drop '{draggedJob.Name}' => '{droppedJob.Name}'.");
if (draggedJob.JobIndex > droppedJob.JobIndex)
{
draggedJob.JobIndex = droppedJob.JobIndex - 1;
}
else
{
draggedJob.JobIndex = droppedJob.JobIndex + 1;
}
int index = 1;
foreach (var job in Jobs.OrderBy(x => x.JobIndex))
{
job.JobIndex = index++;
}
DraftJobsCollectionView.Refresh();
}
#endregion
#region Job Selection & Loading
///
/// Selects the job.
///
/// The job.
public async void SelectJob(Job job, bool directlyToEdit = false)
{
//if (!ApplicationManager.IsInTechnicianMode && job.ColorSpace != null && job.ColorSpace.Code == ColorSpaces.Volume.ToInt32())
//{
// await NotificationProvider.ShowError("The selected job is supported only in technician mode.");
// return;
//}
LogManager.Log($"Job '{job.Name}' selected.");
RaiseMessage(new JobSelectedMessage() { Job = job, Context = _db });
if (BuildProvider.MachineType.IsXMachine())
{
await NavigationManager.NavigateTo(nameof(JobEurekaView));
}
else
{
if (!directlyToEdit && MachineProvider.MachineOperator.CanPrint)
{
await NavigationManager.NavigateWithObject(new JobSummeryNavigationObject()
{
Context = _db,
Job = job,
});
}
else
{
await NavigationManager.NavigateTo(nameof(JobView));
}
}
}
///
/// Loads the jobs from database.
///
public void LoadJobs(Action onCompleted = null, bool animate = true)
{
try
{
LogManager.Log("Loading machine jobs...");
Task.Factory.StartNew(() =>
{
if (animate) IsLoadingJobs = true;
Thread.Sleep(500);
_db = ObservablesContext.CreateDefault();
_colorSpaces = _db.ColorSpaces.ToList();
var jobs = new JobsCollectionBuilder(_db).Set(x => x.MachineGuid == MachineProvider.Machine.Guid).WithSegments().WithBrushStops().WithCustomer().WithColorSpace().WithSegmentsGroups().WithRmls().Build();
InvokeUI(() =>
{
Jobs = jobs;
DraftJobsCollectionView = new ListCollectionView(Jobs);
DraftJobsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Job.LastUpdated), ListSortDirection.Descending));
DraftJobsCollectionView.Filter = new Predicate(x =>
{
var job = x as Job;
return job.JobStatus == JobStatuses.Draft;
});
HistoryJobsCollectionView = new ListCollectionView(Jobs);
HistoryJobsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Job.LastUpdated), ListSortDirection.Descending));
HistoryJobsCollectionView.Filter = new Predicate(x =>
{
var job = x as Job;
return job.JobStatus != JobStatuses.Draft;
});
IsLoadingJobs = false;
LogManager.Log("Machine jobs loaded!");
onCompleted?.Invoke();
});
});
}
catch (Exception ex)
{
LogManager.Log(ex);
NotificationProvider.ShowError("An error occurred while trying to load the machine jobs.");
}
}
///
/// Clears the job selection.
///
public void ClearSelection()
{
SelectedJobs.Clear();
IsMultiSelecting = false;
}
private void SelectAllJobs()
{
SelectAll = !SelectAll;
}
///
/// Adds a new job.
///
private async void AddNewJob(Color? colorProfile = null, TwnFile twnFile = null)
{
try
{
LogManager.Log("Adding new job...");
var settings = SettingsManager.Default.GetOrCreate();
var machine = MachineProvider.Machine;
if (_rmls.Count == 0)
{
await Task.Delay(200);
}
var selectedRmlGuid = Settings.DefaultRmlGuid ?? _rmls.First().Guid;
Job job = new Job();
job.LastUpdated = DateTime.UtcNow;
job.JobSource = JobSource.Local;
job.NumberOfHeads = 1;
job.NumberOfUnits = 1;
job.SampleUnitsOrMeters = 1;
job.CreationDate = DateTime.UtcNow;
job.JobStatus = JobStatuses.Draft;
var selectedSpoolTypeGuid = Settings.SpoolTypeGuid ?? _spoolTypes.First().Guid;
if (BuildProvider.IsEureka)
{
job.Name = "Unnamed";
job.EnableInterSegment = false;
job.InterSegmentLength = 0;
if (BuildProvider.MachineType == MachineTypes.Eureka)
{
job.NumberOfSpools = 4;
}
else
{
job.NumberOfSpools = 1;
}
job.NumberOfUnits = 1;
}
else
{
JobCreationViewVM vm = new JobCreationViewVM(_spoolTypes.ToList(), _rmls.ToList(), selectedRmlGuid, 0, false);
vm.SelectedSpoolType = false == String.IsNullOrEmpty(selectedSpoolTypeGuid) ? _spoolTypes.FirstOrDefault(x => x.Guid == selectedSpoolTypeGuid) : _spoolTypes.FirstOrDefault(x => x.Type == SpoolTypes.StandardSpool);
if (twnFile == null)
{
vm = await NotificationProvider.ShowDialog(vm);
if (!vm.DialogResult)
return;
if (vm.SelectedRML != null)
{
selectedRmlGuid = vm.SelectedRML.Guid;
}
if (vm.SelectedSpoolType != null)
{
selectedSpoolTypeGuid = vm.SelectedSpoolType.Guid;
}
job.Name = vm.JobName;
job.EnableInterSegment = vm.WhiteGap > 0;
job.InterSegmentLength = vm.WhiteGap;
}
}
//job.JobType = vm.SelectedJobType;
job.EnableLubrication = true;
//job.ColorSpaceGuid = Adapter.ColorSpaces.FirstOrDefault(x => x.Code == vm.SelectedColorSpace.ToInt32()).Guid;
//job.ColorSpace = _colorSpaces.SingleOrDefault(x => x.Guid == job.ColorSpaceGuid);
job.MachineGuid = MachineProvider.Machine.Guid;
job.UserGuid = null;
job.RmlGuid = selectedRmlGuid;
job.WindingMethodGuid = Adapter.WindingMethods.FirstOrDefault().Guid;
job.SpoolTypeGuid = selectedSpoolTypeGuid;
if (Jobs.Count > 0)
{
job.JobIndex = Jobs.Max(x => x.JobIndex) + 1;
}
if (colorProfile == null)
{
var segment = job.AddSolidSegment(Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 100);
segment.BrushStops.Clear();
}
else
{
var segment = job.AddSolidSegment(colorProfile.Value, Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 100);
segment.BrushStops.Clear();
job.Name = $"SnapMatch {colorProfile.Value.R}, {colorProfile.Value.G}, {colorProfile.Value.B}";
}
if (twnFile != null)
{
job.Name = twnFile.Name;
job.NumberOfUnits = Math.Max(twnFile.NumberOfCopies, 1);
job.EmbroideryFileName = twnFile.Name + "." + twnFile.EmbroideryFileFormat;
job.EmbroideryFileData = twnFile.EmbroideryFile;
job.EmbroideryJpeg = twnFile.ThumbnailData;
job.Segments.Clear();
int index = 1;
foreach (var segment in twnFile.Segments)
{
Segment s = new Segment();
s.Job = job;
s.SegmentIndex = index++;
s.Name = "Embroidery Segment";
s.Length = segment.Length / 100d;
int sIndex = 1;
foreach (var stop in segment.BrushStops)
{
BrushStop st = new BrushStop();
st.Segment = s;
st.StopIndex = sIndex++;
st.OffsetPercent = stop.Offset * 100d;
st.Red = stop.R;
st.Green = stop.G;
st.Blue = stop.B;
st.ColorSpaceGuid = job.ColorSpaceGuid;
s.BrushStops.Add(st);
}
job.Segments.Add(s);
}
}
_db.Jobs.Add(job);
await _db.SaveChangesAsync();
Jobs.Add(job);
LogManager.Log($"Job {job.Name} added successfully.");
RaiseMessage(new JobSelectedMessage() { Job = job, Context = _db });
await Task.Delay(200);
if(BuildProvider.IsEureka)
{
await NavigationManager.NavigateWithObject(new JobNavigationObject()
{
Job = job,
Intent = JobNavigationIntent.NewJob
});
}
else
{
await NavigationManager.NavigateWithObject(new JobNavigationObject()
{
Job = job,
Intent = JobNavigationIntent.NewJob
});
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error creating new job.");
await NotificationProvider.ShowError("An error occurred while trying to add a new job.");
}
}
///
/// Deletes the specified jobs from db.
///
/// The jobs.
private async void DeleteJobs(ObservableCollection jobs)
{
try
{
LogManager.Log($"Removing selected jobs:\n{jobs.Select(x => x.Name).ToList().ToJsonString()}");
if (await NotificationProvider.ShowQuestion("Are you sure you want to delete the selected jobs"))
{
foreach (var job in jobs)
{
await job.DeleteCascadeAsync(_db);
Jobs.Remove(job);
}
await _db.SaveChangesAsync();
ClearSelection();
}
}
catch (Exception ex)
{
LogManager.Log(ex, "Error removing selected jobs.");
await NotificationProvider.ShowError("An error occurred while trying to remove the selected jobs.");
}
}
///
/// Clones the specified jobs.
///
/// The jobs.
private async void CloneJobs(ObservableCollection jobs)
{
try
{
LogManager.Log($"Cloning selected jobs:\n{jobs.Select(x => x.Name).ToList().ToJsonString()}");
int index = Jobs.Max(x => x.JobIndex);
List clonedJobs = new List();
foreach (var job in SelectedJobs)
{
var cloned = job.Clone();
cloned.JobIndex = ++index;
_db.Jobs.Add(cloned);
clonedJobs.Add(cloned);
}
await _db.SaveChangesAsync();
foreach (var job in clonedJobs)
{
Jobs.Add(job);
}
ClearSelection();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error cloning selected jobs.");
await NotificationProvider.ShowError("An error occurred while trying to clone the selected jobs.");
}
}
///
/// Moves to list (Draft/History) jobs.
///
/// The jobs.
private async void MoveToListJobs(ObservableCollection jobs)
{
bool isHistory = SelectedCategory == JobsCategory.History;
string list = isHistory ? "Draft" : "History";
try
{
LogManager.Log($"Move To {list} selected jobs:\n{jobs.Select(x => x.Name).ToList().ToJsonString()}");
foreach (var job in SelectedJobs)
{
if(isHistory)
{
if(job.JobStatus != JobStatuses.Draft)
{
job.JobStatus = JobStatuses.Draft;
job.LastUpdated = DateTime.UtcNow;
}
}
if(!isHistory)//draft
{
if(job.JobStatus == JobStatuses.Draft)
{
job.JobStatus = JobStatuses.Completed;
job.LastUpdated = DateTime.UtcNow;
}
}
}
await _db.SaveChangesAsync();
HistoryJobsCollectionView.Refresh();
DraftJobsCollectionView.Refresh();
ClearSelection();
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error Move To {list} selected jobs.");
await NotificationProvider.ShowError($"An error occurred while trying to Move To {list} the selected jobs.");
}
}
///
/// Called when the search filter has been changed
///
private void OnFilterChanged()
{
if (DraftJobsCollectionView != null && HistoryJobsCollectionView != null)
{
CollectionFilter.RaiseFilterChanged();
View.ScrollToTop();
}
}
#endregion
#region Message Handling
///
/// Handles the job removed message.
///
/// The MSG.
private void HandleJobRemovedMessage(JobRemovedMessage msg)
{
try
{
LogManager.Log("JobRemovedMessage message received, removing job from list...");
var job = Jobs.SingleOrDefault(x => x.Guid == msg.Job.Guid);
Jobs.Remove(job);
_db.Entry(job).State = System.Data.Entity.EntityState.Detached;
}
catch (Exception ex)
{
LogManager.Log(ex, "Could not remove job");
}
}
///
/// Handles the job saved message.
///
/// The MSG.
private void HandleJobSavedMessage(JobSavedMessage msg)
{
LogManager.Log("JobSavedMessage message received.");
LoadJobs();
}
#endregion
#region Override Methods
///
/// Called when the application has been started.
///
public override void OnApplicationStarted()
{
BrushStop.ColorSynchronizationMode = BrushStop.ColorSynchronizationModes.None;
LoadJobs();
ExternalBridgeService.ColorProfileRequest += ExternalBridgeService_ColorProfileRequest;
}
public async override void OnApplicationReady()
{
base.OnApplicationReady();
StorageProvider.RegisterFileHandler(ExplorerFileDefinition.Job.Extension, HandleJobFileLoaded);
StorageProvider.RegisterFileHandler(ExplorerFileDefinition.ColorProfile.Extension, HandleColorProfileFileLoaded);
StorageProvider.RegisterFileHandler(ExplorerFileDefinition.Pulse.Extension, HandlePulseFileLoaded);
StorageProvider.RegisterFileHandler(ExplorerFileDefinition.CsvFile.Extension, HandleCsvJobFileLoaded);
//Load catalogs.
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
_catalogs = await new CatalogsCollectionBuilder(db).SetAll().ForSite(MachineProvider.Machine.SiteGuid).BuildAsync();
_rmls = (await new RmlsCollectionBuilder(db).SetAll().WithSpools().ForHeadType(MachineProvider.Machine.MachineHeadType).ForSite(MachineProvider.Machine.SiteGuid).BuildAsync()).OrderBy(x => x.FinalName).ToObservableCollection();
//_rmls = (await new RmlsCollectionBuilder(db).SetAll().WithSpools().BuildAsync()).OrderBy(x => x.FinalName).ToObservableCollection();
_spoolTypes = await MachineProvider.Machine.GetSiteSpoolTypes(db);
}
MachineDataSynchronizer.SynchronizationEnded += MachineDataSynchronizer_SynchronizationEnded;
RemoteJobUploadService.JobReceived += RemoteJobUploadService_JobReceived;
}
public override void OnNavigatedTo()
{
base.OnNavigatedTo();
JobViewVM._start_printing_btn?.Pop();
Filter = null;
}
#endregion
#region Job Export
private async void ExportJob()
{
var selected_job = SelectedJobs.FirstOrDefault();
if (selected_job == null) return;
var selectedJobs = SelectedJobs.ToList();
ClearSelection();
var result = await NavigationManager.
NavigateForResult(
new StorageNavigationRequest()
{
Intent = selectedJobs.Count == 1 ? StorageNavigationIntent.SaveFile : StorageNavigationIntent.SaveFiles,
DefaultFileName = selected_job.Name,
Filter = ExplorerFileDefinition.Job.Extension,
Title = selectedJobs.Count == 1 ? "Save Job File" : "Save Job Files",
});
if (result != null)
{
if (selectedJobs.Count == 1)
{
try
{
var jobFile = await selected_job.ToJobFile();
using (FileStream fs = new FileStream(result.Path + ExplorerFileDefinition.Job.Extension, FileMode.Create))
{
jobFile.WriteTo(fs);
}
await NotificationProvider.ShowSuccess("Job saved successfully.");
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error saving job {selected_job.Name} to file.");
await NotificationProvider.ShowError($"An error occurred while trying to save the job.\n{ex.Message}");
}
}
else
{
foreach (var job in selectedJobs)
{
try
{
var jobFile = await job.ToJobFile();
using (FileStream fs = new FileStream(Path.Combine(result.Path, jobFile.Name.ToValidFileName()) + ExplorerFileDefinition.Job.Extension, FileMode.Create))
{
jobFile.WriteTo(fs);
}
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error saving job {job.Name} to file.");
await NotificationProvider.ShowError($"An error occurred while trying to save the job.\n{ex.Message}");
}
}
await NotificationProvider.ShowSuccess("Jobs saved successfully.");
}
}
}
#endregion
#region Handle Job File Loading From Storage
private async void HandleJobFileLoaded(List jobFiles)
{
var vm = await NotificationProvider.ShowDialog();
if (vm.DialogResult)
{
using (ObservablesContext jobContext = ObservablesContext.CreateDefault())
{
foreach (var jobFile in jobFiles)
{
try
{
JobFile jFile = JobFile.Parser.ParseFrom(File.ReadAllBytes(jobFile.Path));
var job = await Job.FromJobFile(jFile, MachineProvider.Machine.Guid, null);
job.JobSource = JobSource.Local;
jobContext.Jobs.Add(job);
await jobContext.SaveChangesAsync();
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error occurred while trying to import job from file {jobFile.Path}.");
await NotificationProvider.ShowError($"An error occurred while trying to import the selected job file.\n{ex.Message}");
}
}
LoadJobs(() =>
{
//Editing of a job is currently deprecated due to enabling multiple job imports.
//if (vm.ImportAndEdit)
//{
// var postJob = Jobs.SingleOrDefault(x => x.Guid == job.Guid);
// if (postJob != null)
// {
// SelectJob(postJob, true);
// }
//}
});
}
}
}
#endregion
#region Handle CSV Job File Loading From Storage
private async void HandleCsvJobFileLoaded(List files)
{
var item = files.FirstOrDefault();
if (item == null) return;
var vm = new ImportCsvJobViewVM();
vm.Name = Path.GetFileNameWithoutExtension(item.Name);
await vm.Init();
await NotificationProvider.ShowDialog(vm);
if (vm.DialogResult && vm.SelectedRml != null)
{
try
{
NotificationProvider.SetGlobalBusyMessage("Importing job from file...");
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var result = await SegmentsCsvHelper.FromFile(item.Path, MachineProvider.Machine, db);
var segments = result.Segments;
Job job = new Job();
job.LastUpdated = DateTime.UtcNow;
job.JobSource = JobSource.Local;
job.Name = vm.Name;
job.NumberOfHeads = 1;
job.NumberOfUnits = 1;
job.NumberOfSpools = BuildProvider.MachineType == MachineTypes.Eureka ? 4 : 1;
job.SampleUnitsOrMeters = 1;
job.CreationDate = DateTime.UtcNow;
job.JobStatus = JobStatuses.Draft;
job.JobType = JobTypes.Knitting;
job.EnableLubrication = true;
job.MachineGuid = MachineProvider.Machine.Guid;
job.RmlGuid = vm.SelectedRml.Guid;
job.Machine = await new MachineBuilder(db).Set(job.MachineGuid).WithCats().WithConfiguration().BuildAsync();
job.Rml = await new RmlBuilder(db).Set(job.RmlGuid).WithActiveParametersGroup().WithCAT(MachineProvider.Machine.Guid).WithCCT().WithGbdAndLub().WithLiquidFactors().BuildAsync();
job.WindingMethodGuid = Adapter.WindingMethods.FirstOrDefault().Guid;
job.SpoolTypeGuid = Settings.SpoolTypeGuid != null ? Settings.SpoolTypeGuid : Adapter.SpoolTypes.FirstOrDefault().Guid;
foreach (var segment in segments)
{
segment.Job = job;
job.Segments.Add(segment);
}
IColorConverter converter = new DefaultColorConverter();
foreach (var stop in segments.SelectMany(x => x.BrushStops))
{
var output = converter.Convert(stop, false);
var suggestion = output.CreateSingleSuggestion();
stop.Red = suggestion.Color.R;
stop.Green = suggestion.Color.G;
stop.Blue = suggestion.Color.B;
stop.BestMatchR = suggestion.Color.R;
stop.BestMatchG = suggestion.Color.G;
stop.BestMatchB = suggestion.Color.B;
}
db.Jobs.Add(job);
await db.SaveChangesAsync();
LoadJobs();
}
NotificationProvider.ReleaseGlobalBusyMessage();
}
catch (Exception ex)
{
NotificationProvider.ReleaseGlobalBusyMessage();
LogManager.Log(ex, "Error importing job from CSV.");
await NotificationProvider.ShowError($"Error importing job from csv file.\n{ex.FlattenMessage()}");
}
}
}
#endregion
#region Handle CSV Job File Received By Remote Job Upload Service
private void RemoteJobUploadService_JobReceived(object sender, Common.RemoteJobUpload.RemoteJobReceivedEventArgs e)
{
if (e.Type == RemoteJobUploadType.CSV)
{
Task.Factory.StartNew(async () =>
{
try
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var result = await SegmentsCsvHelper.FromFile(e.FilePath, MachineProvider.Machine, db);
var segments = result.Segments;
String rmlGuid = null;
if (result.Rml != null)
{
rmlGuid = result.Rml.Guid;
}
else
{
rmlGuid = Settings.DefaultRmlGuid;
}
var machine = await new MachineBuilder(db).SetFirst().WithConfiguration().BuildAsync();
Job job = new Job();
job.LastUpdated = DateTime.UtcNow;
job.JobSource = JobSource.Local;
job.Name = e.Name;
job.NumberOfHeads = 1;
job.NumberOfUnits = 1;
job.SampleUnitsOrMeters = 1;
job.NumberOfSpools = BuildProvider.MachineType == MachineTypes.Eureka ? 4 : 1;
job.CreationDate = DateTime.UtcNow;
job.JobStatus = JobStatuses.Draft;
job.JobType = JobTypes.Knitting;
job.EnableLubrication = true;
job.MachineGuid = MachineProvider.Machine.Guid;
job.RmlGuid = rmlGuid;
job.Machine = await new MachineBuilder(db).Set(job.MachineGuid).WithCats().WithConfiguration().BuildAsync();
job.Rml = await new RmlBuilder(db).Set(job.RmlGuid).WithActiveParametersGroup().WithCAT(MachineProvider.Machine.Guid).WithCCT().WithGbdAndLub().WithLiquidFactors().BuildAsync();
job.WindingMethodGuid = Adapter.WindingMethods.FirstOrDefault().Guid;
job.SpoolTypeGuid = Settings.SpoolTypeGuid != null ? Settings.SpoolTypeGuid : Adapter.SpoolTypes.FirstOrDefault().Guid;
foreach (var segment in segments)
{
segment.Job = job;
job.Segments.Add(segment);
}
IColorConverter converter = new DefaultColorConverter();
int segmentIndex = 0;
foreach (var stop in segments.SelectMany(x => x.BrushStops).Where(x => x.BrushColorSpace != ColorSpaces.RGB))
{
segmentIndex++;
var output = converter.Convert(stop, false);
var suggestion = output.CreateSingleSuggestion();
stop.Red = suggestion.Color.R;
stop.Green = suggestion.Color.G;
stop.Blue = suggestion.Color.B;
stop.BestMatchR = suggestion.Color.R;
stop.BestMatchG = suggestion.Color.G;
stop.BestMatchB = suggestion.Color.B;
stop.SetLiquidVolumes(machine.Configuration, job.Rml, job.Rml.GetActiveProcessGroup().ProcessParametersTables[suggestion.ProcessParametersTableIndex]);
if (stop.IsLiquidVolumesOutOfRange)
{
throw new InvalidOperationException($"Volumes out of range for thread '{job.Rml.FinalName}' at segment {segmentIndex}.");
}
}
db.Jobs.Add(job);
await db.SaveChangesAsync();
}
LoadJobs(() =>
{
NotificationProvider.PushNotification(new MessageNotificationItem($"Csv job '{e.Name}' received successfully.", "", MessageNotificationItem.MessageNotificationItemTypes.Success, () => { }, NotificationItem.NotificationPriority.Low));
e.Confirm();
}, false);
}
catch (Exception ex)
{
LogManager.Log(ex, "Error occurred on remote job upload.");
e.Abort(ex.FlattenMessage());
}
});
}
}
#endregion
#region Handle TCC File Loading From Storage
private async void HandleColorProfileFileLoaded(List tccFiles)
{
var tccFile = tccFiles.FirstOrDefault();
try
{
DetectionColorFile tcc = DetectionColorFile.Parser.ParseFrom(File.ReadAllBytes(tccFile.Path));
var vm = await NotificationProvider.ShowDialog(new ImportColorProfileViewVM()
{
Color = Color.FromRgb(
(byte)tcc.ProcessedColor.R,
(byte)tcc.ProcessedColor.G,
(byte)tcc.ProcessedColor.B),
});
if (vm.DialogResult)
{
AddNewJob(vm.Color);
}
}
catch (Exception ex)
{
LogManager.Log(ex, $"Error occurred while trying to import detection color from file {tccFile.Path}.");
await NotificationProvider.ShowError($"An error occurred while trying to import the selected detection color.\n{ex.Message}");
}
}
#endregion
#region Handle Pulse TWN Loading From Storage
private async void HandlePulseFileLoaded(List twnFiles)
{
var twnFile = twnFiles.FirstOrDefault();
TwnFile twn = TwnFile.FromFile(twnFile.Path);
BitmapSource preview = twn.Thumbnail.ToBitmapSource();
var vm = await NotificationProvider.ShowDialog(new ImportTwnFileViewVM()
{
Thumbnail = preview,
});
if (vm.DialogResult)
{
AddNewJob(null, twn);
}
}
#endregion
#region Handle New Synchronized Jobs
private void MachineDataSynchronizer_SynchronizationEnded(object sender, SynchronizationEndedEventArgs e)
{
if (e.NewChangedJobs > 0 && !_isJobsSynchronizationNotificationActive)
{
_isJobsSynchronizationNotificationActive = true;
var item = NotificationProvider.PushNotification();
item.Pressed += (_, __) =>
{
_isJobsSynchronizationNotificationActive = false;
LoadJobs(() =>
{
NotificationProvider.ShowSuccess("Your job list is now synchronized.");
});
};
item.Closed += (_, __) =>
{
_isJobsSynchronizationNotificationActive = false;
};
}
}
#endregion
#region Color Profile Request
private void ExternalBridgeService_ColorProfileRequest(object sender, ColorProfileRequestEventArgs e)
{
InvokeUI(async () =>
{
var vm = await NotificationProvider.ShowDialog(new ColorProfileReceivedViewVM()
{
Color = Color.FromRgb(
(byte)e.Request.DetectionColor.R,
(byte)e.Request.DetectionColor.G,
(byte)e.Request.DetectionColor.B),
});
if (vm.DialogResult)
{
e.Approve();
AddNewJob(vm.Color);
}
else
{
e.Decline();
}
});
}
#endregion
}
}