Browse Source

PRS DESKTOP - changed report and user grid email functions to open default email app, moved email functions to EmailUtils

Nick-PRSDigital@bitbucket.org 2 years ago
parent
commit
47b2528c3f
2 changed files with 90 additions and 200 deletions
  1. 88 151
      prs.desktop/MainWindow.xaml.cs
  2. 2 49
      prs.desktop/Panels/Users/UserGrid.cs

+ 88 - 151
prs.desktop/MainWindow.xaml.cs

@@ -67,6 +67,8 @@ using Role = Comal.Classes.Role;
 using SortDirection = InABox.Core.SortDirection;
 using ValidationResult = InABox.Clients.ValidationResult;
 using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using FastReport.Export.Email;
 
 namespace PRSDesktop
 {
@@ -77,7 +79,7 @@ namespace PRSDesktop
     public partial class MainWindow : IPanelHost
     {
         //private const int WM_LBUTTONDOWN = 0x201;
-        
+
 
         private static PipeServer<string>? _client;
 
@@ -91,7 +93,7 @@ namespace PRSDesktop
 
 
         //Dictionary<Type, IBasePanel> Panels = new Dictionary<Type, IBasePanel>();
-        
+
         private DispatcherTimer? _recorder;
 
 
@@ -114,16 +116,16 @@ namespace PRSDesktop
         private int CurrentPanel_Keys;
         private string CurrentPanel_Label = "";
         private DateTime CurrentPanel_Ticks = DateTime.MinValue;
-        
+
         private Fluent.RibbonTabItem? CurrentTab;
         private Fluent.Button? CurrentButton;
 
         private readonly int FRAMES_PER_SECOND = 10;
 
         private DatabaseType DatabaseType;
-        
+
         private readonly Dictionary<int, int> messages = new();
-        
+
         private readonly DispatcherTimer NotificationsWatchDog;
 
         private DateTime pausestarted = DateTime.MinValue;
@@ -157,7 +159,7 @@ namespace PRSDesktop
             HotKeyManager.RegisterHotKey(Key.F5, ToggleRecording);
             HotKeyManager.RegisterHotKey(Key.F6, ShowRecordingNotes);
             HotKeyManager.RegisterHotKey(Key.F4, ToggleRecordingAudio);
-            
+
             DatabaseType = App.DatabaseSettings.DatabaseType;
             switch (DatabaseType)
             {
@@ -167,7 +169,7 @@ namespace PRSDesktop
                     DbFactory.Logo = App.DatabaseSettings.Logo;
                     break;
                 case DatabaseType.Networked:
-                    ClientFactory.SetClientType(typeof(JsonClient<>), "Wpf", CoreUtils.GetVersion(), 
+                    ClientFactory.SetClientType(typeof(JsonClient<>), "Wpf", CoreUtils.GetVersion(),
                         App.DatabaseSettings.URL, App.DatabaseSettings.Port, true);
                     break;
                 case DatabaseType.Local:
@@ -191,9 +193,9 @@ namespace PRSDesktop
             catch
             {
             }
-            
+
             InitializeComponent();
-            
+
             VideoRecordingStatus.Source = PRSDesktop.Resources.videorecording.AsGrayScale().AsBitmapImage();
             AudioRecordingStatus.Source = PRSDesktop.Resources.audiorecording.AsGrayScale().AsBitmapImage();
             SecondaryWindowStatus.Source = PRSDesktop.Resources.target.AsGrayScale().AsBitmapImage();
@@ -303,7 +305,7 @@ namespace PRSDesktop
             else if (loginException != null)
                 MessageBox.Show(loginException.Message);
 
-            if(DoLogin(App.DatabaseSettings.Autologin) == ValidationResult.VALID)
+            if (DoLogin(App.DatabaseSettings.Autologin) == ValidationResult.VALID)
             {
                 AfterLogin();
             }
@@ -331,7 +333,7 @@ namespace PRSDesktop
 
         private void ClientFactory_OnRequestError(RequestException e)
         {
-            if(e.Status == StatusCode.Unauthenticated)
+            if (e.Status == StatusCode.Unauthenticated)
             {
                 switch (e.Method)
                 {
@@ -365,7 +367,7 @@ namespace PRSDesktop
 
         private void ApplyColorScheme()
         {
-            
+
             Color baseColor;
             try
             {
@@ -380,12 +382,12 @@ namespace PRSDesktop
             BaseDynamicGrid.SelectionBackground = ThemeManager.SelectionBackgroundBrush;
             BaseDynamicGrid.SelectionForeground = ThemeManager.SelectionForegroundBrush;
             BaseDynamicGrid.FilterBackground = ThemeManager.FilterBackgroundBrush;
-            
+
             //_ribbon.Background =  new SolidColorBrush(Colors.White);
             //_ribbon.BackStageColor = ThemeConverter.GetBrush(ElementType.Ribbon, BrushType.Background);
             ////_ribbon.BackStage.Background = ThemeConverter.GetBrush(ElementType.Ribbon, BrushType.Background);
             ////_ribbon.BackStage.Foreground = ThemeConverter.GetBrush(ElementType.Ribbon, BrushType.Foreground);
-            
+
             UpdateRibbonColors();
             CurrentPanel?.Refresh();
 
@@ -493,11 +495,11 @@ namespace PRSDesktop
 
         private void ConfigureMainScreen()
         {
-            
+
             var button = _ribbon.FindVisualChildren<Fluent.DropDownButton>().FirstOrDefault();
             if (button != null)
                 button.Visibility = Visibility.Collapsed;
-            
+
             if (ClientFactory.UserGuid == Guid.Empty)
                 _ribbonRow.Height = new GridLength(30, GridUnitType.Pixel);
             else
@@ -628,7 +630,7 @@ namespace PRSDesktop
                         AddSetupAction(ProjectsTab, "Job Statuses", JobStatusButton_Click, PRSDesktop.Resources.view,
                             Security.CanView<JobStatus>());
                         AddSetupAction(ProjectsTab, "Document MileStones", JobDocumentMileStoneButton_OnClick, PRSDesktop.Resources.revision,
-                            true);                        
+                            true);
                         AddSetupAction(ProjectsTab, "Document Tags", JobDocumentTagButton_OnClick, PRSDesktop.Resources.checklist,
                             true);
                         AddSetupAction(ProjectsTab, "Financial Statuses", FinancialStatusButton_Click, PRSDesktop.Resources.view,
@@ -964,7 +966,7 @@ namespace PRSDesktop
                         AddSetupModulesAndReports(EquipmentTab);
 
                         SetTabVisibleIfAny(EquipmentTab, EquipmentButton, TrackersMasterList);
-                        
+
                     }
                 ),
                 new ProgressSection(
@@ -1044,7 +1046,7 @@ namespace PRSDesktop
 
                         LogoutButton.Visibility = ClientFactory.UserGuid == Guid.Empty ? Visibility.Collapsed : Visibility.Visible;
                         LoginButton.Visibility = ClientFactory.UserGuid != Guid.Empty ? Visibility.Collapsed : Visibility.Visible;
-                        
+
                         EditDetailsButton.Visibility = ClientFactory.UserGuid == Guid.Empty ? Visibility.Collapsed : Visibility.Visible;
 
                         SetupDock<CanViewContactsDock>(ContactDock, Contacts);
@@ -1061,12 +1063,12 @@ namespace PRSDesktop
             );
         }
 
-        private void SetupDock<TSecurityDescriptor>(LayoutAnchorable layout, IDockPanel dock) 
+        private void SetupDock<TSecurityDescriptor>(LayoutAnchorable layout, IDockPanel dock)
             where TSecurityDescriptor : ISecurityDescriptor, new()
         {
             if (Security.IsAllowed<TSecurityDescriptor>())
             {
-                if(!DockGroup.Children.Any(x => x == layout))
+                if (!DockGroup.Children.Any(x => x == layout))
                 {
                     DockGroup.Children.Add(layout);
                 }
@@ -1126,7 +1128,7 @@ namespace PRSDesktop
                     if (module.Length == 2)
                         foreach (Fluent.RibbonTabItem tab in _ribbon.Tabs)
                         {
-                            if (String.Equals(tab.Header,module.First()))
+                            if (String.Equals(tab.Header, module.First()))
                             {
                                 _ribbon.SelectedTabItem = tab;
                                 foreach (Fluent.RibbonGroupBox bar in tab.Groups)
@@ -1157,7 +1159,7 @@ namespace PRSDesktop
                 }
             }
         }
-        
+
         private void _ribbon_OnLoaded(object sender, RoutedEventArgs e)
         {
             _ribbon.SelectedTabItem = CurrentTab;
@@ -1202,12 +1204,12 @@ namespace PRSDesktop
                 return (Fluent.RibbonTabItem)sender;
             return GetTabItem(sender.Parent as FrameworkElement);
         }
-        
+
         private T LoadWindow<T>(Fluent.Button sender) where T : IBasePanel, new()
         {
             using (new WaitCursor())
             {
-                
+
                 UnloadWindow();
 
                 CurrentTab = GetTabItem(sender);
@@ -1224,7 +1226,8 @@ namespace PRSDesktop
                 CurrentPanel.Setup();
                 CurrentPanel.IsReady = true;
 
-                CurrentPanel.OnUpdateDataModel += (s, m) => {
+                CurrentPanel.OnUpdateDataModel += (s, m) =>
+                {
                     ReloadModules(s, m);
                     ReloadReports(s, m);
                 };
@@ -1277,7 +1280,7 @@ namespace PRSDesktop
                             Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
                         }
                     }
-                    
+
                 }
                 //stopwatch.Stop();
                 //Logger.Send(LogType.Information, ClientFactory.UserID, String.Format("Loading {0} to took {1} ms", sender != null ? sender.Label : module, stopwatch.ElapsedMilliseconds));
@@ -1395,7 +1398,7 @@ namespace PRSDesktop
                     result = ValidationResult.VALID;
                 }
             }
-            
+
             return result ?? ValidationResult.INVALID;
         }
 
@@ -1420,7 +1423,7 @@ namespace PRSDesktop
             ConfigureMainScreen();
             LoadApplicationState();
             LoadSecondaryWindows();
-            
+
             //if (_ribbon.Menu.IsVisible)
             //{
             //    _ribbon.;
@@ -1465,8 +1468,8 @@ namespace PRSDesktop
                 new Filter<Employee>(x => x.UserID).IsEqualTo(ClientFactory.UserGuid),
                 new Columns<Employee>(x => x.ID).Add(x => x.Email)
             );
-            App.EmployeeID = me.Rows.FirstOrDefault()?.Get<Employee,Guid>(x=>x.ID) ?? Guid.Empty;
-            App.EmployeeEmail = me.Rows.FirstOrDefault()?.Get<Employee,String>(x=>x.Email) ?? "";
+            App.EmployeeID = me.Rows.FirstOrDefault()?.Get<Employee, Guid>(x => x.ID) ?? Guid.Empty;
+            App.EmployeeEmail = me.Rows.FirstOrDefault()?.Get<Employee, String>(x => x.Email) ?? "";
         }
 
         private void ExecuteLogout()
@@ -1524,7 +1527,7 @@ namespace PRSDesktop
             ConfigureMainScreen();
             LoadSecondaryWindows();
 
-            if(message != null)
+            if (message != null)
             {
                 MessageBox.Show(message);
             }
@@ -1622,7 +1625,7 @@ namespace PRSDesktop
 
         private bool ShowHelp()
         {
-            Process.Start(new ProcessStartInfo("https://prs-software.com.au/wiki/index.php/" + CurrentPanelSlug()) { UseShellExecute = true});
+            Process.Start(new ProcessStartInfo("https://prs-software.com.au/wiki/index.php/" + CurrentPanelSlug()) { UseShellExecute = true });
             return true;
         }
 
@@ -1724,15 +1727,15 @@ namespace PRSDesktop
         private void RegisterModules(IProgress<string> progress)
         {
             foreach (Fluent.RibbonTabItem tab in _ribbon.Tabs)
-            foreach (Fluent.RibbonGroupBox bar in tab.Groups)
-            foreach (var item in bar.Items)
-                Dispatcher.Invoke(() =>
-                {
-                    var button = item as RibbonButton;
-                    if (button != null && button.Label != "Refresh")
-                        if (bar.Header.Equals("Actions"))
-                            Modules.Register(button.Label);
-                });
+                foreach (Fluent.RibbonGroupBox bar in tab.Groups)
+                    foreach (var item in bar.Items)
+                        Dispatcher.Invoke(() =>
+                        {
+                            var button = item as RibbonButton;
+                            if (button != null && button.Label != "Refresh")
+                                if (bar.Header.Equals("Actions"))
+                                    Modules.Register(button.Label);
+                        });
 
             //foreach (var item in _ribbon.BackStage.Items)
             //{
@@ -1789,75 +1792,10 @@ namespace PRSDesktop
 
         private void DoEmailReport(DataModel model, byte[] data)
         {
-            //var mailer = ClientFactory.CreateMailer();
-            //if (mailer == null)
-            CreateEMLFile(model, data);
-            //else
-            //{
-
-            //}
+            EmailUtils.CreateEMLFile(model.Name, data, App.EmployeeEmail, "Emailing report for " + model.Name);
         }
-
-        private void CreateEMLFile(DataModel model, byte[] data)
-        {
-            var attachment = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(model.Name, ".pdf"));
-            File.WriteAllBytes(attachment, data);
-
-            var message = new MailMessage();
-            message.From = new MailAddress(App.EmployeeEmail);
-            message.Subject = "Your subject here";
-            message.IsBodyHtml = true;
-            message.Body = "<span style='font-size: 12pt; color: red;'>My HTML formatted body</span>";
-
-            message.Attachments.Add(new Attachment(attachment));
-
-            var filename = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(model.Name, ".eml"));
-
-            using (var filestream = File.Open(filename, FileMode.Create))
-            {
-                var binaryWriter = new BinaryWriter(filestream);
-                //Write the Unsent header to the file so the mail client knows this mail must be presented in "New message" mode
-                binaryWriter.Write(Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine));
-
-                var assembly = typeof(SmtpClient).Assembly;
-                var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter")!;
-
-                // Get reflection info for MailWriter contructor
-                var mailWriterConstructor =
-                    mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null)!;
-
-                // Construct MailWriter object with our FileStream
-                var mailWriter = mailWriterConstructor.Invoke(new object[] { filestream });
-
-                // Get reflection info for Send() method on MailMessage
-                var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic)!;
-
-                sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
-
-                // Finally get reflection info for Close() method on our MailWriter
-                var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic)!;
-
-                // Call close method
-                closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
-            }
-
-            // Open the file with the default associated application registered on the local machine
-            Process.Start(new ProcessStartInfo(filename) { UseShellExecute = true });
-
-
-            //String attachment = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.ChangeExtension(Report.FileName, ".pdf"));
-            //File.WriteAllBytes(attachment, data);
-            //Outlook.Application outlookApp = new Outlook.Application();
-            //Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
-            //mailItem.Subject = System.IO.Path.ChangeExtension(Report.FileName, "");
-            //mailItem.To = "";
-            //mailItem.HTMLBody = "";
-            //mailItem.Attachments.Add(attachment, Outlook.OlAttachmentType.olByValue, Type.Missing, Type.Missing);
-            //mailItem.Display(false);
-        }
-
         #endregion
-        
+
         private Fluent.RibbonGroupBox? FindRibbonBar(Fluent.RibbonTabItem tab, Func<Fluent.RibbonGroupBox, bool> predicate)
         {
             foreach (var group in tab.Groups)
@@ -1985,7 +1923,7 @@ namespace PRSDesktop
         {
             LoadWindow<MapsPanel>((Fluent.Button)sender);
         }
-        
+
         private void FactorySetup_Click()
         {
             var list = new MasterList(typeof(ManufacturingFactory));
@@ -2270,7 +2208,7 @@ namespace PRSDesktop
             var list = new MasterList(typeof(GLCode));
             list.ShowDialog();
         }
-        
+
 
         private void AssignmentsButton_Click(object sender, RoutedEventArgs e)
         {
@@ -2313,7 +2251,7 @@ namespace PRSDesktop
             var list = new MasterList(typeof(PaymentType));
             list.ShowDialog();
         }
-        
+
         private void TaxCodeList_Click()
         {
             var list = new MasterList(typeof(TaxCode));
@@ -2500,8 +2438,8 @@ namespace PRSDesktop
             if (form.ShowDialog() == true)
                 ReloadNotifications();
         }
-        
-        
+
+
         private void CompanyInformation_Click(object sender, RoutedEventArgs e)
         {
             var info = new Client<CompanyInformation>().Load().FirstOrDefault();
@@ -2509,7 +2447,7 @@ namespace PRSDesktop
                 info = new CompanyInformation();
             new DynamicDataGrid<CompanyInformation>().EditItems(new[] { info });
         }
-        
+
         private void StockWarehouseList_Click()
         {
             var list = new MasterList(typeof(StockWarehouse));
@@ -2534,9 +2472,9 @@ namespace PRSDesktop
             list.ShowDialog();
             QuoteDiagramSymbolCache.Refresh();
         }
-        
+
         private void QuoteTakeOffUnits_Click()
-        { 
+        {
             var list = new MasterList(typeof(QuoteTakeOffUnit));
             list.ShowDialog();
         }
@@ -2546,7 +2484,7 @@ namespace PRSDesktop
             var list = new MasterList(typeof(JobDocumentSetMileStoneType));
             list.ShowDialog();
         }
-        
+
         private void JobDocumentTagButton_OnClick()
         {
             var list = new MasterList(typeof(JobDocumentSetTag));
@@ -2562,7 +2500,7 @@ namespace PRSDesktop
             var items = new List<ISetupActionItem>();
             if (SetupActions.TryGetValue(tab, out var actions))
             {
-                foreach(var action in actions)
+                foreach (var action in actions)
                 {
                     items.Add(action);
                 }
@@ -2593,7 +2531,7 @@ namespace PRSDesktop
                         menu.AddSeparator();
                 }
             }
-            if(CurrentPanel?.GetType().HasInterface(typeof(IPropertiesPanel<>)) == true && Security.IsAllowed<CanConfigurePanels>())
+            if (CurrentPanel?.GetType().HasInterface(typeof(IPropertiesPanel<>)) == true && Security.IsAllowed<CanConfigurePanels>())
             {
                 menu.AddItem("Configure Panel", PRSDesktop.Resources.edit, ConfigurePanel_Click);
             }
@@ -2644,7 +2582,7 @@ namespace PRSDesktop
             var properties = LoadPanelProperties<TPanel, TProperties>();
             var editor = new DynamicEditorForm(typeof(TProperties));
             editor.Items = new BaseObject[] { properties };
-            if(editor.ShowDialog() == true)
+            if (editor.ShowDialog() == true)
             {
                 SavePanelProperties<TPanel, TProperties>(properties);
             }
@@ -2729,7 +2667,7 @@ namespace PRSDesktop
                 e.Cancel = true;
                 return;
             }*/
-            
+
             App.IsClosing = true;
 
             FinalizeAutoTimesheet();
@@ -2786,7 +2724,7 @@ namespace PRSDesktop
             {
                 Notifications.AddNotification(notification);
             }
-            if(CurrentPanel is NotificationPanel panel)
+            if (CurrentPanel is NotificationPanel panel)
             {
                 panel.AddNotification(notification);
             }
@@ -2845,12 +2783,13 @@ namespace PRSDesktop
                     null,
                     (o, e) =>
                     {
-                        if(e is RemoteException remote)
+                        if (e is RemoteException remote)
                         {
-                            if(remote.Status == StatusCode.Unauthenticated)
+                            if (remote.Status == StatusCode.Unauthenticated)
                             {
                                 Logger.Send(LogType.Information, ClientFactory.UserID, "User has been logged out");
-                                Dispatcher.Invoke(() => {
+                                Dispatcher.Invoke(() =>
+                                {
                                     Logout("You have been logged out due to inactivity");
                                 });
                             }
@@ -2859,11 +2798,11 @@ namespace PRSDesktop
                                 Logger.Send(LogType.Information, ClientFactory.UserID, CoreUtils.FormatException(remote));
                             }
                         }
-                        else if(e is not null)
+                        else if (e is not null)
                         {
                             Logger.Send(LogType.Information, ClientFactory.UserID, CoreUtils.FormatException(e));
                         }
-                        else if(o is not null)
+                        else if (o is not null)
                         {
                             var row = o.Rows.FirstOrDefault();
                             if (row == null)
@@ -2899,7 +2838,7 @@ namespace PRSDesktop
                         new Client<Assignment>().Save(_kanbantrackingassignment, "");
                     }
 
-                    
+
                     if (Security.IsAllowed<MonitorApplicationWindows>())
                     {
                         if (ActivityHistory == null)
@@ -2995,9 +2934,9 @@ namespace PRSDesktop
             if (CurrentPanel != null)
                 CurrentPanel_Keys++;
         }
-        
+
         #region Recording
-        
+
         //private IntPtr myHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
         //{
 
@@ -3345,7 +3284,7 @@ namespace PRSDesktop
             Progress.Close();
 
             var dirName = Path.GetDirectoryName(filename);
-            if(dirName is not null)
+            if (dirName is not null)
             {
                 var startInfo = new ProcessStartInfo(dirName);
                 startInfo.Verb = "open";
@@ -3453,9 +3392,9 @@ namespace PRSDesktop
                 return $"{url}:{port}";
             }
             else
-                return Path.Combine(CoreUtils.GetCommonAppData("PRSServer"),"update");
+                return Path.Combine(CoreUtils.GetCommonAppData("PRSServer"), "update");
         }
-        
+
         private string GetLatestVersion(string location)
         {
             return App.DatabaseSettings.DatabaseType switch
@@ -3483,7 +3422,7 @@ namespace PRSDesktop
                 _ => null,
             };
         }
-        
+
         private void CheckForUpdates()
         {
             Update.CheckForUpdates(
@@ -3562,7 +3501,7 @@ namespace PRSDesktop
         {
             if (ClientFactory.IsSupported<CustomModule>())
             {
-                foreach(var (module, image) in CustomModuleUtils.LoadCustomModuleThumbnails(section, model))
+                foreach (var (module, image) in CustomModuleUtils.LoadCustomModuleThumbnails(section, model))
                 {
                     progress.Report(new Tuple<string, Bitmap, CustomModule>(module.Name ?? "", image, module));
                 }
@@ -3574,7 +3513,7 @@ namespace PRSDesktop
             Fluent.RibbonGroupBox? Actions = CurrentTab != null
                 ? FindRibbonBar(CurrentTab, x => x.Header.Equals("Actions"))
                 : null;
-            
+
             if (Actions != null)
             {
                 if (!CurrentModules.Any(x => x.GetType().Equals(typeof(RibbonSeparator))))
@@ -3623,7 +3562,7 @@ namespace PRSDesktop
                         if (result)
                             CurrentPanel.Refresh();
                     }
-                    catch(CompileException c)
+                    catch (CompileException c)
                     {
                         MessageBox.Show(c.Message);
                     }
@@ -3652,7 +3591,7 @@ namespace PRSDesktop
                 ReloadModules(section, dataModel);
             }
         }
-        
+
         private void ManageModulesClick(object sender, RoutedEventArgs e)
         {
             ManageModules();
@@ -3668,7 +3607,7 @@ namespace PRSDesktop
                 return;
 
             var ReportsBar = FindRibbonBar(CurrentTab, x => x.Header.Equals("Print"));
-            if(ReportsBar is not null)
+            if (ReportsBar is not null)
             {
                 ReportsBar.Visibility = Security.IsAllowed<CanPrintReports>() ? Visibility.Visible : Visibility.Collapsed;
                 //ReportsBar.IsLauncherVisible = Security.IsAllowed<CanDesignReports>();
@@ -3700,12 +3639,12 @@ namespace PRSDesktop
 
             var ReportsBar = FindRibbonBar(CurrentTab, x => x.Header.Equals("Print"));
 
-            if(ReportsBar is not null)
+            if (ReportsBar is not null)
             {
                 var bFound = false;
                 foreach (var item in ReportsBar.Items)
                 {
-                    if(item is RibbonButton button && report.Item2.Equals(button.Tag))
+                    if (item is RibbonButton button && report.Item2.Equals(button.Tag))
                         bFound = true;
                 }
 
@@ -3732,7 +3671,7 @@ namespace PRSDesktop
                 }
             }
         }
-        
+
         private void ReportButtonMenu_DesignReport_Click(Guid templateID)
         {
             if (CurrentPanel is null)
@@ -3757,7 +3696,7 @@ namespace PRSDesktop
             var item = (RibbonButton)sender;
             var id = (Guid)item.Tag;
             var template = new Client<ReportTemplate>().Load(new Filter<ReportTemplate>(x => x.ID).IsEqualTo(id)).FirstOrDefault();
-            if(template == null)
+            if (template == null)
             {
                 Logger.Send(LogType.Error, "", $"No Report Template with ID '{id}'");
                 MessageBox.Show("Report does not exist!");
@@ -3819,7 +3758,7 @@ namespace PRSDesktop
                     new Columns<KanbanSubscriber>(x => x.Kanban.ID)
                         .Add(x => x.Kanban.Number)
                         .Add(x => x.Kanban.Title)
-                        .Add(x=>x.Assignee),
+                        .Add(x => x.Assignee),
                     new SortOrder<KanbanSubscriber>(x => x.Kanban.Number, SortDirection.Ascending)
                 );
                 foreach (var row in kanbans.Rows)
@@ -3870,7 +3809,7 @@ namespace PRSDesktop
                 createNewAssignment = true;
             }
 
-            if(createNewAssignment)
+            if (createNewAssignment)
             {
                 _kanbantrackingassignment = new Assignment();
                 _kanbantrackingassignment.Task.ID = kanbanID;
@@ -3918,14 +3857,14 @@ namespace PRSDesktop
             if (layout.IsActive && layout.IsVisible)
                 dock.Refresh();
         }
-        
+
         private void _ribbon_OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
         {
             e.Handled = true;
         }
 
         #region Backstage Functions
-        
+
         private void DatabaseSettings_OnClick(object sender, RoutedEventArgs e)
         {
             var config = new DataBaseConfiguration();
@@ -3975,7 +3914,7 @@ namespace PRSDesktop
 
         private void DocumentTypeList_OnClick(object sender, RoutedEventArgs e)
         {
-            var list = new MasterList(typeof(DocumentType)); 
+            var list = new MasterList(typeof(DocumentType));
             list.ShowDialog();
         }
 
@@ -4062,8 +4001,6 @@ namespace PRSDesktop
             Close();
         }
 
-
         #endregion
-
     }
 }

+ 2 - 49
prs.desktop/Panels/Users/UserGrid.cs

@@ -11,6 +11,7 @@ using InABox.Core;
 using InABox.DynamicGrid;
 using InABox.Mail;
 using InABox.WPF;
+using PRS.Shared;
 using PRSDesktop.Panels.Users;
 using Syncfusion.Windows.Shared;
 
@@ -61,55 +62,7 @@ namespace PRSDesktop
                 "Please restart the app after loading from the link." + Environment.NewLine + Environment.NewLine +
                 "These links will expire after 10 minutes";
 
-            Clipboard.SetText(emailcontent);
-
-            if (string.IsNullOrWhiteSpace(user.EmailAddress))
-            {
-                MessageBox.Show("User email is blank - please populate email address or send the text copied to your clipboard");
-                return false;
-            }
-
-            var currentuser = new Client<User>()
-                .Query(new Filter<User>(x => x.ID).IsEqualTo(ClientFactory.UserGuid))
-                .Rows.FirstOrDefault()?.ToObject<User>();
-            if (currentuser is null)
-                return false;
-
-            var result = MessageBox.Show("Send email with user credentials to " + user.EmailAddress + " ?", "Alert", MessageBoxButton.YesNo);
-            switch (result)
-            {
-                case MessageBoxResult.Yes:
-                    break;
-                case MessageBoxResult.No:
-                    return false;
-                default:
-                    return false;
-            }
-
-            bool currentUserEmailDetailsOK = !string.IsNullOrWhiteSpace(currentuser.EmailHost) && currentuser.EmailPort != 0
-                && !string.IsNullOrWhiteSpace(currentuser.EmailAddress) && !string.IsNullOrWhiteSpace(currentuser.EmailPassword);
-
-            var mailer = new ExchangeMailer
-            {
-                MailboxHost = currentuser.EmailHost,
-                MailboxPort = currentuser.EmailPort,
-                MailboxUserName = currentuser.EmailAddress,
-                MailboxPassword = currentuser.EmailPassword
-            };
-            if (mailer.Connect())
-            {
-                var msg = mailer.CreateMessage();
-                msg.To = new string[] { user.EmailAddress };
-                msg.Subject = "Link to PRS Mobile";
-                msg.Body = emailcontent;
-                var bOK = mailer.SendMessage(msg);
-
-                if (!currentUserEmailDetailsOK)
-                    MessageBox.Show("Unable to send email - Email host, port, address or password missing for current user. Please update. The link has been copied to your clipboard for sending");
-
-                else if (bOK)
-                    MessageBox.Show("Link has been sent to email service. The link has been copied to your clipboard in case it is not received by the user");
-            }
+            EmailUtils.CreateEMLFile(user.EmailAddress, "PRS Mobile Configuration Links", emailcontent);
 
             return true;
         }