Celestino Rey пре 5 месеци
родитељ
комит
dc2f9dda4f

+ 1 - 1
K8S/Makefile

@@ -1,5 +1,5 @@
 export REGISTRO=harbor.rancher.lab:30002\/siemensrad
-export IMG_VERSION = alpine-25-15
+export IMG_VERSION = alpine-30
 export NAMESPACE = trgenerator
 
 # limpia todo

+ 22 - 5
src/templates/textdocs/document_detail.html

@@ -10,11 +10,14 @@
                 <div>
                     <h2>{{ document.title }}</h2>
                     <!-- NEW: Byline with author's name -->
-                    <h6 class="card-subtitle text-muted">By {{ document.author.nombre }} on {{ document.created_at|date:"F d, Y" }}</h6>
+                    <h6 class="card-subtitle text-muted">
+                        Latest version v{{ document.latest_version.version_number }}
+                        By {{ document.author.nombre }} on {{ document.latest_version.created_at|date:"F d, Y" }}
+                    </h6>
                 </div>
                 <!-- Action Buttons -->
                 <div>
-                    <a href="{% url 'document_update' pk=document.pk %}" class="btn btn-secondary">Edit</a>
+                    <a href="{% url 'document_edit' pk=document.pk %}" class="btn btn-secondary">Edit</a>
                     <a href="{% url 'document_delete' pk=document.pk %}" class="btn btn-danger">Delete</a>
                     <a href="{% url 'generate_pdf' pk=document.pk %}" class="btn btn-info">Export to PDF</a>
                 </div>
@@ -22,13 +25,27 @@
         </div>
         <div class="card-body">
             <h4 class="card-title">Introduction</h4>
-            <div>{{ document.introduction|safe }}</div>
+            <div>{{ document.latest_version.introduction|safe }}</div>
             <hr>
             <h4 class="card-title">Main Body</h4>
-            <div>{{ document.main_body|safe }}</div>
+            <div>{{ document.latest_version.main_body|safe }}</div>
             <hr>
             <h4 class="card-title">Conclusion</h4>
-            <div>{{ document.conclusion|safe }}</div>
+            <div>{{ document.latest_version.conclusion|safe }}</div>
+        </div>
+        <div class="mt-4">
+        <h4>Version History</h4>
+            <ul class="list-group">
+                {% for version in document.versions.all %}
+                    <li class="list-group-item">
+                        <a href="{% url 'view_version' pk=document.pk version_number=version.version_number %}">
+                            Version {{ version.version_number }}
+                        </a>
+                        <small class="text-muted"> - created on {{ version.created_at|date:"F d, Y" }}</small>
+                        {% if version == document.latest_version %}<span class="badge bg-success ms-2">Latest</span>{% endif %}
+                    </li>
+                {% endfor %}
+            </ul>
         </div>
     </div>
 {% endblock %}

+ 36 - 0
src/templates/textdocs/document_edit_form.html

@@ -0,0 +1,36 @@
+{% extends 'textdocs/base.html' %}
+
+{% block title %}New Version for {{ document.title }}{% endblock %}
+
+{% block content %}
+    <h2>Create New Version for: <span class="text-primary">{{ document.title }}</span></h2>
+    <p class="text-muted">
+        You are editing the content from version {{ document.latest_version.version_number }}. 
+        Saving will create version {{ document.latest_version.version_number|add:1 }}.
+    </p>
+    <hr>
+
+    <form method="post">
+        {% csrf_token %}
+
+        {% if form.errors %}
+            <div class="alert alert-danger">
+                <strong>Please correct the errors below:</strong>
+                <ul>
+                    {% for field, errors in form.errors.items %}
+                        {% for error in errors %}
+                            <li>{{ field|title }}: {{ error }}</li>
+                        {% endfor %}
+                    {% endfor %}
+                </ul>
+            </div>
+        {% endif %}
+
+        {{ form.as_p }}
+        
+        <div class="mt-3">
+            <button type="submit" class="btn btn-success">Save as New Version</button>
+            <a href="{{ document.get_absolute_url }}" class="btn btn-secondary">Cancel</a>
+        </div>
+    </form>
+{% endblock %}

+ 43 - 4
src/templates/textdocs/document_form.html

@@ -1,10 +1,49 @@
 {% extends 'textdocs/base.html' %}
+
+{% block title %}Create a New Document{% endblock %}
+
 {% block content %}
-    <h2>{% if form.instance.pk %}Edit Technical Report{% else %}Create a New Technical Report{% endif %}</h2>
+    <h2>Create a New Document</h2>
+    <p class="text-muted">You will create the main document and its first version (v1).</p>
+    <hr>
+
     <form method="post">
         {% csrf_token %}
-        {{ form.as_p }}
-        <button type="submit" class="btn btn-success">Save Document</button>
-        <a href="{% url 'document_list' %}" class="btn btn-secondary">Cancel</a>
+
+        <!-- Combined error handling for both forms -->
+        {% if title_form.errors or content_form.errors %}
+            <div class="alert alert-danger">
+                <strong>Please correct the errors below:</strong>
+                <ul>
+                    {% for field, errors in title_form.errors.items %}
+                        {% for error in errors %}
+                            <li>{{ field|title }}: {{ error }}</li>
+                        {% endfor %}
+                    {% endfor %}
+                    {% for field, errors in content_form.errors.items %}
+                        {% for error in errors %}
+                            <li>{{ field|title }}: {{ error }}</li>
+                        {% endfor %}
+                    {% endfor %}
+                </ul>
+            </div>
+        {% endif %}
+
+        <!-- Render the title form part -->
+        <div class="mb-3">
+            <label for="id_title" class="form-label"><strong>Document Title</strong></label>
+            {{ title_form.title }}
+        </div>
+
+        <hr>
+
+        <!-- Render the content form part (this will have the TinyMCE editors) -->
+        <p><strong>Initial Content (Version 1)</strong></p>
+        {{ content_form.as_p }}
+        
+        <div class="mt-3">
+            <button type="submit" class="btn btn-success">Create Document and First Version</button>
+            <a href="{% url 'document_list' %}" class="btn btn-secondary">Cancel</a>
+        </div>
     </form>
 {% endblock %}

+ 42 - 0
src/templates/textdocs/version_detail.html

@@ -0,0 +1,42 @@
+{% extends 'textdocs/base.html' %}
+
+{% block title %}Version {{ version.version_number }} of {{ version.document.title }}{% endblock %}
+
+{% block content %}
+
+    <!-- Navigation to get back to the main document page -->
+    <a href="{{ version.document.get_absolute_url }}" class="btn btn-secondary mb-3">‹ Back to Latest Version</a>
+
+    <!-- A warning banner to prevent confusion -->
+    {% if version.version_number != version.document.latest_version.version_number %}
+    <div class="alert alert-warning" role="alert">
+        <strong>Heads up!</strong> You are viewing an older version of this document (v{{ version.version_number }}). The content may be out of date.
+    </div>
+    {% endif %}
+
+    <div class="card">
+        <div class="card-header">
+            <div class="d-flex justify-content-between align-items-center">
+                <div>
+                    <h2>{{ version.document.title }}</h2>
+                    <h5 class="card-subtitle text-success">
+                        Viewing Version {{ version.version_number }}
+                    </h5>
+                    <h6 class="card-subtitle text-muted mt-1">
+                        Created by {{ version.document.author.username }} on {{ version.created_at|date:"F d, Y" }}
+                    </h6>
+                </div>
+            </div>
+        </div>
+        <div class="card-body">
+            <h4 class="card-title">Introduction</h4>
+            <div>{{ version.introduction|safe }}</div>
+            <hr>
+            <h4 class="card-title">Main Body</h4>
+            <div>{{ version.main_body|safe }}</div>
+            <hr>
+            <h4 class="card-title">Conclusion</h4>
+            <div>{{ version.conclusion|safe }}</div>
+        </div>
+    </div>
+{% endblock %}

+ 11 - 9
src/textdocs/forms.py

@@ -1,17 +1,19 @@
 # textdocs/forms.py
 from django import forms
-from .models import Document
-from tinymce.widgets import TinyMCE # <-- Import the TinyMCE widget
+from .models import DocumentVersion # Changed from Document
+from tinymce.widgets import TinyMCE
 
-class DocumentForm(forms.ModelForm):
+# This form is now for creating a *version* of the content
+class DocumentVersionForm(forms.ModelForm):
     class Meta:
-        model = Document
-        fields = ['title', 'introduction', 'main_body', 'conclusion']
-        
-        # Use the TinyMCE widget for our text fields
+        model = DocumentVersion
+        fields = ['introduction', 'main_body', 'conclusion']
         widgets = {
-            'title': forms.TextInput(attrs={'class': 'form-control'}),
             'introduction': TinyMCE(attrs={'cols': 80, 'rows': 10}),
             'main_body': TinyMCE(attrs={'cols': 80, 'rows': 20}),
             'conclusion': TinyMCE(attrs={'cols': 80, 'rows': 10}),
-        }
+        }
+
+# We also need a simple form for creating the parent document
+class DocumentCreateForm(forms.Form):
+    title = forms.CharField(max_length=255, widget=forms.TextInput(attrs={'class': 'form-control'}))

+ 34 - 14
src/textdocs/models.py

@@ -1,26 +1,46 @@
 # textdocs/models.py
 from django.db import models
 from django.urls import reverse
-from django.conf import settings # Import settings
+from django.conf import settings
 
 class Document(models.Model):
-    """Represents a single document with its fixed sections."""
-    
-    # NEW: Link to the user who created the document
-    author = models.ForeignKey(
-        settings.AUTH_USER_MODEL,
-        on_delete=models.CASCADE,
-        related_name='documents'
-    )
-
+    """
+    Represents the main document container. Stores permanent info.
+    """
+    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
     title = models.CharField(max_length=255)
-    introduction = models.TextField(help_text="The introductory section of the document.")
-    main_body = models.TextField(help_text="The main content or analysis.")
-    conclusion = models.TextField(help_text="The concluding remarks or summary.")
     created_at = models.DateTimeField(auto_now_add=True)
 
     def __str__(self):
         return self.title
 
     def get_absolute_url(self):
-        return reverse('document_detail', kwargs={'pk': self.pk})
+        # The main detail page will always show the latest version
+        return reverse('document_detail', kwargs={'pk': self.pk})
+
+    @property
+    def latest_version(self):
+        # A helper to easily get the most recent version
+        return self.versions.order_by('-version_number').first()
+
+class DocumentVersion(models.Model):
+    """
+    Represents a specific version of a Document's content.
+    """
+    document = models.ForeignKey(Document, on_delete=models.CASCADE, related_name='versions')
+    version_number = models.PositiveIntegerField()
+    
+    # The content fields now live here
+    introduction = models.TextField()
+    main_body = models.TextField()
+    conclusion = models.TextField()
+    
+    created_at = models.DateTimeField(auto_now_add=True)
+    
+    class Meta:
+        # Ensure a document can't have two versions with the same number
+        unique_together = ('document', 'version_number')
+        ordering = ['-version_number'] # Default order is newest first
+
+    def __str__(self):
+        return f"{self.document.title} (v{self.version_number})"

+ 2 - 1
src/textdocs/urls.py

@@ -9,6 +9,7 @@ urlpatterns = [
     path('document/<int:pk>/pdf/', views.generate_pdf, name='generate_pdf'),
     
     # --- NEW URLS for Edit and Delete ---
-    path('document/<int:pk>/edit/', views.document_update, name='document_update'),
+    path('document/<int:pk>/edit/', views.document_edit, name='document_edit'),
+    path('document/<int:pk>/version/<int:version_number>/', views.view_version, name='view_version'),
     path('document/<int:pk>/delete/', views.document_delete, name='document_delete'),
 ]

+ 66 - 29
src/textdocs/views.py

@@ -7,59 +7,96 @@ from django.template.loader import render_to_string
 from weasyprint import HTML
 from django.contrib.auth.decorators import login_required
 
-from .models import Document
-from .forms import DocumentForm
+from .models import Document, DocumentVersion # Changed from Document
+from .forms import DocumentVersionForm, DocumentCreateForm # Changed from DocumentForm
 
 @login_required
 def document_list(request):
     """Shows a list of all created documents."""
-    documents = Document.objects.order_by('-created_at')
+    documents = Document.objects.filter(author=request.user).order_by('-created_at')
     return render(request, 'textdocs/document_list.html', {'documents': documents})
 
 @login_required
 def document_detail(request, pk):
     """Shows the details of a single document."""
-    document = get_object_or_404(Document, pk=pk)
+    document = get_object_or_404(Document, pk=pk, author=request.user)
     return render(request, 'textdocs/document_detail.html', {'document': document})
 
 @login_required
 def document_create(request):
-    """Handles the creation of a new document via a form."""
+    """
+    Handles the creation of a new parent Document and its first version.
+    This is a two-form process now, but we'll combine them logically.
+    """
     if request.method == 'POST':
-        print("Method is POST. Processing form data.") # Log POST request
-
-        form = DocumentForm(request.POST)
-        if form.is_valid():
-            document = form.save()
-            return redirect('document_detail', pk=document.pk)
+        title_form = DocumentCreateForm(request.POST)
+        content_form = DocumentVersionForm(request.POST)
+        if title_form.is_valid() and content_form.is_valid():
+            # Create the parent Document
+            document = Document.objects.create(
+                author=request.user,
+                title=title_form.cleaned_data['title']
+            )
+            # Create the first version
+            version = content_form.save(commit=False)
+            version.document = document
+            version.version_number = 1
+            version.save()
+            return redirect(document.get_absolute_url())
     else:
-        form = DocumentForm()
-    return render(request, 'textdocs/document_form.html', {'form': form})
+        title_form = DocumentCreateForm()
+        content_form = DocumentVersionForm()
+        
+    return render(request, 'textdocs/document_form.html', {
+        'title_form': title_form, 
+        'content_form': content_form
+    })
+
 
-# --- NEW: View for updating a document ---
 @login_required
-def document_update(request, pk):
-    """Handles editing and saving an existing document."""
-    document = get_object_or_404(Document, pk=pk)
+def document_edit(request, pk):
+    """
+    Handles creating a NEW version of an existing document.
+    This replaces the old 'update' view.
+    """
+    document = get_object_or_404(Document, pk=pk, author=request.user)
+    latest_version = document.latest_version
+
     if request.method == 'POST':
-        # Pass the instance to the form to update it
-        form = DocumentForm(request.POST, instance=document)
+        form = DocumentVersionForm(request.POST)
         if form.is_valid():
-            form.save()
-            return redirect('document_detail', pk=document.pk)
+            new_version = form.save(commit=False)
+            new_version.document = document
+            # Increment the version number
+            new_version.version_number = latest_version.version_number + 1
+            new_version.save()
+            return redirect(document.get_absolute_url())
     else:
-        # Pre-populate the form with the existing document's data
-        form = DocumentForm(instance=document)
-    return render(request, 'textdocs/document_form.html', {'form': form})
+        # Pre-populate the form with the content of the latest version
+        form = DocumentVersionForm(instance=latest_version)
+
+    return render(request, 'textdocs/document_edit_form.html', {
+        'form': form,
+        'document': document
+    })
+
+# NEW VIEW: To see old versions
+@login_required
+def view_version(request, pk, version_number):
+    document = get_object_or_404(Document, pk=pk, author=request.user)
+    version = get_object_or_404(DocumentVersion, document=document, version_number=version_number)
+    return render(request, 'textdocs/version_detail.html', {'version': version})
 
 # --- NEW: View for deleting a document ---
 @login_required
 def document_delete(request, pk):
-    """Handles the deletion of a document after confirmation."""
-    document = get_object_or_404(Document, pk=pk)
+    """Handles the deletion of a document and all its versions."""
+    document = get_object_or_404(Document, pk=pk, author=request.user)
     if request.method == 'POST':
         # This is after the user confirms the deletion
-        document.delete()
+        document.versions.all().delete() # First delete all versions
+        document.delete() # Then delete the document itself
+        
         return redirect('document_list') # Redirect to the list after deletion
     
     # If it's a GET request, show the confirmation page
@@ -67,8 +104,8 @@ def document_delete(request, pk):
 
 @login_required
 def generate_pdf(request, pk):
-    """Generates a PDF for a specific document."""
-    document = get_object_or_404(Document, pk=pk)
+    """Generates a PDF for a specific version of a document."""
+    document = get_object_or_404(Document, pk=pk, author=request.user)
     html_string = render_to_string('textdocs/document_pdf.html', {'document': document})
     html = HTML(string=html_string, base_url=request.build_absolute_uri())
     pdf = html.write_pdf()