V1.31 exercise_type clone, evaluation inline

This commit is contained in:
Tibor Bossanyi (Freelancer)
2021-10-19 08:23:52 +02:00
parent ae805ffcf5
commit 2a4731dc29
26 changed files with 295 additions and 100 deletions
@@ -5,7 +5,7 @@ from .exercise_plan_template import ExercisePlanTemplateAdmin, ExercisePlanTempl
from .product import ProductAdmin from .product import ProductAdmin
from .exercise_device import ExerciseDeviceAdmin from .exercise_device import ExerciseDeviceAdmin
from .tutorial import TutorialAdmin from .tutorial import TutorialAdmin
from .evaluation import EvaluationAdmin, EvaluationAttributeAdmin from .evaluation import EvaluationAdmin
from .exercise_plan import ExercisePlanAdmin from .exercise_plan import ExercisePlanAdmin
from .description import DescriptionAdmin from .description import DescriptionAdmin
from .training_plan import TrainingPlanAdmin, TrainingPlanDetailAdmin from .training_plan import TrainingPlanAdmin, TrainingPlanDetailAdmin
@@ -5,5 +5,5 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<p>Controlling</p> <p>Controlling2</p>
{% endblock %} {% endblock %}
@@ -25,5 +25,5 @@ class ControllingAdmin(admin.ModelAdmin):
] ]
admin.site.register(Controlling, ControllingAdmin) #admin.site.register(Controlling, ControllingAdmin)
admin.autodiscover() #admin.autodiscover()
@@ -19,5 +19,5 @@ class DescriptionAdmin(admin.ModelAdmin):
] ]
admin.site.register(Description, DescriptionAdmin) #admin.site.register(Description, DescriptionAdmin)
admin.autodiscover() #admin.autodiscover()
@@ -1,32 +1,42 @@
from adminsortable2.admin import SortableInlineAdminMixin
from django.contrib import admin from django.contrib import admin
#from .inline_select_action import BaseInlineSelectActionsMixin
from inline_actions.admin import InlineActionsMixin, InlineActionsModelAdminMixin
from ..models.evaluation import EvaluationAttribute, Evaluation from ..models.evaluation import EvaluationAttribute, Evaluation
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
class EvaluationAdmin(admin.ModelAdmin): class EvaluationAttributeInline(InlineActionsMixin, SortableInlineAdminMixin, admin.TabularInline):
model = EvaluationAttribute
extra = 0
list_display = (
'sort', 'evaluation_attr_id', 'name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
list_editable = ('sort', 'name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
list_display_links = ('sort', )
ordering = ('sort',)
inline_actions = ('clone_eval',)
def clone_eval(self, request, obj, parent_obj=None):
print("cloning {obj}")
obj.pk = None
obj.name = obj.name + "_copy"
obj.save()
messages.info(request, f'{obj} has been cloned')
clone_eval.short_description = _("Clone the selected evaluation")
class EvaluationAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin):
list_display = ('evaluation_id', 'name', 'get_exercise_type') list_display = ('evaluation_id', 'name', 'get_exercise_type')
def get_exercise_type(self, obj): def get_exercise_type(self, obj):
return obj.exercise_type.name return obj.exercise_type.name
inlines = [
class EvaluationAttributeAdmin(admin.ModelAdmin): EvaluationAttributeInline
list_display = ( ]
'evaluation_attr_id', 'name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
list_editable = ('name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
list_filter = ('evaluation',)
def copy_attributes(self, request, queryset):
for objectAttr in reversed(queryset):
objectAttr.pk = None
objectAttr.name = objectAttr.name + "_copy"
objectAttr.save()
copy_attributes.short_description = "Clone the selected attribute"
actions = [copy_attributes]
admin.site.register(Evaluation, EvaluationAdmin) admin.site.register(Evaluation, EvaluationAdmin)
admin.site.register(EvaluationAttribute, EvaluationAttributeAdmin)
admin.autodiscover() admin.autodiscover()
@@ -50,6 +50,15 @@ class ExerciseTypeAdmin(admin.ModelAdmin):
list_display = ('exercise_type_id', 'name_colored', 'active', 'base', 'buddy_warning', 'is_description', 'is_desc_hu', 'alternatives') list_display = ('exercise_type_id', 'name_colored', 'active', 'base', 'buddy_warning', 'is_description', 'is_desc_hu', 'alternatives')
search_fields = ['name', 'exercisetypetranslation__name'] search_fields = ['name', 'exercisetypetranslation__name']
fields = ('name', 'description', 'unit', 'unit_quantity', 'unit_quantity_unit', 'active', 'base', 'buddy_warning') fields = ('name', 'description', 'unit', 'unit_quantity', 'unit_quantity_unit', 'active', 'base', 'buddy_warning')
list_filter = ('active','base', 'buddy_warning')
actions = ('clone',)
@admin.action(description=_('Clone exercise type'))
def clone(modeladmin, request, queryset):
for qs in queryset:
qs.pk = None
qs.name = qs.name + "_copy"
qs.save()
def name_colored(self, obj): def name_colored(self, obj):
if obj.active: if obj.active:
@@ -108,7 +108,7 @@ class BaseInlineSelectActionsMixin:
) )
) )
print("Buttons " + str(buttons)) #print("Buttons " + str(buttons))
return mark_safe( return mark_safe(
'<div class="submit_row inline_select_actions">{}</div>'.format(''.join(buttons)) '<div class="submit_row inline_select_actions">{}</div>'.format(''.join(buttons))
) )
@@ -7,5 +7,5 @@ class ProductAdmin(admin.ModelAdmin):
list_display = ('product_id', 'name', 'type') list_display = ('product_id', 'name', 'type')
admin.site.register(Product, ProductAdmin) #admin.site.register(Product, ProductAdmin)
admin.autodiscover() #admin.autodiscover()
@@ -18,7 +18,7 @@ class TrainingPlanDetailInline(BaseInlineSelectActionsMixin, SortableInlineAdmin
list_display_links = ('sort', ) list_display_links = ('sort', )
ordering = ('sort',) ordering = ('sort',)
inline_select_actions = ['copy_attributes',] inline_select_actions = ['clone',]
def repeat_max(self, obj): def repeat_max(self, obj):
if obj.repeat_max: if obj.repeat_max:
@@ -47,7 +47,7 @@ class TrainingPlanDetailInline(BaseInlineSelectActionsMixin, SortableInlineAdmin
return actions return actions
@admin.action(description='clone') @admin.action(description='clone')
def copy_attributes(self, request, obj, parent_obj=None): def clone(self, request, obj, parent_obj=None):
name = str(request.queryset[0].training_plan) name = str(request.queryset[0].training_plan)
details = TrainingPlanDetail.objects.filter(training_plan__name=name).order_by('sort') details = TrainingPlanDetail.objects.filter(training_plan__name=name).order_by('sort')
@@ -59,7 +59,7 @@ class TrainingPlanDetailInline(BaseInlineSelectActionsMixin, SortableInlineAdmin
objectAttr.save() objectAttr.save()
new_sort = new_sort + 1 new_sort = new_sort + 1
copy_attributes.short_description = _("Clone the selected Training Plan Detail") clone.short_description = _("Clone the selected Training Plan Detail")
def select_max_repeat(self, request, queryset): def select_max_repeat(self, request, queryset):
for obj in queryset: for obj in queryset:
@@ -93,6 +93,6 @@ class TutorialAdmin(admin.ModelAdmin):
fields = ('name',) fields = ('name',)
admin.site.register(Tutorial, TutorialAdmin) #admin.site.register(Tutorial, TutorialAdmin)
admin.site.register(TutorialSteps, TutorialStepsAdmin) #admin.site.register(TutorialSteps, TutorialStepsAdmin)
admin.autodiscover() #admin.autodiscover()
@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-26 11:21+0200\n" "POT-Creation-Date: 2021-10-17 10:52+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -22,14 +22,17 @@ msgstr ""
#: .\aitrainer_backoffice\admin\exercise_device.py:32 #: .\aitrainer_backoffice\admin\exercise_device.py:32
#: .\aitrainer_backoffice\admin\exercise_type.py:27 #: .\aitrainer_backoffice\admin\exercise_type.py:27
#: .\aitrainer_backoffice\admin\exercisetree.py:41 #: .\aitrainer_backoffice\admin\exercisetree.py:41
#: .\aitrainer_backoffice\admin\notification.py:21
msgid "Image Preview" msgid "Image Preview"
msgstr "Kép előnézet" msgstr "Kép előnézet"
#: .\aitrainer_backoffice\admin\evaluation.py:29
msgid "Clone the selected evaluation"
msgstr "Kiértékelés klónozása"
#: .\aitrainer_backoffice\admin\inline_select_action.py:116 #: .\aitrainer_backoffice\admin\inline_select_action.py:116
#, fuzzy
#| msgid "Descriptions"
msgid "Actions" msgid "Actions"
msgstr "Leírás" msgstr "Akciók"
#: .\aitrainer_backoffice\admin\training_plan.py:30 #: .\aitrainer_backoffice\admin\training_plan.py:30
#: .\aitrainer_backoffice\admin\training_plan.py:159 #: .\aitrainer_backoffice\admin\training_plan.py:159
@@ -43,10 +46,8 @@ msgstr "Ismétlés: -1, HA MAX ismétlés"
#: .\aitrainer_backoffice\admin\training_plan.py:62 #: .\aitrainer_backoffice\admin\training_plan.py:62
#: .\aitrainer_backoffice\admin\training_plan.py:185 #: .\aitrainer_backoffice\admin\training_plan.py:185
#, fuzzy
#| msgid "Training Plan Detail"
msgid "Clone the selected Training Plan Detail" msgid "Clone the selected Training Plan Detail"
msgstr "Edzésprogram részlet" msgstr "Edzésprogram klónozása"
#: .\aitrainer_backoffice\admin\training_plan.py:69 #: .\aitrainer_backoffice\admin\training_plan.py:69
#: .\aitrainer_backoffice\admin\training_plan.py:192 #: .\aitrainer_backoffice\admin\training_plan.py:192
@@ -63,11 +64,10 @@ msgid "text_key"
msgstr "Szöveg kulcs" msgstr "Szöveg kulcs"
#: .\aitrainer_backoffice\models\app_text.py:11 #: .\aitrainer_backoffice\models\app_text.py:11
msgid "App képernyőkép" msgid "App Screenshot"
msgstr "" msgstr "Képernyőkép"
#: .\aitrainer_backoffice\models\app_text.py:12 #: .\aitrainer_backoffice\models\app_text.py:12
#| msgid "Translations"
msgid "Checked, Translation is OK" msgid "Checked, Translation is OK"
msgstr "Fordítás rendben, ellenőrizve" msgstr "Fordítás rendben, ellenőrizve"
@@ -88,7 +88,7 @@ msgstr "App Fordítások"
#: .\aitrainer_backoffice\models\exercisetree.py:36 #: .\aitrainer_backoffice\models\exercisetree.py:36
#: .\aitrainer_backoffice\models\faq.py:34 #: .\aitrainer_backoffice\models\faq.py:34
#: .\aitrainer_backoffice\models\property.py:29 #: .\aitrainer_backoffice\models\property.py:29
#: .\aitrainer_backoffice\models\sports.py:31 #: .\aitrainer_backoffice\models\sports.py:29
#: .\aitrainer_backoffice\models\training_plan.py:58 #: .\aitrainer_backoffice\models\training_plan.py:58
#: .\aitrainer_backoffice\models\training_plan_day.py:31 #: .\aitrainer_backoffice\models\training_plan_day.py:31
#: .\aitrainer_backoffice\models\tutorial.py:45 #: .\aitrainer_backoffice\models\tutorial.py:45
@@ -104,20 +104,21 @@ msgstr "Fordítás"
#: .\aitrainer_backoffice\models\exercisetree.py:37 #: .\aitrainer_backoffice\models\exercisetree.py:37
#: .\aitrainer_backoffice\models\faq.py:35 #: .\aitrainer_backoffice\models\faq.py:35
#: .\aitrainer_backoffice\models\property.py:30 #: .\aitrainer_backoffice\models\property.py:30
#: .\aitrainer_backoffice\models\sports.py:32 #: .\aitrainer_backoffice\models\sports.py:30
#: .\aitrainer_backoffice\models\training_plan.py:59 #: .\aitrainer_backoffice\models\training_plan.py:59
#: .\aitrainer_backoffice\models\training_plan_day.py:32 #: .\aitrainer_backoffice\models\training_plan_day.py:32
#: .\aitrainer_backoffice\models\tutorial.py:46 #: .\aitrainer_backoffice\models\tutorial.py:46
msgid "Translations" msgid "Translations"
msgstr "Fordítások" msgstr "Fordítások"
#: .\aitrainer_backoffice\models\customer.py:9
#: .\aitrainer_backoffice\models\description.py:11 #: .\aitrainer_backoffice\models\description.py:11
#: .\aitrainer_backoffice\models\evaluation.py:41 #: .\aitrainer_backoffice\models\evaluation.py:41
#: .\aitrainer_backoffice\models\faq.py:11 #: .\aitrainer_backoffice\models\faq.py:11
#: .\aitrainer_backoffice\models\faq.py:29 #: .\aitrainer_backoffice\models\faq.py:29
#: .\aitrainer_backoffice\models\split_tests.py:7 #: .\aitrainer_backoffice\models\split_tests.py:7
#: .\aitrainer_backoffice\models\sports.py:11 #: .\aitrainer_backoffice\models\sports.py:9
#: .\aitrainer_backoffice\models\sports.py:27 #: .\aitrainer_backoffice\models\sports.py:25
#: .\aitrainer_backoffice\models\training_plan.py:14 #: .\aitrainer_backoffice\models\training_plan.py:14
#: .\aitrainer_backoffice\models\training_plan_day.py:11 #: .\aitrainer_backoffice\models\training_plan_day.py:11
#: .\aitrainer_backoffice\models\training_plan_day.py:27 #: .\aitrainer_backoffice\models\training_plan_day.py:27
@@ -125,6 +126,21 @@ msgstr "Fordítások"
msgid "name" msgid "name"
msgstr "Név" msgstr "Név"
#: .\aitrainer_backoffice\models\customer.py:10
#| msgid "name"
msgid "firstname"
msgstr "Keresztnév"
#: .\aitrainer_backoffice\models\customer.py:28
#| msgid "Customer Property"
msgid "Customer"
msgstr "Ügyfél"
#: .\aitrainer_backoffice\models\customer.py:29
#| msgid "Customer Properties"
msgid "Customers"
msgstr "Ügyfelek"
#: .\aitrainer_backoffice\models\description.py:19 #: .\aitrainer_backoffice\models\description.py:19
msgid "Description" msgid "Description"
msgstr "Leírás" msgstr "Leírás"
@@ -147,7 +163,7 @@ msgstr "Kiértékelés"
#: .\aitrainer_backoffice\models\evaluation.py:17 #: .\aitrainer_backoffice\models\evaluation.py:17
msgid "Evaluations" msgid "Evaluations"
msgstr "Kiértékelés Csoport" msgstr "Kiértékelések"
#: .\aitrainer_backoffice\models\evaluation.py:40 #: .\aitrainer_backoffice\models\evaluation.py:40
msgid "evaluation_foreign" msgid "evaluation_foreign"
@@ -181,13 +197,13 @@ msgstr "Osztályozás"
msgid "suggestion" msgid "suggestion"
msgstr "Javaslat" msgstr "Javaslat"
#: .\aitrainer_backoffice\models\evaluation.py:54
msgid "Evaluation Table"
msgstr "Kiértékelés tábla"
#: .\aitrainer_backoffice\models\evaluation.py:55 #: .\aitrainer_backoffice\models\evaluation.py:55
msgid "Evaluation Table"
msgstr "Kiértékelés"
#: .\aitrainer_backoffice\models\evaluation.py:56
msgid "Evaluation Tables" msgid "Evaluation Tables"
msgstr "Kiértékelés táblák" msgstr "Kiértékelések"
#: .\aitrainer_backoffice\models\exercise_device.py:18 #: .\aitrainer_backoffice\models\exercise_device.py:18
#: .\aitrainer_backoffice\models\exercise_type.py:87 #: .\aitrainer_backoffice\models\exercise_type.py:87
@@ -301,6 +317,15 @@ msgstr "GYÍK"
msgid "FAQs" msgid "FAQs"
msgstr "GYÍK" msgstr "GYÍK"
#: .\aitrainer_backoffice\models\notification.py:20
msgid "Notification"
msgstr ""
#: .\aitrainer_backoffice\models\notification.py:21
#| msgid "Descriptions"
msgid "Notifications"
msgstr ""
#: .\aitrainer_backoffice\models\product.py:24 #: .\aitrainer_backoffice\models\product.py:24
msgid "Product" msgid "Product"
msgstr "Termék" msgstr "Termék"
@@ -333,11 +358,11 @@ msgstr "A/B Teszt"
msgid "A/B Tests" msgid "A/B Tests"
msgstr "A/B Tesztek" msgstr "A/B Tesztek"
#: .\aitrainer_backoffice\models\sports.py:15 #: .\aitrainer_backoffice\models\sports.py:13
msgid "Sport" msgid "Sport"
msgstr "" msgstr ""
#: .\aitrainer_backoffice\models\sports.py:16 #: .\aitrainer_backoffice\models\sports.py:14
msgid "Sports" msgid "Sports"
msgstr "" msgstr ""
@@ -358,13 +383,11 @@ msgid "Training Plan Details"
msgstr "Edzésprogram részletek" msgstr "Edzésprogram részletek"
#: .\aitrainer_backoffice\models\training_plan_day.py:15 #: .\aitrainer_backoffice\models\training_plan_day.py:15
#, fuzzy
#| msgid "Training Plan" #| msgid "Training Plan"
msgid "Training Day" msgid "Training Day"
msgstr "Edzésnap" msgstr "Edzésnap"
#: .\aitrainer_backoffice\models\training_plan_day.py:16 #: .\aitrainer_backoffice\models\training_plan_day.py:16
#, fuzzy
#| msgid "Training Plans" #| msgid "Training Plans"
msgid "Training Days" msgid "Training Days"
msgstr "Edzésnapok" msgstr "Edzésnapok"
@@ -8,7 +8,7 @@ class AppText(models.Model):
text_id = models.AutoField(primary_key=True) text_id = models.AutoField(primary_key=True)
text_key = models.TextField(max_length=255, help_text='Do not edit this! It is the key in the mobile app', text_key = models.TextField(max_length=255, help_text='Do not edit this! It is the key in the mobile app',
verbose_name=_("text_key")) verbose_name=_("text_key"))
screenshot_url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768', blank=True,verbose_name=_("App képernyőkép") ) screenshot_url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768', blank=True,verbose_name=_("App Screenshot") )
checked = models.BooleanField(blank=True, verbose_name=_("Checked, Translation is OK")) checked = models.BooleanField(blank=True, verbose_name=_("Checked, Translation is OK"))
class Meta: class Meta:
@@ -15,6 +15,7 @@ class Customer(models.Model):
date_add = models.DateField() date_add = models.DateField()
synced_date = models.DateTimeField(blank=True,null=True) synced_date = models.DateTimeField(blank=True,null=True)
firebase_reg_token = models.CharField(max_length=255, blank=True, null=True) firebase_reg_token = models.CharField(max_length=255, blank=True, null=True)
lang = models.CharField(max_length=5, blank=True, null=True)
def has_add_permission(self, request): def has_add_permission(self, request):
return False return False
@@ -48,11 +48,13 @@ class EvaluationAttribute(models.Model):
verbose_name=_("evaluation_text")) verbose_name=_("evaluation_text"))
suggestion = models.TextField(max_length=1000, blank=True, null=True, help_text="English suggestion here", suggestion = models.TextField(max_length=1000, blank=True, null=True, help_text="English suggestion here",
verbose_name=_("suggestion")) verbose_name=_("suggestion"))
sort = models.IntegerField()
class Meta: class Meta:
db_table = 'evaluation_attribute' db_table = 'evaluation_attribute'
verbose_name = _("Evaluation Table") verbose_name = _("Evaluation Table")
verbose_name_plural = _("Evaluation Tables") verbose_name_plural = _("Evaluation Tables")
ordering = ['sort']
def __str__(self): def __str__(self):
return self.name return self.name
@@ -1,7 +1,7 @@
import os import os
from firebase_admin import initialize_app from firebase_admin import initialize_app
BACKOFFICE_VERSION = "1.30" BACKOFFICE_VERSION = "1.31"
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -9,16 +9,18 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')] LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')]
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ['DJANGO_KEY'] SECRET_KEY = "lkasdjhklj84ujn3jk4nr5j43njk" #os.environ['DJANGO_KEY']
GOOGLE_APPLICATION_CREDENTIALS="/aitrainer_backoffice/aitrainer_backoffice/aitrainer_backoffice/asset/aitrainer-firebase-adminsdk.json"
os.environ["WORKOUTTEST_SETTING"] = "DEPLOY" os.environ["WORKOUTTEST_SETTING"] = "DEPLOY"
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False DEBUG = False
ALLOWED_HOSTS = ['62.171.188.119', "admin.aitrainer.app"] ALLOWED_HOSTS = ['62.171.188.119', "admin.aitrainer.app"]
env = os.environ['GOOGLE_APPLICATION_CREDENTIALS'] #env = os.environ['GOOGLE_APPLICATION_CREDENTIALS']
FIREBASE_APP = initialize_app() FIREBASE_APP = initialize_app()
DEFAULT_AUTO_FIELD='django.db.models.AutoField' DEFAULT_AUTO_FIELD='django.db.models.AutoField'
@@ -1,7 +1,7 @@
import os import os
from firebase_admin import initialize_app from firebase_admin import initialize_app
BACKOFFICE_VERSION = "1.30" BACKOFFICE_VERSION = "1.31"
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -1,7 +1,7 @@
import os import os
from firebase_admin import initialize_app from firebase_admin import initialize_app
BACKOFFICE_VERSION = "1.30" BACKOFFICE_VERSION = "1.31"
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -0,0 +1,30 @@
{% load i18n admin_urls static %}
<div class="js-inline-admin-formset inline-group"
id="{{ inline_admin_formset.formset.prefix }}-group"
data-inline-type="stacked"
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
<fieldset class="module {{ inline_admin_formset.classes }}">
{% if inline_admin_formset.formset.max_num == 1 %}
<h2>{{ inline_admin_formset.opts.verbose_name|capfirst }}</h2>
{% else %}
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
{% endif %}
{{ inline_admin_formset.formset.management_form }}
{{ inline_admin_formset.formset.non_form_errors }}
<h3>-- Actions Inline -- </h3>
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if inline_admin_form.original or inline_admin_form.show_url %} has_original{% endif %}{% if forloop.last and inline_admin_formset.has_add_permission %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<h3><b>{{ inline_admin_formset.opts.verbose_name|capfirst }}:</b> <span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="{% if inline_admin_formset.has_change_permission %}inlinechangelink{% else %}inlineviewlink{% endif %}">{% if inline_admin_formset.has_change_permission %}{% translate "Change" %}{% else %}{% translate "View" %}{% endif %}</a>{% endif %}
{% else %}#{{ forloop.counter }}{% endif %}</span>
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% translate "View on site" %}</a>{% endif %}
{% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
</h3>
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
{% for fieldset in inline_admin_form %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{% if inline_admin_form.fk_field %}{{ inline_admin_form.fk_field.field }}{% endif %}
</div>{% endfor %}
</fieldset>
</div>
@@ -0,0 +1,84 @@
{% load i18n admin_urls static admin_modify %}
<div class="inline-group sortable" id="{{ inline_admin_formset.formset.prefix }}-group">
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
{{ inline_admin_formset.formset.management_form }}
<fieldset class="module {{ inline_admin_formset.classes }}">
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
{{ inline_admin_formset.formset.non_form_errors }}
<h3>-- Actions Inline -- </h3>
<p>{{ inline_action_form|default:"" }}</p>
<table>
<thead><tr><th>{% trans "Sort" %}</th>
{% for field in inline_admin_formset.fields %}
{% if not field.widget.is_hidden %}
<th{% if forloop.first %} colspan="2"{% endif %}{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}
{% if field.help_text %}&nbsp;<img src="{% static "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}" />{% endif %}
</th>
{% endif %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %}
</tr></thead>
<tbody>
{% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %}
<tr><td colspan="{{ inline_admin_form|cell_count|add:1 }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
{% endif %}
<tr class="form-row {% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last and inline_admin_formset.has_add_permission %} empty-form{% endif %}"
id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<td class="drag">&nbsp;</td>
<td class="original">
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %}
{{ inline_admin_form.original }}
{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}<a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="inlinechangelink">{% trans "Change" %}</a>{% endif %}
{% endif %}
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% trans "View on site" %}</a>{% endif %}
</p>{% endif %}
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
{% spaceless %}
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endspaceless %}
</td>
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if not field.field.is_hidden %}
<td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field.errors.as_ul }}
{{ field.field }}
{% endif %}
</td>
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
</div>
</div>
<script type="application/json" class="inline-tabular-config">
{
"prefix": "{{ inline_admin_formset.formset.prefix|escapejs }}",
"addText": "{% filter escapejs %}{% blocktrans with inline_admin_formset.opts.verbose_name|capfirst as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}{% endfilter %}",
"deleteText": "{% filter escapejs %}{% trans 'Remove' %}{% endfilter %}"
}
</script>
<div class="default_order_field" default_order_field="{{ inline_admin_formset.formset.default_order_field }}" default_order_direction="{{ inline_admin_formset.formset.default_order_direction }}"></div>
@@ -7,6 +7,13 @@
<button type="submit">Mautic Sync</button> <button type="submit">Mautic Sync</button>
</form> </form>
</div> </div>
<div>
<form action="notif/" method="POST">
{% csrf_token %}
<button type="submit">Notification Test</button>
</form>
</div>
<br /> <br />
{{ block.super }} {{ block.super }}
{% endblock %} {% endblock %}
@@ -8,6 +8,7 @@ from django.utils.translation import ugettext_lazy as _
from django.contrib import admin from django.contrib import admin
from rangefilter.filters import DateRangeFilter, DateTimeRangeFilter from rangefilter.filters import DateRangeFilter, DateTimeRangeFilter
from django.urls import path from django.urls import path
from ..automation.mautic import Mautic
SETTING = os.environ['WORKOUTTEST_SETTING'] SETTING = os.environ['WORKOUTTEST_SETTING']
if SETTING == "PROD" : if SETTING == "PROD" :
@@ -76,14 +77,20 @@ class CustomerAdmin(admin.ModelAdmin):
def get_urls(self): def get_urls(self):
urls = super().get_urls() urls = super().get_urls()
my_urls = [ my_urls = [
path('mautic/', self.set_mautic), path('mautic/', self.run_mautic),
path('notif/', self.run_notif),
] ]
return my_urls + urls return my_urls + urls
def set_mautic(self, request): def run_notif(self, request):
self.notif.run() self.notif.run()
return HttpResponseRedirect("../") return HttpResponseRedirect("../")
def run_mautic(self, request):
mautic = Mautic()
mautic.syncLang()
return HttpResponseRedirect("../")
admin.site.register(Customer, CustomerAdmin) admin.site.register(Customer, CustomerAdmin)
admin.autodiscover() admin.autodiscover()
@@ -4,6 +4,7 @@ from firebase_admin import messaging, exceptions
class FCM: class FCM:
logo_url = 'https://workouttest.com/wp-content/uploads/2020/10/WT_long_logo.png' logo_url = 'https://workouttest.com/wp-content/uploads/2020/10/WT_long_logo.png'
image_base = 'https://admin.aitrainer.app/media/images/'
# default constructor # default constructor
def __init__(self): def __init__(self):
@@ -53,10 +54,11 @@ class FCM:
if registration_token == None: if registration_token == None:
return "Registration token is null" return "Registration token is null"
try: try:
notification_image_url = image_url
if image_url == None: if image_url == None:
notification_image_url = self.logo_url notification_image_url = self.logo_url
#registration_token = 'cOqNt8rzo074gbIkBSpCgW:APA91bEBuNi3iVzGKb4JhxqN2j80MoJbNptLHk2qsdeKBQz5grpHtrPPXvDqn5BJVVSaj1nwGPwgN7pi6FIApog_TTP3g1yobgmgpPN6udrYgzILlVPMvdGGFDSDh6gKlczhlTL9NEp0' else:
notification_image_url = self.image_base + '/' + image_url
print(f'image: {notification_image_url}' ) print(f'image: {notification_image_url}' )
@@ -2,8 +2,13 @@ import requests
import logging import logging
from django.db import connections from django.db import connections
import datetime import datetime
import os
from ..models.customer import Customer SETTING = os.environ['WORKOUTTEST_SETTING']
if SETTING == "PROD":
from aitrainer_backoffice.aitrainer_backoffice.models.customer import Customer
else:
from aitrainer_backoffice.models.customer import Customer
class Mautic: class Mautic:
@@ -13,6 +18,37 @@ class Mautic:
qs = Customer.objects.raw( qs = Customer.objects.raw(
'SELECT * from customer WHERE trial_date < "' + tenDays + '" and trial_date is not null') 'SELECT * from customer WHERE trial_date < "' + tenDays + '" and trial_date is not null')
def syncLang(self):
qs = Customer.objects.raw('SELECT * from customer WHERE lang is not null')
logger = logging.getLogger(__name__)
logger.info("Syncronising lang...")
headers = {
'content-type': "application/x-www-form-urlencoded",
'cache-control': "no-cache"
}
index = 0
for customer in qs:
data = "mauticform[email]=" + customer.email + \
"&mauticform[database_id]=" + str(customer.customer_id) + \
"&mauticform[lang]=" + str(customer.lang) + \
"&mauticform[formId]=3" + \
"&mauticform[formName]=appdatachange"
print(data)
form_url = 'https://mautic.aitrainer.app/form/submit?formId=3'
response = requests.post(form_url, data=data.encode('utf-8'), headers=headers)
print(customer.email + " " +str(response.status_code))
index = index + 1
if index == 2:
break
logger.info("Syncronised customer count: " + str(index))
return True
def sync(self): def sync(self):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.info("Syncronising...") logger.info("Syncronising...")
@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-09-26 11:21+0200\n" "POT-Creation-Date: 2021-10-17 10:52+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,40 +18,22 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: .\controlling\admin\customer.py:58 #: .\controlling\admin\customer.py:65
msgid "Registered" msgid "Registered"
msgstr "" msgstr ""
#: .\controlling\models\customer.py:16 #: .\controlling\admin\frequent_customers.py:22
#: .\controlling\models\frequent_customers.py:9
msgid "name"
msgstr ""
#: .\controlling\models\customer.py:17
#: .\controlling\models\frequent_customers.py:10
msgid "firstname"
msgstr ""
#: .\controlling\models\customer.py:33
msgid "Customer"
msgstr ""
#: .\controlling\models\customer.py:34
msgid "Customers"
msgstr ""
#: .\controlling\models\exercise_type.py:26
msgid "Frequent Exercise"
msgstr ""
#: .\controlling\models\exercise_type.py:27
msgid "Frequent Exercises"
msgstr ""
#: .\controlling\models\frequent_customers.py:26
msgid "Frequent Customer" msgid "Frequent Customer"
msgstr "" msgstr ""
#: .\controlling\models\frequent_customers.py:27 #: .\controlling\admin\frequent_customers.py:23
msgid "Frequent Customers" msgid "Frequent Customers"
msgstr "" msgstr ""
#: .\controlling\admin\frequent_exercises.py:22
msgid "Frequent Exercise"
msgstr ""
#: .\controlling\admin\frequent_exercises.py:23
msgid "Frequent Exercises"
msgstr ""
+1 -1
View File
@@ -1,2 +1,2 @@
export $(cat .env | xargs) export $(cat /aitrainer_backoffice.env | xargs)
/usr/local/bin/python /aitrainer_backoffice/aitrainer_backoffice/manage.py runcrons --settings aitrainer_backoffice.settings.deploy >> /var/log/cronjob.log 2>&1 /usr/local/bin/python /aitrainer_backoffice/aitrainer_backoffice/manage.py runcrons --settings aitrainer_backoffice.settings.deploy >> /var/log/cronjob.log 2>&1