mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	More features
- Custom renderers depending on specified model name - Paginate API results
This commit is contained in:
		| @@ -972,4 +972,11 @@ input[type="date"].form-control, input[type="time"].form-control, input[type="da | |||||||
|  |  | ||||||
| .select2-container { | .select2-container { | ||||||
|     width: 100%; |     width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .select2-thumbnail { | ||||||
|  |     max-width: 24px; | ||||||
|  |     max-height: 24px; | ||||||
|  |     border-radius: 4px; | ||||||
|  |     margin-right: 10px; | ||||||
| } | } | ||||||
| @@ -105,6 +105,7 @@ settings_urls = [ | |||||||
| dynamic_javascript_urls = [ | dynamic_javascript_urls = [ | ||||||
|     url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'), |     url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'), | ||||||
|     url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'), |     url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'), | ||||||
|  |     url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'), | ||||||
|     url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'), |     url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'), | ||||||
|     url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'), |     url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'), | ||||||
|     url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'), |     url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'), | ||||||
|   | |||||||
| @@ -150,6 +150,7 @@ | |||||||
| <!-- translated --> | <!-- translated --> | ||||||
| <script type='text/javascript' src="{% i18n_static 'api.js' %}"></script> | <script type='text/javascript' src="{% i18n_static 'api.js' %}"></script> | ||||||
| <script type='text/javascript' src="{% i18n_static 'forms.js' %}"></script> | <script type='text/javascript' src="{% i18n_static 'forms.js' %}"></script> | ||||||
|  | <script type='text/javascript' src="{% i18n_static 'model_renderers.js' %}"></script> | ||||||
| <script type='text/javascript' src="{% i18n_static 'barcode.js' %}"></script> | <script type='text/javascript' src="{% i18n_static 'barcode.js' %}"></script> | ||||||
| <script type='text/javascript' src="{% i18n_static 'bom.js' %}"></script> | <script type='text/javascript' src="{% i18n_static 'bom.js' %}"></script> | ||||||
| <script type='text/javascript' src="{% i18n_static 'company.js' %}"></script> | <script type='text/javascript' src="{% i18n_static 'company.js' %}"></script> | ||||||
|   | |||||||
| @@ -364,7 +364,8 @@ function initializeRelatedField(modal, name, field, options) { | |||||||
|  |  | ||||||
|     // TODO: Add 'placeholder' support for entry select2 fields |     // TODO: Add 'placeholder' support for entry select2 fields | ||||||
|  |  | ||||||
|     // TODO: Add 'pagination' support for the query |     // limit size for AJAX requests | ||||||
|  |     var pageSize = options.pageSize || 25; | ||||||
|  |  | ||||||
|     select.select2({ |     select.select2({ | ||||||
|         ajax: { |         ajax: { | ||||||
| @@ -377,31 +378,52 @@ function initializeRelatedField(modal, name, field, options) { | |||||||
|             cache: true, |             cache: true, | ||||||
|             // matcher: partialMatcher, |             // matcher: partialMatcher, | ||||||
|             data: function(params) { |             data: function(params) { | ||||||
|  |  | ||||||
|  |                 if (!params.page) { | ||||||
|  |                     offset = 0; | ||||||
|  |                 } else { | ||||||
|  |                     offset = (params.page - 1) * pageSize; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 // Re-format search term into InvenTree API style |                 // Re-format search term into InvenTree API style | ||||||
|                 return { |                 return { | ||||||
|                     search: params.term, |                     search: params.term, | ||||||
|  |                     offset: offset, | ||||||
|  |                     limit: pageSize, | ||||||
|                 }; |                 }; | ||||||
|             }, |             }, | ||||||
|             processResults: function(data) { |             processResults: function(response) { | ||||||
|                 // Convert the returned InvenTree data into select2-friendly format |                 // Convert the returned InvenTree data into select2-friendly format | ||||||
|                 var rows = []; |  | ||||||
|  |  | ||||||
|                 // Only ever show the first x items |                 var data = []; | ||||||
|                 for (var idx = 0; idx < data.length && idx < 50; idx++) { |  | ||||||
|                     var row = data[idx]; |  | ||||||
|  |  | ||||||
|                     // Reformat to match select2 requirements |                 var more = false; | ||||||
|                     row.id = row.id || row.pk; |  | ||||||
|  |  | ||||||
|                     // TODO: Fix me? |                 if ('count' in response && 'results' in response) { | ||||||
|                     row.text = `This is ${field.api_url}${row.id}/`; |                     // Response is paginated | ||||||
|  |                     data = response.results; | ||||||
|  |  | ||||||
|                     rows.push(row); |                     // Any more data available? | ||||||
|  |                     if (response.next) { | ||||||
|  |                         more = true; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                 } else { | ||||||
|  |                     // Non-paginated response | ||||||
|  |                     data = response; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // Each 'row' must have the 'id' attribute | ||||||
|  |                 for (var idx = 0; idx < data.length; idx++) { | ||||||
|  |                     data[idx].id = data[idx].pk; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // Ref: https://select2.org/data-sources/formats |                 // Ref: https://select2.org/data-sources/formats | ||||||
|                 var results = { |                 var results = { | ||||||
|                     results: rows, |                     results: data, | ||||||
|  |                     pagination: { | ||||||
|  |                         more: more, | ||||||
|  |                     } | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|                 return results; |                 return results; | ||||||
| @@ -442,7 +464,7 @@ function initializeRelatedField(modal, name, field, options) { | |||||||
|  * - parameters: The field definition (OPTIONS) request |  * - parameters: The field definition (OPTIONS) request | ||||||
|  * - options: Other options provided at time of modal creation by the client |  * - options: Other options provided at time of modal creation by the client | ||||||
|  */ |  */ | ||||||
| function renderModelData(name, model, data, paramaters, options) { | function renderModelData(name, model, data, parameters, options) { | ||||||
|  |  | ||||||
|     if (!data) { |     if (!data) { | ||||||
|         return '{% trans "Searching" %}...'; |         return '{% trans "Searching" %}...'; | ||||||
| @@ -452,20 +474,41 @@ function renderModelData(name, model, data, paramaters, options) { | |||||||
|  |  | ||||||
|     var html = null; |     var html = null; | ||||||
|  |  | ||||||
|  |     var renderer = null; | ||||||
|  |  | ||||||
|  |     // Find a custom renderer  | ||||||
|     switch (model) { |     switch (model) { | ||||||
|         case 'company': |         case 'company': | ||||||
|             html = `<span>${data.name}</span> - <i>${data.description}</i>`; |             renderer = renderCompany; | ||||||
|  |             break; | ||||||
|  |         case 'stockitem': | ||||||
|  |             renderer = renderStockItem; | ||||||
|  |             break; | ||||||
|  |         case 'stocklocation': | ||||||
|  |             renderer = renderStockLocation; | ||||||
|  |             break; | ||||||
|  |         case 'part': | ||||||
|  |             renderer = renderPart; | ||||||
|  |             break; | ||||||
|  |         case 'partcategory': | ||||||
|  |             renderer = renderPartCategory; | ||||||
|  |             break; | ||||||
|         default: |         default: | ||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     if (renderer != null) { | ||||||
|  |         html = renderer(name, data, parameters, options); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (html != null) { |     if (html != null) { | ||||||
|         // Render HTML to an object |         // Render HTML to an object | ||||||
|         var $state = $(html); |         var $state = $(html); | ||||||
|         return $state; |         return $state; | ||||||
|     } else { |     } else { | ||||||
|  |         console.log(`ERROR: Rendering not implemented for model '${model}'`); | ||||||
|         // Simple text rendering |         // Simple text rendering | ||||||
|         return data.text; |         return data.id; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										83
									
								
								InvenTree/templates/js/model_renderers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								InvenTree/templates/js/model_renderers.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | /* | ||||||
|  |  * This file contains functions for rendering various InvenTree database models, | ||||||
|  |  * in particular for displaying them in modal forms in a 'select2' context. | ||||||
|  |  *  | ||||||
|  |  * Each renderer is provided with three arguments: | ||||||
|  |  *  | ||||||
|  |  * - name: The 'name' of the model instance in the referring model | ||||||
|  |  * - data: JSON data which represents the model instance. Returned via a GET request. | ||||||
|  |  * - parameters: The field parameters provided via an OPTIONS request to the endpoint. | ||||||
|  |  * - options: User options provided by the client | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Renderer for "Company" model | ||||||
|  | function renderCompany(name, data, parameters, options) { | ||||||
|  |  | ||||||
|  |     var html = `<span>${data.name}</span> - <i>${data.description}</i>`; | ||||||
|  |  | ||||||
|  |     return html; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Renderer for "StockItem" model | ||||||
|  | function renderStockItem(name, data, parameters, options) { | ||||||
|  |  | ||||||
|  |     // TODO - Include part detail, location, quantity | ||||||
|  |     // TODO - Include part image | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Renderer for "StockLocation" model | ||||||
|  | function renderStockLocation(name, data, parameters, options) { | ||||||
|  |  | ||||||
|  |     var html = `<span>${data.name}</span>`; | ||||||
|  |  | ||||||
|  |     if (data.description) { | ||||||
|  |         html += ` - <i>${data.description}</i>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (data.pathstring) { | ||||||
|  |         html += `<p><small>${data.pathstring}</small></p>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return html; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Renderer for "Part" model | ||||||
|  | function renderPart(name, data, parameters, options) { | ||||||
|  |  | ||||||
|  |     var image = data.image; | ||||||
|  |  | ||||||
|  |     if (!image) { | ||||||
|  |         image = `/static/img/blank_image.png`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     var html = `<img src='${image}' class='select2-thumbnail'>`; | ||||||
|  |      | ||||||
|  |     html += ` <span>${data.full_name ?? data.name}</span>`; | ||||||
|  |  | ||||||
|  |     if (data.description) { | ||||||
|  |         html += ` - <i>${data.description}</i>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return html; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Renderer for "PartCategory" model | ||||||
|  | function renderPartCategory(name, data, parameters, options) { | ||||||
|  |  | ||||||
|  |     var html = `<span>${data.name}</span>`; | ||||||
|  |  | ||||||
|  |     if (data.description) { | ||||||
|  |         html += ` - <i>${data.description}</i>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (data.pathstring) { | ||||||
|  |         html += `<p><small>${data.pathstring}</small></p>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return html; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user