Compare commits

..

3 commits

59 changed files with 1192 additions and 274 deletions

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
__pycache__ __pycache__
.python_version .python_version
*.egg-info *.egg-info
*.mo
media/ media/
./static/ ./static/

View file

@ -28,9 +28,16 @@ following might sound familiar:
- ForgeJo: `git clone https://git.dunkelstern.de/dunkelstern/inventory.git` - ForgeJo: `git clone https://git.dunkelstern.de/dunkelstern/inventory.git`
2. Change to checkout: `cd inventory` 2. Change to checkout: `cd inventory`
3. Install virtualenv and dependencies: `poetry install --no-root` 3. Install virtualenv and dependencies: `poetry install --no-root`
4. Migrate the Database: `poetry run python manage.py migrate` 4. If you want to use the system in another language than the default english set it
5. Create an admin user: `poetry run python manage.py createsuperuser` up in the `inventory_project/settings.py`:
6. Run the server ```python
LANGUAGE_CODE = 'en-us' # or something like 'de-de'
```
see the settings file for defined languages.
5. If you changed the language rebuild the translation files: `poetry run python manage.py compilemessages`
6. Migrate the Database: `poetry run python manage.py migrate`
7. Create an admin user: `poetry run python manage.py createsuperuser`
8. Run the server
- Development server (not for deployment!): `poetry run python manage.py runserver` - Development server (not for deployment!): `poetry run python manage.py runserver`
- Deployment via `gunicorn` on port 8000: `poetry run gunicorn inventory_project.wsgi -b 0.0.0.0:8000` - Deployment via `gunicorn` on port 8000: `poetry run gunicorn inventory_project.wsgi -b 0.0.0.0:8000`
@ -51,6 +58,16 @@ go to `http://localhost:8000` to enter the inventory management system directly
[the service file](inventory.service) in the root of this repository for an [the service file](inventory.service) in the root of this repository for an
example. example.
### Changelog
#### 1.1
- Part count can be configured to be available in settings
- Currency can be configured in settings
- Complete system is translateable (English and German are provided)
![Settings](docs/settings.jpeg)
### Screenshots ### Screenshots
#### Login #### Login

BIN
docs/settings.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View file

@ -3,7 +3,7 @@ from django.shortcuts import redirect
from django.contrib import admin from django.contrib import admin
from django.conf import settings from django.conf import settings
from inventory.models import Item, Documentation from inventory.models import Item, Documentation, Settings
class DocumentationAdmin(admin.ModelAdmin): class DocumentationAdmin(admin.ModelAdmin):
@ -19,6 +19,12 @@ class ItemAdmin(admin.ModelAdmin):
readonly_fields = ['created_at', 'changed_at'] readonly_fields = ['created_at', 'changed_at']
filter_horizontal = ('tags', 'documentation') filter_horizontal = ('tags', 'documentation')
def get_exclude(self, request, obj=None):
s = Settings.objects.first()
if (s.track_amount):
return self.exclude
return (self.exclude or tuple()) + ('count', 'low_count')
def view_on_site(self, obj): def view_on_site(self, obj):
url = reverse('item-detail', kwargs={'pk': obj.id}) url = reverse('item-detail', kwargs={'pk': obj.id})
return settings.SERVER_URL + url return settings.SERVER_URL + url

View file

@ -0,0 +1,561 @@
# Translation for Inventory management system
# Copyright (C) 2025 Johannes Schriewer
# This file is distributed under the same license as the Inventory package.
# Johannes Schriewer <hallo@dunkelstern.de>, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-07 23:07+0100\n"
"PO-Revision-Date: 2025-01-07 23:00+0100\n"
"Last-Translator: Johannes Schriewer <hallo@dunkelstern.de>\n"
"Language: German\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\inventory\models\area.py:8 .\inventory\models\box.py:10
#: .\inventory\models\distributor.py:6 .\inventory\models\documentation.py:6
#: .\inventory\models\form_factor.py:6 .\inventory\models\item.py:8
#: .\inventory\models\layout.py:6 .\inventory\models\manufacturer.py:6
#: .\inventory\models\tag.py:6 .\inventory\models\workshop.py:8
#: .\inventory\templates\inventory\distributor_detail.html:26
#: .\inventory\templates\inventory\item_detail.html:27
#: .\inventory\templates\inventory\item_list.html:7
#: .\inventory\templates\inventory\manufacturer_detail.html:26
msgid "Name"
msgstr "Name"
#: .\inventory\models\area.py:9 .\inventory\models\box.py:11
#: .\inventory\models\distributor.py:7 .\inventory\models\form_factor.py:7
#: .\inventory\models\item.py:9 .\inventory\models\layout.py:7
#: .\inventory\models\manufacturer.py:7 .\inventory\models\tag.py:7
#: .\inventory\models\workshop.py:9
#: .\inventory\templates\inventory\distributor_detail.html:30
#: .\inventory\templates\inventory\item_detail.html:31
#: .\inventory\templates\inventory\item_list.html:9
#: .\inventory\templates\inventory\manufacturer_detail.html:30
msgid "Description"
msgstr "Beschreibung"
#: .\inventory\models\area.py:11
msgid "Show sub area"
msgstr "Unterbereiche anzeigen"
#: .\inventory\models\area.py:13
msgid "Allow sub-areas to be defined in this area"
msgstr "Erlaube Unterbereiche in diesem Bereich"
#: .\inventory\models\area.py:15 .\inventory\models\box.py:14
#: .\inventory\models\distributor.py:16 .\inventory\models\documentation.py:7
#: .\inventory\models\form_factor.py:13 .\inventory\models\item.py:76
#: .\inventory\models\layout.py:8 .\inventory\models\manufacturer.py:13
#: .\inventory\models\tag.py:8 .\inventory\models\workshop.py:17
#: .\inventory\templates\inventory\distributor_detail.html:89
#: .\inventory\templates\inventory\item_detail.html:128
#: .\inventory\templates\inventory\manufacturer_detail.html:57
msgid "Created at"
msgstr "Erstellt am"
#: .\inventory\models\area.py:16 .\inventory\models\box.py:15
#: .\inventory\models\distributor.py:17 .\inventory\models\documentation.py:8
#: .\inventory\models\form_factor.py:14 .\inventory\models\item.py:77
#: .\inventory\models\layout.py:9 .\inventory\models\manufacturer.py:14
#: .\inventory\models\tag.py:9 .\inventory\models\workshop.py:18
#: .\inventory\templates\inventory\distributor_detail.html:91
#: .\inventory\templates\inventory\item_detail.html:130
#: .\inventory\templates\inventory\manufacturer_detail.html:59
msgid "Changed at"
msgstr "Geändert am"
#: .\inventory\models\area.py:24
msgid "Area"
msgstr "Bereich"
#: .\inventory\models\area.py:25
#: .\inventory\templates\inventory\area_detail.html:25
#: .\inventory\templates\inventory\workshop_detail.html:23
msgid "Areas"
msgstr "Bereiche"
#: .\inventory\models\box.py:12 .\inventory\models\distributor.py:14
#: .\inventory\models\form_factor.py:11 .\inventory\models\item.py:58
#: .\inventory\models\manufacturer.py:11 .\inventory\models\tag.py:17
#: .\inventory\models\workshop.py:15 .\inventory\templates\base.html:58
#: .\inventory\templates\inventory\distributor_detail.html:77
#: .\inventory\templates\inventory\item_detail.html:54
#: .\inventory\templates\inventory\manufacturer_detail.html:45
#: .\inventory\templates\inventory\tag_list.html:9
msgid "Tags"
msgstr "Tags"
#: .\inventory\models\box.py:35
msgid "Box"
msgstr "Kisten"
#: .\inventory\models\box.py:36
#: .\inventory\templates\inventory\box-generic.html:7
#: .\inventory\templates\inventory\tag_detail.html:43
msgid "Boxes"
msgstr "Kisten"
#: .\inventory\models\container.py:9 .\inventory\models\layout.py:18
msgid "Layout"
msgstr "Layout"
#: .\inventory\models\container.py:35 .\inventory\models\container.py:45
#: .\inventory\models\container.py:51
#: .\inventory\templates\inventory\item_list.html:10
msgid "Container"
msgstr "Behälter"
#: .\inventory\models\container.py:46
#: .\inventory\templates\inventory\area_detail.html:51
#: .\inventory\templates\inventory\workshop_detail.html:49
msgid "Containers"
msgstr "Behälter"
#: .\inventory\models\container.py:56
msgid "Index of compartment in layout"
msgstr "Index des Abteils im Layout"
#: .\inventory\models\distributor.py:9 .\inventory\models\manufacturer.py:9
#: .\inventory\templates\inventory\distributor_detail.html:40
#: .\inventory\templates\inventory\manufacturer_detail.html:40
msgid "Web link"
msgstr "Web link"
#: .\inventory\models\distributor.py:10
#: .\inventory\templates\inventory\item_detail.html:121
msgid "Search link"
msgstr "Such-link"
#: .\inventory\models\distributor.py:10
msgid "Use {} for search placeholder"
msgstr "Benutze {} oder {0} als Platzhalter"
#: .\inventory\models\distributor.py:11
#: .\inventory\templates\inventory\distributor_detail.html:65
msgid "Phone"
msgstr "Telefon"
#: .\inventory\models\distributor.py:12
#: .\inventory\templates\inventory\distributor_detail.html:71
msgid "E-Mail"
msgstr "E-Mail"
#: .\inventory\models\distributor.py:13 .\inventory\models\form_factor.py:9
#: .\inventory\models\manufacturer.py:10
#: .\inventory\templates\inventory\distributor_detail.html:35
#: .\inventory\templates\inventory\distributor_list.html:15
#: .\inventory\templates\inventory\manufacturer_detail.html:35
#: .\inventory\templates\inventory\manufacturer_list.html:15
msgid "Icon"
msgstr "Symbol"
#: .\inventory\models\distributor.py:24 .\inventory\models\item.py:31
#: .\inventory\templates\inventory\distributor_detail.html:6
#: .\inventory\templates\inventory\distributor_detail.html:10
#: .\inventory\templates\inventory\distributor_list.html:16
#: .\inventory\templates\inventory\item_detail.html:96
#: .\inventory\templates\inventory\item_list.html:15
msgid "Distributor"
msgstr "Händler"
#: .\inventory\models\distributor.py:25 .\inventory\templates\base.html:55
#: .\inventory\templates\inventory\distributor_list.html:5
#: .\inventory\templates\inventory\distributor_list.html:8
#: .\inventory\templates\inventory\tag_detail.html:63
msgid "Distributors"
msgstr "Händler"
#: .\inventory\models\documentation.py:17
#: .\inventory\models\documentation.py:18 .\inventory\models\item.py:52
#: .\inventory\templates\inventory\item_detail.html:135
msgid "Documentation"
msgstr "Dokumentation"
#: .\inventory\models\form_factor.py:10
#: .\inventory\templates\inventory\cell.html:16
#: .\inventory\templates\inventory\item_list.html:25
#: .\inventory\templates\inventory\search_result_item.html:6
msgid "Datasheet"
msgstr "Datenblatt"
#: .\inventory\models\form_factor.py:23 .\inventory\models\item.py:17
#: .\inventory\templates\inventory\item_detail.html:68
msgid "Form factor"
msgstr "Formfaktor"
#: .\inventory\models\form_factor.py:24
#: .\inventory\templates\inventory\tag_detail.html:121
msgid "Form factors"
msgstr "Formfaktoren"
#: .\inventory\models\item.py:11
msgid "Size"
msgstr "Größe"
#: .\inventory\models\item.py:13
msgid "Number of sub-compartments this item takes up"
msgstr "Anzahl der Unterteilungen die dieses Teil benötigt"
#: .\inventory\models\item.py:24 .\inventory\models\manufacturer.py:21
#: .\inventory\templates\inventory\item_detail.html:85
#: .\inventory\templates\inventory\item_list.html:12
#: .\inventory\templates\inventory\manufacturer_detail.html:6
#: .\inventory\templates\inventory\manufacturer_detail.html:10
#: .\inventory\templates\inventory\manufacturer_list.html:16
msgid "Manufacturer"
msgstr "Hersteller"
#: .\inventory\models\item.py:37
msgid "Distributor item no."
msgstr "Händler Bestellnummer"
#: .\inventory\models\item.py:43
#: .\inventory\templates\inventory\item_detail.html:107
msgid "Price"
msgstr "Preis"
#: .\inventory\models\item.py:49
msgid "Last ordered on"
msgstr "Zuletzt bestellt am"
#: .\inventory\models\item.py:63
msgid "Count"
msgstr "Anzahl"
#: .\inventory\models\item.py:66
msgid "Number of parts available"
msgstr "Anzahl der verfügbaren Teile"
#: .\inventory\models\item.py:69
#: .\inventory\templates\inventory\item_detail.html:49
msgid "Low watermark"
msgstr "Bestellgrenze"
#: .\inventory\models\item.py:72
msgid "Low watermark on which to alert ordering more"
msgstr "Untere Grenze ab der das Teil nachbestellt werden soll"
#: .\inventory\models\item.py:75
msgid "Custom metadata, used by templates"
msgstr "Metadaten die in der Vorlage verwendet werden können"
#: .\inventory\models\item.py:98
msgid "Item"
msgstr "Teil"
#: .\inventory\models\item.py:99
#: .\inventory\templates\inventory\box-generic.html:16
#: .\inventory\templates\inventory\manufacturer_detail.html:64
#: .\inventory\templates\inventory\tag_detail.html:113
msgid "Items"
msgstr "Teile"
#: .\inventory\models\layout.py:10
msgid "Data"
msgstr "Konfiguration"
#: .\inventory\models\layout.py:11
msgid "Template name"
msgstr "Vorlage"
#: .\inventory\models\layout.py:19
msgid "Layouts"
msgstr "Layouts"
#: .\inventory\models\manufacturer.py:22 .\inventory\templates\base.html:52
#: .\inventory\templates\inventory\manufacturer_list.html:5
#: .\inventory\templates\inventory\manufacturer_list.html:8
#: .\inventory\templates\inventory\tag_detail.html:88
msgid "Manufacturers"
msgstr "Hersteller"
#: .\inventory\models\settings.py:13
msgid "Default container to display when calling the index page"
msgstr "Standardbehälter der beim Aufruf der Index-Seite gezeigt werden soll"
#: .\inventory\models\settings.py:17
msgid "Show item count in overview and warn on low watermarks"
msgstr "Aktiviere die Mengenangaben und Nachbestellgrenzen"
#: .\inventory\models\settings.py:19
msgid "Currency"
msgstr "Währung"
#: .\inventory\models\settings.py:19
msgid "Currency name"
msgstr "Name der Währung"
#: .\inventory\models\settings.py:20
msgid "Currency symbol"
msgstr "Währungssymbol"
#: .\inventory\models\settings.py:22
msgid "Currency symbol at end"
msgstr "Währungssymbol am Ende"
#: .\inventory\models\settings.py:24
msgid "Currency symbol after amount"
msgstr "Zeige das Währungssymbol nach der Zahl an"
#: .\inventory\models\settings.py:28 .\inventory\models\settings.py:31
#: .\inventory\models\settings.py:32
msgid "Settings"
msgstr "Einstellungen"
#: .\inventory\models\tag.py:16
#: .\inventory\templates\inventory\tag_detail.html:5
msgid "Tag"
msgstr "Tag"
#: .\inventory\models\workshop.py:11
msgid "Show boxes"
msgstr "Behälter anzeigen"
#: .\inventory\models\workshop.py:13
msgid "Allow boxes to be defined directly in this workshop"
msgstr "Erlaube Behälter in dieser Werkstatt"
#: .\inventory\models\workshop.py:26 .\inventory\templates\base.html:61
#: .\inventory\templates\inventory\workshop_detail.html:5
msgid "Workshop"
msgstr "Werkstatt"
#: .\inventory\models\workshop.py:27
#: .\inventory\templates\inventory\tag_detail.html:23
#: .\inventory\templates\inventory\workshop_list.html:5
#: .\inventory\templates\inventory\workshop_list.html:8
msgid "Workshops"
msgstr "Werkstätten"
#: .\inventory\templates\base.html:43 .\inventory\templates\base.html:46
#: .\inventory\templates\base.html:47
#: .\inventory\templates\inventory\distributor_detail.html:45
#: .\inventory\templates\inventory\distributor_detail.html:58
#: .\inventory\templates\inventory\search.html:5
#: .\inventory\templates\inventory\search.html:8
#: .\inventory\templates\inventory\search.html:13
#: .\inventory\templates\inventory\search.html:14
#: .\inventory\templates\inventory\search_result.html:6
#: .\inventory\templates\inventory\search_result.html:9
#: .\inventory\templates\inventory\search_result.html:14
#: .\inventory\templates\inventory\search_result.html:15
#: .\inventory\templates\inventory\tag_list.html:43
#: .\inventory\templates\inventory\tag_list.html:44
msgid "Search"
msgstr "Suchen"
#: .\inventory\templates\base.html:68
msgid "Logout"
msgstr "Ausloggen"
#: .\inventory\templates\inventory\area_detail.html:16
#: .\inventory\templates\inventory\area_detail.html:36
#: .\inventory\templates\inventory\area_detail.html:62
#: .\inventory\templates\inventory\box-detail.html:20
#: .\inventory\templates\inventory\cell.html:19
#: .\inventory\templates\inventory\distributor_detail.html:17
#: .\inventory\templates\inventory\distributor_list.html:33
#: .\inventory\templates\inventory\item_detail.html:18
#: .\inventory\templates\inventory\item_list.html:28
#: .\inventory\templates\inventory\manufacturer_detail.html:17
#: .\inventory\templates\inventory\manufacturer_list.html:33
#: .\inventory\templates\inventory\tag_detail.html:16
#: .\inventory\templates\inventory\tag_detail.html:33
#: .\inventory\templates\inventory\tag_detail.html:53
#: .\inventory\templates\inventory\tag_detail.html:78
#: .\inventory\templates\inventory\tag_detail.html:103
#: .\inventory\templates\inventory\workshop_detail.html:16
#: .\inventory\templates\inventory\workshop_detail.html:34
#: .\inventory\templates\inventory\workshop_detail.html:59
#: .\inventory\templates\inventory\workshop_list.html:21
msgid "Edit"
msgstr "Bearbeiten"
#: .\inventory\templates\inventory\area_detail.html:41
#: .\inventory\templates\inventory\workshop_detail.html:39
msgid "No areas defined"
msgstr "Keine Bereiche definiert"
#: .\inventory\templates\inventory\area_detail.html:47
#: .\inventory\templates\inventory\workshop_detail.html:45
msgid "Create new area..."
msgstr "Neuen Bereich anlegen..."
#: .\inventory\templates\inventory\area_detail.html:67
#: .\inventory\templates\inventory\workshop_detail.html:64
msgid "No containers defined"
msgstr "Keine Behälter definiert..."
#: .\inventory\templates\inventory\area_detail.html:73
#: .\inventory\templates\inventory\workshop_detail.html:70
msgid "Create new container..."
msgstr "Neuen Behälter anlegen..."
#: .\inventory\templates\inventory\box-detail.html:12
#: .\inventory\templates\inventory\distributor_detail.html:9
#: .\inventory\templates\inventory\item_detail.html:10
#: .\inventory\templates\inventory\manufacturer_detail.html:9
#: .\inventory\templates\inventory\tag_detail.html:8
#: .\inventory\templates\inventory\workshop_detail.html:8
msgid "Back"
msgstr "Zurück"
#: .\inventory\templates\inventory\cell.html:21
msgid "Details"
msgstr "Details"
#: .\inventory\templates\inventory\cell.html:26
#: .\inventory\templates\inventory\item_detail.html:42
msgid "Low stock"
msgstr "Wenig Vorrat"
#: .\inventory\templates\inventory\cell.html:43
msgid "New item..."
msgstr "Neues Teil..."
#: .\inventory\templates\inventory\distributor_detail.html:57
msgid "Search query"
msgstr "Suchanfrage"
#: .\inventory\templates\inventory\distributor_detail.html:83
#: .\inventory\templates\inventory\item_detail.html:60
#: .\inventory\templates\inventory\manufacturer_detail.html:51
#: .\inventory\templates\inventory\tag_list.html:50
msgid "No tags"
msgstr "Keine Tags"
#: .\inventory\templates\inventory\distributor_list.html:8
#: .\inventory\templates\inventory\tag_list.html:9
#: .\inventory\templates\inventory\workshop_list.html:8
#: .\inventory\templates\registration\login.html:5
msgid "Inventory management"
msgstr "Inventarverwaltung"
#: .\inventory\templates\inventory\distributor_list.html:43
msgid "Create new distributor..."
msgstr "Neuen Händler anlegen..."
#: .\inventory\templates\inventory\item_detail.html:36
#: .\inventory\templates\inventory\item_detail.html:45
msgid "Amount"
msgstr "Anzahl"
#: .\inventory\templates\inventory\item_detail.html:46
msgid "Update"
msgstr "Speichern"
#: .\inventory\templates\inventory\item_detail.html:108
msgid "Sum"
msgstr "Summe"
#: .\inventory\templates\inventory\item_detail.html:114
msgid "Last ordered"
msgstr "Zuletzt bestellt"
#: .\inventory\templates\inventory\manufacturer_list.html:8
msgid "Inventory Management"
msgstr "Inventarverwaltung"
#: .\inventory\templates\inventory\manufacturer_list.html:42
msgid "Create new manufacturer..."
msgstr "Neuen Hersteller anlegen..."
#: .\inventory\templates\inventory\pagination.html:6
#: .\inventory\templates\inventory\search_result.html:33
msgid "First page"
msgstr "Erste Seite"
#: .\inventory\templates\inventory\pagination.html:7
#: .\inventory\templates\inventory\search_result.html:34
msgid "Previous page"
msgstr "Vorherige Seite"
#: .\inventory\templates\inventory\pagination.html:13
#: .\inventory\templates\inventory\search_result.html:38
msgid "Next page"
msgstr "Nächste Seite"
#: .\inventory\templates\inventory\pagination.html:14
#: .\inventory\templates\inventory\search_result.html:39
msgid "Last page"
msgstr "Letzte Seite"
#: .\inventory\templates\inventory\search_result.html:18
msgid "Search result for"
msgstr "Suchergebnisse für"
#: .\inventory\templates\inventory\search_result.html:27
msgid "Nothing found"
msgstr "Nichts gefunden"
#: .\inventory\templates\inventory\search_result_item.html:11
msgid "Contained in"
msgstr "Im Behälter"
#: .\inventory\templates\inventory\set_index.html:10
msgid "Currently set as index page"
msgstr "Momentan als Index-Seite definiert"
#: .\inventory\templates\inventory\set_index.html:12
msgid "Promote to index page"
msgstr "Als Index-Seite definieren"
#: .\inventory\templates\inventory\tag_list.html:55
msgid "Create new tag..."
msgstr "Neues Tag anlegen..."
#: .\inventory\templates\inventory\workshop_list.html:30
msgid "Create new workshop..."
msgstr "Neue Werkstatt anlegen..."
#: .\inventory\templates\registration\login.html:5
msgid "Login"
msgstr "Einloggen"
#: .\inventory\templates\registration\login.html:11
msgid "Your username and password didn't match. Please try again."
msgstr ""
"Benutzername und Passwort passen nicht zusammen, bitte versuche es noch "
"einmal."
#: .\inventory\templates\registration\login.html:17
msgid ""
"\n"
" Your account doesn't have access to this page. To proceed,\n"
" please login with an account that has access.\n"
" "
msgstr ""
"\n"
" Dein Zugang hat keinen Zugriff auf diese Seite.\n"
" Zum Fortfahren bitte mit einem Zugang einloggen der die\n"
" entsprechenden Rechte besitzt!\n"
" "
#: .\inventory\templates\registration\login.html:24
msgid ""
"\n"
" Please login to see this page.\n"
" "
msgstr ""
"\n"
" Bitte einloggen um auf diese Seite Zugriff zu bekommen.\n"
" "
#: .\inventory\templates\registration\login.html:49
msgid "Lost password?"
msgstr "Passwort vergessen?"
#: .\inventory_project\settings.py:121
msgid "German"
msgstr "Deutsch"
#: .\inventory_project\settings.py:122
msgid "English"
msgstr "Englisch"

View file

@ -0,0 +1,23 @@
# Generated by Django 5.1.4 on 2025-01-07 17:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0005_alter_sorting_collation'),
]
operations = [
migrations.AddField(
model_name='item',
name='count',
field=models.PositiveIntegerField(default=1, help_text='Number of parts available'),
),
migrations.AddField(
model_name='item',
name='low_count',
field=models.PositiveIntegerField(default=0, help_text='Low watermark on which to alert ordering more'),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-01-07 17:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_item_count_item_low_count'),
]
operations = [
migrations.AddField(
model_name='settings',
name='track_amount',
field=models.BooleanField(default=False, help_text='Show item count in overview and warn on low watermarks'),
),
]

View file

@ -0,0 +1,28 @@
# Generated by Django 5.1.4 on 2025-01-07 18:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0007_settings_track_amount'),
]
operations = [
migrations.AddField(
model_name='settings',
name='currency',
field=models.CharField(default='Euro', help_text='Currency name', max_length=30),
),
migrations.AddField(
model_name='settings',
name='currency_symbol',
field=models.CharField(default='&euro;', help_text='Currency symbol', max_length=20),
),
migrations.AddField(
model_name='settings',
name='currency_symbol_position',
field=models.BooleanField(default=True, help_text='Currency symbol after amount'),
),
]

View file

@ -1,14 +1,19 @@
from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.db import models from django.db import models
from .container import Container, CanBeContained from .container import Container, CanBeContained
class Area(CanBeContained, Container): class Area(CanBeContained, Container):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
description = models.CharField(max_length=4096) description = models.CharField(_("Description"), max_length=4096)
show_sub_area = models.BooleanField(default=True, help_text="Allow sub-areas to be defined in this area") show_sub_area = models.BooleanField(
created_at = models.DateTimeField(auto_now_add=True) _("Show sub area"),
changed_at = models.DateTimeField(auto_now=True) default=True,
help_text=_("Allow sub-areas to be defined in this area")
)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
@property @property
def url(self): def url(self):
@ -16,3 +21,5 @@ class Area(CanBeContained, Container):
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Area")
verbose_name_plural = _("Areas")

View file

@ -1,3 +1,4 @@
from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.utils.text import slugify from django.utils.text import slugify
from django.template.loader import get_template, TemplateDoesNotExist from django.template.loader import get_template, TemplateDoesNotExist
@ -6,15 +7,12 @@ from .container import CanBeContained, Container
class Box(CanBeContained, Container): class Box(CanBeContained, Container):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
description = models.CharField(max_length=4096) description = models.CharField(_("Description"), max_length=4096)
tags = models.ManyToManyField('inventory.Tag', blank=True) tags = models.ManyToManyField('inventory.Tag', verbose_name=_("Tags"), blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
class Meta:
verbose_name_plural = 'Boxes'
@property @property
def template_name(self): def template_name(self):
@ -34,3 +32,5 @@ class Box(CanBeContained, Container):
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Box")
verbose_name_plural = _("Boxes")

View file

@ -1,9 +1,16 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from django.apps import apps from django.apps import apps
class Container(models.Model): class Container(models.Model):
layout = models.ForeignKey('inventory.Layout', on_delete=models.PROTECT, null=True, blank=True) layout = models.ForeignKey(
'inventory.Layout',
verbose_name=_("Layout"),
on_delete=models.PROTECT,
null=True,
blank=True
)
@property @property
def subclass(self): def subclass(self):
@ -25,7 +32,7 @@ class Container(models.Model):
_, obj = self.subclass _, obj = self.subclass
if obj is not None: if obj is not None:
return obj.name return obj.name
return 'Container' return _("Container")
@property @property
def url(self): def url(self):
@ -34,15 +41,19 @@ class Container(models.Model):
return obj.url return obj.url
return None return None
class Meta:
verbose_name = _("Container")
verbose_name_plural = _("Containers")
class CanBeContained(models.Model): class CanBeContained(models.Model):
container = models.ForeignKey( container = models.ForeignKey(
'inventory.Container', 'inventory.Container',
verbose_name=_("Container"),
related_name="%(class)s_related", related_name="%(class)s_related",
null=True, null=True,
on_delete=models.CASCADE on_delete=models.CASCADE
) )
index = models.PositiveIntegerField('Index of compartment in layout') index = models.PositiveIntegerField(_("Index of compartment in layout"))
class Meta: class Meta:
abstract = True abstract = True

View file

@ -1,22 +1,25 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
class Distributor(models.Model): class Distributor(models.Model):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
description = models.CharField(max_length=4096) description = models.CharField(_("Description"), max_length=4096)
web_link = models.URLField(null=True, blank=True) web_link = models.URLField(_("Web link"), null=True, blank=True)
search_link = models.URLField(help_text='Use {} for search placeholder', null=True, blank=True) search_link = models.URLField(_("Search link"), help_text=_("Use {} for search placeholder"), null=True, blank=True)
phone = models.CharField(max_length=128, null=True, blank=True) phone = models.CharField(_("Phone"), max_length=128, null=True, blank=True)
email = models.EmailField(null=True, blank=True, default=None) email = models.EmailField(_("E-Mail"), null=True, blank=True, default=None)
icon = models.ImageField(null=True, blank=True) icon = models.ImageField(_("Icon"), null=True, blank=True)
tags = models.ManyToManyField('inventory.Tag', blank=True) tags = models.ManyToManyField('inventory.Tag', verbose_name=_("Tags"), blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
def __str__(self): def __str__(self):
return self.name return self.name
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Distributor")
verbose_name_plural = _("Distributors")

View file

@ -1,10 +1,11 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
class Documentation(models.Model): class Documentation(models.Model):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
file = models.FileField() file = models.FileField()
@ -13,3 +14,5 @@ class Documentation(models.Model):
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Documentation")
verbose_name_plural = _("Documentation")

View file

@ -1,16 +1,17 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
class FormFactor(models.Model): class FormFactor(models.Model):
name = models.CharField(max_length=255, unique=True, db_collation="numeric") name = models.CharField(_("Name"), max_length=255, unique=True, db_collation="numeric")
description = models.CharField(max_length=4096, db_collation="numeric") description = models.CharField(_("Description"), max_length=4096, db_collation="numeric")
icon = models.ImageField(null=True, blank=True) icon = models.ImageField(_("Icon"), null=True, blank=True)
datasheet = models.FileField(null=True, blank=True) datasheet = models.FileField(_("Datasheet"), null=True, blank=True)
tags = models.ManyToManyField('inventory.Tag', blank=True) tags = models.ManyToManyField('inventory.Tag', verbose_name=_("Tags"), blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
def __str__(self): def __str__(self):
items = [self.name] items = [self.name]
@ -19,3 +20,5 @@ class FormFactor(models.Model):
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Form factor")
verbose_name_plural = _("Form factors")

View file

@ -1,24 +1,80 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
from .container import CanBeContained from .container import CanBeContained
class Item(CanBeContained): class Item(CanBeContained):
name = models.TextField(max_length=255, db_collation="numeric") name = models.TextField(_("Name"), max_length=255, db_collation="numeric")
description = models.CharField(max_length=4096, db_collation="numeric") description = models.CharField(_("Description"), max_length=4096, db_collation="numeric")
size = models.PositiveIntegerField(default=1, help_text="Number of sub-compartments this item takes up") size = models.PositiveIntegerField(
form_factor = models.ForeignKey('inventory.FormFactor', null=True, blank=True, on_delete=models.PROTECT) _("Size"),
manufacturer = models.ForeignKey('inventory.Manufacturer', null=True, blank=True, on_delete=models.PROTECT) default=1,
distributor = models.ForeignKey('inventory.Distributor', null=True, blank=True, on_delete=models.PROTECT) help_text=_("Number of sub-compartments this item takes up")
distributor_item_no = models.CharField(max_length=255, null=True, blank=True) )
price = models.DecimalField(decimal_places=3, max_digits=7, null=True, blank=True) form_factor = models.ForeignKey(
last_ordered_on = models.DateField(null=True, blank=True) 'inventory.FormFactor',
documentation = models.ManyToManyField('inventory.Documentation', related_name='items', blank=True) verbose_name=_("Form factor"),
tags = models.ManyToManyField('inventory.Tag', blank=True) null=True,
blank=True,
on_delete=models.PROTECT
)
manufacturer = models.ForeignKey(
'inventory.Manufacturer',
verbose_name=_("Manufacturer"),
null=True,
blank=True,
on_delete=models.PROTECT
)
distributor = models.ForeignKey(
'inventory.Distributor',
verbose_name=_("Distributor"),
null=True,
blank=True,
on_delete=models.PROTECT
)
distributor_item_no = models.CharField(
_("Distributor item no."),
max_length=255,
null=True,
blank=True
)
price = models.DecimalField(
_("Price"),
decimal_places=3,
max_digits=7,
null=True,
blank=True
)
last_ordered_on = models.DateField(_("Last ordered on"), null=True, blank=True)
documentation = models.ManyToManyField(
'inventory.Documentation',
verbose_name=_("Documentation"),
related_name='items',
blank=True
)
tags = models.ManyToManyField(
'inventory.Tag',
verbose_name=_("Tags"),
blank=True
)
metadata = models.JSONField('Custom metadata, used by templates', blank=True, null=True) count = models.PositiveIntegerField(
created_at = models.DateTimeField(auto_now_add=True) _("Count"),
changed_at = models.DateTimeField(auto_now=True) default=1,
null=False,
help_text=_("Number of parts available")
)
low_count = models.PositiveIntegerField(
_("Low watermark"),
default=0,
null=False,
help_text=_("Low watermark on which to alert ordering more")
)
metadata = models.JSONField(_("Custom metadata, used by templates"), blank=True, null=True)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
def __str__(self): def __str__(self):
items = [self.name, self.description] items = [self.name, self.description]
@ -32,6 +88,12 @@ class Item(CanBeContained):
return list(self.tags.all()) + list(self.form_factor.tags.all()) return list(self.tags.all()) + list(self.form_factor.tags.all())
else: else:
return list(self.tags.all()) return list(self.tags.all())
@property
def value(self):
return self.count * self.price
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Item")
verbose_name_plural = _("Items")

View file

@ -1,16 +1,19 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
class Layout(models.Model): class Layout(models.Model):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
description = models.CharField(max_length=4096) description = models.CharField(_("Description"), max_length=4096)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
data = models.JSONField() data = models.JSONField(_("Data"))
template_name = models.CharField(max_length=255, null=True, blank=True) template_name = models.CharField(_("Template name"), max_length=255, null=True, blank=True)
def __str__(self): def __str__(self):
return self.name return self.name
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Layout")
verbose_name_plural = _("Layouts")

View file

@ -1,19 +1,22 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
class Manufacturer(models.Model): class Manufacturer(models.Model):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
description = models.CharField(max_length=4096, blank=True) description = models.CharField(_("Description"), max_length=4096, blank=True)
web_link = models.URLField(null=True, blank=True) web_link = models.URLField(_("Web link"), null=True, blank=True)
icon = models.ImageField(null=True, blank=True) icon = models.ImageField(_("Icon"), null=True, blank=True)
tags = models.ManyToManyField('inventory.Tag', blank=True) tags = models.ManyToManyField('inventory.Tag', verbose_name=_("Tags"), blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
def __str__(self): def __str__(self):
return self.name return self.name
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Manufacturer")
verbose_name_plural = _("Manufacturers")

View file

@ -1,3 +1,5 @@
from django.utils.translation import gettext_lazy as _
from django.utils.translation import gettext
from django.db import models from django.db import models
@ -8,11 +10,23 @@ class Settings(models.Model):
default=None, default=None,
null=True, null=True,
blank=True, blank=True,
help_text='Default container to display when calling the index page' help_text=_("Default container to display when calling the index page")
)
track_amount = models.BooleanField(
default=False,
help_text=_("Show item count in overview and warn on low watermarks")
)
currency = models.CharField(_("Currency"), max_length=30, help_text=_("Currency name"), default="Euro")
currency_symbol = models.CharField(_("Currency symbol"), max_length=20, default="&euro;")
currency_symbol_position = models.BooleanField(
_("Currency symbol at end"),
default=True,
help_text=_("Currency symbol after amount")
) )
def __str__(self): def __str__(self):
return 'Settings' return gettext("Settings")
class Meta: class Meta:
verbose_name_plural = 'Settings' verbose_name = _("Settings")
verbose_name_plural = _("Settings")

View file

@ -1,14 +1,17 @@
from django.utils.translation import gettext_lazy as _
from django.db import models from django.db import models
class Tag(models.Model): class Tag(models.Model):
name = models.CharField(max_length=255, unique=True, db_collation="numeric") name = models.CharField(_("Name"), max_length=255, unique=True, db_collation="numeric")
description = models.CharField(max_length=4096, db_collation="numeric") description = models.CharField(_("Description"), max_length=4096, db_collation="numeric")
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
def __str__(self): def __str__(self):
return self.name return self.name
class Meta: class Meta:
ordering = ['name', 'pk'] ordering = ['name', 'pk']
verbose_name = _("Tag")
verbose_name_plural = _("Tags")

View file

@ -1,16 +1,21 @@
from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.db import models from django.db import models
from .container import Container from .container import Container
class Workshop(Container): class Workshop(Container):
name = models.CharField(max_length=255, unique=True) name = models.CharField(_("Name"), max_length=255, unique=True)
description = models.CharField(max_length=4096) description = models.CharField(_("Description"), max_length=4096)
show_boxes = models.BooleanField(default=True, help_text="Allow boxes to be defined directly in this workshop") show_boxes = models.BooleanField(
tags = models.ManyToManyField('inventory.Tag', blank=True) _("Show boxes"),
default=True,
help_text=_("Allow boxes to be defined directly in this workshop")
)
tags = models.ManyToManyField('inventory.Tag', verbose_name=_("Tags"), blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True) changed_at = models.DateTimeField(_("Changed at"), auto_now=True)
@property @property
def url(self): def url(self):
@ -18,3 +23,5 @@ class Workshop(Container):
class Meta: class Meta:
ordering = ("name", ) ordering = ("name", )
verbose_name = _("Workshop")
verbose_name_plural = _("Workshops")

View file

@ -89,6 +89,24 @@ td.disabled {
opacity: 0.75; opacity: 0.75;
} }
.cell .stock {
position: absolute;
top: 5px;
left: 5px;
display: inline;
font-size: xx-small;
color: #808080;
line-height: 10px;
}
.cell .stock .icon {
display: inline-block;
width: 10px;
height: 10px;
margin: 0 2px 0 0;
vertical-align: text-top;
}
.cell .form_factor { .cell .form_factor {
position: absolute; position: absolute;
display: inline; display: inline;
@ -153,7 +171,13 @@ td.disabled {
top: 3px; top: 3px;
right: 7px; right: 7px;
} }
.cell .stock {
font-size: 75%;
top: 3px;
left: 3px;
}
.cell .price { .cell .price {
font-size: 75%; font-size: 75%;
bottom: 3px; bottom: 3px;

View file

@ -26,6 +26,11 @@ table.attribute-list th {
border-style: solid; border-style: solid;
} }
table.attribute-list .small {
color: #808080;
font-size: xx-small;
}
table.box { table.box {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
@ -158,8 +163,7 @@ img.icon {
margin-right: 10px; margin-right: 10px;
width: 18px; width: 18px;
height: 18px; height: 18px;
position: relative; vertical-align: middle;
top: 2px;
} }
img.logo { img.logo {
@ -277,9 +281,6 @@ table.list thead th {
padding: 10px; padding: 10px;
} }
table.list tbody tr {
}
table.list tbody td { table.list tbody td {
border-bottom: 1px solid black; border-bottom: 1px solid black;
padding: 10px; padding: 10px;
@ -322,3 +323,16 @@ table.list tbody td {
font-weight: normal; font-weight: normal;
color: #808080; color: #808080;
} }
div.icon {
width: 18px;
height: 18px;
display: inline-block;
vertical-align: middle;
}
div.warning-icon {
background-color: #c00000;
-webkit-mask: url(/static/inventory/img/warn.svg) no-repeat center;
mask: url(/static/inventory/img/warn.svg) no-repeat center;
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40 480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"/></svg>

After

Width:  |  Height:  |  Size: 542 B

View file

@ -1,6 +1,8 @@
{% load static %} {% load static %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="{{ LANGUAGE_CODE }}">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1"> <meta name="viewport" content="initial-scale=1, maximum-scale=1">
@ -38,32 +40,32 @@
} }
} }
</script> </script>
<a href="{% url 'search' %}" onclick="showSearch(event)"><img class="icon" title="Search" src="{% static "inventory/img/search.svg" %}"></a> <a href="{% url 'search' %}" onclick="showSearch(event)"><img class="icon" title="{% translate 'Search' %}" src="{% static "inventory/img/search.svg" %}"></a>
<div id="search-container"> <div id="search-container">
<form action="{% url 'search' %}" method="get"> <form action="{% url 'search' %}" method="get">
<input name="q" id="search" type="text" placeholder="Search"> <input name="q" id="search" type="text" placeholder="{% translate 'Search' %}">
<button type="submit">Search</button> <button type="submit">{% translate 'Search' %}</button>
</form> </form>
</div> </div>
</li> </li>
<li> <li>
<a href="{% url 'manufacturer-list' %}"><img class="icon" title="Manufacturers" src="{% static "inventory/img/manufacturer.svg" %}"></a> <a href="{% url 'manufacturer-list' %}"><img class="icon" title="{% translate 'Manufacturers' %}" src="{% static "inventory/img/manufacturer.svg" %}"></a>
</li> </li>
<li> <li>
<a href="{% url 'distributor-list' %}"><img class="icon" title="Distributors" src="{% static "inventory/img/distributor.svg" %}"></a> <a href="{% url 'distributor-list' %}"><img class="icon" title="{% translate 'Distributors' %}" src="{% static "inventory/img/distributor.svg" %}"></a>
</li> </li>
<li> <li>
<a href="{% url 'tag-list' %}"><img class="icon" title="Tags" src="{% static "inventory/img/tags.svg" %}"></a> <a href="{% url 'tag-list' %}"><img class="icon" title="{% translate 'Tags' %}" src="{% static "inventory/img/tags.svg" %}"></a>
</li> </li>
<li> <li>
<a href="{% url 'index' %}"><img class="icon" title="Workshops" src="{% static "inventory/img/workshop.svg" %}"></a> <a href="{% url 'index' %}"><img class="icon" title="{% translate 'Workshop' %}" src="{% static "inventory/img/workshop.svg" %}"></a>
</li> </li>
</ul> </ul>
{% if user.is_authenticated %} {% if user.is_authenticated %}
<form method="POST" action="{% url "logout" %}"> <form method="POST" action="{% url "logout" %}">
{% csrf_token %} {% csrf_token %}
<button><img class="icon" src="{% static "inventory/img/logout.svg" %}"> Logout</button> <button type="submit"><img class="icon" src="{% static "inventory/img/logout.svg" %}" title="{% translate 'Logout' %}"> {% translate 'Logout' %}</button>
</form> </form>
{% endif %} {% endif %}
</nav> </nav>

View file

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block title %}{{ area.name }}{% endblock %} {% block title %}{{ area.name }}{% endblock %}
@ -12,7 +13,7 @@
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_area_change" object_id=area.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_area_change" object_id=area.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% include 'inventory/set_index.html' with item=area is_index=is_index %} {% include 'inventory/set_index.html' with item=area is_index=is_index %}
{% endif %} {% endif %}
@ -21,7 +22,7 @@
{% block content %} {% block content %}
{% if area.show_sub_area %} {% if area.show_sub_area %}
<h3>Areas</h3> <h3>{% translate 'Areas' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
@ -32,22 +33,22 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_area_change" object_id=a.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_area_change" object_id=a.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td>No areas defined</td></tr> <tr><td>{% translate 'No areas defined' %}</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_area_add" %}?container={{ area.id }}&index=0">Create new area...</a></p> <p><a href="{% url "admin:inventory_area_add" %}?container={{ area.id }}&index=0">{% translate 'Create new area...' %}</a></p>
{% endif %} {% endif %}
{% endif %} {% endif %}
<h3>Containers</h3> <h3>{% translate 'Containers' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
@ -58,17 +59,17 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_box_change" object_id=box.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_box_change" object_id=box.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td>No containers defined</td></tr> <tr><td>{% translate 'No containers defined' %}</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_box_add" %}?container={{ area.id }}&index=0">Create new container...</a></p> <p><a href="{% url "admin:inventory_box_add" %}?container={{ area.id }}&index=0">{% translate 'Create new container...' %}</a></p>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block head %} {% block head %}
<link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}">
@ -8,7 +9,7 @@
{% block title %}{{ object.name }}{% endblock %} {% block title %}{{ object.name }}{% endblock %}
{% block header_bar %} {% block header_bar %}
<a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a> <a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}" title="{% translate 'Back' %}"></a>
{{ object.name }} {{ object.name }}
<span class="small">{{ object.description}}</span></h2> <span class="small">{{ object.description}}</span></h2>
{% endblock %} {% endblock %}
@ -16,7 +17,7 @@
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_box_change" object_id=object.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_box_change" object_id=object.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% include 'inventory/set_index.html' with item=object is_index=is_index %} {% include 'inventory/set_index.html' with item=object is_index=is_index %}
{% endif %} {% endif %}

View file

@ -1,9 +1,10 @@
{% extends "inventory/box-detail.html" %} {% extends "inventory/box-detail.html" %}
{% load i18n %}
{% block content %} {% block content %}
{% if box.box_related.exists %} {% if box.box_related.exists %}
<h3>Boxes</h3> <h3>{% translate 'Boxes' %}</h3>
<ul> <ul>
{% for b in box.box_related.all %} {% for b in box.box_related.all %}
<li><a href="{% url 'box-detail' b.id %}" title="{{ b.description }}">{{ b.name }} ({{ b.layout.name }})</a></li> <li><a href="{% url 'box-detail' b.id %}" title="{{ b.description }}">{{ b.name }} ({{ b.layout.name }})</a></li>
@ -12,7 +13,7 @@
{% endif %} {% endif %}
{% if box.item_related.exists %} {% if box.item_related.exists %}
<h3>Items</h3> <h3>{% translate 'Items' %}</h3>
<ul> <ul>
{% for item in box.item_related.all %} {% for item in box.item_related.all %}
<li {% if hilight == item.id %}class="hilighted"{% endif %}><a href="{% url 'item-detail' item.id %}" title="{{ item.description }}">{{ item.name }}</a></li> <li {% if hilight == item.id %}class="hilighted"{% endif %}><a href="{% url 'item-detail' item.id %}" title="{{ item.description }}">{{ item.name }}</a></li>

View file

@ -9,7 +9,7 @@
<td rowspan="2"> <td rowspan="2">
<div class="compartments-vertical"> <div class="compartments-vertical">
{% for compartment in layouted.0.0 %} {% for compartment in layouted.0.0 %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -17,7 +17,7 @@
<td class="triple-height" colspan="3"> <td class="triple-height" colspan="3">
<div class="compartments"> <div class="compartments">
{% for compartment in layouted.0.1 %} {% for compartment in layouted.0.1 %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -27,7 +27,7 @@
<td class="triple-height"> <td class="triple-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -9,7 +9,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in layouted.0 %} {% for compartment in layouted.0 %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -10,7 +10,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -20,7 +20,7 @@
<td rowspan="2"> <td rowspan="2">
<div class="compartments-vertical"> <div class="compartments-vertical">
{% for compartment in layouted.1.0 %} {% for compartment in layouted.1.0 %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -29,7 +29,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -40,7 +40,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -11,7 +11,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -27,7 +27,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -42,7 +42,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -11,7 +11,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -27,7 +27,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -42,7 +42,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -11,7 +11,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -27,7 +27,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -42,7 +42,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -11,7 +11,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -10,7 +10,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -21,7 +21,7 @@
<td> <td>
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -10,7 +10,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -21,7 +21,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -32,7 +32,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -45,7 +45,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -10,7 +10,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -21,7 +21,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -32,7 +32,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
@ -45,7 +45,7 @@
<td class="double-height"> <td class="double-height">
<div class="compartments"> <div class="compartments">
{% for compartment in item %} {% for compartment in item %}
{% include "inventory/cell.html" with item=compartment hilight=hilight %} {% include "inventory/cell.html" with item=compartment hilight=hilight settings=settings %}
{% endfor %} {% endfor %}
</div> </div>
</td> </td>

View file

@ -1,5 +1,8 @@
{% load static %} {% load static %}
{% load i18n %}
{% load admin_urls %} {% load admin_urls %}
{% load currency %}
<div class="cell{% if hilight == item.id %} search-hilight{% endif %}"> <div class="cell{% if hilight == item.id %} search-hilight{% endif %}">
{% if item.name %} {% if item.name %}
{% if item.metadata.package %} {% if item.metadata.package %}
@ -10,16 +13,23 @@
</a> </a>
<div class="cell-buttons"> <div class="cell-buttons">
{% if item.documentation.all %} {% if item.documentation.all %}
<a class="datasheet" href="{{ item.documentation.all.0.file.url }}"><img class="icon" src="{% static "inventory/img/datasheet.svg" %}"></a> <a class="datasheet" href="{{ item.documentation.all.0.file.url }}"><img class="icon" src="{% static "inventory/img/datasheet.svg" %}" title="{% translate 'Datasheet' %}"></a>
{% endif %} {% endif %}
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_item_change" object_id=item.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a class="edit" href="{% url "admin:inventory_item_change" object_id=item.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
<a class="details" href="{% url "item-detail" pk=item.pk %}"><img class="icon" src="{% static "inventory/img/detail.svg" %}"></a> <a class="details" href="{% url "item-detail" pk=item.pk %}"><img class="icon" src="{% static "inventory/img/detail.svg" %}" title="{% translate 'Details' %}"></a>
</div> </div>
{% if settings.track_amount %}
{% if item.count <= item.low_count %}
<div class="stock"><div class="icon warning-icon" title="{% translate 'Low stock' %}"></div>{{ item.count }}</div>
{% else %}
<div class="stock">{{ item.count }}</div>
{% endif %}
{% endif %}
{% if item.price %} {% if item.price %}
<div class="price">{{ item.price | floatformat:2 }} &euro;</div> <div class="price">{{ item.price | currency:"short" }}</div>
{% endif %} {% endif %}
{% if item.form_factor %} {% if item.form_factor %}
<div class="form_factor">{{ item.form_factor.name }}</div> <div class="form_factor">{{ item.form_factor.name }}</div>
@ -30,7 +40,7 @@
{% else %} {% else %}
<div class="cell-buttons"> <div class="cell-buttons">
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_item_add" %}?index={{ item.index }}&container={{ item.container_id }}"><img class="icon" src="{% static "inventory/img/add.svg" %}"></a> <a class="edit" href="{% url "admin:inventory_item_add" %}?index={{ item.index }}&container={{ item.container_id }}"><img class="icon" src="{% static "inventory/img/add.svg" %}" title="{% translate 'New item...' %}"></a>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}

View file

@ -1,19 +1,20 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %}
{% load static %} {% load static %}
{% load formatstring %} {% load formatstring %}
{% block title %}Distributor: {{ distributor }}{% endblock %} {% block title %}{% translate 'Distributor' %}: {{ distributor }}{% endblock %}
{% block header_bar %} {% block header_bar %}
<a href="{% url 'distributor-list' %}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a> <a href="{% url 'distributor-list' %}"><img class="icon" src="{% static "inventory/img/back.svg" %}" title="{% translate 'Back' %}"></a>
Distributor: {{ distributor.name }} {% translate 'Distributor' %}: {{ distributor.name }}
<span class="small">{{ distributor.description }}</span></h2> <span class="small">{{ distributor.description }}</span></h2>
{% endblock %} {% endblock %}
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_distributor_change" object_id=distributor.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_distributor_change" object_id=distributor.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -22,26 +23,26 @@
<table class="attribute-list"> <table class="attribute-list">
<tbody> <tbody>
<tr> <tr>
<th>Name</th> <th>{% translate 'Name' %}</th>
<td>{{ distributor.name }}</td> <td>{{ distributor.name }}</td>
</tr> </tr>
<tr> <tr>
<th>Description</th> <th>{% translate 'Description' %}</th>
<td>{{ distributor.description }}</td> <td>{{ distributor.description }}</td>
</tr> </tr>
{% if distributor.icon %} {% if distributor.icon %}
<tr> <tr>
<th>Icon</th> <th>{% translate 'Icon' %}</th>
<td><img src="{{ distributor.icon.url }}" title="{{ distributor.name }}" style="max-height: 20px;"></td> <td><img src="{{ distributor.icon.url }}" title="{{ distributor.name }}" style="max-height: 20px;"></td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<th>Link</th> <th>{% translate 'Web link' %}</th>
<td>{% if distributor.web_link %}<a href="{{ distributor.web_link }}" title="{{ distributor.name }}">{{ distributor.web_link }}{% else %}-{% endif %}</td> <td>{% if distributor.web_link %}<a href="{{ distributor.web_link }}" title="{{ distributor.name }}">{{ distributor.web_link }}{% else %}-{% endif %}</td>
</tr> </tr>
{% if distributor.search_link %} {% if distributor.search_link %}
<tr> <tr>
<th>Search</th> <th>{% translate 'Search' %}</th>
<td> <td>
<script> <script>
function distro_search(e) { function distro_search(e) {
@ -53,42 +54,41 @@
} }
</script> </script>
<form> <form>
<label for="distributor_search">Search query:</label> <input name="distributor_search" id="distributor_search" type="text" placeholder="{% translate 'Search query' %}">
<input name="distributor_search" id="distributor_search" type="text"> <button onclick="distro_search(event)" type="submit">{% translate 'Search' %}</button>
<button onclick="distro_search(event)" type="submit">Search</button>
</form> </form>
</td> </td>
</tr> </tr>
{% endif %} {% endif %}
{% if distributor.phone %} {% if distributor.phone %}
<tr> <tr>
<th>Phone</th> <th>{% translate 'Phone' %}</th>
<td>{{ distributor.phone }}</td> <td>{{ distributor.phone }}</td>
</tr> </tr>
{% endif %} {% endif %}
{% if distributor.email %} {% if distributor.email %}
<tr> <tr>
<th>Email</th> <th>{% translate 'E-Mail' %}</th>
<td><a href="mailto:{{ distributor.email }}">{{ distributor.email }}</a></td> <td><a href="mailto:{{ distributor.email }}">{{ distributor.email }}</a></td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<th>Tags</th> <th>{% translate 'Tags' %}</th>
<td> <td>
<ul class="tag-list"> <ul class="tag-list">
{% for tag in distributor.tags.all %} {% for tag in distributor.tags.all %}
<li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li> <li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li>
{% empty %} {% empty %}
No tags {% translate 'No tags' %}
{% endfor %} {% endfor %}
</ul> </ul>
</td> </td>
</tr> </tr>
<tr><th>Created at</th><td>{{ distributor.created_at }}</td></tr> <tr><th>{% translate 'Created at' %}</th><td>{{ distributor.created_at }}</td></tr>
{% if distributor.created_at != distributor.changed_at %} {% if distributor.created_at != distributor.changed_at %}
<tr><th>Last change</th><td>{{ distributor.changed_at }}</td></tr> <tr><th>{% translate 'Changed at' %}</th><td>{{ distributor.changed_at }}</td></tr>
{% endif %} {% endif %}
</tbody> </tbody>
</table> </table>

View file

@ -1,18 +1,19 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %}
{% load static %} {% load static %}
{% block title %}Distributors{% endblock %} {% block title %}{% translate 'Distributors' %}{% endblock %}
{% block header_bar %} {% block header_bar %}
Inventory management - Distributors {% translate 'Inventory management' %} - {% translate 'Distributors' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<table class="list"> <table class="list">
<thead> <thead>
<tr> <tr>
<th class="icon">Logo</th> <th class="icon">{% translate 'Icon' %}</th>
<th>Distributor</th> <th>{% translate 'Distributor' %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -29,7 +30,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_distributor_change" object_id=distributor.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_distributor_change" object_id=distributor.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -39,7 +40,7 @@
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_distributor_add" %}?layout=1">Create new distributor...</a></p> <p><a href="{% url "admin:inventory_distributor_add" %}?layout=1">{% translate 'Create new distributor...' %}</a></p>
{% endif %} {% endif %}

View file

@ -1,11 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load formatstring %} {% load formatstring %}
{% load currency %}
{% block title %}{{ item }}{% endblock %} {% block title %}{{ item }}{% endblock %}
{% block header_bar %} {% block header_bar %}
<a href="{{ item.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a> <a href="{{ item.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}" title="{% translate 'Back' %}"></a>
{{ item.name }} {{ item.name }}
<span class="small">{{ item.description }}{% if item.form_factor %}, {{ item.form_factor }}{% endif %}</span></h2> <span class="small">{{ item.description }}{% if item.form_factor %}, {{ item.form_factor }}{% endif %}</span></h2>
{% endblock %} {% endblock %}
@ -13,7 +15,7 @@
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_item_change" object_id=item.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_item_change" object_id=item.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -22,21 +24,40 @@
<table class="attribute-list"> <table class="attribute-list">
<tbody> <tbody>
<tr> <tr>
<th>Name</th> <th>{% translate 'Name' %}</th>
<td>{{ item.name }}</td> <td>{{ item.name }}</td>
</tr> </tr>
<tr> <tr>
<th>Description</th> <th>{% translate 'Description' %}</th>
<td>{{ item.description }}</td> <td>{{ item.description }}</td>
</tr> </tr>
{% if settings.track_amount %}
<tr> <tr>
<th>Tags</th> <th>{% translate 'Amount' %}</th>
<td>
<form method="post" action="{% url 'item-detail' item.pk %}">
{% csrf_token %}
<label for="amount">
{% if item.count <= item.low_count %}
<div class="icon warning-icon" title="{% translate 'Low stock' %}"></div>
{% endif %}
</label>
<input type="text" name="amount" id="amount" value="{{ item.count }}" placeholder="{% translate 'Amount' %}">
<button name="save" type="submit">{% translate 'Update' %}</button>
<button name="dec" type="submit">-1</button>
</form>
<span class="small right">{% translate 'Low watermark' %}: {{ item.low_count }}</span>
</td>
</tr>
{% endif %}
<tr>
<th>{% translate 'Tags' %}</th>
<td> <td>
<ul class="tag-list"> <ul class="tag-list">
{% for tag in item.all_tags %} {% for tag in item.all_tags %}
<li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li> <li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li>
{% empty %} {% empty %}
No tags {% translate 'No tags' %}
{% endfor %} {% endfor %}
</ul> </ul>
</td> </td>
@ -44,7 +65,7 @@
{% if item.form_factor %} {% if item.form_factor %}
<tr> <tr>
<th>Form factor</th> <th>{% translate 'Form factor' %}</th>
<td> <td>
{% if item.form_factor.datasheet %} {% if item.form_factor.datasheet %}
<a href="{% url 'distributor-detail' item.distributor.id %}"> <a href="{% url 'distributor-detail' item.distributor.id %}">
@ -61,7 +82,7 @@
{% if item.manufacturer %} {% if item.manufacturer %}
<tr> <tr>
<th>Manufacturer</th> <th>{% translate 'Manufacturer' %}</th>
<td> <td>
<a href="{% url 'manufacturer-detail' item.manufacturer.id %}"> <a href="{% url 'manufacturer-detail' item.manufacturer.id %}">
{% if item.manufacturer.icon %}<img src="{{ item.manufacturer.icon.url }}" class="icon">{% endif %}{{ item.manufacturer.name }} {% if item.manufacturer.icon %}<img src="{{ item.manufacturer.icon.url }}" class="icon">{% endif %}{{ item.manufacturer.name }}
@ -72,7 +93,7 @@
{% if item.distributor %} {% if item.distributor %}
<tr> <tr>
<th>Distributor</th> <th>{% translate 'Distributor' %}</th>
<td> <td>
<a href="{% url 'distributor-detail' item.distributor.id %}"> <a href="{% url 'distributor-detail' item.distributor.id %}">
{% if item.distributor.icon %}<img src="{{ item.distributor.icon.url }}" class="icon">{% endif %}{{ item.distributor.name }} {% if item.distributor.icon %}<img src="{{ item.distributor.icon.url }}" class="icon">{% endif %}{{ item.distributor.name }}
@ -83,35 +104,35 @@
{% if item.price %} {% if item.price %}
<tr> <tr>
<th>Price</th> <th>{% translate 'Price' %}</th>
<td>{{ item.price }} Euro</td> <td>{{ item.price | currency:"detail" }} <span class="small">{% if settings.track_amount %}({% translate 'Sum' %}: {{ item.value | currency:"long" }}){% endif %}</span></td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.last_ordered_on %} {% if item.last_ordered_on %}
<tr> <tr>
<th>Last ordered</th> <th>{% translate 'Last ordered' %}</th>
<td>{{ item.last_ordered_on }}</td> <td>{{ item.last_ordered_on }}</td>
</tr> </tr>
{% endif %} {% endif %}
{% if item.distributor_item_no %} {% if item.distributor_item_no %}
<tr> <tr>
<th>Link</th> <th>{% translate 'Search link' %}</th>
<td> <td>
<a href="{% formatstring item.distributor.search_link item.distributor_item_no %}">{% formatstring item.distributor.search_link item.distributor_item_no %}</a> <a href="{% formatstring item.distributor.search_link item.distributor_item_no %}">{% formatstring item.distributor.search_link item.distributor_item_no %}</a>
</td> </td>
</tr> </tr>
{% endif %} {% endif %}
<tr><th>Created at</th><td>{{ item.created_at }}</td></tr> <tr><th>{% translate 'Created at' %}</th><td>{{ item.created_at }}</td></tr>
{% if item.created_at != item.changed_at %} {% if item.created_at != item.changed_at %}
<tr><th>Last change</th><td>{{ item.changed_at }}</td></tr> <tr><th>{% translate 'Changed at' %}</th><td>{{ item.changed_at }}</td></tr>
{% endif %} {% endif %}
{% if item.documentation.exists %} {% if item.documentation.exists %}
<tr> <tr>
<th>Datasheets</th> <th>{% translate 'Documentation' %}</th>
<td> <td>
<ul> <ul>
{% for doc in item.documentation.all %} {% for doc in item.documentation.all %}

View file

@ -1,17 +1,18 @@
{% load i18n %}
{% load static %} {% load static %}
<table class="list"> <table class="list">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>{% translate 'Name' %}</th>
<th></th> <th></th>
<th>Description</th> <th>{% translate 'Description' %}</th>
<th>Container</th> <th>{% translate 'Container' %}</th>
{% if show_manufacturer %} {% if show_manufacturer %}
<th>Manufacturer</th> <th>{% translate 'Manufacturer' %}</th>
{% endif %} {% endif %}
{% if show_distributor %} {% if show_distributor %}
<th>Distributor</th> <th>{% translate 'Distributor' %}</th>
{% endif %} {% endif %}
</tr> </tr>
</thead> </thead>
@ -21,10 +22,10 @@
<td><a href="{% url 'item-detail' item.id %}">{{ item.name }}</a></td> <td><a href="{% url 'item-detail' item.id %}">{{ item.name }}</a></td>
<td class="right"> <td class="right">
{% if item.documentation.all %} {% if item.documentation.all %}
<a class="datasheet" href="{{ item.documentation.all.0.file.url }}"><img class="icon" src="{% static "inventory/img/datasheet.svg" %}"></a> <a class="datasheet" href="{{ item.documentation.all.0.file.url }}"><img class="icon" src="{% static "inventory/img/datasheet.svg" %}" title="{% translate 'Datasheet' %}"></a>
{% endif %} {% endif %}
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_item_change" object_id=item.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a class="edit" href="{% url "admin:inventory_item_change" object_id=item.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
<td>{{ item.description }}</td> <td>{{ item.description }}</td>

View file

@ -1,19 +1,20 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load formatstring %} {% load formatstring %}
{% block title %}Manufacturer: {{ manufacturer }}{% endblock %} {% block title %}{% translate 'Manufacturer' %}: {{ manufacturer }}{% endblock %}
{% block header_bar %} {% block header_bar %}
<a href="{% url 'manufacturer-list' %}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a> <a href="{% url 'manufacturer-list' %}"><img class="icon" src="{% static "inventory/img/back.svg" %}" title="{% translate 'Back' %}"></a>
Manufacturer: {{ manufacturer.name }} {% translate 'Manufacturer' %}: {{ manufacturer.name }}
<span class="small">{{ manufacturer.description }}</span></h2> <span class="small">{{ manufacturer.description }}</span></h2>
{% endblock %} {% endblock %}
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_manufacturer_change" object_id=manufacturer.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_manufacturer_change" object_id=manufacturer.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -22,45 +23,45 @@
<table class="attribute-list"> <table class="attribute-list">
<tbody> <tbody>
<tr> <tr>
<th>Name</th> <th>{% translate 'Name' %}</th>
<td>{{ manufacturer.name }}</td> <td>{{ manufacturer.name }}</td>
</tr> </tr>
<tr> <tr>
<th>Description</th> <th>{% translate 'Description' %}</th>
<td>{{ manufacturer.description }}</td> <td>{{ manufacturer.description }}</td>
</tr> </tr>
{% if manufacturer.icon %} {% if manufacturer.icon %}
<tr> <tr>
<th>Icon</th> <th>{% translate 'Icon' %}</th>
<td><img src="{{ manufacturer.icon.url }}" title="{{ manufacturer.name }}" style="max-height: 20px;"></td> <td><img src="{{ manufacturer.icon.url }}" title="{{ manufacturer.name }}" style="max-height: 20px;"></td>
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<th>Link</th> <th>{% translate 'Web link' %}</th>
<td>{% if manufacturer.web_link %}<a href="{{ manufacturer.web_link }}" title="{{ manufacturer.name }}">{{ manufacturer.web_link }}{% else %}-{% endif %}</td> <td>{% if manufacturer.web_link %}<a href="{{ manufacturer.web_link }}" title="{{ manufacturer.name }}">{{ manufacturer.web_link }}{% else %}-{% endif %}</td>
</tr> </tr>
<tr> <tr>
<th>Tags</th> <th>{% translate 'Tags' %}</th>
<td> <td>
<ul class="tag-list"> <ul class="tag-list">
{% for tag in manufacturer.tags.all %} {% for tag in manufacturer.tags.all %}
<li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li> <li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li>
{% empty %} {% empty %}
No tags {% translate 'No tags' %}
{% endfor %} {% endfor %}
</ul> </ul>
</td> </td>
</tr> </tr>
<tr><th>Created at</th><td>{{ manufacturer.created_at }}</td></tr> <tr><th>{% translate 'Created at' %}</th><td>{{ manufacturer.created_at }}</td></tr>
{% if manufacturer.created_at != manufacturer.changed_at %} {% if manufacturer.created_at != manufacturer.changed_at %}
<tr><th>Last change</th><td>{{ manufacturer.changed_at }}</td></tr> <tr><th>{% translate 'Changed at' %}</th><td>{{ manufacturer.changed_at }}</td></tr>
{% endif %} {% endif %}
</tbody> </tbody>
</table> </table>
<h2>Items</h2> <h2>{% translate 'Items' %}</h2>
{% url 'manufacturer-detail' manufacturer.id as this_url %} {% url 'manufacturer-detail' manufacturer.id as this_url %}
{% include "inventory/pagination.html" with url=this_url id="paginator_top" param="item" paginator=items %} {% include "inventory/pagination.html" with url=this_url id="paginator_top" param="item" paginator=items %}

View file

@ -1,18 +1,19 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block title %}Manufacturers{% endblock %} {% block title %}{% translate 'Manufacturers' %}{% endblock %}
{% block header_bar %} {% block header_bar %}
Inventory management - Manufacturers {% translate 'Inventory Management' %} - {% translate 'Manufacturers' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<table class="list"> <table class="list">
<thead> <thead>
<tr> <tr>
<th>Logo</th> <th>{% translate 'Icon' %}</th>
<th>Manufacturer</th> <th>{% translate 'Manufacturer' %}</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -29,7 +30,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_manufacturer_change" object_id=manufacturer.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_manufacturer_change" object_id=manufacturer.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -38,7 +39,7 @@
</table> </table>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_manufacturer_add" %}?layout=1">Create new manufacturer...</a></p> <p><a href="{% url "admin:inventory_manufacturer_add" %}?layout=1">{% translate 'Create new manufacturer...' %}</a></p>
{% endif %} {% endif %}

View file

@ -1,15 +1,16 @@
{% load static %} {% load static %}
{% load i18n %}
<div class="pagination" id="{{ id }}"> <div class="pagination" id="{{ id }}">
{% if paginator.has_previous %} {% if paginator.has_previous %}
<a href="{{ url }}?{{ param }}_page=1#{{ id }}"><img src="{% static 'inventory/img/first.svg' %}" class="icon" title="First page"></a> <a href="{{ url }}?{{ param }}_page=1#{{ id }}"><img src="{% static 'inventory/img/first.svg' %}" class="icon" title="{% translate 'First page' %}"></a>
<a href="{{ url }}?{{ param }}_page={{ paginator.previous_page_number }}#{{ id }}"><img src="{% static 'inventory/img/previous.svg' %}" class="icon" title="Previous page"></a> <a href="{{ url }}?{{ param }}_page={{ paginator.previous_page_number }}#{{ id }}"><img src="{% static 'inventory/img/previous.svg' %}" class="icon" title="{% translate 'Previous page' %}"></a>
{% endif %} {% endif %}
{% if paginator.paginator.num_pages > 1 %} {% if paginator.paginator.num_pages > 1 %}
{{ paginator.number }}/{{ paginator.paginator.num_pages }} {{ paginator.number }}/{{ paginator.paginator.num_pages }}
{% endif %} {% endif %}
{% if paginator.has_next %} {% if paginator.has_next %}
<a href="{{ url }}?{{ param }}_page={{ paginator.next_page_number }}#{{ id }}"><img src="{% static 'inventory/img/next.svg' %}" class="icon" title="Next page"></a> <a href="{{ url }}?{{ param }}_page={{ paginator.next_page_number }}#{{ id }}"><img src="{% static 'inventory/img/next.svg' %}" class="icon" title="{% translate 'Next page' %}"></a>
<a href="{{ url }}?{{ param }}_page={{ paginator.paginator.num_pages}}#{{ id }}"><img src="{% static 'inventory/img/last.svg' %}" class="icon" title="Last page"></a> <a href="{{ url }}?{{ param }}_page={{ paginator.paginator.num_pages}}#{{ id }}"><img src="{% static 'inventory/img/last.svg' %}" class="icon" title="{% translate 'Last page' %}"></a>
{% endif %} {% endif %}
</div> </div>

View file

@ -1,15 +1,16 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block title %}Search{% endblock %} {% block title %}{% translate 'Search' %}{% endblock %}
{% block header_bar %} {% block header_bar %}
Search {% translate 'Search' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<form method="get" action="{% url 'search' %}"> <form method="get" action="{% url 'search' %}">
<input type="text" id="search" name="q"> <input type="text" id="search" name="q" placeholder="{% translate 'Search' %}">
<button type="submit">Search</button> <button type="submit">{% translate 'Search' %}</button>
</form> </form>
{% endblock %} {% endblock %}

View file

@ -1,20 +1,21 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load hilight %} {% load hilight %}
{% block title %}Search{% endblock %} {% block title %}{% translate 'Search' %}{% endblock %}
{% block header_bar %} {% block header_bar %}
Search {% translate 'Search' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<form method="get" action="{% url 'search' %}"> <form method="get" action="{% url 'search' %}">
<input type="text" id="search" name="q" value="{{ q }}"> <input type="text" id="search" name="q" value="{{ q }}" placeholder="{% translate 'Search' %}">
<button type="submit">Search</button> <button type="submit">{% translate 'Search' %}</button>
</form> </form>
<h2>Search result for '{{ q }}'</h2> <h2>{% translate 'Search result for' %} '{{ q }}'</h2>
{% for result in results %} {% for result in results %}
<div class="search-result"> <div class="search-result">
@ -23,19 +24,19 @@
<hr> <hr>
</div> </div>
{% empty %} {% empty %}
<p>Noting found</p> <p>{% translate 'Nothing found' %}</p>
{% endfor %} {% endfor %}
{% if pages > 1 %} {% if pages > 1 %}
<div class="pagination"> <div class="pagination">
{% if page > 1 %} {% if page > 1 %}
<a href="{% url 'search' %}?q={{ q }}&page=1"><img src="{% static 'inventory/img/first.svg' %}" class="icon" title="First page"></a> <a href="{% url 'search' %}?q={{ q }}&page=1"><img src="{% static 'inventory/img/first.svg' %}" class="icon" title="{% translate 'First page' %}"></a>
<a href="{% url 'search' %}?q={{ q }}&page={{ page | add:'-1'}}"><img src="{% static 'inventory/img/previous.svg' %}" class="icon" title="Previous page"></a> <a href="{% url 'search' %}?q={{ q }}&page={{ page | add:'-1'}}"><img src="{% static 'inventory/img/previous.svg' %}" class="icon" title="{% translate 'Previous page' %}"></a>
{% endif %} {% endif %}
{{ page }}/{{ pages }} {{ page }}/{{ pages }}
{% if page < pages %} {% if page < pages %}
<a href="{% url 'search' %}?q={{ q }}&page={{ page | add:'1'}}"><img src="{% static 'inventory/img/next.svg' %}" class="icon" title="Next page"></a> <a href="{% url 'search' %}?q={{ q }}&page={{ page | add:'1'}}"><img src="{% static 'inventory/img/next.svg' %}" class="icon" title="{% translate 'Next page' %}"></a>
<a href="{% url 'search' %}?q={{ q }}&page={{ pages }}"><img src="{% static 'inventory/img/last.svg' %}" class="icon" title="Last page"></a> <a href="{% url 'search' %}?q={{ q }}&page={{ pages }}"><img src="{% static 'inventory/img/last.svg' %}" class="icon" title="{% translate 'Last page' %}"></a>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}

View file

@ -1,17 +1,16 @@
{% load static %} {% load static %}
{% load i18n %}
{% load hilight %} {% load hilight %}
<p> <p>
{% if item.documentation.all %} {% if item.documentation.all %}
<a class="datasheet" href="{{ item.documentation.all.0.file.url }}"><img class="icon" src="{% static "inventory/img/datasheet.svg" %}"></a> <a class="datasheet" href="{{ item.documentation.all.0.file.url }}"><img class="icon" src="{% static "inventory/img/datasheet.svg" %}" title="{% translate 'Datasheet' %}"></a>
{% endif %} {% endif %}
{{ item | hilight:tokens }} {{ item | hilight:tokens }}
<span class="small">{{item.form_factor.name}}</span> <span class="small">{{item.form_factor.name}}</span>
</p> </p>
<p>Contained in: <a href="{{ item.container_url }}?hilight={{ item.id }}">{{ item.container.display_name }}</a></p> <p>{% translate 'Contained in' %}: <a href="{{ item.container_url }}?hilight={{ item.id }}">{{ item.container.display_name }}</a></p>
<ul class="tag-list"> <ul class="tag-list">
{% for tag in item.all_tags %} {% for tag in item.all_tags %}
<li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li> <li><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li>
{% empty %}
No tags
{% endfor %} {% endfor %}
</ul> </ul>

View file

@ -1,4 +1,5 @@
{% load static %} {% load static %}
{% load i18n %}
<li> <li>
<form method="POST" action="{% url "index" %}"> <form method="POST" action="{% url "index" %}">
@ -6,9 +7,9 @@
<input type="hidden" name="index_id" value='{{ item.id }}'> <input type="hidden" name="index_id" value='{{ item.id }}'>
<button class="icon-only-button"> <button class="icon-only-button">
{% if is_index %} {% if is_index %}
<img class="icon" src="{% static "inventory/img/star-filled.svg" %}"> <img class="icon" src="{% static "inventory/img/star-filled.svg" %}" title="{% translate 'Currently set as index page' %}">
{% else %} {% else %}
<img class="icon" src="{% static "inventory/img/star-outline.svg" %}"> <img class="icon" src="{% static "inventory/img/star-outline.svg" %}" title="{% translate 'Promote to index page' %}">
{% endif %} {% endif %}
</button> </button>
</form> </form>

View file

@ -1,10 +1,11 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block title %}Tag {{ tag.name }}{% endblock %} {% block title %}{% translate 'Tag' %} {{ tag.name }}{% endblock %}
{% block header_bar %} {% block header_bar %}
<a href="{% url "tag-list" %}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a> <a href="{% url "tag-list" %}"><img class="icon" src="{% static "inventory/img/back.svg" %}" title="{% translate 'Back' %}"></a>
{{ tag.name }} {{ tag.name }}
<span class="small">{{ tag.description}}</span> <span class="small">{{ tag.description}}</span>
{% endblock %} {% endblock %}
@ -12,14 +13,14 @@
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_tag_change" object_id=tag.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_tag_change" object_id=tag.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if tag.workshop_set.count > 0 %} {% if tag.workshop_set.count > 0 %}
<h3>Workshops</h3> <h3>{% translate 'Workshops' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
{% for workshop in tag.workshop_set.all %} {% for workshop in tag.workshop_set.all %}
@ -29,7 +30,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_workshop_change" object_id=workshop.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_workshop_change" object_id=workshop.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -39,7 +40,7 @@
{% endif %} {% endif %}
{% if tag.box_set.count > 0 %} {% if tag.box_set.count > 0 %}
<h3>Boxes</h3> <h3>{% translate 'Boxes' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
{% for box in tag.box_set.all %} {% for box in tag.box_set.all %}
@ -49,7 +50,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_workshop_change" object_id=box.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_workshop_change" object_id=box.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -59,7 +60,7 @@
{% endif %} {% endif %}
{% if tag.distributor_set.count > 0 %} {% if tag.distributor_set.count > 0 %}
<h3>Distributors</h3> <h3>{% translate 'Distributors' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
{% for distributor in tag.distributor_set.all %} {% for distributor in tag.distributor_set.all %}
@ -74,7 +75,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_workshop_change" object_id=distributor.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_workshop_change" object_id=distributor.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -84,7 +85,7 @@
{% endif %} {% endif %}
{% if tag.manufacturer_set.count > 0 %} {% if tag.manufacturer_set.count > 0 %}
<h3>Manufacturers</h3> <h3>{% translate 'Manufacturers' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
{% for manufacturer in tag.manufacturer_set.all %} {% for manufacturer in tag.manufacturer_set.all %}
@ -99,7 +100,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_workshop_change" object_id=manufacturer.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_workshop_change" object_id=manufacturer.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -109,7 +110,7 @@
{% endif %} {% endif %}
{% if items %} {% if items %}
<h3>Items</h3> <h3>{% translate 'Items' %}</h3>
{% url 'tag-detail' tag.id as this_url %} {% url 'tag-detail' tag.id as this_url %}
{% include "inventory/pagination.html" with url=this_url id="items_paginator_top" param="item" paginator=items %} {% include "inventory/pagination.html" with url=this_url id="items_paginator_top" param="item" paginator=items %}
{% include "inventory/item_list.html" with items=items show_manufacturer=1 show_distributor=1 %} {% include "inventory/item_list.html" with items=items show_manufacturer=1 show_distributor=1 %}
@ -117,7 +118,7 @@
{% endif %} {% endif %}
{% if tag.formfactor_set.count > 0 %} {% if tag.formfactor_set.count > 0 %}
<h3>Form factors</h3> <h3>{% translate 'Form factors' %}</h3>
<ul class="compact-list"> <ul class="compact-list">
{% for formfactor in tag.formfactor_set.all %} {% for formfactor in tag.formfactor_set.all %}
<li>{{ formfactor.name }}</li> <li>{{ formfactor.name }}</li>

View file

@ -1,11 +1,12 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load formatstring %} {% load formatstring %}
{% block title %}Tags{% endblock %} {% block title %}Tags{% endblock %}
{% block header_bar %} {% block header_bar %}
Inventory Management - Tags {% translate 'Inventory management' %} - {% translate 'Tags' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -39,19 +40,19 @@
} }
</script> </script>
<form> <form>
<input type="text" id="tag-search" name="tag-search" placeholder="Search" oninput="updateSearch(event)"> <input type="text" id="tag-search" name="tag-search" placeholder="{% translate 'Search' %}" oninput="updateSearch(event)">
<button onclick="updateSearch(event)">Search</button> <button onclick="updateSearch(event)">{% translate 'Search' %}</button>
</form> </form>
<ul class="tag-list" id="tagcloud"> <ul class="tag-list" id="tagcloud">
{% for tag in object_list %} {% for tag in object_list %}
<li data-search="{{ tag.name | lower }} {{ tag.description | lower }}"><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li> <li data-search="{{ tag.name | lower }} {{ tag.description | lower }}"><a href="{% url 'tag-detail' tag.id %}" title="{{ tag.name }}">{{ tag.name }}</a></li>
{% empty %} {% empty %}
No tags {% translate 'No tags' %}
{% endfor %} {% endfor %}
</ul> </ul>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_tag_add" %}?layout=1">Create new tag...</a></p> <p><a href="{% url "admin:inventory_tag_add" %}?layout=1">{% translate 'Create new tag...' %}</a></p>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -1,10 +1,11 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block title %}Workshop {{ workshop.name }}{% endblock %} {% block title %}{% translate 'Workshop' %} {{ workshop.name }}{% endblock %}
{% block header_bar %} {% block header_bar %}
<a href="{% url "workshop-list" %}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a> <a href="{% url "workshop-list" %}"><img class="icon" src="{% static "inventory/img/back.svg" %}" title="{% translate 'Back' %}"></a>
{{ workshop.name }} {{ workshop.name }}
<span class="small">{{ workshop.description}}</span> <span class="small">{{ workshop.description}}</span>
{% endblock %} {% endblock %}
@ -12,14 +13,14 @@
{% block header_icons %} {% block header_icons %}
{% if user.is_staff %} {% if user.is_staff %}
<li> <li>
<a href="{% url "admin:inventory_workshop_change" object_id=workshop.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a> <a href="{% url "admin:inventory_workshop_change" object_id=workshop.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}" title="{% translate 'Edit' %}"></a>
</li> </li>
{% include 'inventory/set_index.html' with item=workshop is_index=is_index %} {% include 'inventory/set_index.html' with item=workshop is_index=is_index %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h3>Areas</h3> <h3>{% translate 'Areas' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
@ -30,22 +31,22 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_area_change" object_id=area.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_area_change" object_id=area.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td>No areas defined</td></tr> <tr><td>{% translate 'No areas defined' %}</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_area_add" %}?container={{ workshop.id }}&index=0">Create new area...</a></p> <p><a href="{% url "admin:inventory_area_add" %}?container={{ workshop.id }}&index=0">{% translate 'Create new area...' %}</a></p>
{% endif %} {% endif %}
{% if workshop.show_boxes %} {% if workshop.show_boxes %}
<h3>Containers</h3> <h3>{% translate 'Containers' %}</h3>
<table class="list"> <table class="list">
<tbody> <tbody>
{% for box in workshop.box_related.all %} {% for box in workshop.box_related.all %}
@ -55,18 +56,18 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_box_change" object_id=box.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_box_change" object_id=box.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td>No containers defined</td></tr> <tr><td>{% translate 'No containers defined' %}</td></tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_box_add" %}?container={{ workshop.id }}&index=0">Create new container...</a></p> <p><a href="{% url "admin:inventory_box_add" %}?container={{ workshop.id }}&index=0">{% translate 'Create new container...' %}</a></p>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -1,10 +1,11 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% block title %}Workshops{% endblock %} {% block title %}{% translate 'Workshops' %}{% endblock %}
{% block header_bar %} {% block header_bar %}
Inventory management - Workshops {% translate 'Inventory management' %} - {% translate 'Workshops' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -17,7 +18,7 @@
</td> </td>
<td> <td>
{% if user.is_staff %} {% if user.is_staff %}
<a class="edit" href="{% url "admin:inventory_workshop_change" object_id=workshop.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}"></a> <a class="edit" href="{% url "admin:inventory_workshop_change" object_id=workshop.pk %}"><img class="icon" src="{% static 'inventory/img/edit.svg' %}" title="{% translate 'Edit' %}"></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
@ -26,7 +27,7 @@
</table> </table>
{% if user.is_staff %} {% if user.is_staff %}
<p><a href="{% url "admin:inventory_workshop_add" %}?layout=1">Create new workshop...</a></p> <p><a href="{% url "admin:inventory_workshop_add" %}?layout=1">{% translate 'Create new workshop...' %}</a></p>
{% endif %} {% endif %}

View file

@ -1,21 +1,30 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n%}
{% block header_bar %} {% block header_bar %}
Inventory management - Login {% translate 'Inventory management' %} - {% translate 'Login' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if form.errors %} {% if form.errors %}
<p>Your username and password didn't match. Please try again.</p> <p>{% blocktranslate %}Your username and password didn't match. Please try again.{% endblocktranslate %}</p>
{% endif %} {% endif %}
{% if next %} {% if next %}
{% if user.is_authenticated %} {% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed, <p>
please login with an account that has access.</p> {% blocktranslate %}
Your account doesn't have access to this page. To proceed,
please login with an account that has access.
{% endblocktranslate %}
</p>
{% else %} {% else %}
<p>Please login to see this page.</p> <p>
{% blocktranslate %}
Please login to see this page.
{% endblocktranslate %}
</p>
{% endif %} {% endif %}
{% endif %} {% endif %}
@ -37,6 +46,6 @@
</form> </form>
{# Assumes you setup the password_reset view in your URLconf #} {# Assumes you setup the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p> <p><a href="{% url 'password_reset' %}">{% translate 'Lost password?' %}</a></p>
{% endblock %} {% endblock %}

View file

@ -0,0 +1,29 @@
from django import template
from django.utils.safestring import mark_safe
from django.utils.formats import number_format
from inventory.models import Settings
register = template.Library()
s = Settings.objects.first()
@register.filter(name='currency')
def currency(value, format):
value = float(value)
if format == 'detail':
value = number_format(round(value, 3), 3, use_l10n=True)
else:
value = number_format(round(value, 2), 2, use_l10n=True)
if format == 'long' or format == 'detail':
symbol = s.currency
else:
symbol = s.currency_symbol
if s.currency_symbol_position:
result = f"{value} {symbol}"
else:
result = f"{symbol} {value}"
return mark_safe(result)

View file

@ -4,7 +4,7 @@ from django.utils.decorators import method_decorator
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.db.models import QuerySet from django.db.models import QuerySet
from inventory.models import Box from inventory.models import Box, Settings
from .utils import CanBeIndexMixin from .utils import CanBeIndexMixin
@ -54,6 +54,7 @@ class BoxView(CanBeIndexMixin, DetailView):
context = self.get_context_data(object=self.object) context = self.get_context_data(object=self.object)
context['layouted'], _ = self.layout(self.object.item_related.all().order_by('index'), self.object.layout.data) context['layouted'], _ = self.layout(self.object.item_related.all().order_by('index'), self.object.layout.data)
context['hilight'] = hilighted context['hilight'] = hilighted
context['settings'] = Settings.objects.first()
return self.render_to_response(context) return self.render_to_response(context)

View file

@ -1,15 +1,30 @@
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.shortcuts import get_object_or_404
from inventory.models import Item from inventory.models import Item, Settings
@method_decorator(login_required, name='dispatch') @method_decorator(login_required, name='dispatch')
class ItemView(DetailView): class ItemView(DetailView):
context_object_name = 'item' context_object_name = 'item'
queryset = Item.objects.all().select_related('container', 'container__layout', 'manufacturer', 'distributor').prefetch_related('documentation') queryset = Item.objects.all().select_related('container', 'container__layout', 'manufacturer', 'distributor').prefetch_related('documentation')
def get_context_data(self, *args, object_list=None, **kwargs):
result = super().get_context_data(*args, object_list=object_list, **kwargs)
result['settings'] = Settings.objects.first()
return result
def post(self, request, pk):
item = get_object_or_404(Item.objects.filter(pk=pk))
if request.POST.get('dec', None) is not None:
if item.count > 0:
item.count -= 1
item.save()
if request.POST.get('save', None) is not None:
item.count = request.POST.get('amount', 0)
item.save()
return self.get(request)
@method_decorator(login_required, name='dispatch') @method_decorator(login_required, name='dispatch')
class ItemListView(ListView): class ItemListView(ListView):

View file

@ -14,6 +14,7 @@ from typing import List
import os import os
import sys import sys
import asyncio import asyncio
from django.utils.translation import gettext_lazy as _
if sys.platform == 'win32': if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
@ -116,6 +117,10 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/ # https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGES = [
("de", _("German")),
("en", _("English")),
]
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'