diff --git a/k356/app/settings.py b/k356/app/settings.py
index 9efcc7d..d3823dd 100644
--- a/k356/app/settings.py
+++ b/k356/app/settings.py
@@ -10,12 +10,10 @@ For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""
-from pathlib import Path
-from django.utils.module_loading import import_module
-
-
import os
+from pathlib import Path
+from django.utils.module_loading import import_module
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -24,7 +22,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = 'django-insecure-$440wv7cqb$-umfo-x%w_@p3g5kuuk1(!rv#=7*gzndx4_h4ds'
+SECRET_KEY = "django-insecure-$440wv7cqb$-umfo-x%w_@p3g5kuuk1(!rv#=7*gzndx4_h4ds"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
@@ -35,18 +33,34 @@ ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
-
- 'main',
- 'users',
- 'items',
+ "django.contrib.admin",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.sessions",
+ "django.contrib.messages",
+ "django.contrib.staticfiles",
+ "django_js_reverse",
+ "djangobower",
+ "main",
+ "users",
+ "items",
+]
- 'django_js_reverse',
+BOWER_COMPONENT_ROOT = os.path.join(BASE_DIR, "components")
+BOWER_INSTALLED_APPS = [
+ "https://code.jquery.com/jquery-3.7.1.min.js",
+ "https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js",
+ "https://cdn.jsdelivr.net/npm/sweetalert2@11",
+ "https://cdn.jsdelivr.net/npm/vue-resource@1.5.3",
+ "https://cdn.jsdelivr.net/npm/js-cookie@3.0.5/dist/js.cookie.min.js",
+ "https://unpkg.com/vue-router@3/dist/vue-router.js",
+ "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css",
+ "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js",
+ "https://cdn.jsdelivr.net/npm/bootswatch@5.3.3/dist/lux/bootstrap.min.css",
+ "https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css",
+ "https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js",
+ "https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css",
+ "https://fonts.cdnfonts.com/css/jetbrains-mono",
]
STATIC_URL = "/static/"
@@ -56,7 +70,7 @@ STATICFILES_DIRS = (os.path.join(BASE_DIR, "static_source"),)
STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
- # "djangobower.finders.BowerFinder",
+ "djangobower.finders.BowerFinder",
# "compressor.finders.CompressorFinder",
)
@@ -70,37 +84,37 @@ STORAGES = {
}
MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
]
-ROOT_URLCONF = 'app.urls'
+ROOT_URLCONF = "app.urls"
TEMPLATES = [
{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "DIRS": [
os.path.join(BASE_DIR, "templates"),
],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- 'app.utils.extra_context.extra_context',
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ "app.utils.extra_context.extra_context",
],
},
},
]
-WSGI_APPLICATION = 'app.wsgi.application'
+WSGI_APPLICATION = "app.wsgi.application"
# Database
@@ -114,16 +128,16 @@ DATABASES = {}
AUTH_PASSWORD_VALIDATORS = [
{
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
@@ -131,9 +145,9 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
# https://docs.djangoproject.com/en/5.1/topics/i18n/
-LANGUAGE_CODE = 'en-us'
+LANGUAGE_CODE = "en-us"
-TIME_ZONE = 'UTC'
+TIME_ZONE = "UTC"
USE_I18N = True
@@ -142,12 +156,11 @@ USE_TZ = True
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
-DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
from app.settingsLocal import *
-
for extra_app in EXTRA_APPS:
INSTALLED_APPS.append(extra_app)
diff --git a/k356/app/utils/api/api_list.py b/k356/app/utils/api/api_list.py
index f3ceefb..a662697 100644
--- a/k356/app/utils/api/api_list.py
+++ b/k356/app/utils/api/api_list.py
@@ -4,8 +4,8 @@ def header_for_table(model):
return [
{
- "text": value,
"value": key,
+ **value,
}
for key, value in headers.items()
] + [
@@ -15,7 +15,3 @@ def header_for_table(model):
"sortable": False,
},
]
-
-
-def encrypted_fields(model):
- return model.Encryption.fields
diff --git a/k356/app/utils/extra_context.py b/k356/app/utils/extra_context.py
index 2562200..8a5b44d 100644
--- a/k356/app/utils/extra_context.py
+++ b/k356/app/utils/extra_context.py
@@ -1,10 +1,10 @@
-from django.conf import settings
-from django.apps import apps
-
-
-from users.models import UserSettings
from pathlib import Path
+from django.apps import apps
+from django.conf import settings
+from rich import print
+from users.models import UserSettings
+
def extra_context(request):
@@ -21,17 +21,16 @@ def extra_context(request):
for path in p.iterdir():
components.append(path.name)
- return {
+ ret = {
"user_settings": user_settings,
"templates": {
component: f"components/{component}/template.html"
for component in components
},
"components": {
- component: {
- "path": f"components/{component}/vue.js",
- "flat_name": component.replace("-", "_").lower(),
- }
- for component in components
- }
+ component: f"components/{component}/vue.js" for component in components
+ },
}
+
+ print(ret)
+ return ret
diff --git a/k356/app/utils/models.py b/k356/app/utils/models.py
index d72d45f..35be261 100644
--- a/k356/app/utils/models.py
+++ b/k356/app/utils/models.py
@@ -11,15 +11,44 @@ class BaseQuerySet(models.QuerySet):
def headers(self):
"""Return the list of header for a list."""
+ def _field(field):
+ ret = {
+ field.name: {
+ "text": field.verbose_name.capitalize(),
+ "align": "",
+ "encrypted": field.name in self.model.Encryption.fields,
+ "editable": field.name
+ not in self.model.Serialization.excluded_fields_edit,
+ "field_widget": "v-textarea",
+ }
+ }
+
+ if isinstance(field, RelatedField):
+ ret[f"{field.name}__name"] = {
+ "text": f"{field.verbose_name.capitalize()} - Name",
+ "align": "",
+ "encrypted": True,
+ }
+ ret[f"{field.name}__name"] = {
+ "text": f"{field.verbose_name.capitalize()} - Identifier",
+ "align": "",
+ "encrypted": True,
+ }
+
+ ret[field.name].update(
+ align=" d-none",
+ testing=123,
+ field_widget="v-select",
+ )
+
+ return ret
+
fields = {}
for field in self.model._meta.fields:
if field.name in self.model.Serialization.excluded_fields:
continue
- # if isinstance(field, RelatedField):
- # fields[f"{field.name}__name"] = field.verbose_name.capitalize()
-
- fields[field.name] = field.verbose_name.capitalize()
+ fields.update(_field(field))
return fields
diff --git a/k356/items/templates/components/ItemList/template.html b/k356/items/templates/components/ItemList/template.html
new file mode 100644
index 0000000..fb816ff
--- /dev/null
+++ b/k356/items/templates/components/ItemList/template.html
@@ -0,0 +1 @@
+{% extends "base_components/glist/template.html" %}
diff --git a/k356/items/templates/components/ItemList/vue.js b/k356/items/templates/components/ItemList/vue.js
new file mode 100644
index 0000000..335a17a
--- /dev/null
+++ b/k356/items/templates/components/ItemList/vue.js
@@ -0,0 +1,7 @@
+{% extends "base_components/glist/vue.js" %}
+{% load main %}
+
+{% block component %}
+ {% define 'items' 'items' %}
+ {{ block.super }}
+{% endblock %}
diff --git a/k356/items/templates/components/ItemView/template.html b/k356/items/templates/components/ItemView/template.html
new file mode 100644
index 0000000..f3d2078
--- /dev/null
+++ b/k356/items/templates/components/ItemView/template.html
@@ -0,0 +1,40 @@
+{% load i18n %}
+
+
diff --git a/k356/items/templates/components/ItemView/vue.js b/k356/items/templates/components/ItemView/vue.js
new file mode 100644
index 0000000..99c35d7
--- /dev/null
+++ b/k356/items/templates/components/ItemView/vue.js
@@ -0,0 +1,282 @@
+ItemView = {
+ template: "#ItemView",
+ delimiters: ["[[", "]]"],
+ props: ["crypto_key"],
+
+ data: function() {
+ return {
+ search: "",
+ items: [],
+ items_headers: [],
+ items_relations: [],
+ types: [],
+ types_headers: [],
+ types_relations: [],
+ }
+ },
+
+ mounted: function() {
+ this.reload()
+ },
+
+ computed: {
+ items_encrypted_fields: function() {
+ return this.items_headers.filter(e => e.encrypted).map(e => e.value)
+ },
+
+ types_encrypted_fields: function() {
+ return this.types_headers.filter(e => e.encrypted).map(e => e.value)
+ },
+ },
+
+ methods: {
+
+ reload () {
+
+ var self = this
+
+ this.$http.get(Urls["items:list"]()).then(response => {
+
+ Object.keys(response.data.result).forEach(name => {
+ self.$set(self, name, response.data.result[name])
+ })
+
+ self.items.forEach(item => {
+ self.decryptObject(self.items_encrypted_fields, item)
+ })
+
+ self.types.forEach(type => {
+ self.decryptObject(self.types_encrypted_fields, type)
+ })
+
+ }).catch(err => {
+
+ Swal.fire({title: "{{_('Error during loading of items') | escapejs}}", icon: "error", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+
+ },
+
+ async aDecryptObject (encrypted_fields, obj) {
+
+ var self = this
+
+ return new Promise((resolve) => {
+
+ let promises = encrypted_fields.map(field => {
+ // Encrypt all necessary fields
+ if (obj[field] == null) {
+ return null
+ }
+
+ return new Promise((resolve) => {
+ return decryptWithKey(self.crypto_key, obj[field]).then(dec => {
+ resolve({field: field, value: dec})
+ })
+ })
+
+ }).filter(e => e != null)
+
+ Promise.all(promises).then(values => {
+
+ values.forEach(value => {
+ obj[value.field] = value.value
+ })
+
+ resolve(obj)
+
+ })
+
+ })
+
+ },
+
+ decryptObject (encrypted_fields, obj) {
+
+ var self = this
+
+ return new Promise((resolve) => {
+
+ let promises = encrypted_fields.map(field => {
+ // Encrypt all necessary fields
+ if (obj[field] == null) {
+ return null
+ }
+
+ return new Promise((resolve) => {
+ return decryptWithKey(self.crypto_key, obj[field]).then(dec => {
+ resolve({field: field, value: dec})
+ })
+ })
+
+ }).filter(e => e != null)
+
+ Promise.all(promises).then(values => {
+
+ values.forEach(value => {
+ obj[value.field] = value.value
+ })
+
+ resolve(obj)
+
+ })
+
+ })
+
+ },
+
+ object_edition (url_edit, url_create, encrypted_fields, method, obj) {
+ // Return a Promise
+ var self = this
+
+ return new Promise((resolve) => {
+
+ let url = Urls[url_edit](obj.id)
+
+ if (obj.id == undefined || obj.id == null) {
+ url = Urls[url_create]()
+ }
+
+ let promises = encrypted_fields.map(field => {
+ // Encrypt all necessary fields
+ if (obj[field] == null) {
+ return null
+ }
+
+ return new Promise((resolve) => {
+ return encryptWithKey(self.crypto_key, obj[field]).then(enc => {
+ resolve({field: field, value: enc})
+ })
+ })
+
+ }).filter(e => e != null)
+
+ Promise.all(promises).then(values => {
+
+ values.forEach(value => {
+ obj[value.field] = value.value
+ })
+
+ self.$http[method](url, obj).then(response => {
+
+ if (method == "delete") {
+
+ resolve()
+
+ } else {
+
+ self.decryptObject(encrypted_fields, response.data.object).then(new_obj => {
+ resolve(new_obj)
+ })
+
+ }
+
+ }).catch(err => {
+
+ let msg = "{{_('Error during edition') | escapejs}}"
+ if (method == "delete") {
+ msg = "{{_('Error during deletion') | escapejs}}"
+ }
+
+ Swal.fire({title: msg, icon: "error", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+
+ })
+ })
+ },
+
+ item_edition (method, item) {
+ return this.object_edition("items:edit", "items:create", this.items_encrypted_fields, method, item)
+ },
+
+ type_edition (method, item) {
+ return this.object_edition("items:type.edit", "items:type.create", this.items_encrypted_fields, method, item)
+ },
+
+ createItem (item) {
+
+ var self = this
+
+ this.item_edition("post", item).then(new_item => {
+
+ self.items.push(new_item)
+
+ Swal.fire({title: "{{_('Item successfully created!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+
+ },
+
+ editItem (index, item) {
+
+ var self = this
+
+ this.item_edition("post", item).then(new_item => {
+
+ // Remove the 'current' (non edited) item from the list
+ self.items.splice(index, 1)
+ self.items.push(new_item)
+
+ Swal.fire({title: "{{_('Item successfully edited') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+ },
+
+ deleteItem (index) {
+
+ var self = this
+ var item = this.items[index]
+
+ this.item_edition("delete", item).then(() => {
+ self.items.splice(this.items.indexOf(item), 1)
+
+ Swal.fire({title: "{{_('Item successfully deleted!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+ },
+
+ createType (type) {
+
+ var self = this
+
+ this.type_edition("post", type).then(new_type => {
+
+ self.types.push(new_type)
+
+ Swal.fire({title: "{{_('Type successfully created!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+
+ },
+
+ editType (index, type) {
+
+ var self = this
+
+ this.type_edition("post", type).then(new_type => {
+
+ // Remove the 'current' (non edited) item from the list
+ self.types.splice(index, 1)
+ self.types.push(new_type)
+
+ Swal.fire({title: "{{_('Type successfully edited') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+ },
+
+ deleteType (index) {
+
+ var self = this
+ var type = this.types[index]
+
+ this.type_edition("delete", type).then(() => {
+ self.types.splice(this.types.indexOf(type), 1)
+
+ Swal.fire({title: "{{_('Type successfully deleted!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000})
+
+ })
+ },
+
+ },
+}
diff --git a/k356/items/templates/components/item/template.html b/k356/items/templates/components/item/template.html
deleted file mode 100644
index d4d2074..0000000
--- a/k356/items/templates/components/item/template.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load i18n %}
-
-
-
-
diff --git a/k356/items/templates/components/item/vue.js b/k356/items/templates/components/item/vue.js
deleted file mode 100644
index 1b8a100..0000000
--- a/k356/items/templates/components/item/vue.js
+++ /dev/null
@@ -1,4 +0,0 @@
-item = {
- template: "#item",
- props: ["crypto_key", "item"],
-}
diff --git a/k356/items/templates/components/item_list/template.html b/k356/items/templates/components/item_list/template.html
deleted file mode 100644
index b389e4f..0000000
--- a/k356/items/templates/components/item_list/template.html
+++ /dev/null
@@ -1,88 +0,0 @@
-{% load i18n %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% trans "New item" %}
-
-
-
-
-
-
-
-
-
- [[ data.item.name ]] - [[ data.item.custom_identifier ]]
-
-
-
-
-
-
-
-
-
-
- {% trans "Cancel" %}
- {% trans "Save" %}
-
-
-
-
-
-
- {% trans "Are you sure you want to delete this item?" %}
-
-
- {% trans "Cancel" %}
- {% trans "OK" %}
-
-
-
-
-
-
-
-
- mdi-pencil
- mdi-delete
-
-
-
- {% trans "Reset" %}
-
-
-
-
-
-
-
-
diff --git a/k356/items/templates/components/item_list/vue.js b/k356/items/templates/components/item_list/vue.js
deleted file mode 100644
index 3fbc8a3..0000000
--- a/k356/items/templates/components/item_list/vue.js
+++ /dev/null
@@ -1,191 +0,0 @@
-item_list = {
- template: "#item_list",
- delimiters: ["[[", "]]"],
- props: ["crypto_key", "locked"],
-
- data: function() {
- return {
- dialog: false,
- dialogDelete: false,
- editedIndex: -1,
- defaultItem: {},
- editedItem: {},
- search: null,
- data: {},
- }
- },
-
- mounted: function() {
-
- var self = this;
-
- this.$http.get(Urls["items:list"]()).then(response => {
-
- Object.keys(response.data.result).forEach(name => {
- self.$set(self.data, name, response.data.result[name]);
- });
-
- self.data.items.forEach(item => {
- self.decryptItem(item);
- });
-
- }).catch(err => {
-
- Swal.fire({title: "{{_('Error during loading of items.') | escapejs}}", icon: "error", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
-
- });
-
- },
-
- computed: {
- formTitle () {
- return this.editedIndex === -1 ? "{{_('New item') | escapejs}}" : "{{_('Edit item') | escapejs}}"
- },
- },
-
- watch: {
- dialog (val) {
- val || this.close()
- },
- dialogDelete (val) {
- val || this.closeDelete()
- },
- },
-
- methods: {
-
- decryptItem (item) {
- this.data.items_encrypted.forEach(field => {
- decryptWithKey(this.crypto_key, item[field]).then(dec => {
- item[field] = dec;
- })
- });
- return item;
- },
-
- editItem (item) {
- this.editedIndex = this.data.items.indexOf(item)
- this.editedItem = Object.assign({}, item)
- this.dialog = true
- },
-
- deleteItem (item) {
- this.editedIndex = this.data.items.indexOf(item)
- this.editedItem = Object.assign({}, item)
- this.dialogDelete = true
- },
-
- deleteItemConfirm () {
- var item = this.data.items[this.editedIndex];
-
- this.item_edition("delete", item).then(response => {
- this.data.items.splice(this.data.items.indexOf(item), 1)
- Swal.fire({title: "{{_('Item successfully deleted!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
- });
-
- this.closeDelete()
- },
-
- close () {
- this.dialog = false
- this.$nextTick(() => {
- this.editedItem = Object.assign({}, this.defaultItem)
- this.editedIndex = -1
- })
- },
-
- closeDelete () {
- this.dialogDelete = false
- this.$nextTick(() => {
- this.editedItem = Object.assign({}, this.defaultItem)
- this.editedIndex = -1
- })
- },
-
- item_edition (method, item) {
- // Return a Promise
- var self = this;
-
- return new Promise((resolve) => {
-
- let url = Urls["items:edit"](item.id)
-
- if (item.id == undefined || item.id == null) {
- url = Urls["items:create"]()
- }
-
- let promises = self.data.items_encrypted.map(field => {
- // Encrypt all necessary fields
- if (item[field] == null) {
- return null;
- }
-
- return new Promise((resolve) => {
- return encryptWithKey(self.crypto_key, item[field]).then(enc => {
- resolve({field: field, value: enc});
- });
- });
-
- }).filter(e => e != null);
-
- Promise.all(promises).then(values => {
-
- values.forEach(value => {
- item[value.field] = value.value;
- });
-
- self.$http[method](url, item).then(response => {
-
- resolve(response.data);
-
- }).catch(err => {
-
- let msg = "{{_('Error during edition of item') | escapejs}}";
- if (method == "delete") {
- msg = "{{_('Error during deletion of item') | escapejs}}";
- }
-
- Swal.fire({title: msg, icon: "error", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
-
- });
-
- });
- });
- },
-
- save () {
- if (this.editedIndex > -1) {
-
- var self = this;
-
- this.item_edition("post", this.editedItem).then(data => {
-
- self.data.items.splice(this.data.items.indexOf(self.editedItem), 1)
- console.log('pre edit', data.item)
- new_item = self.decryptItem(data.item);
- console.log('edited item', new_item);
- // self.data.items.push(self.decryptItem(data.item));
-
- Swal.fire({title: "{{_('Item successfully edited') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
-
- });
-
- } else {
-
- var self = this;
-
- this.item_edition("post", this.editedItem).then(data => {
- new_item = self.decryptItem(data.item);
- console.log('new item', new_item);
- // self.data.items.push(self.decryptItem(data.item));
-
- // console.log(data.item);
-
- Swal.fire({title: "{{_('Item successfully created!') | escapejs}}", icon: "success", position:"top-end", showConfirmButton: false, toast: true, timer: 1000});
- });
-
- }
- this.close()
- },
- }
-}
diff --git a/k356/items/urls.py b/k356/items/urls.py
index a8cdee7..cebf85f 100644
--- a/k356/items/urls.py
+++ b/k356/items/urls.py
@@ -1,5 +1,5 @@
from django.urls import path
-from items.views import item as item_view
+from items.views import item_view, type_view
app_name = "items"
@@ -7,4 +7,6 @@ urlpatterns = [
path("", item_view.item_list, name="list"),
path("", item_view.item_edit, name="edit"),
path("create", item_view.item_edit, {"id": None}, name="create"),
+ path("type/", type_view.type_edit, name="type.edit"),
+ path("type/create", type_view.type_edit, {"id": None}, name="type.create"),
]
diff --git a/k356/items/views/item.py b/k356/items/views/item_view.py
similarity index 88%
rename from k356/items/views/item.py
rename to k356/items/views/item_view.py
index a4c3068..031ccd4 100644
--- a/k356/items/views/item.py
+++ b/k356/items/views/item_view.py
@@ -1,6 +1,6 @@
import json
-from app.utils.api.api_list import encrypted_fields, header_for_table
+from app.utils.api.api_list import header_for_table
from django.contrib.auth.decorators import login_required
from django.db import models
from django.db.models.fields.related import RelatedField
@@ -12,18 +12,15 @@ from items.models import Item, ItemType
def item_list(request):
items = Item.objects.filter(author=request.user.setting)
-
types = ItemType.objects.filter(author=request.user.setting)
return JsonResponse(
{
"result": {
"items": list(items.serialize()),
- "types": list(types.serialize()),
"items_headers": header_for_table(Item),
+ "types": list(types.serialize()),
"types_headers": header_for_table(ItemType),
- "items_encrypted": encrypted_fields(Item),
- "types_encrypted": encrypted_fields(ItemType),
},
"count": items.count(),
}
@@ -85,6 +82,6 @@ def item_edit(request, id=None):
return JsonResponse(
{
- "item": Item.objects.filter(id=item.id).serialize().first(),
+ "object": Item.objects.filter(id=item.id).serialize().first(),
}
)
diff --git a/k356/items/views/type_view.py b/k356/items/views/type_view.py
new file mode 100644
index 0000000..35bfd6e
--- /dev/null
+++ b/k356/items/views/type_view.py
@@ -0,0 +1,67 @@
+import json
+
+from django.contrib.auth.decorators import login_required
+from django.db import models
+from django.db.models.fields.related import RelatedField
+from django.http import JsonResponse
+from items.models import ItemType
+
+
+@login_required
+def type_edit(request, id=None):
+ """Create/edit type view."""
+
+ if id:
+ item = ItemType.objects.filter(id=id, author=request.user.setting).first()
+
+ else:
+ item = ItemType(author=request.user.setting)
+
+ if not item:
+ return JsonResponse({}, status=404)
+
+ if request.method == "DELETE":
+ try:
+ item.delete()
+
+ except Exception:
+ return JsonResponse({"error": "INVALID_DELETE"}, status=401)
+
+ return JsonResponse({})
+
+ if request.method != "POST":
+ return JsonResponse({}, status=405)
+
+ try:
+ data = json.loads(request.body)
+
+ except Exception:
+ return JsonResponse({"error": "INVALID_DATA"}, status=401)
+
+ for field in item._meta.fields:
+ if field.name in item.Serialization.excluded_fields_edit:
+ continue
+
+ if isinstance(field, RelatedField):
+ # For now, disregard related field (fk, m2m, 1-1)
+ if isinstance(field, models.ForeignKey):
+ setattr(item, f"{field.name}_id", data[field.name])
+
+ continue
+
+ if field.name not in data:
+ continue
+
+ setattr(item, field.name, data[field.name])
+
+ try:
+ item.save()
+
+ except Exception:
+ return JsonResponse({"error": "DATA_INVALID"}, status=401)
+
+ return JsonResponse(
+ {
+ "object": ItemType.objects.filter(id=item.id).serialize().first(),
+ }
+ )
diff --git a/k356/main/templates/components/encryption-testing/template.html b/k356/main/templates/components/EncryptionTesting/template.html
similarity index 100%
rename from k356/main/templates/components/encryption-testing/template.html
rename to k356/main/templates/components/EncryptionTesting/template.html
diff --git a/k356/main/templates/components/encryption-testing/vue.js b/k356/main/templates/components/EncryptionTesting/vue.js
similarity index 92%
rename from k356/main/templates/components/encryption-testing/vue.js
rename to k356/main/templates/components/EncryptionTesting/vue.js
index 9824ec7..860f964 100644
--- a/k356/main/templates/components/encryption-testing/vue.js
+++ b/k356/main/templates/components/EncryptionTesting/vue.js
@@ -1,5 +1,5 @@
-encryption_testing = {
- template: "#encryption-testing",
+EncryptionTesting = {
+ template: "#EncryptionTesting",
props: ["crypto_key"],
data: function() {
return {
diff --git a/k356/main/templates/components/k356-loading/template.html b/k356/main/templates/components/Loading/template.html
similarity index 100%
rename from k356/main/templates/components/k356-loading/template.html
rename to k356/main/templates/components/Loading/template.html
diff --git a/k356/main/templates/components/k356-loading/vue.js b/k356/main/templates/components/Loading/vue.js
similarity index 98%
rename from k356/main/templates/components/k356-loading/vue.js
rename to k356/main/templates/components/Loading/vue.js
index 36b6126..f388af4 100644
--- a/k356/main/templates/components/k356-loading/vue.js
+++ b/k356/main/templates/components/Loading/vue.js
@@ -1,7 +1,7 @@
const rvalidate = Vue.resource(Urls["users:k356.validate"]);
-k356_loading = {
- template: "#k356-loading",
+Loading = {
+ template: "#Loading",
props: ["crypto_key"],
data: function() {
diff --git a/k356/main/templates/main/home.html b/k356/main/templates/main/home.html
deleted file mode 100644
index 8594a28..0000000
--- a/k356/main/templates/main/home.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "base.html" %}
-
-{% load i18n %}
-
-{% block title %}{% trans "Home" %}{% endblock %}
-{% block body %}
-
-
-
-{% endblock %}
diff --git a/k356/main/templatetags/__init__.py b/k356/main/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/k356/main/templatetags/main.py b/k356/main/templatetags/main.py
new file mode 100644
index 0000000..b61709a
--- /dev/null
+++ b/k356/main/templatetags/main.py
@@ -0,0 +1,9 @@
+from django import template
+
+register = template.Library()
+
+
+@register.simple_tag(takes_context=True)
+def define(context, key, value):
+ context.dicts[0][key] = value
+ return ""
diff --git a/k356/templates/base.html b/k356/templates/base.html
index ea05565..197f52f 100644
--- a/k356/templates/base.html
+++ b/k356/templates/base.html
@@ -11,9 +11,7 @@
-
-
@@ -28,14 +26,22 @@
+
+
+
-
-
+
+