diff --git a/.gitignore b/.gitignore index 4942dd8..fc3d755 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ env/** venv/** .idea/** .vscode/** +__init__* aitrainer_backoffice/aitrainer_backoffice/__pycache__/** aitrainer_backoffice/aitrainer_backoffice/**/__pycache__/** aitrainer_backoffice/controlling/__pycache__/** diff --git a/aitrainer_backoffice/aitrainer_backoffice/asset/aitrainer-firebase-adminsdk.json b/aitrainer_backoffice/aitrainer_backoffice/asset/aitrainer-firebase-adminsdk.json new file mode 100644 index 0000000..7f1cc5a --- /dev/null +++ b/aitrainer_backoffice/aitrainer_backoffice/asset/aitrainer-firebase-adminsdk.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "aitrainer-af0ec", + "private_key_id": "80c39e9c6224fe9b4929070fa64b09d1a7fb054d", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCYbnWs6O3tL0E/\nKokD4mxxTNTMRbEGOvuSAMjhOZOCuN2+LcHTynPXSSy/Ko55s4r1dT6gwtTMvMWe\ng8z/HbsvywXQlFGBj8BheHNB4ns5pd+doFX/lGO3iOz3vFTqgdVpi8R26zPE9rKz\nSuUFnDdlLIYC+eKMbZ6icKpHC5CMe/juXlNdZMlfjs4z6qGWB99kNjc6zrqh4peR\nuMF2GfV57ur4aeWrDKzb9eGoAD+3Fs5SP0jrBVVzzQoBpYmk3TtgySutMrZ8YFPI\nppQ1Vk29UZ2uDdTkv+YHP05qmIHcyeisbtQEA8m2WXtdPNH67oOpCZijEJj/pSHg\nDoXW4EXBAgMBAAECggEAA70l3sVh3KD9mTaKYNGDdm37hD0rX+s/c2/YfYnDf//X\n1Ivbxr2fBMdTNScuknagcG/dRuUwggsZT8+Mzi8lAcGZlWml7CciAWIKdbG/8wSK\nDRw7L8csgPp3UYZJkOz5VprqiT4wqWKhtHsgTfhsdWtXqCgH8gjYTMS1sINsmr2A\nB0Vg1T6r688jGchCxXg0TDRNyTjOKwMeSnljW+OCVfV9OncUPqrL1jayDUoiy06n\nS2xdZuVeV3zVDtmtZfWDbBTH8+Gi4bbxST0W0nAAUGCeLfE7+sc6jB2uUr76aUH7\nvjaxy3/GcxEey55scD5Q3G0kgaNsMC9V44MO/pVs9wKBgQDF4nZFNq0LptHOH9Es\nWczXMddAhuqaGI0Yq2PAYCzRnrJdoWTjOwod99qRakVNb6kxOmhLc7FabBviG/vu\n83zhg4K2PD+XsP4p+5+N3iW6yDF6Cpp/rsYFuKuHV1Dic0tFBHlSNQAKFrgUqHf5\nmA9d6QNpiuhXDEb3Hm9LXFkHcwKBgQDFMrMWQOoJ7XEhYBXdv55dF+swHAdCkO66\nmuWiC/52g5hpWxx3SlcKoSKtKvzxkkkg3PhhrLbrNQ0ydVnwHFRERTxC2jO8PYQ+\nUNRfW+p2ZA5z+OdciNWYHDd/+vIUG3ouGHtHVO+IEbl4bMBghXgDoZstI3m+T34B\niLJ/QOQo+wKBgG/yDDxdkQmdZuV35Gp1psc6n+4WJRPlvbRuCPFktxYi8/659gwC\nc1e+xnwrJWeIOqvpweSlX3iq3h9M+3oTbttY/ZJAhS04aKCxg3LLcIa5CBxlcT+4\nTLgh34+iGtTwqm0x+bxC1XHfpmWxZKXjmxXiYxbLCWNtQ5w7MHTumkL3AoGBAMQe\n70OTne/vqRLzd+vJdlvJvQtk5MeMUxFdmkI2wYXmzP8DMWVmlvioV094MIak4XwA\nqDqkRmvYoF5tndwSoLAhV5R5ZPizCcHcK8sHJEFIs6MdiiRapmuYrI3o6zeaOEJ9\n8KV50Jw4XIhrSEz2kOyznhwfayYd8wjdhgDPbdtfAoGAactiYA8HLK6GzFigJ48Z\nsdCSgARS1w0ABlZgQqcf43hoWV/zs0J0F9hrqorZ1p1eVmwnKyNffWBaaMK+L7kj\nE++8YwaILh4kQAy5perW1xbebE56Yp77HOWvRFxgnHD4VbLom3DXws31Wa3R6bY6\n/iXuXLenZr8EzJw3KX5DLkM=\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-ajrq1@aitrainer-af0ec.iam.gserviceaccount.com", + "client_id": "113509590657169902603", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-ajrq1%40aitrainer-af0ec.iam.gserviceaccount.com" +} diff --git a/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo b/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo index 4d1d06d..ef22998 100644 Binary files a/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo and b/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo differ diff --git a/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po b/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po index a4b77b3..8d5860d 100644 --- a/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po +++ b/aitrainer_backoffice/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-10 16:50+0200\n" +"POT-Creation-Date: 2021-09-26 11:21+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,38 +18,109 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#: .\aitrainer_backoffice\admin\app_text.py:25 #: .\aitrainer_backoffice\admin\exercise_device.py:32 #: .\aitrainer_backoffice\admin\exercise_type.py:27 -#: .\aitrainer_backoffice\admin\exercisetree.py:40 +#: .\aitrainer_backoffice\admin\exercisetree.py:41 msgid "Image Preview" msgstr "Kép előnézet" -#: .\aitrainer_backoffice\admin\training_plan.py:29 +#: .\aitrainer_backoffice\admin\inline_select_action.py:116 +#, fuzzy +#| msgid "Descriptions" +msgid "Actions" +msgstr "Leírás" + +#: .\aitrainer_backoffice\admin\training_plan.py:30 +#: .\aitrainer_backoffice\admin\training_plan.py:159 msgid "Special cases: Weight = -1 IF the Weight should be calculated." msgstr "" -#: .\aitrainer_backoffice\admin\training_plan.py:30 +#: .\aitrainer_backoffice\admin\training_plan.py:31 +#: .\aitrainer_backoffice\admin\training_plan.py:160 msgid "Repeats = -1 IF the repeats should be maximized" msgstr "Ismétlés: -1, HA MAX ismétlés" -#: .\aitrainer_backoffice\admin\training_plan.py:49 +#: .\aitrainer_backoffice\admin\training_plan.py:62 +#: .\aitrainer_backoffice\admin\training_plan.py:185 #, fuzzy #| msgid "Training Plan Detail" msgid "Clone the selected Training Plan Detail" msgstr "Edzésprogram részlet" -#: .\aitrainer_backoffice\admin\training_plan.py:55 +#: .\aitrainer_backoffice\admin\training_plan.py:69 +#: .\aitrainer_backoffice\admin\training_plan.py:192 msgid "Select the exercises with MAX repeats" msgstr "" -#: .\aitrainer_backoffice\admin\training_plan.py:61 +#: .\aitrainer_backoffice\admin\training_plan.py:76 +#: .\aitrainer_backoffice\admin\training_plan.py:199 msgid "Select the exercises CALCULATED weight" msgstr "" +#: .\aitrainer_backoffice\models\app_text.py:10 +msgid "text_key" +msgstr "Szöveg kulcs" + +#: .\aitrainer_backoffice\models\app_text.py:11 +msgid "App képernyőkép" +msgstr "" + +#: .\aitrainer_backoffice\models\app_text.py:12 +#| msgid "Translations" +msgid "Checked, Translation is OK" +msgstr "Fordítás rendben, ellenőrizve" + +#: .\aitrainer_backoffice\models\app_text.py:16 +msgid "App Text" +msgstr "App Fordítás" + +#: .\aitrainer_backoffice\models\app_text.py:17 +msgid "App Texts" +msgstr "App Fordítások" + +#: .\aitrainer_backoffice\models\app_text.py:31 +#: .\aitrainer_backoffice\models\description.py:34 +#: .\aitrainer_backoffice\models\exercise_device.py:53 +#: .\aitrainer_backoffice\models\exercise_plan.py:32 +#: .\aitrainer_backoffice\models\exercise_plan_template.py:38 +#: .\aitrainer_backoffice\models\exercise_type.py:73 +#: .\aitrainer_backoffice\models\exercisetree.py:36 +#: .\aitrainer_backoffice\models\faq.py:34 +#: .\aitrainer_backoffice\models\property.py:29 +#: .\aitrainer_backoffice\models\sports.py:31 +#: .\aitrainer_backoffice\models\training_plan.py:58 +#: .\aitrainer_backoffice\models\training_plan_day.py:31 +#: .\aitrainer_backoffice\models\tutorial.py:45 +msgid "Translation" +msgstr "Fordítás" + +#: .\aitrainer_backoffice\models\app_text.py:32 +#: .\aitrainer_backoffice\models\description.py:35 +#: .\aitrainer_backoffice\models\exercise_device.py:54 +#: .\aitrainer_backoffice\models\exercise_plan.py:33 +#: .\aitrainer_backoffice\models\exercise_plan_template.py:39 +#: .\aitrainer_backoffice\models\exercise_type.py:74 +#: .\aitrainer_backoffice\models\exercisetree.py:37 +#: .\aitrainer_backoffice\models\faq.py:35 +#: .\aitrainer_backoffice\models\property.py:30 +#: .\aitrainer_backoffice\models\sports.py:32 +#: .\aitrainer_backoffice\models\training_plan.py:59 +#: .\aitrainer_backoffice\models\training_plan_day.py:32 +#: .\aitrainer_backoffice\models\tutorial.py:46 +msgid "Translations" +msgstr "Fordítások" + #: .\aitrainer_backoffice\models\description.py:11 -#: .\aitrainer_backoffice\models\evaluation.py:40 +#: .\aitrainer_backoffice\models\evaluation.py:41 #: .\aitrainer_backoffice\models\faq.py:11 -#: .\aitrainer_backoffice\models\training_plan.py:10 +#: .\aitrainer_backoffice\models\faq.py:29 +#: .\aitrainer_backoffice\models\split_tests.py:7 +#: .\aitrainer_backoffice\models\sports.py:11 +#: .\aitrainer_backoffice\models\sports.py:27 +#: .\aitrainer_backoffice\models\training_plan.py:14 +#: .\aitrainer_backoffice\models\training_plan_day.py:11 +#: .\aitrainer_backoffice\models\training_plan_day.py:27 #: .\aitrainer_backoffice\models\tutorial.py:11 msgid "name" msgstr "Név" @@ -62,93 +133,69 @@ msgstr "Leírás" msgid "Descriptions" msgstr "Leírás" -#: .\aitrainer_backoffice\models\description.py:34 -#: .\aitrainer_backoffice\models\exercise_device.py:53 -#: .\aitrainer_backoffice\models\exercise_plan.py:32 -#: .\aitrainer_backoffice\models\exercise_plan_template.py:38 -#: .\aitrainer_backoffice\models\exercise_type.py:72 -#: .\aitrainer_backoffice\models\exercisetree.py:33 -#: .\aitrainer_backoffice\models\faq.py:32 -#: .\aitrainer_backoffice\models\property.py:29 -#: .\aitrainer_backoffice\models\tutorial.py:45 -msgid "Translation" -msgstr "Fordítás" - -#: .\aitrainer_backoffice\models\description.py:35 -#: .\aitrainer_backoffice\models\exercise_device.py:54 -#: .\aitrainer_backoffice\models\exercise_plan.py:33 -#: .\aitrainer_backoffice\models\exercise_plan_template.py:39 -#: .\aitrainer_backoffice\models\exercise_type.py:73 -#: .\aitrainer_backoffice\models\exercisetree.py:34 -#: .\aitrainer_backoffice\models\faq.py:33 -#: .\aitrainer_backoffice\models\property.py:30 -#: .\aitrainer_backoffice\models\tutorial.py:46 -msgid "Translations" -msgstr "Fordítások" - #: .\aitrainer_backoffice\models\evaluation.py:10 msgid "exercise_type" msgstr "Aktuális gyakorlat" -#: .\aitrainer_backoffice\models\evaluation.py:11 +#: .\aitrainer_backoffice\models\evaluation.py:12 msgid "unit" msgstr "Mértékegység" -#: .\aitrainer_backoffice\models\evaluation.py:15 +#: .\aitrainer_backoffice\models\evaluation.py:16 msgid "Evaluation" msgstr "Kiértékelés" -#: .\aitrainer_backoffice\models\evaluation.py:16 +#: .\aitrainer_backoffice\models\evaluation.py:17 msgid "Evaluations" msgstr "Kiértékelés Csoport" -#: .\aitrainer_backoffice\models\evaluation.py:39 +#: .\aitrainer_backoffice\models\evaluation.py:40 msgid "evaluation_foreign" msgstr "Kiértékelés Főcsoport" -#: .\aitrainer_backoffice\models\evaluation.py:41 +#: .\aitrainer_backoffice\models\evaluation.py:42 msgid "sex" msgstr "Nem" -#: .\aitrainer_backoffice\models\evaluation.py:42 +#: .\aitrainer_backoffice\models\evaluation.py:43 msgid "age_min" msgstr "Kortól" -#: .\aitrainer_backoffice\models\evaluation.py:43 +#: .\aitrainer_backoffice\models\evaluation.py:44 msgid "age_max" msgstr "Korig" -#: .\aitrainer_backoffice\models\evaluation.py:44 +#: .\aitrainer_backoffice\models\evaluation.py:45 msgid "value_min" msgstr "Min érték" -#: .\aitrainer_backoffice\models\evaluation.py:45 +#: .\aitrainer_backoffice\models\evaluation.py:46 msgid "value_max" msgstr "Max érték" -#: .\aitrainer_backoffice\models\evaluation.py:47 +#: .\aitrainer_backoffice\models\evaluation.py:48 msgid "evaluation_text" msgstr "Osztályozás" -#: .\aitrainer_backoffice\models\evaluation.py:49 +#: .\aitrainer_backoffice\models\evaluation.py:50 msgid "suggestion" msgstr "Javaslat" -#: .\aitrainer_backoffice\models\evaluation.py:53 +#: .\aitrainer_backoffice\models\evaluation.py:54 msgid "Evaluation Table" msgstr "Kiértékelés tábla" -#: .\aitrainer_backoffice\models\evaluation.py:54 +#: .\aitrainer_backoffice\models\evaluation.py:55 msgid "Evaluation Tables" msgstr "Kiértékelés táblák" #: .\aitrainer_backoffice\models\exercise_device.py:18 -#: .\aitrainer_backoffice\models\exercise_type.py:86 +#: .\aitrainer_backoffice\models\exercise_type.py:87 msgid "Exercise Device" msgstr "Edzés eszköz" #: .\aitrainer_backoffice\models\exercise_device.py:19 -#: .\aitrainer_backoffice\models\exercise_type.py:87 +#: .\aitrainer_backoffice\models\exercise_type.py:88 msgid "Exercise Devices" msgstr "Edzés eszközök" @@ -192,60 +239,65 @@ msgstr "Edzésterv sablon gyakorlat" msgid "Exercise Plan Template Details" msgstr "Edzésterv sablon gyakorlatok" -#: .\aitrainer_backoffice\models\exercise_type.py:34 +#: .\aitrainer_backoffice\models\exercise_type.py:35 msgid "Exercise" msgstr "Gyakorlat" -#: .\aitrainer_backoffice\models\exercise_type.py:35 +#: .\aitrainer_backoffice\models\exercise_type.py:36 msgid "Exercises" msgstr "Gyakorlatok" -#: .\aitrainer_backoffice\models\exercise_type.py:56 +#: .\aitrainer_backoffice\models\exercise_type.py:57 msgid "Image" msgstr "Kép" -#: .\aitrainer_backoffice\models\exercise_type.py:57 +#: .\aitrainer_backoffice\models\exercise_type.py:58 msgid "Images" msgstr "Képek" -#: .\aitrainer_backoffice\models\exercise_type.py:99 +#: .\aitrainer_backoffice\models\exercise_type.py:103 msgid "Exercise Alternative" msgstr "Gyakorlat alternatíva" -#: .\aitrainer_backoffice\models\exercise_type.py:100 +#: .\aitrainer_backoffice\models\exercise_type.py:104 msgid "Exercise Alternatives" msgstr "Gyakorlat alternatívák" -#: .\aitrainer_backoffice\models\exercise_type.py:111 +#: .\aitrainer_backoffice\models\exercise_type.py:115 msgid "Exercise Parent" msgstr "Gyakorlat szülő" -#: .\aitrainer_backoffice\models\exercise_type.py:112 +#: .\aitrainer_backoffice\models\exercise_type.py:116 msgid "Exercise Parents" msgstr "Gyakorlat szülők" -#: .\aitrainer_backoffice\models\exercisetree.py:16 +#: .\aitrainer_backoffice\models\exercisetree.py:15 +#: .\aitrainer_backoffice\models\training_plan.py:17 +msgid "internal_name" +msgstr "" + +#: .\aitrainer_backoffice\models\exercisetree.py:19 msgid "Exercise Tree" msgstr "Gyakorlat Menü" -#: .\aitrainer_backoffice\models\exercisetree.py:17 +#: .\aitrainer_backoffice\models\exercisetree.py:20 msgid "Exercise Tree Items" msgstr "Gyakorlat Menü elemek" -#: .\aitrainer_backoffice\models\exercisetree.py:45 +#: .\aitrainer_backoffice\models\exercisetree.py:48 msgid "Parent menu" msgstr "Szülő menüpont" -#: .\aitrainer_backoffice\models\exercisetree.py:50 -#: .\aitrainer_backoffice\models\exercisetree.py:51 +#: .\aitrainer_backoffice\models\exercisetree.py:53 +#: .\aitrainer_backoffice\models\exercisetree.py:54 msgid "Menu Tree Representation" msgstr "" -#: .\aitrainer_backoffice\models\faq.py:16 +#: .\aitrainer_backoffice\models\faq.py:17 msgid "FAQ" msgstr "GYÍK" -#: .\aitrainer_backoffice\models\faq.py:17 +#: .\aitrainer_backoffice\models\faq.py:18 msgid "FAQs" msgstr "GYÍK" @@ -273,22 +325,50 @@ msgstr "Ügyfél tulajdonság" msgid "Customer Properties" msgstr "Ügyfél tulajdonságok" -#: .\aitrainer_backoffice\models\training_plan.py:14 +#: .\aitrainer_backoffice\models\split_tests.py:17 +msgid "A/B Test" +msgstr "A/B Teszt" + +#: .\aitrainer_backoffice\models\split_tests.py:18 +msgid "A/B Tests" +msgstr "A/B Tesztek" + +#: .\aitrainer_backoffice\models\sports.py:15 +msgid "Sport" +msgstr "" + +#: .\aitrainer_backoffice\models\sports.py:16 +msgid "Sports" +msgstr "" + +#: .\aitrainer_backoffice\models\training_plan.py:23 msgid "Training Plan" -msgstr "Edzésprogram Csoport" +msgstr "Edzésprogram" -#: .\aitrainer_backoffice\models\training_plan.py:15 +#: .\aitrainer_backoffice\models\training_plan.py:24 msgid "Training Plans" -msgstr "Edzésprogram Csoportok" +msgstr "Edzésprogramok" -#: .\aitrainer_backoffice\models\training_plan.py:35 +#: .\aitrainer_backoffice\models\training_plan.py:44 msgid "Training Plan Detail" msgstr "Edzésprogram részlet" -#: .\aitrainer_backoffice\models\training_plan.py:36 +#: .\aitrainer_backoffice\models\training_plan.py:45 msgid "Training Plan Details" msgstr "Edzésprogram részletek" +#: .\aitrainer_backoffice\models\training_plan_day.py:15 +#, fuzzy +#| msgid "Training Plan" +msgid "Training Day" +msgstr "Edzésnap" + +#: .\aitrainer_backoffice\models\training_plan_day.py:16 +#, fuzzy +#| msgid "Training Plans" +msgid "Training Days" +msgstr "Edzésnapok" + #: .\aitrainer_backoffice\models\tutorial.py:15 msgid "Tutorial" msgstr "Tutorial" diff --git a/aitrainer_backoffice/aitrainer_backoffice/models/app_text.py b/aitrainer_backoffice/aitrainer_backoffice/models/app_text.py index 6a249d9..c06264a 100644 --- a/aitrainer_backoffice/aitrainer_backoffice/models/app_text.py +++ b/aitrainer_backoffice/aitrainer_backoffice/models/app_text.py @@ -6,10 +6,10 @@ from .enums import LanguageTypes class AppText(models.Model): text_id = models.AutoField(primary_key=True) - text_key = models.CharField(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")) - screenshot_url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768', blank=True, ) - checked = models.BooleanField(blank=True) + screenshot_url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768', blank=True,verbose_name=_("App képernyőkép") ) + checked = models.BooleanField(blank=True, verbose_name=_("Checked, Translation is OK")) class Meta: db_table = 'app_text' @@ -24,7 +24,7 @@ class AppTextTranslation(models.Model): translation_id = models.AutoField(primary_key=True) text = models.ForeignKey(AppText, on_delete=models.CASCADE) language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU) - translation = models.CharField(max_length=255) + translation = models.TextField(max_length=1000) class Meta: db_table = 'app_text_translation' diff --git a/aitrainer_backoffice/aitrainer_backoffice/settings/deploy.py b/aitrainer_backoffice/aitrainer_backoffice/settings/deploy.py index a177b04..07a874d 100644 --- a/aitrainer_backoffice/aitrainer_backoffice/settings/deploy.py +++ b/aitrainer_backoffice/aitrainer_backoffice/settings/deploy.py @@ -1,6 +1,6 @@ import os -BACKOFFICE_VERSION = 1.28 +BACKOFFICE_VERSION = "1.29.1" # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/aitrainer_backoffice/aitrainer_backoffice/settings/dev.py b/aitrainer_backoffice/aitrainer_backoffice/settings/dev.py index 0b76b90..8fb4037 100644 --- a/aitrainer_backoffice/aitrainer_backoffice/settings/dev.py +++ b/aitrainer_backoffice/aitrainer_backoffice/settings/dev.py @@ -1,6 +1,6 @@ import os -BACKOFFICE_VERSION = 1.28 +BACKOFFICE_VERSION = "1.29.1" # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/aitrainer_backoffice/aitrainer_backoffice/settings/prod.py b/aitrainer_backoffice/aitrainer_backoffice/settings/prod.py index 45af958..21a1f21 100644 --- a/aitrainer_backoffice/aitrainer_backoffice/settings/prod.py +++ b/aitrainer_backoffice/aitrainer_backoffice/settings/prod.py @@ -1,6 +1,6 @@ import os -BACKOFFICE_VERSION = 1.28 +BACKOFFICE_VERSION = "1.29.1" # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/aitrainer_backoffice/controlling/admin/customer.py b/aitrainer_backoffice/controlling/admin/customer.py index 992165e..98836cb 100644 --- a/aitrainer_backoffice/controlling/admin/customer.py +++ b/aitrainer_backoffice/controlling/admin/customer.py @@ -12,6 +12,7 @@ from ..models.customer import Customer from ..models.customer import Sport from ..mautic import MauticHelper from ..cron import cron +from ..push_notification import messaging class SportFilter(SimpleListFilter, ABC): @@ -74,8 +75,7 @@ class CustomerAdmin(admin.ModelAdmin): return my_urls + urls def set_mautic(self, request): - cron.sync_customers() - self.message_user(request, "All heroes are now synced") + messaging.send_to_token() return HttpResponseRedirect("../") diff --git a/aitrainer_backoffice/controlling/push_notification/messaging.py b/aitrainer_backoffice/controlling/push_notification/messaging.py new file mode 100644 index 0000000..204c4bb --- /dev/null +++ b/aitrainer_backoffice/controlling/push_notification/messaging.py @@ -0,0 +1,243 @@ +"""Server Side FCM sample. +Firebase Cloud Messaging (FCM) can be used to send messages to clients on iOS, +Android and Web. +This sample uses FCM to send two types of messages to clients that are subscribed +to the `news` topic. One type of message is a simple notification message (display message). +The other is a notification message (display notification) with platform specific +customizations. For example, a badge is added to messages that are sent to iOS devices. +""" + +import argparse +import json +import requests +import datetime + +from google.oauth2 import service_account +from firebase_admin import messaging + +PROJECT_ID = 'aitrainer-af0ec' +BASE_URL = 'https://fcm.googleapis.com' +FCM_ENDPOINT = 'v1/projects/' + PROJECT_ID + '/messages:send' +FCM_URL = BASE_URL + '/' + FCM_ENDPOINT +SCOPES = ['https://www.googleapis.com/auth/firebase.messaging'] + +# [START retrieve_access_token] +def _get_access_token(): + """Retrieve a valid access token that can be used to authorize requests. + :return: Access token. + """ + credentials = credentials = service_account.Credentials.from_service_account_file( + "asset/aitrainer-firebase-adminsdk.json", + scopes=['email'], + ) + access_token_info = credentials.get_access_token() + return access_token_info.access_token +# [END retrieve_access_token] + +def _send_fcm_message(fcm_message): + """Send HTTP request to FCM with given message. + Args: + fcm_message: JSON object that will make up the body of the request. + """ + # [START use_access_token] + headers = { + 'Authorization': 'Bearer ' + _get_access_token(), + 'Content-Type': 'application/json; UTF-8', + } + # [END use_access_token] + resp = requests.post(FCM_URL, data=json.dumps(fcm_message), headers=headers) + + if resp.status_code == 200: + print('Message sent to Firebase for delivery, response:') + print(resp.text) + else: + print('Unable to send message to Firebase') + print(resp.text) + +def _build_common_message(): + """Construct common notifiation message. + Construct a JSON object that will be used to define the + common parts of a notification message that will be sent + to any app instance subscribed to the news topic. + """ + return { + 'message': { + 'topic': 'news', + 'notification': { + 'title': 'FCM Notification', + 'body': 'Notification from FCM' + } + } + } + +def _build_override_message(): + """Construct common notification message with overrides. + Constructs a JSON object that will be used to customize + the messages that are sent to iOS and Android devices. + """ + fcm_message = _build_common_message() + + apns_override = { + 'payload': { + 'aps': { + 'badge': 1 + } + }, + 'headers': { + 'apns-priority': '10' + } + } + + android_override = { + 'notification': { + 'click_action': 'android.intent.action.MAIN' + } + } + + fcm_message['message']['android'] = android_override + fcm_message['message']['apns'] = apns_override + + return fcm_message + +def send_to_token(): + # [START send_to_token] + # This registration token comes from the client FCM SDKs. + registration_token = 'fFjCZmrHREpRvxZMIKhNSI:APA91bH7cfctHFHbKxtQ5XGRlL26jgLLzo3a1x4hlPfZYi9WxrauMkdIBmqnIQnyD8Jc3xEs0gAsgNYNMLDEgdrHV3bbH4gvFHYUrYzOHZFr-2aVCsYF9otT8_fmAV380egGf5HiCIYd' + + # See documentation on defining a message payload. + message = messaging.Message( + data={ + 'score': '850', + 'time': '2:45', + }, + token=registration_token, + ) + + # Send a message to the device corresponding to the provided + # registration token. + response = messaging.send(message) + # Response is a message ID string. + print('Successfully sent message:', response) + # [END send_to_token] + +def send_to_topic(): + # [START send_to_topic] + # The topic name can be optionally prefixed with "/topics/". + topic = 'highScores' + + # See documentation on defining a message payload. + message = messaging.Message( + data={ + 'score': '850', + 'time': '2:45', + }, + topic=topic, + ) + + # Send a message to the devices subscribed to the provided topic. + response = messaging.send(message) + # Response is a message ID string. + print('Successfully sent message:', response) + # [END send_to_topic] + + +def send_to_condition(): + # [START send_to_condition] + # Define a condition which will send to devices which are subscribed + # to either the Google stock or the tech industry topics. + condition = "'stock-GOOG' in topics || 'industry-tech' in topics" + + # See documentation on defining a message payload. + message = messaging.Message( + notification=messaging.Notification( + title='$GOOG up 1.43% on the day', + body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.', + ), + condition=condition, + ) + + # Send a message to devices subscribed to the combination of topics + # specified by the provided condition. + response = messaging.send(message) + # Response is a message ID string. + print('Successfully sent message:', response) + # [END send_to_condition] + + +def send_dry_run(): + message = messaging.Message( + data={ + 'score': '850', + 'time': '2:45', + }, + token='token', + ) + + # [START send_dry_run] + # Send a message in the dry run mode. + response = messaging.send(message, dry_run=True) + # Response is a message ID string. + print('Dry run successful:', response) + # [END send_dry_run] + + +def android_message(): + # [START android_message] + message = messaging.Message( + android=messaging.AndroidConfig( + ttl=datetime.timedelta(seconds=3600), + priority='normal', + notification=messaging.AndroidNotification( + title='$GOOG up 1.43% on the day', + body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.', + icon='stock_ticker_update', + color='#f45342' + ), + ), + topic='industry-tech', + ) + # [END android_message] + return message + + +def apns_message(): + # [START apns_message] + message = messaging.Message( + apns=messaging.APNSConfig( + headers={'apns-priority': '10'}, + payload=messaging.APNSPayload( + aps=messaging.Aps( + alert=messaging.ApsAlert( + title='$GOOG up 1.43% on the day', + body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.', + ), + badge=42, + ), + ), + ), + topic='industry-tech', + ) + # [END apns_message] + return message + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--message') + args = parser.parse_args() + if args.message and args.message == 'common-message': + common_message = _build_common_message() + print('FCM request body for message using common notification object:') + print(json.dumps(common_message, indent=2)) + _send_fcm_message(common_message) + elif args.message and args.message == 'override-message': + override_message = _build_override_message() + print('FCM request body for override message:') + print(json.dumps(override_message, indent=2)) + _send_fcm_message(override_message) + else: + print('''Invalid command. Please use one of the following commands: +python messaging.py --message=common-message +python messaging.py --message=override-message''') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo b/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..71cbdf3 Binary files /dev/null and b/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.mo differ diff --git a/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po b/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..dfec580 --- /dev/null +++ b/aitrainer_backoffice/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,57 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-26 11:21+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \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" + +#: .\controlling\admin\customer.py:58 +msgid "Registered" +msgstr "" + +#: .\controlling\models\customer.py:16 +#: .\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" +msgstr "" + +#: .\controlling\models\frequent_customers.py:27 +msgid "Frequent Customers" +msgstr "" diff --git a/requirements.txt b/requirements.txt index f7f5df2..4d88cc0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,4 +16,5 @@ gunicorn==20.0.4 django-admin-sortable2==1.0 django-inline_actions==2.4.0 django-admin-rangefilter==0.8.1 -django-cron==0.5.1 \ No newline at end of file +django-cron==0.5.1 +firebase-admin \ No newline at end of file