mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 15:15:42 +00:00 
			
		
		
		
	Client side QR Codes (#4357)
* Add JS for qrcodejs Ref: https://davidshimjs.github.io/qrcodejs/ * Simple function for rendering a QR code * Refactor QR code view for Part * Replace QR code view for SupplierPart * Refactor QR codes for stock item and stock location models * Remove base QRCodeView entirely
This commit is contained in:
		
							
								
								
									
										1
									
								
								InvenTree/InvenTree/static/script/qrcode.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								InvenTree/InvenTree/static/script/qrcode.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -320,44 +320,6 @@ class AjaxView(AjaxMixin, View):
 | 
				
			|||||||
        return self.renderJsonResponse(request)
 | 
					        return self.renderJsonResponse(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class QRCodeView(AjaxView):
 | 
					 | 
				
			||||||
    """An 'AJAXified' view for displaying a QR code.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Subclasses should implement the get_qr_data(self) function.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ajax_template_name = "qr_code.html"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get(self, request, *args, **kwargs):
 | 
					 | 
				
			||||||
        """Return json with qr-code data."""
 | 
					 | 
				
			||||||
        self.request = request
 | 
					 | 
				
			||||||
        self.pk = self.kwargs['pk']
 | 
					 | 
				
			||||||
        return self.renderJsonResponse(request, None, context=self.get_context_data())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_qr_data(self):
 | 
					 | 
				
			||||||
        """Returns the text object to render to a QR code.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        The actual rendering will be handled by the template
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_context_data(self):
 | 
					 | 
				
			||||||
        """Get context data for passing to the rendering template.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Explicity passes the parameter 'qr_data'
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        context = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        qr = self.get_qr_data()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if qr:
 | 
					 | 
				
			||||||
            context['qr_data'] = qr
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            context['error_msg'] = 'Error generating QR code'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return context
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AjaxUpdateView(AjaxMixin, UpdateView):
 | 
					class AjaxUpdateView(AjaxMixin, UpdateView):
 | 
				
			||||||
    """An 'AJAXified' UpdateView for updating an object in the db.
 | 
					    """An 'AJAXified' UpdateView for updating an object in the db.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -270,10 +270,10 @@ src="{% static 'img/blank_image.png' %}"
 | 
				
			|||||||
{% if barcodes %}
 | 
					{% if barcodes %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$("#show-qr-code").click(function() {
 | 
					$("#show-qr-code").click(function() {
 | 
				
			||||||
    launchModalForm("{% url 'supplier-part-qr' part.pk %}",
 | 
					    showQRDialog(
 | 
				
			||||||
    {
 | 
					        '{% trans "Supplier Part QR Code" %}',
 | 
				
			||||||
        no_post: true,
 | 
					        '{"supplierpart": {{ part.pk }}}'
 | 
				
			||||||
    });
 | 
					    );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$("#barcode-link").click(function() {
 | 
					$("#barcode-link").click(function() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,6 @@ manufacturer_part_urls = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
supplier_part_urls = [
 | 
					supplier_part_urls = [
 | 
				
			||||||
    re_path(r'^(?P<pk>\d+)/', include([
 | 
					    re_path(r'^(?P<pk>\d+)/', include([
 | 
				
			||||||
        re_path('^qr_code/?', views.SupplierPartQRCode.as_view(), name='supplier-part-qr'),
 | 
					 | 
				
			||||||
        re_path('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'),
 | 
					        re_path('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'),
 | 
				
			||||||
    ]))
 | 
					    ]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ from django.urls import reverse
 | 
				
			|||||||
from django.utils.translation import gettext_lazy as _
 | 
					from django.utils.translation import gettext_lazy as _
 | 
				
			||||||
from django.views.generic import DetailView, ListView
 | 
					from django.views.generic import DetailView, ListView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from InvenTree.views import InvenTreeRoleMixin, QRCodeView
 | 
					from InvenTree.views import InvenTreeRoleMixin
 | 
				
			||||||
from plugin.views import InvenTreePluginViewMixin
 | 
					from plugin.views import InvenTreePluginViewMixin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Company, ManufacturerPart, SupplierPart
 | 
					from .models import Company, ManufacturerPart, SupplierPart
 | 
				
			||||||
@@ -112,18 +112,3 @@ class SupplierPartDetail(InvenTreePluginViewMixin, DetailView):
 | 
				
			|||||||
    context_object_name = 'part'
 | 
					    context_object_name = 'part'
 | 
				
			||||||
    queryset = SupplierPart.objects.all()
 | 
					    queryset = SupplierPart.objects.all()
 | 
				
			||||||
    permission_required = 'purchase_order.view'
 | 
					    permission_required = 'purchase_order.view'
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class SupplierPartQRCode(QRCodeView):
 | 
					 | 
				
			||||||
    """View for displaying a QR code for a StockItem object."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ajax_form_title = _("Stock Item QR Code")
 | 
					 | 
				
			||||||
    role_required = 'stock.view'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_qr_data(self):
 | 
					 | 
				
			||||||
        """Generate QR code data for the StockItem."""
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            part = SupplierPart.objects.get(id=self.pk)
 | 
					 | 
				
			||||||
            return part.format_barcode()
 | 
					 | 
				
			||||||
        except SupplierPart.DoesNotExist:
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2118,9 +2118,6 @@ part_api_urls = [
 | 
				
			|||||||
        # BOM download
 | 
					        # BOM download
 | 
				
			||||||
        re_path(r'^bom-download/?', views.BomDownload.as_view(), name='api-bom-download'),
 | 
					        re_path(r'^bom-download/?', views.BomDownload.as_view(), name='api-bom-download'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # QR code download
 | 
					 | 
				
			||||||
        re_path(r'^qr_code/?', views.PartQRCode.as_view(), name='api-part-qr'),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Old pricing endpoint
 | 
					        # Old pricing endpoint
 | 
				
			||||||
        re_path(r'^pricing2/', views.PartPricing.as_view(), name='part-pricing'),
 | 
					        re_path(r'^pricing2/', views.PartPricing.as_view(), name='part-pricing'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -447,11 +447,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    {% if barcodes %}
 | 
					    {% if barcodes %}
 | 
				
			||||||
    $("#show-qr-code").click(function() {
 | 
					    $("#show-qr-code").click(function() {
 | 
				
			||||||
        launchModalForm(
 | 
					        showQRDialog(
 | 
				
			||||||
            "{% url 'api-part-qr' part.id %}",
 | 
					            '{% trans "Part QR Code" %}',
 | 
				
			||||||
            {
 | 
					            '{"part": {{ part.pk }}}',
 | 
				
			||||||
                no_post: true,
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -113,28 +113,3 @@ class PartDetailTest(PartViewTestCase):
 | 
				
			|||||||
        response = self.client.get(reverse('api-bom-download', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
 | 
					        response = self.client.get(reverse('api-bom-download', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
 | 
				
			||||||
        self.assertEqual(response.status_code, 200)
 | 
					        self.assertEqual(response.status_code, 200)
 | 
				
			||||||
        self.assertIn('streaming_content', dir(response))
 | 
					        self.assertIn('streaming_content', dir(response))
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class PartQRTest(PartViewTestCase):
 | 
					 | 
				
			||||||
    """Tests for the Part QR Code AJAX view."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_html_redirect(self):
 | 
					 | 
				
			||||||
        """A HTML request for a QR code should be redirected (use an AJAX request instead)"""
 | 
					 | 
				
			||||||
        response = self.client.get(reverse('api-part-qr', args=(1,)))
 | 
					 | 
				
			||||||
        self.assertEqual(response.status_code, 302)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_valid_part(self):
 | 
					 | 
				
			||||||
        """Test QR code response for a Part"""
 | 
					 | 
				
			||||||
        response = self.client.get(reverse('api-part-qr', args=(1,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
 | 
					 | 
				
			||||||
        self.assertEqual(response.status_code, 200)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        data = str(response.content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.assertIn('Part QR Code', data)
 | 
					 | 
				
			||||||
        self.assertIn('<img src=', data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_invalid_part(self):
 | 
					 | 
				
			||||||
        """Test response for an invalid Part ID value"""
 | 
					 | 
				
			||||||
        response = self.client.get(reverse('api-part-qr', args=(9999,)), HTTP_X_REQUESTED_WITH='XMLHttpRequest')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.assertEqual(response.status_code, 200)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,8 +16,7 @@ from common.models import InvenTreeSetting
 | 
				
			|||||||
from common.views import FileManagementAjaxView, FileManagementFormView
 | 
					from common.views import FileManagementAjaxView, FileManagementFormView
 | 
				
			||||||
from company.models import SupplierPart
 | 
					from company.models import SupplierPart
 | 
				
			||||||
from InvenTree.helpers import str2bool, str2int
 | 
					from InvenTree.helpers import str2bool, str2int
 | 
				
			||||||
from InvenTree.views import (AjaxUpdateView, AjaxView, InvenTreeRoleMixin,
 | 
					from InvenTree.views import AjaxUpdateView, AjaxView, InvenTreeRoleMixin
 | 
				
			||||||
                             QRCodeView)
 | 
					 | 
				
			||||||
from plugin.views import InvenTreePluginViewMixin
 | 
					from plugin.views import InvenTreePluginViewMixin
 | 
				
			||||||
from stock.models import StockItem, StockLocation
 | 
					from stock.models import StockItem, StockLocation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -372,22 +371,6 @@ class PartDetailFromIPN(PartDetail):
 | 
				
			|||||||
        return super(PartDetailFromIPN, self).get(request, *args, **kwargs)
 | 
					        return super(PartDetailFromIPN, self).get(request, *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PartQRCode(QRCodeView):
 | 
					 | 
				
			||||||
    """View for displaying a QR code for a Part object."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ajax_form_title = _("Part QR Code")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    role_required = 'part.view'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_qr_data(self):
 | 
					 | 
				
			||||||
        """Generate QR code data for the Part."""
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            part = Part.objects.get(id=self.pk)
 | 
					 | 
				
			||||||
            return part.format_barcode()
 | 
					 | 
				
			||||||
        except Part.DoesNotExist:
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class PartImageSelect(AjaxUpdateView):
 | 
					class PartImageSelect(AjaxUpdateView):
 | 
				
			||||||
    """View for selecting Part image from existing images."""
 | 
					    """View for selecting Part image from existing images."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -523,10 +523,10 @@ $('#stock-edit-status').click(function () {
 | 
				
			|||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$("#show-qr-code").click(function() {
 | 
					$("#show-qr-code").click(function() {
 | 
				
			||||||
    launchModalForm("{% url 'stock-item-qr' item.id %}",
 | 
					    showQRDialog(
 | 
				
			||||||
    {
 | 
					        '{% trans "Stock Item QR Code" %}',
 | 
				
			||||||
        no_post: true,
 | 
					        '{"stockitem": {{ item.pk }}}',
 | 
				
			||||||
    });
 | 
					    );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% if barcodes %}
 | 
					{% if barcodes %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -399,10 +399,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    {% if barcodes %}
 | 
					    {% if barcodes %}
 | 
				
			||||||
    $('#show-qr-code').click(function() {
 | 
					    $('#show-qr-code').click(function() {
 | 
				
			||||||
        launchModalForm("{% url 'stock-location-qr' location.id %}",
 | 
					        showQRDialog(
 | 
				
			||||||
        {
 | 
					            '{% trans "Stock Location QR Code" %}',
 | 
				
			||||||
            no_post: true,
 | 
					            '{"stocklocation": {{ location.pk }}}'
 | 
				
			||||||
        });
 | 
					        );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $("#barcode-link").click(function() {
 | 
					    $("#barcode-link").click(function() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,8 +7,6 @@ from stock import views
 | 
				
			|||||||
location_urls = [
 | 
					location_urls = [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    re_path(r'^(?P<pk>\d+)/', include([
 | 
					    re_path(r'^(?P<pk>\d+)/', include([
 | 
				
			||||||
        re_path(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Anything else - direct to the location detail view
 | 
					        # Anything else - direct to the location detail view
 | 
				
			||||||
        re_path('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'),
 | 
					        re_path('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'),
 | 
				
			||||||
    ])),
 | 
					    ])),
 | 
				
			||||||
@@ -16,8 +14,6 @@ location_urls = [
 | 
				
			|||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
stock_item_detail_urls = [
 | 
					stock_item_detail_urls = [
 | 
				
			||||||
    re_path(r'^qr_code/', views.StockItemQRCode.as_view(), name='stock-item-qr'),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Anything else - direct to the item detail view
 | 
					    # Anything else - direct to the item detail view
 | 
				
			||||||
    re_path('^.*$', views.StockItemDetail.as_view(), name='stock-item-detail'),
 | 
					    re_path('^.*$', views.StockItemDetail.as_view(), name='stock-item-detail'),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,11 +2,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from django.http import HttpResponseRedirect
 | 
					from django.http import HttpResponseRedirect
 | 
				
			||||||
from django.urls import reverse
 | 
					from django.urls import reverse
 | 
				
			||||||
from django.utils.translation import gettext_lazy as _
 | 
					 | 
				
			||||||
from django.views.generic import DetailView, ListView
 | 
					from django.views.generic import DetailView, ListView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import common.settings
 | 
					import common.settings
 | 
				
			||||||
from InvenTree.views import InvenTreeRoleMixin, QRCodeView
 | 
					from InvenTree.views import InvenTreeRoleMixin
 | 
				
			||||||
from plugin.views import InvenTreePluginViewMixin
 | 
					from plugin.views import InvenTreePluginViewMixin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import StockItem, StockLocation
 | 
					from .models import StockItem, StockLocation
 | 
				
			||||||
@@ -101,34 +100,3 @@ class StockItemDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
 | 
				
			|||||||
                return HttpResponseRedirect(reverse('stock-index'))
 | 
					                return HttpResponseRedirect(reverse('stock-index'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return super().get(request, *args, **kwargs)
 | 
					        return super().get(request, *args, **kwargs)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class StockLocationQRCode(QRCodeView):
 | 
					 | 
				
			||||||
    """View for displaying a QR code for a StockLocation object."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ajax_form_title = _("Stock Location QR code")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    role_required = ['stock_location.view', 'stock.view']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_qr_data(self):
 | 
					 | 
				
			||||||
        """Generate QR code data for the StockLocation."""
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            loc = StockLocation.objects.get(id=self.pk)
 | 
					 | 
				
			||||||
            return loc.format_barcode()
 | 
					 | 
				
			||||||
        except StockLocation.DoesNotExist:
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class StockItemQRCode(QRCodeView):
 | 
					 | 
				
			||||||
    """View for displaying a QR code for a StockItem object."""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ajax_form_title = _("Stock Item QR Code")
 | 
					 | 
				
			||||||
    role_required = 'stock.view'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_qr_data(self):
 | 
					 | 
				
			||||||
        """Generate QR code data for the StockItem."""
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            item = StockItem.objects.get(id=self.pk)
 | 
					 | 
				
			||||||
            return item.format_barcode()
 | 
					 | 
				
			||||||
        except StockItem.DoesNotExist:
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,7 @@
 | 
				
			|||||||
    getFieldValue,
 | 
					    getFieldValue,
 | 
				
			||||||
    reloadFieldOptions,
 | 
					    reloadFieldOptions,
 | 
				
			||||||
    showModalImage,
 | 
					    showModalImage,
 | 
				
			||||||
 | 
					    showQRDialog,
 | 
				
			||||||
    showQuestionDialog,
 | 
					    showQuestionDialog,
 | 
				
			||||||
    showModalSpinner,
 | 
					    showModalSpinner,
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
@@ -590,19 +591,18 @@ function renderErrorMessage(xhr) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Display a modal dialog message box.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* title - Title text
 | 
				
			||||||
 | 
					* content - HTML content of the dialog window
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
function showAlertDialog(title, content, options={}) {
 | 
					function showAlertDialog(title, content, options={}) {
 | 
				
			||||||
    /* Display a modal dialog message box.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * title - Title text
 | 
					 | 
				
			||||||
     * content - HTML content of the dialog window
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (options.alert_style) {
 | 
					    if (options.alert_style) {
 | 
				
			||||||
        // Wrap content in an alert block
 | 
					        // Wrap content in an alert block
 | 
				
			||||||
        content = `<div class='alert alert-block alert-${options.alert_style}'>${content}</div>`;
 | 
					        content = `<div class='alert alert-block alert-${options.alert_style}'>${content}</div>`;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    var modal = createNewModal({
 | 
					    var modal = createNewModal({
 | 
				
			||||||
        title: title,
 | 
					        title: title,
 | 
				
			||||||
        closeText: '{% trans "Close" %}',
 | 
					        closeText: '{% trans "Close" %}',
 | 
				
			||||||
@@ -612,6 +612,36 @@ function showAlertDialog(title, content, options={}) {
 | 
				
			|||||||
    modalSetContent(modal, content);
 | 
					    modalSetContent(modal, content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $(modal).modal('show');
 | 
					    $(modal).modal('show');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (options.after_render) {
 | 
				
			||||||
 | 
					        options.after_render(modal);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Display a simple modal window with a QR code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function showQRDialog(title, data, options={}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let content = `
 | 
				
			||||||
 | 
					    <div id='qrcode-container' style='margin: auto; width: 256px; padding: 25px;'>
 | 
				
			||||||
 | 
					        <div id='qrcode'></div>
 | 
				
			||||||
 | 
					    </div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    options.after_render = function(modal) {
 | 
				
			||||||
 | 
					        let qrcode = new QRCode('qrcode', {
 | 
				
			||||||
 | 
					            width: 256,
 | 
				
			||||||
 | 
					            height: 256,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        qrcode.makeCode(data);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    showAlertDialog(
 | 
				
			||||||
 | 
					        title,
 | 
				
			||||||
 | 
					        content,
 | 
				
			||||||
 | 
					        options
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,3 +35,4 @@
 | 
				
			|||||||
<script defer type='text/javascript' src="{% static 'easymde/easymde.min.js' %}"></script>
 | 
					<script defer type='text/javascript' src="{% static 'easymde/easymde.min.js' %}"></script>
 | 
				
			||||||
<script defer type='text/javascript' src="{% static 'script/randomColor.min.js' %}"></script>
 | 
					<script defer type='text/javascript' src="{% static 'script/randomColor.min.js' %}"></script>
 | 
				
			||||||
<script defer type='text/javascript' src="{% static 'script/html5-qrcode.min.js' %}"></script>
 | 
					<script defer type='text/javascript' src="{% static 'script/html5-qrcode.min.js' %}"></script>
 | 
				
			||||||
 | 
					<script defer type='text/javascript' src="{% static 'script/qrcode.min.js' %}"></script>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user