JobDocumentSetPanel.xaml.cs 12 KB

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