From b122b88435574350671450bfc4d535e5c4d22545 Mon Sep 17 00:00:00 2001 From: AJ Date: Tue, 28 Oct 2025 17:24:00 -0400 Subject: [PATCH] feat(ui): add equipment and drawing selectors powered by API\n\n- Inject ICutFabApiClient into MainForm\n- Populate equipment and drawings on load\n- Hook selection changes and pass into export context\n- Resize layout and replace prefix textbox with selectors --- ExportDXF/Forms/MainForm.Designer.cs | 98 +++++++++++++--------- ExportDXF/Forms/MainForm.cs | 116 +++++++++++++++------------ 2 files changed, 126 insertions(+), 88 deletions(-) diff --git a/ExportDXF/Forms/MainForm.Designer.cs b/ExportDXF/Forms/MainForm.Designer.cs index 2a6007c..7af8c30 100644 --- a/ExportDXF/Forms/MainForm.Designer.cs +++ b/ExportDXF/Forms/MainForm.Designer.cs @@ -31,11 +31,13 @@ this.activeDocTitleBox = new System.Windows.Forms.TextBox(); this.richTextBox1 = new System.Windows.Forms.RichTextBox(); this.label1 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.prefixTextBox = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.label3 = new System.Windows.Forms.Label(); this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.label4 = new System.Windows.Forms.Label(); + this.equipmentNoBox = new System.Windows.Forms.ComboBox(); + this.label5 = new System.Windows.Forms.Label(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); this.SuspendLayout(); // // activeDocTitleBox @@ -46,8 +48,8 @@ this.activeDocTitleBox.Location = new System.Drawing.Point(130, 13); this.activeDocTitleBox.Name = "activeDocTitleBox"; this.activeDocTitleBox.ReadOnly = true; - this.activeDocTitleBox.Size = new System.Drawing.Size(584, 25); - this.activeDocTitleBox.TabIndex = 2; + this.activeDocTitleBox.Size = new System.Drawing.Size(748, 25); + this.activeDocTitleBox.TabIndex = 1; this.activeDocTitleBox.TextChanged += new System.EventHandler(this.activeDocTitleBox_TextChanged); // // richTextBox1 @@ -59,8 +61,8 @@ this.richTextBox1.Location = new System.Drawing.Point(12, 106); this.richTextBox1.Name = "richTextBox1"; this.richTextBox1.ReadOnly = true; - this.richTextBox1.Size = new System.Drawing.Size(754, 342); - this.richTextBox1.TabIndex = 3; + this.richTextBox1.Size = new System.Drawing.Size(866, 556); + this.richTextBox1.TabIndex = 10; this.richTextBox1.Text = ""; // // label1 @@ -69,72 +71,92 @@ this.label1.Location = new System.Drawing.Point(13, 16); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(111, 17); - this.label1.TabIndex = 4; + this.label1.TabIndex = 0; this.label1.Text = "Active document :"; // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(23, 47); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(101, 17); - this.label2.TabIndex = 4; - this.label2.Text = "Prefix files with :"; - // - // prefixTextBox - // - this.prefixTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.prefixTextBox.Location = new System.Drawing.Point(130, 44); - this.prefixTextBox.Name = "prefixTextBox"; - this.prefixTextBox.Size = new System.Drawing.Size(584, 25); - this.prefixTextBox.TabIndex = 2; - // // button1 // this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.button1.Image = global::ExportDXF.Properties.Resources.play; - this.button1.Location = new System.Drawing.Point(720, 13); + this.button1.Location = new System.Drawing.Point(884, 13); this.button1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(46, 56); - this.button1.TabIndex = 0; + this.button1.TabIndex = 11; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(12, 78); + this.label3.Location = new System.Drawing.Point(12, 47); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(112, 17); - this.label3.TabIndex = 4; + this.label3.TabIndex = 2; this.label3.Text = "View flip decider :"; // // comboBox1 // this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox1.FormattingEnabled = true; - this.comboBox1.Location = new System.Drawing.Point(130, 75); + this.comboBox1.Location = new System.Drawing.Point(130, 44); this.comboBox1.Name = "comboBox1"; - this.comboBox1.Size = new System.Drawing.Size(353, 25); - this.comboBox1.TabIndex = 5; + this.comboBox1.Size = new System.Drawing.Size(432, 25); + this.comboBox1.TabIndex = 3; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(42, 78); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(82, 17); + this.label4.TabIndex = 4; + this.label4.Text = "Equipment #"; + // + // equipmentNoBox + // + this.equipmentNoBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.equipmentNoBox.FormattingEnabled = true; + this.equipmentNoBox.Location = new System.Drawing.Point(130, 75); + this.equipmentNoBox.Name = "equipmentNoBox"; + this.equipmentNoBox.Size = new System.Drawing.Size(138, 25); + this.equipmentNoBox.TabIndex = 5; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(314, 78); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(68, 17); + this.label5.TabIndex = 6; + this.label5.Text = "Drawing #"; + // + // comboBox2 + // + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Location = new System.Drawing.Point(388, 75); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(174, 25); + this.comboBox2.TabIndex = 7; // // MainForm // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; - this.ClientSize = new System.Drawing.Size(778, 460); + this.ClientSize = new System.Drawing.Size(942, 674); + this.Controls.Add(this.comboBox2); + this.Controls.Add(this.equipmentNoBox); + this.Controls.Add(this.label5); this.Controls.Add(this.comboBox1); + this.Controls.Add(this.label4); this.Controls.Add(this.label3); - this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Controls.Add(this.richTextBox1); - this.Controls.Add(this.prefixTextBox); this.Controls.Add(this.activeDocTitleBox); this.Controls.Add(this.button1); this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.MaximizeBox = false; + this.MinimumSize = new System.Drawing.Size(643, 355); this.Name = "MainForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "ExportDXF"; @@ -149,10 +171,12 @@ private System.Windows.Forms.TextBox activeDocTitleBox; private System.Windows.Forms.RichTextBox richTextBox1; private System.Windows.Forms.Label label1; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.TextBox prefixTextBox; private System.Windows.Forms.Label label3; private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox equipmentNoBox; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ComboBox comboBox2; } } diff --git a/ExportDXF/Forms/MainForm.cs b/ExportDXF/Forms/MainForm.cs index 89c1489..40ac98a 100644 --- a/ExportDXF/Forms/MainForm.cs +++ b/ExportDXF/Forms/MainForm.cs @@ -1,35 +1,33 @@ -using ExportDXF.Extensions; +using ExportDXF.Extensions; using ExportDXF.Models; using ExportDXF.Services; using ExportDXF.ViewFlipDeciders; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Information; using System; using System.Drawing; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; - namespace ExportDXF.Forms { public partial class MainForm : Form { private readonly ISolidWorksService _solidWorksService; private readonly IDxfExportService _exportService; + private readonly ICutFabApiClient _apiClient; private CancellationTokenSource _cancellationTokenSource; - - public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService) + public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService, ICutFabApiClient apiClient) { InitializeComponent(); - _solidWorksService = solidWorksService ?? throw new ArgumentNullException(nameof(solidWorksService)); - _exportService = exportService ?? throw new ArgumentNullException(nameof(exportService)); - + _apiClient = apiClient ?? + throw new ArgumentNullException(nameof(apiClient)); InitializeViewFlipDeciders(); } - ~MainForm() { _cancellationTokenSource?.Dispose(); @@ -37,29 +35,24 @@ namespace ExportDXF.Forms components?.Dispose(); Dispose(false); } - protected override async void OnLoad(EventArgs e) { base.OnLoad(e); - button1.Enabled = false; - await InitializeAsync(); } - private async Task InitializeAsync() { try { LogMessage("Connecting to SolidWorks, this may take a minute..."); - await _solidWorksService.ConnectAsync(); _solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged; - LogMessage("Ready", Color.Green); - UpdateActiveDocumentDisplay(); button1.Enabled = true; + // Populate equipment and (initial) drawings + await PopulateEquipmentAsync(); } catch (Exception ex) { @@ -68,7 +61,58 @@ namespace ExportDXF.Forms Application.Exit(); } } - + private async Task PopulateEquipmentAsync() + { + try + { + LogMessage($"Loading equipment from {_apiClient.BaseUrl} ..."); + var list = await _apiClient.GetEquipmentAsync(); + equipmentNoBox.DisplayMember = nameof(CutFabApiClient.ApiEquipment.EquipmentNumber); + equipmentNoBox.ValueMember = nameof(CutFabApiClient.ApiEquipment.ID); + equipmentNoBox.DataSource = list; + equipmentNoBox.SelectedIndexChanged -= equipmentNoBox_SelectedIndexChanged; + equipmentNoBox.SelectedIndexChanged += equipmentNoBox_SelectedIndexChanged; + if (list != null && list.Count > 0) + { + equipmentNoBox.SelectedIndex = 0; + await PopulateDrawingsForSelectedEquipmentAsync(); + LogMessage($"Loaded {list.Count} equipment record(s)", Color.Green); + } + else + { + LogMessage("No equipment returned by API", Color.DarkBlue); + } + } + catch (Exception ex) + { + LogMessage($"Failed to load equipment: {ex.Message}", Color.Red); + } + } + private async void equipmentNoBox_SelectedIndexChanged(object sender, EventArgs e) + { + await PopulateDrawingsForSelectedEquipmentAsync(); + } + private async Task PopulateDrawingsForSelectedEquipmentAsync() + { + try + { + var selected = equipmentNoBox.SelectedItem as CutFabApiClient.ApiEquipment; + if (selected == null) + { + comboBox2.DataSource = null; + return; + } + var drawings = await _apiClient.GetDrawingsForEquipmentAsync(selected.ID); + comboBox2.DisplayMember = nameof(CutFabApiClient.ApiDrawingSummary.DrawingNumber); + comboBox2.ValueMember = nameof(CutFabApiClient.ApiDrawingSummary.ID); + comboBox2.DataSource = drawings; + LogMessage($"Loaded {drawings.Count} drawing(s) for equipment {selected.EquipmentNumber}"); + } + catch (Exception ex) + { + LogMessage($"Failed to load drawings: {ex.Message}", Color.Red); + } + } private void InitializeViewFlipDeciders() { var items = ViewFlipDeciderFactory.GetAvailableDeciders() @@ -78,7 +122,6 @@ namespace ExportDXF.Forms ViewFlipDecider = d }) .ToList(); - // Move "Automatic" to the top if it exists var automatic = items.FirstOrDefault(i => i.Name == "Automatic"); if (automatic != null) @@ -86,11 +129,9 @@ namespace ExportDXF.Forms items.Remove(automatic); items.Insert(0, automatic); } - comboBox1.DataSource = items; comboBox1.DisplayMember = "Name"; } - private async void button1_Click(object sender, EventArgs e) { if (_cancellationTokenSource != null) @@ -102,39 +143,33 @@ namespace ExportDXF.Forms await StartExportAsync(); } } - private async Task StartExportAsync() { try { _cancellationTokenSource = new CancellationTokenSource(); var token = _cancellationTokenSource.Token; - UpdateUIForExportStart(); - var activeDoc = _solidWorksService.GetActiveDocument(); if (activeDoc == null) { LogMessage("No active document.", Color.Red); return; } - var viewFlipDecider = GetSelectedViewFlipDecider(); - var prefix = prefixTextBox.Text; - + var drawingNumberText = comboBox2.Text?.Trim(); + var selectedEquipment = equipmentNoBox.SelectedItem as CutFabApiClient.ApiEquipment; var exportContext = new ExportContext { ActiveDocument = activeDoc, ViewFlipDecider = viewFlipDecider, - FilePrefix = prefix, + FilePrefix = drawingNumberText, + EquipmentId = selectedEquipment?.ID, CancellationToken = token, ProgressCallback = LogMessage }; - LogMessage($"Started at {DateTime.Now:t}"); - await Task.Run(() => _exportService.Export(exportContext), token); - LogMessage("Done.", Color.Green); } catch (OperationCanceledException) @@ -153,41 +188,33 @@ namespace ExportDXF.Forms _cancellationTokenSource = null; } } - private void CancelExport() { button1.Enabled = false; _cancellationTokenSource?.Cancel(); } - private IViewFlipDecider GetSelectedViewFlipDecider() { var item = comboBox1.SelectedItem as ViewFlipDeciderComboboxItem; return item?.ViewFlipDecider; } - private void UpdateUIForExportStart() { activeDocTitleBox.Enabled = false; - prefixTextBox.Enabled = false; comboBox1.Enabled = false; button1.Image = Properties.Resources.stop_alt; - if (richTextBox1.TextLength != 0) { richTextBox1.AppendText("\n\n"); } } - private void UpdateUIForExportComplete() { activeDocTitleBox.Enabled = true; - prefixTextBox.Enabled = true; comboBox1.Enabled = true; button1.Image = Properties.Resources.play; button1.Enabled = true; } - private void OnActiveDocumentChanged(object sender, EventArgs e) { if (InvokeRequired) @@ -195,47 +222,36 @@ namespace ExportDXF.Forms Invoke(new Action(() => OnActiveDocumentChanged(sender, e))); return; } - UpdateActiveDocumentDisplay(); UpdatePrefixFromActiveDocument(); } - private void UpdateActiveDocumentDisplay() { var activeDoc = _solidWorksService.GetActiveDocument(); activeDocTitleBox.Text = activeDoc?.Title ?? ""; } - private void UpdatePrefixFromActiveDocument() { var activeDoc = _solidWorksService.GetActiveDocument(); - if (activeDoc == null) { - prefixTextBox.Text = string.Empty; return; } - if (activeDoc.DocumentType == DocumentType.Drawing) { var drawingInfo = DrawingInfo.Parse(activeDoc.Title); if (drawingInfo != null) { - prefixTextBox.Text = $"{drawingInfo.JobNo} {drawingInfo.DrawingNo} PT"; - prefixTextBox.SelectionStart = prefixTextBox.Text.Length; } } else { - prefixTextBox.Text = string.Empty; } } - private void activeDocTitleBox_TextChanged(object sender, EventArgs e) { UpdatePrefixFromActiveDocument(); } - private void LogMessage(string message, Color? color = null) { if (InvokeRequired) @@ -243,7 +259,6 @@ namespace ExportDXF.Forms Invoke(new Action(() => LogMessage(message, color))); return; } - if (color.HasValue) { richTextBox1.AppendText(message + System.Environment.NewLine, color.Value); @@ -252,8 +267,7 @@ namespace ExportDXF.Forms { richTextBox1.AppendText(message + System.Environment.NewLine); } - richTextBox1.ScrollToCaret(); } } -} +} \ No newline at end of file