From 9ba43e8fd1318851ddd7ab0330974a46684bc086 Mon Sep 17 00:00:00 2001 From: bobbyvish Date: Thu, 21 Mar 2024 13:09:14 +0530 Subject: [PATCH 1/2] refactor code by applying isort and added left arrow icon --- module_activity/api/serializers.py | 33 +-- module_activity/api/urls.py | 2 +- module_activity/api/views.py | 48 ++-- module_activity/forms.py | 7 +- module_activity/models.py | 1 + module_activity/urls.py | 3 +- module_activity/views.py | 34 +-- module_auth/api/serializers.py | 5 +- module_auth/api/urls.py | 2 +- module_auth/api/utils.py | 12 +- module_auth/api/views.py | 48 ++-- module_auth/forms.py | 4 +- module_auth/urls.py | 3 +- module_auth/views.py | 48 ++-- module_cms/api/serializers.py | 2 + module_cms/api/urls.py | 1 + module_cms/api/views.py | 6 +- module_cms/forms.py | 9 +- module_cms/models.py | 6 +- module_cms/urls.py | 1 + module_cms/views.py | 34 ++- module_iam/models.py | 26 +- module_iam/urls.py | 10 +- module_iam/views.py | 203 +++++++------- module_notification/forms.py | 2 + module_notification/models.py | 2 + module_notification/urls.py | 3 +- module_notification/views.py | 36 ++- module_project/settings/base.py | 1 + module_project/settings/development.py | 4 +- module_project/urls.py | 4 +- module_project/utils.py | 17 +- module_support/api/serializers.py | 2 + module_support/api/urls.py | 1 + module_support/api/views.py | 6 +- module_support/models.py | 1 + module_support/urls.py | 1 + module_support/views.py | 32 ++- .../base_structure/elements/sidebar.html | 5 +- .../base_structure/layout/dashboard.html | 6 - .../chronic_conditon_list.html | 20 +- .../module_activity/intolerance_list.html | 20 +- .../module_activity/past_treatment_list.html | 20 +- templates/module_activity/symptoms_list.html | 20 +- templates/module_auth/user_add.html | 7 +- templates/module_auth/user_view.html | 6 +- templates/module_auth/users_archive_list.html | 7 +- templates/module_auth/users_list.html | 3 +- templates/module_cms/faq_add.html | 12 +- templates/module_cms/privacy_policy_edit.html | 12 +- .../module_cms/terms_and_condition_edit.html | 12 +- templates/module_iam/iam_group.html | 4 +- templates/module_iam/iam_group_add.html | 12 +- .../module_iam/iam_group_archive_list.html | 248 +++++++++++++++++ templates/module_iam/iam_principal_add.html | 12 +- .../module_iam/iam_principal_archive.html | 244 +++++++++++++++++ .../module_iam/iam_principal_group_link.html | 19 +- templates/module_iam/iam_role.html | 8 +- templates/module_iam/iam_role_add.html | 12 +- templates/module_iam/iam_role_archive.html | 252 ++++++++++++++++++ templates/module_iam/profile_details.html | 17 +- .../module_iam/profile_details_edit.html | 13 +- .../module_notification/add_notification.html | 7 +- .../contactus_archive_list.html | 14 +- 64 files changed, 1222 insertions(+), 450 deletions(-) create mode 100644 templates/module_iam/iam_group_archive_list.html create mode 100644 templates/module_iam/iam_principal_archive.html create mode 100644 templates/module_iam/iam_role_archive.html diff --git a/module_activity/api/serializers.py b/module_activity/api/serializers.py index 29e944c..73de20b 100644 --- a/module_activity/api/serializers.py +++ b/module_activity/api/serializers.py @@ -1,27 +1,18 @@ -import os import math -from django.conf import settings -from rest_framework import serializers -from django.utils import timezone +import os from datetime import datetime + +from django.conf import settings +from django.utils import timezone +from rest_framework import serializers + from module_iam.models import IAmPrincipal -from ..models import ( - PrincipalHealthData, - Intolerance, - Symptoms, - PastTreatment, - ChronicCondition, - Medicine, - Medication, - Bowel, - SymptomTypeAfterMeal, - SymptomTypeBeforeMeal, - MealSymptomRecord, - FoodIngredientRecord, - FoodRecord, - BeverageRecord, - MealRecord, -) + +from ..models import (BeverageRecord, Bowel, ChronicCondition, + FoodIngredientRecord, FoodRecord, Intolerance, + MealRecord, MealSymptomRecord, Medication, Medicine, + PastTreatment, PrincipalHealthData, Symptoms, + SymptomTypeAfterMeal, SymptomTypeBeforeMeal) class IAmPrincipalSerializer(serializers.ModelSerializer): diff --git a/module_activity/api/urls.py b/module_activity/api/urls.py index 4bb9188..daedfe5 100644 --- a/module_activity/api/urls.py +++ b/module_activity/api/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from . import views +from . import views urlpatterns = [ diff --git a/module_activity/api/views.py b/module_activity/api/views.py index aa700ca..00fd1ed 100644 --- a/module_activity/api/views.py +++ b/module_activity/api/views.py @@ -1,39 +1,26 @@ from datetime import datetime, timedelta -from rest_framework.views import APIView -from rest_framework.response import Response + +from django.db.models import Count, Max, Min, Prefetch from rest_framework import status from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView from rest_framework_simplejwt.authentication import JWTAuthentication -from django.db.models import Prefetch, Count, Max, Min -from module_project import constants, date_utils -from module_project.utils import ApiResponse -from module_iam.models import IAmPrincipal -from ..models import ( - PrincipalHealthData, - Intolerance, - Symptoms, - PastTreatment, - ChronicCondition, - Medication, - Bowel, - MealSymptomRecord, - MealRecord, -) -from .serializers import ( - IntoleranceSerializer, - SymptomsSerializer, - PastTreatmentSerializer, - ChronicConditionSerializer, - MedicationSerializer, - BowelSerializer, - MealSymptomRecordSerializer, - MealRecordSerializer, - IAmPrincipalSerializer, - PrincipalHealthDataSerializer, - PrincipalAndHealthSerializer, -) +from module_iam.models import IAmPrincipal +from module_project import constants, date_utils from module_project.service import OneSignalNotificationService +from module_project.utils import ApiResponse + +from ..models import (Bowel, ChronicCondition, Intolerance, MealRecord, + MealSymptomRecord, Medication, PastTreatment, + PrincipalHealthData, Symptoms) +from .serializers import (BowelSerializer, ChronicConditionSerializer, + IAmPrincipalSerializer, IntoleranceSerializer, + MealRecordSerializer, MealSymptomRecordSerializer, + MedicationSerializer, PastTreatmentSerializer, + PrincipalAndHealthSerializer, + PrincipalHealthDataSerializer, SymptomsSerializer) class ProfileAPIView(APIView): @@ -630,7 +617,6 @@ class MealAPIView(APIView): message=constants.RECORD_DELETED, status=status.HTTP_204_NO_CONTENT ) - from collections import defaultdict diff --git a/module_activity/forms.py b/module_activity/forms.py index b30b2d2..384b576 100644 --- a/module_activity/forms.py +++ b/module_activity/forms.py @@ -1,7 +1,10 @@ from django import forms -from module_project import constants -from .models import Intolerance, Symptoms, PastTreatment, ChronicCondition + from module_iam.models import IAmPrincipal +from module_project import constants + +from .models import ChronicCondition, Intolerance, PastTreatment, Symptoms + class IntoleranceForm(forms.ModelForm): class Meta: diff --git a/module_activity/models.py b/module_activity/models.py index f737746..545bee5 100644 --- a/module_activity/models.py +++ b/module_activity/models.py @@ -1,4 +1,5 @@ from django.db import models + from module_iam.models import BaseModel, IAmPrincipal diff --git a/module_activity/urls.py b/module_activity/urls.py index e335251..d52d152 100644 --- a/module_activity/urls.py +++ b/module_activity/urls.py @@ -1,7 +1,8 @@ from django.urls import path -from . import views from django.views.generic import TemplateView +from . import views + app_name = "module_activity" urlpatterns = [ diff --git a/module_activity/views.py b/module_activity/views.py index 233c64a..aa0efc0 100644 --- a/module_activity/views.py +++ b/module_activity/views.py @@ -1,35 +1,25 @@ import logging - from collections import defaultdict from datetime import datetime, timedelta -from django.shortcuts import get_object_or_404, render, redirect + from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin +from django.db.models import Count, Prefetch, Q +from django.http import JsonResponse +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views import generic -from django.db.models import Q, Prefetch, Count -from .models import ( - Intolerance, - Symptoms, - ChronicCondition, - PastTreatment, - MealRecord, - Bowel, - MealSymptomRecord, - Medication, -) -from .forms import ( - IntoleranceForm, - SymptomsForm, - PastTreatmentForm, - ChronicConditionForm, -) from django_datatables_view.base_datatable_view import BaseDatatableView -from module_iam.models import IAmPrincipal + from module_iam import iam_constant +from module_iam.models import IAmPrincipal from module_project import constants, date_utils from module_project.utils import JsonResponseUtil -from django.http import JsonResponse + +from .forms import (ChronicConditionForm, IntoleranceForm, PastTreatmentForm, + SymptomsForm) +from .models import (Bowel, ChronicCondition, Intolerance, MealRecord, + MealSymptomRecord, Medication, PastTreatment, Symptoms) logger = logging.getLogger(__name__) @@ -45,7 +35,7 @@ class BaseView(generic.TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["page_name"] = self.page_name - context["principal_id"] = self.kwargs.get("principal_id") + context["principal_id"] = get_object_or_404(IAmPrincipal, id=self.kwargs.get("principal_id")) return context diff --git a/module_auth/api/serializers.py b/module_auth/api/serializers.py index 9d228f3..d0f189a 100644 --- a/module_auth/api/serializers.py +++ b/module_auth/api/serializers.py @@ -1,9 +1,10 @@ +from django.contrib.auth import authenticate from django.contrib.auth.hashers import make_password from rest_framework import serializers +from rest_framework.validators import UniqueValidator + from module_iam.models import IAmPrincipal from module_project import constants -from django.contrib.auth import authenticate -from rest_framework.validators import UniqueValidator # class BasePasswordSerializer(serializers.Serializer): # confirm_password = serializers.CharField(write_only=True, required=True) diff --git a/module_auth/api/urls.py b/module_auth/api/urls.py index d0e924e..f943791 100644 --- a/module_auth/api/urls.py +++ b/module_auth/api/urls.py @@ -1,7 +1,7 @@ from django.urls import path -from . import views from rest_framework_simplejwt.views import TokenRefreshView +from . import views urlpatterns = [ path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), diff --git a/module_auth/api/utils.py b/module_auth/api/utils.py index 2386d5f..9e77ed3 100644 --- a/module_auth/api/utils.py +++ b/module_auth/api/utils.py @@ -1,11 +1,13 @@ +import logging from typing import Optional + +import requests +from django.core.exceptions import ValidationError +from rest_framework_simplejwt.tokens import RefreshToken + +from module_iam.models import IAmPrincipal, IAmPrincipalOtp from module_project import constants from module_project.utils import ApiResponse -from module_iam.models import IAmPrincipal, IAmPrincipalOtp -from rest_framework_simplejwt.tokens import RefreshToken -from django.core.exceptions import ValidationError -import requests -import logging logger = logging.getLogger(__name__) diff --git a/module_auth/api/views.py b/module_auth/api/views.py index cb6b8b0..165ae9f 100644 --- a/module_auth/api/views.py +++ b/module_auth/api/views.py @@ -1,29 +1,25 @@ from datetime import datetime -from rest_framework import status -from rest_framework.views import APIView -from rest_framework.permissions import IsAuthenticated -from rest_framework_simplejwt.authentication import JWTAuthentication -from module_project import constants -from module_project.service import SMSService, EmailService -from module_project.utils import ApiResponse -from .utils import AuthService, GoogleAuthService -from django.contrib.auth import authenticate -import requests -from module_iam.models import AppVersion, IAmPrincipal, IAmPrincipalOtp, IAmPrincipalType, IAmPrincipalSource -from .serializers import ( - RegistrationSerializer, - LoginSerializer, - OtpVerificationSerializer, - PasswordResetSerializer, -) -from django.conf import settings -from rest_framework.response import Response -from .utils import ( - generate_token_and_user_data, - get_principal_by_email, - authticate_with_otp_and_passsword, -) +import requests +from django.conf import settings +from django.contrib.auth import authenticate +from rest_framework import status +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework_simplejwt.authentication import JWTAuthentication + +from module_iam.models import (AppVersion, IAmPrincipal, IAmPrincipalOtp, + IAmPrincipalSource, IAmPrincipalType) +from module_project import constants +from module_project.service import EmailService, SMSService +from module_project.utils import ApiResponse + +from .serializers import (LoginSerializer, OtpVerificationSerializer, + PasswordResetSerializer, RegistrationSerializer) +from .utils import (AuthService, GoogleAuthService, + authticate_with_otp_and_passsword, + generate_token_and_user_data, get_principal_by_email) class RegistrationView(APIView): @@ -257,6 +253,7 @@ class GoogleSignin(APIView): def post(self, request): try: access_token = request.data["access_token"] + player_id = request.data["player_id"] user_info = GoogleAuthService.get_user_info(access_token) print(f"User Info : {user_info}") @@ -272,6 +269,7 @@ class GoogleSignin(APIView): email=user_info['email'], first_name=f"{user_info['given_name']} {user_info['family_name']}", last_login=datetime.now(), + player_id=player_id, principal_type=IAmPrincipalType.get_principal_user(), principal_source=IAmPrincipalSource.get_principal_google() ) @@ -289,6 +287,8 @@ class GoogleSignin(APIView): import jwt + + class AppleSignin(APIView): authentication_classes = [] permission_classes = [] diff --git a/module_auth/forms.py b/module_auth/forms.py index 0a90eb6..efbef3b 100644 --- a/module_auth/forms.py +++ b/module_auth/forms.py @@ -1,7 +1,9 @@ from django import forms from django.core import validators -from module_project import constants + from module_iam.models import IAmPrincipal +from module_project import constants + class LoginForm(forms.Form): email = forms.EmailField( diff --git a/module_auth/urls.py b/module_auth/urls.py index 23d6bf6..cd00a28 100644 --- a/module_auth/urls.py +++ b/module_auth/urls.py @@ -1,6 +1,7 @@ from django.urls import path +from django.views.generic import RedirectView, TemplateView + from . import views -from django.views.generic import TemplateView, RedirectView app_name = "module_auth" diff --git a/module_auth/views.py b/module_auth/views.py index b28597a..bab9b42 100644 --- a/module_auth/views.py +++ b/module_auth/views.py @@ -1,31 +1,31 @@ import logging - from datetime import datetime -from django.db.models import Q, Prefetch + from django.contrib import messages from django.contrib.auth import authenticate, login, logout -from django.contrib.auth.views import LogoutView from django.contrib.auth.forms import PasswordResetForm from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.auth.views import ( - LoginView, - PasswordResetCompleteView, - PasswordResetConfirmView, - PasswordResetDoneView, - PasswordResetView, -) -from django.shortcuts import render, redirect, get_object_or_404 +from django.contrib.auth.views import (LoginView, LogoutView, + PasswordResetCompleteView, + PasswordResetConfirmView, + PasswordResetDoneView, + PasswordResetView) +from django.db.models import Prefetch, Q +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views import generic -from .forms import LoginForm, UserForm -from module_iam.models import IAmPrincipal, IAmPrincipalType -from module_iam import iam_constant -from module_activity.models import PrincipalHealthData, Intolerance, Symptoms, PastTreatment, ChronicCondition from django_datatables_view.base_datatable_view import BaseDatatableView + +from module_activity.models import (ChronicCondition, Intolerance, + PastTreatment, PrincipalHealthData, + Symptoms) +from module_iam import iam_constant +from module_iam.models import IAmPrincipal, IAmPrincipalType +from module_project import constants from module_project.mixins import ActionMixin from module_project.utils import JsonResponseUtil -from module_project import constants +from .forms import LoginForm, UserForm logger = logging.getLogger(__name__) @@ -169,12 +169,26 @@ class UserListJson(BaseDatatableView): ) for column in self.columns: - search_value = self.request.GET.get(f'columns[{self.columns.index(column)}][search][value]', None) + # print(f"columen index pattern {}") + search_value = self.request.GET.get(f'columns[{self.columns.index(column)+1}][search][value]', None) if search_value: qs = qs.filter(**{f"{column}__icontains": search_value}) return qs + def ordering(self, qs): + order = self.request.GET.get('order[0][dir]', None) + if order: + column_index = int(self.request.GET.get('order[0][column]', None)) - 1 + order_column = self.order_columns[column_index] + + if order == "asc": + qs = qs.order_by(order_column) + elif order == "desc": + qs = qs.order_by("-" + order_column) + + return qs + class UserActionView(ActionMixin): model = IAmPrincipal diff --git a/module_cms/api/serializers.py b/module_cms/api/serializers.py index e5b908c..2c3677f 100644 --- a/module_cms/api/serializers.py +++ b/module_cms/api/serializers.py @@ -1,7 +1,9 @@ from rest_framework import serializers from taggit.models import Tag + from module_cms.models import Faqs, Organization + class FaqSerializer(serializers.ModelSerializer): class Meta: model = Faqs diff --git a/module_cms/api/urls.py b/module_cms/api/urls.py index 70121cc..c82fd6e 100644 --- a/module_cms/api/urls.py +++ b/module_cms/api/urls.py @@ -1,4 +1,5 @@ from django.urls import path + from . import views urlpatterns = [ diff --git a/module_cms/api/views.py b/module_cms/api/views.py index 4604042..16e8c2d 100644 --- a/module_cms/api/views.py +++ b/module_cms/api/views.py @@ -1,10 +1,12 @@ -from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated +from rest_framework.views import APIView from rest_framework_simplejwt.authentication import JWTAuthentication + from module_project import constants from module_project.utils import ApiResponse -from .serializers import FaqSerializer, OrganizationSerializer + from ..models import Faqs, Organization +from .serializers import FaqSerializer, OrganizationSerializer class FaqListAPIView(APIView): diff --git a/module_cms/forms.py b/module_cms/forms.py index ff681cc..50b4208 100644 --- a/module_cms/forms.py +++ b/module_cms/forms.py @@ -1,14 +1,11 @@ from django import forms -from django.core.exceptions import ValidationError from django.core import validators -from .models import ( - Organization, - FaqCategory, - Faqs, -) +from django.core.exceptions import ValidationError from module_project import constants +from .models import FaqCategory, Faqs, Organization + class OrganizationForm(forms.ModelForm): class Meta: diff --git a/module_cms/models.py b/module_cms/models.py index 9dcac40..5a9c936 100644 --- a/module_cms/models.py +++ b/module_cms/models.py @@ -1,7 +1,9 @@ from django.db import models -from module_iam.models import BaseModel, IAmPrincipal -from taggit.managers import TaggableManager from django_quill.fields import QuillField +from taggit.managers import TaggableManager + +from module_iam.models import BaseModel, IAmPrincipal + # Create your models here. class Organization(BaseModel): diff --git a/module_cms/urls.py b/module_cms/urls.py index dbae20e..0bb6342 100644 --- a/module_cms/urls.py +++ b/module_cms/urls.py @@ -1,4 +1,5 @@ from django.urls import path + from . import views app_name = "module_cms" diff --git a/module_cms/views.py b/module_cms/views.py index ed65bb4..b849e78 100644 --- a/module_cms/views.py +++ b/module_cms/views.py @@ -3,18 +3,19 @@ import logging from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Q -from django.shortcuts import render, redirect, get_object_or_404 +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views import generic -from module_iam.models import IAmPrincipal -from module_iam import iam_constant -from .forms import AboutUsForm, TermsAndConditionForm, FaqsForm, PrivacyPolicyForm -from .models import Faqs, Organization -from module_project.mixins import DatatablesMixin from django_datatables_view.base_datatable_view import BaseDatatableView -from module_project.mixins import ActionMixin +from module_iam import iam_constant +from module_iam.models import IAmPrincipal from module_project import constants +from module_project.mixins import ActionMixin, DatatablesMixin + +from .forms import (AboutUsForm, FaqsForm, PrivacyPolicyForm, + TermsAndConditionForm) +from .models import Faqs, Organization logger = logging.getLogger(__name__) @@ -35,8 +36,8 @@ class FaqView(LoginRequiredMixin, generic.TemplateView): class FaqListJson(BaseDatatableView): model = Faqs - columns = ["id", "question", "answer", "active", "deleted"] - order_columns = ["id", "question", "answer", "active", "deleted"] + columns = ["id", "question", "answer", "active"] + order_columns = ["id", "question", "answer", "active"] def get_initial_queryset(self): deleted_flag = self.request.GET.get('deleted_flag', None) @@ -55,11 +56,24 @@ class FaqListJson(BaseDatatableView): ) for column in self.columns: - search_value = self.request.GET.get(f'columns[{self.columns.index(column)}][search][value]', None) + search_value = self.request.GET.get(f'columns[{self.columns.index(column)+1}][search][value]', None) if search_value: qs = qs.filter(**{f"{column}__icontains": search_value}) return qs + + def ordering(self, qs): + order = self.request.GET.get('order[0][dir]', None) + if order: + column_index = int(self.request.GET.get('order[0][column]', None)) - 1 + order_column = self.order_columns[column_index] + + if order == "asc": + qs = qs.order_by(order_column) + elif order == "desc": + qs = qs.order_by("-" + order_column) + + return qs class FaqCreateOrUpdateView(LoginRequiredMixin, generic.View): diff --git a/module_iam/models.py b/module_iam/models.py index e26173c..c442808 100644 --- a/module_iam/models.py +++ b/module_iam/models.py @@ -1,32 +1,30 @@ -from collections.abc import Iterable import datetime import random import string +from collections.abc import Iterable # from manage_wallets.models import Wallet, Transaction, TransactionStatus, TransactionType from django.conf import settings -from django.core.cache import cache from django.contrib.auth import get_user_model from django.contrib.auth.models import AbstractUser, BaseUserManager +from django.core.cache import cache +# from .utils import UserContext +from django.core.validators import (MaxValueValidator, MinValueValidator, + RegexValidator) from django.db import models from django.utils import timezone from django.utils.text import slugify +from module_project.utils import RandomGenerator + +from .iam_constant import (PRINCIPAL_SOURCE_APP, PRINCIPAL_SOURCE_APPLE, + PRINCIPAL_SOURCE_GOOGLE, PRINCIPAL_SOURCE_WEB, + PRINCIPAL_TYPE_ADMIN, PRINCIPAL_TYPE_SUBADMIN, + PRINCIPAL_TYPE_USER) + # from phonenumber_field.modelfields import PhoneNumberField -from module_project.utils import RandomGenerator -from .iam_constant import ( - PRINCIPAL_TYPE_USER, - PRINCIPAL_TYPE_ADMIN, - PRINCIPAL_TYPE_SUBADMIN, - PRINCIPAL_SOURCE_APP, - PRINCIPAL_SOURCE_APPLE, - PRINCIPAL_SOURCE_GOOGLE, - PRINCIPAL_SOURCE_WEB, -) -# from .utils import UserContext -from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator class BaseModel(models.Model): diff --git a/module_iam/urls.py b/module_iam/urls.py index c347256..41cd53e 100644 --- a/module_iam/urls.py +++ b/module_iam/urls.py @@ -1,4 +1,5 @@ from django.urls import path + from . import views app_name = "module_iam" @@ -6,11 +7,12 @@ app_name = "module_iam" urlpatterns = [ path('dashboard/', views.DashboardView.as_view(), name="dashboard"), - # path('principal/', views.PrincipalListView.as_view(), name="principal_list"), - # path('principal/add/', views.PrincipalCreateOrUpdateView.as_view(), name="principal_add"), + path('principal/add/', views.PrincipalCreateOrUpdateView.as_view(), name="principal_add"), path('principal/edit/', views.PrincipalCreateOrUpdateView.as_view(), name="principal_edit"), # path('principal/delete/', views.PrincipalDeleteView.as_view(), name="principal_delete"), + path('principal/archive/', views.PrincipalArchiveView.as_view(), name="principal_archive"), + path('principal/archive/list/', views.PrincipalArchiveListJsonView.as_view(), name="principal_archive_list"), path('principal/group/link/', views.PrincipalGroupLinkView.as_view(), name="principal_group_link"), path('principal/group/link/list/admin/', views.PrincipalGroupLinkAdminListJsonView.as_view(), name="principal_group_link_list"), @@ -19,16 +21,18 @@ urlpatterns = [ path('principal/group/link/action/', views.PrincipalGroupLinkActionView.as_view(), name="principal_group_link_action"), path('principal/group/', views.PrincipalGroupView.as_view(), name="principal_group"), - path('principal/group/list', views.PrincipalGroupListJsonView.as_view(), name="principal_group_list"), + path('principal/group/list/', views.PrincipalGroupListJsonView.as_view(), name="principal_group_list"), path('principal/group/add/', views.PrincipalGroupCreateOrUpdateView.as_view(), name="principal_group_add"), path('principal/group/edit//', views.PrincipalGroupCreateOrUpdateView.as_view(), name="principal_group_edit"), path('principal/group/action/', views.PrincipalGroupActionView.as_view(), name="principal_group_action"), + path('principal/group/archive/list/', views.PrincipalGroupArchiveView.as_view(), name="principal_group_archive"), path('principal/role/', views.AppRoleView.as_view(), name="role"), path('principal/role/list/', views.AppRoleListJsonView.as_view(), name="role_list"), path('principal/role/add/', views.AppRoleCreateOrUpdateView.as_view(), name="role_add"), path('principal/role/edit//', views.AppRoleCreateOrUpdateView.as_view(), name="role_edit"), path('principal/role/action/', views.AppRoleActionView.as_view(), name="role_action"), + path('principal/role/archive/list/', views.AppRoleArchiveView.as_view(), name="role_archive"), path("profile/", views.PrincipalProfileView.as_view(), name="profile_details"), path("profile/edit/", views.PrincipalProfileEditView.as_view(), name="profile_details_edit") diff --git a/module_iam/views.py b/module_iam/views.py index 0fc0dba..bf2cf6a 100644 --- a/module_iam/views.py +++ b/module_iam/views.py @@ -1,41 +1,29 @@ -from typing import Any - -from django.db import transaction -from django.db.models.base import Model as Model -from django.db.models.query import QuerySet -from django.views import generic import logging - from datetime import datetime +from typing import Any from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin +from django.db import transaction from django.db.models import Q +from django.db.models.base import Model as Model +from django.db.models.query import QuerySet from django.http import JsonResponse -from django.shortcuts import render, redirect, get_object_or_404 +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy -from module_iam import iam_constant -from module_project.mixins import DatatablesMixin +from django.views import generic from django_datatables_view.base_datatable_view import BaseDatatableView -from module_project.mixins import ActionMixin -from module_project.utils import JsonResponseUtil -from .forms import ( - CustomAuthenticationForm, - IAmPrincipalForm, - IAmPrincipalGroupRoleLinkForm, - IAmPrincipalRoleAppResourceActionLinkForm, - IAmPrincipalGroupLinkForm, - ProfileEditForm, -) -from .models import ( - IAmPrincipal, - IAmPrincipalType, - IAmAppResourceActionLink, - IAmPrincipalGroup, - IAmRole, -) +from module_iam import iam_constant from module_project import constants +from module_project.mixins import ActionMixin, DatatablesMixin +from module_project.utils import JsonResponseUtil + +from .forms import (CustomAuthenticationForm, IAmPrincipalForm, + IAmPrincipalGroupLinkForm, IAmPrincipalGroupRoleLinkForm, + IAmPrincipalRoleAppResourceActionLinkForm, ProfileEditForm) +from .models import (IAmAppResourceActionLink, IAmPrincipal, IAmPrincipalGroup, + IAmPrincipalType, IAmRole) logger = logging.getLogger(__name__) @@ -119,6 +107,37 @@ class PrincipalCreateOrUpdateView(LoginRequiredMixin, generic.View): return render(request, template_name=self.template_name, context=context) +class PrincipalArchiveListJsonView(BaseDatatableView): + model = IAmPrincipal + columns = ["id", "first_name", "email", "is_active"] + order_columns = ["id", "first_name", "email", "is_active"] + + def get_initial_queryset(self): + deleted_flag = self.request.GET.get("deleted_flag", False) + return self.model.objects.filter( + deleted=deleted_flag, + principal_type__name__in=( + iam_constant.PRINCIPAL_TYPE_ADMIN, + iam_constant.PRINCIPAL_TYPE_SUBADMIN, + ), + ) + + def render_column(self, row, column): + if column == "principal_type_name": + return row.principal_type.name if row.principal_type else None + return super().render_column(row, column) + + def filter_queryset(self, qs): + search_value = self.request.GET.get("search[value]", None) + if search_value: + qs = qs.filter( + Q(id__icontains=search_value) + | Q(first_name__icontains=search_value) + | Q(email__icontains=search_value) + ) + return qs + + class PrincipalGroupLinkView(LoginRequiredMixin, generic.TemplateView): page_name = iam_constant.RESOURCE_IAM_PRINCIPAL_GROUP model = IAmPrincipal @@ -129,6 +148,12 @@ class PrincipalGroupLinkView(LoginRequiredMixin, generic.TemplateView): context["page_name"] = self.page_name return context +class PrincipalArchiveView(PrincipalGroupLinkView): + page_name = iam_constant.RESOURCE_IAM_PRINCIPAL + resource = None + action = None + template_name = "module_iam/iam_principal_archive.html" + class PrincipalGroupLinkAdminListJsonView(BaseDatatableView): model = IAmPrincipal @@ -137,8 +162,10 @@ class PrincipalGroupLinkAdminListJsonView(BaseDatatableView): def get_initial_queryset(self): deleted_flag = self.request.GET.get("deleted_flag", False) - return self.model.objects.filter(deleted=deleted_flag, principal_type__name=iam_constant.PRINCIPAL_TYPE_ADMIN) - + return self.model.objects.filter( + deleted=deleted_flag, principal_type__name=iam_constant.PRINCIPAL_TYPE_ADMIN + ) + def render_column(self, row, column): if column == "principal_type_name": return row.principal_type.name if row.principal_type else None @@ -148,7 +175,9 @@ class PrincipalGroupLinkAdminListJsonView(BaseDatatableView): search_value = self.request.GET.get("search[value]", None) if search_value: qs = qs.filter( - Q(id__icontains=search_value) | Q(first_name__icontains=search_value) | Q(email__icontains=search_value) + Q(id__icontains=search_value) + | Q(first_name__icontains=search_value) + | Q(email__icontains=search_value) ) return qs @@ -160,7 +189,10 @@ class PrincipalGroupLinkSubAdminListJsonView(BaseDatatableView): def get_initial_queryset(self): deleted_flag = self.request.GET.get("deleted_flag", False) - return self.model.objects.filter(deleted=deleted_flag, principal_type__name=iam_constant.PRINCIPAL_TYPE_SUBADMIN) + return self.model.objects.filter( + deleted=deleted_flag, + principal_type__name=iam_constant.PRINCIPAL_TYPE_SUBADMIN, + ) def render_column(self, row, column): if column == "principal_type_name": @@ -173,7 +205,9 @@ class PrincipalGroupLinkSubAdminListJsonView(BaseDatatableView): search_value = self.request.GET.get("search[value]", None) if search_value: qs = qs.filter( - Q(id__icontains=search_value) | Q(first_name__icontains=search_value) | Q(email__icontains=search_value) + Q(id__icontains=search_value) + | Q(first_name__icontains=search_value) + | Q(email__icontains=search_value) ) return qs @@ -222,24 +256,26 @@ class PrincipalGroupLinkActionView(generic.View): def post(self, request, *args, **kwargs): if self.model is None: - raise NotImplementedError("Subclasses of BaseActionView must define a 'model' attribute.") + raise NotImplementedError( + "Subclasses of BaseActionView must define a 'model' attribute." + ) - action = request.POST.get('action') # 'archive', 'active', or 'unarchive' - ids = request.POST.getlist('ids[]') # List of IDs to perform action on - active = request.POST.get('active') + action = request.POST.get("action") # 'archive', 'active', or 'unarchive' + ids = request.POST.getlist("ids[]") # List of IDs to perform action on + active = request.POST.get("active") print(f"arhive action {action} and id is {ids} and active data is {active}") - if action == 'archive': + if action == "archive": # Update 'deleted' field to True for the selected users self.model.objects.filter(id__in=ids).update(deleted=True, is_active=False) - message = 'Record archived successfully.' - elif action == 'active': + message = "Record archived successfully." + elif action == "active": # Update 'active' field to True for the selected users self.model.objects.filter(id__in=ids).update(is_active=active.capitalize()) - message = 'Record updated successfully.' - elif action == 'unarchive': + message = "Record updated successfully." + elif action == "unarchive": # Update 'deleted' field to False for the selected users self.model.objects.filter(id__in=ids).update(deleted=False) - message = 'Record unarchived successfully.' + message = "Record unarchived successfully." else: return JsonResponseUtil.error(message="Invalid Action") @@ -266,6 +302,11 @@ class PrincipalGroupListJsonView(BaseDatatableView): deleted_flag = self.request.GET.get("deleted_flag", False) return self.model.objects.filter(deleted=deleted_flag) + def render_column(self, row, column): + if column == "roles": + return [{"name": role.name} for role in row.role.all()] + return super().render_column(row, column) + def filter_queryset(self, qs): search_value = self.request.GET.get("search[value]", None) if search_value: @@ -274,31 +315,6 @@ class PrincipalGroupListJsonView(BaseDatatableView): ) return qs - def generate_role_data(self, queryset): - roles_data = [] - for obj in queryset: - roles = [{"name": role.name} for role in obj.role.all()] - print(f"role data is this {roles}") - roles_data.append( - { - "id": obj.id, - "name": obj.name, - "active": str(obj.active), - "roles": roles, - } - ) - return roles_data - - def get_context_data(self, *args, **kwargs): - roles = self.filter_queryset(self.get_initial_queryset()) - role_data = self.generate_role_data(roles) - context = super().get_context_data(*args, **kwargs) - context["recordsTotal"] = len(role_data) - context["recordsFiltered"] = len(role_data) - context["data"] = role_data - context["result"] = "ok" - return context - class PrincipalGroupCreateOrUpdateView(LoginRequiredMixin, generic.View): page_name = iam_constant.RESOURCE_IAM_GROUP @@ -349,6 +365,9 @@ class PrincipalGroupActionView(ActionMixin): model = IAmPrincipalGroup +class PrincipalGroupArchiveView(PrincipalGroupView): + template_name = "module_iam/iam_group_archive_list.html" + class AppRoleView(LoginRequiredMixin, generic.TemplateView): page_name = iam_constant.RESOURCE_IAM_ROLE model = IAmRole @@ -378,6 +397,22 @@ class AppRoleListJsonView(BaseDatatableView): .filter(deleted=deleted_flag) ) + def render_column(self, row, column): + if column == "resources": + resources = {} + # Loop through all the app_resource_action links for the current ro + for link in row.app_resource_action.all(): + resource = link.app_resource.name + action = link.app_action.name + # If the resource is already in the dictionary, append the action to the list of actions + if resource in resources: + resources[resource].append(action) + # Otherwise, add the resource to the dictionary with a list containing the action + else: + resources[resource] = [action] + return resources + return super().render_column(row, column) + def filter_queryset(self, qs): search_value = self.request.GET.get("search[value]", None) if search_value: @@ -389,36 +424,6 @@ class AppRoleListJsonView(BaseDatatableView): ) return qs - def generate_resource_data(self, roles): - role_data = [] - for role in roles: - role_info = { - "id": role.id, - "name": role.name, - "active": str(role.active), - "resources": {}, - } - - for link in role.app_resource_action.all(): - resource = link.app_resource.name - action = link.app_action.name - if resource in role_info["resources"]: - role_info["resources"][resource].append(action) - else: - role_info["resources"][resource] = [action] - role_data.append(role_info) - return role_data - - def get_context_data(self, *args, **kwargs): - roles = self.filter_queryset(self.get_initial_queryset()) - role_data = self.generate_resource_data(roles) - context = super().get_context_data(*args, **kwargs) - context["recordsTotal"] = len(role_data) - context["recordsFiltered"] = len(role_data) - context["data"] = role_data - context["result"] = "ok" - return context - class AppRoleCreateOrUpdateView(LoginRequiredMixin, generic.View): page_name = iam_constant.RESOURCE_IAM_ROLE @@ -478,6 +483,10 @@ class AppRoleActionView(LoginRequiredMixin, ActionMixin): model = IAmRole +class AppRoleArchiveView(AppRoleView): + template_name = "module_iam/iam_role_archive.html" + + class PrincipalProfileView(LoginRequiredMixin, generic.TemplateView): page_name = iam_constant.RESOURCE_MANAGE_DASHBOARD model = IAmPrincipal diff --git a/module_notification/forms.py b/module_notification/forms.py index 6f54868..b5c1c76 100644 --- a/module_notification/forms.py +++ b/module_notification/forms.py @@ -1,6 +1,8 @@ from django import forms + from .models import PushNotification + class PushNotificationForm(forms.ModelForm): class Meta: model = PushNotification diff --git a/module_notification/models.py b/module_notification/models.py index 792ec45..3d37c81 100644 --- a/module_notification/models.py +++ b/module_notification/models.py @@ -1,6 +1,8 @@ from django.db import models + from module_iam.models import BaseModel + # Create your models here. class PushNotification(BaseModel): title = models.CharField(max_length=255) diff --git a/module_notification/urls.py b/module_notification/urls.py index 98f6add..a5fbd54 100644 --- a/module_notification/urls.py +++ b/module_notification/urls.py @@ -1,7 +1,8 @@ from django.urls import path -from . import views from django.views.generic import TemplateView +from . import views + app_name = "module_notification" urlpatterns = [ diff --git a/module_notification/views.py b/module_notification/views.py index 017bc31..3a46b00 100644 --- a/module_notification/views.py +++ b/module_notification/views.py @@ -1,25 +1,28 @@ +import itertools import logging - from datetime import datetime, timedelta + from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Q from django.http import HttpRequest from django.http.response import HttpResponse as HttpResponse -from django.shortcuts import render, redirect, get_object_or_404 +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views import generic -from module_iam.models import IAmPrincipal -from module_project.service import OneSignalService -from .models import PushNotification -from .forms import PushNotificationForm -from module_iam import iam_constant from django_datatables_view.base_datatable_view import BaseDatatableView -from module_project.mixins import ActionMixin +from module_iam import iam_constant +from module_iam.iam_constant import PRINCIPAL_TYPE_USER +from module_iam.models import IAmPrincipal from module_project import constants +from module_project.mixins import ActionMixin +from module_project.service import OneSignalService from module_project.utils import JsonResponseUtil +from .forms import PushNotificationForm +from .models import PushNotification + # Create your views here. class NotificationView(LoginRequiredMixin, generic.TemplateView): @@ -39,7 +42,7 @@ class NotificationListJsonView(BaseDatatableView): order_columns = ["id", "title", "message", "active", "timestamp"] def get_initial_queryset(self): - deleted_flag = self.request.GET.get('deleted_flag', None) + deleted_flag = self.request.GET.get("deleted_flag", None) return self.model.objects.filter(deleted=deleted_flag) @@ -142,10 +145,19 @@ class NotificationSendView(generic.View): fifteen_days_ago = datetime.now() - timedelta(days=3) # Filter the IAmPrincipal objects based on the last_login field being greater than or equal to fifteen_days_ago - player_ids = list(IAmPrincipal.objects.filter(last_login__gte=fifteen_days_ago).values_list('player_id', flat=True)) + player_ids = list( + IAmPrincipal.objects.filter( + principal_type__name=PRINCIPAL_TYPE_USER, + last_login__gte=fifteen_days_ago, + ).values_list("player_id", flat=True) + ) + # removing none from list + player_ids = list(itertools.filterfalse(lambda x: x is None, player_ids)) if not obj: - return JsonResponseUtil.error(message="No notification with such ID exists.") + return JsonResponseUtil.error( + message="No notification with such ID exists." + ) try: notification = OneSignalService() @@ -163,4 +175,4 @@ class NotificationSendView(generic.View): } return JsonResponseUtil.error(**error_response) - return JsonResponseUtil.success(message="success") \ No newline at end of file + return JsonResponseUtil.success(message="success") diff --git a/module_project/settings/base.py b/module_project/settings/base.py index 89a7f98..90d7393 100644 --- a/module_project/settings/base.py +++ b/module_project/settings/base.py @@ -225,6 +225,7 @@ ONESIGNAL_USER_AUTH_KEY = env.str("ONESIGNAL_USER_AUTH_KEY") # https://docs.djangoproject.com/en/dev/ref/settings/#logging # See https://docs.djangoproject.com/en/dev/topics/logging for # more details on how to customize your logging configuration. + LOGGING = { "version": 1, "disable_existing_loggers": False, diff --git a/module_project/settings/development.py b/module_project/settings/development.py index 31e097c..84eba51 100644 --- a/module_project/settings/development.py +++ b/module_project/settings/development.py @@ -39,8 +39,8 @@ BASE_DOMAIN = "" MEDIA_URL = "/media/" MEDIA_ROOT = os.path.join(BASE_DIR, "media") -STATIC_ROOT = os.path.join(BASE_DIR, "static") +# STATIC_ROOT = os.path.join(BASE_DIR, "static") STATIC_URL = "/static/" -# STATICFILES_DIRS = [BASE_DIR.joinpath("static")] +STATICFILES_DIRS = [BASE_DIR.joinpath("static")] diff --git a/module_project/urls.py b/module_project/urls.py index 09aa08c..36a85d0 100644 --- a/module_project/urls.py +++ b/module_project/urls.py @@ -14,10 +14,10 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.contrib import admin -from django.urls import path, include from django.conf import settings from django.conf.urls.static import static +from django.contrib import admin +from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), diff --git a/module_project/utils.py b/module_project/utils.py index 9997fe1..d59a275 100644 --- a/module_project/utils.py +++ b/module_project/utils.py @@ -1,13 +1,16 @@ -from rest_framework.response import Response -from rest_framework.exceptions import NotFound -from django.http import JsonResponse -from . import constants -from rest_framework import status -import string -import random import logging import os +import random import stat +import string + +from django.http import JsonResponse +from rest_framework import status +from rest_framework.exceptions import NotFound +from rest_framework.response import Response + +from . import constants + class GroupWriteRotatingFileHandler(logging.handlers.RotatingFileHandler): diff --git a/module_support/api/serializers.py b/module_support/api/serializers.py index ab03113..8d27133 100644 --- a/module_support/api/serializers.py +++ b/module_support/api/serializers.py @@ -1,6 +1,8 @@ from rest_framework import serializers + from module_support.models import ContactUs, Feedback + class ContactUsSerializer(serializers.ModelSerializer): class Meta: model = ContactUs diff --git a/module_support/api/urls.py b/module_support/api/urls.py index 9db15aa..47f3302 100644 --- a/module_support/api/urls.py +++ b/module_support/api/urls.py @@ -1,4 +1,5 @@ from django.urls import path + from . import views urlpatterns = [ diff --git a/module_support/api/views.py b/module_support/api/views.py index 3ce68df..2897b8e 100644 --- a/module_support/api/views.py +++ b/module_support/api/views.py @@ -1,10 +1,12 @@ -from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated +from rest_framework.views import APIView from rest_framework_simplejwt.authentication import JWTAuthentication + from module_project import constants from module_project.utils import ApiResponse -from .serializers import ContactUsSerializer, FeedbackSerializer + from ..models import ContactUs, Feedback +from .serializers import ContactUsSerializer, FeedbackSerializer class ContactusAPIView(APIView): diff --git a/module_support/models.py b/module_support/models.py index e92f623..6bf0d30 100644 --- a/module_support/models.py +++ b/module_support/models.py @@ -1,4 +1,5 @@ from django.db import models + from module_iam.models import BaseModel, IAmPrincipal # Create your models here. diff --git a/module_support/urls.py b/module_support/urls.py index c7298d3..dfc77fd 100644 --- a/module_support/urls.py +++ b/module_support/urls.py @@ -1,4 +1,5 @@ from django.urls import path + from . import views app_name = "module_support" diff --git a/module_support/views.py b/module_support/views.py index 00658c1..5430301 100644 --- a/module_support/views.py +++ b/module_support/views.py @@ -1,20 +1,21 @@ from django.conf import settings -from django.shortcuts import render from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Q -from django.shortcuts import render, redirect, get_object_or_404 +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse_lazy from django.views import generic -from module_iam.models import IAmPrincipal -from module_iam import iam_constant -from module_project.service import EmailService -from .models import ContactUs, Feedback -from module_project.mixins import DatatablesMixin from django_datatables_view.base_datatable_view import BaseDatatableView -from module_project.mixins import ActionMixin + +from module_iam import iam_constant +from module_iam.models import IAmPrincipal from module_project import constants +from module_project.mixins import ActionMixin, DatatablesMixin +from module_project.service import EmailService from module_project.utils import JsonResponseUtil + +from .models import ContactUs, Feedback + # Create your views here. @@ -54,11 +55,24 @@ class ContactUsListJson(BaseDatatableView): ) for column in self.columns: - search_value = self.request.GET.get(f'columns[{self.columns.index(column)}][search][value]', None) + search_value = self.request.GET.get(f'columns[{self.columns.index(column)+1}][search][value]', None) if search_value: qs = qs.filter(**{f"{column}__icontains": search_value}) return qs + + def ordering(self, qs): + order = self.request.GET.get('order[0][dir]', None) + if order: + column_index = int(self.request.GET.get('order[0][column]', None)) - 1 + order_column = self.order_columns[column_index] + + if order == "asc": + qs = qs.order_by(order_column) + elif order == "desc": + qs = qs.order_by("-" + order_column) + + return qs class ContactUsActionView(ActionMixin): diff --git a/templates/base_structure/elements/sidebar.html b/templates/base_structure/elements/sidebar.html index cf1c8b3..974637b 100644 --- a/templates/base_structure/elements/sidebar.html +++ b/templates/base_structure/elements/sidebar.html @@ -46,11 +46,8 @@