JobPanel.xaml.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Threading;
  9. using Comal.Classes;
  10. using InABox.Clients;
  11. using InABox.Configuration;
  12. using InABox.Core;
  13. using InABox.DynamicGrid;
  14. using InABox.DynamicGrid.Spreadsheet;
  15. using InABox.WPF;
  16. using Microsoft.Office.Interop.Outlook;
  17. using System.ComponentModel;
  18. using Selection = InABox.Core.Selection;
  19. using PRSDesktop.Panels.Jobs;
  20. namespace PRSDesktop
  21. {
  22. public class JobPanelSettings : BaseObject, IGlobalConfigurationSettings
  23. {
  24. [Caption("Milestone Task",IncludePath = false)]
  25. public KanbanTypeLink DocumentMilestoneKanbanType { get; set; }
  26. }
  27. /// <summary>
  28. /// Interaction logic for JobPanel.xaml
  29. /// </summary>
  30. public partial class JobPanel : UserControl, IPanel<Job>
  31. {
  32. private enum PageIndex
  33. {
  34. Details = 00,
  35. Scopes,
  36. Documents,
  37. Stages,
  38. ITPs,
  39. ProductMappings,
  40. ProductStyles,
  41. BOM,
  42. Requisitions,
  43. Orders,
  44. Designs,
  45. Manufacturing,
  46. Dispatch,
  47. Delivery,
  48. Onsite,
  49. Kanban,
  50. Equipment,
  51. Employee,
  52. Tracker,
  53. Assignment,
  54. Timesheet,
  55. Form,
  56. Invoice,
  57. Spreadsheets,
  58. Summary
  59. }
  60. private int CurrentPage = -1;
  61. private JobDetails? JobDetailsPage;
  62. private JobScopePanel? _jobScopePage;
  63. private JobDocumentSetPanel? JobDocumentsPage;
  64. private JobStagesPanel? JobPlanningPage;
  65. private JobITPGrid? JobITPPage;
  66. private JobProductMappingsGrid? ProductMappingsPage;
  67. private JobProductStylesGrid? ProductStylesPage;
  68. private JobBillOfMaterialsPanel? JobBillOfMaterialsPage;
  69. private JobRequisitionPanel? JobRequisitionsPage;
  70. private JobDesignList? JobDesignsPage;
  71. private JobOrderGrid? JobOrderPage;
  72. private ManufacturingGrid? JobManufacturingPage;
  73. private ReadyToGoGrid? JobReadyToGoPage;
  74. private DeliveryPanel? JobDeliveriesPage;
  75. private DeliveredOnSiteGrid? JobOnSitePage;
  76. private TaskPanel? JobTasksPage;
  77. private JobEquipmentGrid? JobEquipmentPage;
  78. private JobEmployeePanel? JobEmployeePage;
  79. private JobTrackerGrid? JobTrackerPage;
  80. private JobAssignmentPanel? JobActivitiesPage;
  81. private JobTimesheetGrid? JobTimeSheetsPage;
  82. private JobFormGrid? JobFormsPage;
  83. private InvoicePanel? JobInvoicePage;
  84. private JobSpreadsheetGrid? JobSpreadsheetPage;
  85. private JobSummaryPanel? JobSummaryPage;
  86. private DateTime lastselection = DateTime.MaxValue;
  87. private IDataModelSource modelsource;
  88. // User Settings
  89. private JobScreenSettings settings;
  90. // Global Settings
  91. private JobPanelSettings _settings = null;
  92. private DispatcherTimer timer;
  93. public JobPanel()
  94. {
  95. InitializeComponent();
  96. }
  97. public bool IsReady { get; set; }
  98. public Dictionary<string, object[]> Selected()
  99. {
  100. return (PageIndex)JobPages.SelectedIndex switch
  101. {
  102. PageIndex.Details => JobDetailsPage?.Selected(),
  103. PageIndex.Scopes => _jobScopePage?.Selected(),
  104. PageIndex.Documents => JobDocumentsPage?.Selected(),
  105. PageIndex.Stages => JobPlanningPage?.Selected(),
  106. PageIndex.ITPs => new Dictionary<string, object[]> { { typeof(JobITP).EntityName(), JobITPPage.SelectedRows } },
  107. PageIndex.BOM => new Dictionary<string, object[]>
  108. { { typeof(JobBillOfMaterials).EntityName(), JobBillOfMaterialsPage.SelectedRows } },
  109. PageIndex.Designs => JobDesignsPage?.Selected(),
  110. PageIndex.Orders => new Dictionary<string, object[]> { { typeof(PurchaseOrderItem).EntityName(), JobOrderPage?.SelectedRows } },
  111. PageIndex.Requisitions => new Dictionary<string, object[]>
  112. { { typeof(JobRequisition).EntityName(), JobRequisitionsPage?.Requisitions?.SelectedRows } },
  113. PageIndex.Manufacturing => new Dictionary<string, object[]>
  114. { { typeof(ManufacturingPacket).EntityName(), JobManufacturingPage.SelectedRows } },
  115. PageIndex.Dispatch => new Dictionary<string, object[]> { { typeof(DeliveryItem).EntityName(), JobReadyToGoPage.SelectedRows } },
  116. PageIndex.Delivery => new Dictionary<string, object[]>
  117. { { typeof(Delivery).EntityName(), JobDeliveriesPage.Deliveries.SelectedRows } },
  118. PageIndex.Onsite => new Dictionary<string, object[]> { { typeof(DeliveryItem).EntityName(), JobOnSitePage.SelectedRows } },
  119. PageIndex.Kanban => JobTasksPage.Selected(),
  120. PageIndex.Equipment => new Dictionary<string, object[]> { { typeof(Equipment).EntityName(), JobEquipmentPage.SelectedRows } },
  121. PageIndex.Employee => new Dictionary<string, object[]>
  122. { { typeof(Employee).EntityName(), JobEmployeePage.Employees.SelectedRows } },
  123. PageIndex.Tracker => new Dictionary<string, object[]> { { typeof(GPSTracker).EntityName(), JobTrackerPage.SelectedRows } },
  124. PageIndex.Assignment => new Dictionary<string, object[]>
  125. { { typeof(Assignment).EntityName(), JobActivitiesPage.Assignments.SelectedRows } },
  126. PageIndex.Timesheet => new Dictionary<string, object[]> { { typeof(TimeSheet).EntityName(), JobTimeSheetsPage.SelectedRows } },
  127. PageIndex.Form => new Dictionary<string, object[]> { { typeof(JobForm).EntityName(), JobFormsPage.SelectedRows } },
  128. PageIndex.Invoice => new Dictionary<string, object[]> { { typeof(Invoice).EntityName(), JobInvoicePage.Invoices.SelectedRows } },
  129. PageIndex.Spreadsheets => new Dictionary<string, object[]> { { typeof(JobSpreadsheet).EntityName(), JobSpreadsheetPage.SelectedRows } },
  130. PageIndex.Summary => new Dictionary<string, object[]> { { typeof(JobMaterial).EntityName(), JobSummaryPage.Summary.SelectedRows } },
  131. _ => new Dictionary<string,object[]> {{ typeof(Job).EntityName(), JobGrid.SelectedRows}}
  132. };
  133. }
  134. public void Setup()
  135. {
  136. Task[] settingstasks = new Task[]
  137. {
  138. Task.Run(() =>
  139. {
  140. _settings = new GlobalConfiguration<JobPanelSettings>().Load();
  141. }),
  142. Task.Run(() =>
  143. {
  144. settings = new UserConfiguration<JobScreenSettings>().Load();
  145. })
  146. };
  147. Task.WaitAll(settingstasks);
  148. SplitPanel.View = settings.ViewType == ScreenViewType.Register ? DynamicSplitPanelView.Master :
  149. settings.ViewType == ScreenViewType.Details ? DynamicSplitPanelView.Detail : DynamicSplitPanelView.Combined;
  150. SplitPanel.AnchorWidth = settings.AnchorWidth;
  151. var sc = new Dictionary<Guid, string> { { Guid.Empty, "All Jobs" } };
  152. var statuses = new Client<JobStatus>().Query();
  153. foreach (var row in statuses.Rows)
  154. sc[row.Get<JobStatus, Guid>(x => x.ID)] = row.Get<JobStatus, string>(x => x.Description);
  155. JobStatus.ItemsSource = sc;
  156. if (sc.ContainsKey(settings.JobStatus))
  157. JobStatus.SelectedValue = settings.JobStatus;
  158. else
  159. JobStatus.SelectedValue = sc.Keys.First();
  160. JobGrid.OnSelectItem += JobGrid_OnSelectItem;
  161. JobGrid.BeforeRefresh += JobGrid_BeforeRefresh;
  162. JobGrid.AfterRefresh += JobGrid_AfterRefresh;
  163. Scopes.Visibility = Security.CanView<JobScope>() ? Visibility.Visible : Visibility.Collapsed;
  164. Documents.Visibility = Security.CanView<JobDocumentSet>() ? Visibility.Visible : Visibility.Collapsed;
  165. Stages.Visibility = ClientFactory.IsSupported<JobStage>() ? Visibility.Visible : Visibility.Collapsed;
  166. ITPs.Visibility = ClientFactory.IsSupported<JobITP>() ? Visibility.Visible : Visibility.Collapsed;
  167. ProductMappings.Visibility = ClientFactory.IsSupported<JobProductMapping>() ? Visibility.Visible : Visibility.Collapsed;
  168. ProductStyles.Visibility = ClientFactory.IsSupported<JobStyle>() ? Visibility.Visible : Visibility.Collapsed;
  169. BOM.Visibility = ClientFactory.IsSupported<JobBillOfMaterials>() ? Visibility.Visible : Visibility.Collapsed;
  170. Requisitions.Visibility = ClientFactory.IsSupported<JobRequisition>() ? Visibility.Visible : Visibility.Collapsed;
  171. Orders.Visibility = ClientFactory.IsSupported<PurchaseOrderItem>() ? Visibility.Visible : Visibility.Collapsed;
  172. Setouts.Visibility = ClientFactory.IsSupported<Setout>() ? Visibility.Visible : Visibility.Collapsed;
  173. Manufacturing.Visibility = ClientFactory.IsSupported<ManufacturingPacket>() ? Visibility.Visible : Visibility.Collapsed;
  174. Dispatch.Visibility = ClientFactory.IsSupported<DeliveryItem>() ? Visibility.Visible : Visibility.Collapsed;
  175. Deliveries.Visibility = ClientFactory.IsSupported<Delivery>() ? Visibility.Visible : Visibility.Collapsed;
  176. OnSite.Visibility = ClientFactory.IsSupported<DeliveryItem>() ? Visibility.Visible : Visibility.Collapsed;
  177. Tasks.Visibility = ClientFactory.IsSupported<Kanban>() ? Visibility.Visible : Visibility.Collapsed;
  178. EquipmentTab.Visibility = ClientFactory.IsSupported<Equipment>() ? Visibility.Visible : Visibility.Collapsed;
  179. Employees.Visibility = ClientFactory.IsSupported<Employee>() ? Visibility.Visible : Visibility.Collapsed;
  180. Trackers.Visibility = ClientFactory.IsSupported<GPSTracker>() ? Visibility.Visible : Visibility.Collapsed;
  181. Assignments.Visibility = ClientFactory.IsSupported<Assignment>() ? Visibility.Visible : Visibility.Collapsed;
  182. Timesheets.Visibility = ClientFactory.IsSupported<TimeSheet>() ? Visibility.Visible : Visibility.Collapsed;
  183. Forms.Visibility = Security.CanView<JobForm>() ? Visibility.Visible : Visibility.Collapsed;
  184. Invoices.Visibility = Security.CanView<Invoice>() ? Visibility.Visible : Visibility.Collapsed;
  185. Spreadsheets.Visibility = Security.CanView<JobSpreadsheet>() ? Visibility.Visible : Visibility.Collapsed;
  186. Summary.Visibility = ClientFactory.IsSupported<JobMaterial>() ? Visibility.Visible : Visibility.Collapsed;
  187. JobGrid.ColumnsTag = settings.ViewType == ScreenViewType.Register ? settings.ViewType.ToString() : "";
  188. JobGrid.Refresh(true, false);
  189. timer = new DispatcherTimer();
  190. timer.Tick += Timer_Tick;
  191. timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
  192. timer.IsEnabled = true;
  193. }
  194. private bool _jobGridRefreshing;
  195. private void JobGrid_BeforeRefresh(object sender, BeforeRefreshEventArgs args)
  196. {
  197. _jobGridRefreshing = true;
  198. }
  199. private void JobGrid_AfterRefresh(object sender, AfterRefreshEventArgs args)
  200. {
  201. if (settings.CurrentJob == Guid.Empty)
  202. {
  203. JobGrid.SelectedRows = Array.Empty<CoreRow>();
  204. }
  205. else
  206. {
  207. JobGrid.SelectedRows = JobGrid.Data.Rows.Where(x => x.Get<Job, Guid>(x => x.ID) == settings.CurrentJob).ToArray();
  208. }
  209. _jobGridRefreshing = false;
  210. }
  211. public void Shutdown(CancelEventArgs? cancel)
  212. {
  213. timer.IsEnabled = false;
  214. timer = null;
  215. Details.Content = null;
  216. JobDetailsPage = null;
  217. Scopes.Content = null;
  218. _jobScopePage = null;
  219. Documents.Content = null;
  220. JobDocumentsPage = null;
  221. Stages.Content = null;
  222. JobPlanningPage = null;
  223. //Levels.Content = null;
  224. //LevelGrid = null;
  225. //Zones.Content = null;
  226. //ZoneGrid = null;
  227. ITPs.Content = null;
  228. JobITPPage = null;
  229. BOM.Content = null;
  230. JobBillOfMaterialsPage = null;
  231. Setouts.Content = null;
  232. JobDesignsPage = null;
  233. Requisitions.Content = null;
  234. JobRequisitionsPage = null;
  235. Orders.Content = null;
  236. JobOrderPage = null;
  237. Manufacturing.Content = null;
  238. JobManufacturingPage = null;
  239. Dispatch.Content = null;
  240. JobReadyToGoPage = null;
  241. Deliveries.Content = null;
  242. JobDeliveriesPage = null;
  243. OnSite.Content = null;
  244. JobOnSitePage = null;
  245. Tasks.Content = null;
  246. JobTasksPage = null;
  247. EquipmentTab.Content = null;
  248. JobEquipmentPage = null;
  249. Employees.Content = null;
  250. JobEmployeePage = null;
  251. Trackers.Content = null;
  252. JobTrackerPage = null;
  253. Assignments.Content = null;
  254. JobActivitiesPage = null;
  255. Timesheets.Content = null;
  256. JobTimeSheetsPage = null;
  257. Forms.Content = null;
  258. JobFormsPage = null;
  259. Invoices.Content = null;
  260. JobInvoicePage = null;
  261. Spreadsheets.Content = null;
  262. JobSpreadsheetPage = null;
  263. Summary.Content = null;
  264. JobSummaryPage = null;
  265. }
  266. public void Refresh()
  267. {
  268. JobGrid.StatusID = (Guid)JobStatus.SelectedValue;
  269. JobGrid.Refresh(false, true);
  270. lastselection = DateTime.MinValue;
  271. }
  272. public void CreateToolbarButtons(IPanelHost host)
  273. {
  274. ProjectSetupActions.JobStatuses(host);
  275. ProjectSetupActions.DocumentMilestones(host);
  276. ProjectSetupActions.JobScopeStatuses(host);
  277. ProjectSetupActions.DrawingTemplates(host);
  278. host.CreateSetupSeparator();
  279. ProjectSetupActions.JobSpreadsheetTemplates(host);
  280. host.CreateSetupSeparator();
  281. ProjectSetupActions.SetoutGroups(host);
  282. host.CreateSetupAction(new PanelAction() { Caption = "Job Settings", Image = PRSDesktop.Resources.specifications, OnExecute = JobSettingsClick });
  283. }
  284. private void JobSettingsClick(PanelAction obj)
  285. {
  286. var pages = new DynamicEditorPages();
  287. var buttons = new DynamicEditorButtons();
  288. buttons.Add(
  289. "",
  290. PRSDesktop.Resources.help.AsBitmapImage(),
  291. _settings,
  292. (f, i) =>
  293. {
  294. Process.Start(new ProcessStartInfo("https://prsdigital.com.au/wiki/index.php/" + typeof(Equipment).Name.SplitCamelCase().Replace(" ", "_"))
  295. { UseShellExecute = true });
  296. }
  297. );
  298. var propertyEditor = new DynamicEditorForm(typeof(JobPanelSettings), pages, buttons);
  299. propertyEditor.OnDefineLookups += sender =>
  300. {
  301. var colname = sender.ColumnName;
  302. var values = sender.LookupEditorDefinition.Values(colname, new [] { _settings });
  303. sender.LoadLookups(values);
  304. };
  305. propertyEditor.OnEditorValueChanged += (sender, name, value) =>
  306. {
  307. CoreUtils.SetPropertyValue(_settings, name, value);
  308. return new Dictionary<string, object?>();
  309. };
  310. propertyEditor.Items = new BaseObject[] { _settings };
  311. if (propertyEditor.ShowDialog() == true)
  312. {
  313. new GlobalConfiguration<JobPanelSettings>().Save(_settings);
  314. }
  315. }
  316. public event DataModelUpdateEvent? OnUpdateDataModel;
  317. public string SectionName => modelsource?.SectionName ?? "Job Details";
  318. public DataModel DataModel(Selection selection)
  319. {
  320. if (modelsource == null)
  321. {
  322. var row = JobGrid.SelectedRows.FirstOrDefault();
  323. var jobid = row != null ? row.Get<Job, Guid>(x => x.ID) : CoreUtils.FullGuid;
  324. return new JobDetailsDataModel(new Filter<Job>(x => x.ID).IsEqualTo(jobid));
  325. }
  326. return modelsource.DataModel(selection);
  327. }
  328. public void Heartbeat(TimeSpan time)
  329. {
  330. }
  331. private void Timer_Tick(object? sender, EventArgs e)
  332. {
  333. if (lastselection < DateTime.Now.AddMilliseconds(-500) && !_jobGridRefreshing)
  334. {
  335. lastselection = DateTime.MaxValue;
  336. var job = JobGrid.SelectedRows.FirstOrDefault()?.ToObject<Job>() ?? new Job();
  337. //var jobid = row != null ? row.Get<Job, Guid>(x => x.ID) : CoreUtils.FullGuid;
  338. //Guid customerid = row != null ? row.Get<Job, Guid>(x => x.Customer.ID) : Guid.Empty;
  339. var page = (PageIndex)JobPages.SelectedIndex;
  340. switch (page)
  341. {
  342. case PageIndex.Details :
  343. RefreshPanel(Details, ref JobDetailsPage, job);
  344. break;
  345. case PageIndex.Scopes : RefreshPanel(Scopes, ref _jobScopePage, job);
  346. break;
  347. case PageIndex.Documents : RefreshPanel(Documents, ref JobDocumentsPage, job);
  348. break;
  349. case PageIndex.Stages : RefreshPanel(Stages, ref JobPlanningPage, job);
  350. break;
  351. case PageIndex.ITPs : RefreshGrid(ITPs, ref JobITPPage, job);
  352. break;
  353. case PageIndex.ProductMappings: RefreshGrid(ProductMappings, ref ProductMappingsPage, job);
  354. break;
  355. case PageIndex.ProductStyles: RefreshGrid(ProductStyles, ref ProductStylesPage, job);
  356. break;
  357. case PageIndex.BOM : RefreshPanel(BOM, ref JobBillOfMaterialsPage, job);
  358. break;
  359. case PageIndex.Requisitions : RefreshPanel(Requisitions, ref JobRequisitionsPage, job);
  360. break;
  361. case PageIndex.Orders : RefreshGrid(Orders, ref JobOrderPage, job);
  362. break;
  363. case PageIndex.Designs : RefreshPanel(Setouts, ref JobDesignsPage, job);
  364. break;
  365. case PageIndex.Manufacturing : RefreshGrid(Manufacturing, ref JobManufacturingPage, job);
  366. break;
  367. case PageIndex.Dispatch :
  368. RefreshGrid(Dispatch, ref JobReadyToGoPage, job);
  369. break;
  370. case PageIndex.Delivery :
  371. RefreshPanel(Deliveries, ref JobDeliveriesPage, job);
  372. break;
  373. case PageIndex.Onsite :
  374. RefreshGrid(OnSite, ref JobOnSitePage, job);
  375. break;
  376. case PageIndex.Kanban :
  377. RefreshPanel(Tasks, ref JobTasksPage, job);
  378. break;
  379. case PageIndex.Equipment :
  380. RefreshGrid(EquipmentTab, ref JobEquipmentPage, job);
  381. break;
  382. case PageIndex.Employee :
  383. RefreshPanel(Employees, ref JobEmployeePage, job);
  384. break;
  385. case PageIndex.Tracker :
  386. RefreshGrid(Trackers, ref JobTrackerPage, job);
  387. break;
  388. case PageIndex.Assignment :
  389. RefreshPanel(Assignments, ref JobActivitiesPage, job);
  390. break;
  391. case PageIndex.Timesheet :
  392. RefreshGrid(Timesheets, ref JobTimeSheetsPage, job);
  393. break;
  394. case PageIndex.Form :
  395. RefreshGrid(Forms, ref JobFormsPage, job);
  396. break;
  397. case PageIndex.Invoice :
  398. RefreshPanel(Invoices, ref JobInvoicePage, job);
  399. break;
  400. case PageIndex.Spreadsheets :
  401. RefreshGrid(Spreadsheets, ref JobSpreadsheetPage, job);
  402. break;
  403. case PageIndex.Summary :
  404. RefreshPanel(Summary, ref JobSummaryPage, job);
  405. break;
  406. }
  407. }
  408. }
  409. private void RefreshPanel<T>(TabItem container, ref T? panel, Job job) where T : IBasePanel, IJobControl, new()
  410. {
  411. if (panel == null)
  412. {
  413. panel = new T();
  414. panel.IsReady = false;
  415. //panel.ParentID = CoreUtils.FullGuid;
  416. panel.Job = new Job();
  417. panel.Settings = _settings;
  418. panel.Setup();
  419. panel.IsReady = true;
  420. container.Content = panel;
  421. }
  422. if (JobPages.SelectedIndex != CurrentPage)
  423. {
  424. modelsource = panel;
  425. OnUpdateDataModel?.Invoke(panel.SectionName, panel.DataModel(Selection.None));
  426. CurrentPage = JobPages.SelectedIndex;
  427. }
  428. //panel.ParentID = jobid;
  429. panel.Job = job;
  430. panel.Settings = _settings;
  431. panel.Refresh();
  432. }
  433. private void RefreshGrid<T>(TabItem container, ref T? grid, Job job) where T : IDynamicGrid, IJobControl, IDataModelSource, new()
  434. {
  435. var bInitialised = false;
  436. if (grid == null)
  437. {
  438. grid = new T();
  439. container.Content = grid;
  440. }
  441. else
  442. {
  443. bInitialised = true;
  444. }
  445. if (JobPages.SelectedIndex != CurrentPage)
  446. {
  447. modelsource = grid;
  448. OnUpdateDataModel?.Invoke(grid.SectionName, grid.DataModel(Selection.None));
  449. CurrentPage = JobPages.SelectedIndex;
  450. }
  451. //grid.ParentID = jobid;
  452. grid.Job = job;
  453. grid.Settings = _settings;
  454. grid.Refresh(!bInitialised, true);
  455. }
  456. private void JobGrid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
  457. {
  458. if (!_jobGridRefreshing)
  459. {
  460. lastselection = DateTime.Now;
  461. settings.CurrentJob = e.Rows?.FirstOrDefault()?.Get<Job, Guid>(x => x.ID) ?? Guid.Empty;
  462. new UserConfiguration<JobScreenSettings>().Save(settings);
  463. }
  464. }
  465. private void ShowEmailInterface(PanelAction obj)
  466. {
  467. var form = new EmailInterfaceForm();
  468. form.ShowDialog();
  469. }
  470. private MAPIFolder? FindFolder(NameSpace oNS, string foldername)
  471. {
  472. var folder = oNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
  473. if (string.IsNullOrEmpty(foldername))
  474. return folder;
  475. var comps = foldername.Split('/');
  476. foreach (var comp in comps)
  477. {
  478. var curfolder = folder;
  479. var bFound = false;
  480. foreach (MAPIFolder subfolder in folder.Folders)
  481. if (subfolder.Name.Equals(comp))
  482. {
  483. curfolder = subfolder;
  484. bFound = true;
  485. break;
  486. }
  487. if (bFound)
  488. folder = curfolder;
  489. else
  490. return null;
  491. }
  492. return folder;
  493. }
  494. private string ConstructReply(string job, string name, string body, bool html)
  495. {
  496. var emp = new Client<Employee>().Load(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault();
  497. var template = html
  498. ? "<p>Dear {0}</p>Thankyou for your email.</p><p>It has been allocated Job #{1}, and will be attended to as soon as possible.</p><p><b><u>Job Description:</u></b><br>{2}</p><p>Regards,</p><p>{3}"
  499. : "Dear {0}\n\nThankyou for your email.\n\nIt has been allocated Job #{1}, and will be attended to as soon as possible.\n\nJob Description:\n================\n{2}\n\nRegards,\n\n{3}";
  500. return string.Format(template, name.Split(' ').First(), job, body, emp != null ? emp.Name : "Frog Software");
  501. }
  502. private void CheckMailbox(PanelAction obj)
  503. {
  504. Progress.SetMessage("Connecting to Mail Service");
  505. var mailer = ClientFactory.CreateMailer();
  506. if (!mailer.Connect())
  507. {
  508. Progress.Close();
  509. MessageBox.Show("Unable to Connect to Mail System!");
  510. return;
  511. }
  512. Progress.SetMessage("Locating PRS Folder");
  513. var prs = mailer.FindFolder(null, "PRS");
  514. if (prs == null)
  515. {
  516. Progress.Close();
  517. MessageBox.Show("Unable to Find PRS Folder");
  518. return;
  519. }
  520. Progress.SetMessage("Locating Archive Folder");
  521. var archive = mailer.FindFolder(prs, "Archive");
  522. if (archive == null)
  523. {
  524. Progress.Close();
  525. MessageBox.Show("Unable to Find PRS/Archive Folder");
  526. return;
  527. }
  528. var me = new Client<Employee>().Load(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault();
  529. if (me == null)
  530. {
  531. Progress.Close();
  532. MessageBox.Show(string.Format("Employee [{0}] does not have a valid email address", me.Name));
  533. return;
  534. }
  535. //Outlook.Application app = new Outlook.Application();
  536. //Outlook.NameSpace ns = app.GetNamespace("mapi");
  537. //ns.Logon(Missing.Value, Missing.Value, false, true);
  538. //Outlook.MAPIFolder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
  539. //Outlook.MAPIFolder folder = FindFolder(ns,"PRS");
  540. //if (folder == null)
  541. // folder = (Outlook.Folder)inbox.Folders.Add("PRS",Outlook.OlDefaultFolders.olFolderInbox);
  542. //Outlook.MAPIFolder archive = FindFolder(ns, "PRS/Archive");
  543. //if (archive == null)
  544. // archive = (Outlook.Folder)folder.Folders.Add("Archive", Outlook.OlDefaultFolders.olFolderInbox);
  545. JobGrid jg = null;
  546. Customer[] customers = null;
  547. Progress.SetMessage("Scanning PRS Folder");
  548. var items = mailer.GetMessages(prs);
  549. foreach (var item in items)
  550. {
  551. if (customers == null)
  552. {
  553. Progress.SetMessage("Loading Customer Details");
  554. customers = new Client<Customer>().Load();
  555. }
  556. var cust = customers.FirstOrDefault(x => x.Email.Equals(item.From));
  557. if (cust != null)
  558. {
  559. if (jg == null)
  560. jg = new JobGrid();
  561. var job = new Job();
  562. jg.OnCustomiseEditor += Jg_OnCustomiseEditor;
  563. job.Name = item.Subject;
  564. job.Notes = new[] { item.Body };
  565. job.Customer.ID = cust.ID;
  566. job.Customer.Synchronise(cust);
  567. job.Account.ID = !cust.Account.IsValid() ? cust.ID : cust.Account.ID;
  568. var defstatus = new Client<JobStatus>().Query(new Filter<JobStatus>(x => x.Default).IsEqualTo(true));
  569. if (defstatus.Rows.Any())
  570. job.JobStatus.ID = defstatus.Rows.First().Get<JobStatus, Guid>(x => x.ID);
  571. Progress.Close();
  572. if (jg.EditItems(new[] { job }))
  573. {
  574. item.Subject = string.Format("{0} (PRS #{1})", job.Name, job.JobNumber);
  575. item.Save();
  576. mailer.MoveMessage(item, archive);
  577. //item.Move(archive);
  578. var message = mailer.CreateMessage();
  579. message.From = me.Email;
  580. message.Subject = string.Format("RE: {0}", item.Subject);
  581. message.Body = ConstructReply(job.JobNumber, cust.Name, string.Join("\n\n", job.Notes), false);
  582. message.To = new[] { cust.Email };
  583. mailer.SendMessage(message);
  584. //Outlook.MailItem replyMail = item.ReplyAll();
  585. //replyMail.To = cust.Email;
  586. //replyMail.Body = ConstructReply(job.JobNumber, cust.Name, String.Join("\n\n",job.Notes), false);
  587. //replyMail.Send();
  588. }
  589. Progress.Show("Scanning PRS Folder");
  590. }
  591. }
  592. items = null;
  593. Progress.SetMessage("Refreshing");
  594. Refresh();
  595. Progress.Close();
  596. MessageBox.Show("All Done");
  597. //ns.Logoff();
  598. //folder = null;
  599. //ns = null;
  600. //app = null;
  601. }
  602. private void Jg_OnCustomiseEditor(IDynamicEditorForm sender, Job[]? items, DynamicGridColumn column, BaseEditor editor)
  603. {
  604. if (column.ColumnName.Equals("Notes"))
  605. {
  606. if (editor is NotesEditor notes)
  607. notes.AlwaysEnabled = true;
  608. }
  609. }
  610. public Dictionary<Type, CoreTable> DataEnvironment()
  611. {
  612. var env = new Dictionary<Type, CoreTable>();
  613. env[typeof(Job)] = JobGrid.Data;
  614. return env;
  615. }
  616. private void JobPages_SelectionChanged(object sender, SelectionChangedEventArgs e)
  617. {
  618. if (e.Source == JobPages)
  619. lastselection = DateTime.MinValue;
  620. }
  621. private void JobStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
  622. {
  623. if (IsReady)
  624. {
  625. settings.JobStatus = (Guid)JobStatus.SelectedValue;
  626. new UserConfiguration<JobScreenSettings>().Save(settings);
  627. JobGrid.StatusID = (Guid)JobStatus.SelectedValue;
  628. JobGrid.Refresh(false, true);
  629. }
  630. }
  631. private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
  632. {
  633. settings.ViewType = SplitPanel.View == DynamicSplitPanelView.Master ? ScreenViewType.Register :
  634. SplitPanel.View == DynamicSplitPanelView.Detail ? ScreenViewType.Details : ScreenViewType.Combined;
  635. settings.AnchorWidth = SplitPanel.AnchorWidth;
  636. new UserConfiguration<JobScreenSettings>().Save(settings);
  637. var newTag = settings.ViewType == ScreenViewType.Register ? settings.ViewType.ToString() : "";
  638. if (JobGrid.ColumnsTag != newTag)
  639. {
  640. JobGrid.ColumnsTag = newTag;
  641. JobGrid.Refresh(true, true);
  642. }
  643. }
  644. }
  645. }