mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
7be1edd896
2
.gitignore
vendored
2
.gitignore
vendored
@ -34,6 +34,8 @@ docs/_build
|
|||||||
# Local static and media file storage (only when running in development mode)
|
# Local static and media file storage (only when running in development mode)
|
||||||
InvenTree/media
|
InvenTree/media
|
||||||
InvenTree/static
|
InvenTree/static
|
||||||
|
media
|
||||||
|
static
|
||||||
|
|
||||||
# Local config file
|
# Local config file
|
||||||
config.yaml
|
config.yaml
|
||||||
|
@ -88,6 +88,12 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.basecurrency {
|
||||||
|
color: #050;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.bomselect {
|
.bomselect {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
}
|
}
|
||||||
@ -198,6 +204,28 @@
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-container {
|
||||||
|
width: 90%;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-nav {
|
||||||
|
height: 100%;
|
||||||
|
width: 160px;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
//top: 0;
|
||||||
|
//left: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-content {
|
||||||
|
margin-left: 175px;
|
||||||
|
padding: 0px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.breadcrump {
|
.breadcrump {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,13 @@ from company.urls import company_urls
|
|||||||
from company.urls import supplier_part_urls
|
from company.urls import supplier_part_urls
|
||||||
from company.urls import price_break_urls
|
from company.urls import price_break_urls
|
||||||
|
|
||||||
|
from common.urls import common_urls
|
||||||
from part.urls import part_urls
|
from part.urls import part_urls
|
||||||
from stock.urls import stock_urls
|
from stock.urls import stock_urls
|
||||||
from build.urls import build_urls
|
from build.urls import build_urls
|
||||||
from order.urls import order_urls
|
from order.urls import order_urls
|
||||||
|
|
||||||
|
from common.api import common_api_urls
|
||||||
from part.api import part_api_urls, bom_api_urls
|
from part.api import part_api_urls, bom_api_urls
|
||||||
from company.api import company_api_urls
|
from company.api import company_api_urls
|
||||||
from stock.api import stock_api_urls
|
from stock.api import stock_api_urls
|
||||||
@ -39,6 +41,7 @@ from users.urls import user_urls
|
|||||||
admin.site.site_header = "InvenTree Admin"
|
admin.site.site_header = "InvenTree Admin"
|
||||||
|
|
||||||
apipatterns = [
|
apipatterns = [
|
||||||
|
url(r'^common/', include(common_api_urls)),
|
||||||
url(r'^part/', include(part_api_urls)),
|
url(r'^part/', include(part_api_urls)),
|
||||||
url(r'^bom/', include(bom_api_urls)),
|
url(r'^bom/', include(bom_api_urls)),
|
||||||
url(r'^company/', include(company_api_urls)),
|
url(r'^company/', include(company_api_urls)),
|
||||||
@ -53,11 +56,23 @@ apipatterns = [
|
|||||||
url(r'^$', InfoView.as_view(), name='inventree-info'),
|
url(r'^$', InfoView.as_view(), name='inventree-info'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
settings_urls = [
|
||||||
|
|
||||||
|
url(r'^user/?', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings-user'),
|
||||||
|
url(r'^currency/?', SettingsView.as_view(template_name='InvenTree/settings/currency.html'), name='settings-currency'),
|
||||||
|
url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
|
||||||
|
|
||||||
|
# Catch any other urls
|
||||||
|
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/user.html'), name='settings'),
|
||||||
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^part/', include(part_urls)),
|
url(r'^part/', include(part_urls)),
|
||||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
url(r'^supplier-part/', include(supplier_part_urls)),
|
||||||
url(r'^price-break/', include(price_break_urls)),
|
url(r'^price-break/', include(price_break_urls)),
|
||||||
|
|
||||||
|
url(r'^common/', include(common_urls)),
|
||||||
|
|
||||||
url(r'^stock/', include(stock_urls)),
|
url(r'^stock/', include(stock_urls)),
|
||||||
|
|
||||||
url(r'^company/', include(company_urls)),
|
url(r'^company/', include(company_urls)),
|
||||||
@ -70,7 +85,7 @@ urlpatterns = [
|
|||||||
url(r'^login/', auth_views.LoginView.as_view(), name='login'),
|
url(r'^login/', auth_views.LoginView.as_view(), name='login'),
|
||||||
url(r'^logout/', auth_views.LogoutView.as_view(template_name='registration/logout.html'), name='logout'),
|
url(r'^logout/', auth_views.LogoutView.as_view(template_name='registration/logout.html'), name='logout'),
|
||||||
|
|
||||||
url(r'^settings/', SettingsView.as_view(), name='settings'),
|
url(r'^settings/', include(settings_urls)),
|
||||||
|
|
||||||
url(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
|
url(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
|
||||||
url(r'^set-password/', SetPasswordView.as_view(), name='set-password'),
|
url(r'^set-password/', SetPasswordView.as_view(), name='set-password'),
|
||||||
|
39
InvenTree/common/api.py
Normal file
39
InvenTree/common/api.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
"""
|
||||||
|
Provides a JSON API for common components.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from rest_framework import permissions, generics, filters
|
||||||
|
|
||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from .models import Currency
|
||||||
|
from .serializers import CurrencySerializer
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencyList(generics.ListCreateAPIView):
|
||||||
|
""" API endpoint for accessing a list of Currency objects.
|
||||||
|
|
||||||
|
- GET: Return a list of Currencies
|
||||||
|
- POST: Create a new currency
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = Currency.objects.all()
|
||||||
|
serializer_class = CurrencySerializer
|
||||||
|
|
||||||
|
permission_classes = [
|
||||||
|
permissions.IsAuthenticated,
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_backends = [
|
||||||
|
filters.OrderingFilter,
|
||||||
|
]
|
||||||
|
|
||||||
|
ordering_fields = ['suffix', 'value']
|
||||||
|
|
||||||
|
|
||||||
|
common_api_urls = [
|
||||||
|
url(r'^currency/?$', CurrencyList.as_view(), name='api-currency-list'),
|
||||||
|
]
|
24
InvenTree/common/forms.py
Normal file
24
InvenTree/common/forms.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"""
|
||||||
|
Django forms for interacting with common objects
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from InvenTree.forms import HelperForm
|
||||||
|
|
||||||
|
from .models import Currency
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencyEditForm(HelperForm):
|
||||||
|
""" Form for creating / editing a currency object """
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Currency
|
||||||
|
fields = [
|
||||||
|
'symbol',
|
||||||
|
'suffix',
|
||||||
|
'description',
|
||||||
|
'value',
|
||||||
|
'base'
|
||||||
|
]
|
22
InvenTree/common/serializers.py
Normal file
22
InvenTree/common/serializers.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
"""
|
||||||
|
JSON serializers for common components
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .models import Currency
|
||||||
|
|
||||||
|
from InvenTree.serializers import InvenTreeModelSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencySerializer(InvenTreeModelSerializer):
|
||||||
|
""" Serializer for Currency object """
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Currency
|
||||||
|
fields = [
|
||||||
|
'pk',
|
||||||
|
'symbol',
|
||||||
|
'suffix',
|
||||||
|
'description',
|
||||||
|
'value',
|
||||||
|
'base'
|
||||||
|
]
|
7
InvenTree/common/templates/common/delete_currency.html
Normal file
7
InvenTree/common/templates/common/delete_currency.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% extends "modal_delete_form.html" %}
|
||||||
|
|
||||||
|
{% block pre_form_content %}
|
||||||
|
|
||||||
|
Are you sure you wish to delete this currency?
|
||||||
|
|
||||||
|
{% endblock %}
|
18
InvenTree/common/urls.py
Normal file
18
InvenTree/common/urls.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
"""
|
||||||
|
URL lookup for common views
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.conf.urls import url, include
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
currency_urls = [
|
||||||
|
url(r'^new/', views.CurrencyCreate.as_view(), name='currency-create'),
|
||||||
|
|
||||||
|
url(r'^(?P<pk>\d+)/edit/', views.CurrencyEdit.as_view(), name='currency-edit'),
|
||||||
|
url(r'^(?P<pk>\d+)/delete/', views.CurrencyDelete.as_view(), name='currency-delete'),
|
||||||
|
]
|
||||||
|
|
||||||
|
common_urls = [
|
||||||
|
url(r'currency/', include(currency_urls)),
|
||||||
|
]
|
@ -1 +1,35 @@
|
|||||||
# Create your views here.
|
"""
|
||||||
|
Django views for interacting with common models
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from InvenTree.views import AjaxCreateView, AjaxUpdateView, AjaxDeleteView
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from . import forms
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencyCreate(AjaxCreateView):
|
||||||
|
""" View for creating a new Currency object """
|
||||||
|
|
||||||
|
model = models.Currency
|
||||||
|
form_class = forms.CurrencyEditForm
|
||||||
|
ajax_form_title = 'Create new Currency'
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencyEdit(AjaxUpdateView):
|
||||||
|
""" View for editing an existing Currency object """
|
||||||
|
|
||||||
|
model = models.Currency
|
||||||
|
form_class = forms.CurrencyEditForm
|
||||||
|
ajax_form_title = 'Edit Currency'
|
||||||
|
|
||||||
|
|
||||||
|
class CurrencyDelete(AjaxDeleteView):
|
||||||
|
""" View for deleting an existing Currency object """
|
||||||
|
|
||||||
|
model = models.Currency
|
||||||
|
ajax_form_title = 'Delete Currency'
|
||||||
|
ajax_template_name = "common/delete_currency.html"
|
||||||
|
@ -21,10 +21,12 @@ from django.urls import reverse
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from .models import Part, PartCategory, BomItem, PartStar
|
from .models import Part, PartCategory, BomItem, PartStar
|
||||||
|
from .models import PartParameter, PartParameterTemplate
|
||||||
|
|
||||||
from .serializers import PartSerializer, BomItemSerializer
|
from .serializers import PartSerializer, BomItemSerializer
|
||||||
from .serializers import CategorySerializer
|
from .serializers import CategorySerializer
|
||||||
from .serializers import PartStarSerializer
|
from .serializers import PartStarSerializer
|
||||||
|
from .serializers import PartParameterSerializer, PartParameterTemplateSerializer
|
||||||
|
|
||||||
from InvenTree.views import TreeSerializer
|
from InvenTree.views import TreeSerializer
|
||||||
from InvenTree.helpers import str2bool
|
from InvenTree.helpers import str2bool
|
||||||
@ -261,6 +263,53 @@ class PartStarList(generics.ListCreateAPIView):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PartParameterTemplateList(generics.ListCreateAPIView):
|
||||||
|
""" API endpoint for accessing a list of PartParameterTemplate objects.
|
||||||
|
|
||||||
|
- GET: Return list of PartParameterTemplate objects
|
||||||
|
- POST: Create a new PartParameterTemplate object
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = PartParameterTemplate.objects.all()
|
||||||
|
serializer_class = PartParameterTemplateSerializer
|
||||||
|
|
||||||
|
permission_classes = [
|
||||||
|
permissions.IsAuthenticated,
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_backends = [
|
||||||
|
filters.OrderingFilter,
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_fields = [
|
||||||
|
'name',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PartParameterList(generics.ListCreateAPIView):
|
||||||
|
""" API endpoint for accessing a list of PartParameter objects
|
||||||
|
|
||||||
|
- GET: Return list of PartParameter objects
|
||||||
|
- POST: Create a new PartParameter object
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = PartParameter.objects.all()
|
||||||
|
serializer_class = PartParameterSerializer
|
||||||
|
|
||||||
|
permission_classes = [
|
||||||
|
permissions.IsAuthenticated,
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_backends = [
|
||||||
|
DjangoFilterBackend
|
||||||
|
]
|
||||||
|
|
||||||
|
filter_fields = [
|
||||||
|
'part',
|
||||||
|
'template',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class BomList(generics.ListCreateAPIView):
|
class BomList(generics.ListCreateAPIView):
|
||||||
""" API endpoint for accessing a list of BomItem objects.
|
""" API endpoint for accessing a list of BomItem objects.
|
||||||
|
|
||||||
@ -362,12 +411,18 @@ part_star_api_urls = [
|
|||||||
url(r'^.*$', PartStarList.as_view(), name='api-part-star-list'),
|
url(r'^.*$', PartStarList.as_view(), name='api-part-star-list'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
part_param_api_urls = [
|
||||||
|
url(r'^template/$', PartParameterTemplateList.as_view(), name='api-part-param-template-list'),
|
||||||
|
|
||||||
|
url(r'^.*$', PartParameterList.as_view(), name='api-part-param-list'),
|
||||||
|
]
|
||||||
|
|
||||||
part_api_urls = [
|
part_api_urls = [
|
||||||
url(r'^tree/?', PartCategoryTree.as_view(), name='api-part-tree'),
|
url(r'^tree/?', PartCategoryTree.as_view(), name='api-part-tree'),
|
||||||
|
|
||||||
url(r'^category/', include(cat_api_urls)),
|
url(r'^category/', include(cat_api_urls)),
|
||||||
url(r'^star/', include(part_star_api_urls)),
|
url(r'^star/', include(part_star_api_urls)),
|
||||||
|
url(r'^parameter/', include(part_param_api_urls)),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/?', PartDetail.as_view(), name='api-part-detail'),
|
url(r'^(?P<pk>\d+)/?', PartDetail.as_view(), name='api-part-detail'),
|
||||||
|
|
||||||
|
18
InvenTree/part/migrations/0018_auto_20190907_0941.py
Normal file
18
InvenTree/part/migrations/0018_auto_20190907_0941.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.2.4 on 2019-09-07 09:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('part', '0017_bomitem_checksum'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='partparametertemplate',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(help_text='Parameter Name', max_length=100, unique=True),
|
||||||
|
),
|
||||||
|
]
|
@ -1068,7 +1068,7 @@ class PartParameterTemplate(models.Model):
|
|||||||
""" Return the number of instances of this Parameter Template """
|
""" Return the number of instances of this Parameter Template """
|
||||||
return self.instances.count()
|
return self.instances.count()
|
||||||
|
|
||||||
name = models.CharField(max_length=100, help_text='Parameter Name')
|
name = models.CharField(max_length=100, help_text='Parameter Name', unique=True)
|
||||||
|
|
||||||
units = models.CharField(max_length=25, help_text='Parameter Units', blank=True)
|
units = models.CharField(max_length=25, help_text='Parameter Units', blank=True)
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ from .models import Part, PartStar
|
|||||||
|
|
||||||
from .models import PartCategory
|
from .models import PartCategory
|
||||||
from .models import BomItem
|
from .models import BomItem
|
||||||
|
from .models import PartParameter, PartParameterTemplate
|
||||||
|
|
||||||
from InvenTree.serializers import InvenTreeModelSerializer
|
from InvenTree.serializers import InvenTreeModelSerializer
|
||||||
|
|
||||||
@ -174,3 +175,28 @@ class BomItemSerializer(InvenTreeModelSerializer):
|
|||||||
'note',
|
'note',
|
||||||
'validated',
|
'validated',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PartParameterSerializer(InvenTreeModelSerializer):
|
||||||
|
""" JSON serializers for the PartParameter model """
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = PartParameter
|
||||||
|
fields = [
|
||||||
|
'pk',
|
||||||
|
'part',
|
||||||
|
'template',
|
||||||
|
'data'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PartParameterTemplateSerializer(InvenTreeModelSerializer):
|
||||||
|
""" JSON serializer for the PartParameterTemplate model """
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = PartParameterTemplate
|
||||||
|
fields = [
|
||||||
|
'pk',
|
||||||
|
'name',
|
||||||
|
'units',
|
||||||
|
]
|
||||||
|
@ -21,6 +21,8 @@ part_attachment_urls = [
|
|||||||
part_parameter_urls = [
|
part_parameter_urls = [
|
||||||
|
|
||||||
url('^template/new/', views.PartParameterTemplateCreate.as_view(), name='part-param-template-create'),
|
url('^template/new/', views.PartParameterTemplateCreate.as_view(), name='part-param-template-create'),
|
||||||
|
url('^template/(?P<pk>\d+)/edit/', views.PartParameterTemplateEdit.as_view(), name='part-param-template-edit'),
|
||||||
|
url('^template/(?P<pk>\d+)/delete/', views.PartParameterTemplateDelete.as_view(), name='part-param-template-edit'),
|
||||||
|
|
||||||
url('^new/', views.PartParameterCreate.as_view(), name='part-param-create'),
|
url('^new/', views.PartParameterCreate.as_view(), name='part-param-create'),
|
||||||
url('^(?P<pk>\d+)/edit/', views.PartParameterEdit.as_view(), name='part-param-edit'),
|
url('^(?P<pk>\d+)/edit/', views.PartParameterEdit.as_view(), name='part-param-edit'),
|
||||||
|
@ -1446,6 +1446,21 @@ class PartParameterTemplateCreate(AjaxCreateView):
|
|||||||
ajax_form_title = 'Create Part Parameter Template'
|
ajax_form_title = 'Create Part Parameter Template'
|
||||||
|
|
||||||
|
|
||||||
|
class PartParameterTemplateEdit(AjaxUpdateView):
|
||||||
|
""" View for editing a PartParameterTemplate """
|
||||||
|
|
||||||
|
model = PartParameterTemplate
|
||||||
|
form_class = part_forms.EditPartParameterTemplateForm
|
||||||
|
ajax_form_title = 'Edit Part Parameter Template'
|
||||||
|
|
||||||
|
|
||||||
|
class PartParameterTemplateDelete(AjaxDeleteView):
|
||||||
|
""" View for deleting an existing PartParameterTemplate """
|
||||||
|
|
||||||
|
model = PartParameterTemplate
|
||||||
|
ajax_form_title = "Delete Part Parameter Template"
|
||||||
|
|
||||||
|
|
||||||
class PartParameterCreate(AjaxCreateView):
|
class PartParameterCreate(AjaxCreateView):
|
||||||
""" View for creating a new PartParameter """
|
""" View for creating a new PartParameter """
|
||||||
|
|
||||||
|
108
InvenTree/templates/InvenTree/settings/currency.html
Normal file
108
InvenTree/templates/InvenTree/settings/currency.html
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
{% extends "InvenTree/settings/settings.html" %}
|
||||||
|
|
||||||
|
{% block tabs %}
|
||||||
|
{% include "InvenTree/settings/tabs.html" with tab='currency' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block settings %}
|
||||||
|
|
||||||
|
<h4>Currencies</h4>
|
||||||
|
|
||||||
|
<div id='currency-buttons'>
|
||||||
|
<button class='btn btn-success' id='new-currency'>New Currency</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class='table table-striped table-condensed' id='currency-table' data-toolbar='#currency-buttons'>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js_ready %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
$("#currency-table").bootstrapTable({
|
||||||
|
url: "{% url 'api-currency-list' %}",
|
||||||
|
queryParams: {
|
||||||
|
ordering: 'suffix'
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
search: true,
|
||||||
|
pagination: true,
|
||||||
|
pageSize: 25,
|
||||||
|
formatNoMatches: function() { return "No currencies found"; },
|
||||||
|
rowStyle: function(row, index) {
|
||||||
|
if (row.base) {
|
||||||
|
return {classes: 'basecurrency'};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'pk',
|
||||||
|
title: 'ID',
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'symbol',
|
||||||
|
title: 'Symbol',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'suffix',
|
||||||
|
title: 'Currency',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'description',
|
||||||
|
title: 'Description',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'value',
|
||||||
|
title: 'Value',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
|
||||||
|
var bEdit = "<button title='Edit Currency' class='cur-edit btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='glyphicon glyphicon-edit'></span></button>";
|
||||||
|
var bDel = "<button title='Delete Currency' class='cur-delete btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='glyphicon glyphicon-trash'></span></button>";
|
||||||
|
|
||||||
|
var html = "<div class='btn-group' role='group'>" + bEdit + bDel + "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#currency-table").on('click', '.cur-edit', function() {
|
||||||
|
var button = $(this);
|
||||||
|
var url = "/common/currency/" + button.attr('pk') + "/edit/";
|
||||||
|
|
||||||
|
launchModalForm(url, {
|
||||||
|
success: function() {
|
||||||
|
$("#currency-table").bootstrapTable('refresh');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#currency-table").on('click', '.cur-delete', function() {
|
||||||
|
var button = $(this);
|
||||||
|
var url = "/common/currency/" + button.attr('pk') + "/delete/";
|
||||||
|
|
||||||
|
launchModalForm(url, {
|
||||||
|
success: function() {
|
||||||
|
$("#currency-table").bootstrapTable('refresh');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#new-currency").click(function() {
|
||||||
|
launchModalForm("{% url 'currency-create' %}", {
|
||||||
|
success: function() {
|
||||||
|
$("#currency-table").bootstrapTable('refresh');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
{% endblock %}
|
93
InvenTree/templates/InvenTree/settings/part.html
Normal file
93
InvenTree/templates/InvenTree/settings/part.html
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
{% extends "InvenTree/settings/settings.html" %}
|
||||||
|
|
||||||
|
{% block tabs %}
|
||||||
|
{% include "InvenTree/settings/tabs.html" with tab='part' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block settings %}
|
||||||
|
<h4>Part Parameter Templates</h4>
|
||||||
|
|
||||||
|
<div id='param-buttons'>
|
||||||
|
<button class='btn btn-success' id='new-param'>New Parameter</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class='table table-striped table-condensed' id='param-table' data-toolbar='#param-buttons'>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js_ready %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
$("#param-table").bootstrapTable({
|
||||||
|
url: "{% url 'api-part-param-template-list' %}",
|
||||||
|
queryParams: {
|
||||||
|
ordering: 'name',
|
||||||
|
},
|
||||||
|
sortable: true,
|
||||||
|
search: true,
|
||||||
|
pagination: true,
|
||||||
|
pageSize: 25,
|
||||||
|
formatNoMatches: function() { return "No part parameter templates found"; },
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'pk',
|
||||||
|
title: 'ID',
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: 'Name',
|
||||||
|
sortable: 'true',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'units',
|
||||||
|
title: 'Units',
|
||||||
|
sortable: 'true',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
var bEdit = "<button title='Edit Template' class='template-edit btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='glyphicon glyphicon-edit'></span></button>";
|
||||||
|
var bDel = "<button title='Delete Template' class='template-delete btn btn-default btn-glyph' type='button' pk='" + row.pk + "'><span class='glyphicon glyphicon-trash'></span></button>";
|
||||||
|
|
||||||
|
var html = "<div class='btn-group' role='group'>" + bEdit + bDel + "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#new-param").click(function() {
|
||||||
|
launchModalForm("{% url 'part-param-template-create' %}", {
|
||||||
|
success: function() {
|
||||||
|
$("#param-table").bootstrapTable('refresh');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#param-table").on('click', '.template-edit', function() {
|
||||||
|
var button = $(this);
|
||||||
|
|
||||||
|
var url = "/part/parameter/template/" + button.attr('pk') + "/edit/";
|
||||||
|
|
||||||
|
launchModalForm(url, {
|
||||||
|
success: function() {
|
||||||
|
$("#param-table").bootstrapTable('refresh');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#param-table").on('click', '.template-delete', function() {
|
||||||
|
var button = $(this);
|
||||||
|
|
||||||
|
var url = "/part/parameter/template/" + button.attr('pk') + "/delete/";
|
||||||
|
|
||||||
|
launchModalForm(url, {
|
||||||
|
success: function() {
|
||||||
|
$("#param-table").bootstrapTable('refresh');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
{% endblock %}
|
32
InvenTree/templates/InvenTree/settings/settings.html
Normal file
32
InvenTree/templates/InvenTree/settings/settings.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block page_title %}
|
||||||
|
InvenTree | Settings
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class='settings-container'>
|
||||||
|
|
||||||
|
<h3>InvenTree Settings</h3>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class='settings-nav'>
|
||||||
|
{% block tabs %}
|
||||||
|
{% include "InvenTree/settings/tabs.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='settings-content'>
|
||||||
|
{% block settings %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js_load %}
|
||||||
|
{{ block.super }}
|
||||||
|
{% endblock %}
|
11
InvenTree/templates/InvenTree/settings/tabs.html
Normal file
11
InvenTree/templates/InvenTree/settings/tabs.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<ul class='nav nav-pills nav-stacked'>
|
||||||
|
<li{% ifequal tab 'user' %} class='active'{% endifequal %}>
|
||||||
|
<a href="{% url 'settings-user' %}"><span class='glyphicon glyphicon-user'></span> User</a>
|
||||||
|
</li>
|
||||||
|
<li{% ifequal tab 'currency' %} class='active'{% endifequal %}>
|
||||||
|
<a href="{% url 'settings-currency' %}"><span class='glyphicon glyphicon-usd'></span> Currency</a>
|
||||||
|
</li>
|
||||||
|
<li{% ifequal tab 'part' %} class='active'{% endifequal %}>
|
||||||
|
<a href="{% url 'settings-part' %}"><span class='glyphicon glyphicon-briefcase'></span> Part</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
@ -1,12 +1,10 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "InvenTree/settings/settings.html" %}
|
||||||
|
|
||||||
{% block page_title %}
|
{% block tabs %}
|
||||||
InvenTree | Settings
|
{% include "InvenTree/settings/tabs.html" with tab='user' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block settings %}
|
||||||
<h3>InvenTree Settings</h3>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div class='row'>
|
<div class='row'>
|
||||||
<div class='col-sm-6'>
|
<div class='col-sm-6'>
|
||||||
@ -18,8 +16,7 @@ InvenTree | Settings
|
|||||||
<div class='btn btn-primary' type='button' id='edit-password' title='Change Password'>Set Password</div>
|
<div class='btn btn-primary' type='button' id='edit-password' title='Change Password'>Set Password</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<table class='table table-striped table-condensed'>
|
<table class='table table-striped table-condensed'>
|
||||||
<tr>
|
<tr>
|
||||||
@ -38,10 +35,6 @@ InvenTree | Settings
|
|||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_load %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block js_ready %}
|
{% block js_ready %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
@ -1,10 +1,12 @@
|
|||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from .serializers import UserSerializer
|
from .serializers import UserSerializer
|
||||||
|
|
||||||
from rest_framework.authtoken.views import ObtainAuthToken
|
from rest_framework.authtoken.views import ObtainAuthToken
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
|
||||||
class UserDetail(generics.RetrieveAPIView):
|
class UserDetail(generics.RetrieveAPIView):
|
||||||
@ -27,15 +29,30 @@ class GetAuthToken(ObtainAuthToken):
|
|||||||
""" Return authentication token for an authenticated user. """
|
""" Return authentication token for an authenticated user. """
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
return self.login(request)
|
||||||
|
|
||||||
|
def delete(self, request):
|
||||||
|
return self.logout(request)
|
||||||
|
|
||||||
|
def login(self, request):
|
||||||
serializer = self.serializer_class(data=request.data,
|
serializer = self.serializer_class(data=request.data,
|
||||||
context={'request': request})
|
context={'request': request})
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
user = serializer.validated_data['user']
|
user = serializer.validated_data['user']
|
||||||
token, created = Token.objects.get_or_create(user=user)
|
token, created = Token.objects.get_or_create(user=user)
|
||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'token': token.key,
|
'token': token.key,
|
||||||
'pk': user.pk,
|
'pk': user.pk,
|
||||||
'username': user.username,
|
'username': user.username,
|
||||||
'email': user.email
|
'email': user.email
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def logout(self, request):
|
||||||
|
try:
|
||||||
|
request.user.auth_token.delete()
|
||||||
|
return Response({"success": "Successfully logged out."},
|
||||||
|
status=status.HTTP_202_ACCEPTED)
|
||||||
|
except (AttributeError, ObjectDoesNotExist):
|
||||||
|
return Response({"error": "Bad request"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
Loading…
Reference in New Issue
Block a user