diff --git a/cookbook/admin.py b/cookbook/admin.py
index cb0d4307d..c39d4e861 100644
--- a/cookbook/admin.py
+++ b/cookbook/admin.py
@@ -5,3 +5,8 @@ from .models import *
admin.site.register(Recipe)
admin.site.register(Keyword)
admin.site.register(Category)
+
+admin.site.register(Sync)
+admin.site.register(SyncLog)
+admin.site.register(RecipeImport)
+admin.site.register(Storage)
diff --git a/cookbook/filters.py b/cookbook/filters.py
index 91972678b..d5d84d874 100644
--- a/cookbook/filters.py
+++ b/cookbook/filters.py
@@ -6,7 +6,8 @@ from cookbook.models import Recipe, Keyword
class RecipeFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='contains')
- keywords = django_filters.ModelMultipleChoiceFilter(queryset=Keyword.objects.all(), widget=MultiSelectWidget, method='filter_keywords')
+ keywords = django_filters.ModelMultipleChoiceFilter(queryset=Keyword.objects.all(), widget=MultiSelectWidget,
+ method='filter_keywords')
@staticmethod
def filter_keywords(queryset, name, value):
@@ -19,3 +20,14 @@ class RecipeFilter(django_filters.FilterSet):
class Meta:
model = Recipe
fields = ['name', 'category', 'keywords']
+
+
+class QuickRecipeFilter(django_filters.FilterSet):
+ name = django_filters.CharFilter(lookup_expr='contains')
+ category = django_filters.CharFilter(lookup_expr='contains')
+ keywords = django_filters.ModelMultipleChoiceFilter(queryset=Keyword.objects.all(), widget=MultiSelectWidget,
+ method='filter_keywords')
+
+ class Meta:
+ model = Recipe
+ fields = ['name', 'category', 'keywords']
diff --git a/cookbook/forms.py b/cookbook/forms.py
index a57c6b8c8..5e4efd694 100644
--- a/cookbook/forms.py
+++ b/cookbook/forms.py
@@ -1,7 +1,8 @@
-from django.utils.translation import gettext as _
from django import forms
-from .models import *
from django.forms import widgets
+from django.utils.translation import gettext as _
+
+from .models import *
class MultiSelectWidget(widgets.SelectMultiple):
@@ -44,8 +45,10 @@ class KeywordForm(forms.ModelForm):
class StorageForm(forms.ModelForm):
username = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password'}), required=False)
- password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}), required=False)
- token = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}), required=False)
+ password = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}),
+ required=False)
+ token = forms.CharField(widget=forms.TextInput(attrs={'autocomplete': 'new-password', 'type': 'password'}),
+ required=False)
class Meta:
model = Storage
@@ -61,10 +64,8 @@ class SyncForm(forms.ModelForm):
class BatchEditForm(forms.Form):
search = forms.CharField(label=_('Search String'))
category = forms.ModelChoiceField(queryset=Category.objects.all().order_by('id'), required=False)
- keywords = forms.ModelMultipleChoiceField(queryset=Keyword.objects.all().order_by('id'), required=False)
-
- class Media:
- js = ('custom/js/form_multiselect.js',)
+ keywords = forms.ModelMultipleChoiceField(queryset=Keyword.objects.all().order_by('id'), required=False,
+ widget=MultiSelectWidget)
class ImportRecipeForm(forms.ModelForm):
diff --git a/cookbook/models.py b/cookbook/models.py
index 35bfa27f8..73bbae6ec 100644
--- a/cookbook/models.py
+++ b/cookbook/models.py
@@ -23,6 +23,9 @@ class Sync(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
+ def __str__(self):
+ return self.path
+
class SyncLog(models.Model):
sync = models.ForeignKey(Sync, on_delete=models.CASCADE)
@@ -79,3 +82,6 @@ class RecipeImport(models.Model):
storage = models.ForeignKey(Storage, on_delete=models.PROTECT)
path = models.CharField(max_length=512, default="")
created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return self.name
\ No newline at end of file
diff --git a/cookbook/templates/base.html b/cookbook/templates/base.html
index 9f238472f..7bb9bfca4 100644
--- a/cookbook/templates/base.html
+++ b/cookbook/templates/base.html
@@ -93,9 +93,9 @@
{% trans 'Manage Data' %}
diff --git a/cookbook/templates/batch/monitor.html b/cookbook/templates/batch/monitor.html
index 135af6901..1550bd4cf 100644
--- a/cookbook/templates/batch/monitor.html
+++ b/cookbook/templates/batch/monitor.html
@@ -24,7 +24,7 @@
- {% trans 'Sync Now!' %}
+ {% trans 'Sync Now!' %}
{% render_table monitored_paths %}
diff --git a/cookbook/templates/batch/waiting.html b/cookbook/templates/batch/waiting.html
index de51ef42f..29164ffae 100644
--- a/cookbook/templates/batch/waiting.html
+++ b/cookbook/templates/batch/waiting.html
@@ -9,17 +9,24 @@
{% trans 'Importing Recipes' %}
-
+
+
+
+
+
+
+ {% trans 'This can take a few minutes, depending on the number of recipes in sync, please wait.' %}
+
diff --git a/cookbook/templates/generic/list_template.html b/cookbook/templates/generic/list_template.html
index 4732b4c31..69a992eac 100644
--- a/cookbook/templates/generic/list_template.html
+++ b/cookbook/templates/generic/list_template.html
@@ -18,7 +18,7 @@
{% if table.Meta.model|get_class == 'RecipeImport' %}
- {% trans 'Import all' %}
+ {% trans 'Import all' %}
{% endif %}
diff --git a/cookbook/templates/index.html b/cookbook/templates/index.html
index 3a5890968..1618d3cb7 100644
--- a/cookbook/templates/index.html
+++ b/cookbook/templates/index.html
@@ -16,18 +16,16 @@
{% if filter %}
-
{% endif %}
diff --git a/cookbook/templates/stats.html b/cookbook/templates/stats.html
new file mode 100644
index 000000000..24b162fd3
--- /dev/null
+++ b/cookbook/templates/stats.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block title %}{% trans 'Stats' %}{% endblock %}
+
+
+{% block content %}
+
+
+ {% trans 'Statistics' %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/cookbook/urls.py b/cookbook/urls.py
index 958c9b87f..333769cd5 100644
--- a/cookbook/urls.py
+++ b/cookbook/urls.py
@@ -36,10 +36,11 @@ urlpatterns = [
path('delete/import/
/', edit.ImportDelete.as_view(), name='delete_import'),
path('delete/storage//', edit.StorageDelete.as_view(), name='delete_storage'),
- path('batch/sync', batch.batch_monitor, name='batch_monitor'), # TODO move to generic "new" view
- path('batch/edit', batch.batch_edit, name='batch_edit'),
- path('batch/import/all', batch.batch_import_all, name='batch_import_all'),
- path('batch/sync/wait', batch.sync_wait, name='batch_sync_wait'),
+ path('data/sync', data.sync, name='data_sync'), # TODO move to generic "new" view
+ path('data/batch/edit', data.batch_edit, name='data_batch_edit'),
+ path('data/batch/import', data.batch_import, name='data_batch_import'),
+ path('data/sync/wait', data.sync_wait, name='data_sync_wait'),
+ path('data/statistics', data.statistics, name='data_stats'),
path('api/get_file_link//', api.get_file_link, name='api_get_file_link'),
path('api/sync_all/', api.sync_all, name='api_sync'),
diff --git a/cookbook/views/__init__.py b/cookbook/views/__init__.py
index d6ec7ae9d..49380f828 100644
--- a/cookbook/views/__init__.py
+++ b/cookbook/views/__init__.py
@@ -1,6 +1,6 @@
from cookbook.views.views import *
from cookbook.views.api import *
-from cookbook.views.batch import *
+from cookbook.views.data import *
from cookbook.views.edit import *
from cookbook.views.new import *
from cookbook.views.lists import *
\ No newline at end of file
diff --git a/cookbook/views/batch.py b/cookbook/views/data.py
similarity index 81%
rename from cookbook/views/batch.py
rename to cookbook/views/data.py
index 328f82a14..27d7aff40 100644
--- a/cookbook/views/batch.py
+++ b/cookbook/views/data.py
@@ -3,16 +3,16 @@ from datetime import datetime
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
+from django.utils.translation import ngettext
from django_tables2 import RequestConfig
from cookbook.forms import SyncForm, BatchEditForm, RecipeImport
-from cookbook.models import Recipe, Category, Sync
+from cookbook.models import Recipe, Sync
from cookbook.tables import SyncTable
-from django.utils.translation import gettext as _, ngettext
@login_required
-def batch_monitor(request):
+def sync(request):
if request.method == "POST":
form = SyncForm(request.POST)
if form.is_valid():
@@ -21,7 +21,7 @@ def batch_monitor(request):
new_path.storage = form.cleaned_data['storage']
new_path.last_checked = datetime.now()
new_path.save()
- return redirect('batch_monitor')
+ return redirect('data_sync')
else:
form = SyncForm()
@@ -37,7 +37,7 @@ def sync_wait(request):
@login_required
-def batch_import_all(request):
+def batch_import(request):
imports = RecipeImport.objects.all()
for new_recipe in imports:
recipe = Recipe(name=new_recipe.name, path=new_recipe.path, storage=new_recipe.storage)
@@ -54,17 +54,17 @@ def batch_edit(request):
if form.is_valid():
word = form.cleaned_data['search']
category = form.cleaned_data['category']
- keyword = form.cleaned_data['keyword']
+ keywords = form.cleaned_data['keywords']
recipes = Recipe.objects.filter(name__contains=word)
count = 0
for recipe in recipes:
edit = False
if category is not None:
- recipe.category = Category.objects.get(name=category)
+ recipe.category = category
edit = True
- if keyword.__sizeof__() > 0:
- recipe.keywords.add(*list(keyword))
+ if keywords.__sizeof__() > 0:
+ recipe.keywords.add(*list(keywords))
edit = True
if edit:
count = count + 1
@@ -79,8 +79,13 @@ def batch_edit(request):
}
messages.add_message(request, messages.SUCCESS, msg)
- return redirect('batch_edit')
+ return redirect('data_batch_edit')
else:
form = BatchEditForm()
return render(request, 'batch/edit.html', {'form': form})
+
+
+@login_required
+def statistics(request):
+ return render(request, 'index.html')
diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py
index af199c175..dfb181dd4 100644
--- a/cookbook/views/edit.py
+++ b/cookbook/views/edit.py
@@ -142,7 +142,7 @@ class ImportDelete(LoginRequiredMixin, DeleteView):
class MonitorDelete(LoginRequiredMixin, DeleteView):
template_name = "generic\delete_template.html"
model = Sync
- success_url = reverse_lazy('batch_monitor')
+ success_url = reverse_lazy('data_sync')
def get_context_data(self, **kwargs):
context = super(MonitorDelete, self).get_context_data(**kwargs)