refactor: replace CutFab API with local file export and database
Remove CutFabApiClient and DrawingSelectionForm - exports no longer depend on an external API server. DXF/PDF files are saved directly to a configurable output folder, and export records are persisted to a local SQL Server database via EF Core. Replace Color-based progress logging with LogLevel enum across all services. Redesign MainForm with equipment/drawing filter dropdowns populated from export history, log row coloring by severity, and simplified startup flow in Program.cs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
283
ExportDXF/Forms/DrawingSelectionForm.Designer.cs
generated
283
ExportDXF/Forms/DrawingSelectionForm.Designer.cs
generated
@@ -1,283 +0,0 @@
|
||||
namespace ExportDXF.Forms
|
||||
{
|
||||
partial class DrawingSelectionForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.equipmentLabel = new System.Windows.Forms.Label();
|
||||
this.equipmentComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.drawingLabel = new System.Windows.Forms.Label();
|
||||
this.drawingComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.newDrawingButton = new System.Windows.Forms.Button();
|
||||
this.newDrawingPanel = new System.Windows.Forms.Panel();
|
||||
this.qtyNumericUpDown = new System.Windows.Forms.NumericUpDown();
|
||||
this.qtyLabel = new System.Windows.Forms.Label();
|
||||
this.descriptionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.descriptionLabel = new System.Windows.Forms.Label();
|
||||
this.drawingNumberTextBox = new System.Windows.Forms.TextBox();
|
||||
this.drawingNumberLabel = new System.Windows.Forms.Label();
|
||||
this.currentDrawingLabel = new System.Windows.Forms.Label();
|
||||
this.okButton = new System.Windows.Forms.Button();
|
||||
this.cancelButton = new System.Windows.Forms.Button();
|
||||
this.statusLabel = new System.Windows.Forms.Label();
|
||||
this.newDrawingPanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.qtyNumericUpDown)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// equipmentLabel
|
||||
//
|
||||
this.equipmentLabel.AutoSize = true;
|
||||
this.equipmentLabel.Location = new System.Drawing.Point(12, 15);
|
||||
this.equipmentLabel.Name = "equipmentLabel";
|
||||
this.equipmentLabel.Size = new System.Drawing.Size(82, 17);
|
||||
this.equipmentLabel.TabIndex = 0;
|
||||
this.equipmentLabel.Text = "Equipment #";
|
||||
//
|
||||
// equipmentComboBox
|
||||
//
|
||||
this.equipmentComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.equipmentComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.equipmentComboBox.FormattingEnabled = true;
|
||||
this.equipmentComboBox.Location = new System.Drawing.Point(100, 12);
|
||||
this.equipmentComboBox.Name = "equipmentComboBox";
|
||||
this.equipmentComboBox.Size = new System.Drawing.Size(470, 25);
|
||||
this.equipmentComboBox.TabIndex = 1;
|
||||
this.equipmentComboBox.SelectedIndexChanged += new System.EventHandler(this.equipmentComboBox_SelectedIndexChanged);
|
||||
//
|
||||
// drawingLabel
|
||||
//
|
||||
this.drawingLabel.AutoSize = true;
|
||||
this.drawingLabel.Location = new System.Drawing.Point(12, 48);
|
||||
this.drawingLabel.Name = "drawingLabel";
|
||||
this.drawingLabel.Size = new System.Drawing.Size(68, 17);
|
||||
this.drawingLabel.TabIndex = 2;
|
||||
this.drawingLabel.Text = "Drawing #";
|
||||
//
|
||||
// drawingComboBox
|
||||
//
|
||||
this.drawingComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.drawingComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.drawingComboBox.FormattingEnabled = true;
|
||||
this.drawingComboBox.Location = new System.Drawing.Point(100, 45);
|
||||
this.drawingComboBox.Name = "drawingComboBox";
|
||||
this.drawingComboBox.Size = new System.Drawing.Size(370, 25);
|
||||
this.drawingComboBox.TabIndex = 3;
|
||||
//
|
||||
// newDrawingButton
|
||||
//
|
||||
this.newDrawingButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.newDrawingButton.Location = new System.Drawing.Point(476, 43);
|
||||
this.newDrawingButton.Name = "newDrawingButton";
|
||||
this.newDrawingButton.Size = new System.Drawing.Size(94, 27);
|
||||
this.newDrawingButton.TabIndex = 4;
|
||||
this.newDrawingButton.Text = "New Drawing";
|
||||
this.newDrawingButton.UseVisualStyleBackColor = true;
|
||||
this.newDrawingButton.Click += new System.EventHandler(this.newDrawingButton_Click);
|
||||
//
|
||||
// newDrawingPanel
|
||||
//
|
||||
this.newDrawingPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.newDrawingPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.newDrawingPanel.Controls.Add(this.qtyNumericUpDown);
|
||||
this.newDrawingPanel.Controls.Add(this.qtyLabel);
|
||||
this.newDrawingPanel.Controls.Add(this.descriptionTextBox);
|
||||
this.newDrawingPanel.Controls.Add(this.descriptionLabel);
|
||||
this.newDrawingPanel.Controls.Add(this.drawingNumberTextBox);
|
||||
this.newDrawingPanel.Controls.Add(this.drawingNumberLabel);
|
||||
this.newDrawingPanel.Location = new System.Drawing.Point(15, 85);
|
||||
this.newDrawingPanel.Name = "newDrawingPanel";
|
||||
this.newDrawingPanel.Size = new System.Drawing.Size(555, 120);
|
||||
this.newDrawingPanel.TabIndex = 5;
|
||||
this.newDrawingPanel.Visible = false;
|
||||
//
|
||||
// qtyNumericUpDown
|
||||
//
|
||||
this.qtyNumericUpDown.Location = new System.Drawing.Point(124, 72);
|
||||
this.qtyNumericUpDown.Maximum = new decimal(new int[] {
|
||||
10000,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.qtyNumericUpDown.Minimum = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.qtyNumericUpDown.Name = "qtyNumericUpDown";
|
||||
this.qtyNumericUpDown.Size = new System.Drawing.Size(100, 25);
|
||||
this.qtyNumericUpDown.TabIndex = 5;
|
||||
this.qtyNumericUpDown.Value = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// qtyLabel
|
||||
//
|
||||
this.qtyLabel.AutoSize = true;
|
||||
this.qtyLabel.Location = new System.Drawing.Point(10, 74);
|
||||
this.qtyLabel.Name = "qtyLabel";
|
||||
this.qtyLabel.Size = new System.Drawing.Size(56, 17);
|
||||
this.qtyLabel.TabIndex = 4;
|
||||
this.qtyLabel.Text = "Quantity";
|
||||
//
|
||||
// descriptionTextBox
|
||||
//
|
||||
this.descriptionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.descriptionTextBox.Location = new System.Drawing.Point(124, 41);
|
||||
this.descriptionTextBox.Name = "descriptionTextBox";
|
||||
this.descriptionTextBox.Size = new System.Drawing.Size(411, 25);
|
||||
this.descriptionTextBox.TabIndex = 3;
|
||||
//
|
||||
// descriptionLabel
|
||||
//
|
||||
this.descriptionLabel.AutoSize = true;
|
||||
this.descriptionLabel.Location = new System.Drawing.Point(10, 44);
|
||||
this.descriptionLabel.Name = "descriptionLabel";
|
||||
this.descriptionLabel.Size = new System.Drawing.Size(74, 17);
|
||||
this.descriptionLabel.TabIndex = 2;
|
||||
this.descriptionLabel.Text = "Description";
|
||||
//
|
||||
// drawingNumberTextBox
|
||||
//
|
||||
this.drawingNumberTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.drawingNumberTextBox.Location = new System.Drawing.Point(124, 10);
|
||||
this.drawingNumberTextBox.Name = "drawingNumberTextBox";
|
||||
this.drawingNumberTextBox.Size = new System.Drawing.Size(411, 25);
|
||||
this.drawingNumberTextBox.TabIndex = 1;
|
||||
this.drawingNumberTextBox.TextChanged += new System.EventHandler(this.drawingNumberTextBox_TextChanged);
|
||||
//
|
||||
// drawingNumberLabel
|
||||
//
|
||||
this.drawingNumberLabel.AutoSize = true;
|
||||
this.drawingNumberLabel.Location = new System.Drawing.Point(10, 13);
|
||||
this.drawingNumberLabel.Name = "drawingNumberLabel";
|
||||
this.drawingNumberLabel.Size = new System.Drawing.Size(108, 17);
|
||||
this.drawingNumberLabel.TabIndex = 0;
|
||||
this.drawingNumberLabel.Text = "Drawing Number";
|
||||
//
|
||||
// currentDrawingLabel
|
||||
//
|
||||
this.currentDrawingLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.currentDrawingLabel.AutoEllipsis = true;
|
||||
this.currentDrawingLabel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.currentDrawingLabel.Location = new System.Drawing.Point(15, 217);
|
||||
this.currentDrawingLabel.Name = "currentDrawingLabel";
|
||||
this.currentDrawingLabel.Size = new System.Drawing.Size(557, 41);
|
||||
this.currentDrawingLabel.TabIndex = 9;
|
||||
this.currentDrawingLabel.Text = "Loading active drawing...";
|
||||
//
|
||||
// okButton
|
||||
//
|
||||
this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.okButton.Enabled = false;
|
||||
this.okButton.Location = new System.Drawing.Point(414, 273);
|
||||
this.okButton.Name = "okButton";
|
||||
this.okButton.Size = new System.Drawing.Size(75, 30);
|
||||
this.okButton.TabIndex = 6;
|
||||
this.okButton.Text = "OK";
|
||||
this.okButton.UseVisualStyleBackColor = true;
|
||||
this.okButton.Click += new System.EventHandler(this.okButton_Click);
|
||||
//
|
||||
// cancelButton
|
||||
//
|
||||
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelButton.Location = new System.Drawing.Point(495, 273);
|
||||
this.cancelButton.Name = "cancelButton";
|
||||
this.cancelButton.Size = new System.Drawing.Size(75, 30);
|
||||
this.cancelButton.TabIndex = 7;
|
||||
this.cancelButton.Text = "Cancel";
|
||||
this.cancelButton.UseVisualStyleBackColor = true;
|
||||
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
|
||||
//
|
||||
// statusLabel
|
||||
//
|
||||
this.statusLabel.AutoSize = true;
|
||||
this.statusLabel.Location = new System.Drawing.Point(15, 280);
|
||||
this.statusLabel.Name = "statusLabel";
|
||||
this.statusLabel.Size = new System.Drawing.Size(44, 17);
|
||||
this.statusLabel.TabIndex = 8;
|
||||
this.statusLabel.Text = "Ready";
|
||||
//
|
||||
// DrawingSelectionForm
|
||||
//
|
||||
this.AcceptButton = this.okButton;
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.CancelButton = this.cancelButton;
|
||||
this.ClientSize = new System.Drawing.Size(584, 315);
|
||||
this.Controls.Add(this.currentDrawingLabel);
|
||||
this.Controls.Add(this.statusLabel);
|
||||
this.Controls.Add(this.cancelButton);
|
||||
this.Controls.Add(this.okButton);
|
||||
this.Controls.Add(this.newDrawingPanel);
|
||||
this.Controls.Add(this.newDrawingButton);
|
||||
this.Controls.Add(this.drawingComboBox);
|
||||
this.Controls.Add(this.drawingLabel);
|
||||
this.Controls.Add(this.equipmentComboBox);
|
||||
this.Controls.Add(this.equipmentLabel);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "DrawingSelectionForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Select Drawing - ExportDXF";
|
||||
this.newDrawingPanel.ResumeLayout(false);
|
||||
this.newDrawingPanel.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.qtyNumericUpDown)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label equipmentLabel;
|
||||
private System.Windows.Forms.ComboBox equipmentComboBox;
|
||||
private System.Windows.Forms.Label drawingLabel;
|
||||
private System.Windows.Forms.ComboBox drawingComboBox;
|
||||
private System.Windows.Forms.Button newDrawingButton;
|
||||
private System.Windows.Forms.Panel newDrawingPanel;
|
||||
private System.Windows.Forms.TextBox drawingNumberTextBox;
|
||||
private System.Windows.Forms.Label drawingNumberLabel;
|
||||
private System.Windows.Forms.TextBox descriptionTextBox;
|
||||
private System.Windows.Forms.Label descriptionLabel;
|
||||
private System.Windows.Forms.NumericUpDown qtyNumericUpDown;
|
||||
private System.Windows.Forms.Label qtyLabel;
|
||||
private System.Windows.Forms.Label currentDrawingLabel;
|
||||
private System.Windows.Forms.Button okButton;
|
||||
private System.Windows.Forms.Button cancelButton;
|
||||
private System.Windows.Forms.Label statusLabel;
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
using ExportDXF.Services;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ExportDXF.Forms
|
||||
{
|
||||
public partial class DrawingSelectionForm : Form
|
||||
{
|
||||
private readonly ICutFabApiClient _apiClient;
|
||||
private readonly ISolidWorksService _solidWorksService;
|
||||
|
||||
public int? SelectedDrawingId { get; private set; }
|
||||
public string SelectedDrawingNumber { get; private set; }
|
||||
|
||||
public DrawingSelectionForm(ICutFabApiClient apiClient, ISolidWorksService solidWorksService)
|
||||
{
|
||||
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
|
||||
_solidWorksService = solidWorksService ?? throw new ArgumentNullException(nameof(solidWorksService));
|
||||
_solidWorksService.ActiveDocumentChanged += (s, e) => DisplayActiveDrawing();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override async void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
DisplayActiveDrawing();
|
||||
await LoadEquipmentAsync();
|
||||
}
|
||||
|
||||
private void DisplayActiveDrawing()
|
||||
{
|
||||
try
|
||||
{
|
||||
var activeDoc = _solidWorksService.GetActiveDocument();
|
||||
if (activeDoc != null && activeDoc.DocumentType == Models.DocumentType.Drawing)
|
||||
{
|
||||
currentDrawingLabel.Text = $"Active Drawing: {activeDoc.Title}";
|
||||
currentDrawingLabel.ForeColor = Color.Green;
|
||||
}
|
||||
else if (activeDoc != null)
|
||||
{
|
||||
currentDrawingLabel.Text = $"Active Document: {activeDoc.Title} (Not a Drawing)";
|
||||
currentDrawingLabel.ForeColor = Color.Orange;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentDrawingLabel.Text = "No active SolidWorks document";
|
||||
currentDrawingLabel.ForeColor = Color.Gray;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
currentDrawingLabel.Text = $"Error getting active document: {ex.Message}";
|
||||
currentDrawingLabel.ForeColor = Color.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadEquipmentAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
statusLabel.Text = "Loading equipment...";
|
||||
statusLabel.ForeColor = Color.Black;
|
||||
|
||||
var equipment = await _apiClient.GetEquipmentAsync();
|
||||
|
||||
equipmentComboBox.DisplayMember = nameof(CutFabApiClient.ApiEquipment.EquipmentNumber);
|
||||
equipmentComboBox.ValueMember = nameof(CutFabApiClient.ApiEquipment.ID);
|
||||
equipmentComboBox.DataSource = equipment;
|
||||
|
||||
if (equipment.Count > 0)
|
||||
{
|
||||
equipmentComboBox.SelectedIndex = 0;
|
||||
statusLabel.Text = $"Loaded {equipment.Count} equipment record(s)";
|
||||
statusLabel.ForeColor = Color.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusLabel.Text = "No equipment found";
|
||||
statusLabel.ForeColor = Color.Red;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
statusLabel.Text = $"Error loading equipment: {ex.Message}";
|
||||
statusLabel.ForeColor = Color.Red;
|
||||
MessageBox.Show($"Failed to load equipment: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void equipmentComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
await LoadDrawingsAsync();
|
||||
}
|
||||
|
||||
private async Task LoadDrawingsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var selectedEquipment = equipmentComboBox.SelectedItem as CutFabApiClient.ApiEquipment;
|
||||
if (selectedEquipment == null)
|
||||
{
|
||||
drawingComboBox.DataSource = null;
|
||||
return;
|
||||
}
|
||||
|
||||
statusLabel.Text = "Loading drawings...";
|
||||
statusLabel.ForeColor = Color.Black;
|
||||
|
||||
var drawings = await _apiClient.GetDrawingsForEquipmentAsync(selectedEquipment.ID);
|
||||
|
||||
drawingComboBox.DisplayMember = nameof(CutFabApiClient.ApiDrawingSummary.DrawingNumber);
|
||||
drawingComboBox.ValueMember = nameof(CutFabApiClient.ApiDrawingSummary.ID);
|
||||
drawingComboBox.DataSource = drawings;
|
||||
|
||||
if (drawings.Count > 0)
|
||||
{
|
||||
statusLabel.Text = $"Loaded {drawings.Count} drawing(s)";
|
||||
statusLabel.ForeColor = Color.Green;
|
||||
drawingComboBox.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusLabel.Text = "No drawings found for this equipment";
|
||||
statusLabel.ForeColor = Color.DarkBlue;
|
||||
drawingComboBox.Enabled = false;
|
||||
}
|
||||
|
||||
UpdateOkButtonState();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
statusLabel.Text = $"Error loading drawings: {ex.Message}";
|
||||
statusLabel.ForeColor = Color.Red;
|
||||
}
|
||||
}
|
||||
|
||||
private void newDrawingButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
ToggleNewDrawingMode(!newDrawingPanel.Visible);
|
||||
}
|
||||
|
||||
private void ToggleNewDrawingMode(bool enabled)
|
||||
{
|
||||
newDrawingPanel.Visible = enabled;
|
||||
drawingComboBox.Enabled = !enabled;
|
||||
newDrawingButton.Text = enabled ? "Cancel New" : "New Drawing";
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
drawingNumberTextBox.Focus();
|
||||
}
|
||||
|
||||
UpdateOkButtonState();
|
||||
}
|
||||
|
||||
private void drawingNumberTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateOkButtonState();
|
||||
}
|
||||
|
||||
private void UpdateOkButtonState()
|
||||
{
|
||||
if (newDrawingPanel.Visible)
|
||||
{
|
||||
// Creating new drawing - require drawing number
|
||||
okButton.Enabled = !string.IsNullOrWhiteSpace(drawingNumberTextBox.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Selecting existing drawing
|
||||
okButton.Enabled = drawingComboBox.SelectedItem != null;
|
||||
}
|
||||
}
|
||||
|
||||
private async void okButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
okButton.Enabled = false;
|
||||
statusLabel.Text = "Processing...";
|
||||
statusLabel.ForeColor = Color.Black;
|
||||
|
||||
if (newDrawingPanel.Visible)
|
||||
{
|
||||
// Create new drawing
|
||||
await CreateNewDrawingAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use existing drawing
|
||||
var selectedDrawing = drawingComboBox.SelectedItem as CutFabApiClient.ApiDrawingSummary;
|
||||
if (selectedDrawing != null)
|
||||
{
|
||||
SelectedDrawingId = selectedDrawing.ID;
|
||||
SelectedDrawingNumber = selectedDrawing.DrawingNumber;
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
statusLabel.Text = $"Error: {ex.Message}";
|
||||
statusLabel.ForeColor = Color.Red;
|
||||
MessageBox.Show($"Operation failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
okButton.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CreateNewDrawingAsync()
|
||||
{
|
||||
var selectedEquipment = equipmentComboBox.SelectedItem as CutFabApiClient.ApiEquipment;
|
||||
if (selectedEquipment == null)
|
||||
{
|
||||
MessageBox.Show("Please select equipment first.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var drawingNumber = drawingNumberTextBox.Text.Trim();
|
||||
if (string.IsNullOrWhiteSpace(drawingNumber))
|
||||
{
|
||||
MessageBox.Show("Please enter a drawing number.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
statusLabel.Text = "Creating new drawing...";
|
||||
statusLabel.ForeColor = Color.Black;
|
||||
|
||||
var response = await _apiClient.CreateDrawingWithInfoAsync(selectedEquipment.ID, drawingNumber);
|
||||
|
||||
if (response.Success && response.Data.HasValue)
|
||||
{
|
||||
SelectedDrawingId = response.Data.Value;
|
||||
SelectedDrawingNumber = drawingNumber;
|
||||
statusLabel.Text = "Drawing created successfully";
|
||||
statusLabel.ForeColor = Color.Green;
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorMsg = response.Error ?? "Unknown error occurred";
|
||||
statusLabel.Text = $"Failed to create drawing: {errorMsg}";
|
||||
statusLabel.ForeColor = Color.Red;
|
||||
MessageBox.Show($"Failed to create drawing: {errorMsg}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
okButton.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
290
ExportDXF/Forms/MainForm.Designer.cs
generated
290
ExportDXF/Forms/MainForm.Designer.cs
generated
@@ -1,4 +1,4 @@
|
||||
namespace ExportDXF.Forms
|
||||
namespace ExportDXF.Forms
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
@@ -28,192 +28,169 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
this.runButton = new System.Windows.Forms.Button();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.viewFlipDeciderBox = new System.Windows.Forms.ComboBox();
|
||||
this.mainTabControl = new System.Windows.Forms.TabControl();
|
||||
this.logEventsTab = new System.Windows.Forms.TabPage();
|
||||
this.logEventsDataGrid = new System.Windows.Forms.DataGridView();
|
||||
this.bomTab = new System.Windows.Forms.TabPage();
|
||||
this.bomDataGrid = new System.Windows.Forms.DataGridView();
|
||||
this.cutTemplatesTab = new System.Windows.Forms.TabPage();
|
||||
this.cutTemplatesDataGrid = new System.Windows.Forms.DataGridView();
|
||||
this.dwgDetailsTab = new System.Windows.Forms.TabPage();
|
||||
this.drawingPdfViewer = new AxAcroPDFLib.AxAcroPDF();
|
||||
this.mainTabControl.SuspendLayout();
|
||||
this.logEventsTab.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.logEventsDataGrid)).BeginInit();
|
||||
this.bomTab.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.bomDataGrid)).BeginInit();
|
||||
this.cutTemplatesTab.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.cutTemplatesDataGrid)).BeginInit();
|
||||
this.dwgDetailsTab.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.drawingPdfViewer)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
runButton = new System.Windows.Forms.Button();
|
||||
label3 = new System.Windows.Forms.Label();
|
||||
viewFlipDeciderBox = new System.Windows.Forms.ComboBox();
|
||||
mainTabControl = new System.Windows.Forms.TabControl();
|
||||
logEventsTab = new System.Windows.Forms.TabPage();
|
||||
logEventsDataGrid = new System.Windows.Forms.DataGridView();
|
||||
bomTab = new System.Windows.Forms.TabPage();
|
||||
bomDataGrid = new System.Windows.Forms.DataGridView();
|
||||
equipmentBox = new System.Windows.Forms.ComboBox();
|
||||
label1 = new System.Windows.Forms.Label();
|
||||
label2 = new System.Windows.Forms.Label();
|
||||
drawingNoBox = new System.Windows.Forms.ComboBox();
|
||||
mainTabControl.SuspendLayout();
|
||||
logEventsTab.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)logEventsDataGrid).BeginInit();
|
||||
bomTab.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)bomDataGrid).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// runButton
|
||||
//
|
||||
this.runButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.runButton.Location = new System.Drawing.Point(790, 13);
|
||||
this.runButton.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.runButton.Name = "runButton";
|
||||
this.runButton.Size = new System.Drawing.Size(100, 30);
|
||||
this.runButton.TabIndex = 11;
|
||||
this.runButton.Text = "Start";
|
||||
this.runButton.UseVisualStyleBackColor = true;
|
||||
this.runButton.Click += new System.EventHandler(this.button1_Click);
|
||||
runButton.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
runButton.Location = new System.Drawing.Point(656, 13);
|
||||
runButton.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
runButton.Name = "runButton";
|
||||
runButton.Size = new System.Drawing.Size(100, 30);
|
||||
runButton.TabIndex = 11;
|
||||
runButton.Text = "Start";
|
||||
runButton.UseVisualStyleBackColor = true;
|
||||
runButton.Click += button1_Click;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(12, 20);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(112, 17);
|
||||
this.label3.TabIndex = 2;
|
||||
this.label3.Text = "View flip decider :";
|
||||
label3.AutoSize = true;
|
||||
label3.Location = new System.Drawing.Point(26, 46);
|
||||
label3.Name = "label3";
|
||||
label3.Size = new System.Drawing.Size(105, 17);
|
||||
label3.TabIndex = 2;
|
||||
label3.Text = "View flip decider";
|
||||
//
|
||||
// viewFlipDeciderBox
|
||||
//
|
||||
this.viewFlipDeciderBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.viewFlipDeciderBox.FormattingEnabled = true;
|
||||
this.viewFlipDeciderBox.Location = new System.Drawing.Point(130, 17);
|
||||
this.viewFlipDeciderBox.Name = "viewFlipDeciderBox";
|
||||
this.viewFlipDeciderBox.Size = new System.Drawing.Size(375, 25);
|
||||
this.viewFlipDeciderBox.TabIndex = 3;
|
||||
viewFlipDeciderBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
viewFlipDeciderBox.FormattingEnabled = true;
|
||||
viewFlipDeciderBox.Location = new System.Drawing.Point(137, 43);
|
||||
viewFlipDeciderBox.Name = "viewFlipDeciderBox";
|
||||
viewFlipDeciderBox.Size = new System.Drawing.Size(502, 25);
|
||||
viewFlipDeciderBox.TabIndex = 3;
|
||||
//
|
||||
// mainTabControl
|
||||
//
|
||||
this.mainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.mainTabControl.Controls.Add(this.logEventsTab);
|
||||
this.mainTabControl.Controls.Add(this.bomTab);
|
||||
this.mainTabControl.Controls.Add(this.cutTemplatesTab);
|
||||
this.mainTabControl.Controls.Add(this.dwgDetailsTab);
|
||||
this.mainTabControl.Location = new System.Drawing.Point(15, 50);
|
||||
this.mainTabControl.Name = "mainTabControl";
|
||||
this.mainTabControl.Padding = new System.Drawing.Point(20, 5);
|
||||
this.mainTabControl.SelectedIndex = 0;
|
||||
this.mainTabControl.Size = new System.Drawing.Size(879, 594);
|
||||
this.mainTabControl.TabIndex = 12;
|
||||
mainTabControl.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
mainTabControl.Controls.Add(logEventsTab);
|
||||
mainTabControl.Controls.Add(bomTab);
|
||||
mainTabControl.Location = new System.Drawing.Point(15, 74);
|
||||
mainTabControl.Name = "mainTabControl";
|
||||
mainTabControl.Padding = new System.Drawing.Point(20, 5);
|
||||
mainTabControl.SelectedIndex = 0;
|
||||
mainTabControl.Size = new System.Drawing.Size(741, 586);
|
||||
mainTabControl.TabIndex = 12;
|
||||
//
|
||||
// logEventsTab
|
||||
//
|
||||
this.logEventsTab.Controls.Add(this.logEventsDataGrid);
|
||||
this.logEventsTab.Location = new System.Drawing.Point(4, 30);
|
||||
this.logEventsTab.Name = "logEventsTab";
|
||||
this.logEventsTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.logEventsTab.Size = new System.Drawing.Size(871, 560);
|
||||
this.logEventsTab.TabIndex = 0;
|
||||
this.logEventsTab.Text = "Log Events";
|
||||
this.logEventsTab.UseVisualStyleBackColor = true;
|
||||
logEventsTab.Controls.Add(logEventsDataGrid);
|
||||
logEventsTab.Location = new System.Drawing.Point(4, 30);
|
||||
logEventsTab.Name = "logEventsTab";
|
||||
logEventsTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
logEventsTab.Size = new System.Drawing.Size(733, 552);
|
||||
logEventsTab.TabIndex = 0;
|
||||
logEventsTab.Text = "Log Events";
|
||||
logEventsTab.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// logEventsDataGrid
|
||||
//
|
||||
this.logEventsDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.logEventsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.logEventsDataGrid.Location = new System.Drawing.Point(6, 6);
|
||||
this.logEventsDataGrid.Name = "logEventsDataGrid";
|
||||
this.logEventsDataGrid.Size = new System.Drawing.Size(859, 548);
|
||||
this.logEventsDataGrid.TabIndex = 0;
|
||||
logEventsDataGrid.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
logEventsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
logEventsDataGrid.GridColor = System.Drawing.Color.WhiteSmoke;
|
||||
logEventsDataGrid.Location = new System.Drawing.Point(6, 6);
|
||||
logEventsDataGrid.Name = "logEventsDataGrid";
|
||||
logEventsDataGrid.Size = new System.Drawing.Size(721, 540);
|
||||
logEventsDataGrid.TabIndex = 0;
|
||||
//
|
||||
// bomTab
|
||||
//
|
||||
this.bomTab.Controls.Add(this.bomDataGrid);
|
||||
this.bomTab.Location = new System.Drawing.Point(4, 30);
|
||||
this.bomTab.Name = "bomTab";
|
||||
this.bomTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.bomTab.Size = new System.Drawing.Size(871, 560);
|
||||
this.bomTab.TabIndex = 1;
|
||||
this.bomTab.Text = "Bill Of Materials";
|
||||
this.bomTab.UseVisualStyleBackColor = true;
|
||||
bomTab.Controls.Add(bomDataGrid);
|
||||
bomTab.Location = new System.Drawing.Point(4, 30);
|
||||
bomTab.Name = "bomTab";
|
||||
bomTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
bomTab.Size = new System.Drawing.Size(733, 552);
|
||||
bomTab.TabIndex = 1;
|
||||
bomTab.Text = "Bill Of Materials";
|
||||
bomTab.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// bomDataGrid
|
||||
//
|
||||
this.bomDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.bomDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.bomDataGrid.Location = new System.Drawing.Point(6, 6);
|
||||
this.bomDataGrid.Name = "bomDataGrid";
|
||||
this.bomDataGrid.Size = new System.Drawing.Size(859, 548);
|
||||
this.bomDataGrid.TabIndex = 1;
|
||||
bomDataGrid.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
bomDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
bomDataGrid.GridColor = System.Drawing.Color.WhiteSmoke;
|
||||
bomDataGrid.Location = new System.Drawing.Point(6, 6);
|
||||
bomDataGrid.Name = "bomDataGrid";
|
||||
bomDataGrid.Size = new System.Drawing.Size(721, 540);
|
||||
bomDataGrid.TabIndex = 1;
|
||||
//
|
||||
// cutTemplatesTab
|
||||
// equipmentBox
|
||||
//
|
||||
this.cutTemplatesTab.Controls.Add(this.cutTemplatesDataGrid);
|
||||
this.cutTemplatesTab.Location = new System.Drawing.Point(4, 30);
|
||||
this.cutTemplatesTab.Name = "cutTemplatesTab";
|
||||
this.cutTemplatesTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.cutTemplatesTab.Size = new System.Drawing.Size(871, 560);
|
||||
this.cutTemplatesTab.TabIndex = 3;
|
||||
this.cutTemplatesTab.Text = "Cut Templates";
|
||||
this.cutTemplatesTab.UseVisualStyleBackColor = true;
|
||||
equipmentBox.FormattingEnabled = true;
|
||||
equipmentBox.Location = new System.Drawing.Point(137, 12);
|
||||
equipmentBox.Name = "equipmentBox";
|
||||
equipmentBox.Size = new System.Drawing.Size(166, 25);
|
||||
equipmentBox.TabIndex = 13;
|
||||
//
|
||||
// cutTemplatesDataGrid
|
||||
// label1
|
||||
//
|
||||
this.cutTemplatesDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cutTemplatesDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.cutTemplatesDataGrid.Location = new System.Drawing.Point(6, 6);
|
||||
this.cutTemplatesDataGrid.Name = "cutTemplatesDataGrid";
|
||||
this.cutTemplatesDataGrid.Size = new System.Drawing.Size(859, 548);
|
||||
this.cutTemplatesDataGrid.TabIndex = 2;
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new System.Drawing.Point(61, 15);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new System.Drawing.Size(70, 17);
|
||||
label1.TabIndex = 2;
|
||||
label1.Text = "Equipment";
|
||||
//
|
||||
// dwgDetailsTab
|
||||
// label2
|
||||
//
|
||||
this.dwgDetailsTab.Controls.Add(this.drawingPdfViewer);
|
||||
this.dwgDetailsTab.Location = new System.Drawing.Point(4, 30);
|
||||
this.dwgDetailsTab.Name = "dwgDetailsTab";
|
||||
this.dwgDetailsTab.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.dwgDetailsTab.Size = new System.Drawing.Size(871, 560);
|
||||
this.dwgDetailsTab.TabIndex = 2;
|
||||
this.dwgDetailsTab.Text = "Drawing Details";
|
||||
this.dwgDetailsTab.UseVisualStyleBackColor = true;
|
||||
label2.AutoSize = true;
|
||||
label2.Location = new System.Drawing.Point(354, 15);
|
||||
label2.Name = "label2";
|
||||
label2.Size = new System.Drawing.Size(56, 17);
|
||||
label2.TabIndex = 2;
|
||||
label2.Text = "Drawing";
|
||||
//
|
||||
// drawingPdfViewer
|
||||
// drawingNoBox
|
||||
//
|
||||
this.drawingPdfViewer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.drawingPdfViewer.Enabled = true;
|
||||
this.drawingPdfViewer.Location = new System.Drawing.Point(6, 6);
|
||||
this.drawingPdfViewer.Name = "drawingPdfViewer";
|
||||
this.drawingPdfViewer.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("drawingPdfViewer.OcxState")));
|
||||
this.drawingPdfViewer.Size = new System.Drawing.Size(859, 548);
|
||||
this.drawingPdfViewer.TabIndex = 0;
|
||||
drawingNoBox.FormattingEnabled = true;
|
||||
drawingNoBox.Location = new System.Drawing.Point(416, 12);
|
||||
drawingNoBox.Name = "drawingNoBox";
|
||||
drawingNoBox.Size = new System.Drawing.Size(223, 25);
|
||||
drawingNoBox.TabIndex = 13;
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.ClientSize = new System.Drawing.Size(906, 656);
|
||||
this.Controls.Add(this.mainTabControl);
|
||||
this.Controls.Add(this.viewFlipDeciderBox);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.runButton);
|
||||
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";
|
||||
this.mainTabControl.ResumeLayout(false);
|
||||
this.logEventsTab.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.logEventsDataGrid)).EndInit();
|
||||
this.bomTab.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.bomDataGrid)).EndInit();
|
||||
this.cutTemplatesTab.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.cutTemplatesDataGrid)).EndInit();
|
||||
this.dwgDetailsTab.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.drawingPdfViewer)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
ClientSize = new System.Drawing.Size(768, 672);
|
||||
Controls.Add(drawingNoBox);
|
||||
Controls.Add(equipmentBox);
|
||||
Controls.Add(mainTabControl);
|
||||
Controls.Add(viewFlipDeciderBox);
|
||||
Controls.Add(label2);
|
||||
Controls.Add(label1);
|
||||
Controls.Add(label3);
|
||||
Controls.Add(runButton);
|
||||
Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0);
|
||||
Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
MaximizeBox = false;
|
||||
MinimumSize = new System.Drawing.Size(643, 355);
|
||||
Name = "MainForm";
|
||||
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
Text = "ExportDXF";
|
||||
mainTabControl.ResumeLayout(false);
|
||||
logEventsTab.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)logEventsDataGrid).EndInit();
|
||||
bomTab.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)bomDataGrid).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -224,12 +201,11 @@
|
||||
private System.Windows.Forms.TabControl mainTabControl;
|
||||
private System.Windows.Forms.TabPage logEventsTab;
|
||||
private System.Windows.Forms.TabPage bomTab;
|
||||
private System.Windows.Forms.TabPage dwgDetailsTab;
|
||||
private System.Windows.Forms.DataGridView logEventsDataGrid;
|
||||
private AxAcroPDFLib.AxAcroPDF drawingPdfViewer;
|
||||
private System.Windows.Forms.DataGridView bomDataGrid;
|
||||
private System.Windows.Forms.TabPage cutTemplatesTab;
|
||||
private System.Windows.Forms.DataGridView cutTemplatesDataGrid;
|
||||
private System.Windows.Forms.ComboBox equipmentBox;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.ComboBox drawingNoBox;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
using ExportDXF.Data;
|
||||
using ExportDXF.Extensions;
|
||||
using ExportDXF.Models;
|
||||
using ExportDXF.Services;
|
||||
using ExportDXF.ViewFlipDeciders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
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 readonly IFileExportService _fileExportService;
|
||||
private readonly Func<ExportDxfDbContext> _dbContextFactory;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private readonly BindingList<LogEvent> _logEvents;
|
||||
private readonly BindingList<BomItem> _bomItems;
|
||||
private readonly BindingList<CutFabApiClient.ApiCutTemplate> _cutTemplates;
|
||||
private readonly int _selectedDrawingId;
|
||||
private readonly string _selectedDrawingNumber;
|
||||
private List<DrawingInfo> _allDrawings;
|
||||
|
||||
public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService, ICutFabApiClient apiClient, int selectedDrawingId, string selectedDrawingNumber)
|
||||
public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService, IFileExportService fileExportService, Func<ExportDxfDbContext> dbContextFactory = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
_solidWorksService = solidWorksService ??
|
||||
throw new ArgumentNullException(nameof(solidWorksService));
|
||||
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
|
||||
_exportService = exportService ??
|
||||
throw new ArgumentNullException(nameof(exportService));
|
||||
_apiClient = apiClient ??
|
||||
throw new ArgumentNullException(nameof(apiClient));
|
||||
_selectedDrawingId = selectedDrawingId;
|
||||
_selectedDrawingNumber = selectedDrawingNumber ?? throw new ArgumentNullException(nameof(selectedDrawingNumber));
|
||||
_fileExportService = fileExportService ??
|
||||
throw new ArgumentNullException(nameof(fileExportService));
|
||||
_dbContextFactory = dbContextFactory ?? (() => new ExportDxfDbContext());
|
||||
_logEvents = new BindingList<LogEvent>();
|
||||
_bomItems = new BindingList<BomItem>();
|
||||
_cutTemplates = new BindingList<CutFabApiClient.ApiCutTemplate>();
|
||||
_allDrawings = new List<DrawingInfo>();
|
||||
InitializeViewFlipDeciders();
|
||||
InitializeLogEventsGrid();
|
||||
InitializeBomGrid();
|
||||
InitializeCutTemplatesGrid();
|
||||
InitializeDrawingDropdowns();
|
||||
}
|
||||
|
||||
~MainForm()
|
||||
{
|
||||
_cancellationTokenSource?.Dispose();
|
||||
@@ -49,12 +52,14 @@ namespace ExportDXF.Forms
|
||||
components?.Dispose();
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected override async void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
runButton.Enabled = false;
|
||||
await InitializeAsync();
|
||||
}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
@@ -62,87 +67,18 @@ namespace ExportDXF.Forms
|
||||
LogMessage("Connecting to SolidWorks, this may take a minute...");
|
||||
await _solidWorksService.ConnectAsync();
|
||||
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
|
||||
LogMessage("Ready", Color.Green);
|
||||
LogMessage($"Output folder: {_fileExportService.OutputFolder}");
|
||||
LogMessage("Ready");
|
||||
UpdateActiveDocumentDisplay();
|
||||
runButton.Enabled = true;
|
||||
|
||||
// Load the selected drawing's BOM items
|
||||
LogMessage($"Loading BOM items for drawing {_selectedDrawingNumber}...");
|
||||
await LoadBomItemsForDrawingAsync(_selectedDrawingId);
|
||||
|
||||
// Load cut templates
|
||||
await LoadCutTemplatesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"Failed to connect to SolidWorks: {ex.Message}", Color.Red);
|
||||
LogMessage($"Failed to connect to SolidWorks: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show("Failed to connect to SolidWorks.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Application.Exit();
|
||||
}
|
||||
}
|
||||
private async Task LoadBomItemsForDrawingAsync(int drawingId)
|
||||
{
|
||||
try
|
||||
{
|
||||
_bomItems.Clear();
|
||||
|
||||
var apiBomItems = await _apiClient.GetBomItemsForDrawingAsync(drawingId);
|
||||
|
||||
foreach (var apiItem in apiBomItems)
|
||||
{
|
||||
var bomItem = new BomItem
|
||||
{
|
||||
ID = apiItem.ID,
|
||||
ItemNo = apiItem.ItemNo ?? "",
|
||||
PartNo = apiItem.PartNo ?? "",
|
||||
SortOrder = apiItem.SortOrder,
|
||||
Qty = apiItem.Qty,
|
||||
TotalQty = apiItem.TotalQty,
|
||||
Description = apiItem.Description ?? "",
|
||||
PartName = apiItem.PartName ?? "",
|
||||
ConfigurationName = apiItem.ConfigurationName ?? "",
|
||||
Material = apiItem.Material ?? "",
|
||||
DrawingID = apiItem.DrawingID,
|
||||
CutTemplateID = apiItem.CutTemplateID,
|
||||
CutTemplateName = apiItem.CutTemplateName ?? "",
|
||||
Thickness = apiItem.Thickness,
|
||||
KFactor = apiItem.KFactor,
|
||||
DefaultBendRadius = apiItem.DefaultBendRadius
|
||||
};
|
||||
|
||||
_bomItems.Add(bomItem);
|
||||
}
|
||||
|
||||
LogMessage($"Loaded {apiBomItems.Count} BOM item(s)", Color.Green);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"Failed to load BOM items: {ex.Message}", Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadCutTemplatesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_cutTemplates.Clear();
|
||||
|
||||
LogMessage("Loading cut templates...");
|
||||
|
||||
var apiCutTemplates = await _apiClient.GetCutTemplatesAsync();
|
||||
|
||||
foreach (var template in apiCutTemplates)
|
||||
{
|
||||
_cutTemplates.Add(template);
|
||||
}
|
||||
|
||||
LogMessage($"Loaded {apiCutTemplates.Count} cut template(s)", Color.Green);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"Failed to load cut templates: {ex.Message}", Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeViewFlipDeciders()
|
||||
{
|
||||
@@ -163,6 +99,7 @@ namespace ExportDXF.Forms
|
||||
viewFlipDeciderBox.DataSource = items;
|
||||
viewFlipDeciderBox.DisplayMember = "Name";
|
||||
}
|
||||
|
||||
private void InitializeLogEventsGrid()
|
||||
{
|
||||
// Clear any existing columns first
|
||||
@@ -191,6 +128,13 @@ namespace ExportDXF.Forms
|
||||
Width = 70
|
||||
});
|
||||
|
||||
logEventsDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
DataPropertyName = nameof(LogEvent.Part),
|
||||
HeaderText = "File",
|
||||
Width = 180
|
||||
});
|
||||
|
||||
logEventsDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
DataPropertyName = nameof(LogEvent.Message),
|
||||
@@ -198,6 +142,9 @@ namespace ExportDXF.Forms
|
||||
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
|
||||
});
|
||||
|
||||
// Add row coloring based on log level
|
||||
logEventsDataGrid.CellFormatting += LogEventsDataGrid_CellFormatting;
|
||||
|
||||
// Set the data source AFTER adding columns
|
||||
logEventsDataGrid.DataSource = _logEvents;
|
||||
}
|
||||
@@ -264,84 +211,85 @@ namespace ExportDXF.Forms
|
||||
Width = 120
|
||||
});
|
||||
|
||||
bomDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
DataPropertyName = nameof(BomItem.CutTemplateName),
|
||||
HeaderText = "Cut Template",
|
||||
Width = 120
|
||||
});
|
||||
|
||||
// Set the data source AFTER adding columns
|
||||
bomDataGrid.DataSource = _bomItems;
|
||||
}
|
||||
|
||||
private void InitializeCutTemplatesGrid()
|
||||
private void InitializeDrawingDropdowns()
|
||||
{
|
||||
// Clear any existing columns first
|
||||
cutTemplatesDataGrid.Columns.Clear();
|
||||
|
||||
// Configure grid settings
|
||||
cutTemplatesDataGrid.AutoGenerateColumns = false;
|
||||
cutTemplatesDataGrid.AllowUserToAddRows = false;
|
||||
cutTemplatesDataGrid.AllowUserToDeleteRows = false;
|
||||
cutTemplatesDataGrid.ReadOnly = true;
|
||||
cutTemplatesDataGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
|
||||
// Add columns
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
try
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.Name),
|
||||
HeaderText = "Name",
|
||||
Width = 200
|
||||
});
|
||||
using (var db = _dbContextFactory())
|
||||
{
|
||||
// Get all drawing numbers from the database
|
||||
var drawingNumbers = db.ExportRecords
|
||||
.Select(r => r.DrawingNumber)
|
||||
.Where(d => !string.IsNullOrEmpty(d))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
// Parse into DrawingInfo objects
|
||||
_allDrawings = drawingNumbers
|
||||
.Select(DrawingInfo.Parse)
|
||||
.Where(d => d != null)
|
||||
.Distinct()
|
||||
.OrderBy(d => d.EquipmentNo)
|
||||
.ThenBy(d => d.DrawingNo)
|
||||
.ToList();
|
||||
|
||||
// Get distinct equipment numbers
|
||||
var equipmentNumbers = _allDrawings
|
||||
.Select(d => d.EquipmentNo)
|
||||
.Distinct()
|
||||
.OrderBy(e => e)
|
||||
.ToList();
|
||||
|
||||
// Populate equipment dropdown
|
||||
equipmentBox.Items.Clear();
|
||||
equipmentBox.Items.Add(""); // Empty option for "all"
|
||||
foreach (var eq in equipmentNumbers)
|
||||
{
|
||||
equipmentBox.Items.Add(eq);
|
||||
}
|
||||
|
||||
// Populate drawing dropdown with all drawings initially
|
||||
UpdateDrawingDropdown();
|
||||
|
||||
// Wire up event handler for equipment selection change
|
||||
equipmentBox.SelectedIndexChanged += EquipmentBox_SelectedIndexChanged;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.Material),
|
||||
HeaderText = "Material",
|
||||
Width = 120
|
||||
});
|
||||
// Database might not exist yet - that's OK
|
||||
System.Diagnostics.Debug.WriteLine($"Failed to load drawings from database: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
private void EquipmentBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateDrawingDropdown();
|
||||
}
|
||||
|
||||
private void UpdateDrawingDropdown()
|
||||
{
|
||||
var selectedEquipment = equipmentBox.SelectedItem?.ToString();
|
||||
|
||||
var filteredDrawings = string.IsNullOrEmpty(selectedEquipment)
|
||||
? _allDrawings
|
||||
: _allDrawings.Where(d => d.EquipmentNo == selectedEquipment).ToList();
|
||||
|
||||
drawingNoBox.Items.Clear();
|
||||
drawingNoBox.Items.Add(""); // Empty option
|
||||
foreach (var drawing in filteredDrawings)
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.Thickness),
|
||||
HeaderText = "Thickness",
|
||||
Width = 80,
|
||||
DefaultCellStyle = new DataGridViewCellStyle { Format = "0.##" }
|
||||
});
|
||||
drawingNoBox.Items.Add(drawing.DrawingNo);
|
||||
}
|
||||
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
if (drawingNoBox.Items.Count > 0)
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.KFactor),
|
||||
HeaderText = "K-Factor",
|
||||
Width = 80,
|
||||
DefaultCellStyle = new DataGridViewCellStyle { Format = "0.####" }
|
||||
});
|
||||
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.DefaultBendRadius),
|
||||
HeaderText = "Bend Radius",
|
||||
Width = 90,
|
||||
DefaultCellStyle = new DataGridViewCellStyle { Format = "0.##" }
|
||||
});
|
||||
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.Version),
|
||||
HeaderText = "Version",
|
||||
Width = 70
|
||||
});
|
||||
|
||||
cutTemplatesDataGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
DataPropertyName = nameof(CutFabApiClient.ApiCutTemplate.Description),
|
||||
HeaderText = "Description",
|
||||
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
|
||||
});
|
||||
|
||||
// Set the data source AFTER adding columns
|
||||
cutTemplatesDataGrid.DataSource = _cutTemplates;
|
||||
drawingNoBox.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private async void button1_Click(object sender, EventArgs e)
|
||||
@@ -355,6 +303,7 @@ namespace ExportDXF.Forms
|
||||
await StartExportAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task StartExportAsync()
|
||||
{
|
||||
try
|
||||
@@ -362,33 +311,47 @@ namespace ExportDXF.Forms
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
var token = _cancellationTokenSource.Token;
|
||||
UpdateUIForExportStart();
|
||||
|
||||
var activeDoc = _solidWorksService.GetActiveDocument();
|
||||
if (activeDoc == null)
|
||||
{
|
||||
LogMessage("No active document.", Color.Red);
|
||||
LogMessage("No active document.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse drawing number from active document title
|
||||
var drawingInfo = DrawingInfo.Parse(activeDoc.Title);
|
||||
var filePrefix = drawingInfo != null ? $"{drawingInfo.EquipmentNo} {drawingInfo.DrawingNo}" : activeDoc.Title;
|
||||
|
||||
var viewFlipDecider = GetSelectedViewFlipDecider();
|
||||
var exportContext = new ExportContext
|
||||
{
|
||||
ActiveDocument = activeDoc,
|
||||
ViewFlipDecider = viewFlipDecider,
|
||||
FilePrefix = _selectedDrawingNumber,
|
||||
EquipmentId = null, // Not needed for export
|
||||
FilePrefix = filePrefix,
|
||||
EquipmentId = null,
|
||||
CancellationToken = token,
|
||||
ProgressCallback = LogMessage
|
||||
ProgressCallback = (msg, level, file) => LogMessage(msg, level, file),
|
||||
BomItemCallback = AddBomItem
|
||||
};
|
||||
|
||||
// Clear previous BOM items
|
||||
_bomItems.Clear();
|
||||
|
||||
LogMessage($"Started at {DateTime.Now:t}");
|
||||
LogMessage($"Exporting to: {_fileExportService.OutputFolder}");
|
||||
|
||||
await Task.Run(() => _exportService.Export(exportContext), token);
|
||||
LogMessage("Done.", Color.Green);
|
||||
|
||||
LogMessage("Done.");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
LogMessage("Export canceled.", Color.Red);
|
||||
LogMessage("Export canceled.", LogLevel.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogMessage($"Export failed: {ex.Message}", Color.Red);
|
||||
LogMessage($"Export failed: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Export failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
@@ -398,27 +361,32 @@ namespace ExportDXF.Forms
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelExport()
|
||||
{
|
||||
runButton.Enabled = false;
|
||||
_cancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
private IViewFlipDecider GetSelectedViewFlipDecider()
|
||||
{
|
||||
var item = viewFlipDeciderBox.SelectedItem as ViewFlipDeciderComboboxItem;
|
||||
return item?.ViewFlipDecider;
|
||||
}
|
||||
|
||||
private void UpdateUIForExportStart()
|
||||
{
|
||||
viewFlipDeciderBox.Enabled = false;
|
||||
runButton.Image = Properties.Resources.stop_alt;
|
||||
runButton.Text = "Stop";
|
||||
}
|
||||
|
||||
private void UpdateUIForExportComplete()
|
||||
{
|
||||
viewFlipDeciderBox.Enabled = true;
|
||||
runButton.Image = Properties.Resources.play;
|
||||
runButton.Text = "Start";
|
||||
runButton.Enabled = true;
|
||||
}
|
||||
|
||||
private void OnActiveDocumentChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
@@ -428,20 +396,17 @@ namespace ExportDXF.Forms
|
||||
}
|
||||
UpdateActiveDocumentDisplay();
|
||||
}
|
||||
|
||||
private void UpdateActiveDocumentDisplay()
|
||||
{
|
||||
var activeDoc = _solidWorksService.GetActiveDocument();
|
||||
var docTitle = activeDoc?.Title ?? "No Document Open";
|
||||
this.Text = $"ExportDXF - {docTitle}";
|
||||
}
|
||||
private void LogMessage(string message, Color? color = null)
|
||||
{
|
||||
var level = color.HasValue && color.Value == Color.Red ? LogLevel.Error :
|
||||
color.HasValue && color.Value == Color.Green ? LogLevel.Info :
|
||||
color.HasValue && color.Value == Color.DarkBlue ? LogLevel.Warning :
|
||||
LogLevel.Info;
|
||||
|
||||
AddLogEvent(level, LogAction.Start, message);
|
||||
private void LogMessage(string message, LogLevel level = LogLevel.Info, string file = null)
|
||||
{
|
||||
AddLogEvent(level, LogAction.Start, message, part: file);
|
||||
}
|
||||
|
||||
private void AddLogEvent(LogLevel level, LogAction action, string message, string equipment = "", string drawing = "", string part = "", string target = "", string result = "OK", int durationMs = 0)
|
||||
@@ -474,5 +439,40 @@ namespace ExportDXF.Forms
|
||||
logEventsDataGrid.FirstDisplayedScrollingRowIndex = logEventsDataGrid.Rows.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddBomItem(BomItem item)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => AddBomItem(item)));
|
||||
return;
|
||||
}
|
||||
_bomItems.Add(item);
|
||||
}
|
||||
|
||||
private void LogEventsDataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
||||
{
|
||||
if (e.RowIndex < 0 || e.RowIndex >= _logEvents.Count)
|
||||
return;
|
||||
|
||||
var logEvent = _logEvents[e.RowIndex];
|
||||
var row = logEventsDataGrid.Rows[e.RowIndex];
|
||||
|
||||
switch (logEvent.Level)
|
||||
{
|
||||
case LogLevel.Warning:
|
||||
row.DefaultCellStyle.BackColor = Color.LightGoldenrodYellow;
|
||||
row.DefaultCellStyle.ForeColor = Color.DarkOrange;
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
row.DefaultCellStyle.BackColor = Color.MistyRose;
|
||||
row.DefaultCellStyle.ForeColor = Color.DarkRed;
|
||||
break;
|
||||
default:
|
||||
row.DefaultCellStyle.BackColor = Color.White;
|
||||
row.DefaultCellStyle.ForeColor = Color.Black;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
@@ -26,36 +26,36 @@
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
@@ -117,12 +117,4 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="drawingPdfViewer.OcxState" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACFTeXN0
|
||||
ZW0uV2luZG93cy5Gb3Jtcy5BeEhvc3QrU3RhdGUBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAIQAAAAIB
|
||||
AAAAAQAAAAAAAAAAAAAAAAwAAAAADgAASGsAANA3AAAL
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -14,14 +14,29 @@ namespace ExportDXF.Models
|
||||
public string PartName { get; set; } = "";
|
||||
public string ConfigurationName { get; set; } = "";
|
||||
public string Material { get; set; } = "";
|
||||
public int DrawingID { get; set; }
|
||||
public int? CutTemplateID { get; set; }
|
||||
public string CutTemplateName { get; set; } = "";
|
||||
public string DxfFilePath { get; set; } = "";
|
||||
|
||||
// Sheet metal properties
|
||||
private double? _thickness;
|
||||
public double? Thickness
|
||||
{
|
||||
get => _thickness;
|
||||
set => _thickness = value.HasValue ? Math.Round(value.Value, 8) : null;
|
||||
}
|
||||
|
||||
// Sheet metal properties from CutTemplate
|
||||
public double? Thickness { get; set; }
|
||||
public double? KFactor { get; set; }
|
||||
public double? DefaultBendRadius { get; set; }
|
||||
|
||||
private double? _defaultBendRadius;
|
||||
public double? DefaultBendRadius
|
||||
{
|
||||
get => _defaultBendRadius;
|
||||
set => _defaultBendRadius = value.HasValue ? Math.Round(value.Value, 8) : null;
|
||||
}
|
||||
|
||||
// EF Core relationship to ExportRecord
|
||||
public int ExportRecordId { get; set; }
|
||||
public virtual ExportRecord ExportRecord { get; set; }
|
||||
}
|
||||
|
||||
public struct Size
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using ExportDXF.ViewFlipDeciders;
|
||||
using ExportDXF.Models;
|
||||
using ExportDXF.ViewFlipDeciders;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using SolidWorks.Interop.swconst;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
@@ -44,12 +44,18 @@ namespace ExportDXF.Services
|
||||
|
||||
/// <summary>
|
||||
/// Callback for reporting progress and status messages.
|
||||
/// Parameters: message, level, file (optional)
|
||||
/// </summary>
|
||||
public Action<string, Color?> ProgressCallback { get; set; }
|
||||
public Action<string, LogLevel, string> ProgressCallback { get; set; }
|
||||
|
||||
public void LogProgress(string message, Color? color = null)
|
||||
/// <summary>
|
||||
/// Callback for adding BOM items to the UI.
|
||||
/// </summary>
|
||||
public Action<BomItem> BomItemCallback { get; set; }
|
||||
|
||||
public void LogProgress(string message, LogLevel level = LogLevel.Info, string file = null)
|
||||
{
|
||||
ProgressCallback?.Invoke(message, color);
|
||||
ProgressCallback?.Invoke(message, level, file);
|
||||
}
|
||||
|
||||
public SldWorks SolidWorksApp { get; set; }
|
||||
@@ -90,7 +96,7 @@ namespace ExportDXF.Services
|
||||
|
||||
if (SolidWorksApp == null)
|
||||
{
|
||||
ProgressCallback?.Invoke("Warning: Cannot cleanup template drawing - SolidWorks app not available", Color.DarkBlue);
|
||||
ProgressCallback?.Invoke("Warning: Cannot cleanup template drawing - SolidWorks app not available", LogLevel.Warning, null);
|
||||
TemplateDrawing = null;
|
||||
return;
|
||||
}
|
||||
@@ -104,7 +110,7 @@ namespace ExportDXF.Services
|
||||
{
|
||||
// Close the document without saving
|
||||
SolidWorksApp.CloseDoc(title);
|
||||
ProgressCallback?.Invoke("Closed template drawing", null);
|
||||
ProgressCallback?.Invoke("Closed template drawing", LogLevel.Info, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +119,7 @@ namespace ExportDXF.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ProgressCallback?.Invoke($"Failed to close template drawing: {ex.Message}", Color.Red);
|
||||
ProgressCallback?.Invoke($"Failed to close template drawing: {ex.Message}", LogLevel.Error, null);
|
||||
|
||||
// Still clear the reference to prevent further issues
|
||||
TemplateDrawing = null;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using ExportDXF.Forms;
|
||||
using ExportDXF.Forms;
|
||||
using ExportDXF.Services;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ExportDXF
|
||||
@@ -18,78 +17,40 @@ namespace ExportDXF
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
// Simple DI setup - could use a DI container like Microsoft.Extensions.DependencyInjection
|
||||
var container = new ServiceContainer();
|
||||
|
||||
// Show drawing selection dialog first
|
||||
var drawingSelectionForm = container.ResolveDrawingSelectionAsync().GetAwaiter().GetResult();
|
||||
var result = drawingSelectionForm.ShowDialog();
|
||||
|
||||
if (result == DialogResult.OK && drawingSelectionForm.SelectedDrawingId.HasValue)
|
||||
{
|
||||
// User selected a drawing, proceed to main form
|
||||
var mainForm = container.Resolve<MainForm>(
|
||||
drawingSelectionForm.SelectedDrawingId.Value,
|
||||
drawingSelectionForm.SelectedDrawingNumber);
|
||||
|
||||
Application.Run(mainForm);
|
||||
}
|
||||
// If user cancelled, just exit
|
||||
var mainForm = container.ResolveMainForm();
|
||||
Application.Run(mainForm);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple dependency injection container.
|
||||
/// For production, consider using Microsoft.Extensions.DependencyInjection or similar.
|
||||
/// </summary>
|
||||
public class ServiceContainer
|
||||
{
|
||||
private readonly string _baseUrl;
|
||||
private readonly CutFabApiClient _apiClient;
|
||||
private readonly string _outputFolder;
|
||||
|
||||
public ServiceContainer()
|
||||
{
|
||||
_baseUrl = ConfigurationManager.AppSettings["CutFab.ApiBaseUrl"] ?? "http://localhost:7027";
|
||||
_apiClient = new CutFabApiClient(_baseUrl);
|
||||
_outputFolder = ConfigurationManager.AppSettings["ExportOutputFolder"] ?? @"C:\ExportDXF\Output";
|
||||
}
|
||||
|
||||
public async Task<DrawingSelectionForm> ResolveDrawingSelectionAsync()
|
||||
public MainForm ResolveMainForm()
|
||||
{
|
||||
// Connect to SolidWorks first
|
||||
var solidWorksService = new SolidWorksService();
|
||||
try
|
||||
{
|
||||
await solidWorksService.ConnectAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Windows.Forms.MessageBox.Show(
|
||||
$"Warning: Could not connect to SolidWorks: {ex.Message}\n\nYou can still select a drawing, but the active document will not be displayed.",
|
||||
"SolidWorks Connection Warning",
|
||||
System.Windows.Forms.MessageBoxButtons.OK,
|
||||
System.Windows.Forms.MessageBoxIcon.Warning);
|
||||
}
|
||||
|
||||
return new DrawingSelectionForm(_apiClient, solidWorksService);
|
||||
}
|
||||
|
||||
public MainForm Resolve<T>(int selectedDrawingId, string selectedDrawingNumber) where T : MainForm
|
||||
{
|
||||
// Create the dependency tree
|
||||
var solidWorksService = new SolidWorksService();
|
||||
|
||||
var bomExtractor = new BomExtractor();
|
||||
var partExporter = new PartExporter();
|
||||
var drawingExporter = new DrawingExporter();
|
||||
var fileExportService = new FileExportService(_outputFolder);
|
||||
|
||||
var exportService = new DxfExportService(
|
||||
solidWorksService,
|
||||
bomExtractor,
|
||||
partExporter,
|
||||
drawingExporter,
|
||||
_apiClient);
|
||||
fileExportService);
|
||||
|
||||
return new MainForm(solidWorksService, exportService, _apiClient, selectedDrawingId, selectedDrawingNumber);
|
||||
return new MainForm(solidWorksService, exportService, fileExportService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using ExportDXF.Extensions;
|
||||
using ExportDXF.ItemExtractors;
|
||||
using ExportDXF.Models;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace ExportDXF.Services
|
||||
{
|
||||
@@ -16,14 +16,14 @@ namespace ExportDXF.Services
|
||||
/// Extracts items from all BOM tables in a drawing document.
|
||||
/// </summary>
|
||||
/// <param name="drawing">The drawing document containing BOM tables.</param>
|
||||
/// <param name="progressCallback">Optional callback for progress updates.</param>
|
||||
/// <param name="progressCallback">Optional callback for progress updates (message, level, file).</param>
|
||||
/// <returns>A list of extracted items.</returns>
|
||||
List<Item> ExtractFromDrawing(DrawingDoc drawing, Action<string, Color?> progressCallback);
|
||||
List<Item> ExtractFromDrawing(DrawingDoc drawing, Action<string, LogLevel, string> progressCallback);
|
||||
}
|
||||
|
||||
public class BomExtractor : IBomExtractor
|
||||
{
|
||||
public List<Item> ExtractFromDrawing(DrawingDoc drawing, Action<string, Color?> progressCallback)
|
||||
public List<Item> ExtractFromDrawing(DrawingDoc drawing, Action<string, LogLevel, string> progressCallback)
|
||||
{
|
||||
if (drawing == null)
|
||||
throw new ArgumentNullException(nameof(drawing));
|
||||
@@ -32,11 +32,11 @@ namespace ExportDXF.Services
|
||||
|
||||
if (bomTables.Count == 0)
|
||||
{
|
||||
progressCallback?.Invoke("Error: Bill of materials not found.", Color.Red);
|
||||
progressCallback?.Invoke("Error: Bill of materials not found.", LogLevel.Error, null);
|
||||
return new List<Item>();
|
||||
}
|
||||
|
||||
progressCallback?.Invoke($"Found {bomTables.Count} BOM table(s)", null);
|
||||
progressCallback?.Invoke($"Found {bomTables.Count} BOM table(s)", LogLevel.Info, null);
|
||||
|
||||
var allItems = new List<Item>();
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace ExportDXF.Services
|
||||
SkipHiddenRows = true
|
||||
};
|
||||
|
||||
progressCallback?.Invoke($"Fetching components from {bom.BomFeature.Name}", null);
|
||||
progressCallback?.Invoke($"Fetching components from {bom.BomFeature.Name}", LogLevel.Info, null);
|
||||
|
||||
var items = extractor.GetItems();
|
||||
allItems.AddRange(items);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
progressCallback?.Invoke($"Failed to extract from {bom.BomFeature.Name}: {ex.Message}", Color.Red);
|
||||
progressCallback?.Invoke($"Failed to extract: {ex.Message}", LogLevel.Error, bom.BomFeature.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,468 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Script.Serialization;
|
||||
using static ExportDXF.Services.CutFabApiClient;
|
||||
|
||||
namespace ExportDXF.Services
|
||||
{
|
||||
public interface ICutFabApiClient
|
||||
{
|
||||
string BaseUrl { get; }
|
||||
Task<int?> ResolveDrawingIdAsync(string drawingNumber);
|
||||
Task<int?> CreateDrawingAsync(int equipmentId, string drawingNumber);
|
||||
Task<CutFabApiClient.ApiResponse<int?>> CreateDrawingWithInfoAsync(int equipmentId, string drawingNumber);
|
||||
Task<bool> UploadDrawingPdfAsync(string drawingNumber, string pdfPath, string uploadedBy = null, string notes = null);
|
||||
Task<bool> UploadDxfZipAsync(
|
||||
int drawingId,
|
||||
string zipPath,
|
||||
double? thickness = null,
|
||||
double? kfactor = null,
|
||||
double? defaultBendRadius = null,
|
||||
string material = null);
|
||||
Task<int?> CreateBomItemAsync(object upsertBomItemDto);
|
||||
Task<bool> AutoLinkTemplatesAsync(int drawingId);
|
||||
Task<List<ApiEquipment>> GetEquipmentAsync();
|
||||
Task<List<ApiDrawingSummary>> GetDrawingsForEquipmentAsync(int equipmentId);
|
||||
Task<List<ApiBomItem>> GetBomItemsForDrawingAsync(int drawingId);
|
||||
Task<List<ApiCutTemplate>> GetCutTemplatesAsync();
|
||||
}
|
||||
|
||||
public class CutFabApiClient : ICutFabApiClient, IDisposable
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly string _baseUrl;
|
||||
public string BaseUrl => _baseUrl;
|
||||
public class ApiResponse<T>
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int StatusCode { get; set; }
|
||||
public T Data { get; set; }
|
||||
public string RawBody { get; set; }
|
||||
public string Error { get; set; }
|
||||
}
|
||||
|
||||
public CutFabApiClient(string baseUrl)
|
||||
{
|
||||
_baseUrl = (baseUrl ?? string.Empty).TrimEnd('/');
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_baseUrl))
|
||||
{
|
||||
// Default to deployed API port from deployment script
|
||||
_baseUrl = "http://localhost:7027";
|
||||
}
|
||||
|
||||
_http = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(100)
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<int?> ResolveDrawingIdAsync(string drawingNumber)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = $"{_baseUrl}/api/Drawings/resolve?drawingNumber={Uri.EscapeDataString(drawingNumber)}";
|
||||
var resp = await _http.GetAsync(url).ConfigureAwait(false);
|
||||
if (!resp.IsSuccessStatusCode) return null;
|
||||
var json = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
|
||||
if (dict != null && dict.ContainsKey("ID"))
|
||||
{
|
||||
var idObj = dict["ID"]; // serializer returns int or double depending
|
||||
if (idObj is int i) return i;
|
||||
if (idObj is double d) return (int)d;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int?> CreateDrawingAsync(int equipmentId, string drawingNumber)
|
||||
{
|
||||
var payload = new { DrawingNumber = drawingNumber, Description = (string)null, Qty = 1, EquipmentID = equipmentId };
|
||||
var json = new JavaScriptSerializer().Serialize(payload);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/api/Drawings", content).ConfigureAwait(false);
|
||||
if (!resp.IsSuccessStatusCode) return null;
|
||||
var body = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(body);
|
||||
if (dict != null && dict.ContainsKey("ID"))
|
||||
{
|
||||
var idObj = dict["ID"]; if (idObj is int i) return i; if (idObj is double d) return (int)d;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<ApiResponse<int?>> CreateDrawingWithInfoAsync(int equipmentId, string drawingNumber)
|
||||
{
|
||||
var result = new ApiResponse<int?> { Success = false, StatusCode = 0, Data = null, RawBody = null, Error = null };
|
||||
try
|
||||
{
|
||||
var payload = new { DrawingNumber = drawingNumber, Description = (string)null, Qty = 1, EquipmentID = equipmentId };
|
||||
var json = new JavaScriptSerializer().Serialize(payload);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/api/Drawings", content).ConfigureAwait(false);
|
||||
result.StatusCode = (int)resp.StatusCode;
|
||||
result.Success = resp.IsSuccessStatusCode;
|
||||
var body = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
result.RawBody = body;
|
||||
if (!resp.IsSuccessStatusCode)
|
||||
{
|
||||
result.Error = "HTTP " + ((int)resp.StatusCode) + " " + resp.ReasonPhrase;
|
||||
return result;
|
||||
}
|
||||
try
|
||||
{
|
||||
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(body);
|
||||
if (dict != null)
|
||||
{
|
||||
object v;
|
||||
if (TryGetCI(dict, new[] { "ID", "id" }, out v))
|
||||
{
|
||||
if (v is int i) { result.Data = i; return result; }
|
||||
if (v is double d) { result.Data = (int)d; return result; }
|
||||
int parsed; if (int.TryParse(Convert.ToString(v), out parsed)) { result.Data = parsed; return result; }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Error = ex.Message;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Error = ex.Message;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UploadDrawingPdfAsync(string drawingNumber, string pdfPath, string uploadedBy = null, string notes = null)
|
||||
{
|
||||
if (!File.Exists(pdfPath)) return false;
|
||||
using (var form = new MultipartFormDataContent())
|
||||
{
|
||||
form.Add(new StringContent(drawingNumber ?? string.Empty), "drawingNumber");
|
||||
if (!string.IsNullOrWhiteSpace(uploadedBy)) form.Add(new StringContent(uploadedBy), "uploadedBy");
|
||||
if (!string.IsNullOrWhiteSpace(notes)) form.Add(new StringContent(notes), "notes");
|
||||
|
||||
var fileContent = new StreamContent(File.OpenRead(pdfPath));
|
||||
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");
|
||||
var fileName = Path.GetFileName(pdfPath);
|
||||
form.Add(fileContent, "file", fileName);
|
||||
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/api/DrawingRevisions/upload", form).ConfigureAwait(false);
|
||||
return resp.IsSuccessStatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UploadDxfZipAsync(int drawingId, string zipPath, double? thickness = null, double? kfactor = null, double? defaultBendRadius = null, string material = null)
|
||||
{
|
||||
if (!File.Exists(zipPath)) return false;
|
||||
using (var form = new MultipartFormDataContent())
|
||||
{
|
||||
var fileContent = new StreamContent(File.OpenRead(zipPath));
|
||||
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/zip");
|
||||
var fileName = Path.GetFileName(zipPath);
|
||||
form.Add(fileContent, "file", fileName);
|
||||
|
||||
// Add thickness and kfactor if provided
|
||||
if (thickness.HasValue)
|
||||
form.Add(new StringContent(thickness.Value.ToString(System.Globalization.CultureInfo.InvariantCulture)), "thickness");
|
||||
if (kfactor.HasValue)
|
||||
form.Add(new StringContent(kfactor.Value.ToString(System.Globalization.CultureInfo.InvariantCulture)), "kfactor");
|
||||
// Add default bend radius and material if provided
|
||||
if (defaultBendRadius.HasValue)
|
||||
form.Add(new StringContent(defaultBendRadius.Value.ToString(System.Globalization.CultureInfo.InvariantCulture)), "defaultBendRadius");
|
||||
if (!string.IsNullOrWhiteSpace(material))
|
||||
form.Add(new StringContent(material), "material");
|
||||
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/api/Drawings/{drawingId}/upload-dxf-templates", form).ConfigureAwait(false);
|
||||
return resp.IsSuccessStatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int?> CreateBomItemAsync(object upsertBomItemDto)
|
||||
{
|
||||
var json = new JavaScriptSerializer().Serialize(upsertBomItemDto);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var resp = await _http.PostAsync($"{_baseUrl}/api/BomItems", content).ConfigureAwait(false);
|
||||
if (!resp.IsSuccessStatusCode) return null;
|
||||
var body = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(body);
|
||||
if (dict != null)
|
||||
{
|
||||
object v;
|
||||
if (TryGetCI(dict, new[] { "ID", "id" }, out v))
|
||||
{
|
||||
if (v is int i) return i;
|
||||
if (v is double d) return (int)d;
|
||||
int parsed; if (int.TryParse(Convert.ToString(v), out parsed)) return parsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
// Successful HTTP with empty/minimal body: treat as success
|
||||
return 0;
|
||||
}
|
||||
|
||||
public async Task<bool> AutoLinkTemplatesAsync(int drawingId)
|
||||
{
|
||||
var url = $"{_baseUrl}/api/Drawings/{drawingId}/auto-link-templates";
|
||||
var resp = await _http.PostAsync(url, new ByteArrayContent(new byte[0])).ConfigureAwait(false);
|
||||
return resp.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
public async Task<List<ApiBomItem>> GetBomItemsForDrawingAsync(int drawingId)
|
||||
{
|
||||
var url = $"{_baseUrl}/api/BomItems/drawing/{drawingId}";
|
||||
var resp = await _http.GetAsync(url).ConfigureAwait(false);
|
||||
if (!resp.IsSuccessStatusCode) return new List<ApiBomItem>();
|
||||
var json = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var serializer = new JavaScriptSerializer();
|
||||
var raw = serializer.DeserializeObject(json);
|
||||
var result = new List<ApiBomItem>();
|
||||
|
||||
if (raw is System.Collections.IEnumerable enumerable && !(raw is string))
|
||||
{
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
var dict = item as Dictionary<string, object>;
|
||||
if (dict == null) continue;
|
||||
var bomItem = new ApiBomItem();
|
||||
object v;
|
||||
if (TryGetCI(dict, new[] { "ID", "id" }, out v)) bomItem.ID = ToInt(v);
|
||||
if (TryGetCI(dict, new[] { "ItemNo", "itemNo" }, out v)) bomItem.ItemNo = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "PartNo", "partNo" }, out v)) bomItem.PartNo = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "SortOrder", "sortOrder" }, out v)) bomItem.SortOrder = ToInt(v);
|
||||
if (TryGetCI(dict, new[] { "Qty", "qty" }, out v)) bomItem.Qty = v != null ? (int?)ToInt(v) : null;
|
||||
if (TryGetCI(dict, new[] { "TotalQty", "totalQty" }, out v)) bomItem.TotalQty = v != null ? (int?)ToInt(v) : null;
|
||||
if (TryGetCI(dict, new[] { "Description", "description" }, out v)) bomItem.Description = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "PartName", "partName" }, out v)) bomItem.PartName = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "ConfigurationName", "configurationName" }, out v)) bomItem.ConfigurationName = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "Material", "material" }, out v)) bomItem.Material = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "DrawingID", "drawingID", "drawingId" }, out v)) bomItem.DrawingID = ToInt(v);
|
||||
if (TryGetCI(dict, new[] { "CutTemplateID", "cutTemplateID", "cutTemplateId" }, out v)) bomItem.CutTemplateID = v != null ? (int?)ToInt(v) : null;
|
||||
|
||||
// Try to get CutTemplate info if available
|
||||
if (TryGetCI(dict, new[] { "CutTemplate", "cutTemplate" }, out v))
|
||||
{
|
||||
var templateDict = v as Dictionary<string, object>;
|
||||
if (templateDict != null)
|
||||
{
|
||||
object tv;
|
||||
if (TryGetCI(templateDict, new[] { "Name", "name" }, out tv)) bomItem.CutTemplateName = tv?.ToString();
|
||||
if (TryGetCI(templateDict, new[] { "Thickness", "thickness" }, out tv)) bomItem.Thickness = ToDouble(tv);
|
||||
if (TryGetCI(templateDict, new[] { "KFactor", "kFactor", "kfactor" }, out tv)) bomItem.KFactor = ToDouble(tv);
|
||||
if (TryGetCI(templateDict, new[] { "DefaultBendRadius", "defaultBendRadius" }, out tv)) bomItem.DefaultBendRadius = ToDouble(tv);
|
||||
}
|
||||
}
|
||||
|
||||
result.Add(bomItem);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<ApiCutTemplate>> GetCutTemplatesAsync()
|
||||
{
|
||||
var url = $"{_baseUrl}/api/CutTemplates";
|
||||
var resp = await _http.GetAsync(url).ConfigureAwait(false);
|
||||
if (!resp.IsSuccessStatusCode) return new List<ApiCutTemplate>();
|
||||
var json = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var serializer = new JavaScriptSerializer();
|
||||
var raw = serializer.DeserializeObject(json);
|
||||
var result = new List<ApiCutTemplate>();
|
||||
|
||||
if (raw is System.Collections.IEnumerable enumerable && !(raw is string))
|
||||
{
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
var dict = item as Dictionary<string, object>;
|
||||
if (dict == null) continue;
|
||||
var template = new ApiCutTemplate();
|
||||
object v;
|
||||
if (TryGetCI(dict, new[] { "ID", "id" }, out v)) template.ID = ToInt(v);
|
||||
if (TryGetCI(dict, new[] { "Name", "name" }, out v)) template.Name = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "FilePath", "filePath" }, out v)) template.FilePath = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "Description", "description" }, out v)) template.Description = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "Material", "material" }, out v)) template.Material = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "Thickness", "thickness" }, out v)) template.Thickness = ToDouble(v);
|
||||
if (TryGetCI(dict, new[] { "KFactor", "kFactor", "kfactor" }, out v)) template.KFactor = ToDouble(v);
|
||||
if (TryGetCI(dict, new[] { "DefaultBendRadius", "defaultBendRadius" }, out v)) template.DefaultBendRadius = ToDouble(v);
|
||||
if (TryGetCI(dict, new[] { "Version", "version" }, out v)) template.Version = ToInt(v);
|
||||
result.Add(template);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_http?.Dispose();
|
||||
}
|
||||
|
||||
// Lightweight DTOs for UI binding
|
||||
public class ApiEquipment
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string EquipmentNumber { get; set; }
|
||||
public string Description { get; set; }
|
||||
public override string ToString() => EquipmentNumber ?? base.ToString();
|
||||
}
|
||||
|
||||
public class ApiDrawingSummary
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string DrawingNumber { get; set; }
|
||||
public string Description { get; set; }
|
||||
public override string ToString() => DrawingNumber ?? base.ToString();
|
||||
}
|
||||
|
||||
public class ApiBomItem
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string ItemNo { get; set; }
|
||||
public string PartNo { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public int? Qty { get; set; }
|
||||
public int? TotalQty { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string PartName { get; set; }
|
||||
public string ConfigurationName { get; set; }
|
||||
public string Material { get; set; }
|
||||
public int DrawingID { get; set; }
|
||||
public int? CutTemplateID { get; set; }
|
||||
public string CutTemplateName { get; set; }
|
||||
public double? Thickness { get; set; }
|
||||
public double? KFactor { get; set; }
|
||||
public double? DefaultBendRadius { get; set; }
|
||||
}
|
||||
|
||||
public class ApiCutTemplate
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Material { get; set; }
|
||||
public double? Thickness { get; set; }
|
||||
public double? KFactor { get; set; }
|
||||
public double? DefaultBendRadius { get; set; }
|
||||
public int Version { get; set; }
|
||||
}
|
||||
|
||||
public async Task<List<ApiEquipment>> GetEquipmentAsync()
|
||||
{
|
||||
var url = $"{_baseUrl}/api/Equipment";
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
var resp = await _http.SendAsync(req).ConfigureAwait(false);
|
||||
resp.EnsureSuccessStatusCode();
|
||||
var json = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
var serializer = new JavaScriptSerializer();
|
||||
var raw = serializer.DeserializeObject(json);
|
||||
var result = new List<ApiEquipment>();
|
||||
|
||||
if (raw is System.Collections.IEnumerable enumerable && !(raw is string))
|
||||
{
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
var dict = item as Dictionary<string, object>;
|
||||
if (dict == null) continue;
|
||||
var eq = new ApiEquipment();
|
||||
object v;
|
||||
if (TryGetCI(dict, new[] { "ID", "id" }, out v)) eq.ID = ToInt(v);
|
||||
if (TryGetCI(dict, new[] { "EquipmentNumber", "equipmentNumber", "equipmentNo" }, out v)) eq.EquipmentNumber = v?.ToString();
|
||||
if (TryGetCI(dict, new[] { "Description", "description" }, out v)) eq.Description = v?.ToString();
|
||||
result.Add(eq);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<ApiDrawingSummary>> GetDrawingsForEquipmentAsync(int equipmentId)
|
||||
{
|
||||
var url = $"{_baseUrl}/api/Equipment/{equipmentId}";
|
||||
var resp = await _http.GetAsync(url).ConfigureAwait(false);
|
||||
if (!resp.IsSuccessStatusCode) return new List<ApiDrawingSummary>();
|
||||
var json = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var serializer = new JavaScriptSerializer();
|
||||
var root = serializer.DeserializeObject(json) as Dictionary<string, object>;
|
||||
var results = new List<ApiDrawingSummary>();
|
||||
if (root != null)
|
||||
{
|
||||
object dval;
|
||||
if (!TryGetCI(root, new[] { "Drawings", "drawings" }, out dval)) return results;
|
||||
if (dval is System.Collections.IEnumerable arr && !(dval is string))
|
||||
{
|
||||
foreach (var item in arr)
|
||||
{
|
||||
var d = item as Dictionary<string, object>;
|
||||
if (d == null) continue;
|
||||
var summary = new ApiDrawingSummary();
|
||||
object v;
|
||||
if (TryGetCI(d, new[] { "ID", "id" }, out v)) summary.ID = ToInt(v);
|
||||
if (TryGetCI(d, new[] { "DrawingNumber", "drawingNumber" }, out v)) summary.DrawingNumber = v?.ToString();
|
||||
if (TryGetCI(d, new[] { "Description", "description" }, out v)) summary.Description = v?.ToString();
|
||||
results.Add(summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static bool TryGetCI(Dictionary<string, object> dict, IEnumerable<string> keys, out object value)
|
||||
{
|
||||
foreach (var k in keys)
|
||||
{
|
||||
if (dict.ContainsKey(k)) { value = dict[k]; return true; }
|
||||
foreach (var dk in dict.Keys)
|
||||
{
|
||||
if (string.Equals(dk, k, StringComparison.OrdinalIgnoreCase)) { value = dict[dk]; return true; }
|
||||
}
|
||||
}
|
||||
value = null; return false;
|
||||
}
|
||||
|
||||
private static int ToInt(object v)
|
||||
{
|
||||
if (v == null) return 0;
|
||||
if (v is int i) return i;
|
||||
if (v is long l) return (int)l;
|
||||
if (v is double d) return (int)d;
|
||||
int parsed; if (int.TryParse(v.ToString(), out parsed)) return parsed; return 0;
|
||||
}
|
||||
|
||||
private static double? ToDouble(object v)
|
||||
{
|
||||
if (v == null) return null;
|
||||
if (v is double d) return d;
|
||||
if (v is int i) return (double)i;
|
||||
if (v is long l) return (double)l;
|
||||
if (v is float f) return (double)f;
|
||||
double parsed; if (double.TryParse(v.ToString(), out parsed)) return parsed;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using ExportDXF.Models;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using SolidWorks.Interop.swconst;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace ExportDXF.Services
|
||||
@@ -57,7 +57,7 @@ namespace ExportDXF.Services
|
||||
(int)swExportDataSheetsToExport_e.swExportData_ExportAllSheets,
|
||||
drawing);
|
||||
|
||||
context.ProgressCallback?.Invoke($"Exporting drawing to PDF: \"{pdfFileName}\"", null);
|
||||
context.ProgressCallback?.Invoke("Exporting drawing to PDF", LogLevel.Info, pdfFileName);
|
||||
|
||||
int errors = 0;
|
||||
int warnings = 0;
|
||||
@@ -73,26 +73,26 @@ namespace ExportDXF.Services
|
||||
|
||||
if (success && errors == 0)
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"Saved drawing to PDF: \"{pdfFileName}\"", Color.Green);
|
||||
context.ProgressCallback?.Invoke("Saved drawing to PDF", LogLevel.Info, pdfFileName);
|
||||
}
|
||||
else if (success && warnings > 0)
|
||||
{
|
||||
context.ProgressCallback?.Invoke(
|
||||
$"PDF export completed with warnings: {warnings}",
|
||||
Color.DarkBlue);
|
||||
LogLevel.Warning, pdfFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ProgressCallback?.Invoke(
|
||||
$"PDF export failed. Errors: {errors}, Warnings: {warnings}",
|
||||
Color.Red);
|
||||
LogLevel.Error, pdfFileName);
|
||||
throw new InvalidOperationException($"PDF export failed with {errors} errors and {warnings} warnings.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMessage = $"Failed to export PDF: {ex.Message}";
|
||||
context.ProgressCallback?.Invoke(errorMessage, Color.Red);
|
||||
context.ProgressCallback?.Invoke(errorMessage, LogLevel.Error, null);
|
||||
throw new InvalidOperationException(errorMessage, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
using ExportDXF.Data;
|
||||
using ExportDXF.Extensions;
|
||||
using ExportDXF.ItemExtractors;
|
||||
using ExportDXF.Models;
|
||||
using ExportDXF;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using SolidWorks.Interop.swconst;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using Environment = System.Environment;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace ExportDXF.Services
|
||||
{
|
||||
@@ -33,20 +28,23 @@ namespace ExportDXF.Services
|
||||
private readonly IBomExtractor _bomExtractor;
|
||||
private readonly IPartExporter _partExporter;
|
||||
private readonly IDrawingExporter _drawingExporter;
|
||||
private readonly ICutFabApiClient _apiClient;
|
||||
private readonly IFileExportService _fileExportService;
|
||||
private readonly Func<ExportDxfDbContext> _dbContextFactory;
|
||||
|
||||
public DxfExportService(
|
||||
ISolidWorksService solidWorksService,
|
||||
IBomExtractor bomExtractor,
|
||||
IPartExporter partExporter,
|
||||
IDrawingExporter drawingExporter,
|
||||
ICutFabApiClient apiClient)
|
||||
IFileExportService fileExportService,
|
||||
Func<ExportDxfDbContext> dbContextFactory = null)
|
||||
{
|
||||
_solidWorksService = solidWorksService ?? throw new ArgumentNullException(nameof(solidWorksService));
|
||||
_bomExtractor = bomExtractor ?? throw new ArgumentNullException(nameof(bomExtractor));
|
||||
_partExporter = partExporter ?? throw new ArgumentNullException(nameof(partExporter));
|
||||
_drawingExporter = drawingExporter ?? throw new ArgumentNullException(nameof(drawingExporter));
|
||||
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
|
||||
_fileExportService = fileExportService ?? throw new ArgumentNullException(nameof(fileExportService));
|
||||
_dbContextFactory = dbContextFactory ?? (() => new ExportDxfDbContext());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,7 +79,7 @@ namespace ExportDXF.Services
|
||||
break;
|
||||
|
||||
default:
|
||||
LogProgress(context, "Unknown document type.", Color.Red);
|
||||
LogProgress(context, "Unknown document type.", LogLevel.Error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -91,7 +89,7 @@ namespace ExportDXF.Services
|
||||
_solidWorksService.EnableUserControl(true);
|
||||
|
||||
var duration = DateTime.Now - startTime;
|
||||
LogProgress(context, $"Run time: {duration.ToReadableFormat()}", null);
|
||||
LogProgress(context, $"Run time: {duration.ToReadableFormat()}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,28 +97,28 @@ namespace ExportDXF.Services
|
||||
|
||||
private void ExportPart(ExportContext context)
|
||||
{
|
||||
LogProgress(context, "Active document is a Part", null);
|
||||
LogProgress(context, "Active document is a Part");
|
||||
|
||||
var part = context.ActiveDocument.NativeDocument as PartDoc;
|
||||
if (part == null)
|
||||
{
|
||||
LogProgress(context, "Failed to get part document.", Color.Red);
|
||||
LogProgress(context, "Failed to get part document.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var tempDir = CreateTempWorkDir();
|
||||
_partExporter.ExportSinglePart(part, tempDir, context);
|
||||
// Export directly to the output folder
|
||||
_partExporter.ExportSinglePart(part, _fileExportService.OutputFolder, context);
|
||||
}
|
||||
|
||||
private void ExportAssembly(ExportContext context)
|
||||
{
|
||||
LogProgress(context, "Active document is an Assembly", null);
|
||||
LogProgress(context, "Fetching components...", null);
|
||||
LogProgress(context, "Active document is an Assembly");
|
||||
LogProgress(context, "Fetching components...");
|
||||
|
||||
var assembly = context.ActiveDocument.NativeDocument as AssemblyDoc;
|
||||
if (assembly == null)
|
||||
{
|
||||
LogProgress(context, "Failed to get assembly document.", Color.Red);
|
||||
LogProgress(context, "Failed to get assembly document.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,25 +126,25 @@ namespace ExportDXF.Services
|
||||
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
LogProgress(context, "No items found in assembly.", Color.DarkBlue);
|
||||
LogProgress(context, "No items found in assembly.", LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
LogProgress(context, $"Found {items.Count} item(s).", null);
|
||||
LogProgress(context, $"Found {items.Count} item(s).");
|
||||
|
||||
var tempDir = CreateTempWorkDir();
|
||||
ExportItems(items, tempDir, context, drawingId: null);
|
||||
// Export directly to the output folder
|
||||
ExportItems(items, _fileExportService.OutputFolder, context);
|
||||
}
|
||||
|
||||
private void ExportDrawing(ExportContext context)
|
||||
{
|
||||
LogProgress(context, "Active document is a Drawing", null);
|
||||
LogProgress(context, "Finding BOM tables...", null);
|
||||
LogProgress(context, "Active document is a Drawing");
|
||||
LogProgress(context, "Finding BOM tables...");
|
||||
|
||||
var drawing = context.ActiveDocument.NativeDocument as DrawingDoc;
|
||||
if (drawing == null)
|
||||
{
|
||||
LogProgress(context, "Failed to get drawing document.", Color.Red);
|
||||
LogProgress(context, "Failed to get drawing document.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,126 +152,61 @@ namespace ExportDXF.Services
|
||||
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
LogProgress(context, "Error: Bill of materials not found.", Color.Red);
|
||||
LogProgress(context, "Error: Bill of materials not found.", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
LogProgress(context, $"Found {items.Count} component(s)", null);
|
||||
LogProgress(context, $"Found {items.Count} component(s)");
|
||||
|
||||
var tempDir = CreateTempWorkDir();
|
||||
|
||||
// Determine drawing number
|
||||
// Determine drawing number for file naming
|
||||
var drawingNumber = ParseDrawingNumber(context);
|
||||
if (string.IsNullOrWhiteSpace(drawingNumber))
|
||||
|
||||
// Export drawing to PDF
|
||||
var tempDir = CreateTempWorkDir();
|
||||
_drawingExporter.ExportToPdf(drawing, tempDir, context);
|
||||
|
||||
// Copy PDF to output folder
|
||||
try
|
||||
{
|
||||
LogProgress(context, "Warning: Could not determine drawing number for API upload.", Color.DarkBlue);
|
||||
var pdfs = Directory.GetFiles(tempDir, "*.pdf");
|
||||
if (pdfs.Length > 0)
|
||||
{
|
||||
var savedPath = _fileExportService.SavePdfFile(pdfs[0], drawingNumber);
|
||||
LogProgress(context, $"Saved PDF: {Path.GetFileName(savedPath)}", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogProgress(context, $"PDF save error: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
|
||||
// Resolve drawing ID if possible
|
||||
int? drawingId = null;
|
||||
if (!string.IsNullOrWhiteSpace(drawingNumber))
|
||||
// Create export record in database
|
||||
ExportRecord exportRecord = null;
|
||||
try
|
||||
{
|
||||
drawingId = _apiClient.ResolveDrawingIdAsync(drawingNumber).GetAwaiter().GetResult();
|
||||
// Fallback: if resolve endpoint not available or failed, search equipment details
|
||||
if (drawingId == null && context.EquipmentId.HasValue)
|
||||
using (var db = _dbContextFactory())
|
||||
{
|
||||
try
|
||||
db.Database.EnsureCreated();
|
||||
exportRecord = new ExportRecord
|
||||
{
|
||||
var drawings = _apiClient.GetDrawingsForEquipmentAsync(context.EquipmentId.Value).GetAwaiter().GetResult();
|
||||
if (drawings != null)
|
||||
{
|
||||
// Match by exact DrawingNumber (case-insensitive, trimmed)
|
||||
var match = drawings.FirstOrDefault(d => string.Equals(d.DrawingNumber?.Trim(), drawingNumber.Trim(), StringComparison.OrdinalIgnoreCase));
|
||||
if (match != null) drawingId = match.ID;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
DrawingNumber = drawingNumber ?? context.ActiveDocument.Title,
|
||||
SourceFilePath = context.ActiveDocument.FilePath,
|
||||
OutputFolder = _fileExportService.OutputFolder,
|
||||
ExportedAt = DateTime.Now,
|
||||
ExportedBy = System.Environment.UserName
|
||||
};
|
||||
db.ExportRecords.Add(exportRecord);
|
||||
db.SaveChanges();
|
||||
LogProgress(context, $"Created export record (ID: {exportRecord.Id})", LogLevel.Info);
|
||||
}
|
||||
if (drawingId == null)
|
||||
{
|
||||
// If equipment is provided, create the drawing on the API
|
||||
if (context.EquipmentId.HasValue)
|
||||
{
|
||||
var create = _apiClient.CreateDrawingWithInfoAsync(context.EquipmentId.Value, drawingNumber).GetAwaiter().GetResult();
|
||||
if (create != null && create.Success && create.Data.HasValue)
|
||||
{
|
||||
drawingId = create.Data;
|
||||
LogProgress(context, "Created drawing '" + drawingNumber + "' (ID " + drawingId + ") for equipment " + context.EquipmentId, Color.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
var code = create != null ? create.StatusCode.ToString() : "?";
|
||||
var err = create != null ? (create.Error ?? create.RawBody) : null;
|
||||
if (!string.IsNullOrWhiteSpace(err) && err.Length > 180) err = err.Substring(0, 180) + "...";
|
||||
LogProgress(context, "Warning: Could not create drawing '" + drawingNumber + "' on API (status " + code + "). " + (err ?? string.Empty), Color.DarkBlue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogProgress(context, $"Warning: Drawing '{drawingNumber}' not found in API; uploads will be skipped.", Color.DarkBlue);
|
||||
}
|
||||
}
|
||||
|
||||
// Export drawing to PDF first
|
||||
_drawingExporter.ExportToPdf(drawing, tempDir, context);
|
||||
|
||||
// Upload PDF if we have a drawing number
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(drawingNumber))
|
||||
{
|
||||
var pdfs = Directory.GetFiles(tempDir, "*.pdf");
|
||||
var pdfName = pdfs.Length > 0 ? pdfs[0] : null;
|
||||
if (pdfName != null)
|
||||
{
|
||||
var uploadedBy = Environment.UserName;
|
||||
var ok = _apiClient.UploadDrawingPdfAsync(drawingNumber, pdfName, uploadedBy, null).GetAwaiter().GetResult();
|
||||
LogProgress(context, ok ? $"Uploaded PDF for '{drawingNumber}'" : $"Failed to upload PDF for '{drawingNumber}'", ok ? Color.Green : Color.Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogProgress(context, $"PDF upload error: {ex.Message}", Color.Red);
|
||||
}
|
||||
|
||||
// If we still don't have an ID, resolve again after PDF upload (server may create on upload)
|
||||
if (!drawingId.HasValue && !string.IsNullOrWhiteSpace(drawingNumber))
|
||||
{
|
||||
var resolved = _apiClient.ResolveDrawingIdAsync(drawingNumber).GetAwaiter().GetResult();
|
||||
if (!resolved.HasValue && context.EquipmentId.HasValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
var drawings = _apiClient.GetDrawingsForEquipmentAsync(context.EquipmentId.Value).GetAwaiter().GetResult();
|
||||
if (drawings != null)
|
||||
{
|
||||
var match = drawings.FirstOrDefault(d => string.Equals(d.DrawingNumber?.Trim(), drawingNumber.Trim(), StringComparison.OrdinalIgnoreCase));
|
||||
if (match != null) resolved = match.ID;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (resolved.HasValue)
|
||||
{
|
||||
drawingId = resolved;
|
||||
LogProgress(context, $"Resolved drawing ID after PDF upload: {drawingId}", Color.Green);
|
||||
}
|
||||
}
|
||||
|
||||
// Then export parts to DXF and upload per-file
|
||||
ExportItems(items, tempDir, context, drawingId);
|
||||
|
||||
// Attempt to auto-link templates at the end
|
||||
try
|
||||
{
|
||||
if (drawingId.HasValue)
|
||||
{
|
||||
_apiClient.AutoLinkTemplatesAsync(drawingId.Value).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogProgress(context, $"Database error creating export record: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
|
||||
// Export parts to DXF (directly to output folder) and save BOM items
|
||||
ExportItems(items, _fileExportService.OutputFolder, context, exportRecord?.Id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -293,7 +226,7 @@ namespace ExportDXF.Services
|
||||
// Set up drawing template path
|
||||
context.TemplateDrawing = null;
|
||||
|
||||
LogProgress(context, "Export context initialized", null);
|
||||
LogProgress(context, "Export context initialized");
|
||||
}
|
||||
|
||||
private void CleanupExportContext(ExportContext context)
|
||||
@@ -305,7 +238,7 @@ namespace ExportDXF.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogProgress(context, $"Warning: Failed to cleanup template drawing: {ex.Message}", Color.DarkBlue);
|
||||
LogProgress(context, $"Warning: Failed to cleanup template drawing: {ex.Message}", LogLevel.Warning);
|
||||
// Don't throw - this is cleanup code
|
||||
}
|
||||
}
|
||||
@@ -327,23 +260,22 @@ namespace ExportDXF.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogProgress(context, $"Failed to extract items from assembly: {ex.Message}", Color.Red);
|
||||
LogProgress(context, $"Failed to extract items from assembly: {ex.Message}", LogLevel.Error);
|
||||
return new List<Item>();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportItems(List<Item> items, string saveDirectory, ExportContext context, int? drawingId)
|
||||
private void ExportItems(List<Item> items, string saveDirectory, ExportContext context, int? exportRecordId = null)
|
||||
{
|
||||
LogProgress(context, "", null);
|
||||
|
||||
int successCount = 0;
|
||||
int failureCount = 0;
|
||||
int sortOrder = 0;
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (context.CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
LogProgress(context, "Export canceled by user.", Color.DarkBlue);
|
||||
LogProgress(context, "Export canceled by user.", LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -352,54 +284,49 @@ namespace ExportDXF.Services
|
||||
// PartExporter will handle template drawing creation through context
|
||||
_partExporter.ExportItem(item, saveDirectory, context);
|
||||
|
||||
// Always create BOM item first if we have a drawing
|
||||
if (drawingId.HasValue)
|
||||
{
|
||||
var dto = new
|
||||
{
|
||||
DrawingID = drawingId.Value,
|
||||
ItemNo = item.ItemNo,
|
||||
PartNo = !string.IsNullOrEmpty(item.FileName) ? item.FileName : item.PartName,
|
||||
Qty = (int?)item.Quantity,
|
||||
Description = string.IsNullOrWhiteSpace(item.Description) ? null : item.Description,
|
||||
PartName = string.IsNullOrWhiteSpace(item.PartName) ? null : item.PartName,
|
||||
ConfigurationName = string.IsNullOrWhiteSpace(item.Configuration) ? null : item.Configuration,
|
||||
Material = string.IsNullOrWhiteSpace(item.Material) ? null : item.Material,
|
||||
SortOrder = 0,
|
||||
CutTemplateID = (int?)null,
|
||||
FormProgramID = (int?)null
|
||||
};
|
||||
var bomId = _apiClient.CreateBomItemAsync(dto).GetAwaiter().GetResult();
|
||||
LogProgress(context, bomId.HasValue ? $"Created BOM item for {item.ItemNo ?? item.PartName}" : $"Failed to create BOM item for {item.ItemNo ?? item.PartName}", bomId.HasValue ? Color.Green : Color.Red);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(item.FileName))
|
||||
{
|
||||
successCount++;
|
||||
LogProgress(context, $"Exported: {item.FileName}.dxf", LogLevel.Info);
|
||||
|
||||
// If we know the drawing, upload DXF
|
||||
if (drawingId.HasValue)
|
||||
// Create BOM item
|
||||
var dxfPath = Path.Combine(saveDirectory, item.FileName + ".dxf");
|
||||
var bomItem = new BomItem
|
||||
{
|
||||
var dxfPath = Path.Combine(saveDirectory, item.FileName + ".dxf");
|
||||
if (File.Exists(dxfPath))
|
||||
ExportRecordId = exportRecordId ?? 0,
|
||||
ItemNo = item.ItemNo ?? "",
|
||||
PartNo = item.FileName ?? item.PartName ?? "",
|
||||
SortOrder = sortOrder++,
|
||||
Qty = item.Quantity,
|
||||
TotalQty = item.Quantity,
|
||||
Description = item.Description ?? "",
|
||||
PartName = item.PartName ?? "",
|
||||
ConfigurationName = item.Configuration ?? "",
|
||||
Material = item.Material ?? "",
|
||||
Thickness = item.Thickness > 0 ? item.Thickness : null,
|
||||
KFactor = item.KFactor > 0 ? item.KFactor : null,
|
||||
DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null,
|
||||
DxfFilePath = dxfPath
|
||||
};
|
||||
|
||||
// Add to UI
|
||||
context.BomItemCallback?.Invoke(bomItem);
|
||||
|
||||
// Save BOM item to database if we have an export record
|
||||
if (exportRecordId.HasValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Zip just this file
|
||||
string zipPath = CreateZipWithSingleFile(dxfPath);
|
||||
try
|
||||
using (var db = _dbContextFactory())
|
||||
{
|
||||
// Pass thickness, kfactor, default bend radius and material from the item
|
||||
double? thickness = item.Thickness > 0 ? item.Thickness : (double?)null;
|
||||
double? kfactor = item.KFactor > 0 ? item.KFactor : (double?)null;
|
||||
double? defaultBendRadius = item.BendRadius > 0 ? item.BendRadius : (double?)null;
|
||||
string material = string.IsNullOrWhiteSpace(item.Material) ? null : item.Material;
|
||||
var okZip = _apiClient.UploadDxfZipAsync(drawingId.Value, zipPath, thickness, kfactor, defaultBendRadius, material).GetAwaiter().GetResult();
|
||||
LogProgress(context, okZip ? $"Uploaded DXF: {Path.GetFileName(dxfPath)}" : $"Failed to upload DXF: {Path.GetFileName(dxfPath)}", okZip ? Color.Green : Color.Red);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { if (File.Exists(zipPath)) File.Delete(zipPath); } catch { }
|
||||
db.BomItems.Add(bomItem);
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
catch (Exception dbEx)
|
||||
{
|
||||
LogProgress(context, $"Database error saving BOM item: {dbEx.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -409,20 +336,23 @@ namespace ExportDXF.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogProgress(context, $"Error exporting item {item.ItemNo}: {ex.Message}", Color.Red);
|
||||
LogProgress(context, $"Error exporting item {item.ItemNo}: {ex.Message}", LogLevel.Error);
|
||||
failureCount++;
|
||||
}
|
||||
|
||||
LogProgress(context, "", null);
|
||||
}
|
||||
|
||||
LogProgress(context, $"Export complete: {successCount} succeeded, {failureCount} failed",
|
||||
failureCount > 0 ? Color.DarkBlue : Color.Green);
|
||||
failureCount > 0 ? LogLevel.Warning : LogLevel.Info);
|
||||
|
||||
if (exportRecordId.HasValue)
|
||||
{
|
||||
LogProgress(context, $"BOM items saved to database (ExportRecord ID: {exportRecordId.Value})", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Temp + Upload Helpers
|
||||
#region Helper Methods
|
||||
|
||||
private string CreateTempWorkDir()
|
||||
{
|
||||
@@ -444,21 +374,6 @@ namespace ExportDXF.Services
|
||||
return info != null ? ($"{info.EquipmentNo} {info.DrawingNo}") : null;
|
||||
}
|
||||
|
||||
private string CreateZipWithSingleFile(string filePath)
|
||||
{
|
||||
var zipPath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".zip");
|
||||
if (File.Exists(zipPath)) File.Delete(zipPath);
|
||||
using (var zip = System.IO.Compression.ZipFile.Open(zipPath, System.IO.Compression.ZipArchiveMode.Create))
|
||||
{
|
||||
zip.CreateEntryFromFile(filePath, Path.GetFileName(filePath));
|
||||
}
|
||||
return zipPath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private void ValidateContext(ExportContext context)
|
||||
{
|
||||
if (context.ActiveDocument == null)
|
||||
@@ -468,15 +383,11 @@ namespace ExportDXF.Services
|
||||
throw new ArgumentException("ProgressCallback cannot be null.", nameof(context));
|
||||
}
|
||||
|
||||
private void LogProgress(ExportContext context, string message, Color? color)
|
||||
private void LogProgress(ExportContext context, string message, LogLevel level = LogLevel.Info, string file = null)
|
||||
{
|
||||
context.ProgressCallback?.Invoke(message, color);
|
||||
context.ProgressCallback?.Invoke(message, level, file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using ExportDXF.Extensions;
|
||||
using ExportDXF.Models;
|
||||
using ExportDXF.Utilities;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using SolidWorks.Interop.swconst;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace ExportDXF.Services
|
||||
@@ -75,7 +75,7 @@ namespace ExportDXF.Services
|
||||
|
||||
if (item?.Component == null)
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"Item {item?.ItemNo} - skipped, no component", Color.Yellow);
|
||||
context.ProgressCallback?.Invoke("Skipped, no component", LogLevel.Warning, $"Item {item?.ItemNo}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace ExportDXF.Services
|
||||
|
||||
if (part == null)
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"{item.ItemNo} - skipped, not a part document", null);
|
||||
context.ProgressCallback?.Invoke("Skipped, not a part document", LogLevel.Info, item.PartName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -150,9 +150,11 @@ namespace ExportDXF.Services
|
||||
{
|
||||
var model = part as ModelDoc2;
|
||||
|
||||
var partTitle = model.GetTitle();
|
||||
|
||||
if (!model.IsSheetMetal())
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"{model.GetTitle()} - skipped, not sheet metal", null);
|
||||
context.ProgressCallback?.Invoke("Skipped, not sheet metal", LogLevel.Info, partTitle);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -164,13 +166,13 @@ namespace ExportDXF.Services
|
||||
var modelName = Path.GetFileNameWithoutExtension(model.GetPathName());
|
||||
sheet.SetName(modelName);
|
||||
|
||||
context.ProgressCallback?.Invoke($"{model.GetTitle()} - Creating flat pattern", null);
|
||||
context.ProgressCallback?.Invoke("Creating flat pattern", LogLevel.Info, partTitle);
|
||||
|
||||
var view = CreateFlatPatternView(templateDrawing, model, configName);
|
||||
|
||||
if (view == null)
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"{model.GetTitle()} - Failed to create flat pattern", Color.Red);
|
||||
context.ProgressCallback?.Invoke("Failed to create flat pattern", LogLevel.Error, partTitle);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -178,7 +180,7 @@ namespace ExportDXF.Services
|
||||
|
||||
if (context.ViewFlipDecider?.ShouldFlip(view) == true)
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"{model.GetTitle()} - Flipped view", Color.Blue);
|
||||
context.ProgressCallback?.Invoke("Flipped view", LogLevel.Info, partTitle);
|
||||
view.FlipView = true;
|
||||
}
|
||||
|
||||
@@ -187,7 +189,7 @@ namespace ExportDXF.Services
|
||||
|
||||
AddEtchLines(savePath);
|
||||
|
||||
context.ProgressCallback?.Invoke($"{model.GetTitle()} - Saved to \"{savePath}\"", Color.Green);
|
||||
context.ProgressCallback?.Invoke($"Saved to \"{savePath}\"", LogLevel.Info, partTitle);
|
||||
|
||||
DeleteView(drawingModel, view);
|
||||
|
||||
@@ -195,7 +197,7 @@ namespace ExportDXF.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.ProgressCallback?.Invoke($"Export failed: {ex.Message}", Color.Red);
|
||||
context.ProgressCallback?.Invoke($"Export failed: {ex.Message}", LogLevel.Error, null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -232,7 +234,8 @@ namespace ExportDXF.Services
|
||||
|
||||
if (ViewHelper.HasSupressedBends(view))
|
||||
{
|
||||
context.ProgressCallback?.Invoke("A bend is suppressed, please check flat pattern", Color.Red);
|
||||
var title = partModel.GetTitle();
|
||||
context.ProgressCallback?.Invoke("A bend is suppressed, please check flat pattern", LogLevel.Error, title);
|
||||
}
|
||||
|
||||
if (ViewHelper.HideModelSketches(view))
|
||||
@@ -297,14 +300,16 @@ namespace ExportDXF.Services
|
||||
if (desc.Contains("laser"))
|
||||
{
|
||||
context.ProgressCallback?.Invoke(
|
||||
$"Failed to export item #{item.ItemNo} but description says it is laser cut.",
|
||||
Color.Red);
|
||||
"Export failed but description says it is laser cut",
|
||||
LogLevel.Error,
|
||||
item.PartName);
|
||||
}
|
||||
else if (desc.Contains("plasma"))
|
||||
{
|
||||
context.ProgressCallback?.Invoke(
|
||||
$"Failed to export item #{item.ItemNo} but description says it is plasma cut.",
|
||||
Color.Red);
|
||||
"Export failed but description says it is plasma cut",
|
||||
LogLevel.Error,
|
||||
item.PartName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
</startup>
|
||||
<appSettings>
|
||||
<add key="MaxBendRadius" value="2.0"/>
|
||||
<!-- Deployed API base URL (default port from Deploy-CutFabApi.ps1) -->
|
||||
<add key="CutFab.ApiBaseUrl" value="http://localhost:7027"/>
|
||||
<add key="ExportOutputFolder" value="C:\ExportDXF\Output"/>
|
||||
</appSettings>
|
||||
<connectionStrings>
|
||||
<add name="ExportDxfDb"
|
||||
connectionString="Server=localhost;Database=ExportDxfDb;Trusted_Connection=True;TrustServerCertificate=True;"
|
||||
providerName="Microsoft.Data.SqlClient"/>
|
||||
</connectionStrings>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user