21 KiB
PDF Editor Step 3 - Joint Widget & Weldmap Entegrasyonu Roadmap
📋 Görev Özeti
Amaç: PDF çizimlerinde interaktif joint veri girişi sağlamak ve PDF Editor, Base Weldmap ve Weldlog veritabanları arasında iki yönlü entegrasyon kurmak.
Temel Gereksinimler:
- Veri girişi için interaktif joint widget (popup)
- Kayıt edilene kadar geçici veri depolama
- Base Weldmap ve Weldlog ile SQL entegrasyonu
- İki yönlü veri senkronizasyonu
- Document Revision entegrasyonu (Spool Iso / As-Build)
🎯 Fonksiyonel Gereksinimler Özeti
Senaryo 1: Engineering Iso + Adding Joints
- Kullanıcı PDF üzerine üçgen (Field) veya yuvarlak (Shop) çizer
- Veri girişi için widget otomatik açılır
- Veriler kayıt edilene kadar hafızada tutulur
- Kayıt sırasında: SQL ile Base Weldmap'e ekleme
- Çizimi Document Revision "Spool Iso" kısmına kaydet
Senaryo 2: Spool Iso/Asbuild Iso + Adding Joints & Welder
- Kullanıcı mevcut joint üzerine gelir
- Widget önceden girilmiş verilerle açılır (Welder1-2 boş)
- Welder1-2 dropdown'larında uygun kaynakçıları listele
- PDF görüntüsünü güncelle: joint no (üstte), welder ID (altta), ayırıcı çizgi
- Kayıt sırasında: SQL ile Weldlog'u güncelle
- Çizimi Document Revision "As-Build" kısmına kaydet
Senaryo 3: Veri Var ama Çizim Eksik
- Base Weldmap/Welder verisi var ama çizim eksik mi kontrol et
- Sol paneli aktifleştir: Spool No, Joint No, Welder ID bölümleri
- Kullanıcı Spool No seçer → Joint listesi
- Kullanıcı Joint + F/S şekli seçer → Çizim görünür
- Kullanıcı Joint + Welder + F/S şekli seçer → Welder ile çizim görünür
- Document Revision'a kaydet (Spool Iso veya As-Build)
🗺️ Geliştirme Roadmap'i
Faz 1: Temel Yapı & Veri Yapısı (Hafta 1)
1.1 Geçici Veri Depolama Sistemi
Hedef: Kaydedilmemiş joint verileri için hafıza içi veri depolama sistemi oluştur
Görevler:
- Geçici depolama için
JointDataManagerJavaScript sınıfı oluştur - Veri yapısını uygula:
Map<shapeId, jointData> - Depolamadan önce veri doğrulama ekle
- Tarayıcı sessionStorage'da veri kalıcılığı (yedek)
- Sayfa kapanışında veri temizleme oluştur
En İyi Uygulamalar:
- O(1) arama performansı için Map kullan
- Çakışma çözümü için veri versiyonlama uygula
- Depolamadan önce veri doğrulama katmanı ekle
- Sayfa yenilemede hayatta kalması için sessionStorage kullan
Oluşturulacak/Değiştirilecek Dosyalar:
resources/views/admin/type/pdf-editor.blade.php(JointDataManager sınıfı ekle)- Oluştur:
public/js/pdf-editor/joint-data-manager.js(opsiyonel ayrım)
1.2 Widget Modal Geliştirmesi
Hedef: Mevcut joint widget modal'ını tüm gerekli alanlarla geliştir
Görevler:
joint-widget-modal.blade.phpdosyasını gözden geçir ve geliştir- Edit type'a göre koşullu alan gösterimi ekle
- IC Log member seçimi uygula (Member1, Member2)
- IC Log'dan Material, Dia, NPS, Thickness için otomatik doldurma mantığı ekle
- Yeterliliğe göre welder dropdown filtreleme uygula
- Form doğrulama ekle
En İyi Uygulamalar:
- Dropdown'lar için Select2 kullan (projede mevcut)
- Member seçimi için debounced API çağrıları uygula
- Kademeli dropdown'lar uygula (member → material detayları)
- Asenkron işlemler için yükleme durumları ekle
- Bootstrap 5 form doğrulama kullan
Değiştirilecek Dosyalar:
resources/views/components/modals/joint-widget-modal.blade.phpresources/views/admin/type/pdf-editor.blade.php(widget entegrasyonu)
Önemli Not: Widget açılışı için double-click kullanılacak. Mevcut double-click silme özelliği kaldırılmalı veya farklı bir tuş kombinasyonu ile değiştirilmelidir.
Phase 2: Shape Interaction & Widget Integration (Week 1-2)
2.1 Shape Click/Hover Event Handling
Goal: Open widget when user interacts with joint shapes
Tasks:
- Add click event listener to triangle/circle shapes
- Add hover event listener for existing joints (Scenario 2)
- Position widget near clicked shape
- Load existing data if joint already has data
- Handle shape creation event (Scenario 1)
Best Practices:
- Use Fabric.js event delegation for performance
- Implement debouncing for hover events
- Calculate optimal widget position (avoid screen edges)
- Use requestAnimationFrame for smooth animations
- Add visual feedback (highlight shape on hover)
Implementation:
// Shape click handler
fabricCanvas.on('mouse:down', (e) => {
if (e.target && (e.target.type === 'triangle' || e.target.type === 'circle')) {
if (currentEditType === 'adding_joints' || currentEditType === 'adding_joints_welder') {
openJointWidget(e.target, e.e);
}
}
});
// Hover handler for existing joints
fabricCanvas.on('mouse:over', (e) => {
if (e.target && e.target.shapeId && hasExistingData(e.target.shapeId)) {
showHoverTooltip(e.target);
}
});
2.2 Widget Data Binding
Goal: Connect widget form with shape data
Tasks:
- Load shape data into widget form
- Save widget data to temporary storage
- Update shape label display (joint no, welder ID)
- Handle form field changes (real-time updates)
- Implement cancel/close behavior
Best Practices:
- Use two-way data binding pattern
- Implement reactive updates (update shape when form changes)
- Add unsaved changes warning
- Use event-driven architecture
Files to Modify:
resources/views/admin/type/pdf-editor.blade.phpresources/views/components/modals/joint-widget-modal.blade.php
Phase 3: API Development & Database Integration (Week 2)
3.1 API Endpoints for Joint Data
Goal: Create RESTful API endpoints for joint operations
Tasks:
- Create
saveJointDataendpoint (already exists, enhance) - Create
getJointDataendpoint - Create
checkExistingWeldmapDataendpoint (already exists) - Create
getQualifiedWeldersendpoint - Create
getICLogMembersendpoint (already exists) - Create
getICLogMemberDetailsendpoint (already exists)
Best Practices:
- Use Laravel Resource classes for consistent responses
- Implement proper validation rules
- Add error handling and logging
- Use database transactions for data integrity
- Implement rate limiting for API calls
Files to Create/Modify:
app/Http/Controllers/Api/AnnotationController.php(enhance existing)app/Http/Controllers/Api/PdfEditorLookupController.php(enhance existing)routes/web.php(add routes if needed)
3.2 Base Weldmap Integration
Goal: Insert/update joint data in Base Weldmap
Tasks:
- Map widget form data to weld_logs table structure
- Implement insert logic for new joints
- Implement update logic for existing joints
- Handle field mapping (widget → database)
- Add validation for required fields
- Implement batch insert for multiple joints
Database Mapping:
Widget Field → weld_logs Column
- joint_no → no_of_the_joint_as_per_as_built_survey
- type_of_joint → type_of_joint (F/S)
- welding_date → welding_date
- spool_no1 → spool_number_1
- spool_no2 → spool_number_2
- pose_no1 → pose_number_1
- pose_no2 → pose_number_2
- member1 → member_1
- member2 → member_2
- material → material_1, material_2
- dia1 → dia_1
- dia2 → dia_2
- nps1 → nps_1
- nps2 → nps_2
- thickness1 → thickness_1
- thickness2 → thickness_2
- welder_id1 → welder_1
- welder_id2 → welder_2
Best Practices:
- Use Eloquent models for database operations
- Implement database transactions
- Add rollback on error
- Use bulk insert for performance
- Validate data before database operations
Files to Modify:
app/Http/Controllers/Api/AnnotationController.phpapp/Models/WeldLog.php(if needed)
3.3 Weldlog Integration
Goal: Update welder assignments in Weldlog
Tasks:
- Implement welder assignment update logic
- Handle real_welder_1 and real_welder_2 fields
- Update joint display on PDF after assignment
- Validate welder qualifications before assignment
Best Practices:
- Use updateOrCreate for idempotent operations
- Implement soft validation (warnings, not errors)
- Add audit trail for welder changes
- Use database transactions
Files to Modify:
app/Http/Controllers/Api/AnnotationController.phpapp/Models/WeldLog.php
Phase 4: Two-Way Data Synchronization (Week 2-3)
4.1 Data Existence Check
Goal: Check if Base Weldmap/Welder data exists but drawing is missing
Tasks:
- Create API endpoint to check data existence
- Implement left panel activation logic
- Create Spool No dropdown population
- Create Joint No dropdown (filtered by Spool)
- Create Welder ID dropdown (filtered by Joint)
API Endpoint:
GET /api/pdf-editor/check-existing-weldmap
Query: drawing_number
Response: {
has_data: true/false,
spools: [...],
joints: [...],
welders: [...]
}
Best Practices:
- Cache API responses for performance
- Implement pagination for large datasets
- Use eager loading for relationships
- Add loading states in UI
Files to Create/Modify:
app/Http/Controllers/Api/PdfEditorLookupController.phpresources/views/admin/type/pdf-editor.blade.php(left panel)
4.2 Drawing Generation from Data
Goal: Generate PDF drawing shapes from existing database data
Tasks:
- Implement shape creation from joint data
- Position shapes based on joint relationships
- Add welder labels if welder data exists
- Handle F/S shape selection
- Update annotation storage
Best Practices:
- Use Fabric.js for shape creation
- Implement smart positioning algorithm
- Add collision detection
- Use canvas grouping for related shapes
Files to Modify:
resources/views/admin/type/pdf-editor.blade.php
Phase 5: Document Revision Integration (Week 3)
5.1 Save to Spool Iso
Goal: Save annotated PDF to Document Revision "Spool Iso"
Tasks:
- Implement PDF export with annotations
- Save to Document Revision pdf_spool_iso column
- Update revision metadata
- Handle versioning
Best Practices:
- Use existing PDF export functionality
- Implement async save operation
- Add progress indicator
- Handle save errors gracefully
Files to Modify:
app/Http/Controllers/Api/AnnotationController.phpapp/Http/Controllers/Api/PdfEditorLookupController.php(updateDocumentStage)
5.2 Save to As-Build
Goal: Save annotated PDF to Document Revision "As-Build"
Tasks:
- Similar to Spool Iso but for pdf_as_build column
- Include welder information in saved PDF
- Update revision metadata
Files to Modify:
- Same as 5.1
Phase 6: Welder Qualification Filtering (Week 3)
6.1 Welder Qualification System
Goal: Filter welders based on qualifications and validity
Tasks:
- Integrate with existing Welder Assignment system
- Implement qualification filtering logic
- Check welder expiry dates
- Filter by material compatibility
- Filter by welding method
Best Practices:
- Reuse existing welder assignment logic
- Cache qualification data
- Implement client-side filtering for performance
- Add server-side validation
Files to Modify:
app/Http/Controllers/Api/PdfEditorLookupController.phpapp/Http/Controllers/AutoCompleteType/welder-assignment/welder_1.php(reference)
🔧 Technical Architecture
Frontend Architecture
PDF Editor Canvas (Fabric.js)
↓
Shape Event Handlers
↓
Joint Data Manager (Temporary Storage)
↓
Widget Modal (Form)
↓
API Calls (AJAX)
↓
Backend Controllers
↓
Database (weld_logs, annotations, document_revisions)
Data Flow
Scenario 1: New Joint Creation
User draws shape → Widget opens → User fills form →
Data stored in memory → User clicks Save →
Batch insert to weld_logs → Save PDF to Document Revision
Scenario 2: Welder Assignment
User hovers joint → Widget opens (pre-filled) →
User selects welders → Update memory →
User clicks Save → Update weld_logs →
Update PDF display → Save PDF to Document Revision
Scenario 3: Drawing from Data
Check data exists → Activate left panel →
User selects Spool → Joints list →
User selects Joint + Shape → Create shape on PDF →
Save PDF to Document Revision
📚 Best Practices & Recommendations
1. Temporary Data Storage
Option A: In-Memory (Recommended)
- Use JavaScript Map/Object for fast access
- Store in component state
- Clear on page unload
- Pros: Fast, no persistence needed
- Cons: Lost on page refresh
Option B: SessionStorage
- Use browser sessionStorage API
- Survives page refresh
- Auto-clears on tab close
- Pros: Persistence
- Cons: Limited size, string serialization
Recommendation: Use in-memory storage with sessionStorage backup
class JointDataManager {
constructor() {
this.data = new Map();
this.loadFromSession();
}
save(shapeId, jointData) {
this.data.set(shapeId, jointData);
this.saveToSession();
}
saveToSession() {
const data = Object.fromEntries(this.data);
sessionStorage.setItem('jointData', JSON.stringify(data));
}
loadFromSession() {
const stored = sessionStorage.getItem('jointData');
if (stored) {
const data = JSON.parse(stored);
this.data = new Map(Object.entries(data));
}
}
}
2. Widget Positioning
Option A: Fixed Position (Current)
- Modal in center of screen
- Pros: Simple, consistent
- Cons: May cover important content
Option B: Dynamic Positioning (Recommended)
- Position near clicked shape
- Calculate based on shape coordinates
- Pros: Better UX, doesn't cover content
- Cons: More complex
Recommendation: Use dynamic positioning with fallback to center
function calculateWidgetPosition(shape, canvas) {
const shapeBounds = shape.getBoundingRect();
const canvasOffset = canvas.getElement().getBoundingClientRect();
const x = canvasOffset.left + shapeBounds.left + shapeBounds.width;
const y = canvasOffset.top + shapeBounds.top;
// Check if fits on screen
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const widgetWidth = 600; // Modal width
const widgetHeight = 500; // Estimated modal height
let finalX = x;
let finalY = y;
if (x + widgetWidth > windowWidth) {
finalX = x - widgetWidth - 20; // Position to left
}
if (y + widgetHeight > windowHeight) {
finalY = windowHeight - widgetHeight - 20;
}
return { x: finalX, y: finalY };
}
3. API Design
RESTful Endpoints:
POST /api/pdf-editor/joint-data - Save joint data
GET /api/pdf-editor/joint-data/{id} - Get joint data
PUT /api/pdf-editor/joint-data/{id} - Update joint data
DELETE /api/pdf-editor/joint-data/{id} - Delete joint data
GET /api/pdf-editor/qualified-welders - Get qualified welders
GET /api/pdf-editor/check-weldmap - Check existing weldmap data
Request/Response Format:
// POST /api/pdf-editor/joint-data
{
"drawing_number": "CW-800-AH01JL-FA00.001",
"joints": [
{
"shape_id": "J-001",
"joint_no": "53A",
"type_of_joint": "F",
"welding_date": "2025-01-15",
"spool_no1": "SP01",
"spool_no2": "SP02",
// ... other fields
}
]
}
// Response
{
"success": true,
"message": "Joint data saved successfully",
"data": {
"saved_count": 1,
"joints": [...]
}
}
4. Database Transactions
Best Practice: Use database transactions for data integrity
public function saveJointData(Request $request): JsonResponse
{
DB::beginTransaction();
try {
foreach ($request->joints as $jointData) {
WeldLog::updateOrCreate(
[
'iso_number' => $request->drawing_number,
'no_of_the_joint_as_per_as_built_survey' => $jointData['joint_no'],
],
[
// ... field mappings
]
);
}
DB::commit();
return response()->json(['success' => true]);
} catch (\Exception $e) {
DB::rollBack();
Log::error('Failed to save joint data', ['error' => $e->getMessage()]);
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
}
}
5. Welder Qualification Filtering
Integration with Existing System:
- Reuse
welder_1.phpautocomplete logic - Filter by material compatibility (MaterialGroupMap)
- Filter by welding method
- Check expiry dates
- Filter by qualification status
Implementation:
public function getQualifiedWelders(Request $request): JsonResponse
{
$request->validate([
'material_1' => 'required|string',
'material_2' => 'required|string',
'welding_method' => 'required|string',
'joint_type' => 'nullable|string',
]);
// Use existing welder assignment logic
$qualifiedWelders = $this->filterQualifiedWelders(
$request->material_1,
$request->material_2,
$request->welding_method
);
return response()->json([
'success' => true,
'data' => $qualifiedWelders
]);
}
6. Performance Optimization
Client-Side:
- Debounce API calls (300ms)
- Cache API responses
- Use virtual scrolling for large lists
- Lazy load widget modal
- Use requestAnimationFrame for animations
Server-Side:
- Use database indexes
- Implement query caching
- Use eager loading for relationships
- Implement pagination
- Use database transactions efficiently
7. Error Handling
Client-Side:
async function saveJointData(jointData) {
try {
const response = await fetch('/api/pdf-editor/joint-data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
},
body: JSON.stringify(jointData)
});
const result = await response.json();
if (!result.success) {
throw new Error(result.message || 'Failed to save joint data');
}
return result;
} catch (error) {
console.error('Error saving joint data:', error);
Swal.fire('Error', error.message, 'error');
throw error;
}
}
Server-Side:
try {
// ... operation
} catch (ValidationException $e) {
return response()->json([
'success' => false,
'message' => 'Validation failed',
'errors' => $e->errors()
], 422);
} catch (\Exception $e) {
Log::error('Joint data save failed', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json([
'success' => false,
'message' => 'An error occurred while saving joint data'
], 500);
}
🧪 Testing Strategy
Unit Tests
- JointDataManager class methods
- API endpoint validation
- Database operations
- Data mapping functions
Integration Tests
- Widget open/close flow
- Data save/load cycle
- API endpoint integration
- Database transaction rollback
E2E Tests
- Complete joint creation flow
- Welder assignment flow
- Drawing generation from data
- Document Revision save
📝 Implementation Checklist
Phase 1: Foundation
- Create JointDataManager class
- Enhance joint widget modal
- Add IC Log member selection
- Implement auto-fill logic
Phase 2: Integration
- Add shape click handlers
- Implement widget positioning
- Connect widget to data manager
- Update shape labels
Phase 3: Backend
- Enhance saveJointData endpoint
- Create getQualifiedWelders endpoint
- Implement Base Weldmap integration
- Implement Weldlog integration
Phase 4: Two-Way Sync
- Create check-existing-weldmap endpoint
- Implement left panel activation
- Create drawing from data
- Handle welder display
Phase 5: Document Revision
- Implement Spool Iso save
- Implement As-Build save
- Add versioning support
Phase 6: Welder Filtering
- Integrate qualification system
- Implement material filtering
- Add expiry date checking
🚀 Next Steps
- Review and approve roadmap
- Set up development branch:
feature/pdf-editor-step3-joint-widget - Start with Phase 1: Foundation & Data Structure
- Iterative development: Test each phase before moving to next
- Code review: After each phase completion
📖 References
-
Existing Code:
app/Http/Controllers/Api/AnnotationController.phpapp/Http/Controllers/Api/PdfEditorLookupController.phpresources/views/components/modals/joint-widget-modal.blade.phpapp/Http/Controllers/AutoCompleteType/welder-assignment/welder_1.php
-
Database Tables:
weld_logs- Main joint and welder dataannotations- PDF shape datadocument_revisions- PDF file storageincoming_control- IC Log member datamaterial_group_map- Material compatibilitywelder_tests- Welder qualifications
Document Version: 1.0
Last Updated: 2025-01-XX
Author: Development Team