mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	JS translation fix (#6288)
* Implement {% jstrans %} template
- Forces string escaping in translated text
- Required for js written in templates
* Fix part_base.html
* Update .html files
- Change any templated javascript code to use {% jstrans %}
* Update .js files
- Explicitly use {% jstrans %}
* Update CI checks
			
			
This commit is contained in:
		| @@ -27,6 +27,14 @@ def translation_stats(lang_code): | |||||||
| class CustomTranslateNode(TranslateNode): | class CustomTranslateNode(TranslateNode): | ||||||
|     """Custom translation node class, which sanitizes the translated strings for javascript use.""" |     """Custom translation node class, which sanitizes the translated strings for javascript use.""" | ||||||
|  |  | ||||||
|  |     def __init__(self, filter_expression, noop, asvar, message_context, escape=False): | ||||||
|  |         """Custom constructor for TranslateNode class. | ||||||
|  |  | ||||||
|  |         - Adds an 'escape' argument, which is passed to the render function | ||||||
|  |         """ | ||||||
|  |         super().__init__(filter_expression, noop, asvar, message_context) | ||||||
|  |         self.escape = escape | ||||||
|  |  | ||||||
|     def render(self, context): |     def render(self, context): | ||||||
|         """Custom render function overrides / extends default behaviour.""" |         """Custom render function overrides / extends default behaviour.""" | ||||||
|         result = super().render(context) |         result = super().render(context) | ||||||
| @@ -44,7 +52,7 @@ class CustomTranslateNode(TranslateNode): | |||||||
|         # Escape any quotes contained in the string, if the request is for a javascript file |         # Escape any quotes contained in the string, if the request is for a javascript file | ||||||
|         request = context.get('request', None) |         request = context.get('request', None) | ||||||
|  |  | ||||||
|         if request and request.path.endswith('.js'): |         if self.escape or (request and request.path.endswith('.js')): | ||||||
|             result = result.replace("'", r'\'') |             result = result.replace("'", r'\'') | ||||||
|             result = result.replace('"', r'\"') |             result = result.replace('"', r'\"') | ||||||
|  |  | ||||||
| @@ -54,7 +62,7 @@ class CustomTranslateNode(TranslateNode): | |||||||
|  |  | ||||||
| @register.tag('translate') | @register.tag('translate') | ||||||
| @register.tag('trans') | @register.tag('trans') | ||||||
| def do_translate(parser, token): | def do_translate(parser, token, escape=False): | ||||||
|     """Custom translation function. |     """Custom translation function. | ||||||
|  |  | ||||||
|     - Lifted from https://github.com/django/django/blob/main/django/templatetags/i18n.py. |     - Lifted from https://github.com/django/django/blob/main/django/templatetags/i18n.py. | ||||||
| @@ -110,7 +118,21 @@ def do_translate(parser, token): | |||||||
|             ) |             ) | ||||||
|         seen.add(option) |         seen.add(option) | ||||||
|  |  | ||||||
|     return CustomTranslateNode(message_string, noop, asvar, message_context) |     return CustomTranslateNode( | ||||||
|  |         message_string, noop, asvar, message_context, escape=escape | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @register.tag('jstrans') | ||||||
|  | def do_jstrans(parser, token): | ||||||
|  |     """Custom translation function for javascript strings. | ||||||
|  |  | ||||||
|  |     - Usage: {% jstrans "String to translate" %} | ||||||
|  |     - Performs the same function as the 'trans' tag, but also escapes the translated string. | ||||||
|  |     - Explicitly required for javascript code within a .html template | ||||||
|  |     - Note: Any {% trans %} tag is automatically escaped in a .js file | ||||||
|  |     """ | ||||||
|  |     return do_translate(parser, token, escape=True) | ||||||
|  |  | ||||||
|  |  | ||||||
| # Re-register tags which we have not explicitly overridden | # Re-register tags which we have not explicitly overridden | ||||||
|   | |||||||
| @@ -270,7 +270,7 @@ src="{% static 'img/blank_image.png' %}" | |||||||
|             '{% url "api-build-detail" build.pk %}', |             '{% url "api-build-detail" build.pk %}', | ||||||
|             { |             { | ||||||
|                 method: 'DELETE', |                 method: 'DELETE', | ||||||
|                 title: '{% trans "Delete Build Order" %}', |                 title: '{% jstrans "Delete Build Order" %}', | ||||||
|                 redirect: "{% url 'build-index' %}", |                 redirect: "{% url 'build-index' %}", | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
| @@ -280,7 +280,7 @@ src="{% static 'img/blank_image.png' %}" | |||||||
|     <!-- Barcode functionality callbacks --> |     <!-- Barcode functionality callbacks --> | ||||||
|     $('#show-qr-code').click(function() { |     $('#show-qr-code').click(function() { | ||||||
|         showQRDialog( |         showQRDialog( | ||||||
|             '{% trans "Build Order QR Code" %}', |             '{% jstrans "Build Order QR Code" %}', | ||||||
|             '{"build": {{ build.pk }} }' |             '{"build": {{ build.pk }} }' | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
| @@ -292,7 +292,7 @@ src="{% static 'img/blank_image.png' %}" | |||||||
|                 build: {{ build.pk }}, |                 build: {{ build.pk }}, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 title: '{% trans "Link Barcode to Build Order" %}', |                 title: '{% jstrans "Link Barcode to Build Order" %}', | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -419,8 +419,8 @@ function allocateSelectedLines() { | |||||||
|  |  | ||||||
|     if (unallocated_lines.length == 0) { |     if (unallocated_lines.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Allocation Complete" %}', |             '{% jstrans "Allocation Complete" %}', | ||||||
|             '{% trans "All lines have been fully allocated" %}', |             '{% jstrans "All lines have been fully allocated" %}', | ||||||
|         ); |         ); | ||||||
|     } else { |     } else { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -159,7 +159,7 @@ | |||||||
|     $('#company-delete').click(function() { |     $('#company-delete').click(function() { | ||||||
|         constructForm('{% url "api-company-detail" company.pk %}', { |         constructForm('{% url "api-company-detail" company.pk %}', { | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             title: '{% trans "Delete Company" %}', |             title: '{% jstrans "Delete Company" %}', | ||||||
|             redirect: '{% url "company-index" %}', |             redirect: '{% url "company-index" %}', | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -202,10 +202,10 @@ | |||||||
|     $('#company-image-delete').click(function(event) { |     $('#company-image-delete').click(function(event) { | ||||||
|         event.stopPropagation(); |         event.stopPropagation(); | ||||||
|         showQuestionDialog( |         showQuestionDialog( | ||||||
|             '{% trans "Remove Image" %}', |             '{% jstrans "Remove Image" %}', | ||||||
|             '{% trans "Remove associated image from this company" %}', |             '{% jstrans "Remove associated image from this company" %}', | ||||||
|             { |             { | ||||||
|                 accept_text: '{% trans "Remove" %}', |                 accept_text: '{% jstrans "Remove" %}', | ||||||
|                 submitClass: 'danger', |                 submitClass: 'danger', | ||||||
|                 accept: function() { |                 accept: function() { | ||||||
|                     inventreePut( |                     inventreePut( | ||||||
| @@ -234,7 +234,7 @@ | |||||||
|                 fields: { |                 fields: { | ||||||
|                     image: {}, |                     image: {}, | ||||||
|                 }, |                 }, | ||||||
|                 title: '{% trans "Upload Image" %}', |                 title: '{% jstrans "Upload Image" %}', | ||||||
|                 onSuccess: function(data) { |                 onSuccess: function(data) { | ||||||
|                     reloadImage(data); |                     reloadImage(data); | ||||||
|                 } |                 } | ||||||
| @@ -249,7 +249,7 @@ | |||||||
|                 '{% url "api-company-detail" company.pk %}', |                 '{% url "api-company-detail" company.pk %}', | ||||||
|                 { |                 { | ||||||
|                     method: 'PATCH', |                     method: 'PATCH', | ||||||
|                     title: '{% trans "Download Image" %}', |                     title: '{% jstrans "Download Image" %}', | ||||||
|                     fields: { |                     fields: { | ||||||
|                         remote_image: {}, |                         remote_image: {}, | ||||||
|                     }, |                     }, | ||||||
|   | |||||||
| @@ -203,7 +203,7 @@ $('#parameter-create').click(function() { | |||||||
|                 hidden: true, |                 hidden: true, | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         title: '{% trans "Add Parameter" %}', |         title: '{% jstrans "Add Parameter" %}', | ||||||
|         refreshTable: '#parameter-table', |         refreshTable: '#parameter-table', | ||||||
|     }); |     }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -273,7 +273,7 @@ src="{% static 'img/blank_image.png' %}" | |||||||
|  |  | ||||||
| $("#show-qr-code").click(function() { | $("#show-qr-code").click(function() { | ||||||
|     showQRDialog( |     showQRDialog( | ||||||
|         '{% trans "Supplier Part QR Code" %}', |         '{% jstrans "Supplier Part QR Code" %}', | ||||||
|         '{"supplierpart": {{ part.pk }} }' |         '{"supplierpart": {{ part.pk }} }' | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -284,7 +284,7 @@ $("#barcode-link").click(function() { | |||||||
|             supplierpart: {{ part.pk }}, |             supplierpart: {{ part.pk }}, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             title: '{% trans "Link Barcode to Supplier Part" %}', |             title: '{% jstrans "Link Barcode to Supplier Part" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -356,7 +356,7 @@ $('#update-part-availability').click(function() { | |||||||
|         fields: { |         fields: { | ||||||
|             available: {}, |             available: {}, | ||||||
|         }, |         }, | ||||||
|         title: '{% trans "Update Part Availability" %}', |         title: '{% jstrans "Update Part Availability" %}', | ||||||
|         onSuccess: function() { |         onSuccess: function() { | ||||||
|             location.reload(); |             location.reload(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -315,7 +315,7 @@ $("#export-order").click(function() { | |||||||
| <!-- Barcode functionality callbacks --> | <!-- Barcode functionality callbacks --> | ||||||
| $('#show-qr-code').click(function() { | $('#show-qr-code').click(function() { | ||||||
|     showQRDialog( |     showQRDialog( | ||||||
|         '{% trans "Purchase Order QR Code" %}', |         '{% jstrans "Purchase Order QR Code" %}', | ||||||
|         '{"purchaseorder": {{ order.pk }} }' |         '{"purchaseorder": {{ order.pk }} }' | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -327,7 +327,7 @@ $("#barcode-link").click(function() { | |||||||
|             purchaseorder: {{ order.pk }}, |             purchaseorder: {{ order.pk }}, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             title: '{% trans "Link Barcode to Purchase Order" %}', |             title: '{% jstrans "Link Barcode to Purchase Order" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -260,7 +260,7 @@ $('#print-order-report').click(function() { | |||||||
| <!-- Barcode functionality callbacks --> | <!-- Barcode functionality callbacks --> | ||||||
| $('#show-qr-code').click(function() { | $('#show-qr-code').click(function() { | ||||||
|     showQRDialog( |     showQRDialog( | ||||||
|         '{% trans "Return Order QR Code" %}', |         '{% jstrans "Return Order QR Code" %}', | ||||||
|         '{"returnorder": {{ order.pk }} }' |         '{"returnorder": {{ order.pk }} }' | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -272,7 +272,7 @@ $("#barcode-link").click(function() { | |||||||
|             returnorder: {{ order.pk }}, |             returnorder: {{ order.pk }}, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             title: '{% trans "Link Barcode to Return Order" %}', |             title: '{% jstrans "Link Barcode to Return Order" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -309,7 +309,7 @@ $('#print-order-report').click(function() { | |||||||
| <!-- Barcode functionality callbacks --> | <!-- Barcode functionality callbacks --> | ||||||
| $('#show-qr-code').click(function() { | $('#show-qr-code').click(function() { | ||||||
|     showQRDialog( |     showQRDialog( | ||||||
|         '{% trans "Sales Order QR Code" %}', |         '{% jstrans "Sales Order QR Code" %}', | ||||||
|         '{"salesorder": {{ order.pk }} }' |         '{"salesorder": {{ order.pk }} }' | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -321,7 +321,7 @@ $("#barcode-link").click(function() { | |||||||
|             salesorder: {{ order.pk }}, |             salesorder: {{ order.pk }}, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             title: '{% trans "Link Barcode to Sales Order" %}', |             title: '{% jstrans "Link Barcode to Sales Order" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -656,7 +656,7 @@ | |||||||
|                         value: {{ part.pk }}, |                         value: {{ part.pk }}, | ||||||
|                     }, |                     }, | ||||||
|                     part_2: { |                     part_2: { | ||||||
|                         label: '{% trans "Related Part" %}', |                         label: '{% jstrans "Related Part" %}', | ||||||
|                         filters: { |                         filters: { | ||||||
|                             exclude_id: {{ part.pk }}, |                             exclude_id: {{ part.pk }}, | ||||||
|                             exclude_related: {{ part.pk }}, |                             exclude_related: {{ part.pk }}, | ||||||
| @@ -664,7 +664,7 @@ | |||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|                 focus: 'part_2', |                 focus: 'part_2', | ||||||
|                 title: '{% trans "Add Related Part" %}', |                 title: '{% jstrans "Add Related Part" %}', | ||||||
|                 refreshTable: '#related-parts-table', |                 refreshTable: '#related-parts-table', | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @@ -749,7 +749,7 @@ | |||||||
|                 fields: partTestTemplateFields({ |                 fields: partTestTemplateFields({ | ||||||
|                     part: {{ part.pk }} |                     part: {{ part.pk }} | ||||||
|                 }), |                 }), | ||||||
|                 title: '{% trans "Add Test Result Template" %}', |                 title: '{% jstrans "Add Test Result Template" %}', | ||||||
|                 refreshTable: '#test-template-table', |                 refreshTable: '#test-template-table', | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|   | |||||||
| @@ -441,7 +441,7 @@ | |||||||
|     {% if barcodes %} |     {% if barcodes %} | ||||||
|     $("#show-qr-code").click(function() { |     $("#show-qr-code").click(function() { | ||||||
|         showQRDialog( |         showQRDialog( | ||||||
|             '{% trans "Part QR Code" %}', |             '{% jstrans "Part QR Code" %}', | ||||||
|             '{"part": {{ part.pk }} }', |             '{"part": {{ part.pk }} }', | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
| @@ -458,7 +458,7 @@ | |||||||
|                 part: {{ part.pk }}, |                 part: {{ part.pk }}, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 title: '{% trans "Link Barcode to Part" %}', |                 title: '{% jstrans "Link Barcode to Part" %}', | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
| @@ -469,7 +469,7 @@ | |||||||
|         printLabels({ |         printLabels({ | ||||||
|             items: [{{ part.pk }}], |             items: [{{ part.pk }}], | ||||||
|             key: 'part', |             key: 'part', | ||||||
|             singular_name: '{% trans "part" %}', |             singular_name: 'part', | ||||||
|             url: '{% url "api-part-label-list" %}', |             url: '{% url "api-part-label-list" %}', | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -509,7 +509,7 @@ | |||||||
|         launchModalForm( |         launchModalForm( | ||||||
|             "{% url 'part-pricing' part.id %}", |             "{% url 'part-pricing' part.id %}", | ||||||
|             { |             { | ||||||
|                 submit_text: '{% trans "Calculate" %}', |                 submit_text: '{% jstrans "Calculate" %}', | ||||||
|                 hideErrorMessage: true, |                 hideErrorMessage: true, | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
| @@ -525,10 +525,10 @@ | |||||||
|     $('#part-image-delete').click(function(event) { |     $('#part-image-delete').click(function(event) { | ||||||
|         event.stopPropagation(); |         event.stopPropagation(); | ||||||
|         showQuestionDialog( |         showQuestionDialog( | ||||||
|             '{% trans "Remove Image" %}', |             '{% jstrans "Remove Image" %}', | ||||||
|             '{% trans "Remove associated image from this part" %}', |             '{% jstrans "Remove associated image from this part" %}', | ||||||
|             { |             { | ||||||
|                 accept_text: '{% trans "Remove" %}', |                 accept_text: '{% jstrans "Remove" %}', | ||||||
|                 submitClass: 'danger', |                 submitClass: 'danger', | ||||||
|                 accept: function() { |                 accept: function() { | ||||||
|                     inventreePut( |                     inventreePut( | ||||||
| @@ -557,7 +557,7 @@ | |||||||
|                 fields: { |                 fields: { | ||||||
|                     image: {}, |                     image: {}, | ||||||
|                 }, |                 }, | ||||||
|                 title: '{% trans "Upload Image" %}', |                 title: '{% jstrans "Upload Image" %}', | ||||||
|                 onSuccess: function(data) { |                 onSuccess: function(data) { | ||||||
|                     reloadImage(data); |                     reloadImage(data); | ||||||
|                 } |                 } | ||||||
| @@ -577,7 +577,7 @@ | |||||||
|             sidePagination: 'server', |             sidePagination: 'server', | ||||||
|             singleSelect: true, |             singleSelect: true, | ||||||
|             formatNoMatches: function() { |             formatNoMatches: function() { | ||||||
|                 return '{% trans "No matching images found" %}'; |                 return '{% jstrans "No matching images found" %}'; | ||||||
|             }, |             }, | ||||||
|             columns: [ |             columns: [ | ||||||
|                 { |                 { | ||||||
| @@ -611,7 +611,7 @@ | |||||||
|                 '{% url "api-part-detail" part.pk %}', |                 '{% url "api-part-detail" part.pk %}', | ||||||
|                 { |                 { | ||||||
|                     method: 'PATCH', |                     method: 'PATCH', | ||||||
|                     title: '{% trans "Download Image" %}', |                     title: '{% jstrans "Download Image" %}', | ||||||
|                     fields: { |                     fields: { | ||||||
|                         remote_image: {}, |                         remote_image: {}, | ||||||
|                     }, |                     }, | ||||||
| @@ -673,13 +673,13 @@ | |||||||
|  |  | ||||||
|     // Callback function when the "part details" panel is shown |     // Callback function when the "part details" panel is shown | ||||||
|     $('#collapse-part-details').on('show.bs.collapse', function() { |     $('#collapse-part-details').on('show.bs.collapse', function() { | ||||||
|         $('#toggle-details-button').html('{% trans "Hide Part Details" %}'); |         $('#toggle-details-button').html('{% jstrans "Hide Part Details" %}'); | ||||||
|         inventreeSave('show-part-details', true); |         inventreeSave('show-part-details', true); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // Callback function when the "part details" panel is hidden |     // Callback function when the "part details" panel is hidden | ||||||
|     $('#collapse-part-details').on('hide.bs.collapse', function() { |     $('#collapse-part-details').on('hide.bs.collapse', function() { | ||||||
|         $('#toggle-details-button').html('{% trans "Show Part Details" %}'); |         $('#toggle-details-button').html('{% jstrans "Show Part Details" %}'); | ||||||
|         inventreeSave('show-part-details', false); |         inventreeSave('show-part-details', false); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ $('#part-pricing-refresh').click(function() { | |||||||
|  |  | ||||||
| $('#part-pricing-edit').click(function() { | $('#part-pricing-edit').click(function() { | ||||||
|     constructForm('{% url "api-part-pricing" part.pk %}', { |     constructForm('{% url "api-part-pricing" part.pk %}', { | ||||||
|         title: '{% trans "Update Pricing" %}', |         title: '{% jstrans "Update Pricing" %}', | ||||||
|         fields: { |         fields: { | ||||||
|             override_min: {}, |             override_min: {}, | ||||||
|             override_min_currency: {}, |             override_min_currency: {}, | ||||||
|   | |||||||
| @@ -276,7 +276,7 @@ | |||||||
|                         }, |                         }, | ||||||
|                         multi_delete: true, |                         multi_delete: true, | ||||||
|                         method: 'DELETE', |                         method: 'DELETE', | ||||||
|                         title: '{% trans "Delete Test Data" %}', |                         title: '{% jstrans "Delete Test Data" %}', | ||||||
|                         preFormContent: html, |                         preFormContent: html, | ||||||
|                         refreshTable: '#test-result-table', |                         refreshTable: '#test-result-table', | ||||||
|                     }); |                     }); | ||||||
| @@ -293,7 +293,7 @@ | |||||||
|             fields: stockItemTestResultFields({ |             fields: stockItemTestResultFields({ | ||||||
|                 stock_item: {{ item.pk }}, |                 stock_item: {{ item.pk }}, | ||||||
|             }), |             }), | ||||||
|             title: '{% trans "Add Test Result" %}', |             title: '{% jstrans "Add Test Result" %}', | ||||||
|             refreshTable: '#test-result-table', |             refreshTable: '#test-result-table', | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -504,7 +504,7 @@ $("#stock-test-report").click(function() { | |||||||
| $("#print-label").click(function() { | $("#print-label").click(function() { | ||||||
|     printLabels({ |     printLabels({ | ||||||
|         items: [{{ item.pk }}], |         items: [{{ item.pk }}], | ||||||
|         singular_name: '{% trans "stock item" %}', |         singular_name: '{% jstrans "stock item" %}', | ||||||
|         url: '{% url "api-stockitem-label-list" %}', |         url: '{% url "api-stockitem-label-list" %}', | ||||||
|         key: 'item', |         key: 'item', | ||||||
|     }); |     }); | ||||||
| @@ -529,7 +529,7 @@ $('#stock-edit-status').click(function () { | |||||||
|             status: {}, |             status: {}, | ||||||
|         }, |         }, | ||||||
|         reload: true, |         reload: true, | ||||||
|         title: '{% trans "Edit Stock Status" %}', |         title: '{% jstrans "Edit Stock Status" %}', | ||||||
|     }); |     }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| @@ -538,7 +538,7 @@ $('#stock-edit-status').click(function () { | |||||||
| {% if barcodes %} | {% if barcodes %} | ||||||
| $("#show-qr-code").click(function() { | $("#show-qr-code").click(function() { | ||||||
|     showQRDialog( |     showQRDialog( | ||||||
|         '{% trans "Stock Item QR Code" %}', |         '{% jstrans "Stock Item QR Code" %}', | ||||||
|         '{"stockitem": {{ item.pk }} }', |         '{"stockitem": {{ item.pk }} }', | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -549,7 +549,7 @@ $("#barcode-link").click(function() { | |||||||
|             stockitem: {{ item.pk }}, |             stockitem: {{ item.pk }}, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             title: '{% trans "Link Barcode to Stock Item" %}', |             title: '{% jstrans "Link Barcode to Stock Item" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| }); | }); | ||||||
| @@ -625,7 +625,7 @@ $("#stock-convert").click(function() { | |||||||
|         '{% url "api-stock-item-convert" item.pk %}', |         '{% url "api-stock-item-convert" item.pk %}', | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Convert Stock Item" %}', |             title: '{% jstrans "Convert Stock Item" %}', | ||||||
|             preFormContent: html, |             preFormContent: html, | ||||||
|             reload: true, |             reload: true, | ||||||
|             fields: { |             fields: { | ||||||
| @@ -659,7 +659,7 @@ $("#stock-return-from-customer").click(function() { | |||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Return to Stock" %}', |         title: '{% jstrans "Return to Stock" %}', | ||||||
|         reload: true, |         reload: true, | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -286,7 +286,7 @@ | |||||||
|  |  | ||||||
|         printLabels({ |         printLabels({ | ||||||
|             items: locs, |             items: locs, | ||||||
|             singular_name: '{% trans "stock location" %}', |             singular_name: '{% jstrans "stock location" %}', | ||||||
|             key: 'location', |             key: 'location', | ||||||
|             url: '{% url "api-stocklocation-label-list" %}', |             url: '{% url "api-stocklocation-label-list" %}', | ||||||
|         }); |         }); | ||||||
| @@ -314,7 +314,7 @@ | |||||||
|             { |             { | ||||||
|                 onSuccess: function() { |                 onSuccess: function() { | ||||||
|                     showMessage( |                     showMessage( | ||||||
|                         '{% trans "Scanned stock container into this location" %}', |                         '{% jstrans "Scanned stock container into this location" %}', | ||||||
|                         { |                         { | ||||||
|                             style: 'success', |                             style: 'success', | ||||||
|                         } |                         } | ||||||
| @@ -387,7 +387,7 @@ | |||||||
|     {% if barcodes %} |     {% if barcodes %} | ||||||
|     $('#show-qr-code').click(function() { |     $('#show-qr-code').click(function() { | ||||||
|         showQRDialog( |         showQRDialog( | ||||||
|             '{% trans "Stock Location QR Code" %}', |             '{% jstrans "Stock Location QR Code" %}', | ||||||
|             '{"stocklocation": {{ location.pk }} }' |             '{"stocklocation": {{ location.pk }} }' | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
| @@ -398,7 +398,7 @@ | |||||||
|                 stocklocation: {{ location.pk }}, |                 stocklocation: {{ location.pk }}, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 title: '{% trans "Link Barcode to Stock Location" %}', |                 title: '{% jstrans "Link Barcode to Stock Location" %}', | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -33,10 +33,10 @@ | |||||||
| {% to_list setting_part_starred setting_part_latest setting_bom_validation as settings_list_part %} | {% to_list setting_part_starred setting_part_latest setting_bom_validation as settings_list_part %} | ||||||
|  |  | ||||||
| {% if roles.part.view and True in settings_list_part %} | {% if roles.part.view and True in settings_list_part %} | ||||||
| addHeaderTitle('{% trans "Parts" %}'); | addHeaderTitle('{% jstrans "Parts" %}'); | ||||||
|  |  | ||||||
| {% if setting_part_starred %} | {% if setting_part_starred %} | ||||||
| addHeaderAction('starred-parts', '{% trans "Subscribed Parts" %}', 'fa-bell'); | addHeaderAction('starred-parts', '{% jstrans "Subscribed Parts" %}', 'fa-bell'); | ||||||
| loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", { | loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", { | ||||||
|     name: 'starred-parts', |     name: 'starred-parts', | ||||||
|     params: { |     params: { | ||||||
| @@ -49,7 +49,7 @@ loadSimplePartTable("#table-starred-parts", "{% url 'api-part-list' %}", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_category_starred %} | {% if setting_category_starred %} | ||||||
| addHeaderAction('starred-categories', '{% trans "Subscribed Categories" %}', 'fa-bell'); | addHeaderAction('starred-categories', '{% jstrans "Subscribed Categories" %}', 'fa-bell'); | ||||||
| loadPartCategoryTable($('#table-starred-categories'), { | loadPartCategoryTable($('#table-starred-categories'), { | ||||||
|     params: { |     params: { | ||||||
|         starred: true, |         starred: true, | ||||||
| @@ -59,7 +59,7 @@ loadPartCategoryTable($('#table-starred-categories'), { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_part_latest %} | {% if setting_part_latest %} | ||||||
| addHeaderAction('latest-parts', '{% trans "Latest Parts" %}', 'fa-newspaper'); | addHeaderAction('latest-parts', '{% jstrans "Latest Parts" %}', 'fa-newspaper'); | ||||||
| loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", { | loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", { | ||||||
|     name: 'latest-parts', |     name: 'latest-parts', | ||||||
|     params: { |     params: { | ||||||
| @@ -74,7 +74,7 @@ loadSimplePartTable("#table-latest-parts", "{% url 'api-part-list' %}", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_bom_validation %} | {% if setting_bom_validation %} | ||||||
| addHeaderAction('bom-validation', '{% trans "BOM Waiting Validation" %}', 'fa-times-circle'); | addHeaderAction('bom-validation', '{% jstrans "BOM Waiting Validation" %}', 'fa-times-circle'); | ||||||
| loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", { | loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", { | ||||||
|     name: 'parts-invalid-bom', |     name: 'parts-invalid-bom', | ||||||
|     params: { |     params: { | ||||||
| @@ -103,7 +103,7 @@ loadSimplePartTable("#table-bom-validation", "{% url 'api-part-list' %}", { | |||||||
|  |  | ||||||
| {% if roles.stock.view %} | {% if roles.stock.view %} | ||||||
| {% if setting_stock_recent %} | {% if setting_stock_recent %} | ||||||
| addHeaderAction('recently-updated-stock', '{% trans "Recently Updated" %}', 'fa-clock'); | addHeaderAction('recently-updated-stock', '{% jstrans "Recently Updated" %}', 'fa-clock'); | ||||||
| loadStockTable($('#table-recently-updated-stock'), { | loadStockTable($('#table-recently-updated-stock'), { | ||||||
|     disableFilters: true, |     disableFilters: true, | ||||||
|     params: { |     params: { | ||||||
| @@ -117,7 +117,7 @@ loadStockTable($('#table-recently-updated-stock'), { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_stock_low %} | {% if setting_stock_low %} | ||||||
| addHeaderAction('low-stock', '{% trans "Low Stock" %}', 'fa-flag'); | addHeaderAction('low-stock', '{% jstrans "Low Stock" %}', 'fa-flag'); | ||||||
| loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", { | loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", { | ||||||
|     name: 'parts-low-stock', |     name: 'parts-low-stock', | ||||||
|     params: { |     params: { | ||||||
| @@ -131,7 +131,7 @@ loadSimplePartTable("#table-low-stock", "{% url 'api-part-list' %}", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_stock_depleted %} | {% if setting_stock_depleted %} | ||||||
| addHeaderAction('depleted-stock', '{% trans "Depleted Stock" %}', 'fa-times'); | addHeaderAction('depleted-stock', '{% jstrans "Depleted Stock" %}', 'fa-times'); | ||||||
| loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", { | loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", { | ||||||
|     name: 'parts-depleted-stock', |     name: 'parts-depleted-stock', | ||||||
|     params: { |     params: { | ||||||
| @@ -145,7 +145,7 @@ loadSimplePartTable("#table-depleted-stock", "{% url 'api-part-list' %}", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_stock_needed %} | {% if setting_stock_needed %} | ||||||
| addHeaderAction('stock-to-build', '{% trans "Required for Build Orders" %}', 'fa-bullhorn'); | addHeaderAction('stock-to-build', '{% jstrans "Required for Build Orders" %}', 'fa-bullhorn'); | ||||||
|  |  | ||||||
| loadRequiredForBuildsPartsTable("#table-stock-to-build", {}); | loadRequiredForBuildsPartsTable("#table-stock-to-build", {}); | ||||||
| {% endif %} | {% endif %} | ||||||
| @@ -153,7 +153,7 @@ loadRequiredForBuildsPartsTable("#table-stock-to-build", {}); | |||||||
| {% if expiry %} | {% if expiry %} | ||||||
|  |  | ||||||
| {% if setting_stock_expired %} | {% if setting_stock_expired %} | ||||||
| addHeaderAction('expired-stock', '{% trans "Expired Stock" %}', 'fa-calendar-times'); | addHeaderAction('expired-stock', '{% jstrans "Expired Stock" %}', 'fa-calendar-times'); | ||||||
| loadStockTable($("#table-expired-stock"), { | loadStockTable($("#table-expired-stock"), { | ||||||
|     disableFilters: true, |     disableFilters: true, | ||||||
|     params: { |     params: { | ||||||
| @@ -169,7 +169,7 @@ loadStockTable($("#table-expired-stock"), { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_stock_stale %} | {% if setting_stock_stale %} | ||||||
| addHeaderAction('stale-stock', '{% trans "Stale Stock" %}', 'fa-stopwatch'); | addHeaderAction('stale-stock', '{% jstrans "Stale Stock" %}', 'fa-stopwatch'); | ||||||
| loadStockTable($("#table-stale-stock"), { | loadStockTable($("#table-stale-stock"), { | ||||||
|     disableFilters: true, |     disableFilters: true, | ||||||
|     params: { |     params: { | ||||||
| @@ -193,10 +193,10 @@ loadStockTable($("#table-stale-stock"), { | |||||||
| {% to_list setting_build_pending setting_build_overdue as settings_list_build %} | {% to_list setting_build_pending setting_build_overdue as settings_list_build %} | ||||||
|  |  | ||||||
| {% if roles.build.view and True in settings_list_build %} | {% if roles.build.view and True in settings_list_build %} | ||||||
| addHeaderTitle('{% trans "Build Orders" %}'); | addHeaderTitle('{% jstrans "Build Orders" %}'); | ||||||
|  |  | ||||||
| {% if setting_build_pending %} | {% if setting_build_pending %} | ||||||
| addHeaderAction('build-pending', '{% trans "Build Orders In Progress" %}', 'fa-cogs'); | addHeaderAction('build-pending', '{% jstrans "Build Orders In Progress" %}', 'fa-cogs'); | ||||||
| loadBuildTable("#table-build-pending", { | loadBuildTable("#table-build-pending", { | ||||||
|     locale: '{{ request.LANGUAGE_CODE }}', |     locale: '{{ request.LANGUAGE_CODE }}', | ||||||
|     params: { |     params: { | ||||||
| @@ -207,7 +207,7 @@ loadBuildTable("#table-build-pending", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_build_overdue %} | {% if setting_build_overdue %} | ||||||
| addHeaderAction('build-overdue', '{% trans "Overdue Build Orders" %}', 'fa-calendar-times'); | addHeaderAction('build-overdue', '{% jstrans "Overdue Build Orders" %}', 'fa-calendar-times'); | ||||||
| loadBuildTable("#table-build-overdue", { | loadBuildTable("#table-build-overdue", { | ||||||
|     locale: '{{ request.LANGUAGE_CODE }}', |     locale: '{{ request.LANGUAGE_CODE }}', | ||||||
|     params: { |     params: { | ||||||
| @@ -224,10 +224,10 @@ loadBuildTable("#table-build-overdue", { | |||||||
| {% to_list setting_po_outstanding setting_po_overdue as settings_list_po %} | {% to_list setting_po_outstanding setting_po_overdue as settings_list_po %} | ||||||
|  |  | ||||||
| {% if roles.purchase_order.view and True in settings_list_po %} | {% if roles.purchase_order.view and True in settings_list_po %} | ||||||
| addHeaderTitle('{% trans "Purchase Orders" %}'); | addHeaderTitle('{% jstrans "Purchase Orders" %}'); | ||||||
|  |  | ||||||
| {% if setting_po_outstanding %} | {% if setting_po_outstanding %} | ||||||
| addHeaderAction('po-outstanding', '{% trans "Outstanding Purchase Orders" %}', 'fa-sign-in-alt'); | addHeaderAction('po-outstanding', '{% jstrans "Outstanding Purchase Orders" %}', 'fa-sign-in-alt'); | ||||||
| loadPurchaseOrderTable("#table-po-outstanding", { | loadPurchaseOrderTable("#table-po-outstanding", { | ||||||
|     url: "{% url 'api-po-list' %}", |     url: "{% url 'api-po-list' %}", | ||||||
|     params: { |     params: { | ||||||
| @@ -238,7 +238,7 @@ loadPurchaseOrderTable("#table-po-outstanding", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_po_overdue %} | {% if setting_po_overdue %} | ||||||
| addHeaderAction('po-overdue', '{% trans "Overdue Purchase Orders" %}', 'fa-calendar-times'); | addHeaderAction('po-overdue', '{% jstrans "Overdue Purchase Orders" %}', 'fa-calendar-times'); | ||||||
| loadPurchaseOrderTable("#table-po-overdue", { | loadPurchaseOrderTable("#table-po-overdue", { | ||||||
|     url: "{% url 'api-po-list' %}", |     url: "{% url 'api-po-list' %}", | ||||||
|     params: { |     params: { | ||||||
| @@ -256,10 +256,10 @@ loadPurchaseOrderTable("#table-po-overdue", { | |||||||
| {% to_list setting_so_outstanding setting_so_overdue setting_so_shipments_pending as settings_list_so %} | {% to_list setting_so_outstanding setting_so_overdue setting_so_shipments_pending as settings_list_so %} | ||||||
|  |  | ||||||
| {% if roles.sales_order.view and True in settings_list_so %} | {% if roles.sales_order.view and True in settings_list_so %} | ||||||
| addHeaderTitle('{% trans "Sales Orders" %}'); | addHeaderTitle('{% jstrans "Sales Orders" %}'); | ||||||
|  |  | ||||||
| {% if setting_so_outstanding %} | {% if setting_so_outstanding %} | ||||||
| addHeaderAction('so-outstanding', '{% trans "Outstanding Sales Orders" %}', 'fa-sign-out-alt'); | addHeaderAction('so-outstanding', '{% jstrans "Outstanding Sales Orders" %}', 'fa-sign-out-alt'); | ||||||
| loadSalesOrderTable("#table-so-outstanding", { | loadSalesOrderTable("#table-so-outstanding", { | ||||||
|     url: "{% url 'api-so-list' %}", |     url: "{% url 'api-so-list' %}", | ||||||
|     params: { |     params: { | ||||||
| @@ -270,7 +270,7 @@ loadSalesOrderTable("#table-so-outstanding", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_so_overdue %} | {% if setting_so_overdue %} | ||||||
| addHeaderAction('so-overdue', '{% trans "Overdue Sales Orders" %}', 'fa-calendar-times'); | addHeaderAction('so-overdue', '{% jstrans "Overdue Sales Orders" %}', 'fa-calendar-times'); | ||||||
| loadSalesOrderTable("#table-so-overdue", { | loadSalesOrderTable("#table-so-overdue", { | ||||||
|     url: "{% url 'api-so-list' %}", |     url: "{% url 'api-so-list' %}", | ||||||
|     params: { |     params: { | ||||||
| @@ -281,7 +281,7 @@ loadSalesOrderTable("#table-so-overdue", { | |||||||
| {% endif %} | {% endif %} | ||||||
|  |  | ||||||
| {% if setting_so_shipments_pending %} | {% if setting_so_shipments_pending %} | ||||||
| addHeaderAction('so-shipments', '{% trans "Pending Shipments" %}', 'fa-truck-loading'); | addHeaderAction('so-shipments', '{% jstrans "Pending Shipments" %}', 'fa-truck-loading'); | ||||||
| loadSalesOrderShipmentTable("#table-so-shipments", { | loadSalesOrderShipmentTable("#table-so-shipments", { | ||||||
|     url: "{% url 'api-so-shipment-list' %}", |     url: "{% url 'api-so-shipment-list' %}", | ||||||
|     params: { |     params: { | ||||||
| @@ -296,9 +296,9 @@ loadSalesOrderShipmentTable("#table-so-shipments", { | |||||||
| {% settings_value 'HOMEPAGE_NEWS' user=request.user as setting_news %} | {% settings_value 'HOMEPAGE_NEWS' user=request.user as setting_news %} | ||||||
| {% if setting_news and user.is_staff %} | {% if setting_news and user.is_staff %} | ||||||
|  |  | ||||||
| addHeaderTitle('{% trans "InvenTree News" %}'); | addHeaderTitle('{% jstrans "InvenTree News" %}'); | ||||||
|  |  | ||||||
| addHeaderAction('news', '{% trans "Current News" %}', 'fa-newspaper'); | addHeaderAction('news', '{% jstrans "Current News" %}', 'fa-newspaper'); | ||||||
| loadNewsFeedTable("#table-news", { | loadNewsFeedTable("#table-news", { | ||||||
|     url: "{% url 'api-news-list' %}", |     url: "{% url 'api-news-list' %}", | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ loadNotificationTable("#inbox-table", { | |||||||
|     params: { |     params: { | ||||||
|         read: false, |         read: false, | ||||||
|     }, |     }, | ||||||
|     no_matches: function() { return '{% trans "No unread notifications found" %}'; }, |     no_matches: function() { return '{% jstrans "No unread notifications found" %}'; }, | ||||||
| }); | }); | ||||||
|  |  | ||||||
| $("#mark-all").on('click', function() { | $("#mark-all").on('click', function() { | ||||||
| @@ -55,7 +55,7 @@ $("#mark-all").on('click', function() { | |||||||
| loadNotificationTable("#history-table", { | loadNotificationTable("#history-table", { | ||||||
|     name: 'history', |     name: 'history', | ||||||
|     url: '{% url 'api-notifications-list' %}', |     url: '{% url 'api-notifications-list' %}', | ||||||
|     no_matches: function() { return '{% trans "No notification history found" %}'; }, |     no_matches: function() { return '{% jstrans "No notification history found" %}'; }, | ||||||
| }, true); | }, true); | ||||||
|  |  | ||||||
| $('#history-delete').click(function() { | $('#history-delete').click(function() { | ||||||
| @@ -72,7 +72,7 @@ $('#history-delete').click(function() { | |||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             multi_delete: true, |             multi_delete: true, | ||||||
|             preFormContent: html, |             preFormContent: html, | ||||||
|             title: '{% trans "Delete Notifications" %}', |             title: '{% jstrans "Delete Notifications" %}', | ||||||
|             refreshTable: '#history-table', |             refreshTable: '#history-table', | ||||||
|             form_data: { |             form_data: { | ||||||
|                 filters: { |                 filters: { | ||||||
| @@ -86,7 +86,7 @@ $('#history-delete').click(function() { | |||||||
| $("#history-table").on('click', '.notification-delete', function() { | $("#history-table").on('click', '.notification-delete', function() { | ||||||
|     constructForm(`{% url "api-notifications-list" %}${$(this).attr('pk')}/`, { |     constructForm(`{% url "api-notifications-list" %}${$(this).attr('pk')}/`, { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         title: '{% trans "Delete Notification" %}', |         title: '{% jstrans "Delete Notification" %}', | ||||||
|         onSuccess: function(data) { |         onSuccess: function(data) { | ||||||
|             updateNotificationTables(); |             updateNotificationTables(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -79,9 +79,9 @@ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     {% if roles.part.view %} |     {% if roles.part.view %} | ||||||
|     addItemTitle('{% trans "Part" %}'); |     addItemTitle('{% jstrans "Part" %}'); | ||||||
|  |  | ||||||
|     addItem('part', '{% trans "Parts" %}', 'fa-shapes'); |     addItem('part', '{% jstrans "Parts" %}', 'fa-shapes'); | ||||||
|  |  | ||||||
|     loadPartTable("#table-part", |     loadPartTable("#table-part", | ||||||
|         "{% url 'api-part-list' %}", |         "{% url 'api-part-list' %}", | ||||||
| @@ -94,7 +94,7 @@ | |||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     addItem('category', '{% trans "Part Categories" %}', 'fa-sitemap'); |     addItem('category', '{% jstrans "Part Categories" %}', 'fa-sitemap'); | ||||||
|  |  | ||||||
|     loadPartCategoryTable($("#table-category"), { |     loadPartCategoryTable($("#table-category"), { | ||||||
|         params: { |         params: { | ||||||
| @@ -102,7 +102,7 @@ | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     addItem('manufacturer-part', '{% trans "Manufacturer Parts" %}', 'fa-toolbox'); |     addItem('manufacturer-part', '{% jstrans "Manufacturer Parts" %}', 'fa-toolbox'); | ||||||
|  |  | ||||||
|     loadManufacturerPartTable( |     loadManufacturerPartTable( | ||||||
|         "#table-manufacturer-part", |         "#table-manufacturer-part", | ||||||
| @@ -117,7 +117,7 @@ | |||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     addItem('supplier-part', '{% trans "Supplier Parts" %}', 'fa-pallet'); |     addItem('supplier-part', '{% jstrans "Supplier Parts" %}', 'fa-pallet'); | ||||||
|  |  | ||||||
|     loadSupplierPartTable( |     loadSupplierPartTable( | ||||||
|         "#table-supplier-part", |         "#table-supplier-part", | ||||||
| @@ -136,9 +136,9 @@ | |||||||
|  |  | ||||||
|     {% if roles.build.view %} |     {% if roles.build.view %} | ||||||
|  |  | ||||||
|     addItemTitle('{% trans "Build" %}'); |     addItemTitle('{% jstrans "Build" %}'); | ||||||
|  |  | ||||||
|     addItem('build-order', '{% trans "Build Orders" %}', 'fa-tools'); |     addItem('build-order', '{% jstrans "Build Orders" %}', 'fa-tools'); | ||||||
|  |  | ||||||
|     loadBuildTable('#table-build-order', { |     loadBuildTable('#table-build-order', { | ||||||
|         locale: '{{ request.LANGUAGE_CODE }}', |         locale: '{{ request.LANGUAGE_CODE }}', | ||||||
| @@ -150,9 +150,9 @@ | |||||||
|     {% endif %} |     {% endif %} | ||||||
|  |  | ||||||
|     {% if roles.stock.view %} |     {% if roles.stock.view %} | ||||||
|     addItemTitle('{% trans "Stock" %}'); |     addItemTitle('{% jstrans "Stock" %}'); | ||||||
|  |  | ||||||
|     addItem('stock', '{% trans "Stock Items" %}', 'fa-boxes'); |     addItem('stock', '{% jstrans "Stock Items" %}', 'fa-boxes'); | ||||||
|  |  | ||||||
|     loadStockTable($('#table-stock'), { |     loadStockTable($('#table-stock'), { | ||||||
|         filterKey: 'stocksearch', |         filterKey: 'stocksearch', | ||||||
| @@ -163,7 +163,7 @@ | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     addItem('location', '{% trans "Stock Locations" %}', 'fa-map-marker-alt'); |     addItem('location', '{% jstrans "Stock Locations" %}', 'fa-map-marker-alt'); | ||||||
|  |  | ||||||
|     loadStockLocationTable($("#table-location"), { |     loadStockLocationTable($("#table-location"), { | ||||||
|         filterKey: 'locationsearch', |         filterKey: 'locationsearch', | ||||||
| @@ -175,9 +175,9 @@ | |||||||
|     {% endif %} |     {% endif %} | ||||||
|  |  | ||||||
|     {% if roles.purchase_order.view or roles.sales_order.view %} |     {% if roles.purchase_order.view or roles.sales_order.view %} | ||||||
|     addItemTitle('{% trans "Company" %}'); |     addItemTitle('{% jstrans "Company" %}'); | ||||||
|  |  | ||||||
|     addItem('manufacturer', '{% trans "Manufacturers" %}', 'fa-industry'); |     addItem('manufacturer', '{% jstrans "Manufacturers" %}', 'fa-industry'); | ||||||
|  |  | ||||||
|     loadCompanyTable('#table-manufacturer', "{% url 'api-company-list' %}", { |     loadCompanyTable('#table-manufacturer', "{% url 'api-company-list' %}", { | ||||||
|         params: { |         params: { | ||||||
| @@ -187,7 +187,7 @@ | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     {% if roles.purchase_order.view %} |     {% if roles.purchase_order.view %} | ||||||
|     addItem('supplier', '{% trans "Suppliers" %}', 'fa-building'); |     addItem('supplier', '{% jstrans "Suppliers" %}', 'fa-building'); | ||||||
|  |  | ||||||
|     loadCompanyTable('#table-supplier', "{% url 'api-company-list' %}", { |     loadCompanyTable('#table-supplier', "{% url 'api-company-list' %}", { | ||||||
|         params: { |         params: { | ||||||
| @@ -196,7 +196,7 @@ | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     addItem('purchase-order', '{% trans "Purchase Orders" %}', 'fa-shopping-cart'); |     addItem('purchase-order', '{% jstrans "Purchase Orders" %}', 'fa-shopping-cart'); | ||||||
|  |  | ||||||
|     loadPurchaseOrderTable('#table-purchase-order', { |     loadPurchaseOrderTable('#table-purchase-order', { | ||||||
|         params: { |         params: { | ||||||
| @@ -207,7 +207,7 @@ | |||||||
|     {% endif %} |     {% endif %} | ||||||
|  |  | ||||||
|     {% if roles.sales_order.view %} |     {% if roles.sales_order.view %} | ||||||
|     addItem('customer', '{% trans "Customers" %}', 'fa-user-tie'); |     addItem('customer', '{% jstrans "Customers" %}', 'fa-user-tie'); | ||||||
|  |  | ||||||
|     loadCompanyTable('#table-customer', "{% url 'api-company-list' %}", { |     loadCompanyTable('#table-customer', "{% url 'api-company-list' %}", { | ||||||
|         params: { |         params: { | ||||||
| @@ -216,7 +216,7 @@ | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     addItem('sales-orders', '{% trans "Sales Orders" %}', 'fa-truck'); |     addItem('sales-orders', '{% jstrans "Sales Orders" %}', 'fa-truck'); | ||||||
|  |  | ||||||
|     loadSalesOrderTable('#table-sales-orders', { |     loadSalesOrderTable('#table-sales-orders', { | ||||||
|         params: { |         params: { | ||||||
|   | |||||||
| @@ -55,14 +55,14 @@ $('table').find('.btn-edit-setting').click(function() { | |||||||
|     var title = ''; |     var title = ''; | ||||||
|  |  | ||||||
|     if (plugin != null) { |     if (plugin != null) { | ||||||
|         title = '{% trans "Edit Plugin Setting" %}'; |         title = '{% jstrans "Edit Plugin Setting" %}'; | ||||||
|     } else if (notification) { |     } else if (notification) { | ||||||
|         title = '{% trans "Edit Notification Setting" %}'; |         title = '{% jstrans "Edit Notification Setting" %}'; | ||||||
|         setting = $(this).attr('pk'); |         setting = $(this).attr('pk'); | ||||||
|     } else if (is_global) { |     } else if (is_global) { | ||||||
|         title = '{% trans "Edit Global Setting" %}'; |         title = '{% jstrans "Edit Global Setting" %}'; | ||||||
|     } else { |     } else { | ||||||
|         title = '{% trans "Edit User Setting" %}'; |         title = '{% jstrans "Edit User Setting" %}'; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     editSetting(setting, { |     editSetting(setting, { | ||||||
|   | |||||||
| @@ -41,12 +41,12 @@ onPanelLoad('pricing', function() { | |||||||
|             { |             { | ||||||
|                 field: 'currency', |                 field: 'currency', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Currency" %}', |                 title: '{% jstrans "Currency" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'rate', |                 field: 'rate', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Rate" %}', |                 title: '{% jstrans "Rate" %}', | ||||||
|             } |             } | ||||||
|         ] |         ] | ||||||
|     }); |     }); | ||||||
| @@ -64,21 +64,21 @@ onPanelLoad('units', function() { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 title: '{% trans "Name" %}', |                 title: '{% jstrans "Name" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'definition', |                 field: 'definition', | ||||||
|                 title: '{% trans "Definition" %}', |                 title: '{% jstrans "Definition" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'symbol', |                 field: 'symbol', | ||||||
|                 title: '{% trans "Symbol" %}', |                 title: '{% jstrans "Symbol" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = value; |                     let html = value; | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|  |  | ||||||
|                     buttons += makeEditButton('button-units-edit', row.pk, '{% trans "Edit" %}'); |                     buttons += makeEditButton('button-units-edit', row.pk, '{% jstrans "Edit" %}'); | ||||||
|                     buttons += makeDeleteButton('button-units-delete', row.pk, '{% trans "Delete" %}'); |                     buttons += makeDeleteButton('button-units-delete', row.pk, '{% jstrans "Delete" %}'); | ||||||
|  |  | ||||||
|                     html += wrapButtons(buttons); |                     html += wrapButtons(buttons); | ||||||
|                     return html; |                     return html; | ||||||
| @@ -92,7 +92,7 @@ onPanelLoad('units', function() { | |||||||
|         let pk = $(this).attr('pk'); |         let pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`{% url "api-custom-unit-list" %}${pk}/`, { |         constructForm(`{% url "api-custom-unit-list" %}${pk}/`, { | ||||||
|             title: '{% trans "Edit Custom Unit" %}', |             title: '{% jstrans "Edit Custom Unit" %}', | ||||||
|             fields: { |             fields: { | ||||||
|                 name: {}, |                 name: {}, | ||||||
|                 definition: {}, |                 definition: {}, | ||||||
| @@ -107,7 +107,7 @@ onPanelLoad('units', function() { | |||||||
|         let pk = $(this).attr('pk'); |         let pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`{% url "api-custom-unit-list" %}${pk}/`, { |         constructForm(`{% url "api-custom-unit-list" %}${pk}/`, { | ||||||
|             title: '{% trans "Delete Custom Unit" %}', |             title: '{% jstrans "Delete Custom Unit" %}', | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             refreshTable: '#physical-units-table', |             refreshTable: '#physical-units-table', | ||||||
|         }); |         }); | ||||||
| @@ -121,7 +121,7 @@ onPanelLoad('units', function() { | |||||||
|                 definition: {}, |                 definition: {}, | ||||||
|                 symbol: {}, |                 symbol: {}, | ||||||
|             }, |             }, | ||||||
|             title: '{% trans "New Custom Unit" %}', |             title: '{% jstrans "New Custom Unit" %}', | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             refreshTable: '#physical-units-table', |             refreshTable: '#physical-units-table', | ||||||
|         }); |         }); | ||||||
| @@ -137,17 +137,17 @@ onPanelLoad('project-codes', function() { | |||||||
|         search: true, |         search: true, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No project codes found" %}'; |             return '{% jstrans "No project codes found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'code', |                 field: 'code', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Project Code" %}', |                 title: '{% jstrans "Project Code" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'responsible', |                 field: 'responsible', | ||||||
|                 title: '{% trans "Responsible" %}', |                 title: '{% jstrans "Responsible" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (!row.responsible_detail) { |                     if (!row.responsible_detail) { | ||||||
|                         return '-'; |                         return '-'; | ||||||
| @@ -155,7 +155,7 @@ onPanelLoad('project-codes', function() { | |||||||
|  |  | ||||||
|                     var html = row.responsible_detail.name; |                     var html = row.responsible_detail.name; | ||||||
|  |  | ||||||
|                     if (row.responsible_detail.label == '{% trans "group" %}') { |                     if (row.responsible_detail.label == '{% jstrans "group" %}') { | ||||||
|                         html += `<span class='float-right fas fa-users'></span>`; |                         html += `<span class='float-right fas fa-users'></span>`; | ||||||
|                     } else { |                     } else { | ||||||
|                         html += `<span class='float-right fas fa-user'></span>`; |                         html += `<span class='float-right fas fa-user'></span>`; | ||||||
| @@ -167,13 +167,13 @@ onPanelLoad('project-codes', function() { | |||||||
|             { |             { | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = value; |                     let html = value; | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|  |  | ||||||
|                     buttons += makeEditButton('button-project-code-edit', row.pk, '{% trans "Edit Project Code" %}'); |                     buttons += makeEditButton('button-project-code-edit', row.pk, '{% jstrans "Edit Project Code" %}'); | ||||||
|                     buttons += makeDeleteButton('button-project-code-delete', row.pk, '{% trans "Delete Project Code" %}'); |                     buttons += makeDeleteButton('button-project-code-delete', row.pk, '{% jstrans "Delete Project Code" %}'); | ||||||
|  |  | ||||||
|                     html += wrapButtons(buttons); |                     html += wrapButtons(buttons); | ||||||
|                     return html; |                     return html; | ||||||
| @@ -186,7 +186,7 @@ onPanelLoad('project-codes', function() { | |||||||
|         let pk = $(this).attr('pk'); |         let pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`{% url "api-project-code-list" %}${pk}/`, { |         constructForm(`{% url "api-project-code-list" %}${pk}/`, { | ||||||
|             title: '{% trans "Edit Project Code" %}', |             title: '{% jstrans "Edit Project Code" %}', | ||||||
|             fields: { |             fields: { | ||||||
|                 code: {}, |                 code: {}, | ||||||
|                 description: {}, |                 description: {}, | ||||||
| @@ -200,7 +200,7 @@ onPanelLoad('project-codes', function() { | |||||||
|         let pk = $(this).attr('pk'); |         let pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`{% url "api-project-code-list" %}${pk}/`, { |         constructForm(`{% url "api-project-code-list" %}${pk}/`, { | ||||||
|             title: '{% trans "Delete Project Code" %}', |             title: '{% jstrans "Delete Project Code" %}', | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             refreshTable: '#project-code-table', |             refreshTable: '#project-code-table', | ||||||
|         }); |         }); | ||||||
| @@ -213,7 +213,7 @@ onPanelLoad('project-codes', function() { | |||||||
|                 code: {}, |                 code: {}, | ||||||
|                 description: {}, |                 description: {}, | ||||||
|             }, |             }, | ||||||
|             title: '{% trans "New Project Code" %}', |             title: '{% jstrans "New Project Code" %}', | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             refreshTable: '#project-code-table', |             refreshTable: '#project-code-table', | ||||||
|         }); |         }); | ||||||
| @@ -282,7 +282,7 @@ onPanelLoad('category', function() { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     $('#cat-param-table').inventreeTable({ |     $('#cat-param-table').inventreeTable({ | ||||||
|         formatNoMatches: function() { return '{% trans "No category parameter templates found" %}'; }, |         formatNoMatches: function() { return '{% jstrans "No category parameter templates found" %}'; }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'pk', |                 field: 'pk', | ||||||
| @@ -292,21 +292,21 @@ onPanelLoad('category', function() { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'parameter_template_detail.name', |                 field: 'parameter_template_detail.name', | ||||||
|                 title: '{% trans "Parameter Template" %}', |                 title: '{% jstrans "Parameter Template" %}', | ||||||
|                 sortable: 'true', |                 sortable: 'true', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'category_detail.pathstring', |                 field: 'category_detail.pathstring', | ||||||
|                 title: '{% trans "Category" %}', |                 title: '{% jstrans "Category" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'default_value', |                 field: 'default_value', | ||||||
|                 title: '{% trans "Default Value" %}', |                 title: '{% jstrans "Default Value" %}', | ||||||
|                 sortable: 'true', |                 sortable: 'true', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|                     buttons += makeEditButton('template-edit', row.pk, '{% trans "Edit Template" %}'); |                     buttons += makeEditButton('template-edit', row.pk, '{% jstrans "Edit Template" %}'); | ||||||
|                     buttons += makeDeleteButton('template-delete', row.pk, '{% trans "Delete Template" %}'); |                     buttons += makeDeleteButton('template-delete', row.pk, '{% jstrans "Delete Template" %}'); | ||||||
|  |  | ||||||
|                     let html = value |                     let html = value | ||||||
|                     html += wrapButtons(buttons); |                     html += wrapButtons(buttons); | ||||||
| @@ -323,7 +323,7 @@ onPanelLoad('category', function() { | |||||||
|         var pk = $(this).attr('pk'); |         var pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`/api/part/category/parameters/${pk}/`, { |         constructForm(`/api/part/category/parameters/${pk}/`, { | ||||||
|             title: '{% trans "Edit Category Parameter Template" %}', |             title: '{% jstrans "Edit Category Parameter Template" %}', | ||||||
|             fields: { |             fields: { | ||||||
|                 parameter_template: {}, |                 parameter_template: {}, | ||||||
|                 category: { |                 category: { | ||||||
| @@ -350,7 +350,7 @@ onPanelLoad('category', function() { | |||||||
|  |  | ||||||
|         constructForm(`/api/part/category/parameters/${pk}/`, { |         constructForm(`/api/part/category/parameters/${pk}/`, { | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             title: '{% trans "Delete Category Parameter Template" %}', |             title: '{% jstrans "Delete Category Parameter Template" %}', | ||||||
|             onSuccess: function() { |             onSuccess: function() { | ||||||
|                 loadTemplateTable(pk); |                 loadTemplateTable(pk); | ||||||
|             } |             } | ||||||
| @@ -385,7 +385,7 @@ onPanelLoad('category', function() { | |||||||
|         var pk = $('#category-select').val(); |         var pk = $('#category-select').val(); | ||||||
|  |  | ||||||
|         constructForm('{% url "api-part-category-parameter-list" %}', { |         constructForm('{% url "api-part-category-parameter-list" %}', { | ||||||
|             title: '{% trans "Create Category Parameter Template" %}', |             title: '{% jstrans "Create Category Parameter Template" %}', | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             fields: { |             fields: { | ||||||
|                 parameter_template: {}, |                 parameter_template: {}, | ||||||
| @@ -415,7 +415,7 @@ onPanelLoad('part-parameters', function() { | |||||||
|         constructForm('{% url "api-part-parameter-template-list" %}', { |         constructForm('{% url "api-part-parameter-template-list" %}', { | ||||||
|             fields: partParameterTemplateFields(), |             fields: partParameterTemplateFields(), | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Create Part Parameter Template" %}', |             title: '{% jstrans "Create Part Parameter Template" %}', | ||||||
|             refreshTable: '#param-table', |             refreshTable: '#param-table', | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -437,34 +437,34 @@ onPanelLoad("stock", function() { | |||||||
|         search: true, |         search: true, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No stock location types found" %}'; |             return '{% jstrans "No stock location types found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Name" %}', |                 title: '{% jstrans "Name" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'icon', |                 field: 'icon', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Icon" %}', |                 title: '{% jstrans "Icon" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'location_count', |                 field: 'location_count', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Location count" %}', |                 title: '{% jstrans "Location count" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = value; |                     let html = value; | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|  |  | ||||||
|                     buttons += makeEditButton('button-location-type-edit', row.pk, '{% trans "Edit Location Type" %}'); |                     buttons += makeEditButton('button-location-type-edit', row.pk, '{% jstrans "Edit Location Type" %}'); | ||||||
|                     buttons += makeDeleteButton('button-location-type-delete', row.pk, '{% trans "Delete Location type" %}'); |                     buttons += makeDeleteButton('button-location-type-delete', row.pk, '{% jstrans "Delete Location type" %}'); | ||||||
|  |  | ||||||
|                     html += wrapButtons(buttons); |                     html += wrapButtons(buttons); | ||||||
|                     return html; |                     return html; | ||||||
| @@ -477,7 +477,7 @@ onPanelLoad("stock", function() { | |||||||
|         let pk = $(this).attr('pk'); |         let pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`{% url "api-location-type-list" %}${pk}/`, { |         constructForm(`{% url "api-location-type-list" %}${pk}/`, { | ||||||
|             title: '{% trans "Edit Location Type" %}', |             title: '{% jstrans "Edit Location Type" %}', | ||||||
|             fields: stockLocationTypeFields(), |             fields: stockLocationTypeFields(), | ||||||
|             refreshTable: '#location-type-table', |             refreshTable: '#location-type-table', | ||||||
|         }); |         }); | ||||||
| @@ -487,7 +487,7 @@ onPanelLoad("stock", function() { | |||||||
|         let pk = $(this).attr('pk'); |         let pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|         constructForm(`{% url "api-location-type-list" %}${pk}/`, { |         constructForm(`{% url "api-location-type-list" %}${pk}/`, { | ||||||
|             title: '{% trans "Delete Location Type" %}', |             title: '{% jstrans "Delete Location Type" %}', | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             refreshTable: '#location-type-table', |             refreshTable: '#location-type-table', | ||||||
|         }); |         }); | ||||||
| @@ -497,7 +497,7 @@ onPanelLoad("stock", function() { | |||||||
|         // Construct a new location type |         // Construct a new location type | ||||||
|         constructForm('{% url "api-location-type-list" %}', { |         constructForm('{% url "api-location-type-list" %}', { | ||||||
|             fields: stockLocationTypeFields(), |             fields: stockLocationTypeFields(), | ||||||
|             title: '{% trans "New Location Type" %}', |             title: '{% jstrans "New Location Type" %}', | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             refreshTable: '#location-type-table', |             refreshTable: '#location-type-table', | ||||||
|         }); |         }); | ||||||
| @@ -526,18 +526,18 @@ onPanelLoad('stocktake', function() { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'report', |                 field: 'report', | ||||||
|                 title: '{% trans "Report" %}', |                 title: '{% jstrans "Report" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return attachmentLink(value); |                     return attachmentLink(value); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'part_count', |                 field: 'part_count', | ||||||
|                 title: '{% trans "Part Count" %}', |                 title: '{% jstrans "Part Count" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'date', |                 field: 'date', | ||||||
|                 title: '{% trans "Date" %}', |                 title: '{% jstrans "Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = renderDate(value); |                     let html = renderDate(value); | ||||||
|   | |||||||
| @@ -215,7 +215,7 @@ | |||||||
|  |  | ||||||
| {% block js_ready %} | {% block js_ready %} | ||||||
| (function() { | (function() { | ||||||
| var message = "{% trans 'Do you really want to remove the selected email address?' %}"; | var message = "{% jstrans 'Do you really want to remove the selected email address?' %}"; | ||||||
| var actions = document.getElementsByName('action_remove'); | var actions = document.getElementsByName('action_remove'); | ||||||
| if (actions.length) { | if (actions.length) { | ||||||
| actions[0].addEventListener("click", function(e) { | actions[0].addEventListener("click", function(e) { | ||||||
|   | |||||||
| @@ -222,48 +222,48 @@ function showApiError(xhr, url) { | |||||||
|     switch (xhr.status || 0) { |     switch (xhr.status || 0) { | ||||||
|     // No response |     // No response | ||||||
|     case 0: |     case 0: | ||||||
|         title = '{% trans "No Response" %}'; |         title = '{% jstrans "No Response" %}'; | ||||||
|         message = '{% trans "No response from the InvenTree server" %}'; |         message = '{% jstrans "No response from the InvenTree server" %}'; | ||||||
|         break; |         break; | ||||||
|     // Bad request |     // Bad request | ||||||
|     case 400: |     case 400: | ||||||
|         // Note: Normally error code 400 is handled separately, |         // Note: Normally error code 400 is handled separately, | ||||||
|         //       and should now be shown here! |         //       and should now be shown here! | ||||||
|         title = '{% trans "Error 400: Bad request" %}'; |         title = '{% jstrans "Error 400: Bad request" %}'; | ||||||
|         message = '{% trans "API request returned error code 400" %}'; |         message = '{% jstrans "API request returned error code 400" %}'; | ||||||
|         break; |         break; | ||||||
|     // Not authenticated |     // Not authenticated | ||||||
|     case 401: |     case 401: | ||||||
|         title = '{% trans "Error 401: Not Authenticated" %}'; |         title = '{% jstrans "Error 401: Not Authenticated" %}'; | ||||||
|         message = '{% trans "Authentication credentials not supplied" %}'; |         message = '{% jstrans "Authentication credentials not supplied" %}'; | ||||||
|         break; |         break; | ||||||
|     // Permission denied |     // Permission denied | ||||||
|     case 403: |     case 403: | ||||||
|         title = '{% trans "Error 403: Permission Denied" %}'; |         title = '{% jstrans "Error 403: Permission Denied" %}'; | ||||||
|         message = '{% trans "You do not have the required permissions to access this function" %}'; |         message = '{% jstrans "You do not have the required permissions to access this function" %}'; | ||||||
|         break; |         break; | ||||||
|     // Resource not found |     // Resource not found | ||||||
|     case 404: |     case 404: | ||||||
|         title = '{% trans "Error 404: Resource Not Found" %}'; |         title = '{% jstrans "Error 404: Resource Not Found" %}'; | ||||||
|         message = '{% trans "The requested resource could not be located on the server" %}'; |         message = '{% jstrans "The requested resource could not be located on the server" %}'; | ||||||
|         break; |         break; | ||||||
|     // Method not allowed |     // Method not allowed | ||||||
|     case 405: |     case 405: | ||||||
|         title = '{% trans "Error 405: Method Not Allowed" %}'; |         title = '{% jstrans "Error 405: Method Not Allowed" %}'; | ||||||
|         message = '{% trans "HTTP method not allowed at URL" %}'; |         message = '{% jstrans "HTTP method not allowed at URL" %}'; | ||||||
|         break; |         break; | ||||||
|     // Timeout |     // Timeout | ||||||
|     case 408: |     case 408: | ||||||
|         title = '{% trans "Error 408: Timeout" %}'; |         title = '{% jstrans "Error 408: Timeout" %}'; | ||||||
|         message = '{% trans "Connection timeout while requesting data from server" %}'; |         message = '{% jstrans "Connection timeout while requesting data from server" %}'; | ||||||
|         break; |         break; | ||||||
|     case 503: |     case 503: | ||||||
|         title = '{% trans "Error 503: Service Unavailable" %}'; |         title = '{% jstrans "Error 503: Service Unavailable" %}'; | ||||||
|         message = '{% trans "The server is currently unavailable" %}'; |         message = '{% jstrans "The server is currently unavailable" %}'; | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         title = '{% trans "Unhandled Error Code" %}'; |         title = '{% jstrans "Unhandled Error Code" %}'; | ||||||
|         message = `{% trans "Error code" %}: ${xhr.status}`; |         message = `{% jstrans "Error code" %}: ${xhr.status}`; | ||||||
|  |  | ||||||
|         var response = xhr.responseJSON; |         var response = xhr.responseJSON; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ function addAttachmentButtonCallbacks(url, fields={}) { | |||||||
|             fields: file_fields, |             fields: file_fields, | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             refreshTable: '#attachment-table', |             refreshTable: '#attachment-table', | ||||||
|             title: '{% trans "Add Attachment" %}', |             title: '{% jstrans "Add Attachment" %}', | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
| @@ -67,7 +67,7 @@ function addAttachmentButtonCallbacks(url, fields={}) { | |||||||
|             fields: link_fields, |             fields: link_fields, | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             refreshTable: '#attachment-table', |             refreshTable: '#attachment-table', | ||||||
|             title: '{% trans "Add Link" %}', |             title: '{% jstrans "Add Link" %}', | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -111,13 +111,13 @@ function deleteAttachments(attachments, url, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected attachments will be deleted" %} |     {% jstrans "All selected attachments will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|     <tr> |     <tr> | ||||||
|         <th></th> |         <th></th> | ||||||
|         <th>{% trans "Attachment" %}</th> |         <th>{% jstrans "Attachment" %}</th> | ||||||
|         <th>{% trans "Comment" %}</th> |         <th>{% jstrans "Comment" %}</th> | ||||||
|     </tr> |     </tr> | ||||||
|     ${rows} |     ${rows} | ||||||
|     </table> |     </table> | ||||||
| @@ -126,7 +126,7 @@ function deleteAttachments(attachments, url, options={}) { | |||||||
|     constructForm(url, { |     constructForm(url, { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete Attachments" %}', |         title: '{% jstrans "Delete Attachments" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
| @@ -202,7 +202,7 @@ function makeAttachmentActions(permissions, options) { | |||||||
|         actions.push({ |         actions.push({ | ||||||
|             label: 'delete', |             label: 'delete', | ||||||
|             icon: 'fa-trash-alt icon-red', |             icon: 'fa-trash-alt icon-red', | ||||||
|             title: '{% trans "Delete attachments" %}', |             title: '{% jstrans "Delete attachments" %}', | ||||||
|             callback: options.callback, |             callback: options.callback, | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @@ -250,7 +250,7 @@ function loadAttachmentTable(url, options) { | |||||||
|             { |             { | ||||||
|                 label: 'attachments', |                 label: 'attachments', | ||||||
|                 icon: 'fa-tools', |                 icon: 'fa-tools', | ||||||
|                 title: '{% trans "Attachment actions" %}', |                 title: '{% jstrans "Attachment actions" %}', | ||||||
|                 actions: makeAttachmentActions(permissions, { |                 actions: makeAttachmentActions(permissions, { | ||||||
|                     callback: function(attachments) { |                     callback: function(attachments) { | ||||||
|                         deleteAttachments(attachments, url, options); |                         deleteAttachments(attachments, url, options); | ||||||
| @@ -272,7 +272,7 @@ function loadAttachmentTable(url, options) { | |||||||
|         url: url, |         url: url, | ||||||
|         name: options.name || 'attachments', |         name: options.name || 'attachments', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No attachments found" %}'; |             return '{% jstrans "No attachments found" %}'; | ||||||
|         }, |         }, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         search: true, |         search: true, | ||||||
| @@ -312,7 +312,7 @@ function loadAttachmentTable(url, options) { | |||||||
|                             } |                             } | ||||||
|                         }, |                         }, | ||||||
|                         refreshTable: '#attachment-table', |                         refreshTable: '#attachment-table', | ||||||
|                         title: '{% trans "Edit Attachment" %}', |                         title: '{% jstrans "Edit Attachment" %}', | ||||||
|                     }); |                     }); | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
| @@ -323,7 +323,7 @@ function loadAttachmentTable(url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'attachment', |                 field: 'attachment', | ||||||
|                 title: '{% trans "Attachment" %}', |                 title: '{% jstrans "Attachment" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     if (row.attachment) { |                     if (row.attachment) { | ||||||
| @@ -338,12 +338,12 @@ function loadAttachmentTable(url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'comment', |                 field: 'comment', | ||||||
|                 title: '{% trans "Comment" %}', |                 title: '{% jstrans "Comment" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'upload_date', |                 field: 'upload_date', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Upload Date" %}', |                 title: '{% jstrans "Upload Date" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = renderDate(value); |                     var html = renderDate(value); | ||||||
|  |  | ||||||
| @@ -363,7 +363,7 @@ function loadAttachmentTable(url, options) { | |||||||
|                         buttons += makeEditButton( |                         buttons += makeEditButton( | ||||||
|                             'button-attachment-edit', |                             'button-attachment-edit', | ||||||
|                             row.pk, |                             row.pk, | ||||||
|                             '{% trans "Edit attachment" %}', |                             '{% jstrans "Edit attachment" %}', | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -371,7 +371,7 @@ function loadAttachmentTable(url, options) { | |||||||
|                         buttons += makeDeleteButton( |                         buttons += makeDeleteButton( | ||||||
|                             'button-attachment-delete', |                             'button-attachment-delete', | ||||||
|                             row.pk, |                             row.pk, | ||||||
|                             '{% trans "Delete attachment" %}', |                             '{% jstrans "Delete attachment" %}', | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,23 +40,23 @@ var barcodeInputTimer = null; | |||||||
|  */ |  */ | ||||||
| function makeBarcodeInput(placeholderText='', hintText='') { | function makeBarcodeInput(placeholderText='', hintText='') { | ||||||
|  |  | ||||||
|     placeholderText = placeholderText || '{% trans "Scan barcode data here using barcode scanner" %}'; |     placeholderText = placeholderText || '{% jstrans "Scan barcode data here using barcode scanner" %}'; | ||||||
|  |  | ||||||
|     hintText = hintText || '{% trans "Enter barcode data" %}'; |     hintText = hintText || '{% jstrans "Enter barcode data" %}'; | ||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div id='barcode_scan_video_container' class="mx-auto" style='width: 100%; max-width: 240px; display: none;'> |     <div id='barcode_scan_video_container' class="mx-auto" style='width: 100%; max-width: 240px; display: none;'> | ||||||
|         <div id="barcode_scan_video"></div> |         <div id="barcode_scan_video"></div> | ||||||
|     </div> |     </div> | ||||||
|     <div class='form-group'> |     <div class='form-group'> | ||||||
|         <label class='control-label' for='barcode'>{% trans "Barcode" %}</label> |         <label class='control-label' for='barcode'>{% jstrans "Barcode" %}</label> | ||||||
|         <div class='controls'> |         <div class='controls'> | ||||||
|             <div class='input-group'> |             <div class='input-group'> | ||||||
|                 <span class='input-group-text'> |                 <span class='input-group-text'> | ||||||
|                     ${makeIcon('fa-qrcode')} |                     ${makeIcon('fa-qrcode')} | ||||||
|                 </span> |                 </span> | ||||||
|                 <input id='barcode' class='textinput textInput form-control' type='text' name='barcode' placeholder='${placeholderText}'> |                 <input id='barcode' class='textinput textInput form-control' type='text' name='barcode' placeholder='${placeholderText}'> | ||||||
|                 <button title='{% trans "Scan barcode using connected webcam" %}' id='barcode_scan_btn' type='button' class='btn btn-secondary' onclick='onBarcodeScanClicked()' style='display: none;'> |                 <button title='{% jstrans "Scan barcode using connected webcam" %}' id='barcode_scan_btn' type='button' class='btn btn-secondary' onclick='onBarcodeScanClicked()' style='display: none;'> | ||||||
|                     ${makeIcon('fa-camera')} |                     ${makeIcon('fa-camera')} | ||||||
|                 </button> |                 </button> | ||||||
|             </div> |             </div> | ||||||
| @@ -135,12 +135,12 @@ function onBarcodeScanCompleted(result, options) { | |||||||
|  */ |  */ | ||||||
| function makeNotesField(options={}) { | function makeNotesField(options={}) { | ||||||
|  |  | ||||||
|     var tooltip = options.tooltip || '{% trans "Enter optional notes for stock transfer" %}'; |     var tooltip = options.tooltip || '{% jstrans "Enter optional notes for stock transfer" %}'; | ||||||
|     var placeholder = options.placeholder || '{% trans "Enter notes" %}'; |     var placeholder = options.placeholder || '{% jstrans "Enter notes" %}'; | ||||||
|  |  | ||||||
|     return ` |     return ` | ||||||
|     <div class='form-group'> |     <div class='form-group'> | ||||||
|         <label class='control-label' for='notes'>{% trans "Notes" %}</label> |         <label class='control-label' for='notes'>{% jstrans "Notes" %}</label> | ||||||
|         <div class='controls'> |         <div class='controls'> | ||||||
|             <div class='input-group'> |             <div class='input-group'> | ||||||
|                 <span class='input-group-text'> |                 <span class='input-group-text'> | ||||||
| @@ -185,7 +185,7 @@ function postBarcodeData(barcode_data, options={}) { | |||||||
|                     } else { |                     } else { | ||||||
|                         console.error(xhr); |                         console.error(xhr); | ||||||
|                         data = xhr.responseJSON || {}; |                         data = xhr.responseJSON || {}; | ||||||
|                         showBarcodeMessage(modal, data.error || '{% trans "Server error" %}'); |                         showBarcodeMessage(modal, data.error || '{% jstrans "Server error" %}'); | ||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
| @@ -214,7 +214,7 @@ function postBarcodeData(barcode_data, options={}) { | |||||||
|                     } else { |                     } else { | ||||||
|                         showBarcodeMessage( |                         showBarcodeMessage( | ||||||
|                             modal, |                             modal, | ||||||
|                             '{% trans "Unknown response from server" %}', |                             '{% jstrans "Unknown response from server" %}', | ||||||
|                             'warning' |                             'warning' | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
| @@ -249,7 +249,7 @@ function showBarcodeMessage(modal, message, style='danger') { | |||||||
| function showInvalidResponseError(modal, response, status) { | function showInvalidResponseError(modal, response, status) { | ||||||
|     showBarcodeMessage( |     showBarcodeMessage( | ||||||
|         modal, |         modal, | ||||||
|         `{% trans "Invalid server response" %}<br>{% trans "Status" %}: '${status}'` |         `{% jstrans "Invalid server response" %}<br>{% jstrans "Status" %}: '${status}'` | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -369,7 +369,7 @@ function barcodeDialog(title, options={}) { | |||||||
|         modalShowSubmitButton(modal, false); |         modalShowSubmitButton(modal, false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     var details = options.details || '{% trans "Scan barcode data" %}'; |     var details = options.details || '{% jstrans "Scan barcode data" %}'; | ||||||
|  |  | ||||||
|     var content = ''; |     var content = ''; | ||||||
|  |  | ||||||
| @@ -417,7 +417,7 @@ function barcodeDialog(title, options={}) { | |||||||
| function barcodeScanDialog(options={}) { | function barcodeScanDialog(options={}) { | ||||||
|  |  | ||||||
|     let modal = options.modal || createNewModal(); |     let modal = options.modal || createNewModal(); | ||||||
|     let title = options.title || '{% trans "Scan Barcode" %}'; |     let title = options.title || '{% jstrans "Scan Barcode" %}'; | ||||||
|  |  | ||||||
|     const matching_models = [ |     const matching_models = [ | ||||||
|         'build', |         'build', | ||||||
| @@ -455,7 +455,7 @@ function barcodeScanDialog(options={}) { | |||||||
|                     // No match |                     // No match | ||||||
|                     showBarcodeMessage( |                     showBarcodeMessage( | ||||||
|                         modal, |                         modal, | ||||||
|                         '{% trans "No URL in response" %}', |                         '{% jstrans "No URL in response" %}', | ||||||
|                         'warning' |                         'warning' | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
| @@ -493,15 +493,15 @@ function linkBarcodeDialog(data, options={}) { | |||||||
|  */ |  */ | ||||||
| function unlinkBarcode(data, options={}) { | function unlinkBarcode(data, options={}) { | ||||||
|  |  | ||||||
|     var html = `<b>{% trans "Unlink Barcode" %}</b><br>`; |     var html = `<b>{% jstrans "Unlink Barcode" %}</b><br>`; | ||||||
|  |  | ||||||
|     html += '{% trans "This will remove the link to the associated barcode" %}'; |     html += '{% jstrans "This will remove the link to the associated barcode" %}'; | ||||||
|  |  | ||||||
|     showQuestionDialog( |     showQuestionDialog( | ||||||
|         '{% trans "Unlink Barcode" %}', |         '{% jstrans "Unlink Barcode" %}', | ||||||
|         html, |         html, | ||||||
|         { |         { | ||||||
|             accept_text: '{% trans "Unlink" %}', |             accept_text: '{% jstrans "Unlink" %}', | ||||||
|             accept: function() { |             accept: function() { | ||||||
|                 inventreePut( |                 inventreePut( | ||||||
|                     '{% url "api-barcode-unlink" %}', |                     '{% url "api-barcode-unlink" %}', | ||||||
| @@ -543,9 +543,9 @@ function barcodeCheckInStockItems(location_id, options={}) { | |||||||
|         <table class='table table-condensed table-striped' id='items-table'> |         <table class='table table-condensed table-striped' id='items-table'> | ||||||
|             <thead> |             <thead> | ||||||
|                 <tr> |                 <tr> | ||||||
|                     <th>{% trans "Part" %}</th> |                     <th>{% jstrans "Part" %}</th> | ||||||
|                     <th>{% trans "Location" %}</th> |                     <th>{% jstrans "Location" %}</th> | ||||||
|                     <th>{% trans "Quantity" %}</th> |                     <th>{% jstrans "Quantity" %}</th> | ||||||
|                     <th></th> |                     <th></th> | ||||||
|                 </tr> |                 </tr> | ||||||
|             </thead> |             </thead> | ||||||
| @@ -564,7 +564,7 @@ function barcodeCheckInStockItems(location_id, options={}) { | |||||||
|                 <td>${imageHoverIcon(item.part_detail.thumbnail)} ${item.part_detail.name}</td> |                 <td>${imageHoverIcon(item.part_detail.thumbnail)} ${item.part_detail.name}</td> | ||||||
|                 <td>${location_info}</td> |                 <td>${location_info}</td> | ||||||
|                 <td>${item.quantity}</td> |                 <td>${item.quantity}</td> | ||||||
|                 <td>${makeRemoveButton('button-item-remove', item.pk, '{% trans "Remove stock item" %}')}</td> |                 <td>${makeRemoveButton('button-item-remove', item.pk, '{% jstrans "Remove stock item" %}')}</td> | ||||||
|             </tr>`; |             </tr>`; | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| @@ -607,12 +607,12 @@ function barcodeCheckInStockItems(location_id, options={}) { | |||||||
|     var extra = makeNotesField(); |     var extra = makeNotesField(); | ||||||
|  |  | ||||||
|     barcodeDialog( |     barcodeDialog( | ||||||
|         '{% trans "Scan Stock Items Into Location" %}', |         '{% jstrans "Scan Stock Items Into Location" %}', | ||||||
|         { |         { | ||||||
|             details: '{% trans "Scan stock item barcode to check in to this location" %}', |             details: '{% jstrans "Scan stock item barcode to check in to this location" %}', | ||||||
|             headerContent: table, |             headerContent: table, | ||||||
|             preShow: function() { |             preShow: function() { | ||||||
|                 modalSetSubmitText(modal, '{% trans "Check In" %}'); |                 modalSetSubmitText(modal, '{% jstrans "Check In" %}'); | ||||||
|                 modalEnable(modal, false); |                 modalEnable(modal, false); | ||||||
|                 reloadTable(); |                 reloadTable(); | ||||||
|             }, |             }, | ||||||
| @@ -644,7 +644,7 @@ function barcodeCheckInStockItems(location_id, options={}) { | |||||||
|  |  | ||||||
|                 // Prevent submission without any entries |                 // Prevent submission without any entries | ||||||
|                 if (entries.length == 0) { |                 if (entries.length == 0) { | ||||||
|                     showBarcodeMessage(modal, '{% trans "No barcode provided" %}', 'warning'); |                     showBarcodeMessage(modal, '{% jstrans "No barcode provided" %}', 'warning'); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -684,18 +684,18 @@ function barcodeCheckInStockItems(location_id, options={}) { | |||||||
|                                 }); |                                 }); | ||||||
|  |  | ||||||
|                                 if (duplicate) { |                                 if (duplicate) { | ||||||
|                                     showBarcodeMessage(modal, '{% trans "Stock Item already scanned" %}', 'warning'); |                                     showBarcodeMessage(modal, '{% jstrans "Stock Item already scanned" %}', 'warning'); | ||||||
|                                 } else { |                                 } else { | ||||||
|  |  | ||||||
|                                     if (stockitem.location == location_id) { |                                     if (stockitem.location == location_id) { | ||||||
|                                         showBarcodeMessage(modal, '{% trans "Stock Item already in this location" %}'); |                                         showBarcodeMessage(modal, '{% jstrans "Stock Item already in this location" %}'); | ||||||
|                                         return; |                                         return; | ||||||
|                                     } |                                     } | ||||||
|  |  | ||||||
|                                     // Add this stock item to the list |                                     // Add this stock item to the list | ||||||
|                                     items.push(stockitem); |                                     items.push(stockitem); | ||||||
|  |  | ||||||
|                                     showBarcodeMessage(modal, '{% trans "Added stock item" %}', 'success'); |                                     showBarcodeMessage(modal, '{% jstrans "Added stock item" %}', 'success'); | ||||||
|  |  | ||||||
|                                     reloadTable(); |                                     reloadTable(); | ||||||
|                                 } |                                 } | ||||||
| @@ -704,7 +704,7 @@ function barcodeCheckInStockItems(location_id, options={}) { | |||||||
|                     ); |                     ); | ||||||
|                 } else { |                 } else { | ||||||
|                     // Barcode does not match a stock item |                     // Barcode does not match a stock item | ||||||
|                     showBarcodeMessage(modal, '{% trans "Barcode does not match valid stock item" %}', 'warning'); |                     showBarcodeMessage(modal, '{% jstrans "Barcode does not match valid stock item" %}', 'warning'); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|         } |         } | ||||||
| @@ -723,9 +723,9 @@ function barcodeCheckInStockLocations(location_id, options={}) { | |||||||
|     var header = ''; |     var header = ''; | ||||||
|  |  | ||||||
|     barcodeDialog( |     barcodeDialog( | ||||||
|         '{% trans "Scan Stock Container Into Location" %}', |         '{% jstrans "Scan Stock Container Into Location" %}', | ||||||
|         { |         { | ||||||
|             details: '{% trans "Scan stock container barcode to check in to this location" %}', |             details: '{% jstrans "Scan stock container barcode to check in to this location" %}', | ||||||
|             headerContent: header, |             headerContent: header, | ||||||
|             preShow: function() { |             preShow: function() { | ||||||
|                 modalEnable(modal, false); |                 modalEnable(modal, false); | ||||||
| @@ -759,7 +759,7 @@ function barcodeCheckInStockLocations(location_id, options={}) { | |||||||
|                     ); |                     ); | ||||||
|                 } else { |                 } else { | ||||||
|                     // Barcode does not match a valid stock location |                     // Barcode does not match a valid stock location | ||||||
|                     showBarcodeMessage(modal, '{% trans "Barcode does not match valid stock location" %}', 'warning'); |                     showBarcodeMessage(modal, '{% jstrans "Barcode does not match valid stock location" %}', 'warning'); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -792,7 +792,7 @@ function scanItemsIntoLocation(item_list, options={}) { | |||||||
|         if (location && location.pk) { |         if (location && location.pk) { | ||||||
|             div.html(` |             div.html(` | ||||||
|             <div class='alert alert-block alert-info'> |             <div class='alert alert-block alert-info'> | ||||||
|             <b>{% trans "Location" %}</b></br> |             <b>{% jstrans "Location" %}</b></br> | ||||||
|             ${location.name}<br> |             ${location.name}<br> | ||||||
|             <i>${location.description}</i> |             <i>${location.description}</i> | ||||||
|             </div> |             </div> | ||||||
| @@ -803,13 +803,13 @@ function scanItemsIntoLocation(item_list, options={}) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     barcodeDialog( |     barcodeDialog( | ||||||
|         '{% trans "Check Into Location" %}', |         '{% jstrans "Check Into Location" %}', | ||||||
|         { |         { | ||||||
|             headerContent: header, |             headerContent: header, | ||||||
|             extraFields: extra, |             extraFields: extra, | ||||||
|             modal: modal, |             modal: modal, | ||||||
|             preShow: function() { |             preShow: function() { | ||||||
|                 modalSetSubmitText(modal, '{% trans "Check In" %}'); |                 modalSetSubmitText(modal, '{% jstrans "Check In" %}'); | ||||||
|                 modalEnable(modal, false); |                 modalEnable(modal, false); | ||||||
|             }, |             }, | ||||||
|             onShow: function() { |             onShow: function() { | ||||||
| @@ -872,7 +872,7 @@ function scanItemsIntoLocation(item_list, options={}) { | |||||||
|                             // Barcode does *NOT* correspond to a StockLocation |                             // Barcode does *NOT* correspond to a StockLocation | ||||||
|                             showBarcodeMessage( |                             showBarcodeMessage( | ||||||
|                                 modal, |                                 modal, | ||||||
|                                 '{% trans "Barcode does not match a valid location" %}', |                                 '{% jstrans "Barcode does not match a valid location" %}', | ||||||
|                                 'warning', |                                 'warning', | ||||||
|                             ); |                             ); | ||||||
|                         } |                         } | ||||||
| @@ -881,7 +881,7 @@ function scanItemsIntoLocation(item_list, options={}) { | |||||||
|                     // Barcode does *NOT* correspond to a StockLocation |                     // Barcode does *NOT* correspond to a StockLocation | ||||||
|                     showBarcodeMessage( |                     showBarcodeMessage( | ||||||
|                         modal, |                         modal, | ||||||
|                         '{% trans "Barcode does not match a valid location" %}', |                         '{% jstrans "Barcode does not match a valid location" %}', | ||||||
|                         'warning', |                         'warning', | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ function addBomItem(part_id, options={}) { | |||||||
|     constructForm('{% url "api-bom-list" %}', { |     constructForm('{% url "api-bom-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Create BOM Item" %}', |         title: '{% jstrans "Create BOM Item" %}', | ||||||
|         focus: 'sub_part', |         focus: 'sub_part', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
| @@ -129,8 +129,8 @@ function constructBomUploadTable(data, options={}) { | |||||||
|  |  | ||||||
|         let buttons = ''; |         let buttons = ''; | ||||||
|  |  | ||||||
|         buttons += makeInfoButton('button-row-data', idx, '{% trans "Display row data" %}'); |         buttons += makeInfoButton('button-row-data', idx, '{% jstrans "Display row data" %}'); | ||||||
|         buttons += makeRemoveButton('button-row-remove', idx, '{% trans "Remove row" %}'); |         buttons += makeRemoveButton('button-row-remove', idx, '{% jstrans "Remove row" %}'); | ||||||
|  |  | ||||||
|         buttons = wrapButtons(buttons); |         buttons = wrapButtons(buttons); | ||||||
|  |  | ||||||
| @@ -185,8 +185,8 @@ function constructBomUploadTable(data, options={}) { | |||||||
|         $(`#button-row-data-${idx}`).click(function() { |         $(`#button-row-data-${idx}`).click(function() { | ||||||
|  |  | ||||||
|             var modal = createNewModal({ |             var modal = createNewModal({ | ||||||
|                 title: '{% trans "Row Data" %}', |                 title: '{% jstrans "Row Data" %}', | ||||||
|                 closeText: '{% trans "Close" %}', |                 closeText: '{% jstrans "Close" %}', | ||||||
|                 hideSubmitButton: true |                 hideSubmitButton: true | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
| @@ -303,11 +303,11 @@ function downloadBomTemplate(options={}) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     constructFormBody({}, { |     constructFormBody({}, { | ||||||
|         title: '{% trans "Download BOM Template" %}', |         title: '{% jstrans "Download BOM Template" %}', | ||||||
|         fields: { |         fields: { | ||||||
|             format: { |             format: { | ||||||
|                 label: '{% trans "Format" %}', |                 label: '{% jstrans "Format" %}', | ||||||
|                 help_text: '{% trans "Select file format" %}', |                 help_text: '{% jstrans "Select file format" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|                 type: 'choice', |                 type: 'choice', | ||||||
|                 value: format, |                 value: format, | ||||||
| @@ -337,63 +337,63 @@ function downloadBomTemplate(options={}) { | |||||||
| function exportBom(part_id, options={}) { | function exportBom(part_id, options={}) { | ||||||
|  |  | ||||||
|     constructFormBody({}, { |     constructFormBody({}, { | ||||||
|         title: '{% trans "Export BOM" %}', |         title: '{% jstrans "Export BOM" %}', | ||||||
|         fields: { |         fields: { | ||||||
|             format: { |             format: { | ||||||
|                 label: '{% trans "Format" %}', |                 label: '{% jstrans "Format" %}', | ||||||
|                 help_text: '{% trans "Select file format" %}', |                 help_text: '{% jstrans "Select file format" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|                 type: 'choice', |                 type: 'choice', | ||||||
|                 value: inventreeLoad('bom-export-format', 'csv'), |                 value: inventreeLoad('bom-export-format', 'csv'), | ||||||
|                 choices: exportFormatOptions(), |                 choices: exportFormatOptions(), | ||||||
|             }, |             }, | ||||||
|             cascade: { |             cascade: { | ||||||
|                 label: '{% trans "Multi Level BOM" %}', |                 label: '{% jstrans "Multi Level BOM" %}', | ||||||
|                 help_text: '{% trans "Include BOM data for subassemblies" %}', |                 help_text: '{% jstrans "Include BOM data for subassemblies" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-cascading', true), |                 value: inventreeLoad('bom-export-cascading', true), | ||||||
|             }, |             }, | ||||||
|             levels: { |             levels: { | ||||||
|                 label: '{% trans "Levels" %}', |                 label: '{% jstrans "Levels" %}', | ||||||
|                 help_text: '{% trans "Select maximum number of BOM levels to export (0 = all levels)" %}', |                 help_text: '{% jstrans "Select maximum number of BOM levels to export (0 = all levels)" %}', | ||||||
|                 type: 'integer', |                 type: 'integer', | ||||||
|                 value: 0, |                 value: 0, | ||||||
|                 required: true, |                 required: true, | ||||||
|                 min_value: 0, |                 min_value: 0, | ||||||
|             }, |             }, | ||||||
|             substitute_part_data: { |             substitute_part_data: { | ||||||
|                 label: '{% trans "Include Alternative Parts" %}', |                 label: '{% jstrans "Include Alternative Parts" %}', | ||||||
|                 help_text: '{% trans "Include alternative parts in exported BOM" %}', |                 help_text: '{% jstrans "Include alternative parts in exported BOM" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-substitute_part_data', false), |                 value: inventreeLoad('bom-export-substitute_part_data', false), | ||||||
|             }, |             }, | ||||||
|             parameter_data: { |             parameter_data: { | ||||||
|                 label: '{% trans "Include Parameter Data" %}', |                 label: '{% jstrans "Include Parameter Data" %}', | ||||||
|                 help_text: '{% trans "Include part parameter data in exported BOM" %}', |                 help_text: '{% jstrans "Include part parameter data in exported BOM" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-parameter_data', false), |                 value: inventreeLoad('bom-export-parameter_data', false), | ||||||
|             }, |             }, | ||||||
|             stock_data: { |             stock_data: { | ||||||
|                 label: '{% trans "Include Stock Data" %}', |                 label: '{% jstrans "Include Stock Data" %}', | ||||||
|                 help_text: '{% trans "Include part stock data in exported BOM" %}', |                 help_text: '{% jstrans "Include part stock data in exported BOM" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-stock_data', false), |                 value: inventreeLoad('bom-export-stock_data', false), | ||||||
|             }, |             }, | ||||||
|             manufacturer_data: { |             manufacturer_data: { | ||||||
|                 label: '{% trans "Include Manufacturer Data" %}', |                 label: '{% jstrans "Include Manufacturer Data" %}', | ||||||
|                 help_text: '{% trans "Include part manufacturer data in exported BOM" %}', |                 help_text: '{% jstrans "Include part manufacturer data in exported BOM" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-manufacturer_data', false), |                 value: inventreeLoad('bom-export-manufacturer_data', false), | ||||||
|             }, |             }, | ||||||
|             supplier_data: { |             supplier_data: { | ||||||
|                 label: '{% trans "Include Supplier Data" %}', |                 label: '{% jstrans "Include Supplier Data" %}', | ||||||
|                 help_text: '{% trans "Include part supplier data in exported BOM" %}', |                 help_text: '{% jstrans "Include part supplier data in exported BOM" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-supplier_data', false), |                 value: inventreeLoad('bom-export-supplier_data', false), | ||||||
|             }, |             }, | ||||||
|             pricing_data: { |             pricing_data: { | ||||||
|                 label: '{% trans "Include Pricing Data" %}', |                 label: '{% jstrans "Include Pricing Data" %}', | ||||||
|                 help_text: '{% trans "Include part pricing data in exported BOM" %}', |                 help_text: '{% jstrans "Include part pricing data in exported BOM" %}', | ||||||
|                 type: 'boolean', |                 type: 'boolean', | ||||||
|                 value: inventreeLoad('bom-export-pricing_data', false), |                 value: inventreeLoad('bom-export-pricing_data', false), | ||||||
|             } |             } | ||||||
| @@ -441,7 +441,7 @@ function bomItemFields() { | |||||||
|         sub_part: { |         sub_part: { | ||||||
|             icon: 'fa-shapes', |             icon: 'fa-shapes', | ||||||
|             secondary: { |             secondary: { | ||||||
|                 title: '{% trans "New Part" %}', |                 title: '{% jstrans "New Part" %}', | ||||||
|                 fields: function() { |                 fields: function() { | ||||||
|                     var fields = partFields(); |                     var fields = partFields(); | ||||||
|  |  | ||||||
| @@ -588,7 +588,7 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) { | |||||||
|  |  | ||||||
|         var buttons = ''; |         var buttons = ''; | ||||||
|  |  | ||||||
|         buttons += makeRemoveButton('button-row-remove', pk, '{% trans "Remove substitute part" %}'); |         buttons += makeRemoveButton('button-row-remove', pk, '{% jstrans "Remove substitute part" %}'); | ||||||
|  |  | ||||||
|         // Render a single row |         // Render a single row | ||||||
|         var html = ` |         var html = ` | ||||||
| @@ -619,7 +619,7 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block'> |     <div class='alert alert-block'> | ||||||
|     <strong>{% trans "Base Part" %}</strong><hr> |     <strong>{% jstrans "Base Part" %}</strong><hr> | ||||||
|     ${part_thumb} ${part_name} - <em>${part_desc}</em> |     ${part_thumb} ${part_name} - <em>${part_desc}</em> | ||||||
|     </div> |     </div> | ||||||
|     `; |     `; | ||||||
| @@ -629,8 +629,8 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) { | |||||||
|     <table class='table table-striped table-condensed' id='substitute-table'> |     <table class='table table-striped table-condensed' id='substitute-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>{% trans "Part" %}</th> |                 <th>{% jstrans "Part" %}</th> | ||||||
|                 <th>{% trans "Description" %}</th> |                 <th>{% jstrans "Description" %}</th> | ||||||
|                 <th><!-- Actions --></th> |                 <th><!-- Actions --></th> | ||||||
|             </tr> |             </tr> | ||||||
|         </thead> |         </thead> | ||||||
| @@ -642,7 +642,7 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) { | |||||||
|  |  | ||||||
|     html += ` |     html += ` | ||||||
|     <div class='alert alert-success alert-block'> |     <div class='alert alert-success alert-block'> | ||||||
|         {% trans "Select and add a new substitute part using the input below" %} |         {% jstrans "Select and add a new substitute part using the input below" %} | ||||||
|     </div> |     </div> | ||||||
|     `; |     `; | ||||||
|  |  | ||||||
| @@ -653,13 +653,13 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) { | |||||||
|  |  | ||||||
|             var pre = ` |             var pre = ` | ||||||
|             <div class='alert alert-block alert-warning'> |             <div class='alert alert-block alert-warning'> | ||||||
|             {% trans "Are you sure you wish to remove this substitute part link?" %} |             {% jstrans "Are you sure you wish to remove this substitute part link?" %} | ||||||
|             </div> |             </div> | ||||||
|             `; |             `; | ||||||
|  |  | ||||||
|             constructForm(`{% url "api-bom-substitute-list" %}${pk}/`, { |             constructForm(`{% url "api-bom-substitute-list" %}${pk}/`, { | ||||||
|                 method: 'DELETE', |                 method: 'DELETE', | ||||||
|                 title: '{% trans "Remove Substitute Part" %}', |                 title: '{% jstrans "Remove Substitute Part" %}', | ||||||
|                 preFormContent: pre, |                 preFormContent: pre, | ||||||
|                 confirm: true, |                 confirm: true, | ||||||
|                 onSuccess: function() { |                 onSuccess: function() { | ||||||
| @@ -697,9 +697,9 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) { | |||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         closeText: '{% trans "Close" %}', |         closeText: '{% jstrans "Close" %}', | ||||||
|         submitText: '{% trans "Add Substitute" %}', |         submitText: '{% jstrans "Add Substitute" %}', | ||||||
|         title: '{% trans "Edit BOM Item Substitutes" %}', |         title: '{% jstrans "Edit BOM Item Substitutes" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|             addRemoveCallback(opts.modal, '.button-row-remove'); |             addRemoveCallback(opts.modal, '.button-row-remove'); | ||||||
|         }, |         }, | ||||||
| @@ -761,14 +761,14 @@ function deleteBomItems(items, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected BOM items will be deleted" %} |     {% jstrans "All selected BOM items will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|         <tr> |         <tr> | ||||||
|             <th>{% trans "Part" %}</th> |             <th>{% jstrans "Part" %}</th> | ||||||
|             <th>{% trans "Reference" %}</th> |             <th>{% jstrans "Reference" %}</th> | ||||||
|             <th>{% trans "Quantity" %}</th> |             <th>{% jstrans "Quantity" %}</th> | ||||||
|         </tr> |         </tr> | ||||||
|         ${rows} |         ${rows} | ||||||
|     </table> |     </table> | ||||||
| @@ -777,7 +777,7 @@ function deleteBomItems(items, options={}) { | |||||||
|     constructForm('{% url "api-bom-list"  %}', { |     constructForm('{% url "api-bom-list"  %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete selected BOM items?" %}', |         title: '{% jstrans "Delete selected BOM items?" %}', | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
|         }, |         }, | ||||||
| @@ -823,7 +823,7 @@ function loadBomTable(table, options={}) { | |||||||
|             label: 'actions', |             label: 'actions', | ||||||
|             actions: [{ |             actions: [{ | ||||||
|                 label: 'delete', |                 label: 'delete', | ||||||
|                 title: '{% trans "Delete items" %}', |                 title: '{% jstrans "Delete items" %}', | ||||||
|                 icon: 'fa-trash-alt icon-red', |                 icon: 'fa-trash-alt icon-red', | ||||||
|                 permission: 'part.change', |                 permission: 'part.change', | ||||||
|                 callback: function(data) { |                 callback: function(data) { | ||||||
| @@ -902,7 +902,7 @@ function loadBomTable(table, options={}) { | |||||||
|     cols.push( |     cols.push( | ||||||
|         { |         { | ||||||
|             field: 'sub_part', |             field: 'sub_part', | ||||||
|             title: '{% trans "Part" %}', |             title: '{% jstrans "Part" %}', | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             switchable: false, |             switchable: false, | ||||||
|             sorter: function(_valA, _valB, rowA, rowB) { |             sorter: function(_valA, _valB, rowA, rowB) { | ||||||
| @@ -933,7 +933,7 @@ function loadBomTable(table, options={}) { | |||||||
|                     } else { |                     } else { | ||||||
|                         html += ` |                         html += ` | ||||||
|                             <a href='#' pk='${row.pk}' class='load-sub-assembly' id='load-sub-assembly-${row.pk}'> |                             <a href='#' pk='${row.pk}' class='load-sub-assembly' id='load-sub-assembly-${row.pk}'> | ||||||
|                                 <span class='fas fa-sync-alt' title='{% trans "Load BOM for subassembly" %}'></span> |                                 <span class='fas fa-sync-alt' title='{% jstrans "Load BOM for subassembly" %}'></span> | ||||||
|                             </a> `; |                             </a> `; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @@ -943,11 +943,11 @@ function loadBomTable(table, options={}) { | |||||||
|                 html += makePartIcons(sub_part); |                 html += makePartIcons(sub_part); | ||||||
|  |  | ||||||
|                 if (row.substitutes && row.substitutes.length > 0) { |                 if (row.substitutes && row.substitutes.length > 0) { | ||||||
|                     html += makeIconBadge('fa-exchange-alt', '{% trans "Substitutes Available" %}'); |                     html += makeIconBadge('fa-exchange-alt', '{% jstrans "Substitutes Available" %}'); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (row.allow_variants) { |                 if (row.allow_variants) { | ||||||
|                     html += makeIconBadge('fa-sitemap', '{% trans "Variant stock allowed" %}'); |                     html += makeIconBadge('fa-sitemap', '{% jstrans "Variant stock allowed" %}'); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 return html; |                 return html; | ||||||
| @@ -960,7 +960,7 @@ function loadBomTable(table, options={}) { | |||||||
|     cols.push( |     cols.push( | ||||||
|         { |         { | ||||||
|             field: 'sub_part_detail.description', |             field: 'sub_part_detail.description', | ||||||
|             title: '{% trans "Description" %}', |             title: '{% jstrans "Description" %}', | ||||||
|             formatter: function(value) { |             formatter: function(value) { | ||||||
|                 return withTitle(shortenString(value), value); |                 return withTitle(shortenString(value), value); | ||||||
|             } |             } | ||||||
| @@ -970,7 +970,7 @@ function loadBomTable(table, options={}) { | |||||||
|     // Part reference |     // Part reference | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'reference', |         field: 'reference', | ||||||
|         title: '{% trans "Reference" %}', |         title: '{% jstrans "Reference" %}', | ||||||
|         searchable: true, |         searchable: true, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|     }); |     }); | ||||||
| @@ -978,7 +978,7 @@ function loadBomTable(table, options={}) { | |||||||
|     // Part quantity |     // Part quantity | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'quantity', |         field: 'quantity', | ||||||
|         title: '{% trans "Quantity" %}', |         title: '{% jstrans "Quantity" %}', | ||||||
|         searchable: false, |         searchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false, |         switchable: false, | ||||||
| @@ -994,11 +994,11 @@ function loadBomTable(table, options={}) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (row.consumable) { |             if (row.consumable) { | ||||||
|                 text += ` <small>({% trans "Consumable" %})</small>`; |                 text += ` <small>({% jstrans "Consumable" %})</small>`; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (row.optional) { |             if (row.optional) { | ||||||
|                 text += ' <small>({% trans "Optional" %})</small>'; |                 text += ' <small>({% jstrans "Optional" %})</small>'; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (row.overage) { |             if (row.overage) { | ||||||
| @@ -1011,7 +1011,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'substitutes', |         field: 'substitutes', | ||||||
|         title: '{% trans "Substitutes" %}', |         title: '{% jstrans "Substitutes" %}', | ||||||
|         searchable: false, |         searchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatter: function(value, row) { |         formatter: function(value, row) { | ||||||
| @@ -1025,7 +1025,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'optional', |         field: 'optional', | ||||||
|         title: '{% trans "Optional" %}', |         title: '{% jstrans "Optional" %}', | ||||||
|         searchable: false, |         searchable: false, | ||||||
|         formatter: function(value) { |         formatter: function(value) { | ||||||
|             return yesNoLabel(value); |             return yesNoLabel(value); | ||||||
| @@ -1034,7 +1034,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'consumable', |         field: 'consumable', | ||||||
|         title: '{% trans "Consumable" %}', |         title: '{% jstrans "Consumable" %}', | ||||||
|         searchable: false, |         searchable: false, | ||||||
|         formatter: function(value) { |         formatter: function(value) { | ||||||
|             return yesNoLabel(value); |             return yesNoLabel(value); | ||||||
| @@ -1043,7 +1043,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'allow_variants', |         field: 'allow_variants', | ||||||
|         title: '{% trans "Allow Variants" %}', |         title: '{% jstrans "Allow Variants" %}', | ||||||
|         formatter: function(value) { |         formatter: function(value) { | ||||||
|             return yesNoLabel(value); |             return yesNoLabel(value); | ||||||
|         } |         } | ||||||
| @@ -1051,7 +1051,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'inherited', |         field: 'inherited', | ||||||
|         title: '{% trans "Gets inherited" %}', |         title: '{% jstrans "Gets inherited" %}', | ||||||
|         searchable: false, |         searchable: false, | ||||||
|         formatter: function(value, row) { |         formatter: function(value, row) { | ||||||
|             // This BOM item *is* inheritable, but is defined for this BOM |             // This BOM item *is* inheritable, but is defined for this BOM | ||||||
| @@ -1068,7 +1068,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'pricing', |         field: 'pricing', | ||||||
|         title: '{% trans "Price Range" %}', |         title: '{% jstrans "Price Range" %}', | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         sorter: function(valA, valB, rowA, rowB) { |         sorter: function(valA, valB, rowA, rowB) { | ||||||
|             var a = rowA.pricing_min || rowA.pricing_max; |             var a = rowA.pricing_min || rowA.pricing_max; | ||||||
| @@ -1136,19 +1136,19 @@ function loadBomTable(table, options={}) { | |||||||
|                 if (complete_pricing) { |                 if (complete_pricing) { | ||||||
|                     html += makeIconBadge( |                     html += makeIconBadge( | ||||||
|                         'fa-check-circle icon-green', |                         'fa-check-circle icon-green', | ||||||
|                         '{% trans "BOM pricing is complete" %}', |                         '{% jstrans "BOM pricing is complete" %}', | ||||||
|                     ); |                     ); | ||||||
|                 } else { |                 } else { | ||||||
|                     html += makeIconBadge( |                     html += makeIconBadge( | ||||||
|                         'fa-exclamation-circle icon-yellow', |                         'fa-exclamation-circle icon-yellow', | ||||||
|                         '{% trans "BOM pricing is incomplete" %}', |                         '{% jstrans "BOM pricing is incomplete" %}', | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 return html; |                 return html; | ||||||
|  |  | ||||||
|             } else { |             } else { | ||||||
|                 let html = '<em>{% trans "No pricing available" %}</em>'; |                 let html = '<em>{% jstrans "No pricing available" %}</em>'; | ||||||
|                 html += makeIconBadge('fa-times-circle icon-red'); |                 html += makeIconBadge('fa-times-circle icon-red'); | ||||||
|  |  | ||||||
|                 return html; |                 return html; | ||||||
| @@ -1159,7 +1159,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|     cols.push({ |     cols.push({ | ||||||
|         field: 'available_stock', |         field: 'available_stock', | ||||||
|         title: '{% trans "Available" %}', |         title: '{% jstrans "Available" %}', | ||||||
|         searchable: false, |         searchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatter: function(value, row) { |         formatter: function(value, row) { | ||||||
| @@ -1179,16 +1179,16 @@ function loadBomTable(table, options={}) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (available_stock <= 0) { |             if (available_stock <= 0) { | ||||||
|                 text += makeIconBadge('fa-times-circle icon-red', '{% trans "No Stock Available" %}'); |                 text += makeIconBadge('fa-times-circle icon-red', '{% jstrans "No Stock Available" %}'); | ||||||
|             } else { |             } else { | ||||||
|                 var extra = ''; |                 var extra = ''; | ||||||
|  |  | ||||||
|                 if ((substitute_stock > 0) && (variant_stock > 0)) { |                 if ((substitute_stock > 0) && (variant_stock > 0)) { | ||||||
|                     extra = '{% trans "Includes variant and substitute stock" %}'; |                     extra = '{% jstrans "Includes variant and substitute stock" %}'; | ||||||
|                 } else if (variant_stock > 0) { |                 } else if (variant_stock > 0) { | ||||||
|                     extra = '{% trans "Includes variant stock" %}'; |                     extra = '{% jstrans "Includes variant stock" %}'; | ||||||
|                 } else if (substitute_stock > 0) { |                 } else if (substitute_stock > 0) { | ||||||
|                     extra = '{% trans "Includes substitute stock" %}'; |                     extra = '{% jstrans "Includes substitute stock" %}'; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (extra) { |                 if (extra) { | ||||||
| @@ -1199,7 +1199,7 @@ function loadBomTable(table, options={}) { | |||||||
|             if (row.on_order && row.on_order > 0) { |             if (row.on_order && row.on_order > 0) { | ||||||
|                 text += makeIconBadge( |                 text += makeIconBadge( | ||||||
|                     'fa-shopping-cart', |                     'fa-shopping-cart', | ||||||
|                     `{% trans "On Order" %}: ${row.on_order}`, |                     `{% jstrans "On Order" %}: ${row.on_order}`, | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -1210,13 +1210,13 @@ function loadBomTable(table, options={}) { | |||||||
|     cols.push( |     cols.push( | ||||||
|         { |         { | ||||||
|             field: 'can_build', |             field: 'can_build', | ||||||
|             title: '{% trans "Can Build" %}', |             title: '{% jstrans "Can Build" %}', | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
|  |  | ||||||
|                 // "Consumable" parts are not tracked in the build |                 // "Consumable" parts are not tracked in the build | ||||||
|                 if (row.consumable) { |                 if (row.consumable) { | ||||||
|                     return `<em>{% trans "Consumable item" %}</em>`; |                     return `<em>{% jstrans "Consumable item" %}</em>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 var can_build = canBuildQuantity(row); |                 var can_build = canBuildQuantity(row); | ||||||
| @@ -1256,7 +1256,7 @@ function loadBomTable(table, options={}) { | |||||||
|     cols.push( |     cols.push( | ||||||
|         { |         { | ||||||
|             field: 'note', |             field: 'note', | ||||||
|             title: '{% trans "Notes" %}', |             title: '{% jstrans "Notes" %}', | ||||||
|             searchable: true, |             searchable: true, | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             formatter: function(value) { |             formatter: function(value) { | ||||||
| @@ -1268,7 +1268,7 @@ function loadBomTable(table, options={}) { | |||||||
|     if (options.editable) { |     if (options.editable) { | ||||||
|  |  | ||||||
|         cols.push({ |         cols.push({ | ||||||
|             title: '{% trans "Actions" %}', |             title: '{% jstrans "Actions" %}', | ||||||
|             switchable: false, |             switchable: false, | ||||||
|             field: 'pk', |             field: 'pk', | ||||||
|             visible: true, |             visible: true, | ||||||
| @@ -1276,15 +1276,15 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|                 if (row.part == options.parent_id) { |                 if (row.part == options.parent_id) { | ||||||
|  |  | ||||||
|                     var bValidate = makeIconButton('fa-check-circle icon-green', 'bom-validate-button', row.pk, '{% trans "Validate BOM Item" %}'); |                     var bValidate = makeIconButton('fa-check-circle icon-green', 'bom-validate-button', row.pk, '{% jstrans "Validate BOM Item" %}'); | ||||||
|  |  | ||||||
|                     var bValid = makeIconButton('fa-check-double icon-green', 'bom-valid-button', row.pk, '{% trans "This line has been validated" %}', {disabled: true}); |                     var bValid = makeIconButton('fa-check-double icon-green', 'bom-valid-button', row.pk, '{% jstrans "This line has been validated" %}', {disabled: true}); | ||||||
|  |  | ||||||
|                     var bSubs = makeIconButton('fa-exchange-alt icon-blue', 'bom-substitutes-button', row.pk, '{% trans "Edit substitute parts" %}'); |                     var bSubs = makeIconButton('fa-exchange-alt icon-blue', 'bom-substitutes-button', row.pk, '{% jstrans "Edit substitute parts" %}'); | ||||||
|  |  | ||||||
|                     var bEdit = makeEditButton('bom-edit-button', row.pk, '{% trans "Edit BOM Item" %}'); |                     var bEdit = makeEditButton('bom-edit-button', row.pk, '{% jstrans "Edit BOM Item" %}'); | ||||||
|  |  | ||||||
|                     var bDelt = makeDeleteButton('bom-delete-button', row.pk, '{% trans "Delete BOM Item" %}'); |                     var bDelt = makeDeleteButton('bom-delete-button', row.pk, '{% jstrans "Delete BOM Item" %}'); | ||||||
|  |  | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|  |  | ||||||
| @@ -1304,15 +1304,15 @@ function loadBomTable(table, options={}) { | |||||||
|                     // Return a link to the external BOM |                     // Return a link to the external BOM | ||||||
|  |  | ||||||
|                     return renderLink( |                     return renderLink( | ||||||
|                         '{% trans "View BOM" %}', |                         '{% jstrans "View BOM" %}', | ||||||
|                         `/part/${row.part}/bom/` |                         `/part/${row.part}/bom/` | ||||||
|                     ); |                     ); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             footerFormatter: function(data) { |             footerFormatter: function(data) { | ||||||
|                 return ` |                 return ` | ||||||
|                 <button class='btn btn-success float-right' type='button' title='{% trans "Add BOM Item" %}' id='bom-item-new-footer'> |                 <button class='btn btn-success float-right' type='button' title='{% jstrans "Add BOM Item" %}' id='bom-item-new-footer'> | ||||||
|                     ${makeIcon('fa-plus-circle')} {% trans "Add BOM Item" %} |                     ${makeIcon('fa-plus-circle')} {% jstrans "Add BOM Item" %} | ||||||
|                 </button> |                 </button> | ||||||
|                 `; |                 `; | ||||||
|             } |             } | ||||||
| @@ -1388,7 +1388,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|         }, |         }, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No BOM items found" %}'; |             return '{% jstrans "No BOM items found" %}'; | ||||||
|         }, |         }, | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
|         original: params, |         original: params, | ||||||
| @@ -1477,7 +1477,7 @@ function loadBomTable(table, options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-bom-list" %}${pk}/`, { |             constructForm(`{% url "api-bom-list" %}${pk}/`, { | ||||||
|                 fields: fields, |                 fields: fields, | ||||||
|                 title: '{% trans "Edit BOM Item" %}', |                 title: '{% jstrans "Edit BOM Item" %}', | ||||||
|                 focus: 'sub_part', |                 focus: 'sub_part', | ||||||
|                 onSuccess: function() { |                 onSuccess: function() { | ||||||
|                     reloadBomTable(table); |                     reloadBomTable(table); | ||||||
| @@ -1630,7 +1630,7 @@ function loadUsedInTable(table, part_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 title: '{% trans "Assembly" %}', |                 title: '{% jstrans "Assembly" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1648,7 +1648,7 @@ function loadUsedInTable(table, part_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'sub_part', |                 field: 'sub_part', | ||||||
|                 title: '{% trans "Required Part" %}', |                 title: '{% jstrans "Required Part" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var url = `/part/${value}/`; |                     var url = `/part/${value}/`; | ||||||
| @@ -1665,7 +1665,7 @@ function loadUsedInTable(table, part_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Required Quantity" %}', |                 title: '{% jstrans "Required Quantity" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = value; |                     var html = value; | ||||||
|  |  | ||||||
| @@ -1674,7 +1674,7 @@ function loadUsedInTable(table, part_id, options={}) { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.parent && row.parent != 'top-level-item') { |                     if (row.parent && row.parent != 'top-level-item') { | ||||||
|                         html += ` <em>({% trans "Inherited from parent BOM" %})</em>`; |                         html += ` <em>({% jstrans "Inherited from parent BOM" %})</em>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
|   | |||||||
| @@ -139,7 +139,7 @@ function editBuildOrder(pk) { | |||||||
|     constructForm(`{% url "api-build-list" %}${pk}/`, { |     constructForm(`{% url "api-build-list" %}${pk}/`, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         reload: true, |         reload: true, | ||||||
|         title: '{% trans "Edit Build Order" %}', |         title: '{% jstrans "Edit Build Order" %}', | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -182,7 +182,7 @@ function newBuildOrder(options={}) { | |||||||
|         data: options.data, |         data: options.data, | ||||||
|         follow: true, |         follow: true, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Create Build Order" %}', |         title: '{% jstrans "Create Build Order" %}', | ||||||
|         onSuccess: options.onSuccess, |         onSuccess: options.onSuccess, | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -214,7 +214,7 @@ function cancelBuildOrder(build_id, options={}) { | |||||||
|         `{% url "api-build-list" %}${build_id}/cancel/`, |         `{% url "api-build-list" %}${build_id}/cancel/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Cancel Build Order" %}', |             title: '{% jstrans "Cancel Build Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             fields: { |             fields: { | ||||||
|                 remove_allocated_stock: {}, |                 remove_allocated_stock: {}, | ||||||
| @@ -223,20 +223,20 @@ function cancelBuildOrder(build_id, options={}) { | |||||||
|             preFormContent: function(opts) { |             preFormContent: function(opts) { | ||||||
|                 var html = ` |                 var html = ` | ||||||
|                 <div class='alert alert-block alert-info'> |                 <div class='alert alert-block alert-info'> | ||||||
|                     {% trans "Are you sure you wish to cancel this build?" %} |                     {% jstrans "Are you sure you wish to cancel this build?" %} | ||||||
|                 </div>`; |                 </div>`; | ||||||
|  |  | ||||||
|                 if (opts.context.has_allocated_stock) { |                 if (opts.context.has_allocated_stock) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-warning'> |                     <div class='alert alert-block alert-warning'> | ||||||
|                         {% trans "Stock items have been allocated to this build order" %} |                         {% jstrans "Stock items have been allocated to this build order" %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (opts.context.incomplete_outputs) { |                 if (opts.context.incomplete_outputs) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-warning'> |                     <div class='alert alert-block alert-warning'> | ||||||
|                         {% trans "There are incomplete outputs remaining for this build order" %} |                         {% jstrans "There are incomplete outputs remaining for this build order" %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -288,30 +288,30 @@ function completeBuildOrder(build_id, options={}) { | |||||||
|             if (ctx.allocated && ctx.remaining == 0 && ctx.incomplete == 0) { |             if (ctx.allocated && ctx.remaining == 0 && ctx.incomplete == 0) { | ||||||
|                 html += ` |                 html += ` | ||||||
|                 <div class='alert alert-block alert-success'> |                 <div class='alert alert-block alert-success'> | ||||||
|                 {% trans "Build order is ready to be completed" %}' |                 {% jstrans "Build order is ready to be completed" %}' | ||||||
|                 </div>`; |                 </div>`; | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|                 if (ctx.incomplete > 0) { |                 if (ctx.incomplete > 0) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-danger'> |                     <div class='alert alert-block alert-danger'> | ||||||
|                     <strong>{% trans "Build order has incomplete outputs" %}</strong><br> |                     <strong>{% jstrans "Build order has incomplete outputs" %}</strong><br> | ||||||
|                     {% trans "This build order cannot be completed as there are incomplete outputs" %} |                     {% jstrans "This build order cannot be completed as there are incomplete outputs" %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } else { |                 } else { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-danger'> |                     <div class='alert alert-block alert-danger'> | ||||||
|                     <strong>{% trans "Build Order is incomplete" %}</strong> |                     <strong>{% jstrans "Build Order is incomplete" %}</strong> | ||||||
|                     </div> |                     </div> | ||||||
|                     `; |                     `; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (!ctx.allocated) { |                 if (!ctx.allocated) { | ||||||
|                     html += `<div class='alert alert-block alert-warning'>{% trans "Required stock has not been fully allocated" %}</div>`; |                     html += `<div class='alert alert-block alert-warning'>{% jstrans "Required stock has not been fully allocated" %}</div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (ctx.remaining > 0) { |                 if (ctx.remaining > 0) { | ||||||
|                     html += `<div class='alert alert-block alert-warning'>{% trans "Required build quantity has not been completed" %}</div>`; |                     html += `<div class='alert alert-block alert-warning'>{% jstrans "Required build quantity has not been completed" %}</div>`; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -319,7 +319,7 @@ function completeBuildOrder(build_id, options={}) { | |||||||
|         }, |         }, | ||||||
|         reload: true, |         reload: true, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         title: '{% trans "Complete Build Order" %}', |         title: '{% jstrans "Complete Build Order" %}', | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -360,9 +360,9 @@ function createBuildOutput(build_id, options) { | |||||||
|                 inventreeGet(`{% url "api-part-list" %}${build.part}/serial-numbers/`, {}, { |                 inventreeGet(`{% url "api-part-list" %}${build.part}/serial-numbers/`, {}, { | ||||||
|                     success: function(data) { |                     success: function(data) { | ||||||
|                         if (data.next) { |                         if (data.next) { | ||||||
|                             fields.serial_numbers.placeholder = `{% trans "Next available serial number" %}: ${data.next}`; |                             fields.serial_numbers.placeholder = `{% jstrans "Next available serial number" %}: ${data.next}`; | ||||||
|                         } else if (data.latest) { |                         } else if (data.latest) { | ||||||
|                             fields.serial_numbers.placeholder = `{% trans "Latest serial number" %}: ${data.latest}`; |                             fields.serial_numbers.placeholder = `{% jstrans "Latest serial number" %}: ${data.latest}`; | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                     async: false, |                     async: false, | ||||||
| @@ -371,8 +371,8 @@ function createBuildOutput(build_id, options) { | |||||||
|                 if (options.trackable_parts) { |                 if (options.trackable_parts) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-info'> |                     <div class='alert alert-block alert-info'> | ||||||
|                         {% trans "The Bill of Materials contains trackable parts" %}.<br> |                         {% jstrans "The Bill of Materials contains trackable parts" %}.<br> | ||||||
|                         {% trans "Build outputs must be generated individually" %}. |                         {% jstrans "Build outputs must be generated individually" %}. | ||||||
|                     </div> |                     </div> | ||||||
|                     `; |                     `; | ||||||
|                 } |                 } | ||||||
| @@ -380,15 +380,15 @@ function createBuildOutput(build_id, options) { | |||||||
|                 if (trackable) { |                 if (trackable) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-info'> |                     <div class='alert alert-block alert-info'> | ||||||
|                         {% trans "Trackable parts can have serial numbers specified" %}<br> |                         {% jstrans "Trackable parts can have serial numbers specified" %}<br> | ||||||
|                         {% trans "Enter serial numbers to generate multiple single build outputs" %} |                         {% jstrans "Enter serial numbers to generate multiple single build outputs" %} | ||||||
|                     </div> |                     </div> | ||||||
|                     `; |                     `; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 constructForm(`{% url "api-build-list" %}${build_id}/create-output/`, { |                 constructForm(`{% url "api-build-list" %}${build_id}/create-output/`, { | ||||||
|                     method: 'POST', |                     method: 'POST', | ||||||
|                     title: '{% trans "Create Build Output" %}', |                     title: '{% jstrans "Create Build Output" %}', | ||||||
|                     confirm: true, |                     confirm: true, | ||||||
|                     fields: fields, |                     fields: fields, | ||||||
|                     preFormContent: html, |                     preFormContent: html, | ||||||
| @@ -419,7 +419,7 @@ function makeBuildOutputButtons(output_id, build_info, options={}) { | |||||||
|             'fa-sign-in-alt icon-blue', |             'fa-sign-in-alt icon-blue', | ||||||
|             'button-output-allocate', |             'button-output-allocate', | ||||||
|             output_id, |             output_id, | ||||||
|             '{% trans "Allocate stock items to this build output" %}', |             '{% jstrans "Allocate stock items to this build output" %}', | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         // Add a button to deallocate stock from this build output |         // Add a button to deallocate stock from this build output | ||||||
| @@ -427,7 +427,7 @@ function makeBuildOutputButtons(output_id, build_info, options={}) { | |||||||
|             'fa-minus-circle icon-red', |             'fa-minus-circle icon-red', | ||||||
|             'button-output-deallocate', |             'button-output-deallocate', | ||||||
|             output_id, |             output_id, | ||||||
|             '{% trans "Deallocate stock from build output" %}', |             '{% jstrans "Deallocate stock from build output" %}', | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -436,7 +436,7 @@ function makeBuildOutputButtons(output_id, build_info, options={}) { | |||||||
|         'fa-check-circle icon-green', |         'fa-check-circle icon-green', | ||||||
|         'button-output-complete', |         'button-output-complete', | ||||||
|         output_id, |         output_id, | ||||||
|         '{% trans "Complete build output" %}', |         '{% jstrans "Complete build output" %}', | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // Add a button to "scrap" the build output |     // Add a button to "scrap" the build output | ||||||
| @@ -444,14 +444,14 @@ function makeBuildOutputButtons(output_id, build_info, options={}) { | |||||||
|         'fa-times-circle icon-red', |         'fa-times-circle icon-red', | ||||||
|         'button-output-scrap', |         'button-output-scrap', | ||||||
|         output_id, |         output_id, | ||||||
|         '{% trans "Scrap build output" %}', |         '{% jstrans "Scrap build output" %}', | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // Add a button to "remove" this build output |     // Add a button to "remove" this build output | ||||||
|     html += makeDeleteButton( |     html += makeDeleteButton( | ||||||
|         'button-output-remove', |         'button-output-remove', | ||||||
|         output_id, |         output_id, | ||||||
|         '{% trans "Delete build output" %}', |         '{% jstrans "Delete build output" %}', | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     return wrapButtons(html); |     return wrapButtons(html); | ||||||
| @@ -471,7 +471,7 @@ function deallocateStock(build_id, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-warning'> |     <div class='alert alert-block alert-warning'> | ||||||
|     {% trans "Are you sure you wish to deallocate the selected stock items from this build?" %} |     {% jstrans "Are you sure you wish to deallocate the selected stock items from this build?" %} | ||||||
|     </dvi> |     </dvi> | ||||||
|     `; |     `; | ||||||
|  |  | ||||||
| @@ -489,7 +489,7 @@ function deallocateStock(build_id, options={}) { | |||||||
|                 value: options.build_line, |                 value: options.build_line, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         title: '{% trans "Deallocate Stock Items" %}', |         title: '{% jstrans "Deallocate Stock Items" %}', | ||||||
|         onSuccess: function(response, opts) { |         onSuccess: function(response, opts) { | ||||||
|             if (options.onSuccess) { |             if (options.onSuccess) { | ||||||
|                 options.onSuccess(response, opts); |                 options.onSuccess(response, opts); | ||||||
| @@ -511,9 +511,9 @@ function renderBuildOutput(output, options={}) { | |||||||
|     let output_html = imageHoverIcon(output.part_detail.thumbnail); |     let output_html = imageHoverIcon(output.part_detail.thumbnail); | ||||||
|  |  | ||||||
|     if (output.quantity == 1 && output.serial) { |     if (output.quantity == 1 && output.serial) { | ||||||
|         output_html += `{% trans "Serial Number" %}: ${output.serial}`; |         output_html += `{% jstrans "Serial Number" %}: ${output.serial}`; | ||||||
|     } else { |     } else { | ||||||
|         output_html += `{% trans "Quantity" %}: ${output.quantity}`; |         output_html += `{% jstrans "Quantity" %}: ${output.quantity}`; | ||||||
|         if (output.part_detail && output.part_detail.units) { |         if (output.part_detail && output.part_detail.units) { | ||||||
|             output_html += ` ${output.part_detail.units}  `; |             output_html += ` ${output.part_detail.units}  `; | ||||||
|         } |         } | ||||||
| @@ -521,7 +521,7 @@ function renderBuildOutput(output, options={}) { | |||||||
|  |  | ||||||
|     let buttons = `<div class='btn-group float-right' role='group'>`; |     let buttons = `<div class='btn-group float-right' role='group'>`; | ||||||
|  |  | ||||||
|     buttons += makeRemoveButton('button-row-remove', pk, '{% trans "Remove row" %}'); |     buttons += makeRemoveButton('button-row-remove', pk, '{% jstrans "Remove row" %}'); | ||||||
|  |  | ||||||
|     buttons += '</div>'; |     buttons += '</div>'; | ||||||
|  |  | ||||||
| @@ -575,8 +575,8 @@ function completeBuildOutputs(build_id, outputs, options={}) { | |||||||
|  |  | ||||||
|     if (outputs.length == 0) { |     if (outputs.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Build Outputs" %}', |             '{% jstrans "Select Build Outputs" %}', | ||||||
|             '{% trans "At least one build output must be selected" %}', |             '{% jstrans "At least one build output must be selected" %}', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -590,11 +590,11 @@ function completeBuildOutputs(build_id, outputs, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-success'> |     <div class='alert alert-block alert-success'> | ||||||
|     {% trans "Selected build outputs will be marked as complete" %} |     {% jstrans "Selected build outputs will be marked as complete" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed' id='build-complete-table'> |     <table class='table table-striped table-condensed' id='build-complete-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <th colspan='2'>{% trans "Output" %}</th> |             <th colspan='2'>{% jstrans "Output" %}</th> | ||||||
|             <th><!-- Actions --></th> |             <th><!-- Actions --></th> | ||||||
|         </thead> |         </thead> | ||||||
|         <tbody> |         <tbody> | ||||||
| @@ -622,7 +622,7 @@ function completeBuildOutputs(build_id, outputs, options={}) { | |||||||
|             accept_incomplete_allocation: {}, |             accept_incomplete_allocation: {}, | ||||||
|         }, |         }, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         title: '{% trans "Complete Build Outputs" %}', |         title: '{% jstrans "Complete Build Outputs" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|             // Setup callbacks to remove outputs |             // Setup callbacks to remove outputs | ||||||
|             $(opts.modal).find('.button-row-remove').click(function() { |             $(opts.modal).find('.button-row-remove').click(function() { | ||||||
| @@ -703,8 +703,8 @@ function scrapBuildOutputs(build_id, outputs, options={}) { | |||||||
|  |  | ||||||
|     if (outputs.length == 0) { |     if (outputs.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Build Outputs" %}', |             '{% jstrans "Select Build Outputs" %}', | ||||||
|             '{% trans "At least one build output must be selected" %}', |             '{% jstrans "At least one build output must be selected" %}', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -719,17 +719,17 @@ function scrapBuildOutputs(build_id, outputs, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "Selected build outputs will be marked as scrapped" %} |     {% jstrans "Selected build outputs will be marked as scrapped" %} | ||||||
|     <ul> |     <ul> | ||||||
|         <li>{% trans "Scrapped output are marked as rejected" %}</li> |         <li>{% jstrans "Scrapped output are marked as rejected" %}</li> | ||||||
|         <li>{% trans "Allocated stock items will no longer be available" %}</li> |         <li>{% jstrans "Allocated stock items will no longer be available" %}</li> | ||||||
|         <li>{% trans "The completion status of the build order will not be adjusted" %}</li> |         <li>{% jstrans "The completion status of the build order will not be adjusted" %}</li> | ||||||
|     </ul> |     </ul> | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed' id='build-scrap-table'> |     <table class='table table-striped table-condensed' id='build-scrap-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <th colspan='2'>{% trans "Output" %}</th> |             <th colspan='2'>{% jstrans "Output" %}</th> | ||||||
|             <th>{% trans "Quantity" %}</th> |             <th>{% jstrans "Quantity" %}</th> | ||||||
|             <th><!-- Actions --></th> |             <th><!-- Actions --></th> | ||||||
|         </thead> |         </thead> | ||||||
|         <tbody> |         <tbody> | ||||||
| @@ -754,7 +754,7 @@ function scrapBuildOutputs(build_id, outputs, options={}) { | |||||||
|             discard_allocations: {}, |             discard_allocations: {}, | ||||||
|         }, |         }, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         title: '{% trans "Scrap Build Outputs" %}', |         title: '{% jstrans "Scrap Build Outputs" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|             // Setup callbacks to remove outputs |             // Setup callbacks to remove outputs | ||||||
|             $(opts.modal).find('.button-row-remove').click(function() { |             $(opts.modal).find('.button-row-remove').click(function() { | ||||||
| @@ -829,8 +829,8 @@ function deleteBuildOutputs(build_id, outputs, options={}) { | |||||||
|  |  | ||||||
|     if (outputs.length == 0) { |     if (outputs.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Build Outputs" %}', |             '{% jstrans "Select Build Outputs" %}', | ||||||
|             '{% trans "At least one build output must be selected" %}', |             '{% jstrans "At least one build output must be selected" %}', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -844,15 +844,15 @@ function deleteBuildOutputs(build_id, outputs, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "Selected build outputs will be deleted" %} |     {% jstrans "Selected build outputs will be deleted" %} | ||||||
|     <ul> |     <ul> | ||||||
|     <li>{% trans "Build output data will be permanently deleted" %}</li> |     <li>{% jstrans "Build output data will be permanently deleted" %}</li> | ||||||
|     <li>{% trans "Allocated stock items will be returned to stock" %}</li> |     <li>{% jstrans "Allocated stock items will be returned to stock" %}</li> | ||||||
|     </ul> |     </ul> | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed' id='build-complete-table'> |     <table class='table table-striped table-condensed' id='build-complete-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <th colspan='2'>{% trans "Output" %}</th> |             <th colspan='2'>{% jstrans "Output" %}</th> | ||||||
|             <th><!-- Actions --></th> |             <th><!-- Actions --></th> | ||||||
|         </thead> |         </thead> | ||||||
|         <tbody> |         <tbody> | ||||||
| @@ -865,7 +865,7 @@ function deleteBuildOutputs(build_id, outputs, options={}) { | |||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         fields: {}, |         fields: {}, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         title: '{% trans "Delete Build Outputs" %}', |         title: '{% jstrans "Delete Build Outputs" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|             // Setup callbacks to remove outputs |             // Setup callbacks to remove outputs | ||||||
|             $(opts.modal).find('.button-row-remove').click(function() { |             $(opts.modal).find('.button-row-remove').click(function() { | ||||||
| @@ -952,7 +952,7 @@ function loadBuildOrderAllocationTable(table, options={}) { | |||||||
|         paginationVAlign: 'bottom', |         paginationVAlign: 'bottom', | ||||||
|         original: options.params, |         original: options.params, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No build order allocations found" %}'; |             return '{% jstrans "No build order allocations found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
| @@ -964,7 +964,7 @@ function loadBuildOrderAllocationTable(table, options={}) { | |||||||
|                 field: 'build', |                 field: 'build', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 title: '{% trans "Build Order" %}', |                 title: '{% jstrans "Build Order" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let ref = `${row.build_detail.reference}`; |                     let ref = `${row.build_detail.reference}`; | ||||||
|                     let html = renderLink(ref, `/build/${row.build}/`); |                     let html = renderLink(ref, `/build/${row.build}/`); | ||||||
| @@ -981,7 +981,7 @@ function loadBuildOrderAllocationTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Allocated Quantity" %}', |                 title: '{% jstrans "Allocated Quantity" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let link = `/stock/item/${row.stock_item}/`; |                     let link = `/stock/item/${row.stock_item}/`; | ||||||
|                     let text = formatDecimal(value); |                     let text = formatDecimal(value); | ||||||
| @@ -991,11 +991,11 @@ function loadBuildOrderAllocationTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'location_detail', |                 field: 'location_detail', | ||||||
|                 title: '{% trans "Location" %}', |                 title: '{% jstrans "Location" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     if (!value) { |                     if (!value) { | ||||||
|                         return '{% trans "Location not specified" %}'; |                         return '{% jstrans "Location not specified" %}'; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     let item = row.stock_item_detail; |                     let item = row.stock_item_detail; | ||||||
| @@ -1017,7 +1017,7 @@ function makeBuildOutputActions(build_info) { | |||||||
|     return [ |     return [ | ||||||
|         { |         { | ||||||
|             label: 'complete', |             label: 'complete', | ||||||
|             title: '{% trans "Complete outputs" %}', |             title: '{% jstrans "Complete outputs" %}', | ||||||
|             icon: 'fa-check-circle icon-green', |             icon: 'fa-check-circle icon-green', | ||||||
|             permission: 'build.add', |             permission: 'build.add', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1035,7 +1035,7 @@ function makeBuildOutputActions(build_info) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             label: 'scrap', |             label: 'scrap', | ||||||
|             title: '{% trans "Scrap outputs" %}', |             title: '{% jstrans "Scrap outputs" %}', | ||||||
|             icon: 'fa-times-circle icon-red', |             icon: 'fa-times-circle icon-red', | ||||||
|             permission: 'build.change', |             permission: 'build.change', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1053,7 +1053,7 @@ function makeBuildOutputActions(build_info) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             label: 'delete', |             label: 'delete', | ||||||
|             title: '{% trans "Delete outputs" %}', |             title: '{% jstrans "Delete outputs" %}', | ||||||
|             icon: 'fa-trash-alt icon-red', |             icon: 'fa-trash-alt icon-red', | ||||||
|             permission: 'build.delete', |             permission: 'build.delete', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1107,12 +1107,12 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|             url: '{% url "api-stockitem-label-list" %}', |             url: '{% url "api-stockitem-label-list" %}', | ||||||
|             key: 'item', |             key: 'item', | ||||||
|         }, |         }, | ||||||
|         singular_name: '{% trans "build output" %}', |         singular_name: '{% jstrans "build output" %}', | ||||||
|         plural_name: '{% trans "build outputs" %}', |         plural_name: '{% jstrans "build outputs" %}', | ||||||
|         custom_actions: [{ |         custom_actions: [{ | ||||||
|             label: 'buildoutput', |             label: 'buildoutput', | ||||||
|             icon: 'fa-tools', |             icon: 'fa-tools', | ||||||
|             title: '{% trans "Build output actions" %}', |             title: '{% jstrans "Build output actions" %}', | ||||||
|             actions: makeBuildOutputActions(build_info), |             actions: makeBuildOutputActions(build_info), | ||||||
|         }] |         }] | ||||||
|     }); |     }); | ||||||
| @@ -1281,7 +1281,7 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|             return constructOutputSubTable(index, row, element); |             return constructOutputSubTable(index, row, element); | ||||||
|         }, |         }, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No active build outputs found" %}'; |             return '{% jstrans "No active build outputs found" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function() { |         onLoadSuccess: function() { | ||||||
|             reloadOutputAllocations(); |             reloadOutputAllocations(); | ||||||
| @@ -1296,7 +1296,7 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return imageHoverIcon(row.part_detail.thumbnail) + |                     return imageHoverIcon(row.part_detail.thumbnail) + | ||||||
| @@ -1306,7 +1306,7 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Build Output" %}', |                 title: '{% jstrans "Build Output" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sorter: function(fieldA, fieldB, rowA, rowB) { |                 sorter: function(fieldA, fieldB, rowA, rowB) { | ||||||
| @@ -1351,9 +1351,9 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|                     let text = ''; |                     let text = ''; | ||||||
|  |  | ||||||
|                     if (row.serial && row.quantity == 1) { |                     if (row.serial && row.quantity == 1) { | ||||||
|                         text = `{% trans "Serial Number" %}: ${row.serial}`; |                         text = `{% jstrans "Serial Number" %}: ${row.serial}`; | ||||||
|                     } else { |                     } else { | ||||||
|                         text = `{% trans "Quantity" %}: ${row.quantity}`; |                         text = `{% jstrans "Quantity" %}: ${row.quantity}`; | ||||||
|  |  | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -1364,7 +1364,7 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.batch) { |                     if (row.batch) { | ||||||
|                         text += ` <small>({% trans "Batch" %}: ${row.batch})</small>`; |                         text += ` <small>({% jstrans "Batch" %}: ${row.batch})</small>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     text += stockStatusDisplay(row.status, {classes: 'float-right'}); |                     text += stockStatusDisplay(row.status, {classes: 'float-right'}); | ||||||
| @@ -1374,7 +1374,7 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'fully_allocated', |                 field: 'fully_allocated', | ||||||
|                 title: '{% trans "Allocated Lines" %}', |                 title: '{% jstrans "Allocated Lines" %}', | ||||||
|                 visible: false, |                 visible: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
| @@ -1388,7 +1388,7 @@ function loadBuildOutputTable(build_info, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'tests', |                 field: 'tests', | ||||||
|                 title: '{% trans "Required Tests" %}', |                 title: '{% jstrans "Required Tests" %}', | ||||||
|                 visible: test_templates.length > 0, |                 visible: test_templates.length > 0, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
| @@ -1560,8 +1560,8 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|     if (line_items.length == 0) { |     if (line_items.length == 0) { | ||||||
|  |  | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Parts" %}', |             '{% jstrans "Select Parts" %}', | ||||||
|             '{% trans "You must select at least one part to allocate" %}', |             '{% jstrans "You must select at least one part to allocate" %}', | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
| @@ -1613,7 +1613,7 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|         delete_button += makeRemoveButton( |         delete_button += makeRemoveButton( | ||||||
|             'button-row-remove', |             'button-row-remove', | ||||||
|             pk, |             pk, | ||||||
|             '{% trans "Remove row" %}', |             '{% jstrans "Remove row" %}', | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         delete_button += `</div>`; |         delete_button += `</div>`; | ||||||
| @@ -1624,7 +1624,7 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|                 type: 'decimal', |                 type: 'decimal', | ||||||
|                 min_value: 0, |                 min_value: 0, | ||||||
|                 value: quantity || 0, |                 value: quantity || 0, | ||||||
|                 title: '{% trans "Specify stock allocation quantity" %}', |                 title: '{% jstrans "Specify stock allocation quantity" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -1701,8 +1701,8 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|     if (table_entries.length == 0) { |     if (table_entries.length == 0) { | ||||||
|  |  | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "All Parts Allocated" %}', |             '{% jstrans "All Parts Allocated" %}', | ||||||
|             '{% trans "All selected parts have been fully allocated" %}', |             '{% jstrans "All selected parts have been fully allocated" %}', | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
| @@ -1715,8 +1715,8 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|         'take_from', |         'take_from', | ||||||
|         { |         { | ||||||
|             type: 'related field', |             type: 'related field', | ||||||
|             label: '{% trans "Source Location" %}', |             label: '{% jstrans "Source Location" %}', | ||||||
|             help_text: '{% trans "Select source location (leave blank to take from all locations)" %}', |             help_text: '{% jstrans "Select source location (leave blank to take from all locations)" %}', | ||||||
|             required: false, |             required: false, | ||||||
|         }, |         }, | ||||||
|         {}, |         {}, | ||||||
| @@ -1727,10 +1727,10 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|     <table class='table table-striped table-condensed' id='stock-allocation-table'> |     <table class='table table-striped table-condensed' id='stock-allocation-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>{% trans "Part" %}</th> |                 <th>{% jstrans "Part" %}</th> | ||||||
|                 <th>{% trans "Allocated" %}</th> |                 <th>{% jstrans "Allocated" %}</th> | ||||||
|                 <th style='min-width: 250px;'>{% trans "Stock Item" %}</th> |                 <th style='min-width: 250px;'>{% jstrans "Stock Item" %}</th> | ||||||
|                 <th>{% trans "Quantity" %}</th> |                 <th>{% jstrans "Quantity" %}</th> | ||||||
|                 <th></th> |                 <th></th> | ||||||
|             </tr> |             </tr> | ||||||
|         </thead> |         </thead> | ||||||
| @@ -1744,7 +1744,7 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         fields: {}, |         fields: {}, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         title: '{% trans "Allocate Stock Items to Build Order" %}', |         title: '{% jstrans "Allocate Stock Items to Build Order" %}', | ||||||
|         afterRender: function(fields, options) { |         afterRender: function(fields, options) { | ||||||
|  |  | ||||||
|             var take_from_field = { |             var take_from_field = { | ||||||
| @@ -1755,7 +1755,7 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|                 type: 'related field', |                 type: 'related field', | ||||||
|                 value: source_location, |                 value: source_location, | ||||||
|                 noResults: function(query) { |                 noResults: function(query) { | ||||||
|                     return '{% trans "No matching stock locations" %}'; |                     return '{% jstrans "No matching stock locations" %}'; | ||||||
|                 }, |                 }, | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
| @@ -1828,7 +1828,7 @@ function allocateStockToBuild(build_id, line_items, options={}) { | |||||||
|                             return filters; |                             return filters; | ||||||
|                         }, |                         }, | ||||||
|                         noResults: function(query) { |                         noResults: function(query) { | ||||||
|                             return '{% trans "No matching stock items" %}'; |                             return '{% jstrans "No matching stock items" %}'; | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                     null, |                     null, | ||||||
| @@ -1925,12 +1925,12 @@ function autoAllocateStockToBuild(build_id, bom_items=[], options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-info'> |     <div class='alert alert-block alert-info'> | ||||||
|     <strong>{% trans "Automatic Stock Allocation" %}</strong><br> |     <strong>{% jstrans "Automatic Stock Allocation" %}</strong><br> | ||||||
|     {% trans "Stock items will be automatically allocated to this build order, according to the provided guidelines" %}: |     {% jstrans "Stock items will be automatically allocated to this build order, according to the provided guidelines" %}: | ||||||
|     <ul> |     <ul> | ||||||
|         <li>{% trans "If a location is specified, stock will only be allocated from that location" %}</li> |         <li>{% jstrans "If a location is specified, stock will only be allocated from that location" %}</li> | ||||||
|         <li>{% trans "If stock is considered interchangeable, it will be allocated from the first location it is found" %}</li> |         <li>{% jstrans "If stock is considered interchangeable, it will be allocated from the first location it is found" %}</li> | ||||||
|         <li>{% trans "If substitute stock is allowed, it will be used where stock of the primary part cannot be found" %}</li> |         <li>{% jstrans "If substitute stock is allowed, it will be used where stock of the primary part cannot be found" %}</li> | ||||||
|     </ul> |     </ul> | ||||||
|     </div> |     </div> | ||||||
|     `; |     `; | ||||||
| @@ -1961,7 +1961,7 @@ function autoAllocateStockToBuild(build_id, bom_items=[], options={}) { | |||||||
|     constructForm(`{% url "api-build-list" %}${build_id}/auto-allocate/`, { |     constructForm(`{% url "api-build-list" %}${build_id}/auto-allocate/`, { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Allocate Stock Items" %}', |         title: '{% jstrans "Allocate Stock Items" %}', | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
| @@ -2067,7 +2067,7 @@ function loadBuildTable(table, options) { | |||||||
|     $(table).inventreeTable({ |     $(table).inventreeTable({ | ||||||
|         method: 'get', |         method: 'get', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No builds matching query" %}'; |             return '{% jstrans "No builds matching query" %}'; | ||||||
|         }, |         }, | ||||||
|         url: '{% url "api-build-list" %}', |         url: '{% url "api-build-list" %}', | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
| @@ -2102,13 +2102,13 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 checkbox: true, |                 checkbox: true, | ||||||
|                 title: '{% trans "Select" %}', |                 title: '{% jstrans "Select" %}', | ||||||
|                 searchable: false, |                 searchable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Build" %}', |                 title: '{% jstrans "Build" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -2116,7 +2116,7 @@ function loadBuildTable(table, options) { | |||||||
|                     var html = renderLink(value, '/build/' + row.pk + '/'); |                     var html = renderLink(value, '/build/' + row.pk + '/'); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Build order is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "Build order is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -2124,12 +2124,12 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'title', |                 field: 'title', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'project_code', |                 field: 'project_code', | ||||||
|                 title: '{% trans "Project Code" %}', |                 title: '{% jstrans "Project Code" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: global_settings.PROJECT_CODES_ENABLED, |                 switchable: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 visible: global_settings.PROJECT_CODES_ENABLED, |                 visible: global_settings.PROJECT_CODES_ENABLED, | ||||||
| @@ -2141,13 +2141,13 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'priority', |                 field: 'priority', | ||||||
|                 title: '{% trans "Priority" %}', |                 title: '{% jstrans "Priority" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'part__name', |                 sortName: 'part__name', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -2162,7 +2162,7 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'completed', |                 field: 'completed', | ||||||
|                 title: '{% trans "Progress" %}', |                 title: '{% jstrans "Progress" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return makeProgressBar( |                     return makeProgressBar( | ||||||
| @@ -2176,7 +2176,7 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'status', |                 field: 'status', | ||||||
|                 title: '{% trans "Status" %}', |                 title: '{% jstrans "Status" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return buildStatusDisplay(value); |                     return buildStatusDisplay(value); | ||||||
| @@ -2184,7 +2184,7 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'creation_date', |                 field: 'creation_date', | ||||||
|                 title: '{% trans "Created" %}', |                 title: '{% jstrans "Created" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
| @@ -2192,19 +2192,19 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'issued_by', |                 field: 'issued_by', | ||||||
|                 title: '{% trans "Issued by" %}', |                 title: '{% jstrans "Issued by" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return row.issued_by_detail.username; |                         return row.issued_by_detail.username; | ||||||
|                     } else { |                     } else { | ||||||
|                         return `<i>{% trans "No user information" %}</i>`; |                         return `<i>{% jstrans "No user information" %}</i>`; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'responsible', |                 field: 'responsible', | ||||||
|                 title: '{% trans "Responsible" %}', |                 title: '{% jstrans "Responsible" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (!row.responsible_detail) { |                     if (!row.responsible_detail) { | ||||||
| @@ -2213,7 +2213,7 @@ function loadBuildTable(table, options) { | |||||||
|  |  | ||||||
|                     var html = row.responsible_detail.name; |                     var html = row.responsible_detail.name; | ||||||
|  |  | ||||||
|                     if (row.responsible_detail.label == '{% trans "group" %}') { |                     if (row.responsible_detail.label == '{% jstrans "group" %}') { | ||||||
|                         html += `<span class='float-right fas fa-users'></span>`; |                         html += `<span class='float-right fas fa-users'></span>`; | ||||||
|                     } else { |                     } else { | ||||||
|                         html += `<span class='float-right fas fa-user'></span>`; |                         html += `<span class='float-right fas fa-user'></span>`; | ||||||
| @@ -2224,7 +2224,7 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'target_date', |                 field: 'target_date', | ||||||
|                 title: '{% trans "Target Date" %}', |                 title: '{% jstrans "Target Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
| @@ -2232,7 +2232,7 @@ function loadBuildTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'completion_date', |                 field: 'completion_date', | ||||||
|                 title: '{% trans "Completion Date" %}', |                 title: '{% jstrans "Completion Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
| @@ -2320,7 +2320,7 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 formatter: function(_value, row) { |                 formatter: function(_value, row) { | ||||||
|                     let html = imageHoverIcon(row.part_detail.thumbnail); |                     let html = imageHoverIcon(row.part_detail.thumbnail); | ||||||
|                     html += renderLink(row.part_detail.full_name, `/part/${row.part_detail.pk}/`); |                     html += renderLink(row.part_detail.full_name, `/part/${row.part_detail.pk}/`); | ||||||
| @@ -2329,7 +2329,7 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Allocated Quantity" %}', |                 title: '{% jstrans "Allocated Quantity" %}', | ||||||
|                 formatter: function(_value, row) { |                 formatter: function(_value, row) { | ||||||
|                     let text = ''; |                     let text = ''; | ||||||
|                     let url = ''; |                     let url = ''; | ||||||
| @@ -2340,9 +2340,9 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (serial && row.quantity == 1) { |                     if (serial && row.quantity == 1) { | ||||||
|                         text = `{% trans "Serial Number" %}: ${serial}`; |                         text = `{% jstrans "Serial Number" %}: ${serial}`; | ||||||
|                     } else { |                     } else { | ||||||
|                         text = `{% trans "Quantity" %}: ${row.quantity}`; |                         text = `{% jstrans "Quantity" %}: ${row.quantity}`; | ||||||
|                         if (row.part_detail && row.part_detail.units) { |                         if (row.part_detail && row.part_detail.units) { | ||||||
|                             text += ` <small>${row.part_detail.units}</small>`; |                             text += ` <small>${row.part_detail.units}</small>`; | ||||||
|                         } |                         } | ||||||
| @@ -2357,7 +2357,7 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'location', |                 field: 'location', | ||||||
|                 title: '{% trans "Location" %}', |                 title: '{% jstrans "Location" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (row.location_detail) { |                     if (row.location_detail) { | ||||||
|                         let text = shortenString(row.location_detail.pathstring); |                         let text = shortenString(row.location_detail.pathstring); | ||||||
| @@ -2365,7 +2365,7 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|  |  | ||||||
|                         return renderLink(text, url); |                         return renderLink(text, url); | ||||||
|                     } else { |                     } else { | ||||||
|                         return '<i>{% trans "No location set" %}</i>'; |                         return '<i>{% jstrans "No location set" %}</i>'; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
| @@ -2374,8 +2374,8 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|                 title: '', |                 title: '', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|                     buttons += makeEditButton('button-allocation-edit', row.pk, '{% trans "Edit stock allocation" %}'); |                     buttons += makeEditButton('button-allocation-edit', row.pk, '{% jstrans "Edit stock allocation" %}'); | ||||||
|                     buttons += makeDeleteButton('button-allocation-delete', row.pk, '{% trans "Delete stock allocation" %}'); |                     buttons += makeDeleteButton('button-allocation-delete', row.pk, '{% jstrans "Delete stock allocation" %}'); | ||||||
|                     return wrapButtons(buttons); |                     return wrapButtons(buttons); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -2390,7 +2390,7 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|             fields: { |             fields: { | ||||||
|                 quantity: {}, |                 quantity: {}, | ||||||
|             }, |             }, | ||||||
|             title: '{% trans "Edit Allocation" %}', |             title: '{% jstrans "Edit Allocation" %}', | ||||||
|             onSuccess: function() { |             onSuccess: function() { | ||||||
|                 $(options.parent_table).bootstrapTable('refresh'); |                 $(options.parent_table).bootstrapTable('refresh'); | ||||||
|             }, |             }, | ||||||
| @@ -2402,7 +2402,7 @@ function renderBuildLineAllocationTable(element, build_line, options={}) { | |||||||
|  |  | ||||||
|         constructForm(`{% url "api-build-item-list" %}${pk}/`, { |         constructForm(`{% url "api-build-item-list" %}${pk}/`, { | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             title: '{% trans "Remove Allocation" %}', |             title: '{% jstrans "Remove Allocation" %}', | ||||||
|             onSuccess: function() { |             onSuccess: function() { | ||||||
|                 $(options.parent_table).bootstrapTable('refresh'); |                 $(options.parent_table).bootstrapTable('refresh'); | ||||||
|             }, |             }, | ||||||
| @@ -2443,8 +2443,8 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|                 url: '{% url "api-buildline-label-list" %}', |                 url: '{% url "api-buildline-label-list" %}', | ||||||
|                 key: 'line', |                 key: 'line', | ||||||
|             }, |             }, | ||||||
|             singular_name: '{% trans "build line" %}', |             singular_name: '{% jstrans "build line" %}', | ||||||
|             plural_name: '{% trans "build lines" %}', |             plural_name: '{% jstrans "build lines" %}', | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2462,18 +2462,18 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             }); |             }); | ||||||
|         }, |         }, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No build lines found" %}'; |             return '{% jstrans "No build lines found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 checkbox: true, |                 checkbox: true, | ||||||
|                 title: '{% trans "Select" %}', |                 title: '{% jstrans "Select" %}', | ||||||
|                 searchable: false, |                 searchable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'bom_item', |                 field: 'bom_item', | ||||||
|                 title: '{% trans "Required Part" %}', |                 title: '{% jstrans "Required Part" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'part', |                 sortName: 'part', | ||||||
| @@ -2488,11 +2488,11 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|                     html += imageHoverIcon(row.part_detail.thumbnail) + renderLink(row.part_detail.full_name, `/part/${row.part_detail.pk}/`); |                     html += imageHoverIcon(row.part_detail.thumbnail) + renderLink(row.part_detail.full_name, `/part/${row.part_detail.pk}/`); | ||||||
|  |  | ||||||
|                     if (row.bom_item_detail.allow_variants) { |                     if (row.bom_item_detail.allow_variants) { | ||||||
|                         html += makeIconBadge('fa-sitemap', '{% trans "Variant stock allowed" %}'); |                         html += makeIconBadge('fa-sitemap', '{% jstrans "Variant stock allowed" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.part_detail.trackable) { |                     if (row.part_detail.trackable) { | ||||||
|                         html += makeIconBadge('fa-directions', '{% trans "Trackable part" %}'); |                         html += makeIconBadge('fa-directions', '{% jstrans "Trackable part" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -2500,7 +2500,7 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Reference" %}', |                 title: '{% jstrans "Reference" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return row.bom_item_detail.reference; |                     return row.bom_item_detail.reference; | ||||||
| @@ -2508,7 +2508,7 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'consumable', |                 field: 'consumable', | ||||||
|                 title: '{% trans "Consumable" %}', |                 title: '{% jstrans "Consumable" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -2517,7 +2517,7 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'optional', |                 field: 'optional', | ||||||
|                 title: '{% trans "Optional" %}', |                 title: '{% jstrans "Optional" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -2527,7 +2527,7 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             { |             { | ||||||
|                 field: 'unit_quantity', |                 field: 'unit_quantity', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Unit Quantity" %}', |                 title: '{% jstrans "Unit Quantity" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let text = row.bom_item_detail.quantity; |                     let text = row.bom_item_detail.quantity; | ||||||
|  |  | ||||||
| @@ -2544,12 +2544,12 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Required Quantity" %}', |                 title: '{% jstrans "Required Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'available_stock', |                 field: 'available_stock', | ||||||
|                 title: '{% trans "Available" %}', |                 title: '{% jstrans "Available" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var url = `/part/${row.part_detail.pk}/?display=part-stock`; |                     var url = `/part/${row.part_detail.pk}/?display=part-stock`; | ||||||
| @@ -2573,24 +2573,24 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|                     let icons = ''; |                     let icons = ''; | ||||||
|  |  | ||||||
|                     if (row.bom_item_detail.consumable) { |                     if (row.bom_item_detail.consumable) { | ||||||
|                         icons += `<span class='fas fa-info-circle icon-blue float-right' title='{% trans "Consumable item" %}'></span>`; |                         icons += `<span class='fas fa-info-circle icon-blue float-right' title='{% jstrans "Consumable item" %}'></span>`; | ||||||
|                     } else { |                     } else { | ||||||
|                         if (available < (row.quantity - row.allocated)) { |                         if (available < (row.quantity - row.allocated)) { | ||||||
|                             icons += makeIconBadge('fa-times-circle icon-red', '{% trans "Insufficient stock available" %}'); |                             icons += makeIconBadge('fa-times-circle icon-red', '{% jstrans "Insufficient stock available" %}'); | ||||||
|                         } else { |                         } else { | ||||||
|                             icons += makeIconBadge('fa-check-circle icon-green', '{% trans "Sufficient stock available" %}'); |                             icons += makeIconBadge('fa-check-circle icon-green', '{% jstrans "Sufficient stock available" %}'); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         if (available <= 0) { |                         if (available <= 0) { | ||||||
|                             icons += `<span class='badge rounded-pill bg-danger'>{% trans "No Stock Available" %}</span>`; |                             icons += `<span class='badge rounded-pill bg-danger'>{% jstrans "No Stock Available" %}</span>`; | ||||||
|                         } else { |                         } else { | ||||||
|                             let extra = ''; |                             let extra = ''; | ||||||
|                             if ((row.available_substitute_stock > 0) && (row.available_variant_stock > 0)) { |                             if ((row.available_substitute_stock > 0) && (row.available_variant_stock > 0)) { | ||||||
|                                 extra = '{% trans "Includes variant and substitute stock" %}'; |                                 extra = '{% jstrans "Includes variant and substitute stock" %}'; | ||||||
|                             } else if (row.available_variant_stock > 0) { |                             } else if (row.available_variant_stock > 0) { | ||||||
|                                 extra = '{% trans "Includes variant stock" %}'; |                                 extra = '{% jstrans "Includes variant stock" %}'; | ||||||
|                             } else if (row.available_substitute_stock > 0) { |                             } else if (row.available_substitute_stock > 0) { | ||||||
|                                 extra = '{% trans "Includes substitute stock" %}'; |                                 extra = '{% jstrans "Includes substitute stock" %}'; | ||||||
|                             } |                             } | ||||||
|  |  | ||||||
|                             if (extra) { |                             if (extra) { | ||||||
| @@ -2600,7 +2600,7 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.on_order && row.on_order > 0) { |                     if (row.on_order && row.on_order > 0) { | ||||||
|                         icons += makeIconBadge('fa-shopping-cart', `{% trans "On Order" %}: ${formatDecimal(row.on_order)}`); |                         icons += makeIconBadge('fa-shopping-cart', `{% jstrans "On Order" %}: ${formatDecimal(row.on_order)}`); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return renderLink(text, url) + icons; |                     return renderLink(text, url) + icons; | ||||||
| @@ -2608,7 +2608,7 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'allocated', |                 field: 'allocated', | ||||||
|                 title: '{% trans "Allocated" %}', |                 title: '{% jstrans "Allocated" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return makeProgressBar(row.allocated, row.quantity); |                     return makeProgressBar(row.allocated, row.quantity); | ||||||
| @@ -2625,32 +2625,32 @@ function loadBuildLineTable(table, build_id, options={}) { | |||||||
|  |  | ||||||
|                     // Consumable items do not need to be allocated |                     // Consumable items do not need to be allocated | ||||||
|                     if (row.bom_item_detail.consumable) { |                     if (row.bom_item_detail.consumable) { | ||||||
|                         return `<em>{% trans "Consumable Item" %}</em>`; |                         return `<em>{% jstrans "Consumable Item" %}</em>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.part_detail.trackable && !options.output) { |                     if (row.part_detail.trackable && !options.output) { | ||||||
|                         // Tracked parts must be allocated to a specific build output |                         // Tracked parts must be allocated to a specific build output | ||||||
|                         return `<em>{% trans "Tracked item" %}</em>`; |                         return `<em>{% jstrans "Tracked item" %}</em>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.allocated < row.quantity) { |                     if (row.allocated < row.quantity) { | ||||||
|  |  | ||||||
|                         // Add a button to "build" stock for this line |                         // Add a button to "build" stock for this line | ||||||
|                         if (row.part_detail.assembly) { |                         if (row.part_detail.assembly) { | ||||||
|                             buttons += makeIconButton('fa-tools icon-blue', 'button-build', pk, '{% trans "Build stock" %}'); |                             buttons += makeIconButton('fa-tools icon-blue', 'button-build', pk, '{% jstrans "Build stock" %}'); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         // Add a button to "purchase" stock for this line |                         // Add a button to "purchase" stock for this line | ||||||
|                         if (row.part_detail.purchaseable) { |                         if (row.part_detail.purchaseable) { | ||||||
|                             buttons += makeIconButton('fa-shopping-cart icon-blue', 'button-buy', pk, '{% trans "Order stock" %}'); |                             buttons += makeIconButton('fa-shopping-cart icon-blue', 'button-buy', pk, '{% jstrans "Order stock" %}'); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         // Add a button to "allocate" stock for this line |                         // Add a button to "allocate" stock for this line | ||||||
|                         buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-allocate', pk, '{% trans "Allocate stock" %}'); |                         buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-allocate', pk, '{% jstrans "Allocate stock" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.allocated > 0) { |                     if (row.allocated > 0) { | ||||||
|                         buttons += makeRemoveButton('button-unallocate', pk, '{% trans "Remove stock allocation" %}'); |                         buttons += makeRemoveButton('button-unallocate', pk, '{% jstrans "Remove stock allocation" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return wrapButtons(buttons); |                     return wrapButtons(buttons); | ||||||
|   | |||||||
| @@ -95,7 +95,7 @@ function createManufacturerPart(options={}) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     fields.manufacturer.secondary = { |     fields.manufacturer.secondary = { | ||||||
|         title: '{% trans "Add Manufacturer" %}', |         title: '{% jstrans "Add Manufacturer" %}', | ||||||
|         fields: function() { |         fields: function() { | ||||||
|             var company_fields = companyFormFields(); |             var company_fields = companyFormFields(); | ||||||
|  |  | ||||||
| @@ -108,7 +108,7 @@ function createManufacturerPart(options={}) { | |||||||
|     constructForm('{% url "api-manufacturer-part-list" %}', { |     constructForm('{% url "api-manufacturer-part-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Manufacturer Part" %}', |         title: '{% jstrans "Add Manufacturer Part" %}', | ||||||
|         onSuccess: options.onSuccess |         onSuccess: options.onSuccess | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -129,7 +129,7 @@ function editManufacturerPart(part, options={}) { | |||||||
|  |  | ||||||
|     constructForm(url, { |     constructForm(url, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Edit Manufacturer Part" %}', |         title: '{% jstrans "Edit Manufacturer Part" %}', | ||||||
|         onSuccess: options.onSuccess |         onSuccess: options.onSuccess | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -198,7 +198,7 @@ function createSupplierPart(options={}) { | |||||||
|  |  | ||||||
|     // Add a secondary modal for the supplier |     // Add a secondary modal for the supplier | ||||||
|     fields.supplier.secondary = { |     fields.supplier.secondary = { | ||||||
|         title: '{% trans "Add Supplier" %}', |         title: '{% jstrans "Add Supplier" %}', | ||||||
|         fields: function() { |         fields: function() { | ||||||
|             var company_fields = companyFormFields(); |             var company_fields = companyFormFields(); | ||||||
|  |  | ||||||
| @@ -210,7 +210,7 @@ function createSupplierPart(options={}) { | |||||||
|  |  | ||||||
|     // Add a secondary modal for the manufacturer part |     // Add a secondary modal for the manufacturer part | ||||||
|     fields.manufacturer_part.secondary = { |     fields.manufacturer_part.secondary = { | ||||||
|         title: '{% trans "Add Manufacturer Part" %}', |         title: '{% jstrans "Add Manufacturer Part" %}', | ||||||
|         fields: function(data) { |         fields: function(data) { | ||||||
|             var mp_fields = manufacturerPartFields(); |             var mp_fields = manufacturerPartFields(); | ||||||
|  |  | ||||||
| @@ -240,7 +240,7 @@ function createSupplierPart(options={}) { | |||||||
|     constructForm('{% url "api-supplier-part-list" %}', { |     constructForm('{% url "api-supplier-part-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Supplier Part" %}', |         title: '{% jstrans "Add Supplier Part" %}', | ||||||
|         onSuccess: options.onSuccess, |         onSuccess: options.onSuccess, | ||||||
|         header_html: header, |         header_html: header, | ||||||
|     }); |     }); | ||||||
| @@ -266,7 +266,7 @@ function duplicateSupplierPart(part, options={}) { | |||||||
|             constructForm('{% url "api-supplier-part-list" %}', { |             constructForm('{% url "api-supplier-part-list" %}', { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 fields: fields, |                 fields: fields, | ||||||
|                 title: '{% trans "Duplicate Supplier Part" %}', |                 title: '{% jstrans "Duplicate Supplier Part" %}', | ||||||
|                 data: data, |                 data: data, | ||||||
|                 onSuccess: function(response) { |                 onSuccess: function(response) { | ||||||
|                     handleFormSuccess(response, options); |                     handleFormSuccess(response, options); | ||||||
| @@ -291,7 +291,7 @@ function editSupplierPart(part, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-supplier-part-list" %}${part}/`, { |     constructForm(`{% url "api-supplier-part-list" %}${part}/`, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: options.title || '{% trans "Edit Supplier Part" %}', |         title: options.title || '{% jstrans "Edit Supplier Part" %}', | ||||||
|         onSuccess: options.onSuccess |         onSuccess: options.onSuccess | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| @@ -341,14 +341,14 @@ function deleteSupplierParts(parts, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected supplier parts will be deleted" %} |     {% jstrans "All selected supplier parts will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|     <tr> |     <tr> | ||||||
|         <th>{% trans "Part" %}</th> |         <th>{% jstrans "Part" %}</th> | ||||||
|         <th>{% trans "SKU" %}</th> |         <th>{% jstrans "SKU" %}</th> | ||||||
|         <th>{% trans "Supplier" %}</th> |         <th>{% jstrans "Supplier" %}</th> | ||||||
|         <th>{% trans "MPN" %}</th> |         <th>{% jstrans "MPN" %}</th> | ||||||
|     </tr> |     </tr> | ||||||
|     ${rows} |     ${rows} | ||||||
|     </table> |     </table> | ||||||
| @@ -357,7 +357,7 @@ function deleteSupplierParts(parts, options={}) { | |||||||
|     constructForm('{% url "api-supplier-part-list" %}', { |     constructForm('{% url "api-supplier-part-list" %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete Supplier Parts" %}', |         title: '{% jstrans "Delete Supplier Parts" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
| @@ -395,7 +395,7 @@ function createSupplierPartPriceBreak(part_id, options={}) { | |||||||
|     constructForm('{% url "api-part-supplier-price-list" %}', { |     constructForm('{% url "api-part-supplier-price-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Price Break" %}', |         title: '{% jstrans "Add Price Break" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -441,7 +441,7 @@ function editCompany(pk, options={}) { | |||||||
|             method: 'PATCH', |             method: 'PATCH', | ||||||
|             fields: fields, |             fields: fields, | ||||||
|             reload: true, |             reload: true, | ||||||
|             title: '{% trans "Edit Company" %}', |             title: '{% jstrans "Edit Company" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| @@ -462,7 +462,7 @@ function createCompany(options={}) { | |||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             fields: fields, |             fields: fields, | ||||||
|             follow: true, |             follow: true, | ||||||
|             title: '{% trans "Add new Company" %}', |             title: '{% jstrans "Add new Company" %}', | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| @@ -492,22 +492,22 @@ function loadCompanyTable(table, url, options={}) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             field: 'name', |             field: 'name', | ||||||
|             title: '{% trans "Company" %}', |             title: '{% jstrans "Company" %}', | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             switchable: false, |             switchable: false, | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
|                 var html = imageHoverIcon(row.image) + renderLink(value, row.url); |                 var html = imageHoverIcon(row.image) + renderLink(value, row.url); | ||||||
|  |  | ||||||
|                 if (row.is_customer) { |                 if (row.is_customer) { | ||||||
|                     html += `<span title='{% trans "Customer" %}' class='fas fa-user-tie float-right'></span>`; |                     html += `<span title='{% jstrans "Customer" %}' class='fas fa-user-tie float-right'></span>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (row.is_manufacturer) { |                 if (row.is_manufacturer) { | ||||||
|                     html += `<span title='{% trans "Manufacturer" %}' class='fas fa-industry float-right'></span>`; |                     html += `<span title='{% jstrans "Manufacturer" %}' class='fas fa-industry float-right'></span>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (row.is_supplier) { |                 if (row.is_supplier) { | ||||||
|                     html += `<span title='{% trans "Supplier" %}' class='fas fa-building float-right'></span>`; |                     html += `<span title='{% jstrans "Supplier" %}' class='fas fa-building float-right'></span>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 return html; |                 return html; | ||||||
| @@ -515,11 +515,11 @@ function loadCompanyTable(table, url, options={}) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             field: 'description', |             field: 'description', | ||||||
|             title: '{% trans "Description" %}', |             title: '{% jstrans "Description" %}', | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             field: 'website', |             field: 'website', | ||||||
|             title: '{% trans "Website" %}', |             title: '{% jstrans "Website" %}', | ||||||
|             formatter: function(value) { |             formatter: function(value) { | ||||||
|                 if (value) { |                 if (value) { | ||||||
|                     return renderLink(value, value); |                     return renderLink(value, value); | ||||||
| @@ -533,7 +533,7 @@ function loadCompanyTable(table, url, options={}) { | |||||||
|         columns.push({ |         columns.push({ | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             field: 'parts_supplied', |             field: 'parts_supplied', | ||||||
|             title: '{% trans "Parts Supplied" %}', |             title: '{% jstrans "Parts Supplied" %}', | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
|                 return renderLink(value, `/company/${row.pk}/?display=supplier-parts`); |                 return renderLink(value, `/company/${row.pk}/?display=supplier-parts`); | ||||||
|             } |             } | ||||||
| @@ -542,7 +542,7 @@ function loadCompanyTable(table, url, options={}) { | |||||||
|         columns.push({ |         columns.push({ | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             field: 'parts_manufactured', |             field: 'parts_manufactured', | ||||||
|             title: '{% trans "Parts Manufactured" %}', |             title: '{% jstrans "Parts Manufactured" %}', | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
|                 return renderLink(value, `/company/${row.pk}/?display=manufacturer-parts`); |                 return renderLink(value, `/company/${row.pk}/?display=manufacturer-parts`); | ||||||
|             } |             } | ||||||
| @@ -557,7 +557,7 @@ function loadCompanyTable(table, url, options={}) { | |||||||
|         groupBy: false, |         groupBy: false, | ||||||
|         sidePagination: 'server', |         sidePagination: 'server', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No company information found" %}'; |             return '{% jstrans "No company information found" %}'; | ||||||
|         }, |         }, | ||||||
|         showColumns: true, |         showColumns: true, | ||||||
|         name: options.pagetype || 'company', |         name: options.pagetype || 'company', | ||||||
| @@ -606,7 +606,7 @@ function createContact(options={}) { | |||||||
|     constructForm('{% url "api-contact-list" %}', { |     constructForm('{% url "api-contact-list" %}', { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Create New Contact" %}', |         title: '{% jstrans "Create New Contact" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -622,7 +622,7 @@ function editContact(pk, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-contact-list" %}${pk}/`, { |     constructForm(`{% url "api-contact-list" %}${pk}/`, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Edit Contact" %}', |         title: '{% jstrans "Edit Contact" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -659,13 +659,13 @@ function deleteContacts(contacts, options={}) { | |||||||
|     // eslint-disable-next-line no-useless-escape |     // eslint-disable-next-line no-useless-escape | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected contacts will be deleted" %} |     {% jstrans "All selected contacts will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|     <tr> |     <tr> | ||||||
|         <th>{% trans "Name" %}</th> |         <th>{% jstrans "Name" %}</th> | ||||||
|         <th>{% trans "Email" %}</th> |         <th>{% jstrans "Email" %}</th> | ||||||
|         <th>{% trans "Role" %}</th> |         <th>{% jstrans "Role" %}</th> | ||||||
|     </tr> |     </tr> | ||||||
|     ${rows} |     ${rows} | ||||||
|     </table>`; |     </table>`; | ||||||
| @@ -673,7 +673,7 @@ function deleteContacts(contacts, options={}) { | |||||||
|     constructForm('{% url "api-contact-list" %}', { |     constructForm('{% url "api-contact-list" %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete Contacts" %}', |         title: '{% jstrans "Delete Contacts" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
| @@ -704,32 +704,32 @@ function loadContactTable(table, options={}) { | |||||||
|         uniqueId: 'pk', |         uniqueId: 'pk', | ||||||
|         sidePagination: 'server', |         sidePagination: 'server', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No contacts found" %}'; |             return '{% jstrans "No contacts found" %}'; | ||||||
|         }, |         }, | ||||||
|         showColumns: true, |         showColumns: true, | ||||||
|         name: 'contacts', |         name: 'contacts', | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 title: '{% trans "Name" %}', |                 title: '{% jstrans "Name" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'phone', |                 field: 'phone', | ||||||
|                 title: '{% trans "Phone Number" %}', |                 title: '{% jstrans "Phone Number" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'email', |                 field: 'email', | ||||||
|                 title: '{% trans "Email Address" %}', |                 title: '{% jstrans "Email Address" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'role', |                 field: 'role', | ||||||
|                 title: '{% trans "Role" %}', |                 title: '{% jstrans "Role" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
| @@ -745,11 +745,11 @@ function loadContactTable(table, options={}) { | |||||||
|                     let html = ''; |                     let html = ''; | ||||||
|  |  | ||||||
|                     if (options.allow_edit) { |                     if (options.allow_edit) { | ||||||
|                         html += makeEditButton('btn-contact-edit', pk, '{% trans "Edit Contact" %}'); |                         html += makeEditButton('btn-contact-edit', pk, '{% jstrans "Edit Contact" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (options.allow_delete) { |                     if (options.allow_delete) { | ||||||
|                         html += makeDeleteButton('btn-contact-delete', pk, '{% trans "Delete Contact" %}'); |                         html += makeDeleteButton('btn-contact-delete', pk, '{% jstrans "Delete Contact" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return wrapButtons(html); |                     return wrapButtons(html); | ||||||
| @@ -846,7 +846,7 @@ function createAddress(options={}) { | |||||||
|     constructForm('{% url "api-address-list" %}', { |     constructForm('{% url "api-address-list" %}', { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Create New Address" %}', |         title: '{% jstrans "Create New Address" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -861,7 +861,7 @@ function editAddress(pk, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-address-list" %}${pk}/`, { |     constructForm(`{% url "api-address-list" %}${pk}/`, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Edit Address" %}', |         title: '{% jstrans "Edit Address" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -896,13 +896,13 @@ function deleteAddress(addresses, options={}) { | |||||||
|  |  | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected addresses will be deleted" %} |     {% jstrans "All selected addresses will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|     <tr> |     <tr> | ||||||
|         <th>{% trans "Name" %}</th> |         <th>{% jstrans "Name" %}</th> | ||||||
|         <th>{% trans "Line 1" %}</th> |         <th>{% jstrans "Line 1" %}</th> | ||||||
|         <th>{% trans "Line 2" %}</th> |         <th>{% jstrans "Line 2" %}</th> | ||||||
|     </tr> |     </tr> | ||||||
|     ${rows} |     ${rows} | ||||||
|     </table>`; |     </table>`; | ||||||
| @@ -910,7 +910,7 @@ function deleteAddress(addresses, options={}) { | |||||||
|     constructForm('{% url "api-address-list" %}', { |     constructForm('{% url "api-address-list" %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete Addresses" %}', |         title: '{% jstrans "Delete Addresses" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
| @@ -937,14 +937,14 @@ function loadAddressTable(table, options={}) { | |||||||
|         sidePagination: 'server', |         sidePagination: 'server', | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No addresses found" %}'; |             return '{% jstrans "No addresses found" %}'; | ||||||
|         }, |         }, | ||||||
|         showColumns: true, |         showColumns: true, | ||||||
|         name: 'addresses', |         name: 'addresses', | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'primary', |                 field: 'primary', | ||||||
|                 title: '{% trans "Primary" %}', |                 title: '{% jstrans "Primary" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return yesNoLabel(value); |                     return yesNoLabel(value); | ||||||
| @@ -952,61 +952,61 @@ function loadAddressTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'title', |                 field: 'title', | ||||||
|                 title: '{% trans "Title" %}', |                 title: '{% jstrans "Title" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'line1', |                 field: 'line1', | ||||||
|                 title: '{% trans "Line 1" %}', |                 title: '{% jstrans "Line 1" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'line2', |                 field: 'line2', | ||||||
|                 title: '{% trans "Line 2" %}', |                 title: '{% jstrans "Line 2" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'postal_code', |                 field: 'postal_code', | ||||||
|                 title: '{% trans "Postal code" %}', |                 title: '{% jstrans "Postal code" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'postal_city', |                 field: 'postal_city', | ||||||
|                 title: '{% trans "Postal city" %}', |                 title: '{% jstrans "Postal city" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'province', |                 field: 'province', | ||||||
|                 title: '{% trans "State/province" %}', |                 title: '{% jstrans "State/province" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'country', |                 field: 'country', | ||||||
|                 title: '{% trans "Country" %}', |                 title: '{% jstrans "Country" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'shipping_notes', |                 field: 'shipping_notes', | ||||||
|                 title: '{% trans "Courier notes" %}', |                 title: '{% jstrans "Courier notes" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'internal_shipping_notes', |                 field: 'internal_shipping_notes', | ||||||
|                 title: '{% trans "Internal notes" %}', |                 title: '{% jstrans "Internal notes" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 title: '{% trans "External Link" %}', |                 title: '{% jstrans "External Link" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
| @@ -1022,11 +1022,11 @@ function loadAddressTable(table, options={}) { | |||||||
|                     let html = ''; |                     let html = ''; | ||||||
|  |  | ||||||
|                     if (options.allow_edit) { |                     if (options.allow_edit) { | ||||||
|                         html += makeEditButton('btn-address-edit', pk, '{% trans "Edit Address" %}'); |                         html += makeEditButton('btn-address-edit', pk, '{% jstrans "Edit Address" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (options.allow_delete) { |                     if (options.allow_delete) { | ||||||
|                         html += makeDeleteButton('btn-address-delete', pk, '{% trans "Delete Address" %}'); |                         html += makeDeleteButton('btn-address-delete', pk, '{% jstrans "Delete Address" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return wrapButtons(html); |                     return wrapButtons(html); | ||||||
| @@ -1099,13 +1099,13 @@ function deleteManufacturerParts(selections, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected manufacturer parts will be deleted" %} |     {% jstrans "All selected manufacturer parts will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|     <tr> |     <tr> | ||||||
|         <th>{% trans "Part" %}</th> |         <th>{% jstrans "Part" %}</th> | ||||||
|         <th>{% trans "MPN" %}</th> |         <th>{% jstrans "MPN" %}</th> | ||||||
|         <th>{% trans "Manufacturer" %}</th> |         <th>{% jstrans "Manufacturer" %}</th> | ||||||
|     </tr> |     </tr> | ||||||
|     ${rows} |     ${rows} | ||||||
|     </table> |     </table> | ||||||
| @@ -1114,7 +1114,7 @@ function deleteManufacturerParts(selections, options={}) { | |||||||
|     constructForm('{% url "api-manufacturer-part-list" %}', { |     constructForm('{% url "api-manufacturer-part-list" %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete Manufacturer Parts" %}', |         title: '{% jstrans "Delete Manufacturer Parts" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
| @@ -1148,12 +1148,12 @@ function deleteManufacturerPartParameters(selections, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected parameters will be deleted" %} |     {% jstrans "All selected parameters will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|     <tr> |     <tr> | ||||||
|         <th>{% trans "Name" %}</th> |         <th>{% jstrans "Name" %}</th> | ||||||
|         <th>{% trans "Value" %}</th> |         <th>{% jstrans "Value" %}</th> | ||||||
|     </tr> |     </tr> | ||||||
|     ${rows} |     ${rows} | ||||||
|     </table> |     </table> | ||||||
| @@ -1162,7 +1162,7 @@ function deleteManufacturerPartParameters(selections, options={}) { | |||||||
|     constructForm('{% url "api-manufacturer-part-parameter-list" %}', { |     constructForm('{% url "api-manufacturer-part-parameter-list" %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete Parameters" %}', |         title: '{% jstrans "Delete Parameters" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
| @@ -1178,7 +1178,7 @@ function makeManufacturerPartActions(options={}) { | |||||||
|     return [ |     return [ | ||||||
|         { |         { | ||||||
|             label: 'order', |             label: 'order', | ||||||
|             title: '{% trans "Order parts" %}', |             title: '{% jstrans "Order parts" %}', | ||||||
|             icon: 'fa-shopping-cart', |             icon: 'fa-shopping-cart', | ||||||
|             permission: 'purchase_order.add', |             permission: 'purchase_order.add', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1195,7 +1195,7 @@ function makeManufacturerPartActions(options={}) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             label: 'delete', |             label: 'delete', | ||||||
|             title: '{% trans "Delete manufacturer parts" %}', |             title: '{% jstrans "Delete manufacturer parts" %}', | ||||||
|             icon: 'fa-trash-alt icon-red', |             icon: 'fa-trash-alt icon-red', | ||||||
|             permission: 'purchase_order.delete', |             permission: 'purchase_order.delete', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1227,7 +1227,7 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|         custom_actions: [ |         custom_actions: [ | ||||||
|             { |             { | ||||||
|                 label: 'manufacturer-part', |                 label: 'manufacturer-part', | ||||||
|                 title: '{% trans "Manufacturer part actions" %}', |                 title: '{% jstrans "Manufacturer part actions" %}', | ||||||
|                 icon: 'fa-tools', |                 icon: 'fa-tools', | ||||||
|                 actions: makeManufacturerPartActions({ |                 actions: makeManufacturerPartActions({ | ||||||
|                     manufacturer_id: options.params.manufacturer, |                     manufacturer_id: options.params.manufacturer, | ||||||
| @@ -1246,7 +1246,7 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|         name: 'manufacturerparts', |         name: 'manufacturerparts', | ||||||
|         groupBy: false, |         groupBy: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No manufacturer parts found" %}'; |             return '{% jstrans "No manufacturer parts found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
| @@ -1258,7 +1258,7 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|                 switchable: params['part_detail'], |                 switchable: params['part_detail'], | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'part_detail.full_name', |                 field: 'part_detail.full_name', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     var url = `/part/${row.part}/`; |                     var url = `/part/${row.part}/`; | ||||||
| @@ -1266,15 +1266,15 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|                     var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url); |                     var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url); | ||||||
|  |  | ||||||
|                     if (row.part_detail.is_template) { |                     if (row.part_detail.is_template) { | ||||||
|                         html += makeIconBadge('fa-clone', '{% trans "Template part" %}'); |                         html += makeIconBadge('fa-clone', '{% jstrans "Template part" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.part_detail.assembly) { |                     if (row.part_detail.assembly) { | ||||||
|                         html += makeIconBadge('fa-tools', '{% trans "Assembled part" %}'); |                         html += makeIconBadge('fa-tools', '{% jstrans "Assembled part" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (!row.part_detail.active) { |                     if (!row.part_detail.active) { | ||||||
|                         html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`; |                         html += `<span class='badge badge-right rounded-pill bg-warning'>{% jstrans "Inactive" %}</span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -1283,7 +1283,7 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'manufacturer', |                 field: 'manufacturer', | ||||||
|                 title: '{% trans "Manufacturer" %}', |                 title: '{% jstrans "Manufacturer" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value && row.manufacturer_detail) { |                     if (value && row.manufacturer_detail) { | ||||||
|                         var name = row.manufacturer_detail.name; |                         var name = row.manufacturer_detail.name; | ||||||
| @@ -1299,14 +1299,14 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'MPN', |                 field: 'MPN', | ||||||
|                 title: '{% trans "MPN" %}', |                 title: '{% jstrans "MPN" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return renderClipboard(renderLink(value, `/manufacturer-part/${row.pk}/`)); |                     return renderClipboard(renderLink(value, `/manufacturer-part/${row.pk}/`)); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value, {external: true}); |                         return renderLink(value, value, {external: true}); | ||||||
| @@ -1317,7 +1317,7 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
| @@ -1330,8 +1330,8 @@ function loadManufacturerPartTable(table, url, options) { | |||||||
|                     let pk = row.pk; |                     let pk = row.pk; | ||||||
|                     let html = ''; |                     let html = ''; | ||||||
|  |  | ||||||
|                     html += makeEditButton('button-manufacturer-part-edit', pk, '{% trans "Edit manufacturer part" %}'); |                     html += makeEditButton('button-manufacturer-part-edit', pk, '{% jstrans "Edit manufacturer part" %}'); | ||||||
|                     html += makeDeleteButton('button-manufacturer-part-delete', pk, '{% trans "Delete manufacturer part" %}'); |                     html += makeDeleteButton('button-manufacturer-part-delete', pk, '{% jstrans "Delete manufacturer part" %}'); | ||||||
|  |  | ||||||
|                     return wrapButtons(html); |                     return wrapButtons(html); | ||||||
|                 } |                 } | ||||||
| @@ -1390,7 +1390,7 @@ function loadManufacturerPartParameterTable(table, url, options) { | |||||||
|         name: 'manufacturerpartparameters', |         name: 'manufacturerpartparameters', | ||||||
|         groupBy: false, |         groupBy: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No parameters found" %}'; |             return '{% jstrans "No parameters found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
| @@ -1400,19 +1400,19 @@ function loadManufacturerPartParameterTable(table, url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 title: '{% trans "Name" %}', |                 title: '{% jstrans "Name" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'value', |                 field: 'value', | ||||||
|                 title: '{% trans "Value" %}', |                 title: '{% jstrans "Value" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'units', |                 field: 'units', | ||||||
|                 title: '{% trans "Units" %}', |                 title: '{% jstrans "Units" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
| @@ -1425,8 +1425,8 @@ function loadManufacturerPartParameterTable(table, url, options) { | |||||||
|                     let pk = row.pk; |                     let pk = row.pk; | ||||||
|                     let html = ''; |                     let html = ''; | ||||||
|  |  | ||||||
|                     html += makeEditButton('button-parameter-edit', pk, '{% trans "Edit parameter" %}'); |                     html += makeEditButton('button-parameter-edit', pk, '{% jstrans "Edit parameter" %}'); | ||||||
|                     html += makeDeleteButton('button-parameter-delete', pk, '{% trans "Delete parameter" %}'); |                     html += makeDeleteButton('button-parameter-delete', pk, '{% jstrans "Delete parameter" %}'); | ||||||
|  |  | ||||||
|                     return wrapButtons(html); |                     return wrapButtons(html); | ||||||
|                 } |                 } | ||||||
| @@ -1443,7 +1443,7 @@ function loadManufacturerPartParameterTable(table, url, options) { | |||||||
|                         value: {}, |                         value: {}, | ||||||
|                         units: {}, |                         units: {}, | ||||||
|                     }, |                     }, | ||||||
|                     title: '{% trans "Edit Parameter" %}', |                     title: '{% jstrans "Edit Parameter" %}', | ||||||
|                     refreshTable: table, |                     refreshTable: table, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -1452,7 +1452,7 @@ function loadManufacturerPartParameterTable(table, url, options) { | |||||||
|  |  | ||||||
|                 constructForm(`{% url "api-manufacturer-part-parameter-list" %}${pk}/`, { |                 constructForm(`{% url "api-manufacturer-part-parameter-list" %}${pk}/`, { | ||||||
|                     method: 'DELETE', |                     method: 'DELETE', | ||||||
|                     title: '{% trans "Delete Parameter" %}', |                     title: '{% jstrans "Delete Parameter" %}', | ||||||
|                     refreshTable: table, |                     refreshTable: table, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -1466,7 +1466,7 @@ function makeSupplierPartActions(options={}) { | |||||||
|     return [ |     return [ | ||||||
|         { |         { | ||||||
|             label: 'order', |             label: 'order', | ||||||
|             title: '{% trans "Order parts" %}', |             title: '{% jstrans "Order parts" %}', | ||||||
|             icon: 'fa-shopping-cart', |             icon: 'fa-shopping-cart', | ||||||
|             permission: 'purchase_order.add', |             permission: 'purchase_order.add', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1483,7 +1483,7 @@ function makeSupplierPartActions(options={}) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             label: 'delete', |             label: 'delete', | ||||||
|             title: '{% trans "Delete supplier parts" %}', |             title: '{% jstrans "Delete supplier parts" %}', | ||||||
|             icon: 'fa-trash-alt icon-red', |             icon: 'fa-trash-alt icon-red', | ||||||
|             permission: 'purchase_order.delete', |             permission: 'purchase_order.delete', | ||||||
|             callback: function(data) { |             callback: function(data) { | ||||||
| @@ -1513,7 +1513,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|         custom_actions: [ |         custom_actions: [ | ||||||
|             { |             { | ||||||
|                 label: 'supplier-part', |                 label: 'supplier-part', | ||||||
|                 title: '{% trans "Supplier part actions" %}', |                 title: '{% jstrans "Supplier part actions" %}', | ||||||
|                 icon: 'fa-tools', |                 icon: 'fa-tools', | ||||||
|                 actions: makeSupplierPartActions({ |                 actions: makeSupplierPartActions({ | ||||||
|                     supplier_id: options.params.supplier, |                     supplier_id: options.params.supplier, | ||||||
| @@ -1533,7 +1533,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|         groupBy: false, |         groupBy: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No supplier parts found" %}'; |             return '{% jstrans "No supplier parts found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
| @@ -1546,7 +1546,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'part_detail.full_name', |                 field: 'part_detail.full_name', | ||||||
|                 sortName: 'part', |                 sortName: 'part', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     var url = `/part/${row.part}/`; |                     var url = `/part/${row.part}/`; | ||||||
| @@ -1554,15 +1554,15 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                     var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url); |                     var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url); | ||||||
|  |  | ||||||
|                     if (row.part_detail.is_template) { |                     if (row.part_detail.is_template) { | ||||||
|                         html += makeIconBadge('fa-clone', '{% trans "Template part" %}'); |                         html += makeIconBadge('fa-clone', '{% jstrans "Template part" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.part_detail.assembly) { |                     if (row.part_detail.assembly) { | ||||||
|                         html += makeIconBadge('fa-tools', '{% trans "Assembled part" %}'); |                         html += makeIconBadge('fa-tools', '{% jstrans "Assembled part" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (!row.part_detail.active) { |                     if (!row.part_detail.active) { | ||||||
|                         html += `<span class='badge badge-right rounded-pill bg-warning'>{% trans "Inactive" %}</span>`; |                         html += `<span class='badge badge-right rounded-pill bg-warning'>{% jstrans "Inactive" %}</span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -1571,7 +1571,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'supplier', |                 field: 'supplier', | ||||||
|                 title: '{% trans "Supplier" %}', |                 title: '{% jstrans "Supplier" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         var name = row.supplier_detail.name; |                         var name = row.supplier_detail.name; | ||||||
| @@ -1587,7 +1587,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'SKU', |                 field: 'SKU', | ||||||
|                 title: '{% trans "Supplier Part" %}', |                 title: '{% jstrans "Supplier Part" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return renderClipboard(renderLink(value, `/supplier-part/${row.pk}/`)); |                     return renderClipboard(renderLink(value, `/supplier-part/${row.pk}/`)); | ||||||
|                 } |                 } | ||||||
| @@ -1598,7 +1598,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'manufacturer', |                 sortName: 'manufacturer', | ||||||
|                 field: 'manufacturer_detail.name', |                 field: 'manufacturer_detail.name', | ||||||
|                 title: '{% trans "Manufacturer" %}', |                 title: '{% jstrans "Manufacturer" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value && row.manufacturer_detail) { |                     if (value && row.manufacturer_detail) { | ||||||
|                         var name = value; |                         var name = value; | ||||||
| @@ -1617,7 +1617,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'MPN', |                 sortName: 'MPN', | ||||||
|                 field: 'manufacturer_part_detail.MPN', |                 field: 'manufacturer_part_detail.MPN', | ||||||
|                 title: '{% trans "MPN" %}', |                 title: '{% jstrans "MPN" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value && row.manufacturer_part) { |                     if (value && row.manufacturer_part) { | ||||||
|                         return renderClipboard(renderLink(value, `/manufacturer-part/${row.manufacturer_part}/`)); |                         return renderClipboard(renderLink(value, `/manufacturer-part/${row.manufacturer_part}/`)); | ||||||
| @@ -1628,17 +1628,17 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'packaging', |                 field: 'packaging', | ||||||
|                 title: '{% trans "Packaging" %}', |                 title: '{% jstrans "Packaging" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'pack_quantity', |                 field: 'pack_quantity', | ||||||
|                 title: '{% trans "Pack Quantity" %}', |                 title: '{% jstrans "Pack Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
| @@ -1651,7 +1651,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.part_detail && row.part_detail.units) { |                     if (row.part_detail && row.part_detail.units) { | ||||||
|                         html += `<span class='fas fa-info-circle float-right' title='{% trans "Base Units" %}: ${row.part_detail.units}'></span>`; |                         html += `<span class='fas fa-info-circle float-right' title='{% jstrans "Base Units" %}: ${row.part_detail.units}'></span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -1660,7 +1660,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value, {external: true}); |                         return renderLink(value, value, {external: true}); | ||||||
| @@ -1671,17 +1671,17 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'note', |                 field: 'note', | ||||||
|                 title: '{% trans "Notes" %}', |                 title: '{% jstrans "Notes" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'in_stock', |                 field: 'in_stock', | ||||||
|                 title: '{% trans "In Stock" %}', |                 title: '{% jstrans "In Stock" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'available', |                 field: 'available', | ||||||
|                 title: '{% trans "Availability" %}', |                 title: '{% jstrans "Availability" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (row.availability_updated) { |                     if (row.availability_updated) { | ||||||
| @@ -1690,7 +1690,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|  |  | ||||||
|                         html += makeIconBadge( |                         html += makeIconBadge( | ||||||
|                             'fa-info-circle', |                             'fa-info-circle', | ||||||
|                             `{% trans "Last Updated" %}: ${date}` |                             `{% jstrans "Last Updated" %}: ${date}` | ||||||
|                         ); |                         ); | ||||||
|                         return html; |                         return html; | ||||||
|                     } else { |                     } else { | ||||||
| @@ -1700,7 +1700,7 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'updated', |                 field: 'updated', | ||||||
|                 title: '{% trans "Last Updated" %}', |                 title: '{% jstrans "Last Updated" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -1712,8 +1712,8 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                     let pk = row.pk; |                     let pk = row.pk; | ||||||
|                     let html = ''; |                     let html = ''; | ||||||
|  |  | ||||||
|                     html += makeEditButton('button-supplier-part-edit', pk, '{% trans "Edit supplier part" %}'); |                     html += makeEditButton('button-supplier-part-edit', pk, '{% jstrans "Edit supplier part" %}'); | ||||||
|                     html += makeDeleteButton('button-supplier-part-delete', pk, '{% trans "Delete supplier part" %}'); |                     html += makeDeleteButton('button-supplier-part-delete', pk, '{% jstrans "Delete supplier part" %}'); | ||||||
|  |  | ||||||
|                     return wrapButtons(html); |                     return wrapButtons(html); | ||||||
|                 } |                 } | ||||||
| @@ -1766,7 +1766,7 @@ function loadSupplierPriceBreakTable(options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-part-supplier-price-list" %}${pk}/`, { |             constructForm(`{% url "api-part-supplier-price-list" %}${pk}/`, { | ||||||
|                 method: 'DELETE', |                 method: 'DELETE', | ||||||
|                 title: '{% trans "Delete Price Break" %}', |                 title: '{% jstrans "Delete Price Break" %}', | ||||||
|                 refreshTable: table, |                 refreshTable: table, | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @@ -1776,7 +1776,7 @@ function loadSupplierPriceBreakTable(options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-part-supplier-price-list" %}${pk}/`, { |             constructForm(`{% url "api-part-supplier-price-list" %}${pk}/`, { | ||||||
|                 fields: supplierPartPriceBreakFields(), |                 fields: supplierPartPriceBreakFields(), | ||||||
|                 title: '{% trans "Edit Price Break" %}', |                 title: '{% jstrans "Edit Price Break" %}', | ||||||
|                 refreshTable: table, |                 refreshTable: table, | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @@ -1791,7 +1791,7 @@ function loadSupplierPriceBreakTable(options={}) { | |||||||
|             part: options.part, |             part: options.part, | ||||||
|         }, |         }, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No price break information found" %}'; |             return '{% jstrans "No price break information found" %}'; | ||||||
|         }, |         }, | ||||||
|         onPostBody: function() { |         onPostBody: function() { | ||||||
|             setupCallbacks(); |             setupCallbacks(); | ||||||
| @@ -1805,12 +1805,12 @@ function loadSupplierPriceBreakTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'price', |                 field: 'price', | ||||||
|                 title: '{% trans "Price" %}', |                 title: '{% jstrans "Price" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row, index) { |                 formatter: function(value, row, index) { | ||||||
|                     return formatCurrency(value, { |                     return formatCurrency(value, { | ||||||
| @@ -1820,15 +1820,15 @@ function loadSupplierPriceBreakTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'updated', |                 field: 'updated', | ||||||
|                 title: '{% trans "Last updated" %}', |                 title: '{% jstrans "Last updated" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = renderDate(value); |                     var html = renderDate(value); | ||||||
|  |  | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|  |  | ||||||
|                     buttons += makeEditButton('button-price-break-edit', row.pk, '{% trans "Edit price break" %}'); |                     buttons += makeEditButton('button-price-break-edit', row.pk, '{% jstrans "Edit price break" %}'); | ||||||
|                     buttons += makeDeleteButton('button-price-break-delete', row.pk, '{% trans "Delete price break" %}'); |                     buttons += makeDeleteButton('button-price-break-delete', row.pk, '{% jstrans "Delete price break" %}'); | ||||||
|  |  | ||||||
|                     html += wrapButtons(buttons); |                     html += wrapButtons(buttons); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -183,11 +183,11 @@ function getFilterOptionList(tableKey, filterKey) { | |||||||
|         return { |         return { | ||||||
|             '1': { |             '1': { | ||||||
|                 key: '1', |                 key: '1', | ||||||
|                 value: '{% trans "true" %}', |                 value: '{% jstrans "true" %}', | ||||||
|             }, |             }, | ||||||
|             '0': { |             '0': { | ||||||
|                 key: '0', |                 key: '0', | ||||||
|                 value: '{% trans "false" %}', |                 value: '{% jstrans "false" %}', | ||||||
|             }, |             }, | ||||||
|         }; |         }; | ||||||
|     } else if (settings.type == 'date') { |     } else if (settings.type == 'date') { | ||||||
| @@ -211,7 +211,7 @@ function generateAvailableFilterList(tableKey) { | |||||||
|  |  | ||||||
|     var html = `<select class='form-control filter-input' id='${id}' name='tag'>`; |     var html = `<select class='form-control filter-input' id='${id}' name='tag'>`; | ||||||
|  |  | ||||||
|     html += `<option value=''>{% trans 'Select filter' %}</option>`; |     html += `<option value=''>{% jstrans 'Select filter' %}</option>`; | ||||||
|  |  | ||||||
|     for (var opt in remaining) { |     for (var opt in remaining) { | ||||||
|         var title = getFilterTitle(tableKey, opt); |         var title = getFilterTitle(tableKey, opt); | ||||||
| @@ -293,7 +293,7 @@ function makeCustomActionGroup(action_group, table) { | |||||||
|  |  | ||||||
|     let buttons = []; |     let buttons = []; | ||||||
|     let label = action_group.label || 'actions'; |     let label = action_group.label || 'actions'; | ||||||
|     let title = action_group.title || '{% trans "Actions" %}'; |     let title = action_group.title || '{% jstrans "Actions" %}'; | ||||||
|     let icon = action_group.icon || 'fa-tools'; |     let icon = action_group.icon || 'fa-tools'; | ||||||
|  |  | ||||||
|     // Construct the HTML for each button |     // Construct the HTML for each button | ||||||
| @@ -332,7 +332,7 @@ function makeBarcodeActions(barcode_actions, table) { | |||||||
|  |  | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='btn-group' role='group'> |     <div class='btn-group' role='group'> | ||||||
|     <button id='barcode-actions' title='{% trans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'> |     <button id='barcode-actions' title='{% jstrans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'> | ||||||
|         <span class='fas fa-qrcode'></span> |         <span class='fas fa-qrcode'></span> | ||||||
|     </button> |     </button> | ||||||
|     <ul class='dropdown-menu' role='menu'> |     <ul class='dropdown-menu' role='menu'> | ||||||
| @@ -428,17 +428,17 @@ function setupFilterList(tableKey, table, target, options={}) { | |||||||
|     if (report_button || labels_button) { |     if (report_button || labels_button) { | ||||||
|         let print_buttons = ` |         let print_buttons = ` | ||||||
|         <div class='btn-group' role='group'> |         <div class='btn-group' role='group'> | ||||||
|         <button id='printing-options' title='{% trans "Printing actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'> |         <button id='printing-options' title='{% jstrans "Printing actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'> | ||||||
|             <span class='fas fa-print'></span> <span class='caret'></span> |             <span class='fas fa-print'></span> <span class='caret'></span> | ||||||
|         </button> |         </button> | ||||||
|         <ul class='dropdown-menu' role='menu'>`; |         <ul class='dropdown-menu' role='menu'>`; | ||||||
|  |  | ||||||
|         if (labels_button) { |         if (labels_button) { | ||||||
|             print_buttons += `<li><a class='dropdown-item' href='#' id='print-labels-${tableKey}'><span class='fas fa-tag'></span> {% trans "Print Labels" %}</a></li>`; |             print_buttons += `<li><a class='dropdown-item' href='#' id='print-labels-${tableKey}'><span class='fas fa-tag'></span> {% jstrans "Print Labels" %}</a></li>`; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (report_button) { |         if (report_button) { | ||||||
|             print_buttons += `<li><a class='dropdown-item' href='#' id='print-report-${tableKey}'><span class='fas fa-file-pdf'></span> {% trans "Print Reports" %}</a></li>`; |             print_buttons += `<li><a class='dropdown-item' href='#' id='print-report-${tableKey}'><span class='fas fa-file-pdf'></span> {% jstrans "Print Reports" %}</a></li>`; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         print_buttons += `</ul></div>`; |         print_buttons += `</ul></div>`; | ||||||
| @@ -450,14 +450,14 @@ function setupFilterList(tableKey, table, target, options={}) { | |||||||
|     if (options.download) { |     if (options.download) { | ||||||
|         buttons += makeFilterButton({ |         buttons += makeFilterButton({ | ||||||
|             id: `download-${tableKey}`, |             id: `download-${tableKey}`, | ||||||
|             title: '{% trans "Download table data" %}', |             title: '{% jstrans "Download table data" %}', | ||||||
|             icon: 'fa-download', |             icon: 'fa-download', | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     buttons += makeFilterButton({ |     buttons += makeFilterButton({ | ||||||
|         id: `reload-${tableKey}`, |         id: `reload-${tableKey}`, | ||||||
|         title: '{% trans "Reload table data" %}', |         title: '{% jstrans "Reload table data" %}', | ||||||
|         icon: 'fa-redo-alt', |         icon: 'fa-redo-alt', | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
| @@ -466,7 +466,7 @@ function setupFilterList(tableKey, table, target, options={}) { | |||||||
|  |  | ||||||
|         buttons += makeFilterButton({ |         buttons += makeFilterButton({ | ||||||
|             id: add, |             id: add, | ||||||
|             title: '{% trans "Add new filter" %}', |             title: '{% jstrans "Add new filter" %}', | ||||||
|             icon: 'fa-filter', |             icon: 'fa-filter', | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| @@ -474,7 +474,7 @@ function setupFilterList(tableKey, table, target, options={}) { | |||||||
|         if (Object.keys(filters).length > 0) { |         if (Object.keys(filters).length > 0) { | ||||||
|             buttons += makeFilterButton({ |             buttons += makeFilterButton({ | ||||||
|                 id: clear, |                 id: clear, | ||||||
|                 title: '{% trans "Clear all filters" %}', |                 title: '{% jstrans "Clear all filters" %}', | ||||||
|                 icon: 'fa-backspace icon-red', |                 icon: 'fa-backspace icon-red', | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
| @@ -579,7 +579,7 @@ function setupFilterList(tableKey, table, target, options={}) { | |||||||
|             html += generateAvailableFilterList(tableKey); |             html += generateAvailableFilterList(tableKey); | ||||||
|             html += generateFilterInput(tableKey); |             html += generateFilterInput(tableKey); | ||||||
|  |  | ||||||
|             html += `<button title='{% trans "Create filter" %}' class='btn btn-outline-secondary filter-button' id='${make}'><span class='fas fa-plus'></span></button>`; |             html += `<button title='{% jstrans "Create filter" %}' class='btn btn-outline-secondary filter-button' id='${make}'><span class='fas fa-plus'></span></button>`; | ||||||
|             html += `</div>`; |             html += `</div>`; | ||||||
|  |  | ||||||
|             element.append(html); |             element.append(html); | ||||||
| @@ -669,8 +669,8 @@ function getFilterOptionValue(tableKey, filterKey, valueKey) { | |||||||
|  |  | ||||||
|     // Lookup for boolean options |     // Lookup for boolean options | ||||||
|     if (filter.type == 'bool') { |     if (filter.type == 'bool') { | ||||||
|         if (value == '1') return '{% trans "true" %}'; |         if (value == '1') return '{% jstrans "true" %}'; | ||||||
|         if (value == '0') return '{% trans "false" %}'; |         if (value == '0') return '{% jstrans "false" %}'; | ||||||
|  |  | ||||||
|         return value; |         return value; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -371,9 +371,9 @@ function constructForm(url, options={}) { | |||||||
|                 constructCreateForm(OPTIONS.actions.POST, options); |                 constructCreateForm(OPTIONS.actions.POST, options); | ||||||
|             } else { |             } else { | ||||||
|                 // User does not have permission to POST to the endpoint |                 // User does not have permission to POST to the endpoint | ||||||
|                 showMessage('{% trans "Action Prohibited" %}', { |                 showMessage('{% jstrans "Action Prohibited" %}', { | ||||||
|                     style: 'danger', |                     style: 'danger', | ||||||
|                     details: '{% trans "Create operation not allowed" %}', |                     details: '{% jstrans "Create operation not allowed" %}', | ||||||
|                     icon: 'fas fa-user-times', |                     icon: 'fas fa-user-times', | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
| @@ -386,9 +386,9 @@ function constructForm(url, options={}) { | |||||||
|                 constructChangeForm(OPTIONS.actions.PUT, options); |                 constructChangeForm(OPTIONS.actions.PUT, options); | ||||||
|             } else { |             } else { | ||||||
|                 // User does not have permission to PUT/PATCH to the endpoint |                 // User does not have permission to PUT/PATCH to the endpoint | ||||||
|                 showMessage('{% trans "Action Prohibited" %}', { |                 showMessage('{% jstrans "Action Prohibited" %}', { | ||||||
|                     style: 'danger', |                     style: 'danger', | ||||||
|                     details: '{% trans "Update operation not allowed" %}', |                     details: '{% jstrans "Update operation not allowed" %}', | ||||||
|                     icon: 'fas fa-user-times', |                     icon: 'fas fa-user-times', | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
| @@ -400,9 +400,9 @@ function constructForm(url, options={}) { | |||||||
|                 constructDeleteForm(OPTIONS.actions.DELETE, options); |                 constructDeleteForm(OPTIONS.actions.DELETE, options); | ||||||
|             } else { |             } else { | ||||||
|                 // User does not have permission to DELETE to the endpoint |                 // User does not have permission to DELETE to the endpoint | ||||||
|                 showMessage('{% trans "Action Prohibited" %}', { |                 showMessage('{% jstrans "Action Prohibited" %}', { | ||||||
|                     style: 'danger', |                     style: 'danger', | ||||||
|                     details: '{% trans "Delete operation not allowed" %}', |                     details: '{% jstrans "Delete operation not allowed" %}', | ||||||
|                     icon: 'fas fa-user-times', |                     icon: 'fas fa-user-times', | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
| @@ -414,9 +414,9 @@ function constructForm(url, options={}) { | |||||||
|                 // TODO? |                 // TODO? | ||||||
|             } else { |             } else { | ||||||
|                 // User does not have permission to GET to the endpoint |                 // User does not have permission to GET to the endpoint | ||||||
|                 showMessage('{% trans "Action Prohibited" %}', { |                 showMessage('{% jstrans "Action Prohibited" %}', { | ||||||
|                     style: 'danger', |                     style: 'danger', | ||||||
|                     details: '{% trans "View operation not allowed" %}', |                     details: '{% jstrans "View operation not allowed" %}', | ||||||
|                     icon: 'fas fa-user-times', |                     icon: 'fas fa-user-times', | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
| @@ -540,7 +540,7 @@ function constructFormBody(fields, options) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!('submitText' in options)) { |         if (!('submitText' in options)) { | ||||||
|             options.submitText = '{% trans "Delete" %}'; |             options.submitText = '{% jstrans "Delete" %}'; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -767,7 +767,7 @@ function updateForm(options) { | |||||||
| // The "submit" button will be disabled unless "confirm" is checked | // The "submit" button will be disabled unless "confirm" is checked | ||||||
| function insertConfirmButton(options) { | function insertConfirmButton(options) { | ||||||
|  |  | ||||||
|     var message = options.confirmMessage || '{% trans "Confirm" %}'; |     var message = options.confirmMessage || '{% jstrans "Confirm" %}'; | ||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class="form-check form-switch"> |     <div class="form-check form-switch"> | ||||||
| @@ -793,7 +793,7 @@ function insertConfirmButton(options) { | |||||||
| /* Add a checkbox to select if the modal will stay open after success */ | /* Add a checkbox to select if the modal will stay open after success */ | ||||||
| function insertPersistButton(options) { | function insertPersistButton(options) { | ||||||
|  |  | ||||||
|     var message = options.persistMessage || '{% trans "Keep this form open" %}'; |     var message = options.persistMessage || '{% jstrans "Keep this form open" %}'; | ||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class="form-check form-switch"> |     <div class="form-check form-switch"> | ||||||
| @@ -896,7 +896,7 @@ function submitFormData(fields, options) { | |||||||
|                 if (!validateFormField(name, options)) { |                 if (!validateFormField(name, options)) { | ||||||
|                     data_valid = false; |                     data_valid = false; | ||||||
|  |  | ||||||
|                     data_errors[name] = ['{% trans "Enter a valid number" %}']; |                     data_errors[name] = ['{% jstrans "Enter a valid number" %}']; | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
| @@ -1466,7 +1466,7 @@ function handleFormErrors(errors, fields={}, options={}) { | |||||||
|     // TODO: Display the JSON error text when hovering over the "info" icon |     // TODO: Display the JSON error text when hovering over the "info" icon | ||||||
|     non_field_errors.append( |     non_field_errors.append( | ||||||
|         `<div class='alert alert-block alert-danger'> |         `<div class='alert alert-block alert-danger'> | ||||||
|             <b>{% trans "Form errors exist" %}</b> |             <b>{% jstrans "Form errors exist" %}</b> | ||||||
|             <span id='form-errors-info' class='float-right fas fa-info-circle icon-red'> |             <span id='form-errors-info' class='float-right fas fa-info-circle icon-red'> | ||||||
|             </span> |             </span> | ||||||
|         </div>` |         </div>` | ||||||
| @@ -1964,7 +1964,7 @@ function initializeRelatedField(field, fields, options={}) { | |||||||
|                 if (field.noResults) { |                 if (field.noResults) { | ||||||
|                     return field.noResults(query); |                     return field.noResults(query); | ||||||
|                 } else { |                 } else { | ||||||
|                     return '{% trans "No results found" %}'; |                     return '{% jstrans "No results found" %}'; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @@ -2148,11 +2148,11 @@ function initializeRelatedField(field, fields, options={}) { | |||||||
|         button.on("click", () => { |         button.on("click", () => { | ||||||
|             const tree_id = `${name}_tree`; |             const tree_id = `${name}_tree`; | ||||||
|  |  | ||||||
|             const title = '{% trans "Select" %}' + " " + options.actions[name].label; |             const title = '{% jstrans "Select" %}' + " " + options.actions[name].label; | ||||||
|             const content = ` |             const content = ` | ||||||
|                 <div class="mb-1"> |                 <div class="mb-1"> | ||||||
|                     <div class="input-group mb-2"> |                     <div class="input-group mb-2"> | ||||||
|                         <input class="form-control" type="text" id="${name}_tree_search" placeholder="{% trans "Search" %} ${options.actions[name].label}..." /> |                         <input class="form-control" type="text" id="${name}_tree_search" placeholder="{% jstrans "Search" %} ${options.actions[name].label}..." /> | ||||||
|                         <button class="input-group-text" id="${name}_tree_search_btn"><i class="fas fa-search"></i></button> |                         <button class="input-group-text" id="${name}_tree_search_btn"><i class="fas fa-search"></i></button> | ||||||
|                     </div> |                     </div> | ||||||
|  |  | ||||||
| @@ -2164,7 +2164,7 @@ function initializeRelatedField(field, fields, options={}) { | |||||||
|                 </div> |                 </div> | ||||||
|             `; |             `; | ||||||
|             showQuestionDialog(title, content, { |             showQuestionDialog(title, content, { | ||||||
|                 accept_text: '{% trans "Select" %}', |                 accept_text: '{% jstrans "Select" %}', | ||||||
|                 accept: () => { |                 accept: () => { | ||||||
|                     const selectedNode = $(`#${tree_id}`).treeview('getSelected'); |                     const selectedNode = $(`#${tree_id}`).treeview('getSelected'); | ||||||
|                     if(selectedNode.length > 0) { |                     if(selectedNode.length > 0) { | ||||||
| @@ -2268,7 +2268,7 @@ function initializeChoiceField(field, fields, options) { | |||||||
|  |  | ||||||
| // Render a 'no results' element | // Render a 'no results' element | ||||||
| function searching() { | function searching() { | ||||||
|     return `<span>{% trans "Searching" %}...</span>`; |     return `<span>{% jstrans "Searching" %}...</span>`; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -2482,7 +2482,7 @@ function constructField(name, parameters, options={}) { | |||||||
|  |  | ||||||
|         if (!parameters.required && !options.hideClearButton) { |         if (!parameters.required && !options.hideClearButton) { | ||||||
|             html += ` |             html += ` | ||||||
|             <button class='input-group-text form-clear' id='clear_${field_name}' title='{% trans "Clear input" %}'> |             <button class='input-group-text form-clear' id='clear_${field_name}' title='{% jstrans "Clear input" %}'> | ||||||
|                 <span class='icon-red fas fa-backspace'></span> |                 <span class='icon-red fas fa-backspace'></span> | ||||||
|             </button>`; |             </button>`; | ||||||
|         } |         } | ||||||
| @@ -3068,7 +3068,7 @@ function selectImportFields(url, data={}, options={}) { | |||||||
|         rows += `<tr><td><em>${field_name}</em></td><td>${choice_input}</td></tr>`; |         rows += `<tr><td><em>${field_name}</em></td><td>${choice_input}</td></tr>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     var headers = `<tr><th>{% trans "File Column" %}</th><th>{% trans "Field Name" %}</th></tr>`; |     var headers = `<tr><th>{% jstrans "File Column" %}</th><th>{% jstrans "Field Name" %}</th></tr>`; | ||||||
|  |  | ||||||
|     var html = ''; |     var html = ''; | ||||||
|  |  | ||||||
| @@ -3080,7 +3080,7 @@ function selectImportFields(url, data={}, options={}) { | |||||||
|  |  | ||||||
|     constructForm(url, { |     constructForm(url, { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Select Columns" %}', |         title: '{% jstrans "Select Columns" %}', | ||||||
|         fields: {}, |         fields: {}, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         onSubmit: function(fields, opts) { |         onSubmit: function(fields, opts) { | ||||||
|   | |||||||
| @@ -74,10 +74,10 @@ function yesNoLabel(value, options={}) { | |||||||
|     let color = ''; |     let color = ''; | ||||||
|  |  | ||||||
|     if (toBool(value)) { |     if (toBool(value)) { | ||||||
|         text = options.pass || '{% trans "YES" %}'; |         text = options.pass || '{% jstrans "YES" %}'; | ||||||
|         color = 'bg-success'; |         color = 'bg-success'; | ||||||
|     } else { |     } else { | ||||||
|         text = options.fail || '{% trans "NO" %}'; |         text = options.fail || '{% jstrans "NO" %}'; | ||||||
|         color = 'bg-warning'; |         color = 'bg-warning'; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -90,19 +90,19 @@ function yesNoLabel(value, options={}) { | |||||||
|  |  | ||||||
|  |  | ||||||
| function trueFalseLabel(value, options={}) { | function trueFalseLabel(value, options={}) { | ||||||
|     options.pass = '{% trans "True" %}'; |     options.pass = '{% jstrans "True" %}'; | ||||||
|     options.fail = '{% trans "False" %}'; |     options.fail = '{% jstrans "False" %}'; | ||||||
|  |  | ||||||
|     return yesNoLabel(value, options); |     return yesNoLabel(value, options); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| function editButton(url, text='{% trans "Edit" %}') { | function editButton(url, text='{% jstrans "Edit" %}') { | ||||||
|     return `<button class='btn btn-success edit-button btn-sm' type='button' url='${url}'>${text}</button>`; |     return `<button class='btn btn-success edit-button btn-sm' type='button' url='${url}'>${text}</button>`; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| function deleteButton(url, text='{% trans "Delete" %}') { | function deleteButton(url, text='{% jstrans "Delete" %}') { | ||||||
|     return `<button class='btn btn-danger delete-button btn-sm' type='button' url='${url}'>${text}</button>`; |     return `<button class='btn btn-danger delete-button btn-sm' type='button' url='${url}'>${text}</button>`; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -582,7 +582,7 @@ function renderClipboard(s, prepend=false) { | |||||||
|         return s; |         return s; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     let clipString = `<span class="d-none d-xl-inline"><button class="btn clip-btn" type="button" data-bs-toggle='tooltip' title='{% trans "copy to clipboard" %}'><em class="fas fa-copy"></em></button></span>`; |     let clipString = `<span class="d-none d-xl-inline"><button class="btn clip-btn" type="button" data-bs-toggle='tooltip' title='{% jstrans "copy to clipboard" %}'><em class="fas fa-copy"></em></button></span>`; | ||||||
|  |  | ||||||
|     if (prepend === true) { |     if (prepend === true) { | ||||||
|         return `<div class="flex-cell">${clipString+s}</div>`; |         return `<div class="flex-cell">${clipString+s}</div>`; | ||||||
|   | |||||||
| @@ -101,12 +101,12 @@ function loadRequiredForBuildsPartsTable(table, options={}) { | |||||||
|         search: false, |         search: false, | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No parts required for builds" %}'; |             return '{% jstrans "No parts required for builds" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let name = shortenString(row.full_name); |                     let name = shortenString(row.full_name); | ||||||
|                     let display= imageHoverIcon(row.thumbnail) + renderLink(name, `/part/${row.pk}/`); |                     let display= imageHoverIcon(row.thumbnail) + renderLink(name, `/part/${row.pk}/`); | ||||||
| @@ -116,18 +116,18 @@ function loadRequiredForBuildsPartsTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'total_in_stock', |                 field: 'total_in_stock', | ||||||
|                 title: '{% trans "Available" %}', |                 title: '{% jstrans "Available" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return value; |                     return value; | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'allocated_to_build_orders', |                 field: 'allocated_to_build_orders', | ||||||
|                 title: '{% trans "Allocated Stock" %}', |                 title: '{% jstrans "Allocated Stock" %}', | ||||||
|                 formatter: function(_value, row) { |                 formatter: function(_value, row) { | ||||||
|                     return makeProgressBar( |                     return makeProgressBar( | ||||||
|                         row.allocated_to_build_orders, |                         row.allocated_to_build_orders, | ||||||
|   | |||||||
| @@ -50,8 +50,8 @@ function printLabels(options) { | |||||||
|  |  | ||||||
|     if (!options.items || options.items.length == 0) { |     if (!options.items || options.items.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Items" %}', |             '{% jstrans "Select Items" %}', | ||||||
|             '{% trans "No items selected for printing" %}', |             '{% jstrans "No items selected for printing" %}', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -69,8 +69,8 @@ function printLabels(options) { | |||||||
|         success: function (response) { |         success: function (response) { | ||||||
|             if (response.length == 0) { |             if (response.length == 0) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "No Labels Found" %}', |                     '{% jstrans "No Labels Found" %}', | ||||||
|                     '{% trans "No label templates found which match the selected items" %}', |                     '{% jstrans "No label templates found which match the selected items" %}', | ||||||
|                 ); |                 ); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| @@ -94,7 +94,7 @@ function printLabels(options) { | |||||||
|     if (options.items.length > 1) { |     if (options.items.length > 1) { | ||||||
|         header_html += ` |         header_html += ` | ||||||
|             <div class='alert alert-block alert-info'> |             <div class='alert alert-block alert-info'> | ||||||
|             ${options.items.length} ${options.plural_name} {% trans "selected" %} |             ${options.items.length} ${options.plural_name} {% jstrans "selected" %} | ||||||
|             </div> |             </div> | ||||||
|         `; |         `; | ||||||
|     } |     } | ||||||
| @@ -130,7 +130,7 @@ function printLabels(options) { | |||||||
|         if (Object.keys(printingOptions).length > 0) { |         if (Object.keys(printingOptions).length > 0) { | ||||||
|             formOptions.fields = { |             formOptions.fields = { | ||||||
|                 ...formOptions.fields, |                 ...formOptions.fields, | ||||||
|                 divider: { type: "candy", html: `<hr/><h5>{% trans "Printing Options" %}</h5>` }, |                 divider: { type: "candy", html: `<hr/><h5>{% jstrans "Printing Options" %}</h5>` }, | ||||||
|                 ...printingOptions, |                 ...printingOptions, | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
| @@ -145,14 +145,14 @@ function printLabels(options) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     const printingFormOptions = { |     const printingFormOptions = { | ||||||
|         title: options.items.length === 1 ? `{% trans "Print label" %}` : `{% trans "Print labels" %}`, |         title: options.items.length === 1 ? `{% jstrans "Print label" %}` : `{% jstrans "Print labels" %}`, | ||||||
|         submitText: `{% trans "Print" %}`, |         submitText: `{% jstrans "Print" %}`, | ||||||
|         method: "POST", |         method: "POST", | ||||||
|         disableSuccessMessage: true, |         disableSuccessMessage: true, | ||||||
|         header_html, |         header_html, | ||||||
|         fields: { |         fields: { | ||||||
|             _label_template: { |             _label_template: { | ||||||
|                 label: `{% trans "Select label template" %}`, |                 label: `{% jstrans "Select label template" %}`, | ||||||
|                 type: "choice", |                 type: "choice", | ||||||
|                 localOnly: true, |                 localOnly: true, | ||||||
|                 value: defaultLabelTemplates[options.key], |                 value: defaultLabelTemplates[options.key], | ||||||
| @@ -165,7 +165,7 @@ function printLabels(options) { | |||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             _plugin: { |             _plugin: { | ||||||
|                 label: `{% trans "Select plugin" %}`, |                 label: `{% jstrans "Select plugin" %}`, | ||||||
|                 type: "choice", |                 type: "choice", | ||||||
|                 localOnly: true, |                 localOnly: true, | ||||||
|                 value: user_settings.LABEL_DEFAULT_PRINTER || plugins[0].key, |                 value: user_settings.LABEL_DEFAULT_PRINTER || plugins[0].key, | ||||||
| @@ -184,7 +184,7 @@ function printLabels(options) { | |||||||
|                 // Download the generated file |                 // Download the generated file | ||||||
|                 window.open(response.file); |                 window.open(response.file); | ||||||
|             } else { |             } else { | ||||||
|                 showMessage('{% trans "Labels sent to printer" %}', { |                 showMessage('{% jstrans "Labels sent to printer" %}', { | ||||||
|                     style: 'success', |                     style: 'success', | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -55,12 +55,12 @@ function createNewModal(options={}) { | |||||||
|  |  | ||||||
|     // Add in a "close" button |     // Add in a "close" button | ||||||
|     if (!options.hideCloseButton) { |     if (!options.hideCloseButton) { | ||||||
|         buttons += `<button type='button' class='btn btn-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% trans "Cancel" %}</button>`; |         buttons += `<button type='button' class='btn btn-secondary' id='modal-form-close' data-bs-dismiss='modal'>{% jstrans "Cancel" %}</button>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Add in a "submit" button |     // Add in a "submit" button | ||||||
|     if (!options.hideSubmitButton) { |     if (!options.hideSubmitButton) { | ||||||
|         buttons += `<button type='button' class='btn btn-${submitClass}' id='modal-form-submit'>{% trans "Submit" %}</button>`; |         buttons += `<button type='button' class='btn btn-${submitClass}' id='modal-form-submit'>{% jstrans "Submit" %}</button>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
| @@ -71,7 +71,7 @@ function createNewModal(options={}) { | |||||||
|                     <h4 id='modal-title' class='modal-title'> |                     <h4 id='modal-title' class='modal-title'> | ||||||
|                         <!-- Form title to be injected here --> |                         <!-- Form title to be injected here --> | ||||||
|                     </h4> |                     </h4> | ||||||
|                     <button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='{% trans "Close" %}'></button> |                     <button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='{% jstrans "Close" %}'></button> | ||||||
|                 </div> |                 </div> | ||||||
|                 <div class='modal-body modal-form-content-wrapper'> |                 <div class='modal-body modal-form-content-wrapper'> | ||||||
|                     <div id='non-field-errors'> |                     <div id='non-field-errors'> | ||||||
| @@ -153,9 +153,9 @@ function createNewModal(options={}) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // Set labels based on supplied options |     // Set labels based on supplied options | ||||||
|     modalSetTitle(modal_name, options.title || '{% trans "Form Title" %}'); |     modalSetTitle(modal_name, options.title || '{% jstrans "Form Title" %}'); | ||||||
|     modalSetSubmitText(modal_name, options.submitText || '{% trans "Submit" %}'); |     modalSetSubmitText(modal_name, options.submitText || '{% jstrans "Submit" %}'); | ||||||
|     modalSetCloseText(modal_name, options.closeText || '{% trans "Cancel" %}'); |     modalSetCloseText(modal_name, options.closeText || '{% jstrans "Cancel" %}'); | ||||||
|  |  | ||||||
|     // Return the "name" of the modal |     // Return the "name" of the modal | ||||||
|     return modal_name; |     return modal_name; | ||||||
| @@ -442,7 +442,7 @@ function attachBootstrapCheckbox(modal) { | |||||||
| function loadingMessageContent() { | function loadingMessageContent() { | ||||||
|  |  | ||||||
|     // TODO - This can be made a lot better |     // TODO - This can be made a lot better | ||||||
|     return `<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> {% trans 'Waiting for server...' %}`; |     return `<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> {% jstrans 'Waiting for server...' %}`; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -593,7 +593,7 @@ function renderErrorMessage(xhr) { | |||||||
|         <div class='panel'> |         <div class='panel'> | ||||||
|             <div class='panel panel-heading'> |             <div class='panel panel-heading'> | ||||||
|                 <div class='panel-title'> |                 <div class='panel-title'> | ||||||
|                     <a data-bs-toggle='collapse' href="#collapse-error-info">{% trans "Show Error Information" %}</a> |                     <a data-bs-toggle='collapse' href="#collapse-error-info">{% jstrans "Show Error Information" %}</a> | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|             <div class='panel-collapse collapse' id='collapse-error-info'> |             <div class='panel-collapse collapse' id='collapse-error-info'> | ||||||
| @@ -625,7 +625,7 @@ function showAlertDialog(title, content, options={}) { | |||||||
|  |  | ||||||
|     var modal = createNewModal({ |     var modal = createNewModal({ | ||||||
|         title: title, |         title: title, | ||||||
|         closeText: '{% trans "Close" %}', |         closeText: '{% jstrans "Close" %}', | ||||||
|         hideSubmitButton: true, |         hideSubmitButton: true, | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
| @@ -679,8 +679,8 @@ function showQuestionDialog(title, content, options={}) { | |||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     options.title = title; |     options.title = title; | ||||||
|     options.submitText = options.accept_text || '{% trans "Accept" %}'; |     options.submitText = options.accept_text || '{% jstrans "Accept" %}'; | ||||||
|     options.closeText = options.cancel_text || '{% trans "Cancel" %}'; |     options.closeText = options.cancel_text || '{% jstrans "Cancel" %}'; | ||||||
|  |  | ||||||
|     var modal = createNewModal(options); |     var modal = createNewModal(options); | ||||||
|  |  | ||||||
| @@ -737,7 +737,7 @@ function openModal(options) { | |||||||
|     if (options.title) { |     if (options.title) { | ||||||
|         modalSetTitle(modal, options.title); |         modalSetTitle(modal, options.title); | ||||||
|     } else { |     } else { | ||||||
|         modalSetTitle(modal, '{% trans "Loading Data" %}...'); |         modalSetTitle(modal, '{% jstrans "Loading Data" %}...'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Unless the content is explicitly set, display loading message |     // Unless the content is explicitly set, display loading message | ||||||
| @@ -748,8 +748,8 @@ function openModal(options) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Default labels for 'Submit' and 'Close' buttons in the form |     // Default labels for 'Submit' and 'Close' buttons in the form | ||||||
|     var submit_text = options.submit_text || '{% trans "Submit" %}'; |     var submit_text = options.submit_text || '{% jstrans "Submit" %}'; | ||||||
|     var close_text = options.close_text || '{% trans "Close" %}'; |     var close_text = options.close_text || '{% jstrans "Close" %}'; | ||||||
|  |  | ||||||
|     modalSetButtonText(modal, submit_text, close_text); |     modalSetButtonText(modal, submit_text, close_text); | ||||||
|  |  | ||||||
| @@ -1008,7 +1008,7 @@ function handleModalForm(url, options) { | |||||||
|                             } |                             } | ||||||
|                         } else { |                         } else { | ||||||
|                             $(modal).modal('hide'); |                             $(modal).modal('hide'); | ||||||
|                             showAlertDialog('{% trans "Invalid response from server" %}', '{% trans "Form data missing from server response" %}'); |                             showAlertDialog('{% jstrans "Invalid response from server" %}', '{% jstrans "Form data missing from server response" %}'); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
| @@ -1020,7 +1020,7 @@ function handleModalForm(url, options) { | |||||||
|                 // There was an error submitting form data via POST |                 // There was an error submitting form data via POST | ||||||
|  |  | ||||||
|                 $(modal).modal('hide'); |                 $(modal).modal('hide'); | ||||||
|                 showAlertDialog('{% trans "Error posting form data" %}', renderErrorMessage(xhr)); |                 showAlertDialog('{% jstrans "Error posting form data" %}', renderErrorMessage(xhr)); | ||||||
|             }, |             }, | ||||||
|             complete: function() { |             complete: function() { | ||||||
|                 // TODO |                 // TODO | ||||||
| @@ -1056,8 +1056,8 @@ function launchModalForm(url, options = {}) { | |||||||
|     var modal = options.modal || '#modal-form'; |     var modal = options.modal || '#modal-form'; | ||||||
|  |  | ||||||
|     // Default labels for 'Submit' and 'Close' buttons in the form |     // Default labels for 'Submit' and 'Close' buttons in the form | ||||||
|     var submit_text = options.submit_text || '{% trans "Submit" %}'; |     var submit_text = options.submit_text || '{% jstrans "Submit" %}'; | ||||||
|     var close_text = options.close_text || '{% trans "Close" %}'; |     var close_text = options.close_text || '{% jstrans "Close" %}'; | ||||||
|  |  | ||||||
|     // Clean custom action buttons |     // Clean custom action buttons | ||||||
|     $(modal).find('#modal-footer-buttons').html(''); |     $(modal).find('#modal-footer-buttons').html(''); | ||||||
| @@ -1117,7 +1117,7 @@ function launchModalForm(url, options = {}) { | |||||||
|  |  | ||||||
|             } else { |             } else { | ||||||
|                 $(modal).modal('hide'); |                 $(modal).modal('hide'); | ||||||
|                 showAlertDialog('{% trans "Invalid server response" %}', '{% trans "JSON response missing form data" %}'); |                 showAlertDialog('{% jstrans "Invalid server response" %}', '{% jstrans "JSON response missing form data" %}'); | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         error: function(xhr) { |         error: function(xhr) { | ||||||
| @@ -1127,36 +1127,36 @@ function launchModalForm(url, options = {}) { | |||||||
|             if (xhr.status == 0) { |             if (xhr.status == 0) { | ||||||
|                 // No response from the server |                 // No response from the server | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "No Response" %}', |                     '{% jstrans "No Response" %}', | ||||||
|                     '{% trans "No response from the InvenTree server" %}', |                     '{% jstrans "No response from the InvenTree server" %}', | ||||||
|                 ); |                 ); | ||||||
|             } else if (xhr.status == 400) { |             } else if (xhr.status == 400) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "Error 400: Bad Request" %}', |                     '{% jstrans "Error 400: Bad Request" %}', | ||||||
|                     '{% trans "Server returned error code 400" %}', |                     '{% jstrans "Server returned error code 400" %}', | ||||||
|                 ); |                 ); | ||||||
|             } else if (xhr.status == 401) { |             } else if (xhr.status == 401) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "Error 401: Not Authenticated" %}', |                     '{% jstrans "Error 401: Not Authenticated" %}', | ||||||
|                     '{% trans "Authentication credentials not supplied" %}', |                     '{% jstrans "Authentication credentials not supplied" %}', | ||||||
|                 ); |                 ); | ||||||
|             } else if (xhr.status == 403) { |             } else if (xhr.status == 403) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "Error 403: Permission Denied" %}', |                     '{% jstrans "Error 403: Permission Denied" %}', | ||||||
|                     '{% trans "You do not have the required permissions to access this function" %}', |                     '{% jstrans "You do not have the required permissions to access this function" %}', | ||||||
|                 ); |                 ); | ||||||
|             } else if (xhr.status == 404) { |             } else if (xhr.status == 404) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "Error 404: Resource Not Found" %}', |                     '{% jstrans "Error 404: Resource Not Found" %}', | ||||||
|                     '{% trans "The requested resource could not be located on the server" %}', |                     '{% jstrans "The requested resource could not be located on the server" %}', | ||||||
|                 ); |                 ); | ||||||
|             } else if (xhr.status == 408) { |             } else if (xhr.status == 408) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "Error 408: Timeout" %}', |                     '{% jstrans "Error 408: Timeout" %}', | ||||||
|                     '{% trans "Connection timeout while requesting data from server" %}', |                     '{% jstrans "Connection timeout while requesting data from server" %}', | ||||||
|                 ); |                 ); | ||||||
|             } else { |             } else { | ||||||
|                 showAlertDialog('{% trans "Error requesting form data" %}', renderErrorMessage(xhr)); |                 showAlertDialog('{% jstrans "Error requesting form data" %}', renderErrorMessage(xhr)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             console.error('Modal form error: ' + xhr.status); |             console.error('Modal form error: ' + xhr.status); | ||||||
|   | |||||||
| @@ -216,21 +216,21 @@ function renderStockItem(data, parameters={}) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (data.quantity == 0) { |     if (data.quantity == 0) { | ||||||
|         stock_detail = `<span class='badge rounded-pill bg-danger'>{% trans "No Stock"% }</span>`; |         stock_detail = `<span class='badge rounded-pill bg-danger'>{% jstrans "No Stock"% }</span>`; | ||||||
|     } else { |     } else { | ||||||
|         if (data.serial && data.quantity == 1) { |         if (data.serial && data.quantity == 1) { | ||||||
|             stock_detail = `{% trans "Serial Number" %}: ${data.serial}`; |             stock_detail = `{% jstrans "Serial Number" %}: ${data.serial}`; | ||||||
|         } else { |         } else { | ||||||
|             if (render_available_quantity) { |             if (render_available_quantity) { | ||||||
|                 var available = data.quantity - data.allocated; |                 var available = data.quantity - data.allocated; | ||||||
|                 stock_detail = `{% trans "Available" %}: ${available}`; |                 stock_detail = `{% jstrans "Available" %}: ${available}`; | ||||||
|             } else { |             } else { | ||||||
|                 stock_detail = `{% trans "Quantity" %}: ${data.quantity}`; |                 stock_detail = `{% jstrans "Quantity" %}: ${data.quantity}`; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (data.batch) { |         if (data.batch) { | ||||||
|             stock_detail += ` - <small>{% trans "Batch" %}: ${data.batch}</small>`; |             stock_detail += ` - <small>{% jstrans "Batch" %}: ${data.batch}</small>`; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -301,7 +301,7 @@ function renderPart(data, parameters={}) { | |||||||
|         labels = partStockLabel(data); |         labels = partStockLabel(data); | ||||||
|  |  | ||||||
|         if (!data.active) { |         if (!data.active) { | ||||||
|             labels += `<span class='badge badge-right rounded-pill bg-danger'>{% trans "Inactive" %}</span>`; |             labels += `<span class='badge badge-right rounded-pill bg-danger'>{% jstrans "Inactive" %}</span>`; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -443,7 +443,7 @@ function renderSalesOrderShipment(data, parameters={}) { | |||||||
|     return renderModel( |     return renderModel( | ||||||
|         { |         { | ||||||
|             text: data.order_detail.reference, |             text: data.order_detail.reference, | ||||||
|             textSecondary: `{% trans "Shipment" %} ${data.reference}`, |             textSecondary: `{% jstrans "Shipment" %} ${data.reference}`, | ||||||
|         }, |         }, | ||||||
|         parameters |         parameters | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -30,18 +30,18 @@ function loadNewsFeedTable(table, options={}, enableDelete=false) { | |||||||
|         }, |         }, | ||||||
|         paginationVAlign: 'bottom', |         paginationVAlign: 'bottom', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No news found" %}'; |             return '{% jstrans "No news found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'pk', |                 field: 'pk', | ||||||
|                 title: '{% trans "ID" %}', |                 title: '{% jstrans "ID" %}', | ||||||
|                 visible: false, |                 visible: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'title', |                 field: 'title', | ||||||
|                 title: '{% trans "Title" %}', |                 title: '{% jstrans "Title" %}', | ||||||
|                 sortable: 'true', |                 sortable: 'true', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return `<a href="` + row.link + `">` + value + `</a>`; |                     return `<a href="` + row.link + `">` + value + `</a>`; | ||||||
| @@ -49,15 +49,15 @@ function loadNewsFeedTable(table, options={}, enableDelete=false) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'summary', |                 field: 'summary', | ||||||
|                 title: '{% trans "Summary" %}', |                 title: '{% jstrans "Summary" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'author', |                 field: 'author', | ||||||
|                 title: '{% trans "Author" %}', |                 title: '{% jstrans "Author" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'published', |                 field: 'published', | ||||||
|                 title: '{% trans "Published" %}', |                 title: '{% jstrans "Published" %}', | ||||||
|                 sortable: 'true', |                 sortable: 'true', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = renderDate(value); |                     var html = renderDate(value); | ||||||
|   | |||||||
| @@ -43,13 +43,13 @@ function loadNotificationTable(table, options={}, enableDelete=false) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'pk', |                 field: 'pk', | ||||||
|                 title: '{% trans "ID" %}', |                 title: '{% jstrans "ID" %}', | ||||||
|                 visible: false, |                 visible: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'age', |                 field: 'age', | ||||||
|                 title: '{% trans "Age" %}', |                 title: '{% jstrans "Age" %}', | ||||||
|                 sortable: 'true', |                 sortable: 'true', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return row.age_human; |                     return row.age_human; | ||||||
| @@ -57,12 +57,12 @@ function loadNotificationTable(table, options={}, enableDelete=false) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'category', |                 field: 'category', | ||||||
|                 title: '{% trans "Category" %}', |                 title: '{% jstrans "Category" %}', | ||||||
|                 sortable: 'true', |                 sortable: 'true', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 title: '{% trans "Notification" %}', |                 title: '{% jstrans "Notification" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (row.target && row.target.link) { |                     if (row.target && row.target.link) { | ||||||
|                         return renderLink(value, row.target.link); |                         return renderLink(value, row.target.link); | ||||||
| @@ -73,7 +73,7 @@ function loadNotificationTable(table, options={}, enableDelete=false) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'message', |                 field: 'message', | ||||||
|                 title: '{% trans "Message" %}', |                 title: '{% jstrans "Message" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
| @@ -82,7 +82,7 @@ function loadNotificationTable(table, options={}, enableDelete=false) { | |||||||
|                     let bDel = ''; |                     let bDel = ''; | ||||||
|  |  | ||||||
|                     if (enableDelete) { |                     if (enableDelete) { | ||||||
|                         bDel = `<button title='{% trans "Delete Notification" %}' class='notification-delete btn btn-outline-secondary' type='button' pk='${row.pk}'><span class='fas fa-trash-alt icon-red'></span></button>`; |                         bDel = `<button title='{% jstrans "Delete Notification" %}' class='notification-delete btn btn-outline-secondary' type='button' pk='${row.pk}'><span class='fas fa-trash-alt icon-red'></span></button>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     var html = `<div class='btn-group float-right' role='group'>${bRead}${bDel}</div>`; |                     var html = `<div class='btn-group float-right' role='group'>${bRead}${bDel}</div>`; | ||||||
| @@ -221,11 +221,11 @@ function getReadEditButton(pk, state, small=false) { | |||||||
|     let bReadTarget = ''; |     let bReadTarget = ''; | ||||||
|  |  | ||||||
|     if (state) { |     if (state) { | ||||||
|         bReadText = '{% trans "Mark as unread" %}'; |         bReadText = '{% jstrans "Mark as unread" %}'; | ||||||
|         bReadIcon = 'fas fa-bookmark icon-red'; |         bReadIcon = 'fas fa-bookmark icon-red'; | ||||||
|         bReadTarget = 'unread'; |         bReadTarget = 'unread'; | ||||||
|     } else { |     } else { | ||||||
|         bReadText = '{% trans "Mark as read" %}'; |         bReadText = '{% jstrans "Mark as read" %}'; | ||||||
|         bReadIcon = 'far fa-bookmark icon-green'; |         bReadIcon = 'far fa-bookmark icon-green'; | ||||||
|         bReadTarget = 'read'; |         bReadTarget = 'read'; | ||||||
|     } |     } | ||||||
| @@ -251,7 +251,7 @@ function openNotificationPanel() { | |||||||
|         { |         { | ||||||
|             success: function(response) { |             success: function(response) { | ||||||
|                 if (response.length == 0) { |                 if (response.length == 0) { | ||||||
|                     html = `<p class='text-muted'><em>{% trans "No unread notifications" %}</em><span class='fas fa-check-circle icon-green float-right'></span></p>`; |                     html = `<p class='text-muted'><em>{% jstrans "No unread notifications" %}</em><span class='fas fa-check-circle icon-green float-right'></span></p>`; | ||||||
|                 } else { |                 } else { | ||||||
|                     // build up items |                     // build up items | ||||||
|                     response.forEach(function(item, index) { |                     response.forEach(function(item, index) { | ||||||
| @@ -293,7 +293,7 @@ function openNotificationPanel() { | |||||||
|  * clears the notification panel when closed |  * clears the notification panel when closed | ||||||
|  **/ |  **/ | ||||||
| function closeNotificationPanel() { | function closeNotificationPanel() { | ||||||
|     $('#notification-center').html(`<p class='text-muted'>{% trans "Notifications will load here" %}</p>`); |     $('#notification-center').html(`<p class='text-muted'>{% jstrans "Notifications will load here" %}</p>`); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -86,7 +86,7 @@ function createExtraLineItem(options={}) { | |||||||
|     constructForm(options.url, { |     constructForm(options.url, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Extra Line Item" %}', |         title: '{% jstrans "Add Extra Line Item" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             if (options.table) { |             if (options.table) { | ||||||
|                 reloadBootstrapTable(options.table); |                 reloadBootstrapTable(options.table); | ||||||
| @@ -123,11 +123,11 @@ function exportOrder(redirect_url, options={}) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     constructFormBody({}, { |     constructFormBody({}, { | ||||||
|         title: '{% trans "Export Order" %}', |         title: '{% jstrans "Export Order" %}', | ||||||
|         fields: { |         fields: { | ||||||
|             format: { |             format: { | ||||||
|                 label: '{% trans "Format" %}', |                 label: '{% jstrans "Format" %}', | ||||||
|                 help_text: '{% trans "Select file format" %}', |                 help_text: '{% jstrans "Select file format" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|                 type: 'choice', |                 type: 'choice', | ||||||
|                 value: format, |                 value: format, | ||||||
| @@ -238,7 +238,7 @@ function loadExtraLineTable(options={}) { | |||||||
|                             method: 'POST', |                             method: 'POST', | ||||||
|                             fields: fields, |                             fields: fields, | ||||||
|                             data: data, |                             data: data, | ||||||
|                             title: '{% trans "Duplicate Line" %}', |                             title: '{% jstrans "Duplicate Line" %}', | ||||||
|                             onSuccess: reloadExtraLineTable, |                             onSuccess: reloadExtraLineTable, | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
| @@ -252,7 +252,7 @@ function loadExtraLineTable(options={}) { | |||||||
|  |  | ||||||
|                 constructForm(`${options.url}${pk}/`, { |                 constructForm(`${options.url}${pk}/`, { | ||||||
|                     fields: extraLineFields(), |                     fields: extraLineFields(), | ||||||
|                     title: '{% trans "Edit Line" %}', |                     title: '{% jstrans "Edit Line" %}', | ||||||
|                     onSuccess: reloadExtraLineTable, |                     onSuccess: reloadExtraLineTable, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -265,7 +265,7 @@ function loadExtraLineTable(options={}) { | |||||||
|  |  | ||||||
|                 constructForm(`${options.url}${pk}/`, { |                 constructForm(`${options.url}${pk}/`, { | ||||||
|                     method: 'DELETE', |                     method: 'DELETE', | ||||||
|                     title: '{% trans "Delete Line" %}', |                     title: '{% jstrans "Delete Line" %}', | ||||||
|                     onSuccess: reloadExtraLineTable, |                     onSuccess: reloadExtraLineTable, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -278,7 +278,7 @@ function loadExtraLineTable(options={}) { | |||||||
|         sidePagination: 'server', |         sidePagination: 'server', | ||||||
|         onPostBody: setupCallbacks, |         onPostBody: setupCallbacks, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No line items found" %}'; |             return '{% jstrans "No line items found" %}'; | ||||||
|         }, |         }, | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
|         original: options.params, |         original: options.params, | ||||||
| @@ -288,20 +288,20 @@ function loadExtraLineTable(options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Reference" %}', |                 title: '{% jstrans "Reference" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|                 footerFormatter: function(data) { |                 footerFormatter: function(data) { | ||||||
|                     return data.map(function(row) { |                     return data.map(function(row) { | ||||||
|                         return +row['quantity']; |                         return +row['quantity']; | ||||||
| @@ -313,7 +313,7 @@ function loadExtraLineTable(options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'price', |                 field: 'price', | ||||||
|                 title: '{% trans "Unit Price" %}', |                 title: '{% jstrans "Unit Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return formatCurrency(row.price, { |                     return formatCurrency(row.price, { | ||||||
|                         currency: row.price_currency, |                         currency: row.price_currency, | ||||||
| @@ -324,7 +324,7 @@ function loadExtraLineTable(options={}) { | |||||||
|                 field: 'total_price', |                 field: 'total_price', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 title: '{% trans "Total Price" %}', |                 title: '{% jstrans "Total Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return formatCurrency(row.price * row.quantity, { |                     return formatCurrency(row.price * row.quantity, { | ||||||
|                         currency: row.price_currency, |                         currency: row.price_currency, | ||||||
| @@ -344,11 +344,11 @@ function loadExtraLineTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'notes', |                 field: 'notes', | ||||||
|                 title: '{% trans "Notes" %}', |                 title: '{% jstrans "Notes" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value); |                         return renderLink(value, value); | ||||||
| @@ -366,12 +366,12 @@ function loadExtraLineTable(options={}) { | |||||||
|                         var pk = row.pk; |                         var pk = row.pk; | ||||||
|  |  | ||||||
|                         if (options.allow_edit) { |                         if (options.allow_edit) { | ||||||
|                             html += makeCopyButton('button-duplicate', pk, '{% trans "Duplicate line" %}'); |                             html += makeCopyButton('button-duplicate', pk, '{% jstrans "Duplicate line" %}'); | ||||||
|                             html += makeEditButton('button-edit', pk, '{% trans "Edit line" %}'); |                             html += makeEditButton('button-edit', pk, '{% jstrans "Edit line" %}'); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         if (options.allow_delete) { |                         if (options.allow_delete) { | ||||||
|                             html += makeDeleteButton('button-delete', pk, '{% trans "Delete line" %}', ); |                             html += makeDeleteButton('button-delete', pk, '{% jstrans "Delete line" %}', ); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -43,33 +43,33 @@ function loadPluginTable(table, options={}) { | |||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No plugins found" %}'; |             return '{% jstrans "No plugins found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'name', |                 field: 'name', | ||||||
|                 title: '{% trans "Plugin" %}', |                 title: '{% jstrans "Plugin" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = ''; |                     let html = ''; | ||||||
|  |  | ||||||
|                     if (!row.is_installed) { |                     if (!row.is_installed) { | ||||||
|                         html += `<span class='fa fa-question-circle' title='{% trans "This plugin is no longer installed" %}'></span>`; |                         html += `<span class='fa fa-question-circle' title='{% jstrans "This plugin is no longer installed" %}'></span>`; | ||||||
|                     } else if (row.active) { |                     } else if (row.active) { | ||||||
|                         html += `<span class='fa fa-check-circle icon-green' title='{% trans "This plugin is active" %}'></span>`; |                         html += `<span class='fa fa-check-circle icon-green' title='{% jstrans "This plugin is active" %}'></span>`; | ||||||
|                     } else { |                     } else { | ||||||
|                         html += `<span class='fa fa-times-circle icon-red' title ='{% trans "This plugin is installed but not active" %}'></span>`; |                         html += `<span class='fa fa-times-circle icon-red' title ='{% jstrans "This plugin is installed but not active" %}'></span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     html += ` <span>${value}</span>`; |                     html += ` <span>${value}</span>`; | ||||||
|  |  | ||||||
|                     if (row.is_builtin) { |                     if (row.is_builtin) { | ||||||
|                         html += `<span class='badge bg-success rounded-pill badge-right'>{% trans "Builtin" %}</span>`; |                         html += `<span class='badge bg-success rounded-pill badge-right'>{% jstrans "Builtin" %}</span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (row.is_sample) { |                     if (row.is_sample) { | ||||||
|                         html += `<span class='badge bg-info rounded-pill badge-right'>{% trans "Sample" %}</span>`; |                         html += `<span class='badge bg-info rounded-pill badge-right'>{% jstrans "Sample" %}</span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -77,13 +77,13 @@ function loadPluginTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'meta.description', |                 field: 'meta.description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'meta.version', |                 field: 'meta.version', | ||||||
|                 title: '{% trans "Version" %}', |                 title: '{% jstrans "Version" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         let html = value; |                         let html = value; | ||||||
| @@ -100,7 +100,7 @@ function loadPluginTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'meta.author', |                 field: 'meta.author', | ||||||
|                 title: '{% trans "Author" %}', |                 title: '{% jstrans "Author" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -114,9 +114,9 @@ function loadPluginTable(table, options={}) { | |||||||
|                     // Check if custom plugins are enabled for this instance |                     // Check if custom plugins are enabled for this instance | ||||||
|                     if (options.custom && !row.is_builtin && row.is_installed) { |                     if (options.custom && !row.is_builtin && row.is_installed) { | ||||||
|                         if (row.active) { |                         if (row.active) { | ||||||
|                             buttons += makeIconButton('fa-stop-circle icon-red', 'btn-plugin-disable', row.pk, '{% trans "Disable Plugin" %}'); |                             buttons += makeIconButton('fa-stop-circle icon-red', 'btn-plugin-disable', row.pk, '{% jstrans "Disable Plugin" %}'); | ||||||
|                         } else { |                         } else { | ||||||
|                             buttons += makeIconButton('fa-play-circle icon-green', 'btn-plugin-enable', row.pk, '{% trans "Enable Plugin" %}'); |                             buttons += makeIconButton('fa-play-circle icon-green', 'btn-plugin-enable', row.pk, '{% jstrans "Enable Plugin" %}'); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -148,14 +148,14 @@ function loadPluginTable(table, options={}) { | |||||||
| function installPlugin() { | function installPlugin() { | ||||||
|     constructForm(`/api/plugins/install/`, { |     constructForm(`/api/plugins/install/`, { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Install Plugin" %}', |         title: '{% jstrans "Install Plugin" %}', | ||||||
|         fields: { |         fields: { | ||||||
|             packagename: {}, |             packagename: {}, | ||||||
|             url: {}, |             url: {}, | ||||||
|             confirm: {}, |             confirm: {}, | ||||||
|         }, |         }, | ||||||
|         onSuccess: function(data) { |         onSuccess: function(data) { | ||||||
|             let msg = '{% trans "The Plugin was installed" %}'; |             let msg = '{% jstrans "The Plugin was installed" %}'; | ||||||
|             showMessage(msg, {style: 'success', details: data.result, timeout: 30000}); |             showMessage(msg, {style: 'success', details: data.result, timeout: 30000}); | ||||||
|  |  | ||||||
|             // Reload the plugin table |             // Reload the plugin table | ||||||
| @@ -174,19 +174,19 @@ function activatePlugin(plugin_id, active=true) { | |||||||
|  |  | ||||||
|     let html = active ? ` |     let html = active ? ` | ||||||
|     <span class='alert alert-block alert-info'> |     <span class='alert alert-block alert-info'> | ||||||
|     {% trans "Are you sure you want to enable this plugin?" %} |     {% jstrans "Are you sure you want to enable this plugin?" %} | ||||||
|     </span> |     </span> | ||||||
|     ` : ` |     ` : ` | ||||||
|     <span class='alert alert-block alert-danger'> |     <span class='alert alert-block alert-danger'> | ||||||
|     {% trans "Are you sure you want to disable this plugin?" %} |     {% jstrans "Are you sure you want to disable this plugin?" %} | ||||||
|     </span> |     </span> | ||||||
|     `; |     `; | ||||||
|  |  | ||||||
|     constructForm(null, { |     constructForm(null, { | ||||||
|         title: active ? '{% trans "Enable Plugin" %}' : '{% trans "Disable Plugin" %}', |         title: active ? '{% jstrans "Enable Plugin" %}' : '{% jstrans "Disable Plugin" %}', | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         submitText: active ? '{% trans "Enable" %}' : '{% trans "Disable" %}', |         submitText: active ? '{% jstrans "Enable" %}' : '{% jstrans "Disable" %}', | ||||||
|         submitClass: active ? 'success' : 'danger', |         submitClass: active ? 'success' : 'danger', | ||||||
|         onSubmit: function(_fields, opts) { |         onSubmit: function(_fields, opts) { | ||||||
|             showModalSpinner(opts.modal); |             showModalSpinner(opts.modal); | ||||||
| @@ -200,7 +200,7 @@ function activatePlugin(plugin_id, active=true) { | |||||||
|                     method: 'PATCH', |                     method: 'PATCH', | ||||||
|                     success: function() { |                     success: function() { | ||||||
|                         $(opts.modal).modal('hide'); |                         $(opts.modal).modal('hide'); | ||||||
|                         addCachedAlert('{% trans "Plugin updated" %}', {style: 'success'}); |                         addCachedAlert('{% jstrans "Plugin updated" %}', {style: 'success'}); | ||||||
|                         location.reload(); |                         location.reload(); | ||||||
|                     }, |                     }, | ||||||
|                     error: function(xhr) { |                     error: function(xhr) { | ||||||
| @@ -221,7 +221,7 @@ function reloadPlugins() { | |||||||
|     let url = '{% url "api-plugin-reload" %}'; |     let url = '{% url "api-plugin-reload" %}'; | ||||||
|  |  | ||||||
|     constructForm(url, { |     constructForm(url, { | ||||||
|         title: '{% trans "Reload Plugins" %}', |         title: '{% jstrans "Reload Plugins" %}', | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         fields: { |         fields: { | ||||||
|   | |||||||
| @@ -156,7 +156,7 @@ function calculateTotalPrice(dataset, value_func, currency_func, options={}) { | |||||||
|  |  | ||||||
|     if (!rates) { |     if (!rates) { | ||||||
|         console.error('Could not retrieve currency conversion information from the server'); |         console.error('Could not retrieve currency conversion information from the server'); | ||||||
|         return `<span class='icon-red fas fa-exclamation-circle' title='{% trans "Error fetching currency data" %}'></span>`; |         return `<span class='icon-red fas fa-exclamation-circle' title='{% jstrans "Error fetching currency data" %}'></span>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!currency) { |     if (!currency) { | ||||||
| @@ -318,7 +318,7 @@ function loadBomPricingChart(options={}) { | |||||||
|         search: false, |         search: false, | ||||||
|         showColumns: false, |         showColumns: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No BOM data available" %}'; |             return '{% jstrans "No BOM data available" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function(data) { |         onLoadSuccess: function(data) { | ||||||
|             // Construct BOM pricing chart |             // Construct BOM pricing chart | ||||||
| @@ -350,12 +350,12 @@ function loadBomPricingChart(options={}) { | |||||||
|                 labels: graphLabels, |                 labels: graphLabels, | ||||||
|                 datasets: [ |                 datasets: [ | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Maximum Price" %}', |                         label: '{% jstrans "Maximum Price" %}', | ||||||
|                         data: maxValues, |                         data: maxValues, | ||||||
|                         backgroundColor: colors, |                         backgroundColor: colors, | ||||||
|                     }, |                     }, | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Minimum Price" %}', |                         label: '{% jstrans "Minimum Price" %}', | ||||||
|                         data: minValues, |                         data: minValues, | ||||||
|                         backgroundColor: colors, |                         backgroundColor: colors, | ||||||
|                     }, |                     }, | ||||||
| @@ -366,7 +366,7 @@ function loadBomPricingChart(options={}) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'sub_part', |                 field: 'sub_part', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var url = `/part/${row.sub_part}/`; |                     var url = `/part/${row.sub_part}/`; | ||||||
| @@ -378,17 +378,17 @@ function loadBomPricingChart(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Reference" %}', |                 title: '{% jstrans "Reference" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'pricing', |                 field: 'pricing', | ||||||
|                 title: '{% trans "Price Range" %}', |                 title: '{% jstrans "Price Range" %}', | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var min_price = row.pricing_min; |                     var min_price = row.pricing_min; | ||||||
| @@ -460,7 +460,7 @@ function loadPartSupplierPricingTable(options={}) { | |||||||
|         search: false, |         search: false, | ||||||
|         showColumns: false, |         showColumns: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No supplier pricing data available" %}'; |             return '{% jstrans "No supplier pricing data available" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function(data) { |         onLoadSuccess: function(data) { | ||||||
|             // Update supplier pricing chart |             // Update supplier pricing chart | ||||||
| @@ -471,7 +471,7 @@ function loadPartSupplierPricingTable(options={}) { | |||||||
|             // Sort in increasing order of quantity |             // Sort in increasing order of quantity | ||||||
|             data = data.sort((a, b) => (a.quantity - b.quantity)); |             data = data.sort((a, b) => (a.quantity - b.quantity)); | ||||||
|  |  | ||||||
|             var graphLabels = Array.from(data, (x) => (`${x.part_detail.SKU} - {% trans "Quantity" %} ${x.quantity}`)); |             var graphLabels = Array.from(data, (x) => (`${x.part_detail.SKU} - {% jstrans "Quantity" %} ${x.quantity}`)); | ||||||
|             var graphValues = Array.from(data, (x) => (x.price / x.part_detail.pack_quantity_native)); |             var graphValues = Array.from(data, (x) => (x.price / x.part_detail.pack_quantity_native)); | ||||||
|  |  | ||||||
|             if (chart) { |             if (chart) { | ||||||
| @@ -482,7 +482,7 @@ function loadPartSupplierPricingTable(options={}) { | |||||||
|                 labels: graphLabels, |                 labels: graphLabels, | ||||||
|                 datasets: [ |                 datasets: [ | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Supplier Pricing" %}', |                         label: '{% jstrans "Supplier Pricing" %}', | ||||||
|                         data: graphValues, |                         data: graphValues, | ||||||
|                         backgroundColor: 'rgba(255, 206, 86, 0.2)', |                         backgroundColor: 'rgba(255, 206, 86, 0.2)', | ||||||
|                         borderColor: 'rgb(255, 206, 86)', |                         borderColor: 'rgb(255, 206, 86)', | ||||||
| @@ -495,7 +495,7 @@ function loadPartSupplierPricingTable(options={}) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'supplier', |                 field: 'supplier', | ||||||
|                 title: '{% trans "Supplier" %}', |                 title: '{% jstrans "Supplier" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = ''; |                     var html = ''; | ||||||
|  |  | ||||||
| @@ -507,7 +507,7 @@ function loadPartSupplierPricingTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'sku', |                 field: 'sku', | ||||||
|                 title: '{% trans "SKU" %}', |                 title: '{% jstrans "SKU" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return renderLink( |                     return renderLink( | ||||||
| @@ -519,12 +519,12 @@ function loadPartSupplierPricingTable(options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'price', |                 field: 'price', | ||||||
|                 title: '{% trans "Unit Price" %}', |                 title: '{% jstrans "Unit Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     if (row.price == null) { |                     if (row.price == null) { | ||||||
| @@ -569,7 +569,7 @@ function loadPriceBreakTable(table, options={}) { | |||||||
|         pageSize: 10, |         pageSize: 10, | ||||||
|         method: 'get', |         method: 'get', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return `{% trans "No price break data available" %}`; |             return `{% jstrans "No price break data available" %}`; | ||||||
|         }, |         }, | ||||||
|         queryParams: { |         queryParams: { | ||||||
|             part: options.part |             part: options.part | ||||||
| @@ -593,7 +593,7 @@ function loadPriceBreakTable(table, options={}) { | |||||||
|                     labels: graphLabels, |                     labels: graphLabels, | ||||||
|                     datasets: [ |                     datasets: [ | ||||||
|                         { |                         { | ||||||
|                             label: '{% trans "Unit Price" %}', |                             label: '{% jstrans "Unit Price" %}', | ||||||
|                             data: graphData, |                             data: graphData, | ||||||
|                             backgroundColor: 'rgba(255, 206, 86, 0.2)', |                             backgroundColor: 'rgba(255, 206, 86, 0.2)', | ||||||
|                             borderColor: 'rgb(255, 206, 86)', |                             borderColor: 'rgb(255, 206, 86)', | ||||||
| @@ -613,20 +613,20 @@ function loadPriceBreakTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'price', |                 field: 'price', | ||||||
|                 title: '{% trans "Price" %}', |                 title: '{% jstrans "Price" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = formatCurrency(value, {currency: row.price_currency}); |                     let html = formatCurrency(value, {currency: row.price_currency}); | ||||||
|  |  | ||||||
|                     let buttons = ''; |                     let buttons = ''; | ||||||
|  |  | ||||||
|                     buttons += makeEditButton(`button-${name}-edit`, row.pk, `{% trans "Edit" %} ${human_name}`); |                     buttons += makeEditButton(`button-${name}-edit`, row.pk, `{% jstrans "Edit" %} ${human_name}`); | ||||||
|                     buttons += makeDeleteButton(`button-${name}-delete`, row.pk, `{% trans "Delete" %} ${human_name}"`); |                     buttons += makeDeleteButton(`button-${name}-delete`, row.pk, `{% jstrans "Delete" %} ${human_name}"`); | ||||||
|  |  | ||||||
|                     html += wrapButtons(buttons); |                     html += wrapButtons(buttons); | ||||||
|  |  | ||||||
| @@ -681,7 +681,7 @@ function initPriceBreakSet(table, options) { | |||||||
|                 }, |                 }, | ||||||
|             }, |             }, | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Add Price Break" %}', |             title: '{% jstrans "Add Price Break" %}', | ||||||
|             onSuccess: reloadPriceBreakTable, |             onSuccess: reloadPriceBreakTable, | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -691,7 +691,7 @@ function initPriceBreakSet(table, options) { | |||||||
|  |  | ||||||
|         constructForm(`${pb_url}${pk}/`, { |         constructForm(`${pb_url}${pk}/`, { | ||||||
|             method: 'DELETE', |             method: 'DELETE', | ||||||
|             title: '{% trans "Delete Price Break" %}', |             title: '{% jstrans "Delete Price Break" %}', | ||||||
|             onSuccess: reloadPriceBreakTable, |             onSuccess: reloadPriceBreakTable, | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -709,7 +709,7 @@ function initPriceBreakSet(table, options) { | |||||||
|                     icon: 'fa-coins', |                     icon: 'fa-coins', | ||||||
|                 }, |                 }, | ||||||
|             }, |             }, | ||||||
|             title: '{% trans "Edit Price Break" %}', |             title: '{% jstrans "Edit Price Break" %}', | ||||||
|             onSuccess: reloadPriceBreakTable, |             onSuccess: reloadPriceBreakTable, | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -752,7 +752,7 @@ function loadPurchasePriceHistoryTable(options={}) { | |||||||
|         search: false, |         search: false, | ||||||
|         showColumns: false, |         showColumns: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No purchase history data available" %}'; |             return '{% jstrans "No purchase history data available" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function(data) { |         onLoadSuccess: function(data) { | ||||||
|             // Update purchase price history chart |             // Update purchase price history chart | ||||||
| @@ -788,7 +788,7 @@ function loadPurchasePriceHistoryTable(options={}) { | |||||||
|                 labels: graphLabels, |                 labels: graphLabels, | ||||||
|                 datasets: [ |                 datasets: [ | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Purchase Price History" %}', |                         label: '{% jstrans "Purchase Price History" %}', | ||||||
|                         data: graphValues, |                         data: graphValues, | ||||||
|                         backgroundColor: 'rgba(255, 206, 86, 0.2)', |                         backgroundColor: 'rgba(255, 206, 86, 0.2)', | ||||||
|                         borderColor: 'rgb(255, 206, 86)', |                         borderColor: 'rgb(255, 206, 86)', | ||||||
| @@ -801,7 +801,7 @@ function loadPurchasePriceHistoryTable(options={}) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'order', |                 field: 'order', | ||||||
|                 title: '{% trans "Purchase Order" %}', |                 title: '{% jstrans "Purchase Order" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var order = row.order_detail; |                     var order = row.order_detail; | ||||||
| @@ -823,7 +823,7 @@ function loadPurchasePriceHistoryTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'order_detail.complete_date', |                 field: 'order_detail.complete_date', | ||||||
|                 title: '{% trans "Date" %}', |                 title: '{% jstrans "Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
| @@ -831,7 +831,7 @@ function loadPurchasePriceHistoryTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'purchase_price', |                 field: 'purchase_price', | ||||||
|                 title: '{% trans "Unit Price" %}', |                 title: '{% jstrans "Unit Price" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
| @@ -891,7 +891,7 @@ function loadSalesPriceHistoryTable(options={}) { | |||||||
|         search: false, |         search: false, | ||||||
|         showColumns: false, |         showColumns: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No sales history data available" %}'; |             return '{% jstrans "No sales history data available" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function(data) { |         onLoadSuccess: function(data) { | ||||||
|             // Update sales price history chart |             // Update sales price history chart | ||||||
| @@ -913,7 +913,7 @@ function loadSalesPriceHistoryTable(options={}) { | |||||||
|                 labels: graphLabels, |                 labels: graphLabels, | ||||||
|                 datasets: [ |                 datasets: [ | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Sale Price History" %}', |                         label: '{% jstrans "Sale Price History" %}', | ||||||
|                         data: graphValues, |                         data: graphValues, | ||||||
|                         backgroundColor: 'rgba(255, 206, 86, 0.2)', |                         backgroundColor: 'rgba(255, 206, 86, 0.2)', | ||||||
|                         borderColor: 'rgb(255, 206, 86)', |                         borderColor: 'rgb(255, 206, 86)', | ||||||
| @@ -926,7 +926,7 @@ function loadSalesPriceHistoryTable(options={}) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'order', |                 field: 'order', | ||||||
|                 title: '{% trans "Sales Order" %}', |                 title: '{% jstrans "Sales Order" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var order = row.order_detail; |                     var order = row.order_detail; | ||||||
|                     var customer = row.customer_detail; |                     var customer = row.customer_detail; | ||||||
| @@ -947,14 +947,14 @@ function loadSalesPriceHistoryTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'shipment_date', |                 field: 'shipment_date', | ||||||
|                 title: '{% trans "Date" %}', |                 title: '{% jstrans "Date" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return renderDate(row.order_detail.shipment_date); |                     return renderDate(row.order_detail.shipment_date); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'sale_price', |                 field: 'sale_price', | ||||||
|                 title: '{% trans "Sale Price" %}', |                 title: '{% jstrans "Sale Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return formatCurrency(value, { |                     return formatCurrency(value, { | ||||||
|                         currency: row.sale_price_currency |                         currency: row.sale_price_currency | ||||||
| @@ -1002,7 +1002,7 @@ function loadVariantPricingChart(options={}) { | |||||||
|         search: false, |         search: false, | ||||||
|         showColumns: false, |         showColumns: false, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No variant data available" %}'; |             return '{% jstrans "No variant data available" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function(data) { |         onLoadSuccess: function(data) { | ||||||
|             // Construct variant pricing chart |             // Construct variant pricing chart | ||||||
| @@ -1021,7 +1021,7 @@ function loadVariantPricingChart(options={}) { | |||||||
|                 labels: graphLabels, |                 labels: graphLabels, | ||||||
|                 datasets: [ |                 datasets: [ | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Minimum Price" %}', |                         label: '{% jstrans "Minimum Price" %}', | ||||||
|                         data: minValues, |                         data: minValues, | ||||||
|                         backgroundColor: 'rgba(200, 250, 200, 0.75)', |                         backgroundColor: 'rgba(200, 250, 200, 0.75)', | ||||||
|                         borderColor: 'rgba(200, 250, 200)', |                         borderColor: 'rgba(200, 250, 200)', | ||||||
| @@ -1029,7 +1029,7 @@ function loadVariantPricingChart(options={}) { | |||||||
|                         fill: true, |                         fill: true, | ||||||
|                     }, |                     }, | ||||||
|                     { |                     { | ||||||
|                         label: '{% trans "Maximum Price" %}', |                         label: '{% jstrans "Maximum Price" %}', | ||||||
|                         data: maxValues, |                         data: maxValues, | ||||||
|                         backgroundColor: 'rgba(250, 220, 220, 0.75)', |                         backgroundColor: 'rgba(250, 220, 220, 0.75)', | ||||||
|                         borderColor: 'rgba(250, 220, 220)', |                         borderColor: 'rgba(250, 220, 220)', | ||||||
| @@ -1042,7 +1042,7 @@ function loadVariantPricingChart(options={}) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 title: '{% trans "Variant Part" %}', |                 title: '{% jstrans "Variant Part" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var name = shortenString(row.full_name); |                     var name = shortenString(row.full_name); | ||||||
|                     var display = imageHoverIcon(row.thumbnail) + renderLink(name, `/part/${row.pk}/`); |                     var display = imageHoverIcon(row.thumbnail) + renderLink(name, `/part/${row.pk}/`); | ||||||
| @@ -1051,7 +1051,7 @@ function loadVariantPricingChart(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'pricing', |                 field: 'pricing', | ||||||
|                 title: '{% trans "Price Range" %}', |                 title: '{% jstrans "Price Range" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var min_price = row.pricing_min; |                     var min_price = row.pricing_min; | ||||||
|                     var max_price = row.pricing_max; |                     var max_price = row.pricing_max; | ||||||
|   | |||||||
| @@ -90,7 +90,7 @@ function purchaseOrderFields(options={}) { | |||||||
|         supplier: { |         supplier: { | ||||||
|             icon: 'fa-building', |             icon: 'fa-building', | ||||||
|             secondary: { |             secondary: { | ||||||
|                 title: '{% trans "Add Supplier" %}', |                 title: '{% jstrans "Add Supplier" %}', | ||||||
|                 fields: function() { |                 fields: function() { | ||||||
|                     var fields = companyFormFields(); |                     var fields = companyFormFields(); | ||||||
|  |  | ||||||
| @@ -165,24 +165,24 @@ function purchaseOrderFields(options={}) { | |||||||
|                 supplier_detail: true, |                 supplier_detail: true, | ||||||
|             }, |             }, | ||||||
|             api_url: '{% url "api-po-list" %}', |             api_url: '{% url "api-po-list" %}', | ||||||
|             label: '{% trans "Purchase Order" %}', |             label: '{% jstrans "Purchase Order" %}', | ||||||
|             help_text: '{% trans "Select purchase order to duplicate" %}', |             help_text: '{% jstrans "Select purchase order to duplicate" %}', | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         fields.duplicate_line_items = { |         fields.duplicate_line_items = { | ||||||
|             value: true, |             value: true, | ||||||
|             group: 'duplicate', |             group: 'duplicate', | ||||||
|             type: 'boolean', |             type: 'boolean', | ||||||
|             label: '{% trans "Duplicate Line Items" %}', |             label: '{% jstrans "Duplicate Line Items" %}', | ||||||
|             help_text: '{% trans "Duplicate all line items from the selected order" %}', |             help_text: '{% jstrans "Duplicate all line items from the selected order" %}', | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         fields.duplicate_extra_lines = { |         fields.duplicate_extra_lines = { | ||||||
|             value: true, |             value: true, | ||||||
|             group: 'duplicate', |             group: 'duplicate', | ||||||
|             type: 'boolean', |             type: 'boolean', | ||||||
|             label: '{% trans "Duplicate Extra Lines" %}', |             label: '{% jstrans "Duplicate Extra Lines" %}', | ||||||
|             help_text: '{% trans "Duplicate extra line items from the selected order" %}', |             help_text: '{% jstrans "Duplicate extra line items from the selected order" %}', | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -203,7 +203,7 @@ function editPurchaseOrder(pk, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-po-list" %}${pk}/`, { |     constructForm(`{% url "api-po-list" %}${pk}/`, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Edit Purchase Order" %}', |         title: '{% jstrans "Edit Purchase Order" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -220,7 +220,7 @@ function createPurchaseOrder(options={}) { | |||||||
|  |  | ||||||
|     if (options.duplicate_order) { |     if (options.duplicate_order) { | ||||||
|         groups.duplicate = { |         groups.duplicate = { | ||||||
|             title: '{% trans "Duplication Options" %}', |             title: '{% jstrans "Duplication Options" %}', | ||||||
|             collapsible: false, |             collapsible: false, | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| @@ -239,7 +239,7 @@ function createPurchaseOrder(options={}) { | |||||||
|                 location.href = `/order/purchase-order/${data.pk}/`; |                 location.href = `/order/purchase-order/${data.pk}/`; | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         title: options.title || '{% trans "Create Purchase Order" %}', |         title: options.title || '{% jstrans "Create Purchase Order" %}', | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -311,7 +311,7 @@ function poLineItemFields(options={}) { | |||||||
|                 ).then(function() { |                 ).then(function() { | ||||||
|                     // Update pack size information |                     // Update pack size information | ||||||
|                     if (pack_quantity != 1) { |                     if (pack_quantity != 1) { | ||||||
|                         var txt = `<span class='fas fa-info-circle icon-blue'></span> {% trans "Pack Quantity" %}: ${formatDecimal(pack_quantity)} ${units}`; |                         var txt = `<span class='fas fa-info-circle icon-blue'></span> {% jstrans "Pack Quantity" %}: ${formatDecimal(pack_quantity)} ${units}`; | ||||||
|                         $(opts.modal).find('#hint_id_quantity').after(`<div class='form-info-message' id='info-pack-size'>${txt}</div>`); |                         $(opts.modal).find('#hint_id_quantity').after(`<div class='form-info-message' id='info-pack-size'>${txt}</div>`); | ||||||
|                     } |                     } | ||||||
|                 }).then(function() { |                 }).then(function() { | ||||||
| @@ -349,7 +349,7 @@ function poLineItemFields(options={}) { | |||||||
|             }, |             }, | ||||||
|             secondary: { |             secondary: { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 title: '{% trans "Add Supplier Part" %}', |                 title: '{% jstrans "Add Supplier Part" %}', | ||||||
|                 fields: function(data) { |                 fields: function(data) { | ||||||
|                     var fields = supplierPartFields({ |                     var fields = supplierPartFields({ | ||||||
|                         part: data.part, |                         part: data.part, | ||||||
| @@ -430,7 +430,7 @@ function createPurchaseOrderLineItem(order, options={}) { | |||||||
|     constructForm('{% url "api-po-line-list" %}', { |     constructForm('{% url "api-po-line-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Line Item" %}', |         title: '{% jstrans "Add Line Item" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -447,7 +447,7 @@ function completePurchaseOrder(order_id, options={}) { | |||||||
|         `/api/order/po/${order_id}/complete/`, |         `/api/order/po/${order_id}/complete/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Complete Purchase Order" %}', |             title: '{% jstrans "Complete Purchase Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             fieldsFunction: function(opts) { |             fieldsFunction: function(opts) { | ||||||
|                 var fields = { |                 var fields = { | ||||||
| @@ -464,19 +464,19 @@ function completePurchaseOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|                 var html = ` |                 var html = ` | ||||||
|                 <div class='alert alert-block alert-info'> |                 <div class='alert alert-block alert-info'> | ||||||
|                     {% trans "Mark this order as complete?" %} |                     {% jstrans "Mark this order as complete?" %} | ||||||
|                 </div>`; |                 </div>`; | ||||||
|  |  | ||||||
|                 if (opts.context.is_complete) { |                 if (opts.context.is_complete) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-success'> |                     <div class='alert alert-block alert-success'> | ||||||
|                         {% trans "All line items have been received" %} |                         {% jstrans "All line items have been received" %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } else { |                 } else { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-warning'> |                     <div class='alert alert-block alert-warning'> | ||||||
|                         {% trans 'This order has line items which have not been marked as received.' %}</br> |                         {% jstrans 'This order has line items which have not been marked as received.' %}</br> | ||||||
|                         {% trans 'Completing this order means that the order and line items will no longer be editable.' %} |                         {% jstrans 'Completing this order means that the order and line items will no longer be editable.' %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -499,18 +499,18 @@ function cancelPurchaseOrder(order_id, options={}) { | |||||||
|         `/api/order/po/${order_id}/cancel/`, |         `/api/order/po/${order_id}/cancel/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Cancel Purchase Order" %}', |             title: '{% jstrans "Cancel Purchase Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             preFormContent: function(opts) { |             preFormContent: function(opts) { | ||||||
|                 var html = ` |                 var html = ` | ||||||
|                 <div class='alert alert-info alert-block'> |                 <div class='alert alert-info alert-block'> | ||||||
|                     {% trans "Are you sure you wish to cancel this purchase order?" %} |                     {% jstrans "Are you sure you wish to cancel this purchase order?" %} | ||||||
|                 </div>`; |                 </div>`; | ||||||
|  |  | ||||||
|                 if (!opts.context.can_cancel) { |                 if (!opts.context.can_cancel) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-danger alert-block'> |                     <div class='alert alert-danger alert-block'> | ||||||
|                         {% trans "This purchase order can not be cancelled" %} |                         {% jstrans "This purchase order can not be cancelled" %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -531,12 +531,12 @@ function issuePurchaseOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-block alert-warning'> |     <div class='alert alert-block alert-warning'> | ||||||
|     {% trans 'After placing this order, line items will no longer be editable.' %} |     {% jstrans 'After placing this order, line items will no longer be editable.' %} | ||||||
|     </div>`; |     </div>`; | ||||||
|  |  | ||||||
|     constructForm(`{% url "api-po-list" %}${order_id}/issue/`, { |     constructForm(`{% url "api-po-list" %}${order_id}/issue/`, { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Issue Purchase Order" %}', |         title: '{% jstrans "Issue Purchase Order" %}', | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
| @@ -627,8 +627,8 @@ function orderParts(parts_list, options={}) { | |||||||
|  |  | ||||||
|     if (parts.length == 0) { |     if (parts.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Parts" %}', |             '{% jstrans "Select Parts" %}', | ||||||
|             '{% trans "At least one purchaseable part must be selected" %}', |             '{% jstrans "At least one purchaseable part must be selected" %}', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -653,7 +653,7 @@ function orderParts(parts_list, options={}) { | |||||||
|                 type: 'decimal', |                 type: 'decimal', | ||||||
|                 min_value: 0, |                 min_value: 0, | ||||||
|                 value: quantity, |                 value: quantity, | ||||||
|                 title: '{% trans "Quantity to order" %}', |                 title: '{% jstrans "Quantity to order" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -662,7 +662,7 @@ function orderParts(parts_list, options={}) { | |||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         var supplier_part_prefix = ` |         var supplier_part_prefix = ` | ||||||
|             <button type='button' class='input-group-text button-row-new-sp' pk='${pk}' title='{% trans "New supplier part" %}'> |             <button type='button' class='input-group-text button-row-new-sp' pk='${pk}' title='{% jstrans "New supplier part" %}'> | ||||||
|                 <span class='fas fa-plus-circle icon-green'></span> |                 <span class='fas fa-plus-circle icon-green'></span> | ||||||
|             </button> |             </button> | ||||||
|         `; |         `; | ||||||
| @@ -680,7 +680,7 @@ function orderParts(parts_list, options={}) { | |||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         var purchase_order_prefix = ` |         var purchase_order_prefix = ` | ||||||
|             <button type='button' class='input-group-text button-row-new-po' pk='${pk}' title='{% trans "New purchase order" %}'> |             <button type='button' class='input-group-text button-row-new-po' pk='${pk}' title='{% jstrans "New purchase order" %}'> | ||||||
|                 <span class='fas fa-plus-circle icon-green'></span> |                 <span class='fas fa-plus-circle icon-green'></span> | ||||||
|             </button> |             </button> | ||||||
|         `; |         `; | ||||||
| @@ -703,7 +703,7 @@ function orderParts(parts_list, options={}) { | |||||||
|             buttons += makeRemoveButton( |             buttons += makeRemoveButton( | ||||||
|                 'button-row-remove', |                 'button-row-remove', | ||||||
|                 pk, |                 pk, | ||||||
|                 '{% trans "Remove row" %}', |                 '{% jstrans "Remove row" %}', | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -712,7 +712,7 @@ function orderParts(parts_list, options={}) { | |||||||
|             'fa-shopping-cart icon-blue', |             'fa-shopping-cart icon-blue', | ||||||
|             'button-row-add', |             'button-row-add', | ||||||
|             pk, |             pk, | ||||||
|             '{% trans "Add to purchase order" %}', |             '{% jstrans "Add to purchase order" %}', | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         buttons = wrapButtons(buttons); |         buttons = wrapButtons(buttons); | ||||||
| @@ -757,10 +757,10 @@ function orderParts(parts_list, options={}) { | |||||||
|     <table class='table table-striped table-condensed' id='order-parts-table'> |     <table class='table table-striped table-condensed' id='order-parts-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>{% trans "Part" %}</th> |                 <th>{% jstrans "Part" %}</th> | ||||||
|                 <th style='min-width: 300px;'>{% trans "Supplier Part" %}</th> |                 <th style='min-width: 300px;'>{% jstrans "Supplier Part" %}</th> | ||||||
|                 <th style='min-width: 300px;'>{% trans "Purchase Order" %}</th> |                 <th style='min-width: 300px;'>{% jstrans "Purchase Order" %}</th> | ||||||
|                 <th style='min-width: 50px;'>{% trans "Quantity" %}</th> |                 <th style='min-width: 50px;'>{% jstrans "Quantity" %}</th> | ||||||
|                 <th><!-- Actions --></th> |                 <th><!-- Actions --></th> | ||||||
|             </tr> |             </tr> | ||||||
|         </thead> |         </thead> | ||||||
| @@ -800,9 +800,9 @@ function orderParts(parts_list, options={}) { | |||||||
|  |  | ||||||
|     constructFormBody({}, { |     constructFormBody({}, { | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         title: '{% trans "Order Parts" %}', |         title: '{% jstrans "Order Parts" %}', | ||||||
|         hideSubmitButton: true, |         hideSubmitButton: true, | ||||||
|         closeText: '{% trans "Close" %}', |         closeText: '{% jstrans "Close" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|             parts.forEach(function(part) { |             parts.forEach(function(part) { | ||||||
|  |  | ||||||
| @@ -842,7 +842,7 @@ function orderParts(parts_list, options={}) { | |||||||
|                             } |                             } | ||||||
|                         ).then(function() { |                         ).then(function() { | ||||||
|                             if (pack_quantity != 1) { |                             if (pack_quantity != 1) { | ||||||
|                                 var txt = `<span class='fas fa-info-circle icon-blue'></span> {% trans "Pack Quantity" %}: ${pack_quantity} ${units}`; |                                 var txt = `<span class='fas fa-info-circle icon-blue'></span> {% jstrans "Pack Quantity" %}: ${pack_quantity} ${units}`; | ||||||
|                                 $(opts.modal).find(`#id_quantity_${pk}`).after(`<div class='form-info-message' id='info-pack-size-${pk}'>${txt}</div>`); |                                 $(opts.modal).find(`#id_quantity_${pk}`).after(`<div class='form-info-message' id='info-pack-size-${pk}'>${txt}</div>`); | ||||||
|                             } |                             } | ||||||
|                         }); |                         }); | ||||||
| @@ -860,7 +860,7 @@ function orderParts(parts_list, options={}) { | |||||||
|                     filters: supplier_part_filters, |                     filters: supplier_part_filters, | ||||||
|                     onEdit: onSupplierPartChanged, |                     onEdit: onSupplierPartChanged, | ||||||
|                     noResults: function(query) { |                     noResults: function(query) { | ||||||
|                         return '{% trans "No matching supplier parts" %}'; |                         return '{% jstrans "No matching supplier parts" %}'; | ||||||
|                     } |                     } | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
| @@ -879,7 +879,7 @@ function orderParts(parts_list, options={}) { | |||||||
|                     value: options.order, |                     value: options.order, | ||||||
|                     filters: order_filters, |                     filters: order_filters, | ||||||
|                     noResults: function(query) { |                     noResults: function(query) { | ||||||
|                         return '{% trans "No matching purchase orders" %}'; |                         return '{% jstrans "No matching purchase orders" %}'; | ||||||
|                     } |                     } | ||||||
|                 }, null, opts); |                 }, null, opts); | ||||||
|  |  | ||||||
| @@ -1066,8 +1066,8 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|     if (line_items.length == 0) { |     if (line_items.length == 0) { | ||||||
|  |  | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Line Items" %}', |             '{% jstrans "Select Line Items" %}', | ||||||
|             '{% trans "At least one line item must be selected" %}', |             '{% jstrans "At least one line item must be selected" %}', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -1096,8 +1096,8 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|         if (native_pack_quantity != 1) { |         if (native_pack_quantity != 1) { | ||||||
|             pack_size_div = ` |             pack_size_div = ` | ||||||
|             <div class='alert alert-small alert-block alert-info'> |             <div class='alert alert-small alert-block alert-info'> | ||||||
|                 {% trans "Pack Quantity" %}: ${pack_quantity}<br> |                 {% jstrans "Pack Quantity" %}: ${pack_quantity}<br> | ||||||
|                 {% trans "Received Quantity" %}: <span class='pack_received_quantity' id='items_received_quantity_${pk}'>${received}</span> ${units} |                 {% jstrans "Received Quantity" %}: <span class='pack_received_quantity' id='items_received_quantity_${pk}'>${received}</span> ${units} | ||||||
|             </div>`; |             </div>`; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1108,7 +1108,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|                 type: 'decimal', |                 type: 'decimal', | ||||||
|                 min_value: 0, |                 min_value: 0, | ||||||
|                 value: quantity, |                 value: quantity, | ||||||
|                 title: '{% trans "Quantity to receive" %}', |                 title: '{% jstrans "Quantity to receive" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -1122,8 +1122,8 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|             { |             { | ||||||
|                 type: 'string', |                 type: 'string', | ||||||
|                 required: false, |                 required: false, | ||||||
|                 label: '{% trans "Batch Code" %}', |                 label: '{% jstrans "Batch Code" %}', | ||||||
|                 help_text: '{% trans "Enter batch code for incoming stock items" %}', |                 help_text: '{% jstrans "Enter batch code for incoming stock items" %}', | ||||||
|                 icon: 'fa-layer-group', |                 icon: 'fa-layer-group', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -1146,8 +1146,8 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|             { |             { | ||||||
|                 type: 'string', |                 type: 'string', | ||||||
|                 required: false, |                 required: false, | ||||||
|                 label: '{% trans "Serial Numbers" %}', |                 label: '{% jstrans "Serial Numbers" %}', | ||||||
|                 help_text: '{% trans "Enter serial numbers for incoming stock items" %}', |                 help_text: '{% jstrans "Enter serial numbers for incoming stock items" %}', | ||||||
|                 icon: 'fa-hashtag', |                 icon: 'fa-hashtag', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -1171,7 +1171,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|             `items_location_${pk}`, |             `items_location_${pk}`, | ||||||
|             { |             { | ||||||
|                 type: 'related field', |                 type: 'related field', | ||||||
|                 label: '{% trans "Location" %}', |                 label: '{% jstrans "Location" %}', | ||||||
|                 required: false, |                 required: false, | ||||||
|                 icon: 'fa-sitemap', |                 icon: 'fa-sitemap', | ||||||
|             }, |             }, | ||||||
| @@ -1184,7 +1184,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|             `items_status_${pk}`, |             `items_status_${pk}`, | ||||||
|             { |             { | ||||||
|                 type: 'choice', |                 type: 'choice', | ||||||
|                 label: '{% trans "Stock Status" %}', |                 label: '{% jstrans "Stock Status" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|                 choices: choices, |                 choices: choices, | ||||||
|                 value: 10, // OK |                 value: 10, // OK | ||||||
| @@ -1198,11 +1198,11 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|         let buttons = ''; |         let buttons = ''; | ||||||
|  |  | ||||||
|         if (global_settings.BARCODE_ENABLE) { |         if (global_settings.BARCODE_ENABLE) { | ||||||
|             buttons += makeIconButton('fa-qrcode', 'button-row-add-barcode', pk, '{% trans "Add barcode" %}'); |             buttons += makeIconButton('fa-qrcode', 'button-row-add-barcode', pk, '{% jstrans "Add barcode" %}'); | ||||||
|             buttons += makeIconButton('fa-unlink icon-red', 'button-row-remove-barcode', pk, '{% trans "Remove barcode" %}', {hidden: true}); |             buttons += makeIconButton('fa-unlink icon-red', 'button-row-remove-barcode', pk, '{% jstrans "Remove barcode" %}', {hidden: true}); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         buttons += makeIconButton('fa-sitemap', 'button-row-add-location', pk, '{% trans "Specify location" %}', { |         buttons += makeIconButton('fa-sitemap', 'button-row-add-location', pk, '{% jstrans "Specify location" %}', { | ||||||
|             collapseTarget: `row-destination-${pk}` |             collapseTarget: `row-destination-${pk}` | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| @@ -1210,7 +1210,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|             'fa-layer-group', |             'fa-layer-group', | ||||||
|             'button-row-add-batch', |             'button-row-add-batch', | ||||||
|             pk, |             pk, | ||||||
|             '{% trans "Add batch code" %}', |             '{% jstrans "Add batch code" %}', | ||||||
|             { |             { | ||||||
|                 collapseTarget: `row-batch-${pk}` |                 collapseTarget: `row-batch-${pk}` | ||||||
|             } |             } | ||||||
| @@ -1221,7 +1221,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|                 'fa-hashtag', |                 'fa-hashtag', | ||||||
|                 'button-row-add-serials', |                 'button-row-add-serials', | ||||||
|                 pk, |                 pk, | ||||||
|                 '{% trans "Add serial numbers" %}', |                 '{% jstrans "Add serial numbers" %}', | ||||||
|                 { |                 { | ||||||
|                     collapseTarget: `row-serials-${pk}`, |                     collapseTarget: `row-serials-${pk}`, | ||||||
|                 } |                 } | ||||||
| @@ -1229,7 +1229,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (line_items.length > 1) { |         if (line_items.length > 1) { | ||||||
|             buttons += makeRemoveButton('button-row-remove', pk, '{% trans "Remove row" %}'); |             buttons += makeRemoveButton('button-row-remove', pk, '{% jstrans "Remove row" %}'); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         buttons = wrapButtons(buttons); |         buttons = wrapButtons(buttons); | ||||||
| @@ -1261,19 +1261,19 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|         <!-- Hidden rows for extra data entry --> |         <!-- Hidden rows for extra data entry --> | ||||||
|         <tr id='row-destination-${pk}' class='collapse'> |         <tr id='row-destination-${pk}' class='collapse'> | ||||||
|             <td colspan='2'></td> |             <td colspan='2'></td> | ||||||
|             <th>{% trans "Location" %}</th> |             <th>{% jstrans "Location" %}</th> | ||||||
|             <td colspan='2'>${destination_input}</td> |             <td colspan='2'>${destination_input}</td> | ||||||
|             <td></td> |             <td></td> | ||||||
|         </tr> |         </tr> | ||||||
|         <tr id='row-batch-${pk}' class='collapse'> |         <tr id='row-batch-${pk}' class='collapse'> | ||||||
|             <td colspan='2'></td> |             <td colspan='2'></td> | ||||||
|             <th>{% trans "Batch" %}</th> |             <th>{% jstrans "Batch" %}</th> | ||||||
|             <td colspan='2'>${batch_input}</td> |             <td colspan='2'>${batch_input}</td> | ||||||
|             <td></td> |             <td></td> | ||||||
|         </tr> |         </tr> | ||||||
|         <tr id='row-serials-${pk}' class='collapse'> |         <tr id='row-serials-${pk}' class='collapse'> | ||||||
|             <td colspan='2'></td> |             <td colspan='2'></td> | ||||||
|             <th>{% trans "Serials" %}</th> |             <th>{% jstrans "Serials" %}</th> | ||||||
|             <td colspan=2'>${sn_input}</td> |             <td colspan=2'>${sn_input}</td> | ||||||
|             <td></td> |             <td></td> | ||||||
|         </tr> |         </tr> | ||||||
| @@ -1297,11 +1297,11 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|     <table class='table table-condensed' id='order-receive-table'> |     <table class='table table-condensed' id='order-receive-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>{% trans "Part" %}</th> |                 <th>{% jstrans "Part" %}</th> | ||||||
|                 <th>{% trans "Order Code" %}</th> |                 <th>{% jstrans "Order Code" %}</th> | ||||||
|                 <th>{% trans "Received" %}</th> |                 <th>{% jstrans "Received" %}</th> | ||||||
|                 <th style='min-width: 50px;'>{% trans "Quantity to Receive" %}</th> |                 <th style='min-width: 50px;'>{% jstrans "Quantity to Receive" %}</th> | ||||||
|                 <th style='min-width: 150px;'>{% trans "Status" %}</th> |                 <th style='min-width: 150px;'>{% jstrans "Status" %}</th> | ||||||
|                 <th></th> |                 <th></th> | ||||||
|             </tr> |             </tr> | ||||||
|         </thead> |         </thead> | ||||||
| @@ -1326,8 +1326,8 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|         }, |         }, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         confirmMessage: '{% trans "Confirm receipt of items" %}', |         confirmMessage: '{% jstrans "Confirm receipt of items" %}', | ||||||
|         title: '{% trans "Receive Purchase Order Items" %}', |         title: '{% jstrans "Receive Purchase Order Items" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|  |  | ||||||
|             // Run initialization routines for each line in the form |             // Run initialization routines for each line in the form | ||||||
| @@ -1395,11 +1395,11 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|                     let pk = btn.attr('pk'); |                     let pk = btn.attr('pk'); | ||||||
|  |  | ||||||
|                     // Scan to see if the barcode matches an existing StockItem |                     // Scan to see if the barcode matches an existing StockItem | ||||||
|                     barcodeDialog('{% trans "Scan Item Barcode" %}', { |                     barcodeDialog('{% jstrans "Scan Item Barcode" %}', { | ||||||
|                         details: '{% trans "Scan barcode on incoming item (must not match any existing stock items)" %}', |                         details: '{% jstrans "Scan barcode on incoming item (must not match any existing stock items)" %}', | ||||||
|                         onScan: function(response, barcode_options) { |                         onScan: function(response, barcode_options) { | ||||||
|                             // A 'success' result means that the barcode matches something existing in the database |                             // A 'success' result means that the barcode matches something existing in the database | ||||||
|                             showBarcodeMessage(barcode_options.modal, '{% trans "Barcode matches existing item" %}'); |                             showBarcodeMessage(barcode_options.modal, '{% jstrans "Barcode matches existing item" %}'); | ||||||
|                         }, |                         }, | ||||||
|                         onError400: function(response, barcode_options) { |                         onError400: function(response, barcode_options) { | ||||||
|                             if (response.barcode_data && response.barcode_hash) { |                             if (response.barcode_data && response.barcode_hash) { | ||||||
| @@ -1410,7 +1410,7 @@ function receivePurchaseOrderItems(order_id, line_items, options={}) { | |||||||
|                                 $(opts.modal).find(`#button-row-remove-barcode-${pk}`).show(); |                                 $(opts.modal).find(`#button-row-remove-barcode-${pk}`).show(); | ||||||
|                                 updateFieldValue(`items_barcode_${pk}`, response.barcode_data, {}, opts); |                                 updateFieldValue(`items_barcode_${pk}`, response.barcode_data, {}, opts); | ||||||
|                             } else { |                             } else { | ||||||
|                                 showBarcodeMessage(barcode_options.modal, '{% trans "Invalid barcode data" %}'); |                                 showBarcodeMessage(barcode_options.modal, '{% jstrans "Invalid barcode data" %}'); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
| @@ -1648,7 +1648,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|         showCustomView: display_mode == 'calendar', |         showCustomView: display_mode == 'calendar', | ||||||
|         search: display_mode != 'calendar', |         search: display_mode != 'calendar', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No purchase orders found" %}'; |             return '{% jstrans "No purchase orders found" %}'; | ||||||
|         }, |         }, | ||||||
|         buttons: constructOrderTableButtons({ |         buttons: constructOrderTableButtons({ | ||||||
|             prefix: 'purchaseorder', |             prefix: 'purchaseorder', | ||||||
| @@ -1667,7 +1667,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Purchase Order" %}', |                 title: '{% jstrans "Purchase Order" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1675,7 +1675,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|                     var html = renderLink(value, `/order/purchase-order/${row.pk}/`); |                     var html = renderLink(value, `/order/purchase-order/${row.pk}/`); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "Order is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -1683,7 +1683,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'supplier_detail', |                 field: 'supplier_detail', | ||||||
|                 title: '{% trans "Supplier" %}', |                 title: '{% jstrans "Supplier" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'supplier__name', |                 sortName: 'supplier__name', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1696,15 +1696,15 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'supplier_reference', |                 field: 'supplier_reference', | ||||||
|                 title: '{% trans "Supplier Reference" %}', |                 title: '{% jstrans "Supplier Reference" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'project_code', |                 field: 'project_code', | ||||||
|                 title: '{% trans "Project Code" %}', |                 title: '{% jstrans "Project Code" %}', | ||||||
|                 switchable: global_settings.PROJECT_CODES_ENABLED, |                 switchable: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 visible: global_settings.PROJECT_CODES_ENABLED, |                 visible: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
| @@ -1716,7 +1716,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'status', |                 field: 'status', | ||||||
|                 title: '{% trans "Status" %}', |                 title: '{% jstrans "Status" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1725,7 +1725,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'creation_date', |                 field: 'creation_date', | ||||||
|                 title: '{% trans "Date" %}', |                 title: '{% jstrans "Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
| @@ -1733,7 +1733,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'target_date', |                 field: 'target_date', | ||||||
|                 title: '{% trans "Target Date" %}', |                 title: '{% jstrans "Target Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
| @@ -1741,12 +1741,12 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'line_items', |                 field: 'line_items', | ||||||
|                 title: '{% trans "Items" %}', |                 title: '{% jstrans "Items" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'total_price', |                 field: 'total_price', | ||||||
|                 title: '{% trans "Total Cost" %}', |                 title: '{% jstrans "Total Cost" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1757,7 +1757,7 @@ function loadPurchaseOrderTable(table, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'responsible', |                 field: 'responsible', | ||||||
|                 title: '{% trans "Responsible" %}', |                 title: '{% jstrans "Responsible" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1837,16 +1837,16 @@ function deletePurchaseOrderLineItems(items, options={}) { | |||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
|     <div class='alert alert-block alert-danger'> |     <div class='alert alert-block alert-danger'> | ||||||
|     {% trans "All selected Line items will be deleted" %} |     {% jstrans "All selected Line items will be deleted" %} | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <table class='table table-striped table-condensed'> |     <table class='table table-striped table-condensed'> | ||||||
|         <tr> |         <tr> | ||||||
|             <th>{% trans "Part" %}</th> |             <th>{% jstrans "Part" %}</th> | ||||||
|             <th>{% trans "Description" %}</th> |             <th>{% jstrans "Description" %}</th> | ||||||
|             <th>{% trans "SKU" %}</th> |             <th>{% jstrans "SKU" %}</th> | ||||||
|             <th>{% trans "MPN" %}</th> |             <th>{% jstrans "MPN" %}</th> | ||||||
|             <th>{% trans "Quantity" %}</th> |             <th>{% jstrans "Quantity" %}</th> | ||||||
|         </tr> |         </tr> | ||||||
|         ${rows} |         ${rows} | ||||||
|     </table> |     </table> | ||||||
| @@ -1855,7 +1855,7 @@ function deletePurchaseOrderLineItems(items, options={}) { | |||||||
|     constructForm('{% url "api-po-line-list" %}', { |     constructForm('{% url "api-po-line-list" %}', { | ||||||
|         method: 'DELETE', |         method: 'DELETE', | ||||||
|         multi_delete: true, |         multi_delete: true, | ||||||
|         title: '{% trans "Delete selected Line items?" %}', |         title: '{% jstrans "Delete selected Line items?" %}', | ||||||
|         form_data: { |         form_data: { | ||||||
|             items: ids, |             items: ids, | ||||||
|         }, |         }, | ||||||
| @@ -1910,7 +1910,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                             method: 'POST', |                             method: 'POST', | ||||||
|                             fields: fields, |                             fields: fields, | ||||||
|                             data: data, |                             data: data, | ||||||
|                             title: '{% trans "Duplicate Line Item" %}', |                             title: '{% jstrans "Duplicate Line Item" %}', | ||||||
|                             refreshTable: table, |                             refreshTable: table, | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
| @@ -1925,7 +1925,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|                 constructForm(`{% url "api-po-line-list" %}${pk}/`, { |                 constructForm(`{% url "api-po-line-list" %}${pk}/`, { | ||||||
|                     fields: fields, |                     fields: fields, | ||||||
|                     title: '{% trans "Edit Line Item" %}', |                     title: '{% jstrans "Edit Line Item" %}', | ||||||
|                     refreshTable: table, |                     refreshTable: table, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -1936,7 +1936,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|                 constructForm(`{% url "api-po-line-list" %}${pk}/`, { |                 constructForm(`{% url "api-po-line-list" %}${pk}/`, { | ||||||
|                     method: 'DELETE', |                     method: 'DELETE', | ||||||
|                     title: '{% trans "Delete Line Item" %}', |                     title: '{% jstrans "Delete Line Item" %}', | ||||||
|                     refreshTable: table, |                     refreshTable: table, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -1984,7 +1984,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|         name: 'purchaseorderlines', |         name: 'purchaseorderlines', | ||||||
|         sidePagination: 'server', |         sidePagination: 'server', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No line items found" %}'; |             return '{% jstrans "No line items found" %}'; | ||||||
|         }, |         }, | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
|         original: options.params, |         original: options.params, | ||||||
| @@ -2001,7 +2001,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'part_name', |                 sortName: 'part_name', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     if (row.part_detail) { |                     if (row.part_detail) { | ||||||
| @@ -2011,18 +2011,18 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|                 footerFormatter: function() { |                 footerFormatter: function() { | ||||||
|                     return '{% trans "Total" %}'; |                     return '{% jstrans "Total" %}'; | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'part_detail.description', |                 field: 'part_detail.description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'SKU', |                 sortName: 'SKU', | ||||||
|                 field: 'supplier_part_detail.SKU', |                 field: 'supplier_part_detail.SKU', | ||||||
|                 title: '{% trans "SKU" %}', |                 title: '{% jstrans "SKU" %}', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderClipboard(renderLink(value, `/supplier-part/${row.part}/`)); |                         return renderClipboard(renderLink(value, `/supplier-part/${row.part}/`)); | ||||||
| @@ -2034,7 +2034,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 field: 'supplier_part_detail.link', |                 field: 'supplier_part_detail.link', | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value, {external: true}); |                         return renderLink(value, value, {external: true}); | ||||||
| @@ -2047,7 +2047,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'MPN', |                 sortName: 'MPN', | ||||||
|                 field: 'supplier_part_detail.manufacturer_part_detail.MPN', |                 field: 'supplier_part_detail.manufacturer_part_detail.MPN', | ||||||
|                 title: '{% trans "MPN" %}', |                 title: '{% jstrans "MPN" %}', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     if (row.supplier_part_detail && row.supplier_part_detail.manufacturer_part) { |                     if (row.supplier_part_detail && row.supplier_part_detail.manufacturer_part) { | ||||||
|                         return renderClipboard(renderLink(value, `/manufacturer-part/${row.supplier_part_detail.manufacturer_part}/`)); |                         return renderClipboard(renderLink(value, `/manufacturer-part/${row.supplier_part_detail.manufacturer_part}/`)); | ||||||
| @@ -2059,13 +2059,13 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Reference" %}', |                 title: '{% jstrans "Reference" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let units = ''; |                     let units = ''; | ||||||
|  |  | ||||||
| @@ -2078,7 +2078,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                     if (row.supplier_part_detail && row.supplier_part_detail.pack_quantity_native != 1.0) { |                     if (row.supplier_part_detail && row.supplier_part_detail.pack_quantity_native != 1.0) { | ||||||
|                         let pack_quantity = row.supplier_part_detail.pack_quantity; |                         let pack_quantity = row.supplier_part_detail.pack_quantity; | ||||||
|                         let total = value * row.supplier_part_detail.pack_quantity_native; |                         let total = value * row.supplier_part_detail.pack_quantity_native; | ||||||
|                         data += `<span class='fas fa-info-circle icon-blue float-right' title='{% trans "Pack Quantity" %}: ${pack_quantity} - {% trans "Total Quantity" %}: ${total}${units}'></span>`; |                         data += `<span class='fas fa-info-circle icon-blue float-right' title='{% jstrans "Pack Quantity" %}: ${pack_quantity} - {% jstrans "Total Quantity" %}: ${total}${units}'></span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return data; |                     return data; | ||||||
| @@ -2095,7 +2095,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 field: 'supplier_part_detail.pack_quantity', |                 field: 'supplier_part_detail.pack_quantity', | ||||||
|                 title: '{% trans "Pack Quantity" %}', |                 title: '{% jstrans "Pack Quantity" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var units = row.part_detail.units; |                     var units = row.part_detail.units; | ||||||
|  |  | ||||||
| @@ -2109,7 +2109,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'purchase_price', |                 field: 'purchase_price', | ||||||
|                 title: '{% trans "Unit Price" %}', |                 title: '{% jstrans "Unit Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return formatCurrency(row.purchase_price, { |                     return formatCurrency(row.purchase_price, { | ||||||
|                         currency: row.purchase_price_currency, |                         currency: row.purchase_price_currency, | ||||||
| @@ -2119,7 +2119,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 field: 'total_price', |                 field: 'total_price', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 title: '{% trans "Total Price" %}', |                 title: '{% jstrans "Total Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return formatCurrency(row.purchase_price * row.quantity, { |                     return formatCurrency(row.purchase_price * row.quantity, { | ||||||
|                         currency: row.purchase_price_currency |                         currency: row.purchase_price_currency | ||||||
| @@ -2141,13 +2141,13 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'target_date', |                 field: 'target_date', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 title: '{% trans "Target Date" %}', |                 title: '{% jstrans "Target Date" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (row.target_date) { |                     if (row.target_date) { | ||||||
|                         var html = renderDate(row.target_date); |                         var html = renderDate(row.target_date); | ||||||
|  |  | ||||||
|                         if (row.overdue) { |                         if (row.overdue) { | ||||||
|                             html += makeIconBadge('fa-calendar-times icon-red', '{% trans "This line item is overdue" %}'); |                             html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "This line item is overdue" %}'); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         return html; |                         return html; | ||||||
| @@ -2163,7 +2163,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 field: 'received', |                 field: 'received', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 title: '{% trans "Received" %}', |                 title: '{% jstrans "Received" %}', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     return makeProgressBar(row.received, row.quantity, { |                     return makeProgressBar(row.received, row.quantity, { | ||||||
|                         id: `order-line-progress-${row.pk}`, |                         id: `order-line-progress-${row.pk}`, | ||||||
| @@ -2183,7 +2183,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'destination', |                 field: 'destination', | ||||||
|                 title: '{% trans "Destination" %}', |                 title: '{% jstrans "Destination" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(row.destination_detail.pathstring, `/stock/location/${value}/`); |                         return renderLink(row.destination_detail.pathstring, `/stock/location/${value}/`); | ||||||
| @@ -2194,11 +2194,11 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'notes', |                 field: 'notes', | ||||||
|                 title: '{% trans "Notes" %}', |                 title: '{% jstrans "Notes" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value); |                         return renderLink(value, value); | ||||||
| @@ -2214,13 +2214,13 @@ function loadPurchaseOrderLineItemTable(table, options={}) { | |||||||
|                     let pk = row.pk; |                     let pk = row.pk; | ||||||
|  |  | ||||||
|                     if (options.allow_receive && row.received < row.quantity) { |                     if (options.allow_receive && row.received < row.quantity) { | ||||||
|                         buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-line-receive', pk, '{% trans "Receive line item" %}'); |                         buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-line-receive', pk, '{% jstrans "Receive line item" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (options.allow_edit) { |                     if (options.allow_edit) { | ||||||
|                         buttons += makeCopyButton('button-line-duplicate', pk, '{% trans "Duplicate line item" %}'); |                         buttons += makeCopyButton('button-line-duplicate', pk, '{% jstrans "Duplicate line item" %}'); | ||||||
|                         buttons += makeEditButton('button-line-edit', pk, '{% trans "Edit line item" %}'); |                         buttons += makeEditButton('button-line-edit', pk, '{% jstrans "Edit line item" %}'); | ||||||
|                         buttons += makeDeleteButton('button-line-delete', pk, '{% trans "Delete line item" %}'); |                         buttons += makeDeleteButton('button-line-delete', pk, '{% jstrans "Delete line item" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return wrapButtons(buttons); |                     return wrapButtons(buttons); | ||||||
|   | |||||||
| @@ -60,7 +60,7 @@ function selectReport(reports, items, options={}) { | |||||||
|  |  | ||||||
|         html += ` |         html += ` | ||||||
|         <div class='alert alert-block alert-info'> |         <div class='alert alert-block alert-info'> | ||||||
|         ${items.length} {% trans "items selected" %} |         ${items.length} {% jstrans "items selected" %} | ||||||
|         </div>`; |         </div>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -68,7 +68,7 @@ function selectReport(reports, items, options={}) { | |||||||
|     <form method='post' action='' class='js-modal-form' enctype='multipart/form-data'> |     <form method='post' action='' class='js-modal-form' enctype='multipart/form-data'> | ||||||
|         <div class='form-group'> |         <div class='form-group'> | ||||||
|             <label class='control-label requiredField' for='id_report'> |             <label class='control-label requiredField' for='id_report'> | ||||||
|             {% trans "Select Report Template" %} |             {% jstrans "Select Report Template" %} | ||||||
|             </label> |             </label> | ||||||
|             <div class='controls'> |             <div class='controls'> | ||||||
|                 <select id='id_report' class='select form-control name='report'> |                 <select id='id_report' class='select form-control name='report'> | ||||||
| @@ -83,7 +83,7 @@ function selectReport(reports, items, options={}) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     modalEnable(modal, true); |     modalEnable(modal, true); | ||||||
|     modalSetTitle(modal, '{% trans "Select Test Report Template" %}'); |     modalSetTitle(modal, '{% jstrans "Select Test Report Template" %}'); | ||||||
|     modalSetContent(modal, html); |     modalSetContent(modal, html); | ||||||
|  |  | ||||||
|     attachSelect(modal); |     attachSelect(modal); | ||||||
| @@ -120,8 +120,8 @@ function printReports(options) { | |||||||
|  |  | ||||||
|     if (!options.items || options.items.length == 0) { |     if (!options.items || options.items.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Items" %}', |             '{% jstrans "Select Items" %}', | ||||||
|             '{% trans "No items selected for printing" }', |             '{% jstrans "No items selected for printing" }', | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -137,8 +137,8 @@ function printReports(options) { | |||||||
|         success: function(response) { |         success: function(response) { | ||||||
|             if (response.length == 0) { |             if (response.length == 0) { | ||||||
|                 showAlertDialog( |                 showAlertDialog( | ||||||
|                     '{% trans "No Reports Found" %}', |                     '{% jstrans "No Reports Found" %}', | ||||||
|                     '{% trans "No report templates found which match the selected items" %}', |                     '{% jstrans "No report templates found which match the selected items" %}', | ||||||
|                 ); |                 ); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ function returnOrderFields(options={}) { | |||||||
|         customer: { |         customer: { | ||||||
|             icon: 'fa-user-tie', |             icon: 'fa-user-tie', | ||||||
|             secondary: { |             secondary: { | ||||||
|                 title: '{% trans "Add Customer" %}', |                 title: '{% jstrans "Add Customer" %}', | ||||||
|                 fields: function() { |                 fields: function() { | ||||||
|                     var fields = companyFormFields(); |                     var fields = companyFormFields(); | ||||||
|                     fields.is_customer.value = true; |                     fields.is_customer.value = true; | ||||||
| @@ -131,7 +131,7 @@ function createReturnOrder(options={}) { | |||||||
|     constructForm('{% url "api-return-order-list" %}', { |     constructForm('{% url "api-return-order-list" %}', { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Create Return Order" %}', |         title: '{% jstrans "Create Return Order" %}', | ||||||
|         onSuccess: function(data) { |         onSuccess: function(data) { | ||||||
|             location.href = `/order/return-order/${data.pk}/`; |             location.href = `/order/return-order/${data.pk}/`; | ||||||
|         }, |         }, | ||||||
| @@ -146,7 +146,7 @@ function editReturnOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-return-order-list" %}${order_id}/`, { |     constructForm(`{% url "api-return-order-list" %}${order_id}/`, { | ||||||
|         fields: returnOrderFields(options), |         fields: returnOrderFields(options), | ||||||
|         title: '{% trans "Edit Return Order" %}', |         title: '{% jstrans "Edit Return Order" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -161,12 +161,12 @@ function issueReturnOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-block alert-warning'> |     <div class='alert alert-block alert-warning'> | ||||||
|     {% trans 'After placing this order, line items will no longer be editable.' %} |     {% jstrans 'After placing this order, line items will no longer be editable.' %} | ||||||
|     </div>`; |     </div>`; | ||||||
|  |  | ||||||
|     constructForm(`{% url "api-return-order-list" %}${order_id}/issue/`, { |     constructForm(`{% url "api-return-order-list" %}${order_id}/issue/`, { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Issue Return Order" %}', |         title: '{% jstrans "Issue Return Order" %}', | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
| @@ -183,14 +183,14 @@ function cancelReturnOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-danger alert-block'> |     <div class='alert alert-danger alert-block'> | ||||||
|     {% trans "Are you sure you wish to cancel this Return Order?" %} |     {% jstrans "Are you sure you wish to cancel this Return Order?" %} | ||||||
|     </div>`; |     </div>`; | ||||||
|  |  | ||||||
|     constructForm( |     constructForm( | ||||||
|         `{% url "api-return-order-list" %}${order_id}/cancel/`, |         `{% url "api-return-order-list" %}${order_id}/cancel/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Cancel Return Order" %}', |             title: '{% jstrans "Cancel Return Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             preFormContent: html, |             preFormContent: html, | ||||||
|             onSuccess: function(response) { |             onSuccess: function(response) { | ||||||
| @@ -207,7 +207,7 @@ function cancelReturnOrder(order_id, options={}) { | |||||||
| function completeReturnOrder(order_id, options={}) { | function completeReturnOrder(order_id, options={}) { | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-block alert-warning'> |     <div class='alert alert-block alert-warning'> | ||||||
|     {% trans "Mark this order as complete?" %} |     {% jstrans "Mark this order as complete?" %} | ||||||
|     </div> |     </div> | ||||||
|     `; |     `; | ||||||
|  |  | ||||||
| @@ -215,7 +215,7 @@ function completeReturnOrder(order_id, options={}) { | |||||||
|         `{% url "api-return-order-list" %}${order_id}/complete/`, |         `{% url "api-return-order-list" %}${order_id}/complete/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Complete Return Order" %}', |             title: '{% jstrans "Complete Return Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             preFormContent: html, |             preFormContent: html, | ||||||
|             onSuccess: function(response) { |             onSuccess: function(response) { | ||||||
| @@ -263,7 +263,7 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|         showCustomView: is_calendar, |         showCustomView: is_calendar, | ||||||
|         disablePagination: is_calendar, |         disablePagination: is_calendar, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No return orders found" %}'; |             return '{% jstrans "No return orders found" %}'; | ||||||
|         }, |         }, | ||||||
|         onLoadSuccess: function() { |         onLoadSuccess: function() { | ||||||
|             // TODO |             // TODO | ||||||
| @@ -278,12 +278,12 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Return Order" %}', |                 title: '{% jstrans "Return Order" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = renderLink(value, `/order/return-order/${row.pk}/`); |                     let html = renderLink(value, `/order/return-order/${row.pk}/`); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "Order is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -293,11 +293,11 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'customer__name', |                 sortName: 'customer__name', | ||||||
|                 field: 'customer_detail', |                 field: 'customer_detail', | ||||||
|                 title: '{% trans "Customer" %}', |                 title: '{% jstrans "Customer" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     if (!row.customer_detail) { |                     if (!row.customer_detail) { | ||||||
|                         return '{% trans "Invalid Customer" %}'; |                         return '{% jstrans "Invalid Customer" %}'; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return imageHoverIcon(row.customer_detail.image) + renderLink(row.customer_detail.name, `/company/${row.customer}/sales-orders/`); |                     return imageHoverIcon(row.customer_detail.image) + renderLink(row.customer_detail.name, `/company/${row.customer}/sales-orders/`); | ||||||
| @@ -306,16 +306,16 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'customer_reference', |                 field: 'customer_reference', | ||||||
|                 title: '{% trans "Customer Reference" %}', |                 title: '{% jstrans "Customer Reference" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'project_code', |                 field: 'project_code', | ||||||
|                 title: '{% trans "Project Code" %}', |                 title: '{% jstrans "Project Code" %}', | ||||||
|                 switchable: global_settings.PROJECT_CODES_ENABLED, |                 switchable: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 visible: global_settings.PROJECT_CODES_ENABLED, |                 visible: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
| @@ -328,7 +328,7 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'status', |                 field: 'status', | ||||||
|                 title: '{% trans "Status" %}', |                 title: '{% jstrans "Status" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return returnOrderStatusDisplay(row.status); |                     return returnOrderStatusDisplay(row.status); | ||||||
|                 } |                 } | ||||||
| @@ -336,7 +336,7 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'creation_date', |                 field: 'creation_date', | ||||||
|                 title: '{% trans "Creation Date" %}', |                 title: '{% jstrans "Creation Date" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
|                 } |                 } | ||||||
| @@ -344,19 +344,19 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'target_date', |                 field: 'target_date', | ||||||
|                 title: '{% trans "Target Date" %}', |                 title: '{% jstrans "Target Date" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'line_items', |                 field: 'line_items', | ||||||
|                 title: '{% trans "Items" %}', |                 title: '{% jstrans "Items" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'responsible', |                 field: 'responsible', | ||||||
|                 title: '{% trans "Responsible" %}', |                 title: '{% jstrans "Responsible" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -378,7 +378,7 @@ function loadReturnOrderTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 // TODO: Add in the 'total cost' field |                 // TODO: Add in the 'total cost' field | ||||||
|                 field: 'total_price', |                 field: 'total_price', | ||||||
|                 title: '{% trans "Total Cost" %}', |                 title: '{% jstrans "Total Cost" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 visible: false, |                 visible: false, | ||||||
| @@ -456,7 +456,7 @@ function createReturnOrderLineItem(options={}) { | |||||||
|     constructForm('{% url "api-return-order-line-list" %}', { |     constructForm('{% url "api-return-order-line-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Line Item" %}', |         title: '{% jstrans "Add Line Item" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -473,7 +473,7 @@ function editReturnOrderLineItem(pk, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-return-order-line-list" %}${pk}/`, { |     constructForm(`{% url "api-return-order-line-list" %}${pk}/`, { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Edit Line Item" %}', |         title: '{% jstrans "Edit Line Item" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -488,8 +488,8 @@ function receiveReturnOrderItems(order_id, line_items, options={}) { | |||||||
|  |  | ||||||
|     if (line_items.length == 0) { |     if (line_items.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Line Items"% }', |             '{% jstrans "Select Line Items"% }', | ||||||
|             '{% trans "At least one line item must be selected" %}' |             '{% jstrans "At least one line item must be selected" %}' | ||||||
|         ); |         ); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -503,7 +503,7 @@ function receiveReturnOrderItems(order_id, line_items, options={}) { | |||||||
|         let buttons = ''; |         let buttons = ''; | ||||||
|  |  | ||||||
|         if (line_items.length > 1) { |         if (line_items.length > 1) { | ||||||
|             buttons += makeRemoveButton('button-row-remove', pk, '{% trans "Remove row" %}'); |             buttons += makeRemoveButton('button-row-remove', pk, '{% jstrans "Remove row" %}'); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         buttons = wrapButtons(buttons); |         buttons = wrapButtons(buttons); | ||||||
| @@ -536,8 +536,8 @@ function receiveReturnOrderItems(order_id, line_items, options={}) { | |||||||
|     <table class='table table-striped table-condensed' id='order-receive-table'> |     <table class='table table-striped table-condensed' id='order-receive-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>{% trans "Part" %}</th> |                 <th>{% jstrans "Part" %}</th> | ||||||
|                 <th>{% trans "Serial Number" %}</th> |                 <th>{% jstrans "Serial Number" %}</th> | ||||||
|             </tr> |             </tr> | ||||||
|         </thead> |         </thead> | ||||||
|         <tbody>${table_entries}</tbody> |         <tbody>${table_entries}</tbody> | ||||||
| @@ -558,8 +558,8 @@ function receiveReturnOrderItems(order_id, line_items, options={}) { | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         confirmMessage: '{% trans "Confirm receipt of items" %}', |         confirmMessage: '{% jstrans "Confirm receipt of items" %}', | ||||||
|         title: '{% trans "Receive Return Order Items" %}', |         title: '{% jstrans "Receive Return Order Items" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|             // Add callback to remove rows |             // Add callback to remove rows | ||||||
|             $(opts.modal).find('.button-row-remove').click(function() { |             $(opts.modal).find('.button-row-remove').click(function() { | ||||||
| @@ -666,7 +666,7 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|  |  | ||||||
|                 constructForm(`{% url "api-return-order-line-list" %}${pk}/`, { |                 constructForm(`{% url "api-return-order-line-list" %}${pk}/`, { | ||||||
|                     fields: returnOrderLineItemFields(), |                     fields: returnOrderLineItemFields(), | ||||||
|                     title: '{% trans "Edit Line Item" %}', |                     title: '{% jstrans "Edit Line Item" %}', | ||||||
|                     refreshTable: table, |                     refreshTable: table, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -679,7 +679,7 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|  |  | ||||||
|                 constructForm(`{% url "api-return-order-line-list" %}${pk}/`, { |                 constructForm(`{% url "api-return-order-line-list" %}${pk}/`, { | ||||||
|                     method: 'DELETE', |                     method: 'DELETE', | ||||||
|                     title: '{% trans "Delete Line Item" %}', |                     title: '{% jstrans "Delete Line Item" %}', | ||||||
|                     refreshTable: table, |                     refreshTable: table, | ||||||
|                 }); |                 }); | ||||||
|             }); |             }); | ||||||
| @@ -690,7 +690,7 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|         url: '{% url "api-return-order-line-list" %}', |         url: '{% url "api-return-order-line-list" %}', | ||||||
|         name: 'returnorderlineitems', |         name: 'returnorderlineitems', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No matching line items" %}'; |             return '{% jstrans "No matching line items" %}'; | ||||||
|         }, |         }, | ||||||
|         onPostBody: setupCallbacks, |         onPostBody: setupCallbacks, | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
| @@ -707,7 +707,7 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|                 field: 'part', |                 field: 'part', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let part = row.part_detail; |                     let part = row.part_detail; | ||||||
|                     let html = thumbnailImage(part.thumbnail) + ' '; |                     let html = thumbnailImage(part.thumbnail) + ' '; | ||||||
| @@ -719,18 +719,18 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|                 field: 'item', |                 field: 'item', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 title: '{% trans "Item" %}', |                 title: '{% jstrans "Item" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return renderLink(`{% trans "Serial Number" %}: ${row.item_detail.serial}`, `/stock/item/${row.item}/`); |                     return renderLink(`{% jstrans "Serial Number" %}: ${row.item_detail.serial}`, `/stock/item/${row.item}/`); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Reference" %}', |                 title: '{% jstrans "Reference" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'outcome', |                 field: 'outcome', | ||||||
|                 title: '{% trans "Outcome" %}', |                 title: '{% jstrans "Outcome" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return returnOrderLineItemStatusDisplay(value); |                     return returnOrderLineItemStatusDisplay(value); | ||||||
| @@ -738,7 +738,7 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'price', |                 field: 'price', | ||||||
|                 title: '{% trans "Price" %}', |                 title: '{% jstrans "Price" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return formatCurrency(row.price, { |                     return formatCurrency(row.price, { | ||||||
|                         currency: row.price_currency, |                         currency: row.price_currency, | ||||||
| @@ -748,12 +748,12 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'target_date', |                 field: 'target_date', | ||||||
|                 title: '{% trans "Target Date" %}', |                 title: '{% jstrans "Target Date" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     let html = renderDate(value); |                     let html = renderDate(value); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times icon-red', '{% trans "This line item is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "This line item is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -761,7 +761,7 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'received_date', |                 field: 'received_date', | ||||||
|                 title: '{% trans "Received" %}', |                 title: '{% jstrans "Received" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     if (!value) { |                     if (!value) { | ||||||
| @@ -773,11 +773,11 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'notes', |                 field: 'notes', | ||||||
|                 title: '{% trans "Notes" %}', |                 title: '{% jstrans "Notes" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value); |                         return renderLink(value, value); | ||||||
| @@ -795,14 +795,14 @@ function loadReturnOrderLineItemTable(options={}) { | |||||||
|                     if (options.allow_edit) { |                     if (options.allow_edit) { | ||||||
|  |  | ||||||
|                         if (options.allow_receive && !row.received_date) { |                         if (options.allow_receive && !row.received_date) { | ||||||
|                             buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-line-receive', pk, '{% trans "Mark item as received" %}'); |                             buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-line-receive', pk, '{% jstrans "Mark item as received" %}'); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         buttons += makeEditButton('button-line-edit', pk, '{% trans "Edit line item" %}'); |                         buttons += makeEditButton('button-line-edit', pk, '{% jstrans "Edit line item" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (options.allow_delete) { |                     if (options.allow_delete) { | ||||||
|                         buttons += makeDeleteButton('button-line-delete', pk, '{% trans "Delete line item" %}'); |                         buttons += makeDeleteButton('button-line-delete', pk, '{% jstrans "Delete line item" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return wrapButtons(buttons); |                     return wrapButtons(buttons); | ||||||
|   | |||||||
| @@ -83,7 +83,7 @@ function salesOrderFields(options={}) { | |||||||
|         customer: { |         customer: { | ||||||
|             icon: 'fa-user-tie', |             icon: 'fa-user-tie', | ||||||
|             secondary: { |             secondary: { | ||||||
|                 title: '{% trans "Add Customer" %}', |                 title: '{% jstrans "Add Customer" %}', | ||||||
|                 fields: function() { |                 fields: function() { | ||||||
|                     var fields = companyFormFields(); |                     var fields = companyFormFields(); | ||||||
|                     fields.is_customer.value = true; |                     fields.is_customer.value = true; | ||||||
| @@ -158,7 +158,7 @@ function createSalesOrder(options={}) { | |||||||
|     constructForm('{% url "api-so-list" %}', { |     constructForm('{% url "api-so-list" %}', { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         title: '{% trans "Create Sales Order" %}', |         title: '{% jstrans "Create Sales Order" %}', | ||||||
|         onSuccess: function(data) { |         onSuccess: function(data) { | ||||||
|             location.href = `/order/sales-order/${data.pk}/`; |             location.href = `/order/sales-order/${data.pk}/`; | ||||||
|         }, |         }, | ||||||
| @@ -173,7 +173,7 @@ function editSalesOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|     constructForm(`{% url "api-so-list" %}${order_id}/`, { |     constructForm(`{% url "api-so-list" %}${order_id}/`, { | ||||||
|         fields: salesOrderFields(options), |         fields: salesOrderFields(options), | ||||||
|         title: '{% trans "Edit Sales Order" %}', |         title: '{% jstrans "Edit Sales Order" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         } |         } | ||||||
| @@ -234,7 +234,7 @@ function createSalesOrderLineItem(options={}) { | |||||||
|     constructForm('{% url "api-so-line-list" %}', { |     constructForm('{% url "api-so-line-list" %}', { | ||||||
|         fields: fields, |         fields: fields, | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Add Line Item" %}', |         title: '{% jstrans "Add Line Item" %}', | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
|             handleFormSuccess(response, options); |             handleFormSuccess(response, options); | ||||||
|         }, |         }, | ||||||
| @@ -288,17 +288,17 @@ function completeSalesOrderShipment(shipment_id, options={}) { | |||||||
|             if (!allocations || allocations.length == 0) { |             if (!allocations || allocations.length == 0) { | ||||||
|                 html = ` |                 html = ` | ||||||
|                 <div class='alert alert-block alert-danger'> |                 <div class='alert alert-block alert-danger'> | ||||||
|                 {% trans "No stock items have been allocated to this shipment" %} |                 {% jstrans "No stock items have been allocated to this shipment" %} | ||||||
|                 </div> |                 </div> | ||||||
|                 `; |                 `; | ||||||
|             } else { |             } else { | ||||||
|                 html = ` |                 html = ` | ||||||
|                 {% trans "The following stock items will be shipped" %} |                 {% jstrans "The following stock items will be shipped" %} | ||||||
|                 <table class='table table-striped table-condensed'> |                 <table class='table table-striped table-condensed'> | ||||||
|                     <thead> |                     <thead> | ||||||
|                         <tr> |                         <tr> | ||||||
|                             <th>{% trans "Part" %}</th> |                             <th>{% jstrans "Part" %}</th> | ||||||
|                             <th>{% trans "Stock Item" %}</th> |                             <th>{% jstrans "Stock Item" %}</th> | ||||||
|                         </tr> |                         </tr> | ||||||
|                     </thead> |                     </thead> | ||||||
|                     <tbody> |                     <tbody> | ||||||
| @@ -312,9 +312,9 @@ function completeSalesOrderShipment(shipment_id, options={}) { | |||||||
|                     var stock = ''; |                     var stock = ''; | ||||||
|  |  | ||||||
|                     if (allocation.serial) { |                     if (allocation.serial) { | ||||||
|                         stock = `{% trans "Serial Number" %}: ${allocation.serial}`; |                         stock = `{% jstrans "Serial Number" %}: ${allocation.serial}`; | ||||||
|                     } else { |                     } else { | ||||||
|                         stock = `{% trans "Quantity" %}: ${allocation.quantity}`; |                         stock = `{% jstrans "Quantity" %}: ${allocation.quantity}`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     html += ` |                     html += ` | ||||||
| @@ -333,7 +333,7 @@ function completeSalesOrderShipment(shipment_id, options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-so-shipment-list" %}${shipment_id}/ship/`, { |             constructForm(`{% url "api-so-shipment-list" %}${shipment_id}/ship/`, { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 title: `{% trans "Complete Shipment" %} ${shipment.reference}`, |                 title: `{% jstrans "Complete Shipment" %} ${shipment.reference}`, | ||||||
|                 fields: { |                 fields: { | ||||||
|                     shipment_date: { |                     shipment_date: { | ||||||
|                         value: moment().format('YYYY-MM-DD'), |                         value: moment().format('YYYY-MM-DD'), | ||||||
| @@ -357,7 +357,7 @@ function completeSalesOrderShipment(shipment_id, options={}) { | |||||||
|                 }, |                 }, | ||||||
|                 preFormContent: html, |                 preFormContent: html, | ||||||
|                 confirm: true, |                 confirm: true, | ||||||
|                 confirmMessage: '{% trans "Confirm Shipment" %}', |                 confirmMessage: '{% jstrans "Confirm Shipment" %}', | ||||||
|                 buttons: options.buttons, |                 buttons: options.buttons, | ||||||
|                 onSuccess: function(data) { |                 onSuccess: function(data) { | ||||||
|                     // Reload tables |                     // Reload tables | ||||||
| @@ -413,11 +413,11 @@ function completePendingShipments(order_id, options={}) { | |||||||
|  |  | ||||||
|         if (!pending_shipments.length) { |         if (!pending_shipments.length) { | ||||||
|             html += ` |             html += ` | ||||||
|             {% trans "No pending shipments found" %} |             {% jstrans "No pending shipments found" %} | ||||||
|             `; |             `; | ||||||
|         } else { |         } else { | ||||||
|             html += ` |             html += ` | ||||||
|             {% trans "No stock items have been allocated to pending shipments" %} |             {% jstrans "No stock items have been allocated to pending shipments" %} | ||||||
|             `; |             `; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -427,7 +427,7 @@ function completePendingShipments(order_id, options={}) { | |||||||
|  |  | ||||||
|         constructForm(`{% url "api-so-shipment-list" %}0/ship/`, { |         constructForm(`{% url "api-so-shipment-list" %}0/ship/`, { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Complete Shipments" %}', |             title: '{% jstrans "Complete Shipments" %}', | ||||||
|             preFormContent: html, |             preFormContent: html, | ||||||
|             onSubmit: function(fields, options) { |             onSubmit: function(fields, options) { | ||||||
|                 handleFormSuccess(fields, options); |                 handleFormSuccess(fields, options); | ||||||
| @@ -449,7 +449,7 @@ function completePendingShipmentsHelper(shipments, shipment_idx, options={}) { | |||||||
|                 buttons: [ |                 buttons: [ | ||||||
|                     { |                     { | ||||||
|                         name: 'skip', |                         name: 'skip', | ||||||
|                         title: `{% trans "Skip" %}`, |                         title: `{% jstrans "Skip" %}`, | ||||||
|                         onClick: function(form_options) { |                         onClick: function(form_options) { | ||||||
|                             if (form_options.modal) { |                             if (form_options.modal) { | ||||||
|                                 $(form_options.modal).modal('hide'); |                                 $(form_options.modal).modal('hide'); | ||||||
| @@ -481,7 +481,7 @@ function completeSalesOrder(order_id, options={}) { | |||||||
|         `/api/order/so/${order_id}/complete/`, |         `/api/order/so/${order_id}/complete/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Complete Sales Order" %}', |             title: '{% jstrans "Complete Sales Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             fieldsFunction: function(opts) { |             fieldsFunction: function(opts) { | ||||||
|                 var fields = { |                 var fields = { | ||||||
| @@ -497,21 +497,21 @@ function completeSalesOrder(order_id, options={}) { | |||||||
|             preFormContent: function(opts) { |             preFormContent: function(opts) { | ||||||
|                 var html = ` |                 var html = ` | ||||||
|                 <div class='alert alert-block alert-info'> |                 <div class='alert alert-block alert-info'> | ||||||
|                     {% trans "Mark this order as complete?" %} |                     {% jstrans "Mark this order as complete?" %} | ||||||
|                 </div>`; |                 </div>`; | ||||||
|  |  | ||||||
|                 if (opts.context.pending_shipments) { |                 if (opts.context.pending_shipments) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-danger'> |                     <div class='alert alert-block alert-danger'> | ||||||
|                     {% trans "Order cannot be completed as there are incomplete shipments" %}<br> |                     {% jstrans "Order cannot be completed as there are incomplete shipments" %}<br> | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (!opts.context.is_complete) { |                 if (!opts.context.is_complete) { | ||||||
|                     html += ` |                     html += ` | ||||||
|                     <div class='alert alert-block alert-warning'> |                     <div class='alert alert-block alert-warning'> | ||||||
|                     {% trans "This order has line items which have not been completed." %}<br> |                     {% jstrans "This order has line items which have not been completed." %}<br> | ||||||
|                     {% trans "Completing this order means that the order and line items will no longer be editable." %} |                     {% jstrans "Completing this order means that the order and line items will no longer be editable." %} | ||||||
|                     </div>`; |                     </div>`; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -532,12 +532,12 @@ function issueSalesOrder(order_id, options={}) { | |||||||
|  |  | ||||||
|     let html = ` |     let html = ` | ||||||
|     <div class='alert alert-block alert-info'> |     <div class='alert alert-block alert-info'> | ||||||
|     {% trans "Issue this Sales Order?" %} |     {% jstrans "Issue this Sales Order?" %} | ||||||
|     </div>`; |     </div>`; | ||||||
|  |  | ||||||
|     constructForm(`{% url "api-so-list" %}${order_id}/issue/`, { |     constructForm(`{% url "api-so-list" %}${order_id}/issue/`, { | ||||||
|         method: 'POST', |         method: 'POST', | ||||||
|         title: '{% trans "Issue Sales Order" %}', |         title: '{% jstrans "Issue Sales Order" %}', | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         onSuccess: function(response) { |         onSuccess: function(response) { | ||||||
| @@ -556,12 +556,12 @@ function cancelSalesOrder(order_id, options={}) { | |||||||
|         `/api/order/so/${order_id}/cancel/`, |         `/api/order/so/${order_id}/cancel/`, | ||||||
|         { |         { | ||||||
|             method: 'POST', |             method: 'POST', | ||||||
|             title: '{% trans "Cancel Sales Order" %}', |             title: '{% jstrans "Cancel Sales Order" %}', | ||||||
|             confirm: true, |             confirm: true, | ||||||
|             preFormContent: function(opts) { |             preFormContent: function(opts) { | ||||||
|                 var html = ` |                 var html = ` | ||||||
|                 <div class='alert alert-block alert-warning'> |                 <div class='alert alert-block alert-warning'> | ||||||
|                 {% trans "Cancelling this order means that the order will no longer be editable." %} |                 {% jstrans "Cancelling this order means that the order will no longer be editable." %} | ||||||
|                 </div>`; |                 </div>`; | ||||||
|  |  | ||||||
|                 return html; |                 return html; | ||||||
| @@ -615,7 +615,7 @@ function createSalesOrderShipment(options={}) { | |||||||
|                 constructForm('{% url "api-so-shipment-list" %}', { |                 constructForm('{% url "api-so-shipment-list" %}', { | ||||||
|                     method: 'POST', |                     method: 'POST', | ||||||
|                     fields: fields, |                     fields: fields, | ||||||
|                     title: '{% trans "Create New Shipment" %}', |                     title: '{% jstrans "Create New Shipment" %}', | ||||||
|                     onSuccess: function(data) { |                     onSuccess: function(data) { | ||||||
|                         if (options.onSuccess) { |                         if (options.onSuccess) { | ||||||
|                             options.onSuccess(data); |                             options.onSuccess(data); | ||||||
| @@ -725,7 +725,7 @@ function loadSalesOrderTable(table, options) { | |||||||
|         showCustomView: display_mode == 'calendar', |         showCustomView: display_mode == 'calendar', | ||||||
|         disablePagination: display_mode == 'calendar', |         disablePagination: display_mode == 'calendar', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No sales orders found" %}'; |             return '{% jstrans "No sales orders found" %}'; | ||||||
|         }, |         }, | ||||||
|         buttons: constructOrderTableButtons({ |         buttons: constructOrderTableButtons({ | ||||||
|             prefix: 'salesorder', |             prefix: 'salesorder', | ||||||
| @@ -766,12 +766,12 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Sales Order" %}', |                 title: '{% jstrans "Sales Order" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = renderLink(value, `/order/sales-order/${row.pk}/`); |                     var html = renderLink(value, `/order/sales-order/${row.pk}/`); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "Order is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -781,11 +781,11 @@ function loadSalesOrderTable(table, options) { | |||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 sortName: 'customer__name', |                 sortName: 'customer__name', | ||||||
|                 field: 'customer_detail', |                 field: 'customer_detail', | ||||||
|                 title: '{% trans "Customer" %}', |                 title: '{% jstrans "Customer" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     if (!row.customer_detail) { |                     if (!row.customer_detail) { | ||||||
|                         return '{% trans "Invalid Customer" %}'; |                         return '{% jstrans "Invalid Customer" %}'; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return imageHoverIcon(row.customer_detail.image) + renderLink(row.customer_detail.name, `/company/${row.customer}/sales-orders/`); |                     return imageHoverIcon(row.customer_detail.image) + renderLink(row.customer_detail.name, `/company/${row.customer}/sales-orders/`); | ||||||
| @@ -794,16 +794,16 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'customer_reference', |                 field: 'customer_reference', | ||||||
|                 title: '{% trans "Customer Reference" %}', |                 title: '{% jstrans "Customer Reference" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 sortable: false, |                 sortable: false, | ||||||
|                 field: 'description', |                 field: 'description', | ||||||
|                 title: '{% trans "Description" %}', |                 title: '{% jstrans "Description" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'project_code', |                 field: 'project_code', | ||||||
|                 title: '{% trans "Project Code" %}', |                 title: '{% jstrans "Project Code" %}', | ||||||
|                 switchable: global_settings.PROJECT_CODES_ENABLED, |                 switchable: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 visible: global_settings.PROJECT_CODES_ENABLED, |                 visible: global_settings.PROJECT_CODES_ENABLED, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
| @@ -816,7 +816,7 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'status', |                 field: 'status', | ||||||
|                 title: '{% trans "Status" %}', |                 title: '{% jstrans "Status" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return salesOrderStatusDisplay(row.status); |                     return salesOrderStatusDisplay(row.status); | ||||||
|                 } |                 } | ||||||
| @@ -824,7 +824,7 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'creation_date', |                 field: 'creation_date', | ||||||
|                 title: '{% trans "Creation Date" %}', |                 title: '{% jstrans "Creation Date" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
|                 } |                 } | ||||||
| @@ -832,7 +832,7 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'target_date', |                 field: 'target_date', | ||||||
|                 title: '{% trans "Target Date" %}', |                 title: '{% jstrans "Target Date" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
|                 } |                 } | ||||||
| @@ -840,7 +840,7 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'shipment_date', |                 field: 'shipment_date', | ||||||
|                 title: '{% trans "Shipment Date" %}', |                 title: '{% jstrans "Shipment Date" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     return renderDate(value); |                     return renderDate(value); | ||||||
|                 } |                 } | ||||||
| @@ -848,11 +848,11 @@ function loadSalesOrderTable(table, options) { | |||||||
|             { |             { | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 field: 'line_items', |                 field: 'line_items', | ||||||
|                 title: '{% trans "Items" %}' |                 title: '{% jstrans "Items" %}' | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'total_price', |                 field: 'total_price', | ||||||
|                 title: '{% trans "Total Cost" %}', |                 title: '{% jstrans "Total Cost" %}', | ||||||
|                 switchable: true, |                 switchable: true, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -905,15 +905,15 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|  |  | ||||||
|         let html = ''; |         let html = ''; | ||||||
|  |  | ||||||
|         html += makeEditButton('button-shipment-edit', pk, '{% trans "Edit shipment" %}'); |         html += makeEditButton('button-shipment-edit', pk, '{% jstrans "Edit shipment" %}'); | ||||||
|  |  | ||||||
|         if (!options.shipped) { |         if (!options.shipped) { | ||||||
|             html += makeIconButton('fa-truck icon-green', 'button-shipment-ship', pk, '{% trans "Complete shipment" %}'); |             html += makeIconButton('fa-truck icon-green', 'button-shipment-ship', pk, '{% jstrans "Complete shipment" %}'); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         var enable_delete = row.allocations && row.allocations.length == 0; |         var enable_delete = row.allocations && row.allocations.length == 0; | ||||||
|  |  | ||||||
|         html += makeDeleteButton('button-shipment-delete', pk, '{% trans "Delete shipment" %}', {disabled: !enable_delete}); |         html += makeDeleteButton('button-shipment-delete', pk, '{% jstrans "Delete shipment" %}', {disabled: !enable_delete}); | ||||||
|  |  | ||||||
|         return wrapButtons(html); |         return wrapButtons(html); | ||||||
|     } |     } | ||||||
| @@ -930,7 +930,7 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-so-shipment-list" %}${pk}/`, { |             constructForm(`{% url "api-so-shipment-list" %}${pk}/`, { | ||||||
|                 fields: fields, |                 fields: fields, | ||||||
|                 title: '{% trans "Edit Shipment" %}', |                 title: '{% jstrans "Edit Shipment" %}', | ||||||
|                 refreshTable: table, |                 refreshTable: table, | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @@ -945,7 +945,7 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|             var pk = $(this).attr('pk'); |             var pk = $(this).attr('pk'); | ||||||
|  |  | ||||||
|             constructForm(`{% url "api-so-shipment-list" %}${pk}/`, { |             constructForm(`{% url "api-so-shipment-list" %}${pk}/`, { | ||||||
|                 title: '{% trans "Delete Shipment" %}', |                 title: '{% jstrans "Delete Shipment" %}', | ||||||
|                 method: 'DELETE', |                 method: 'DELETE', | ||||||
|                 refreshTable: table, |                 refreshTable: table, | ||||||
|             }); |             }); | ||||||
| @@ -978,7 +978,7 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No matching shipments found" %}'; |             return '{% jstrans "No matching shipments found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
| @@ -989,13 +989,13 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 visible: show_so_reference, |                 visible: show_so_reference, | ||||||
|                 field: 'order_detail', |                 field: 'order_detail', | ||||||
|                 title: '{% trans "Sales Order" %}', |                 title: '{% jstrans "Sales Order" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var html = renderLink(row.order_detail.reference, `/order/sales-order/${row.order}/`); |                     var html = renderLink(row.order_detail.reference, `/order/sales-order/${row.order}/`); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times icon-red', '{% jstrans "Order is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -1003,12 +1003,12 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'reference', |                 field: 'reference', | ||||||
|                 title: '{% trans "Shipment Reference" %}', |                 title: '{% jstrans "Shipment Reference" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'allocations', |                 field: 'allocations', | ||||||
|                 title: '{% trans "Items" %}', |                 title: '{% jstrans "Items" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
| @@ -1021,39 +1021,39 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'shipment_date', |                 field: 'shipment_date', | ||||||
|                 title: '{% trans "Shipment Date" %}', |                 title: '{% jstrans "Shipment Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderDate(value); |                         return renderDate(value); | ||||||
|                     } else { |                     } else { | ||||||
|                         return '<em>{% trans "Not shipped" %}</em>'; |                         return '<em>{% jstrans "Not shipped" %}</em>'; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'delivery_date', |                 field: 'delivery_date', | ||||||
|                 title: '{% trans "Delivery Date" %}', |                 title: '{% jstrans "Delivery Date" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderDate(value); |                         return renderDate(value); | ||||||
|                     } else { |                     } else { | ||||||
|                         return '<em>{% trans "Unknown" %}</em>'; |                         return '<em>{% jstrans "Unknown" %}</em>'; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'tracking_number', |                 field: 'tracking_number', | ||||||
|                 title: '{% trans "Tracking" %}', |                 title: '{% jstrans "Tracking" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'invoice_number', |                 field: 'invoice_number', | ||||||
|                 title: '{% trans "Invoice" %}', |                 title: '{% jstrans "Invoice" %}', | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|                 title: '{% trans "Link" %}', |                 title: '{% jstrans "Link" %}', | ||||||
|                 formatter: function(value) { |                 formatter: function(value) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderLink(value, value); |                         return renderLink(value, value); | ||||||
| @@ -1064,7 +1064,7 @@ function loadSalesOrderShipmentTable(table, options={}) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'notes', |                 field: 'notes', | ||||||
|                 title: '{% trans "Notes" %}', |                 title: '{% jstrans "Notes" %}', | ||||||
|                 visible: false, |                 visible: false, | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 // TODO: Implement 'notes' field |                 // TODO: Implement 'notes' field | ||||||
| @@ -1106,7 +1106,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|             makeRemoveButton( |             makeRemoveButton( | ||||||
|                 'button-row-remove', |                 'button-row-remove', | ||||||
|                 pk, |                 pk, | ||||||
|                 '{% trans "Remove row" %}', |                 '{% jstrans "Remove row" %}', | ||||||
|             ) |             ) | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
| @@ -1118,7 +1118,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|                 type: 'decimal', |                 type: 'decimal', | ||||||
|                 min_value: 0, |                 min_value: 0, | ||||||
|                 value: quantity || 0, |                 value: quantity || 0, | ||||||
|                 title: '{% trans "Specify stock allocation quantity" %}', |                 title: '{% jstrans "Specify stock allocation quantity" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
| @@ -1168,8 +1168,8 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|  |  | ||||||
|     if (table_entries.length == 0) { |     if (table_entries.length == 0) { | ||||||
|         showAlertDialog( |         showAlertDialog( | ||||||
|             '{% trans "Select Parts" %}', |             '{% jstrans "Select Parts" %}', | ||||||
|             '{% trans "You must select at least one part to allocate" %}', |             '{% jstrans "You must select at least one part to allocate" %}', | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
| @@ -1182,8 +1182,8 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|         'take_from', |         'take_from', | ||||||
|         { |         { | ||||||
|             type: 'related field', |             type: 'related field', | ||||||
|             label: '{% trans "Source Location" %}', |             label: '{% jstrans "Source Location" %}', | ||||||
|             help_text: '{% trans "Select source location (leave blank to take from all locations)" %}', |             help_text: '{% jstrans "Select source location (leave blank to take from all locations)" %}', | ||||||
|             required: false, |             required: false, | ||||||
|         }, |         }, | ||||||
|         {}, |         {}, | ||||||
| @@ -1194,9 +1194,9 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|     <table class='table table-striped table-condensed' id='stock-allocation-table'> |     <table class='table table-striped table-condensed' id='stock-allocation-table'> | ||||||
|         <thead> |         <thead> | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>{% trans "Part" %}</th> |                 <th>{% jstrans "Part" %}</th> | ||||||
|                 <th style='min-width: 250px;'>{% trans "Stock Item" %}</th> |                 <th style='min-width: 250px;'>{% jstrans "Stock Item" %}</th> | ||||||
|                 <th>{% trans "Quantity" %}</th> |                 <th>{% jstrans "Quantity" %}</th> | ||||||
|                 <th></th> |                 <th></th> | ||||||
|         </thead> |         </thead> | ||||||
|         <tbody> |         <tbody> | ||||||
| @@ -1216,7 +1216,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|                 auto_fill: true, |                 auto_fill: true, | ||||||
|                 secondary: { |                 secondary: { | ||||||
|                     method: 'POST', |                     method: 'POST', | ||||||
|                     title: '{% trans "Add Shipment" %}', |                     title: '{% jstrans "Add Shipment" %}', | ||||||
|                     fields: function() { |                     fields: function() { | ||||||
|                         var ref = null; |                         var ref = null; | ||||||
|  |  | ||||||
| @@ -1267,8 +1267,8 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|         }, |         }, | ||||||
|         preFormContent: html, |         preFormContent: html, | ||||||
|         confirm: true, |         confirm: true, | ||||||
|         confirmMessage: '{% trans "Confirm stock allocation" %}', |         confirmMessage: '{% jstrans "Confirm stock allocation" %}', | ||||||
|         title: '{% trans "Allocate Stock Items to Sales Order" %}', |         title: '{% jstrans "Allocate Stock Items to Sales Order" %}', | ||||||
|         afterRender: function(fields, opts) { |         afterRender: function(fields, opts) { | ||||||
|  |  | ||||||
|             // Initialize source location field |             // Initialize source location field | ||||||
| @@ -1280,7 +1280,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|                 type: 'related field', |                 type: 'related field', | ||||||
|                 value: options.source_location || null, |                 value: options.source_location || null, | ||||||
|                 noResults: function(query) { |                 noResults: function(query) { | ||||||
|                     return '{% trans "No matching stock locations" %}'; |                     return '{% jstrans "No matching stock locations" %}'; | ||||||
|                 }, |                 }, | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
| @@ -1359,7 +1359,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) { | |||||||
|                             return filters; |                             return filters; | ||||||
|                         }, |                         }, | ||||||
|                         noResults: function(query) { |                         noResults: function(query) { | ||||||
|                             return '{% trans "No matching stock items" %}'; |                             return '{% jstrans "No matching stock items" %}'; | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                     null, |                     null, | ||||||
| @@ -1474,7 +1474,7 @@ function loadSalesOrderAllocationTable(table, options={}) { | |||||||
|         paginationVAlign: 'bottom', |         paginationVAlign: 'bottom', | ||||||
|         original: options.params, |         original: options.params, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No sales order allocations found" %}'; |             return '{% jstrans "No sales order allocations found" %}'; | ||||||
|         }, |         }, | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
| @@ -1485,7 +1485,7 @@ function loadSalesOrderAllocationTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 field: 'order', |                 field: 'order', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 title: '{% trans "Order" %}', |                 title: '{% jstrans "Order" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     var ref = `${row.order_detail.reference}`; |                     var ref = `${row.order_detail.reference}`; | ||||||
| @@ -1496,37 +1496,37 @@ function loadSalesOrderAllocationTable(table, options={}) { | |||||||
|             { |             { | ||||||
|                 field: 'item', |                 field: 'item', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 title: '{% trans "Stock Item" %}', |                 title: '{% jstrans "Stock Item" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     // Render a link to the particular stock item |                     // Render a link to the particular stock item | ||||||
|  |  | ||||||
|                     var link = `/stock/item/${row.item}/`; |                     var link = `/stock/item/${row.item}/`; | ||||||
|                     var text = `{% trans "Stock Item" %} ${row.item}`; |                     var text = `{% jstrans "Stock Item" %} ${row.item}`; | ||||||
|  |  | ||||||
|                     return renderLink(text, link); |                     return renderLink(text, link); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'location', |                 field: 'location', | ||||||
|                 title: '{% trans "Location" %}', |                 title: '{% jstrans "Location" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     return locationDetail(row.item_detail, true); |                     return locationDetail(row.item_detail, true); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'quantity', |                 field: 'quantity', | ||||||
|                 title: '{% trans "Quantity" %}', |                 title: '{% jstrans "Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'shipment_date', |                 field: 'shipment_date', | ||||||
|                 title: '{% trans "Shipped" %}', |                 title: '{% jstrans "Shipped" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (value) { |                     if (value) { | ||||||
|                         return renderDate(value); |                         return renderDate(value); | ||||||
|                     } else { |                     } else { | ||||||
|                         return `<em>{% trans "Not shipped" %}</em>`; |                         return `<em>{% jstrans "Not shipped" %}</em>`; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -1566,7 +1566,7 @@ function showAllocationSubTable(index, row, element, options) { | |||||||
|                     fields: { |                     fields: { | ||||||
|                         quantity: {}, |                         quantity: {}, | ||||||
|                     }, |                     }, | ||||||
|                     title: '{% trans "Edit Stock Allocation" %}', |                     title: '{% jstrans "Edit Stock Allocation" %}', | ||||||
|                     refreshTable: options.table, |                     refreshTable: options.table, | ||||||
|                 }, |                 }, | ||||||
|             ); |             ); | ||||||
| @@ -1580,8 +1580,8 @@ function showAllocationSubTable(index, row, element, options) { | |||||||
|                 `/api/order/so-allocation/${pk}/`, |                 `/api/order/so-allocation/${pk}/`, | ||||||
|                 { |                 { | ||||||
|                     method: 'DELETE', |                     method: 'DELETE', | ||||||
|                     confirmMessage: '{% trans "Confirm Delete Operation" %}', |                     confirmMessage: '{% jstrans "Confirm Delete Operation" %}', | ||||||
|                     title: '{% trans "Delete Stock Allocation" %}', |                     title: '{% jstrans "Delete Stock Allocation" %}', | ||||||
|                     refreshTable: options.table, |                     refreshTable: options.table, | ||||||
|                 } |                 } | ||||||
|             ); |             ); | ||||||
| @@ -1595,20 +1595,20 @@ function showAllocationSubTable(index, row, element, options) { | |||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 field: 'part_detail', |                 field: 'part_detail', | ||||||
|                 title: '{% trans "Part" %}', |                 title: '{% jstrans "Part" %}', | ||||||
|                 formatter: function(part, row) { |                 formatter: function(part, row) { | ||||||
|                     return imageHoverIcon(part.thumbnail) + renderLink(part.full_name, `/part/${part.pk}/`); |                     return imageHoverIcon(part.thumbnail) + renderLink(part.full_name, `/part/${part.pk}/`); | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'allocated', |                 field: 'allocated', | ||||||
|                 title: '{% trans "Stock Item" %}', |                 title: '{% jstrans "Stock Item" %}', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|                     let item = row.item_detail; |                     let item = row.item_detail; | ||||||
|                     let text = `{% trans "Quantity" %}: ${row.quantity}`; |                     let text = `{% jstrans "Quantity" %}: ${row.quantity}`; | ||||||
|  |  | ||||||
|                     if (item && item.serial != null && row.quantity == 1) { |                     if (item && item.serial != null && row.quantity == 1) { | ||||||
|                         text = `{% trans "Serial Number" %}: ${item.serial}`; |                         text = `{% jstrans "Serial Number" %}: ${item.serial}`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return renderLink(text, `/stock/item/${row.item}/`); |                     return renderLink(text, `/stock/item/${row.item}/`); | ||||||
| @@ -1616,19 +1616,19 @@ function showAllocationSubTable(index, row, element, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'location', |                 field: 'location', | ||||||
|                 title: '{% trans "Location" %}', |                 title: '{% jstrans "Location" %}', | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
|  |  | ||||||
|                     if (row.shipment_date) { |                     if (row.shipment_date) { | ||||||
|                         return `<em>{% trans "Shipped to customer" %} - ${row.shipment_date}</em>`; |                         return `<em>{% jstrans "Shipped to customer" %} - ${row.shipment_date}</em>`; | ||||||
|                     } else if (row.location) { |                     } else if (row.location) { | ||||||
|                         // Location specified |                         // Location specified | ||||||
|                         return renderLink( |                         return renderLink( | ||||||
|                             row.location_detail.pathstring || '{% trans "Location" %}', |                             row.location_detail.pathstring || '{% jstrans "Location" %}', | ||||||
|                             `/stock/location/${row.location}/` |                             `/stock/location/${row.location}/` | ||||||
|                         ); |                         ); | ||||||
|                     } else { |                     } else { | ||||||
|                         return `<em>{% trans "Stock location not specified" %}</em>`; |                         return `<em>{% jstrans "Stock location not specified" %}</em>`; | ||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|             }, |             }, | ||||||
| @@ -1641,10 +1641,10 @@ function showAllocationSubTable(index, row, element, options) { | |||||||
|                     let pk = row.pk; |                     let pk = row.pk; | ||||||
|  |  | ||||||
|                     if (row.shipment_date) { |                     if (row.shipment_date) { | ||||||
|                         html += `<span class='badge bg-success badge-right'>{% trans "Shipped" %}</span>`; |                         html += `<span class='badge bg-success badge-right'>{% jstrans "Shipped" %}</span>`; | ||||||
|                     } else { |                     } else { | ||||||
|                         html += makeEditButton('button-allocation-edit', pk, '{% trans "Edit stock allocation" %}'); |                         html += makeEditButton('button-allocation-edit', pk, '{% jstrans "Edit stock allocation" %}'); | ||||||
|                         html += makeDeleteButton('button-allocation-delete', pk, '{% trans "Delete stock allocation" %}'); |                         html += makeDeleteButton('button-allocation-delete', pk, '{% jstrans "Delete stock allocation" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return wrapButtons(html); |                     return wrapButtons(html); | ||||||
| @@ -1689,13 +1689,13 @@ function showFulfilledSubTable(index, row, element, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'stock', |                 field: 'stock', | ||||||
|                 title: '{% trans "Stock Item" %}', |                 title: '{% jstrans "Stock Item" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     var text = ''; |                     var text = ''; | ||||||
|                     if (row.serial && row.quantity == 1) { |                     if (row.serial && row.quantity == 1) { | ||||||
|                         text = `{% trans "Serial Number" %}: ${row.serial}`; |                         text = `{% jstrans "Serial Number" %}: ${row.serial}`; | ||||||
|                     } else { |                     } else { | ||||||
|                         text = `{% trans "Quantity" %}: ${row.quantity}`; |                         text = `{% jstrans "Quantity" %}: ${row.quantity}`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return renderLink(text, `/stock/item/${row.pk}/`); |                     return renderLink(text, `/stock/item/${row.pk}/`); | ||||||
| @@ -1703,11 +1703,11 @@ function showFulfilledSubTable(index, row, element, options) { | |||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'location', |                 field: 'location', | ||||||
|                 title: '{% trans "Location" %}', |                 title: '{% jstrans "Location" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|                     if (row.customer) { |                     if (row.customer) { | ||||||
|                         return renderLink( |                         return renderLink( | ||||||
|                             '{% trans "Shipped to customer" %}', |                             '{% jstrans "Shipped to customer" %}', | ||||||
|                             `/company/${row.customer}/` |                             `/company/${row.customer}/` | ||||||
|                         ); |                         ); | ||||||
|                     } else if (row.location && row.location_detail) { |                     } else if (row.location && row.location_detail) { | ||||||
| @@ -1716,7 +1716,7 @@ function showFulfilledSubTable(index, row, element, options) { | |||||||
|                             `/stock/location/${row.location}`, |                             `/stock/location/${row.location}`, | ||||||
|                         ); |                         ); | ||||||
|                     } else { |                     } else { | ||||||
|                         return `<em>{% trans "Stock location not specified" %}</em>`; |                         return `<em>{% jstrans "Stock location not specified" %}</em>`; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -1793,7 +1793,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|             sortable: true, |             sortable: true, | ||||||
|             sortName: 'part_detail.name', |             sortName: 'part_detail.name', | ||||||
|             field: 'part', |             field: 'part', | ||||||
|             title: '{% trans "Part" %}', |             title: '{% jstrans "Part" %}', | ||||||
|             switchable: false, |             switchable: false, | ||||||
|             formatter: function(value, row, index, field) { |             formatter: function(value, row, index, field) { | ||||||
|                 if (row.part_detail) { |                 if (row.part_detail) { | ||||||
| @@ -1803,25 +1803,25 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             footerFormatter: function() { |             footerFormatter: function() { | ||||||
|                 return '{% trans "Total" %}'; |                 return '{% jstrans "Total" %}'; | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             sortable: false, |             sortable: false, | ||||||
|             field: 'part_detail.description', |             field: 'part_detail.description', | ||||||
|             title: '{% trans "Description" %}', |             title: '{% jstrans "Description" %}', | ||||||
|             switchable: true, |             switchable: true, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             field: 'reference', |             field: 'reference', | ||||||
|             title: '{% trans "Reference" %}', |             title: '{% jstrans "Reference" %}', | ||||||
|             switchable: true, |             switchable: true, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             field: 'quantity', |             field: 'quantity', | ||||||
|             title: '{% trans "Quantity" %}', |             title: '{% jstrans "Quantity" %}', | ||||||
|             footerFormatter: function(data) { |             footerFormatter: function(data) { | ||||||
|                 return data.map(function(row) { |                 return data.map(function(row) { | ||||||
|                     return +row['quantity']; |                     return +row['quantity']; | ||||||
| @@ -1834,7 +1834,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         { |         { | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             field: 'sale_price', |             field: 'sale_price', | ||||||
|             title: '{% trans "Unit Price" %}', |             title: '{% jstrans "Unit Price" %}', | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
|                 return formatCurrency(row.sale_price, { |                 return formatCurrency(row.sale_price, { | ||||||
|                     currency: row.sale_price_currency |                     currency: row.sale_price_currency | ||||||
| @@ -1844,7 +1844,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         { |         { | ||||||
|             field: 'total_price', |             field: 'total_price', | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             title: '{% trans "Total Price" %}', |             title: '{% jstrans "Total Price" %}', | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
|                 return formatCurrency(row.sale_price * row.quantity, { |                 return formatCurrency(row.sale_price * row.quantity, { | ||||||
|                     currency: row.sale_price_currency, |                     currency: row.sale_price_currency, | ||||||
| @@ -1864,7 +1864,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             field: 'target_date', |             field: 'target_date', | ||||||
|             title: '{% trans "Target Date" %}', |             title: '{% jstrans "Target Date" %}', | ||||||
|             sortable: true, |             sortable: true, | ||||||
|             switchable: true, |             switchable: true, | ||||||
|             formatter: function(value, row) { |             formatter: function(value, row) { | ||||||
| @@ -1872,7 +1872,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|                     var html = renderDate(row.target_date); |                     var html = renderDate(row.target_date); | ||||||
|  |  | ||||||
|                     if (row.overdue) { |                     if (row.overdue) { | ||||||
|                         html += makeIconBadge('fa-calendar-times', '{% trans "This line item is overdue" %}'); |                         html += makeIconBadge('fa-calendar-times', '{% jstrans "This line item is overdue" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     return html; |                     return html; | ||||||
| @@ -1890,7 +1890,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         columns.push( |         columns.push( | ||||||
|             { |             { | ||||||
|                 field: 'stock', |                 field: 'stock', | ||||||
|                 title: '{% trans "Available Stock" %}', |                 title: '{% jstrans "Available Stock" %}', | ||||||
|                 formatter: function(value, row) { |                 formatter: function(value, row) { | ||||||
|  |  | ||||||
|                     let available = row.available_stock + row.available_variant_stock; |                     let available = row.available_stock + row.available_variant_stock; | ||||||
| @@ -1904,17 +1904,17 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|                         html = renderLink(available, url); |                         html = renderLink(available, url); | ||||||
|  |  | ||||||
|                         if (row.available_variant_stock && row.available_variant_stock > 0) { |                         if (row.available_variant_stock && row.available_variant_stock > 0) { | ||||||
|                             html += makeIconBadge('fa-info-circle icon-blue', '{% trans "Includes variant stock" %}'); |                             html += makeIconBadge('fa-info-circle icon-blue', '{% jstrans "Includes variant stock" %}'); | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         html += `<span class='badge rounded-pill bg-danger'>{% trans "No Stock Available" %}</span>`; |                         html += `<span class='badge rounded-pill bg-danger'>{% jstrans "No Stock Available" %}</span>`; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (required > 0) { |                     if (required > 0) { | ||||||
|                         if (available >= required) { |                         if (available >= required) { | ||||||
|                             html += makeIconBadge('fa-check-circle icon-green', '{% trans "Sufficient stock available" %}'); |                             html += makeIconBadge('fa-check-circle icon-green', '{% jstrans "Sufficient stock available" %}'); | ||||||
|                         } else { |                         } else { | ||||||
|                             html += makeIconBadge('fa-times-circle icon-red', '{% trans "Insufficient stock available" %}'); |                             html += makeIconBadge('fa-times-circle icon-red', '{% jstrans "Insufficient stock available" %}'); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -1926,7 +1926,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         columns.push( |         columns.push( | ||||||
|             { |             { | ||||||
|                 field: 'allocated', |                 field: 'allocated', | ||||||
|                 title: '{% trans "Allocated" %}', |                 title: '{% jstrans "Allocated" %}', | ||||||
|                 switchable: false, |                 switchable: false, | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|                 formatter: function(value, row, index, field) { |                 formatter: function(value, row, index, field) { | ||||||
| @@ -1954,7 +1954,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|     columns.push({ |     columns.push({ | ||||||
|         field: 'shipped', |         field: 'shipped', | ||||||
|         title: '{% trans "Shipped" %}', |         title: '{% jstrans "Shipped" %}', | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         formatter: function(value, row) { |         formatter: function(value, row) { | ||||||
| @@ -1979,12 +1979,12 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|     columns.push({ |     columns.push({ | ||||||
|         field: 'notes', |         field: 'notes', | ||||||
|         title: '{% trans "Notes" %}', |         title: '{% jstrans "Notes" %}', | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     columns.push({ |     columns.push({ | ||||||
|         field: 'link', |         field: 'link', | ||||||
|         title: '{% trans "Link" %}', |         title: '{% jstrans "Link" %}', | ||||||
|         formatter: function(value) { |         formatter: function(value) { | ||||||
|             if (value) { |             if (value) { | ||||||
|                 return renderLink(value, value); |                 return renderLink(value, value); | ||||||
| @@ -2005,37 +2005,37 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|                 if (options.allow_edit && (row.shipped < row.quantity)) { |                 if (options.allow_edit && (row.shipped < row.quantity)) { | ||||||
|                     if (part.trackable) { |                     if (part.trackable) { | ||||||
|                         buttons += makeIconButton('fa-hashtag icon-green', 'button-add-by-sn', pk, '{% trans "Allocate serial numbers" %}'); |                         buttons += makeIconButton('fa-hashtag icon-green', 'button-add-by-sn', pk, '{% jstrans "Allocate serial numbers" %}'); | ||||||
|                     } |                     } | ||||||
|                     buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-add', pk, '{% trans "Allocate stock" %}'); |                     buttons += makeIconButton('fa-sign-in-alt icon-green', 'button-add', pk, '{% jstrans "Allocate stock" %}'); | ||||||
|                     if (part.purchaseable) { |                     if (part.purchaseable) { | ||||||
|                         buttons += makeIconButton('fa-shopping-cart', 'button-buy', row.part, '{% trans "Purchase stock" %}'); |                         buttons += makeIconButton('fa-shopping-cart', 'button-buy', row.part, '{% jstrans "Purchase stock" %}'); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (part.assembly) { |                     if (part.assembly) { | ||||||
|                         buttons += makeIconButton('fa-tools', 'button-build', row.part, '{% trans "Build stock" %}'); |                         buttons += makeIconButton('fa-tools', 'button-build', row.part, '{% jstrans "Build stock" %}'); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             buttons += makeIconButton('fa-dollar-sign icon-green', 'button-price', pk, '{% trans "Calculate price" %}'); |             buttons += makeIconButton('fa-dollar-sign icon-green', 'button-price', pk, '{% jstrans "Calculate price" %}'); | ||||||
|  |  | ||||||
|             if (options.allow_edit) { |             if (options.allow_edit) { | ||||||
|                 buttons += makeCopyButton('button-duplicate', pk, '{% trans "Duplicate line item" %}'); |                 buttons += makeCopyButton('button-duplicate', pk, '{% jstrans "Duplicate line item" %}'); | ||||||
|                 buttons += makeEditButton('button-edit', pk, '{% trans "Edit line item" %}'); |                 buttons += makeEditButton('button-edit', pk, '{% jstrans "Edit line item" %}'); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (options.allow_delete) { |             if (options.allow_delete) { | ||||||
|                 var delete_disabled = false; |                 var delete_disabled = false; | ||||||
|  |  | ||||||
|                 var title = '{% trans "Delete line item" %}'; |                 var title = '{% jstrans "Delete line item" %}'; | ||||||
|  |  | ||||||
|                 if (row.shipped) { |                 if (row.shipped) { | ||||||
|                     delete_disabled = true; |                     delete_disabled = true; | ||||||
|                     title = '{% trans "Cannot be deleted as items have been shipped" %}'; |                     title = '{% jstrans "Cannot be deleted as items have been shipped" %}'; | ||||||
|                 } else if (row.allocated) { |                 } else if (row.allocated) { | ||||||
|                     delete_disabled = true; |                     delete_disabled = true; | ||||||
|                     title = '{% trans "Cannot be deleted as items have been allocated" %}'; |                     title = '{% jstrans "Cannot be deleted as items have been allocated" %}'; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // Prevent deletion of the line item if items have been allocated or shipped! |                 // Prevent deletion of the line item if items have been allocated or shipped! | ||||||
| @@ -2067,7 +2067,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|                         method: 'POST', |                         method: 'POST', | ||||||
|                         fields: fields, |                         fields: fields, | ||||||
|                         data: data, |                         data: data, | ||||||
|                         title: '{% trans "Duplicate Line Item" %}', |                         title: '{% jstrans "Duplicate Line Item" %}', | ||||||
|                         refreshTable: table, |                         refreshTable: table, | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
| @@ -2080,7 +2080,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-so-line-list" %}${pk}/`, { |             constructForm(`{% url "api-so-line-list" %}${pk}/`, { | ||||||
|                 fields: soLineItemFields(), |                 fields: soLineItemFields(), | ||||||
|                 title: '{% trans "Edit Line Item" %}', |                 title: '{% jstrans "Edit Line Item" %}', | ||||||
|                 onSuccess: reloadTable, |                 onSuccess: reloadTable, | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @@ -2091,7 +2091,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|             constructForm(`{% url "api-so-line-list" %}${pk}/`, { |             constructForm(`{% url "api-so-line-list" %}${pk}/`, { | ||||||
|                 method: 'DELETE', |                 method: 'DELETE', | ||||||
|                 title: '{% trans "Delete Line Item" %}', |                 title: '{% jstrans "Delete Line Item" %}', | ||||||
|                 onSuccess: reloadTable, |                 onSuccess: reloadTable, | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @@ -2106,7 +2106,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|  |  | ||||||
|                         constructForm(`{% url "api-so-list" %}${options.order}/allocate-serials/`, { |                         constructForm(`{% url "api-so-list" %}${options.order}/allocate-serials/`, { | ||||||
|                             method: 'POST', |                             method: 'POST', | ||||||
|                             title: '{% trans "Allocate Serial Numbers" %}', |                             title: '{% jstrans "Allocate Serial Numbers" %}', | ||||||
|                             fields: { |                             fields: { | ||||||
|                                 line_item: { |                                 line_item: { | ||||||
|                                     value: pk, |                                     value: pk, | ||||||
| @@ -2205,7 +2205,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|             launchModalForm( |             launchModalForm( | ||||||
|                 '{% url "line-pricing" %}', |                 '{% url "line-pricing" %}', | ||||||
|                 { |                 { | ||||||
|                     submit_text: '{% trans "Calculate price" %}', |                     submit_text: '{% jstrans "Calculate price" %}', | ||||||
|                     data: { |                     data: { | ||||||
|                         line_item: pk, |                         line_item: pk, | ||||||
|                         quantity: row.quantity, |                         quantity: row.quantity, | ||||||
| @@ -2213,7 +2213,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|                     buttons: [ |                     buttons: [ | ||||||
|                         { |                         { | ||||||
|                             name: 'update_price', |                             name: 'update_price', | ||||||
|                             title: '{% trans "Update Unit Price" %}' |                             title: '{% jstrans "Update Unit Price" %}' | ||||||
|                         }, |                         }, | ||||||
|                     ], |                     ], | ||||||
|                     success: reloadTable, |                     success: reloadTable, | ||||||
| @@ -2227,7 +2227,7 @@ function loadSalesOrderLineItemTable(table, options={}) { | |||||||
|         name: 'salesorderlineitems', |         name: 'salesorderlineitems', | ||||||
|         sidePagination: 'client', |         sidePagination: 'client', | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No matching line items" %}'; |             return '{% jstrans "No matching line items" %}'; | ||||||
|         }, |         }, | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
|         original: options.params, |         original: options.params, | ||||||
|   | |||||||
| @@ -127,7 +127,7 @@ function updateSearch() { | |||||||
|             filters.active = true; |             filters.active = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addSearchQuery('part', '{% trans "Parts" %}', filters); |         addSearchQuery('part', '{% jstrans "Parts" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('part') && checkPermission('purchase_order')) { |     if (checkPermission('part') && checkPermission('purchase_order')) { | ||||||
| @@ -144,18 +144,18 @@ function updateSearch() { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (user_settings.SEARCH_PREVIEW_SHOW_SUPPLIER_PARTS) { |         if (user_settings.SEARCH_PREVIEW_SHOW_SUPPLIER_PARTS) { | ||||||
|             addSearchQuery('supplierpart', '{% trans "Supplier Parts" %}', filters); |             addSearchQuery('supplierpart', '{% jstrans "Supplier Parts" %}', filters); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (user_settings.SEARCH_PREVIEW_SHOW_MANUFACTURER_PARTS) { |         if (user_settings.SEARCH_PREVIEW_SHOW_MANUFACTURER_PARTS) { | ||||||
|             addSearchQuery('manufacturerpart', '{% trans "Manufacturer Parts" %}', filters); |             addSearchQuery('manufacturerpart', '{% jstrans "Manufacturer Parts" %}', filters); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('part_category') && user_settings.SEARCH_PREVIEW_SHOW_CATEGORIES) { |     if (checkPermission('part_category') && user_settings.SEARCH_PREVIEW_SHOW_CATEGORIES) { | ||||||
|         let filters = {}; |         let filters = {}; | ||||||
|  |  | ||||||
|         addSearchQuery('partcategory', '{% trans "Part Categories" %}', filters); |         addSearchQuery('partcategory', '{% jstrans "Part Categories" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('stock') && user_settings.SEARCH_PREVIEW_SHOW_STOCK) { |     if (checkPermission('stock') && user_settings.SEARCH_PREVIEW_SHOW_STOCK) { | ||||||
| @@ -169,13 +169,13 @@ function updateSearch() { | |||||||
|             filters.in_stock = true; |             filters.in_stock = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addSearchQuery('stockitem', '{% trans "Stock Items" %}', filters); |         addSearchQuery('stockitem', '{% jstrans "Stock Items" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('stock_location') && user_settings.SEARCH_PREVIEW_SHOW_LOCATIONS) { |     if (checkPermission('stock_location') && user_settings.SEARCH_PREVIEW_SHOW_LOCATIONS) { | ||||||
|         let filters = {}; |         let filters = {}; | ||||||
|  |  | ||||||
|         addSearchQuery('stocklocation', '{% trans "Stock Locations" %}', filters); |         addSearchQuery('stocklocation', '{% jstrans "Stock Locations" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('build') && user_settings.SEARCH_PREVIEW_SHOW_BUILD_ORDERS) { |     if (checkPermission('build') && user_settings.SEARCH_PREVIEW_SHOW_BUILD_ORDERS) { | ||||||
| @@ -183,13 +183,13 @@ function updateSearch() { | |||||||
|             part_detail: true |             part_detail: true | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         addSearchQuery('build', '{% trans "Build Orders" %}', filters); |         addSearchQuery('build', '{% jstrans "Build Orders" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ((checkPermission('sales_order') || checkPermission('purchase_order')) && user_settings.SEARCH_PREVIEW_SHOW_COMPANIES) { |     if ((checkPermission('sales_order') || checkPermission('purchase_order')) && user_settings.SEARCH_PREVIEW_SHOW_COMPANIES) { | ||||||
|         let filters = {}; |         let filters = {}; | ||||||
|  |  | ||||||
|         addSearchQuery('company', '{% trans "Companies" %}', filters); |         addSearchQuery('company', '{% jstrans "Companies" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('purchase_order') && user_settings.SEARCH_PREVIEW_SHOW_PURCHASE_ORDERS) { |     if (checkPermission('purchase_order') && user_settings.SEARCH_PREVIEW_SHOW_PURCHASE_ORDERS) { | ||||||
| @@ -202,7 +202,7 @@ function updateSearch() { | |||||||
|             filters.outstanding = true; |             filters.outstanding = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addSearchQuery('purchaseorder', '{% trans "Purchase Orders" %}', filters); |         addSearchQuery('purchaseorder', '{% jstrans "Purchase Orders" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('sales_order') && user_settings.SEARCH_PREVIEW_SHOW_SALES_ORDERS) { |     if (checkPermission('sales_order') && user_settings.SEARCH_PREVIEW_SHOW_SALES_ORDERS) { | ||||||
| @@ -216,7 +216,7 @@ function updateSearch() { | |||||||
|             filters.outstanding = true; |             filters.outstanding = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addSearchQuery('salesorder', '{% trans "Sales Orders" %}', filters); |         addSearchQuery('salesorder', '{% jstrans "Sales Orders" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (checkPermission('return_order') && user_settings.SEARCH_PREVIEW_SHOW_RETURN_ORDERS) { |     if (checkPermission('return_order') && user_settings.SEARCH_PREVIEW_SHOW_RETURN_ORDERS) { | ||||||
| @@ -229,14 +229,14 @@ function updateSearch() { | |||||||
|             filters.outstanding = true; |             filters.outstanding = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         addSearchQuery('returnorder', '{% trans "Return Orders" %}', filters); |         addSearchQuery('returnorder', '{% jstrans "Return Orders" %}', filters); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     let ctx = $('#offcanvas-search').find('#search-context'); |     let ctx = $('#offcanvas-search').find('#search-context'); | ||||||
|  |  | ||||||
|     ctx.html(` |     ctx.html(` | ||||||
|     <div class='alert alert-block alert-secondary'> |     <div class='alert alert-block alert-secondary'> | ||||||
|         <span class='fas fa-spinner fa-spin'></span> <em>{% trans "Searching" %}</em> |         <span class='fas fa-spinner fa-spin'></span> <em>{% jstrans "Searching" %}</em> | ||||||
|     </div> |     </div> | ||||||
|     `); |     `); | ||||||
|  |  | ||||||
| @@ -267,7 +267,7 @@ function updateSearch() { | |||||||
|                 } else { |                 } else { | ||||||
|                     ctx.html(` |                     ctx.html(` | ||||||
|                     <div class='alert alert-block alert-warning'> |                     <div class='alert alert-block alert-warning'> | ||||||
|                         <span class='fas fa-exclamation-circle'></span> <em>{% trans "No results" %}</em> |                         <span class='fas fa-exclamation-circle'></span> <em>{% jstrans "No results" %}</em> | ||||||
|                     </div> |                     </div> | ||||||
|                     `); |                     `); | ||||||
|                 } |                 } | ||||||
| @@ -289,7 +289,7 @@ function clearSearchResults() { | |||||||
|  |  | ||||||
|     panel.find('#search-context').html(` |     panel.find('#search-context').html(` | ||||||
|     <div class='alert alert-block alert-info'> |     <div class='alert alert-block alert-info'> | ||||||
|         <span class='fas fa-search'></span> <em>{% trans "Enter search query" %}</em> |         <span class='fas fa-search'></span> <em>{% jstrans "Enter search query" %}</em> | ||||||
|     </div> |     </div> | ||||||
|     `); |     `); | ||||||
|  |  | ||||||
| @@ -339,7 +339,7 @@ function addSearchResults(results, resultType, resultCount) { | |||||||
|     let renderer = resultType.renderer; |     let renderer = resultType.renderer; | ||||||
|     let renderParams = resultType.renderParams; |     let renderParams = resultType.renderParams; | ||||||
|  |  | ||||||
|     let resultText = resultCount == 1 ? '{% trans "result" %}' : '{% trans "results" %}'; |     let resultText = resultCount == 1 ? '{% jstrans "result" %}' : '{% jstrans "results" %}'; | ||||||
|  |  | ||||||
|     // Add the result group to the panel |     // Add the result group to the panel | ||||||
|     panel.find('#search-results').append(` |     panel.find('#search-results').append(` | ||||||
| @@ -349,10 +349,10 @@ function addSearchResults(results, resultType, resultCount) { | |||||||
|                 <h5>${title}</h5><span class='float-right'><em><small> - ${resultCount} ${resultText}</small></em></span> |                 <h5>${title}</h5><span class='float-right'><em><small> - ${resultCount} ${resultText}</small></em></span> | ||||||
|                 <span class='flex' style='flex-grow: 1;'></span> |                 <span class='flex' style='flex-grow: 1;'></span> | ||||||
|                 <div class='search-result-group-buttons btn-group float-right' role='group'> |                 <div class='search-result-group-buttons btn-group float-right' role='group'> | ||||||
|                     <button class='btn btn-outline-secondary' id='hide-results-${key}' title='{% trans "Minimize results" %}'> |                     <button class='btn btn-outline-secondary' id='hide-results-${key}' title='{% jstrans "Minimize results" %}'> | ||||||
|                         <span class='fas fa-chevron-up'></span> |                         <span class='fas fa-chevron-up'></span> | ||||||
|                     </button> |                     </button> | ||||||
|                     <button class='btn btn-outline-secondary' id='remove-results-${key}' title='{% trans "Remove results" %}'> |                     <button class='btn btn-outline-secondary' id='remove-results-${key}' title='{% jstrans "Remove results" %}'> | ||||||
|                         <span class='fas fa-times icon-red'></span> |                         <span class='fas fa-times icon-red'></span> | ||||||
|                     </button> |                     </button> | ||||||
|                 </div> |                 </div> | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -21,7 +21,7 @@ | |||||||
| // Construct a dynamic API filter for the "issued by" field | // Construct a dynamic API filter for the "issued by" field | ||||||
| function constructIssuedByFilter() { | function constructIssuedByFilter() { | ||||||
|     return { |     return { | ||||||
|         title: '{% trans "Issued By" %}', |         title: '{% jstrans "Issued By" %}', | ||||||
|         options: function() { |         options: function() { | ||||||
|             let users = {}; |             let users = {}; | ||||||
|  |  | ||||||
| @@ -45,7 +45,7 @@ function constructIssuedByFilter() { | |||||||
| // Construct a dynamic API filter for the "project" field | // Construct a dynamic API filter for the "project" field | ||||||
| function constructProjectCodeFilter() { | function constructProjectCodeFilter() { | ||||||
|     return { |     return { | ||||||
|         title: '{% trans "Project Code" %}', |         title: '{% jstrans "Project Code" %}', | ||||||
|         options: function() { |         options: function() { | ||||||
|             let project_codes = {}; |             let project_codes = {}; | ||||||
|  |  | ||||||
| @@ -71,7 +71,7 @@ function constructProjectCodeFilter() { | |||||||
| function constructHasProjectCodeFilter() { | function constructHasProjectCodeFilter() { | ||||||
|     return { |     return { | ||||||
|         type: 'bool', |         type: 'bool', | ||||||
|         title: '{% trans "Has project code" %}', |         title: '{% jstrans "Has project code" %}', | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -86,20 +86,20 @@ function getAttachmentFilters() { | |||||||
| function getReturnOrderFilters() { | function getReturnOrderFilters() { | ||||||
|     var filters = { |     var filters = { | ||||||
|         status: { |         status: { | ||||||
|             title: '{% trans "Order status" %}', |             title: '{% jstrans "Order status" %}', | ||||||
|             options: returnOrderCodes |             options: returnOrderCodes | ||||||
|         }, |         }, | ||||||
|         outstanding: { |         outstanding: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Outstanding" %}', |             title: '{% jstrans "Outstanding" %}', | ||||||
|         }, |         }, | ||||||
|         overdue: { |         overdue: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Overdue" %}', |             title: '{% jstrans "Overdue" %}', | ||||||
|         }, |         }, | ||||||
|         assigned_to_me: { |         assigned_to_me: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assigned to me" %}', |             title: '{% jstrans "Assigned to me" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -117,10 +117,10 @@ function getReturnOrderLineItemFilters() { | |||||||
|     return { |     return { | ||||||
|         received: { |         received: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Received" %}', |             title: '{% jstrans "Received" %}', | ||||||
|         }, |         }, | ||||||
|         outcome: { |         outcome: { | ||||||
|             title: '{% trans "Outcome" %}', |             title: '{% jstrans "Outcome" %}', | ||||||
|             options: returnOrderLineItemCodes, |             options: returnOrderLineItemCodes, | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| @@ -132,19 +132,19 @@ function getVariantsTableFilters() { | |||||||
|     return { |     return { | ||||||
|         active: { |         active: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active" %}', |             title: '{% jstrans "Active" %}', | ||||||
|         }, |         }, | ||||||
|         template: { |         template: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Template" %}', |             title: '{% jstrans "Template" %}', | ||||||
|         }, |         }, | ||||||
|         virtual: { |         virtual: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Virtual" %}', |             title: '{% jstrans "Virtual" %}', | ||||||
|         }, |         }, | ||||||
|         trackable: { |         trackable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Trackable" %}', |             title: '{% jstrans "Trackable" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -155,43 +155,43 @@ function getBOMTableFilters() { | |||||||
|     return { |     return { | ||||||
|         sub_part_trackable: { |         sub_part_trackable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Trackable Part" %}', |             title: '{% jstrans "Trackable Part" %}', | ||||||
|         }, |         }, | ||||||
|         sub_part_assembly: { |         sub_part_assembly: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assembled Part" %}', |             title: '{% jstrans "Assembled Part" %}', | ||||||
|         }, |         }, | ||||||
|         available_stock: { |         available_stock: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has Available Stock" %}', |             title: '{% jstrans "Has Available Stock" %}', | ||||||
|         }, |         }, | ||||||
|         on_order: { |         on_order: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "On Order" %}', |             title: '{% jstrans "On Order" %}', | ||||||
|         }, |         }, | ||||||
|         validated: { |         validated: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Validated" %}', |             title: '{% jstrans "Validated" %}', | ||||||
|         }, |         }, | ||||||
|         inherited: { |         inherited: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Gets inherited" %}', |             title: '{% jstrans "Gets inherited" %}', | ||||||
|         }, |         }, | ||||||
|         allow_variants: { |         allow_variants: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Allow Variant Stock" %}', |             title: '{% jstrans "Allow Variant Stock" %}', | ||||||
|         }, |         }, | ||||||
|         optional: { |         optional: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Optional" %}', |             title: '{% jstrans "Optional" %}', | ||||||
|         }, |         }, | ||||||
|         consumable: { |         consumable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Consumable" %}', |             title: '{% jstrans "Consumable" %}', | ||||||
|         }, |         }, | ||||||
|         has_pricing: { |         has_pricing: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has Pricing" %}', |             title: '{% jstrans "Has Pricing" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -208,19 +208,19 @@ function getUsedInTableFilters() { | |||||||
|     return { |     return { | ||||||
|         'inherited': { |         'inherited': { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Gets inherited" %}', |             title: '{% jstrans "Gets inherited" %}', | ||||||
|         }, |         }, | ||||||
|         'optional': { |         'optional': { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Optional" %}', |             title: '{% jstrans "Optional" %}', | ||||||
|         }, |         }, | ||||||
|         'part_active': { |         'part_active': { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active" %}', |             title: '{% jstrans "Active" %}', | ||||||
|         }, |         }, | ||||||
|         'part_trackable': { |         'part_trackable': { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Trackable" %}', |             title: '{% jstrans "Trackable" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -231,19 +231,19 @@ function getStockLocationFilters() { | |||||||
|     return { |     return { | ||||||
|         cascade: { |         cascade: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Include sublocations" %}', |             title: '{% jstrans "Include sublocations" %}', | ||||||
|             description: '{% trans "Include locations" %}', |             description: '{% jstrans "Include locations" %}', | ||||||
|         }, |         }, | ||||||
|         structural: { |         structural: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Structural" %}', |             title: '{% jstrans "Structural" %}', | ||||||
|         }, |         }, | ||||||
|         external: { |         external: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "External" %}', |             title: '{% jstrans "External" %}', | ||||||
|         }, |         }, | ||||||
|         location_type: { |         location_type: { | ||||||
|             title: '{% trans "Location type" %}', |             title: '{% jstrans "Location type" %}', | ||||||
|             options: function() { |             options: function() { | ||||||
|                 const locationTypes = {}; |                 const locationTypes = {}; | ||||||
|  |  | ||||||
| @@ -264,7 +264,7 @@ function getStockLocationFilters() { | |||||||
|         }, |         }, | ||||||
|         has_location_type: { |         has_location_type: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has location type" %}' |             title: '{% jstrans "Has location type" %}' | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -275,16 +275,16 @@ function getPartCategoryFilters() { | |||||||
|     return { |     return { | ||||||
|         cascade: { |         cascade: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Include subcategories" %}', |             title: '{% jstrans "Include subcategories" %}', | ||||||
|             description: '{% trans "Include subcategories" %}', |             description: '{% jstrans "Include subcategories" %}', | ||||||
|         }, |         }, | ||||||
|         structural: { |         structural: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Structural" %}', |             title: '{% jstrans "Structural" %}', | ||||||
|         }, |         }, | ||||||
|         starred: { |         starred: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Subscribed" %}', |             title: '{% jstrans "Subscribed" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -295,23 +295,23 @@ function getCustomerStockFilters() { | |||||||
|     return { |     return { | ||||||
|         serialized: { |         serialized: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Is Serialized" %}', |             title: '{% jstrans "Is Serialized" %}', | ||||||
|         }, |         }, | ||||||
|         serial_gte: { |         serial_gte: { | ||||||
|             title: '{% trans "Serial number GTE" %}', |             title: '{% jstrans "Serial number GTE" %}', | ||||||
|             description: '{% trans "Serial number greater than or equal to" %}', |             description: '{% jstrans "Serial number greater than or equal to" %}', | ||||||
|         }, |         }, | ||||||
|         serial_lte: { |         serial_lte: { | ||||||
|             title: '{% trans "Serial number LTE" %}', |             title: '{% jstrans "Serial number LTE" %}', | ||||||
|             description: '{% trans "Serial number less than or equal to" %}', |             description: '{% jstrans "Serial number less than or equal to" %}', | ||||||
|         }, |         }, | ||||||
|         serial: { |         serial: { | ||||||
|             title: '{% trans "Serial number" %}', |             title: '{% jstrans "Serial number" %}', | ||||||
|             description: '{% trans "Serial number" %}', |             description: '{% jstrans "Serial number" %}', | ||||||
|         }, |         }, | ||||||
|         batch: { |         batch: { | ||||||
|             title: '{% trans "Batch" %}', |             title: '{% jstrans "Batch" %}', | ||||||
|             description: '{% trans "Batch code" %}', |             description: '{% jstrans "Batch code" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -322,109 +322,109 @@ function getStockTableFilters() { | |||||||
|     var filters = { |     var filters = { | ||||||
|         active: { |         active: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active parts" %}', |             title: '{% jstrans "Active parts" %}', | ||||||
|             description: '{% trans "Show stock for active parts" %}', |             description: '{% jstrans "Show stock for active parts" %}', | ||||||
|         }, |         }, | ||||||
|         assembly: { |         assembly: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assembly" %}', |             title: '{% jstrans "Assembly" %}', | ||||||
|             description: '{% trans "Part is an assembly" %}', |             description: '{% jstrans "Part is an assembly" %}', | ||||||
|         }, |         }, | ||||||
|         allocated: { |         allocated: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Is allocated" %}', |             title: '{% jstrans "Is allocated" %}', | ||||||
|             description: '{% trans "Item has been allocated" %}', |             description: '{% jstrans "Item has been allocated" %}', | ||||||
|         }, |         }, | ||||||
|         available: { |         available: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Available" %}', |             title: '{% jstrans "Available" %}', | ||||||
|             description: '{% trans "Stock is available for use" %}', |             description: '{% jstrans "Stock is available for use" %}', | ||||||
|         }, |         }, | ||||||
|         cascade: { |         cascade: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Include sublocations" %}', |             title: '{% jstrans "Include sublocations" %}', | ||||||
|             description: '{% trans "Include stock in sublocations" %}', |             description: '{% jstrans "Include stock in sublocations" %}', | ||||||
|         }, |         }, | ||||||
|         depleted: { |         depleted: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Depleted" %}', |             title: '{% jstrans "Depleted" %}', | ||||||
|             description: '{% trans "Show stock items which are depleted" %}', |             description: '{% jstrans "Show stock items which are depleted" %}', | ||||||
|         }, |         }, | ||||||
|         in_stock: { |         in_stock: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "In Stock" %}', |             title: '{% jstrans "In Stock" %}', | ||||||
|             description: '{% trans "Show items which are in stock" %}', |             description: '{% jstrans "Show items which are in stock" %}', | ||||||
|         }, |         }, | ||||||
|         is_building: { |         is_building: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "In Production" %}', |             title: '{% jstrans "In Production" %}', | ||||||
|             description: '{% trans "Show items which are in production" %}', |             description: '{% jstrans "Show items which are in production" %}', | ||||||
|         }, |         }, | ||||||
|         include_variants: { |         include_variants: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Include Variants" %}', |             title: '{% jstrans "Include Variants" %}', | ||||||
|             description: '{% trans "Include stock items for variant parts" %}', |             description: '{% jstrans "Include stock items for variant parts" %}', | ||||||
|         }, |         }, | ||||||
|         installed: { |         installed: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Installed" %}', |             title: '{% jstrans "Installed" %}', | ||||||
|             description: '{% trans "Show stock items which are installed in another item" %}', |             description: '{% jstrans "Show stock items which are installed in another item" %}', | ||||||
|         }, |         }, | ||||||
|         sent_to_customer: { |         sent_to_customer: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Sent to customer" %}', |             title: '{% jstrans "Sent to customer" %}', | ||||||
|             description: '{% trans "Show items which have been assigned to a customer" %}', |             description: '{% jstrans "Show items which have been assigned to a customer" %}', | ||||||
|         }, |         }, | ||||||
|         serialized: { |         serialized: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Is Serialized" %}', |             title: '{% jstrans "Is Serialized" %}', | ||||||
|         }, |         }, | ||||||
|         serial: { |         serial: { | ||||||
|             title: '{% trans "Serial number" %}', |             title: '{% jstrans "Serial number" %}', | ||||||
|             description: '{% trans "Serial number" %}', |             description: '{% jstrans "Serial number" %}', | ||||||
|         }, |         }, | ||||||
|         serial_gte: { |         serial_gte: { | ||||||
|             title: '{% trans "Serial number GTE" %}', |             title: '{% jstrans "Serial number GTE" %}', | ||||||
|             description: '{% trans "Serial number greater than or equal to" %}', |             description: '{% jstrans "Serial number greater than or equal to" %}', | ||||||
|         }, |         }, | ||||||
|         serial_lte: { |         serial_lte: { | ||||||
|             title: '{% trans "Serial number LTE" %}', |             title: '{% jstrans "Serial number LTE" %}', | ||||||
|             description: '{% trans "Serial number less than or equal to" %}', |             description: '{% jstrans "Serial number less than or equal to" %}', | ||||||
|         }, |         }, | ||||||
|         status: { |         status: { | ||||||
|             options: stockCodes, |             options: stockCodes, | ||||||
|             title: '{% trans "Stock status" %}', |             title: '{% jstrans "Stock status" %}', | ||||||
|             description: '{% trans "Stock status" %}', |             description: '{% jstrans "Stock status" %}', | ||||||
|         }, |         }, | ||||||
|         has_batch: { |         has_batch: { | ||||||
|             title: '{% trans "Has batch code" %}', |             title: '{% jstrans "Has batch code" %}', | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|         }, |         }, | ||||||
|         batch: { |         batch: { | ||||||
|             title: '{% trans "Batch" %}', |             title: '{% jstrans "Batch" %}', | ||||||
|             description: '{% trans "Batch code" %}', |             description: '{% jstrans "Batch code" %}', | ||||||
|         }, |         }, | ||||||
|         tracked: { |         tracked: { | ||||||
|             title: '{% trans "Tracked" %}', |             title: '{% jstrans "Tracked" %}', | ||||||
|             description: '{% trans "Stock item is tracked by either batch code or serial number" %}', |             description: '{% jstrans "Stock item is tracked by either batch code or serial number" %}', | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|         }, |         }, | ||||||
|         has_purchase_price: { |         has_purchase_price: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has purchase price" %}', |             title: '{% jstrans "Has purchase price" %}', | ||||||
|             description: '{% trans "Show stock items which have a purchase price set" %}', |             description: '{% jstrans "Show stock items which have a purchase price set" %}', | ||||||
|         }, |         }, | ||||||
|         expiry_date_lte: { |         expiry_date_lte: { | ||||||
|             type: 'date', |             type: 'date', | ||||||
|             title: '{% trans "Expiry Date before" %}', |             title: '{% jstrans "Expiry Date before" %}', | ||||||
|         }, |         }, | ||||||
|         expiry_date_gte: { |         expiry_date_gte: { | ||||||
|             type: 'date', |             type: 'date', | ||||||
|             title: '{% trans "Expiry Date after" %}', |             title: '{% jstrans "Expiry Date after" %}', | ||||||
|         }, |         }, | ||||||
|         external: { |         external: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "External Location" %}', |             title: '{% jstrans "External Location" %}', | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -432,14 +432,14 @@ function getStockTableFilters() { | |||||||
|     if (global_settings.STOCK_ENABLE_EXPIRY) { |     if (global_settings.STOCK_ENABLE_EXPIRY) { | ||||||
|         filters.expired = { |         filters.expired = { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Expired" %}', |             title: '{% jstrans "Expired" %}', | ||||||
|             description: '{% trans "Show stock items which have expired" %}', |             description: '{% jstrans "Show stock items which have expired" %}', | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         filters.stale = { |         filters.stale = { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Stale" %}', |             title: '{% jstrans "Stale" %}', | ||||||
|             description: '{% trans "Show stock which is close to expiring" %}', |             description: '{% jstrans "Show stock which is close to expiring" %}', | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -453,11 +453,11 @@ function getStockTestTableFilters() { | |||||||
|     return { |     return { | ||||||
|         result: { |         result: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Test Passed" %}', |             title: '{% jstrans "Test Passed" %}', | ||||||
|         }, |         }, | ||||||
|         include_installed: { |         include_installed: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Include Installed Items" %}', |             title: '{% jstrans "Include Installed Items" %}', | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -474,7 +474,7 @@ function getPartTestTemplateFilters() { | |||||||
|     return { |     return { | ||||||
|         required: { |         required: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Required" %}', |             title: '{% jstrans "Required" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -485,19 +485,19 @@ function getPluginTableFilters() { | |||||||
|     return { |     return { | ||||||
|         active: { |         active: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active" %}', |             title: '{% jstrans "Active" %}', | ||||||
|         }, |         }, | ||||||
|         builtin: { |         builtin: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Builtin" %}', |             title: '{% jstrans "Builtin" %}', | ||||||
|         }, |         }, | ||||||
|         sample: { |         sample: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Sample" %}', |             title: '{% jstrans "Sample" %}', | ||||||
|         }, |         }, | ||||||
|         installed: { |         installed: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Installed" %}' |             title: '{% jstrans "Installed" %}' | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -508,23 +508,23 @@ function getBuildTableFilters() { | |||||||
|  |  | ||||||
|     let filters = { |     let filters = { | ||||||
|         status: { |         status: { | ||||||
|             title: '{% trans "Build status" %}', |             title: '{% jstrans "Build status" %}', | ||||||
|             options: buildCodes, |             options: buildCodes, | ||||||
|         }, |         }, | ||||||
|         active: { |         active: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active" %}', |             title: '{% jstrans "Active" %}', | ||||||
|         }, |         }, | ||||||
|         overdue: { |         overdue: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Overdue" %}', |             title: '{% jstrans "Overdue" %}', | ||||||
|         }, |         }, | ||||||
|         assigned_to_me: { |         assigned_to_me: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assigned to me" %}', |             title: '{% jstrans "Assigned to me" %}', | ||||||
|         }, |         }, | ||||||
|         assigned_to: { |         assigned_to: { | ||||||
|             title: '{% trans "Responsible" %}', |             title: '{% jstrans "Responsible" %}', | ||||||
|             options: function() { |             options: function() { | ||||||
|                 var ownersList = {}; |                 var ownersList = {}; | ||||||
|                 inventreeGet('{% url "api-owner-list" %}', {}, { |                 inventreeGet('{% url "api-owner-list" %}', {}, { | ||||||
| @@ -564,23 +564,23 @@ function getBuildLineTableFilters() { | |||||||
|     return { |     return { | ||||||
|         allocated: { |         allocated: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Allocated" %}', |             title: '{% jstrans "Allocated" %}', | ||||||
|         }, |         }, | ||||||
|         available: { |         available: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Available" %}', |             title: '{% jstrans "Available" %}', | ||||||
|         }, |         }, | ||||||
|         tracked: { |         tracked: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Tracked" %}', |             title: '{% jstrans "Tracked" %}', | ||||||
|         }, |         }, | ||||||
|         consumable: { |         consumable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Consumable" %}', |             title: '{% jstrans "Consumable" %}', | ||||||
|         }, |         }, | ||||||
|         optional: { |         optional: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Optional" %}', |             title: '{% jstrans "Optional" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -591,14 +591,14 @@ function getPurchaseOrderLineItemFilters() { | |||||||
|     return { |     return { | ||||||
|         pending: { |         pending: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Pending" %}', |             title: '{% jstrans "Pending" %}', | ||||||
|         }, |         }, | ||||||
|         received: { |         received: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Received" %}', |             title: '{% jstrans "Received" %}', | ||||||
|         }, |         }, | ||||||
|         order_status: { |         order_status: { | ||||||
|             title: '{% trans "Order status" %}', |             title: '{% jstrans "Order status" %}', | ||||||
|             options: purchaseOrderCodes, |             options: purchaseOrderCodes, | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| @@ -610,20 +610,20 @@ function getPurchaseOrderFilters() { | |||||||
|  |  | ||||||
|     var filters = { |     var filters = { | ||||||
|         status: { |         status: { | ||||||
|             title: '{% trans "Order status" %}', |             title: '{% jstrans "Order status" %}', | ||||||
|             options: purchaseOrderCodes, |             options: purchaseOrderCodes, | ||||||
|         }, |         }, | ||||||
|         outstanding: { |         outstanding: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Outstanding" %}', |             title: '{% jstrans "Outstanding" %}', | ||||||
|         }, |         }, | ||||||
|         overdue: { |         overdue: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Overdue" %}', |             title: '{% jstrans "Overdue" %}', | ||||||
|         }, |         }, | ||||||
|         assigned_to_me: { |         assigned_to_me: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assigned to me" %}', |             title: '{% jstrans "Assigned to me" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -641,7 +641,7 @@ function getSalesOrderAllocationFilters() { | |||||||
|     return { |     return { | ||||||
|         outstanding: { |         outstanding: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Outstanding" %}', |             title: '{% jstrans "Outstanding" %}', | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -651,20 +651,20 @@ function getSalesOrderAllocationFilters() { | |||||||
| function getSalesOrderFilters() { | function getSalesOrderFilters() { | ||||||
|     var filters = { |     var filters = { | ||||||
|         status: { |         status: { | ||||||
|             title: '{% trans "Order status" %}', |             title: '{% jstrans "Order status" %}', | ||||||
|             options: salesOrderCodes, |             options: salesOrderCodes, | ||||||
|         }, |         }, | ||||||
|         outstanding: { |         outstanding: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Outstanding" %}', |             title: '{% jstrans "Outstanding" %}', | ||||||
|         }, |         }, | ||||||
|         overdue: { |         overdue: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Overdue" %}', |             title: '{% jstrans "Overdue" %}', | ||||||
|         }, |         }, | ||||||
|         assigned_to_me: { |         assigned_to_me: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assigned to me" %}', |             title: '{% jstrans "Assigned to me" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -682,7 +682,7 @@ function getSalesOrderLineItemFilters() { | |||||||
|     return { |     return { | ||||||
|         completed: { |         completed: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Completed" %}', |             title: '{% jstrans "Completed" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -693,7 +693,7 @@ function getSupplierPartFilters() { | |||||||
|     return { |     return { | ||||||
|         active: { |         active: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active parts" %}', |             title: '{% jstrans "Active parts" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -704,75 +704,75 @@ function getPartTableFilters() { | |||||||
|     return { |     return { | ||||||
|         cascade: { |         cascade: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Include subcategories" %}', |             title: '{% jstrans "Include subcategories" %}', | ||||||
|             description: '{% trans "Include parts in subcategories" %}', |             description: '{% jstrans "Include parts in subcategories" %}', | ||||||
|         }, |         }, | ||||||
|         active: { |         active: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Active" %}', |             title: '{% jstrans "Active" %}', | ||||||
|             description: '{% trans "Show active parts" %}', |             description: '{% jstrans "Show active parts" %}', | ||||||
|         }, |         }, | ||||||
|         assembly: { |         assembly: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Assembly" %}', |             title: '{% jstrans "Assembly" %}', | ||||||
|         }, |         }, | ||||||
|         unallocated_stock: { |         unallocated_stock: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Available stock" %}', |             title: '{% jstrans "Available stock" %}', | ||||||
|         }, |         }, | ||||||
|         component: { |         component: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Component" %}', |             title: '{% jstrans "Component" %}', | ||||||
|         }, |         }, | ||||||
|         has_units: { |         has_units: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has Units" %}', |             title: '{% jstrans "Has Units" %}', | ||||||
|             description: '{% trans "Part has defined units" %}', |             description: '{% jstrans "Part has defined units" %}', | ||||||
|         }, |         }, | ||||||
|         has_ipn: { |         has_ipn: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has IPN" %}', |             title: '{% jstrans "Has IPN" %}', | ||||||
|             description: '{% trans "Part has internal part number" %}', |             description: '{% jstrans "Part has internal part number" %}', | ||||||
|         }, |         }, | ||||||
|         has_stock: { |         has_stock: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "In stock" %}', |             title: '{% jstrans "In stock" %}', | ||||||
|         }, |         }, | ||||||
|         low_stock: { |         low_stock: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Low stock" %}', |             title: '{% jstrans "Low stock" %}', | ||||||
|         }, |         }, | ||||||
|         purchaseable: { |         purchaseable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Purchasable" %}', |             title: '{% jstrans "Purchasable" %}', | ||||||
|         }, |         }, | ||||||
|         salable: { |         salable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Salable" %}', |             title: '{% jstrans "Salable" %}', | ||||||
|         }, |         }, | ||||||
|         starred: { |         starred: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Subscribed" %}', |             title: '{% jstrans "Subscribed" %}', | ||||||
|         }, |         }, | ||||||
|         stocktake: { |         stocktake: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has stocktake entries" %}', |             title: '{% jstrans "Has stocktake entries" %}', | ||||||
|         }, |         }, | ||||||
|         is_template: { |         is_template: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Template" %}', |             title: '{% jstrans "Template" %}', | ||||||
|         }, |         }, | ||||||
|         trackable: { |         trackable: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Trackable" %}', |             title: '{% jstrans "Trackable" %}', | ||||||
|         }, |         }, | ||||||
|         virtual: { |         virtual: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Virtual" %}', |             title: '{% jstrans "Virtual" %}', | ||||||
|         }, |         }, | ||||||
|         has_pricing: { |         has_pricing: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has Pricing" %}', |             title: '{% jstrans "Has Pricing" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -789,15 +789,15 @@ function getCompanyFilters() { | |||||||
|     return { |     return { | ||||||
|         is_manufacturer: { |         is_manufacturer: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Manufacturer" %}', |             title: '{% jstrans "Manufacturer" %}', | ||||||
|         }, |         }, | ||||||
|         is_supplier: { |         is_supplier: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Supplier" %}', |             title: '{% jstrans "Supplier" %}', | ||||||
|         }, |         }, | ||||||
|         is_customer: { |         is_customer: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Customer" %}', |             title: '{% jstrans "Customer" %}', | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -814,15 +814,15 @@ function getPartParameterTemplateFilters() { | |||||||
|     return { |     return { | ||||||
|         checkbox: { |         checkbox: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Checkbox" %}', |             title: '{% jstrans "Checkbox" %}', | ||||||
|         }, |         }, | ||||||
|         has_choices: { |         has_choices: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has Choices" %}', |             title: '{% jstrans "Has Choices" %}', | ||||||
|         }, |         }, | ||||||
|         has_units: { |         has_units: { | ||||||
|             type: 'bool', |             type: 'bool', | ||||||
|             title: '{% trans "Has Units" %}', |             title: '{% jstrans "Has Units" %}', | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -89,7 +89,7 @@ function constructOrderTableButtons(options={}) { | |||||||
|     // Calendar view button |     // Calendar view button | ||||||
|     if (!options.disableCalendarView) { |     if (!options.disableCalendarView) { | ||||||
|         buttons.push({ |         buttons.push({ | ||||||
|             html: `<button type='button' name='${idx++}' class='btn ${class_calendar}' title='{% trans "Display calendar view" %}'><span class='fas fa-calendar-alt'></span></button>`, |             html: `<button type='button' name='${idx++}' class='btn ${class_calendar}' title='{% jstrans "Display calendar view" %}'><span class='fas fa-calendar-alt'></span></button>`, | ||||||
|             event: function() { |             event: function() { | ||||||
|                 buttonCallback('calendar'); |                 buttonCallback('calendar'); | ||||||
|             } |             } | ||||||
| @@ -99,7 +99,7 @@ function constructOrderTableButtons(options={}) { | |||||||
|     // List view button |     // List view button | ||||||
|     if (!options.disableListView) { |     if (!options.disableListView) { | ||||||
|         buttons.push({ |         buttons.push({ | ||||||
|             html: `<button type='button' name='${idx++}' class='btn ${class_list}' title='{% trans "Display list view" %}'><span class='fas fa-th-list'></span></button>`, |             html: `<button type='button' name='${idx++}' class='btn ${class_list}' title='{% jstrans "Display list view" %}'><span class='fas fa-th-list'></span></button>`, | ||||||
|             event: function() { |             event: function() { | ||||||
|                 buttonCallback('list'); |                 buttonCallback('list'); | ||||||
|             } |             } | ||||||
| @@ -109,7 +109,7 @@ function constructOrderTableButtons(options={}) { | |||||||
|     // Tree view button |     // Tree view button | ||||||
|     if (!options.disableTreeView) { |     if (!options.disableTreeView) { | ||||||
|         buttons.push({ |         buttons.push({ | ||||||
|             html: `<button type='button' name='${idx++}' class='btn ${class_tree}' title='{% trans "Display tree view" %}'><span class='fas fa-sitemap'></span></button>`, |             html: `<button type='button' name='${idx++}' class='btn ${class_tree}' title='{% jstrans "Display tree view" %}'><span class='fas fa-sitemap'></span></button>`, | ||||||
|             event: function() { |             event: function() { | ||||||
|                 buttonCallback('tree'); |                 buttonCallback('tree'); | ||||||
|             } |             } | ||||||
| @@ -127,13 +127,13 @@ function constructExpandCollapseButtons(table, idx=0) { | |||||||
|  |  | ||||||
|     return [ |     return [ | ||||||
|         { |         { | ||||||
|             html: `<button type='button' name='${idx++}' class='btn btn-outline-secondary' title='{% trans "Expand all rows" %}'><span class='fas fa-expand'></span></button>`, |             html: `<button type='button' name='${idx++}' class='btn btn-outline-secondary' title='{% jstrans "Expand all rows" %}'><span class='fas fa-expand'></span></button>`, | ||||||
|             event: function() { |             event: function() { | ||||||
|                 $(table).bootstrapTable('expandAllRows'); |                 $(table).bootstrapTable('expandAllRows'); | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             html: `<button type='button' name='${idx++}' class='btn btn-outline-secondary' title='{% trans "Collapse all rows" %}'><span class='fas fa-compress'></span></button>`, |             html: `<button type='button' name='${idx++}' class='btn btn-outline-secondary' title='{% jstrans "Collapse all rows" %}'><span class='fas fa-compress'></span></button>`, | ||||||
|             event: function() { |             event: function() { | ||||||
|                 $(table).bootstrapTable('collapseAllRows'); |                 $(table).bootstrapTable('collapseAllRows'); | ||||||
|             } |             } | ||||||
| @@ -183,11 +183,11 @@ function downloadTableData(table, opts={}) { | |||||||
|     url += '?'; |     url += '?'; | ||||||
|  |  | ||||||
|     constructFormBody({}, { |     constructFormBody({}, { | ||||||
|         title: opts.title || '{% trans "Export Table Data" %}', |         title: opts.title || '{% jstrans "Export Table Data" %}', | ||||||
|         fields: { |         fields: { | ||||||
|             format: { |             format: { | ||||||
|                 label: '{% trans "Format" %}', |                 label: '{% jstrans "Format" %}', | ||||||
|                 help_text: '{% trans "Select File Format" %}', |                 help_text: '{% jstrans "Select File Format" %}', | ||||||
|                 required: true, |                 required: true, | ||||||
|                 type: 'choice', |                 type: 'choice', | ||||||
|                 value: 'csv', |                 value: 'csv', | ||||||
| @@ -526,39 +526,39 @@ function customGroupSorter(sortName, sortOrder, sortData) { | |||||||
|  |  | ||||||
|     $.fn.bootstrapTable.locales['en-US-custom'] = { |     $.fn.bootstrapTable.locales['en-US-custom'] = { | ||||||
|         formatLoadingMessage: function() { |         formatLoadingMessage: function() { | ||||||
|             return '{% trans "Loading data" %}'; |             return '{% jstrans "Loading data" %}'; | ||||||
|         }, |         }, | ||||||
|         formatRecordsPerPage: function(pageNumber) { |         formatRecordsPerPage: function(pageNumber) { | ||||||
|             return `${pageNumber} {% trans "rows per page" %}`; |             return `${pageNumber} {% jstrans "rows per page" %}`; | ||||||
|         }, |         }, | ||||||
|         formatShowingRows: function(pageFrom, pageTo, totalRows) { |         formatShowingRows: function(pageFrom, pageTo, totalRows) { | ||||||
|  |  | ||||||
|             if (totalRows === undefined || isNaN(totalRows)) { |             if (totalRows === undefined || isNaN(totalRows)) { | ||||||
|                 return '{% trans "Showing all rows" %}'; |                 return '{% jstrans "Showing all rows" %}'; | ||||||
|             } else { |             } else { | ||||||
|                 return `{% trans "Showing" %} ${pageFrom} {% trans "to" %} ${pageTo} {% trans "of" %} ${totalRows} {% trans "rows" %}`; |                 return `{% jstrans "Showing" %} ${pageFrom} {% jstrans "to" %} ${pageTo} {% jstrans "of" %} ${totalRows} {% jstrans "rows" %}`; | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         formatSearch: function() { |         formatSearch: function() { | ||||||
|             return '{% trans "Search" %}'; |             return '{% jstrans "Search" %}'; | ||||||
|         }, |         }, | ||||||
|         formatNoMatches: function() { |         formatNoMatches: function() { | ||||||
|             return '{% trans "No matching results" %}'; |             return '{% jstrans "No matching results" %}'; | ||||||
|         }, |         }, | ||||||
|         formatPaginationSwitch: function() { |         formatPaginationSwitch: function() { | ||||||
|             return '{% trans "Hide/Show pagination" %}'; |             return '{% jstrans "Hide/Show pagination" %}'; | ||||||
|         }, |         }, | ||||||
|         formatRefresh: function() { |         formatRefresh: function() { | ||||||
|             return '{% trans "Refresh" %}'; |             return '{% jstrans "Refresh" %}'; | ||||||
|         }, |         }, | ||||||
|         formatToggle: function() { |         formatToggle: function() { | ||||||
|             return '{% trans "Toggle" %}'; |             return '{% jstrans "Toggle" %}'; | ||||||
|         }, |         }, | ||||||
|         formatColumns: function() { |         formatColumns: function() { | ||||||
|             return '{% trans "Columns" %}'; |             return '{% jstrans "Columns" %}'; | ||||||
|         }, |         }, | ||||||
|         formatAllRows: function() { |         formatAllRows: function() { | ||||||
|             return '{% trans "All" %}'; |             return '{% jstrans "All" %}'; | ||||||
|         }, |         }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ def check_prohibited_tags(data): | |||||||
|         'for', |         'for', | ||||||
|         'endfor', |         'endfor', | ||||||
|         'trans', |         'trans', | ||||||
|  |         'jstrans', | ||||||
|         'load', |         'load', | ||||||
|         'include', |         'include', | ||||||
|         'url', |         'url', | ||||||
| @@ -84,17 +85,18 @@ for filename in pathlib.Path(js_dynamic_dir).rglob('*.js'): | |||||||
|     with open(filename, 'r') as js_file: |     with open(filename, 'r') as js_file: | ||||||
|         data = js_file.readlines() |         data = js_file.readlines() | ||||||
|  |  | ||||||
|     pattern = r'{% trans ' |     invalid_tags = ['trans', 'jstrans'] | ||||||
|  |  | ||||||
|     err_count = 0 |     err_count = 0 | ||||||
|  |  | ||||||
|     for idx, line in enumerate(data): |     for idx, line in enumerate(data): | ||||||
|         results = re.findall(pattern, line) |         for tag in invalid_tags: | ||||||
|  |             tag = '{% ' + tag | ||||||
|  |             if tag in line: | ||||||
|  |                 err_count += 1 | ||||||
|  |  | ||||||
|         if len(results) > 0: |                 print(f" > Error on line {idx+1}: Prohibited tag '{tag}' found") | ||||||
|             errors += 1 |  | ||||||
|  |  | ||||||
|             print(f' > prohibited {{% trans %}} tag found at line {idx + 1}') |  | ||||||
|  |  | ||||||
| if errors > 0: | if errors > 0: | ||||||
|     print(f'Found {errors} incorrect template tags') |     print(f'Found {errors} incorrect template tags') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user