diff --git a/backend/account/admin.py b/backend/account/admin.py index e293140..53c231d 100644 --- a/backend/account/admin.py +++ b/backend/account/admin.py @@ -9,7 +9,7 @@ from django.contrib.postgres.fields import ArrayField from django.contrib.auth.models import Group from unfold.forms import AdminPasswordChangeForm from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm - +from utils.admin import ModelAdmin class UserAddressInLine(TabularInline): model = UserAddressModel extra = 0 @@ -36,6 +36,7 @@ class UserAdmin(BaseUserAdmin, ModelAdmin, ImportExportModelAdmin): fieldsets = ( ('اطلاعات شخصی', {'fields': ('first_name', 'last_name', 'profile_photo', 'password', 'gender', 'birth_date'),}), ('اطلاعات ارتباطی', {'fields': ('phone', 'email'),}), + ('دسترسی های وبسایت', {'fields': ('is_superuser', 'video_uploader'),}), ) empty_value_display = 'ثبت نشده' add_fieldsets = ( diff --git a/backend/account/migrations/0011_user_video_uploader.py b/backend/account/migrations/0011_user_video_uploader.py new file mode 100644 index 0000000..d8249f3 --- /dev/null +++ b/backend/account/migrations/0011_user_video_uploader.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-02-14 22:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0010_useraddressmodel_is_main'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='video_uploader', + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/account/migrations/0012_alter_user_video_uploader.py b/backend/account/migrations/0012_alter_user_video_uploader.py new file mode 100644 index 0000000..425e808 --- /dev/null +++ b/backend/account/migrations/0012_alter_user_video_uploader.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-02-14 23:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0011_user_video_uploader'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='video_uploader', + field=models.BooleanField(default=False, help_text='اپلود کننده ی ویدیویی اموزشی پنل ادمین', verbose_name='اپلودر اموزش'), + ), + ] diff --git a/backend/account/models.py b/backend/account/models.py index fc097df..0e5323b 100644 --- a/backend/account/models.py +++ b/backend/account/models.py @@ -50,6 +50,7 @@ class User(AbstractBaseUser, PermissionsMixin): date_joined = models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ثبتنام') otp_hash = models.CharField(max_length=64, null=True, blank=True, verbose_name='کد یک بار مصرف') otp_expiry = models.DateTimeField(null=True, blank=True, verbose_name='تاریخ تمام شدن کد یک بار مصرف') + video_uploader = models.BooleanField(default=False, help_text='اپلود کننده ی ویدیویی اموزشی پنل ادمین', verbose_name='اپلودر اموزش') objects = UserManager() USERNAME_FIELD = 'phone' diff --git a/backend/blog/admin.py b/backend/blog/admin.py index fd74838..ea7b973 100644 --- a/backend/blog/admin.py +++ b/backend/blog/admin.py @@ -1,12 +1,11 @@ from django.contrib import admin from .models import * -from unfold.admin import ModelAdmin from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget from django.contrib.postgres.fields import ArrayField - +from utils.admin import ModelAdmin @admin.register(BlogModel) class BlogModelAdmin(ModelAdmin, ImportExportModelAdmin): diff --git a/backend/chat/admin.py b/backend/chat/admin.py index 8d83c8f..5532e04 100644 --- a/backend/chat/admin.py +++ b/backend/chat/admin.py @@ -1,12 +1,12 @@ from django.contrib import admin from .models import * -from unfold.admin import ModelAdmin + from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget from django.contrib.postgres.fields import ArrayField - +from utils.admin import ModelAdmin @admin.register(ProductChatModel) class ProductChatAdmin(ModelAdmin, ImportExportModelAdmin): diff --git a/backend/core/settings/unfold_conf.py b/backend/core/settings/unfold_conf.py index 3829318..934d808 100644 --- a/backend/core/settings/unfold_conf.py +++ b/backend/core/settings/unfold_conf.py @@ -30,7 +30,7 @@ UNFOLD = { }, - "BORDER_RADIUS": "8px", + "BORDER_RADIUS": "20px", "SHOW_HISTORY": True, "SHOW_VIEW_ON_SITE": True, "ENVIRONMENT": "core.settings.environment_callback", @@ -93,6 +93,12 @@ UNFOLD = { "icon": "dashboard", "link": reverse_lazy("admin:index"), }, + { + "title": _("آموزش استفاده از پنل"), + "icon": "school", + "link": reverse_lazy("admin:home_learnvideomodel_changelist"), + "badge": "utils.admin.new_learn_video_count", + }, { "title": _("سفارشات"), "icon": "shopping_cart", diff --git a/backend/core/static/visibility.png b/backend/core/static/visibility.png new file mode 100644 index 0000000..3a7a907 Binary files /dev/null and b/backend/core/static/visibility.png differ diff --git a/backend/core/static/visibility_off.png b/backend/core/static/visibility_off.png new file mode 100644 index 0000000..229a843 Binary files /dev/null and b/backend/core/static/visibility_off.png differ diff --git a/backend/core/urls.py b/backend/core/urls.py index 56a7db0..59fbd0f 100644 --- a/backend/core/urls.py +++ b/backend/core/urls.py @@ -26,6 +26,7 @@ urlpatterns = [ path('tickets/', include('ticket.urls')), path('blogs/', include('blog.urls')), path('order/', include('order.urls')), + path('home/', include('home.urls')), path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), ] diff --git a/backend/home/admin.py b/backend/home/admin.py index 57df957..818b2cd 100644 --- a/backend/home/admin.py +++ b/backend/home/admin.py @@ -1,14 +1,15 @@ from django.contrib import admin from .models import * -from unfold.admin import ModelAdmin +from unfold.admin import ModelAdmin as UnfoldModelAdmin from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget from django.contrib.postgres.fields import ArrayField - - - +from unfold.decorators import action, display +from django.utils.html import format_html +from unfold.decorators import display +from utils.admin import ModelAdmin @admin.register(ShowCaseSlider) class ShowCaseSliderAdmin(ModelAdmin, ImportExportModelAdmin): import_form_class = ImportForm @@ -24,6 +25,34 @@ class ShowCaseSliderAdmin(ModelAdmin, ImportExportModelAdmin): } } +@admin.register(LearnVideoModel) +class LearnVideoAdmin(UnfoldModelAdmin): + list_display = ['title', 'section', 'display_viewd'] + search_fields = ['title', 'section'] + compressed_fields = False + list_filter = ['section'] + warn_unsaved_form = True + change_form_template = 'video_change_form_after.html' + formfield_overrides = { + ArrayField: { + "widget": ArrayWidget, + } + } + + + @display(description='دیده شده') + def display_viewd(self, instance): + if instance.viewd: + svg = f'' + else: + svg = f'' + + return format_html( + svg + ) + + + @admin.register(SliderModel) class SliderAdmin(ModelAdmin, ImportExportModelAdmin): diff --git a/backend/home/migrations/0006_learnvideomodel.py b/backend/home/migrations/0006_learnvideomodel.py new file mode 100644 index 0000000..9353a52 --- /dev/null +++ b/backend/home/migrations/0006_learnvideomodel.py @@ -0,0 +1,25 @@ +# Generated by Django 5.1.2 on 2025-02-14 21:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0005_alter_showcaseslider_description_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='LearnVideoModel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=50)), + ('video', models.FileField(upload_to='learning_video/')), + ], + options={ + 'verbose_name': 'ویدیوی اموزشی', + 'verbose_name_plural': 'ویدیوی های اموزشی', + }, + ), + ] diff --git a/backend/home/migrations/0007_learnvideomodel_section_alter_learnvideomodel_title_and_more.py b/backend/home/migrations/0007_learnvideomodel_section_alter_learnvideomodel_title_and_more.py new file mode 100644 index 0000000..b7b3d98 --- /dev/null +++ b/backend/home/migrations/0007_learnvideomodel_section_alter_learnvideomodel_title_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 5.1.2 on 2025-02-14 21:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0006_learnvideomodel'), + ] + + operations = [ + migrations.AddField( + model_name='learnvideomodel', + name='section', + field=models.CharField(default='', max_length=40, verbose_name='بخش مربوطه'), + preserve_default=False, + ), + migrations.AlterField( + model_name='learnvideomodel', + name='title', + field=models.CharField(max_length=100, verbose_name='عنوان ویدیو'), + ), + migrations.AlterField( + model_name='learnvideomodel', + name='video', + field=models.FileField(upload_to='learning_video/', verbose_name='ویدیو'), + ), + ] diff --git a/backend/home/migrations/0008_learnvideomodel_content_type.py b/backend/home/migrations/0008_learnvideomodel_content_type.py new file mode 100644 index 0000000..ab5b2f3 --- /dev/null +++ b/backend/home/migrations/0008_learnvideomodel_content_type.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.2 on 2025-02-14 23:12 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('home', '0007_learnvideomodel_section_alter_learnvideomodel_title_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='learnvideomodel', + name='content_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype', verbose_name='Related Model'), + ), + ] diff --git a/backend/home/migrations/0009_alter_learnvideomodel_content_type.py b/backend/home/migrations/0009_alter_learnvideomodel_content_type.py new file mode 100644 index 0000000..7f1327e --- /dev/null +++ b/backend/home/migrations/0009_alter_learnvideomodel_content_type.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.2 on 2025-02-14 23:28 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('home', '0008_learnvideomodel_content_type'), + ] + + operations = [ + migrations.AlterField( + model_name='learnvideomodel', + name='content_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype', unique=True, verbose_name='مدل مرتبط'), + ), + ] diff --git a/backend/home/migrations/0010_learnvideomodel_viewd.py b/backend/home/migrations/0010_learnvideomodel_viewd.py new file mode 100644 index 0000000..5b4b232 --- /dev/null +++ b/backend/home/migrations/0010_learnvideomodel_viewd.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-02-15 00:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0009_alter_learnvideomodel_content_type'), + ] + + operations = [ + migrations.AddField( + model_name='learnvideomodel', + name='viewd', + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/home/migrations/0011_learnvideomodel_icon_alter_learnvideomodel_viewd.py b/backend/home/migrations/0011_learnvideomodel_icon_alter_learnvideomodel_viewd.py new file mode 100644 index 0000000..adf3697 --- /dev/null +++ b/backend/home/migrations/0011_learnvideomodel_icon_alter_learnvideomodel_viewd.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.2 on 2025-02-15 07:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0010_learnvideomodel_viewd'), + ] + + operations = [ + migrations.AddField( + model_name='learnvideomodel', + name='icon', + field=models.CharField(default='', max_length=30, verbose_name='ایکون'), + preserve_default=False, + ), + migrations.AlterField( + model_name='learnvideomodel', + name='viewd', + field=models.BooleanField(default=False, verbose_name='تماشا شده'), + ), + ] diff --git a/backend/home/migrations/0012_alter_learnvideomodel_content_type.py b/backend/home/migrations/0012_alter_learnvideomodel_content_type.py new file mode 100644 index 0000000..47c18fc --- /dev/null +++ b/backend/home/migrations/0012_alter_learnvideomodel_content_type.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.2 on 2025-02-16 17:45 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('home', '0011_learnvideomodel_icon_alter_learnvideomodel_viewd'), + ] + + operations = [ + migrations.AlterField( + model_name='learnvideomodel', + name='content_type', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype', verbose_name='مدل مرتبط'), + ), + ] diff --git a/backend/home/models.py b/backend/home/models.py index d0d9a1e..857e0e0 100644 --- a/backend/home/models.py +++ b/backend/home/models.py @@ -1,6 +1,6 @@ from django.db import models from product.models import ProductModel - +from django.urls import reverse class SliderModel(models.Model): link = models.URLField(verbose_name='لینک') @@ -45,4 +45,38 @@ class ShowCaseSlider(models.Model): class Meta: verbose_name = 'مدل نمایش کیس' - verbose_name_plural = 'مدل نمایش کیس ها' \ No newline at end of file + verbose_name_plural = 'مدل نمایش کیس ها' + +from django.contrib.contenttypes.models import ContentType +class LearnVideoModel(models.Model): + title = models.CharField(max_length=100, verbose_name='عنوان ویدیو') + section = models.CharField(max_length=40, verbose_name='بخش مربوطه') + video = models.FileField(upload_to='learning_video/', verbose_name='ویدیو') + content_type = models.OneToOneField( + ContentType, + on_delete=models.CASCADE, + verbose_name='مدل مرتبط', blank=True, null=True, unique=True + ) + icon = models.CharField(max_length=30, verbose_name='ایکون') + viewd = models.BooleanField(default=False, verbose_name='تماشا شده') + @property + def section_url(self): + if not self.content_type: + return None + + app_label = self.content_type.app_label + model_name = self.content_type.model + + try: + return reverse(f'admin:{app_label}_{model_name}_changelist') + except Exception: + return None + + + + def __str__(self): + return self.title + + class Meta: + verbose_name = 'ویدیوی اموزشی' + verbose_name_plural = 'ویدیوی های اموزشی' \ No newline at end of file diff --git a/backend/home/urls.py b/backend/home/urls.py new file mode 100644 index 0000000..a406202 --- /dev/null +++ b/backend/home/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('video/view/', views.ChangeViewVideo.as_view(), name='product-chat-view'), +] \ No newline at end of file diff --git a/backend/home/views.py b/backend/home/views.py index 181d7ab..003a09a 100644 --- a/backend/home/views.py +++ b/backend/home/views.py @@ -1,10 +1,19 @@ -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect from rest_framework.views import APIView, Response from product.models import ProductModel, SubCategoryModel, DollorModel from product.serializers import SubCategorySerializer, DynamicProductSerializer from .serializers import * from .models import * from rest_framework import status +from django.views import View + + +class ChangeViewVideo(View): + def get(self, request, pk): + videomodel = get_object_or_404(LearnVideoModel, pk=pk) + videomodel.viewd = not videomodel.viewd + videomodel.save() + return redirect('admin:home_learnvideomodel_changelist') class HomeView(APIView): diff --git a/backend/order/admin.py b/backend/order/admin.py index 813088f..bce84b0 100644 --- a/backend/order/admin.py +++ b/backend/order/admin.py @@ -1,12 +1,12 @@ from django.contrib import admin from .models import * -from unfold.admin import ModelAdmin, TabularInline, StackedInline +from unfold.admin import TabularInline, StackedInline from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget from django.contrib.postgres.fields import ArrayField - +from utils.admin import ModelAdmin class OrderItemModelInline(StackedInline): model = OrderItemModel diff --git a/backend/order/migrations/0005_alter_orderitemmodel_options.py b/backend/order/migrations/0005_alter_orderitemmodel_options.py new file mode 100644 index 0000000..308bddd --- /dev/null +++ b/backend/order/migrations/0005_alter_orderitemmodel_options.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.2 on 2025-02-14 21:23 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0004_alter_orderitemmodel_product'), + ] + + operations = [ + migrations.AlterModelOptions( + name='orderitemmodel', + options={'verbose_name': 'ایتم سبد خرید', 'verbose_name_plural': 'ایتم های سبد خرید'}, + ), + ] diff --git a/backend/product/admin.py b/backend/product/admin.py index 5ea98c7..3cfe104 100644 --- a/backend/product/admin.py +++ b/backend/product/admin.py @@ -1,15 +1,14 @@ -from django.contrib import admin +from django.contrib import admin, messages from .models import * -from unfold.admin import ModelAdmin, TabularInline, StackedInline - +from unfold.admin import TabularInline, StackedInline +from home.models import LearnVideoModel from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget from django.contrib.postgres.fields import ArrayField -from unfold.widgets import ( - UnfoldAdminColorInputWidget, -) +from unfold.widgets import UnfoldAdminColorInputWidget from unfold.decorators import action, display +from utils.admin import ModelAdmin @admin.register(ProductVariant) class ProductVariantAdmin(ModelAdmin, ImportExportModelAdmin): diff --git a/backend/templates/video_change_form_after.html b/backend/templates/video_change_form_after.html new file mode 100644 index 0000000..54b4059 --- /dev/null +++ b/backend/templates/video_change_form_after.html @@ -0,0 +1,166 @@ +{% extends "admin/base_site.html" %} +{% load unfold %} +{% load i18n admin_urls static admin_modify %} + +{% block extrahead %}{{ block.super }} + + {{ media }} +{% endblock %} + +{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %} + +{% if not is_popup %} + {% block breadcrumbs %} +
+
+
    + {% url 'admin:index' as link %} + {% trans 'Home' as name %} + {% include 'unfold/helpers/breadcrumb_item.html' with link=link name=name %} + + {% url 'admin:app_list' app_label=opts.app_label as link %} + {% include 'unfold/helpers/breadcrumb_item.html' with link=link name=opts.app_config.verbose_name %} + + {% if has_view_permission %} + {% url opts|admin_urlname:'changelist' as link %} + {% include 'unfold/helpers/breadcrumb_item.html' with link=link name=opts.verbose_name_plural|capfirst %} + {% else %} + {% include 'unfold/helpers/breadcrumb_item.html' with link='' name=opts.verbose_name_plural|capfirst %} + {% endif %} + + {% if add %} + {% blocktranslate trimmed with name=opts.verbose_name asvar breadcrumb_name %} + Add {{ name }} + {% endblocktranslate %} + + {% include 'unfold/helpers/breadcrumb_item.html' with link='' name=breadcrumb_name %} + {% else %} + {% include 'unfold/helpers/breadcrumb_item.html' with link='' name=original|truncatewords:'18' %} + {% endif %} +
+
+
+ {% endblock %} +{% endif %} + +{% block nav-global %}{% spaceless %} + {% if change and not is_popup %} + {% block object-tools-items %} + {% change_form_object_tools %} + {% endblock %} + {% endif %} +{% endspaceless %}{% endblock %} + +{% block nav-global-side %} + {% if has_add_permission %} + {% include "unfold/helpers/add_link.html" %} + {% endif %} +{% endblock %} + +{% block content %} +
+ {% block form_before %}{% endblock %} +
+
+

+ {{original.icon}} + اموزش بخش {{original.content_type}} +

+
+ +
+ {% component "unfold/components/flex.html" with class="flex-col gap-4 lg:flex-row" %} + {% component "unfold/components/button.html" with href=original.section_url %} + نمایش بخش مربوطه + {% endcomponent %} + {% endcomponent %} +
+
+ {% if adminform.model_admin.change_form_outer_before_template %} + {% include adminform.model_admin.change_form_outer_before_template %} + {% endif %} + +
+ {% if original and original.video %} +

+ + + {{original.content_type}} + + آموزش بخش +

+
+ +
+ {% else %} +

no video available.

+ {% endif %} +
+ + + + {% if request.user.video_uploader %} +
+ {% csrf_token %} + + {% if adminform.model_admin.change_form_before_template %} + {% include adminform.model_admin.change_form_before_template %} + {% endif %} + + {% block form_top %}{% endblock %} + +
+ {% if is_popup %} + + {% endif %} + + {% if to_field %} + + {% endif %} + + {% include "unfold/helpers/messages/errornote.html" with errors=errors %} + {% include "unfold/helpers/messages/error.html" with errors=adminform.form.non_field_errors %} + + {% block field_sets %} + {% for fieldset in adminform %} + {% if "tab" not in fieldset.classes %} + {% include 'admin/includes/fieldset.html' %} + {% endif %} + {% endfor %} + + {% include "unfold/helpers/fieldsets_tabs.html" %} + {% endblock %} + + {% block after_field_sets %}{% endblock %} + + {% block inline_field_sets %} + {% for inline_admin_formset in inline_admin_formsets %} + {% include inline_admin_formset.opts.template %} + {% endfor %} + {% endblock %} + + {% block after_related_objects %}{% endblock %} + + {% if adminform.model_admin.change_form_after_template %} + {% include adminform.model_admin.change_form_after_template %} + {% endif %} + + {% block submit_buttons_bottom %}{% submit_row %}{% endblock %} + + {% block admin_change_form_document_ready %} + + {% endblock %} + + {% prepopulated_fields_js %} +
+
+ {% endif %} + {% if adminform.model_admin.change_form_outer_after_template %} + {% include adminform.model_admin.change_form_outer_after_template %} + {% endif %} + + {% block form_after %}{% endblock %} +
+{% endblock %} \ No newline at end of file diff --git a/backend/ticket/admin.py b/backend/ticket/admin.py index 121c965..5ae80c6 100644 --- a/backend/ticket/admin.py +++ b/backend/ticket/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from .models import * -from unfold.admin import ModelAdmin, TabularInline +from unfold.admin import TabularInline from import_export.admin import ImportExportModelAdmin from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm @@ -10,7 +10,7 @@ from unfold.contrib.filters.admin import ( ChoicesDropdownFilter, MultipleChoicesDropdownFilter, ) - +from utils.admin import ModelAdmin diff --git a/backend/ticket/migrations/0008_alter_ticket_ticket_category.py b/backend/ticket/migrations/0008_alter_ticket_ticket_category.py new file mode 100644 index 0000000..e700fbb --- /dev/null +++ b/backend/ticket/migrations/0008_alter_ticket_ticket_category.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-02-14 21:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0007_alter_ticket_ticket_category'), + ] + + operations = [ + migrations.AlterField( + model_name='ticket', + name='ticket_category', + field=models.CharField(choices=[('finance_and_accounting', 'مالی و حسابداری'), ('user_profile', 'پروفایل کاربری'), ('order_tracking', 'پیگیری سفارش'), ('authentication', 'احراز هویت'), ('product', 'محصول'), ('bug_and_error_reporting', 'اعلام باگ و خطا در وبسایت'), ('other', 'سایر')], max_length=30, verbose_name='دسته بندی تیکت'), + ), + ] diff --git a/backend/utils/admin.py b/backend/utils/admin.py index 61cabce..67786f3 100644 --- a/backend/utils/admin.py +++ b/backend/utils/admin.py @@ -1,7 +1,7 @@ from order.models import OrderModel from product.models import DollorModel, CommentModel from ticket.models import Ticket - +from home.models import LearnVideoModel def admin_pending_count(request): pending_count = OrderModel.objects.filter(status='ADMIN_PENDING').count() @@ -15,4 +15,32 @@ def comment_count(request): return CommentModel.objects.filter(review_status='not_reviwed').count() def new_ticket_count(request): - return Ticket.objects.filter(status__in=['open', 'in_progress']).count() \ No newline at end of file + return Ticket.objects.filter(status__in=['open', 'in_progress']).count() + +def new_learn_video_count(request): + return LearnVideoModel.objects.filter(viewd=False).count() + + +from django.contrib import admin, messages +from unfold.admin import ModelAdmin +from home.models import LearnVideoModel +from import_export.admin import ImportExportModelAdmin +from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm +from unfold.decorators import action, display +from django.shortcuts import redirect +from django.contrib.contenttypes.models import ContentType + + +class ModelAdmin(ModelAdmin): + actions_list = ['redirect_to_learn'] + @action(description=f"چگونگی استفاده این بخش") + def redirect_to_learn(self, request): + content_type = ContentType.objects.get_for_model(self.model) + try: + learn_video = LearnVideoModel.objects.get( + content_type=content_type, + ) + return redirect(f'/admin/home/learnvideomodel/{learn_video.id}/change/') + except Exception as e: + messages.error(request, f"برای بخش {content_type} ویدیویی اپلود نشده است") + return redirect(f'/admin/home/learnvideomodel/') \ No newline at end of file