JobDocumentSetPanel.xaml.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.ComponentModel;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Imaging;
  10. using Comal.Classes;
  11. using InABox.Clients;
  12. using InABox.Core;
  13. using InABox.DynamicGrid;
  14. using InABox.WPF;
  15. using InABox.Wpf;
  16. using Inflector;
  17. using Color = System.Drawing.Color;
  18. using InABox.Configuration;
  19. namespace PRSDesktop
  20. {
  21. public class JobDocumentSetSettings : BaseObject, IGlobalConfigurationSettings
  22. {
  23. [Caption("Milestone Task",IncludePath = false)]
  24. public KanbanTypeLink DocumentMilestoneKanbanType { get; set; }
  25. }
  26. public partial class JobDocumentSetPanel : UserControl, IMasterDetailControl<Job>, IDataModelSource, IPanel<Job>
  27. {
  28. private enum Suppress
  29. {
  30. This
  31. }
  32. private JobDocumentSetSettings _settings = new();
  33. public Job? Master { get; set; }
  34. public JobDocumentSetPanel()
  35. {
  36. using (new EventSuppressor(Suppress.This))
  37. InitializeComponent();
  38. }
  39. public string SectionName => "Job Document Set";
  40. public DataModel DataModel(Selection selection)
  41. {
  42. var ids = Documents.Data != null ? Documents.Data.ExtractValues<JobDocumentSet, Guid>(x => x.ID).ToArray() : new Guid[] { };
  43. return new AutoDataModel<JobDocumentSet>(new Filter<JobDocumentSet>(x => x.ID).InList(ids));
  44. }
  45. public event DataModelUpdateEvent? OnUpdateDataModel;
  46. private static bool GetAreas(CoreTable areas, ComboBox target) //, RowDefinition row)
  47. {
  48. using (new EventSuppressor(Suppress.This))
  49. {
  50. Dictionary<Guid, String> result = new Dictionary<Guid, String>()
  51. {
  52. { Guid.Empty, "" } //$"All {type.ToString().Pluralize()}" }
  53. };
  54. areas.IntoDictionary<JobITP, Guid, String>(result, x => x.ID,
  55. (r) => $"{r.Get<JobITP, String>(c => c.Code)}: {r.Get<JobITP, String>(c => c.Description)}");
  56. // row.Height = result.Count > 1
  57. // ? new GridLength(1, GridUnitType.Auto)
  58. // : new GridLength(0, GridUnitType.Pixel);
  59. var value = target.SelectedValue;
  60. target.ItemsSource = result;
  61. target.SelectedValue = value;
  62. return result.Count > 1;
  63. }
  64. }
  65. private static bool GetTags(CoreTable tags, JobDocumentSetTagType type, ComboBox target) //, RowDefinition row)
  66. {
  67. using (new EventSuppressor(Suppress.This))
  68. {
  69. var result = new Dictionary<Guid, String>()
  70. {
  71. { Guid.Empty, "" }
  72. };
  73. foreach (var tag in tags.Rows.Where(x => x.Get<JobDocumentSetTag, JobDocumentSetTagType>(x => x.Type).Equals(type)))
  74. result[tag.Get<JobDocumentSetTag, Guid>(c => c.ID)] = tag.Get<JobDocumentSetTag, String>(c => c.Description);
  75. // row.Height = result.Count > 1
  76. // ? new GridLength(1, GridUnitType.Auto)
  77. // : new GridLength(0, GridUnitType.Pixel);
  78. var value = target.SelectedValue;
  79. target.ItemsSource = result;
  80. target.SelectedValue = value;
  81. return result.Count > 1;
  82. }
  83. }
  84. public void Setup()
  85. {
  86. _settings = new GlobalConfiguration<JobDocumentSetSettings>().Load();
  87. tasks.Settings = _settings;
  88. tasks.Refresh(true, false);
  89. Folders.Refresh(true, false);
  90. }
  91. public void Shutdown(CancelEventArgs? cancel)
  92. {
  93. }
  94. public void Refresh()
  95. {
  96. LoadDocumentTags();
  97. Folders.Master = Master;
  98. Folders.Refresh(false, true);
  99. Documents.Master = Master;
  100. Documents.Refresh();
  101. }
  102. private void LoadDocumentTags()
  103. {
  104. // Global tags
  105. var tagFilter = new Filter<JobDocumentSetTag>(x => x.Job.ID).IsEqualTo(Guid.Empty);
  106. if(Master is not null && Master.ID != Guid.Empty)
  107. {
  108. tagFilter = tagFilter.Or(x => x.Job.ID).IsEqualTo(Master.ID);
  109. }
  110. var results = Client.QueryMultiple(
  111. new KeyedQueryDef<JobDocumentSetTag>(
  112. tagFilter,
  113. new Columns<JobDocumentSetTag>(x => x.ID)
  114. .Add(x => x.Type)
  115. .Add(x => x.Description),
  116. new SortOrder<JobDocumentSetTag>(x => x.Description)
  117. ),
  118. new KeyedQueryDef<JobITP>(
  119. new Filter<JobITP>(x => x.Job.ID).IsEqualTo(Master?.ID ?? Guid.Empty),
  120. new Columns<JobITP>(x => x.ID).Add(x => x.Code).Add(x => x.Description),
  121. new SortOrder<JobITP>(x => x.Code)));
  122. var tags = results.Get<JobDocumentSetTag>();
  123. /* Documents.DisciplineVisible = */
  124. GetTags(tags, JobDocumentSetTagType.Discipline, Discipline); //, DisciplineRow);
  125. /* Documents.TypeVisible = */
  126. GetTags(tags, JobDocumentSetTagType.Type, Type); //, TypeRow);
  127. /* Documents.CategoryVisible = */
  128. GetTags(tags, JobDocumentSetTagType.Category, Category); //, CategoryRow);
  129. /* Documents.AreaVisible = */
  130. GetAreas(results.Get<JobITP>(), Area); //, AreaRow);
  131. }
  132. public bool IsReady { get; set; }
  133. public void CreateToolbarButtons(IPanelHost host)
  134. {
  135. host.CreateSetupAction(new PanelAction() { Caption = "Job Settings", Image = PRSDesktop.Resources.specifications, OnExecute = JobSettingsClick });
  136. }
  137. private void JobSettingsClick(PanelAction obj)
  138. {
  139. if (DynamicGridUtils.EditObject(_settings))
  140. new GlobalConfiguration<JobDocumentSetSettings>().Save(_settings);
  141. }
  142. public Dictionary<string, object[]> Selected()
  143. {
  144. return new Dictionary<string, object[]>();
  145. }
  146. public void Heartbeat(TimeSpan time)
  147. {
  148. }
  149. private Guid _folderid = Guid.Empty;
  150. private void Folders_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
  151. {
  152. if (e.Rows is null || e.Rows.Length == 0) return;
  153. _folderid = e.Rows[0].Get<JobDocumentSetFolder, Guid>(x => x.ID);
  154. LoadDocuments(_folderid);
  155. }
  156. private void LoadDocuments(Guid folderID)
  157. {
  158. Documents.FolderIDs = Folders.GetChildFolders(folderID).Select(x => x.Get<JobDocumentSetFolder, Guid>(x => x.ID)).ToArray();
  159. Documents.Refresh();
  160. }
  161. private void DynamicSplitPanel_OnOnChanged(object sender, DynamicSplitPanelSettings e)
  162. {
  163. LoadDocuments(e.View == DynamicSplitPanelView.Detail ? Guid.Empty : _folderid);
  164. }
  165. private void Preview_OnSizeChanged(object sender, SizeChangedEventArgs e)
  166. {
  167. //throw new NotImplementedException();
  168. }
  169. private void Documents_OnMileStoneSelected(JobDocumentSetMileStoneBlock block)
  170. {
  171. tasks.JobID = Master?.ID ?? Guid.Empty;
  172. tasks.MileStoneID = block?.ID ?? Guid.Empty;
  173. tasks.Refresh(false, true);
  174. if (block != null && block.Attachments > 0)
  175. {
  176. var id = block.ID;
  177. var files = new Client<JobDocumentSetMileStoneFile>().Query(
  178. new Filter<JobDocumentSetMileStoneFile>(x => x.EntityLink.ID).IsEqualTo(block.ID),
  179. new Columns<JobDocumentSetMileStoneFile>(x => x.ID)
  180. .Add(x => x.DocumentLink.ID)
  181. .Add(x => x.DocumentLink.FileName)
  182. .Add(x => x.Thumbnail),
  183. new SortOrder<JobDocumentSetMileStoneFile>(x => x.DocumentLink.FileName)
  184. );
  185. preview.ItemsSource = files.Rows
  186. .Select(r =>
  187. {
  188. var thumbnailData = r.Get<JobDocumentSetMileStoneFile, byte[]?>(c => c.Thumbnail);
  189. var image = ImageUtils.LoadImage(thumbnailData);
  190. return new Tuple<Guid, String, BitmapImage, JobDocumentSetMileStoneFile>(
  191. r.Get<JobDocumentSetMileStoneFile, Guid>(c => c.ID),
  192. r.Get<JobDocumentSetMileStoneFile, String>(c => c.DocumentLink.FileName),
  193. image != null
  194. ? block.Watermark.IsNullOrWhiteSpace()
  195. ? image
  196. : image.AsBitmap().WatermarkImage(block.Watermark, Color.LightSalmon).AsBitmapImage()
  197. : ImageUtils.BitmapFromColor(Color.White, 256, 192, Color.Transparent)
  198. .WatermarkImage("No Preview\nAvailable", Color.LightGray).AsBitmapImage(),
  199. r.ToObject<JobDocumentSetMileStoneFile>());
  200. }).ToList();
  201. }
  202. else
  203. preview.ItemsSource = new List<Tuple<Guid, String, BitmapImage, JobDocumentSetMileStoneFile>>();
  204. }
  205. private void Tag_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  206. {
  207. Documents.DisciplineID = (Guid)(Discipline.SelectedValue ?? Guid.Empty);
  208. Documents.TypeID = (Guid)(Type.SelectedValue ?? Guid.Empty);
  209. Documents.CategoryID = (Guid)(Category.SelectedValue ?? Guid.Empty);
  210. Documents.AreaID = (Guid)(Area.SelectedValue ?? Guid.Empty);
  211. Documents.Refresh();
  212. }
  213. private void PDFDoubleClick(object sender, MouseButtonEventArgs e)
  214. {
  215. var image = (sender as ListViewItem).Content as Tuple<Guid, String, BitmapImage, JobDocumentSetMileStoneFile>;
  216. if (image != null)
  217. {
  218. var viewer = new DocumentEditor(new JobDocumentSetMileStoneFile[] { image.Item4 });
  219. viewer.ButtonsVisible = false;
  220. viewer.ShowDialog();
  221. }
  222. }
  223. private void Search_OnKeyUp(object sender, KeyEventArgs e)
  224. {
  225. if ((e.Key == Key.Enter) || (e.Key == Key.Return) || (e.Key == Key.Tab) || (e.Key == Key.OemBackTab))
  226. {
  227. Documents.SearchText = Search.Text;
  228. Documents.Refresh();
  229. }
  230. }
  231. private void EditDocumentTags(JobDocumentSetTagType tagtype)
  232. {
  233. var editor = new JobDocumentSetTagEditor()
  234. {
  235. TagType = tagtype,
  236. JobID = Master?.ID ?? Guid.Empty
  237. };
  238. editor.Refresh(true, true);
  239. var window = new DynamicContentDialog(editor, false);
  240. window.Title = $"{tagtype} Document Tags";
  241. window.ShowDialog();
  242. LoadDocumentTags();
  243. }
  244. private void DisciplineButton_OnClick(object sender, RoutedEventArgs e)
  245. {
  246. EditDocumentTags(JobDocumentSetTagType.Discipline);
  247. }
  248. private void TypeButton_OnClick(object sender, RoutedEventArgs e)
  249. {
  250. EditDocumentTags(JobDocumentSetTagType.Type);
  251. }
  252. private void CategoryButton_OnClick(object sender, RoutedEventArgs e)
  253. {
  254. EditDocumentTags(JobDocumentSetTagType.Category);
  255. }
  256. private void ShowPreview_OnClick(object sender, RoutedEventArgs e)
  257. {
  258. PreviewColumn.Width = new GridLength(260, GridUnitType.Pixel);
  259. ShowPreview.Visibility = Visibility.Collapsed;
  260. }
  261. private void HidePreview_OnClick(object sender, RoutedEventArgs e)
  262. {
  263. PreviewColumn.Width = new GridLength(0, GridUnitType.Pixel);
  264. ShowPreview.Visibility = Visibility.Visible;
  265. }
  266. private void Tasks_OnOnChanged(object sender, EventArgs args)
  267. {
  268. Documents.Refresh();
  269. }
  270. }
  271. }