diff --git a/shimatta_kenkyusho/api/views.py b/shimatta_kenkyusho/api/views.py index 3c85ea5..d2519ab 100644 --- a/shimatta_kenkyusho/api/views.py +++ b/shimatta_kenkyusho/api/views.py @@ -47,7 +47,7 @@ class PartsComponentViewSet(viewsets.ModelViewSet): serializer_class = ComponentSerializer permission_classes = [permissions.DjangoModelPermissions] filter_backends = [filters.SearchFilter] - search_fields = ['name', 'package__name', 'manufacturer__name'] + search_fields = ['id', 'name', 'package__name', 'manufacturer__name'] class PartsManufacturerViewSet(viewsets.ModelViewSet): queryset = parts_models.Manufacturer.objects.all() diff --git a/shimatta_kenkyusho/parts/forms.py b/shimatta_kenkyusho/parts/forms.py index e84bbd3..5be0176 100644 --- a/shimatta_kenkyusho/parts/forms.py +++ b/shimatta_kenkyusho/parts/forms.py @@ -71,4 +71,37 @@ class EditStockAmountForm(forms.Form): if not increase: amount = -amount - return stock.atomic_increment(amount) \ No newline at end of file + return stock.atomic_increment(amount) + +class AddStockForm(forms.Form): + watermark_active = forms.BooleanField(required=False) + watermark = forms.IntegerField(min_value=0, required=True, initial=0) + amount = forms.IntegerField(min_value=0, required=True, initial=1) + component_uuid = forms.UUIDField(required=True) + + def clean(self): + cleaned_data = super().clean() + + id = cleaned_data.get('component_uuid') + if not id: + raise ValidationError('No valid component selected!') + component = None + try: + component = parts_models.Component.objects.get(id=id) + except: + raise ValidationError("Invalid component selected!") + cleaned_data['component'] = component + + return cleaned_data + + def save(self, storage): + component = self.cleaned_data.get('component') + amount = self.cleaned_data.get('amount') + watermark = -1 + + if self.cleaned_data.get('watermark-active'): + watermark = self.cleaned_data.get('watermark') + + new_stock = parts_models.Stock.objects.create(storage=storage, component=component, watermark=watermark, amount=amount) + new_stock.save() + \ No newline at end of file diff --git a/shimatta_kenkyusho/parts/views.py b/shimatta_kenkyusho/parts/views.py index db752a8..7c567cb 100644 --- a/shimatta_kenkyusho/parts/views.py +++ b/shimatta_kenkyusho/parts/views.py @@ -13,7 +13,7 @@ from .models import Storage, Stock from .qr_parser import QrCodeValidator from django.core.paginator import Paginator from django.core.exceptions import ValidationError -from .forms import MyTestForm, AddSubStorageForm, DeleteStockForm, EditWatermarkForm, EditStockAmountForm +from .forms import MyTestForm, AddSubStorageForm, DeleteStockForm, EditWatermarkForm, EditStockAmountForm, AddStockForm from django.db.models import Q from django.db.models.functions import Lower import uuid @@ -223,6 +223,7 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): add_storage_form.fields['responsible'].initial = self.request.user.username context['add_storage_form'] = add_storage_form context['delete_storage_error'] = None + context['add_stock_form'] = AddStockForm() return context @@ -293,6 +294,24 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): context = self.get_context_data(**kwargs) return self.render_to_response(context) + def handle_add_stock_post(self, request, **kwargs): + f = AddStockForm(data=request.POST) + error_occured = False + + if f.is_valid(): + try: + f.save(self.object) + except Exception as ex: + f.add_error('', str(ex)) + error_occured = True + else: + error_occured = True + + context = self.get_context_data(**kwargs) + if error_occured: + context['add_stock_form'] = f + return self.render_to_response(context) + def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -308,4 +327,7 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): return self.handle_amount_change_post(request, False, **kwargs) elif 'submit-amount-increase' in request.POST: return self.handle_amount_change_post(request, True, **kwargs) + elif 'submit-add-stock' in request.POST: + return self.handle_add_stock_post(request, **kwargs) + return super().post(request, *args, **kwargs) \ No newline at end of file diff --git a/shimatta_kenkyusho/static/js/add-stock-modal.js b/shimatta_kenkyusho/static/js/add-stock-modal.js index 7d6e72f..6b8d489 100644 --- a/shimatta_kenkyusho/static/js/add-stock-modal.js +++ b/shimatta_kenkyusho/static/js/add-stock-modal.js @@ -1,3 +1,31 @@ +function fill_add_stock_modal_component(data) { + // component has been selected. Process it: + document.getElementById('add-stock-search').value = ''; + console.log(data); + var template = document.querySelector('#add-stock-modal-component-template'); + var container = document.querySelector('#add-stock-modal-component-container'); + container.innerHTML = ''; + var comp_elem = template.content.cloneNode(true); + + if (data.ro_image) { + comp_elem.querySelector('#add-stock-cmp-img').setAttribute('src', data.ro_image); + } + var description_container = comp_elem.querySelector('#add-stock-cmp-desc-container'); + var heading = document.createElement('h6'); + heading.appendChild(document.createTextNode(data.name)); + description_container.appendChild(heading); + if (data.package_data && data.package_data.name) { + description_container.appendChild(document.createTextNode('in '+data.package_data.name)); + } + if (data.ro_manufacturer_name) { + description_container.appendChild(document.createElement('br')); + description_container.appendChild(document.createTextNode('by '+data.ro_manufacturer_name)); + } + document.querySelector('#add-stock-modal-comp-uuid').value = data.id; + console.log("Selected element: "+data.id); + container.appendChild(comp_elem); +} + new AutocompleteCustomUi('add-stock-search', 'add-stock-search-ac-dropdown', function(search, autocomplete_obj) { api_search_component(search, function(results) { @@ -36,9 +64,9 @@ function(search, autocomplete_obj) { node.appendChild(img_container); node.appendChild(text_container); - test.push({'ui': node, 'data': c.url}) + test.push({'ui': node, 'data': c}) } autocomplete_obj.show_results(test, - function(data) {console.log(data);}); + function(data){fill_add_stock_modal_component(data);}); }, function(){}); }); \ No newline at end of file diff --git a/shimatta_kenkyusho/static/js/autocomplete.js b/shimatta_kenkyusho/static/js/autocomplete.js index a1992a9..dbe90d9 100644 --- a/shimatta_kenkyusho/static/js/autocomplete.js +++ b/shimatta_kenkyusho/static/js/autocomplete.js @@ -11,6 +11,8 @@ class AutocompleteCustomUi { this.query_callback(document.getElementById(this.text_id).value, this); }, autocomplete_query_delay_ms).bind(this)); + this.dropdown_data = {}; + } /** @@ -24,15 +26,17 @@ class AutocompleteCustomUi { var ul = document.getElementById(this.dropdown_id); ul.innerHTML = ''; this.select_data = {}; + this.dropdown_data = {}; for (var i = 0; i < nodes_to_add.length; i++) { var ui = nodes_to_add[i]['ui']; var data = nodes_to_add[i]['data'] var dropdown_node = document.createElement('li'); - dropdown_node.dataset.ac_clicked = data; + dropdown_node.dataset.ac_clicked = i; + this.dropdown_data[i] = data; dropdown_node.addEventListener('click', (e) => { - data_clicked_callback(e.currentTarget.dataset.ac_clicked); + data_clicked_callback(this.dropdown_data[e.currentTarget.dataset.ac_clicked]); var text_box = document.getElementById(this.text_id); var dropdown = bootstrap.Dropdown.getOrCreateInstance(text_box); dropdown.hide(); diff --git a/shimatta_kenkyusho/static/js/kenyusho-api-v1.js b/shimatta_kenkyusho/static/js/kenyusho-api-v1.js index 5011d83..951efc0 100644 --- a/shimatta_kenkyusho/static/js/kenyusho-api-v1.js +++ b/shimatta_kenkyusho/static/js/kenyusho-api-v1.js @@ -31,4 +31,8 @@ function api_search_user(search, onSuccess, onFail) { function api_search_component(search, onSuccess, onFail) { return api_ajax_request_without_send('GET', api_urls_v1['component-list']+`?search=${encodeURIComponent(search)}`, function(method, url, json) {onSuccess(json);}, onFail); +} + +function api_get_component_from_id(id, onSuccess, onFail) { + return api_ajax_request_without_send('GET', api_urls_v1['component-list']+`?search=${encodeURIComponent(id)}`, function(method, url, json) {onSuccess(json.results[0]);}, onFail); } \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/modals/add-stock-modal.html b/shimatta_kenkyusho/templates/parts/modals/add-stock-modal.html index df88199..a617aa7 100644 --- a/shimatta_kenkyusho/templates/parts/modals/add-stock-modal.html +++ b/shimatta_kenkyusho/templates/parts/modals/add-stock-modal.html @@ -2,6 +2,7 @@ Input context: - form: A stock-create-form {% endcomment %} +{% load static %} - \ No newline at end of file + + \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/stocks-detail.html b/shimatta_kenkyusho/templates/parts/stocks-detail.html index 3cc305f..7e2eed9 100644 --- a/shimatta_kenkyusho/templates/parts/stocks-detail.html +++ b/shimatta_kenkyusho/templates/parts/stocks-detail.html @@ -121,6 +121,7 @@ {% endblock content %} {% block custom_scripts %} + - {% endblock custom_scripts %}