refactor: validation of all forms
This commit is contained in:
@@ -25,6 +25,7 @@ urlpatterns = [
|
||||
path("meal-symptoms/<int:pk>/", views.MealSymptomAPIView.as_view()),
|
||||
|
||||
path("meal/", views.MealAPIView.as_view()),
|
||||
path("meal/duplicate/", views.MealDuplicateAPIView.as_view()),
|
||||
path("meal/date/", views.MealDateAPIView.as_view()),
|
||||
path("meal/<int:pk>/", views.MealAPIView.as_view()),
|
||||
|
||||
|
||||
@@ -621,6 +621,45 @@ class MealAPIView(APIView):
|
||||
message=constants.RECORD_DELETED, status=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
|
||||
|
||||
class MealDuplicateAPIView(APIView):
|
||||
authentication_classes = [JWTAuthentication]
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = MealRecordSerializer
|
||||
model = MealRecord
|
||||
|
||||
def post(self, request):
|
||||
meal_id = request.POST.get("id")
|
||||
meal_time = request.POST.get("time")
|
||||
try:
|
||||
original_meal = self.model.objects.get(pk=meal_id)
|
||||
except Exception as e:
|
||||
return ApiResponse.error(message="Meal not found", errors=str(e))
|
||||
|
||||
instance = self.model(
|
||||
principal=original_meal.principal,
|
||||
date=original_meal.date,
|
||||
time=meal_time,
|
||||
meal_type=original_meal.meal_type
|
||||
)
|
||||
|
||||
instance.save()
|
||||
|
||||
for food_obj in original_meal.food_records.all():
|
||||
instance.food_records.add(food_obj)
|
||||
|
||||
for beverage_obj in original_meal.beverage_records.all():
|
||||
instance.beverage_records.add(beverage_obj)
|
||||
|
||||
for ingredient_obj in original_meal.food_ingredient_records.all():
|
||||
instance.food_ingredient_records.add(ingredient_obj)
|
||||
|
||||
instance.save()
|
||||
|
||||
serializer_obj = self.serializer_class(instance).data
|
||||
|
||||
return ApiResponse.success(message=constants.SUCCESS, data=serializer_obj)
|
||||
|
||||
class FoodDataAPIView(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
|
||||
@@ -98,6 +98,11 @@ class BaseListJson(BaseDatatableView):
|
||||
model = Intolerance
|
||||
columns = ["id", "name", "duration", "active", "deleted"]
|
||||
order_columns = ["id", "name", "duration", "active", "deleted"]
|
||||
FILTER_ICONTAINS = "icontains"
|
||||
|
||||
def get_filter_method(self):
|
||||
"""Returns preferred filter method"""
|
||||
return self.FILTER_ICONTAINS
|
||||
|
||||
def get_initial_queryset(self):
|
||||
principal_id = self.kwargs.get("principal_id")
|
||||
@@ -105,12 +110,18 @@ class BaseListJson(BaseDatatableView):
|
||||
|
||||
return self.model.objects.filter(principal=principal_id, deleted=deleted_flag)
|
||||
|
||||
def filter_queryset(self, qs):
|
||||
search_value = self.request.GET.get("search[value]", None)
|
||||
if search_value:
|
||||
qs = qs.filter(
|
||||
Q(name__icontains=search_value) | Q(duration__icontains=search_value)
|
||||
)
|
||||
def ordering(self, qs):
|
||||
print(f"request is {self.request.GET}")
|
||||
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]
|
||||
print(f"order column is {order_column}")
|
||||
if order == "asc":
|
||||
qs = qs.order_by(order_column)
|
||||
elif order == "desc":
|
||||
qs = qs.order_by("-" + order_column)
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
@@ -317,6 +328,11 @@ class MealListJsonView(BaseDatatableView):
|
||||
model = MealRecord
|
||||
columns = ["id", "date", "time", "meal_type"]
|
||||
order_columns = ["id", "date", "time", "meal_type"]
|
||||
FILTER_ICONTAINS = "icontains"
|
||||
|
||||
def get_filter_method(self):
|
||||
"""Returns preferred filter method"""
|
||||
return self.FILTER_ICONTAINS
|
||||
|
||||
def get_initial_queryset(self):
|
||||
principal_id = self.kwargs.get("principal_id")
|
||||
|
||||
@@ -249,6 +249,7 @@ class UserRecordView(permission.ResourcePermissionRequiredMixin, LoginRequiredMi
|
||||
recent_meal_symptom_records = MealSymptomRecord.objects.filter(
|
||||
principal=id
|
||||
).order_by('-id')[:5]
|
||||
return recent_meal_symptom_records
|
||||
|
||||
def get(self, request, id):
|
||||
# Retrieve the IAmPrincipal instance
|
||||
|
||||
@@ -100,6 +100,7 @@ class IAmPrincipalForm(forms.ModelForm):
|
||||
if principal_type == models.IAmPrincipalType.objects.get(name=PRINCIPAL_TYPE_ADMIN):
|
||||
instance.is_superuser = True
|
||||
elif principal_type == models.IAmPrincipalType.objects.get(name=PRINCIPAL_TYPE_SUBADMIN):
|
||||
instance.is_superuser = False
|
||||
instance.is_staff = True
|
||||
if commit:
|
||||
instance.save()
|
||||
@@ -221,6 +222,9 @@ class ProfileEditForm(forms.ModelForm):
|
||||
"gender",
|
||||
"phone_no"
|
||||
]
|
||||
labels = {
|
||||
'phone_no': 'Phone Number', # Map phone_no field to phone_number_label variable
|
||||
}
|
||||
|
||||
|
||||
class IAmPrincipalResourceLinkForm(IAmPrincipalForm):
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# Generated by Django 5.0.2 on 2024-04-05 07:06
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('module_iam', '0008_appversion_device_type_alter_appversion_version'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='appversion',
|
||||
name='device_type',
|
||||
field=models.CharField(choices=[('apple', 'apple'), ('android', 'android')], max_length=10, verbose_name='Device Type (apple / android)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='appversion',
|
||||
name='force_upgrade',
|
||||
field=models.BooleanField(default=False, help_text='Indicates whether a force upgrade is needed for this app version.', verbose_name='Force Upgrade'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='appversion',
|
||||
name='recommend_upgrade',
|
||||
field=models.BooleanField(default=False, help_text='Indicates whether a recommend upgrade is needed for this app version.', verbose_name='Recommend Upgrade'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='appversion',
|
||||
name='version',
|
||||
field=models.CharField(max_length=5, validators=[django.core.validators.RegexValidator('^\\d+\\.\\d+\\.\\d+$')], verbose_name='Version'),
|
||||
),
|
||||
]
|
||||
@@ -452,10 +452,10 @@ class AppVersion(models.Model):
|
||||
('apple', 'apple'),
|
||||
('android', 'android'),
|
||||
]
|
||||
device_type = models.CharField(max_length=10, choices=DEVICE_CHOICES)
|
||||
version = models.CharField(max_length=10, validators=[RegexValidator(r'^\d+\.\d+$')])
|
||||
force_upgrade = models.BooleanField(default=False, help_text='Indicates whether a force upgrade is needed for this app version.')
|
||||
recommend_upgrade = models.BooleanField(default=False, help_text='Indicates whether a recommend upgrade is needed for this app version.')
|
||||
device_type = models.CharField(max_length=10, choices=DEVICE_CHOICES, verbose_name='Device Type (apple / android)')
|
||||
version = models.CharField(max_length=5, validators=[RegexValidator(r'^\d+\.\d+\.\d+$')], verbose_name='Version')
|
||||
force_upgrade = models.BooleanField(default=False, verbose_name='Force Upgrade', help_text='Indicates whether a force upgrade is needed for this app version.')
|
||||
recommend_upgrade = models.BooleanField(default=False, verbose_name='Recommend Upgrade', help_text='Indicates whether a recommend upgrade is needed for this app version.')
|
||||
|
||||
class Meta:
|
||||
db_table = "app_version"
|
||||
|
||||
@@ -51,8 +51,8 @@
|
||||
<a href="{% url 'module_iam:principal_group' %}"> IAM Group </a>
|
||||
</li>
|
||||
<li class="{% if page_name == iam_constants_context.RESOURCE_IAM_ROLE %}active{% endif %}">
|
||||
<a href="{% url 'module_iam:role' %}"> IAM Role </a> -->
|
||||
</li>
|
||||
<a href="{% url 'module_iam:role' %}"> IAM Role </a>
|
||||
</li> -->
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
<!-- BEGIN GLOBAL MANDATORY SCRIPTS -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||
<script src="{% static 'src/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"></script>
|
||||
<!-- END GLOBAL MANDATORY SCRIPTS -->
|
||||
|
||||
<!-- BEGIN PAGE LEVEL PLUGINS/CUSTOM SCRIPTS -->
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<script src="{% static 'src/plugins/src/mousetrap/mousetrap.min.js' %}"></script>
|
||||
<script src="{% static 'src/plugins/src/waves/waves.min.js' %}"></script>
|
||||
<script src="{% static 'layouts/collapsible-menu/app.js' %}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"></script>
|
||||
|
||||
<script src="{% static 'src/assets/js/custom.js' %}"></script>
|
||||
<!-- END GLOBAL MANDATORY SCRIPTS -->
|
||||
|
||||
@@ -12,16 +12,12 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<h3>Bowel Details</h3>
|
||||
</div>
|
||||
<div class="col text-end">
|
||||
{% comment %} <button class="btn btn-dark mb-2 me-4" onclick="history.back()">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
Back
|
||||
</button> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-success mb-2 me-4" href="{% url 'module_cms:faq_category_add' %}">Add
|
||||
Category</a> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-primary mb-2 me-4" href="">Add User</a> {% endcomment %}
|
||||
<a onclick="history.back()" style="height: fit-content;width: fit-content;display: inline-block;">
|
||||
<h3 class="card-title m-2 d-flex align-items-center gap-2" style="width: fit-content;">
|
||||
<span class="fw-bold material-symbols-outlined">
|
||||
arrow_back
|
||||
</span><span>Bowel Details</span></h3>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -38,8 +38,10 @@
|
||||
|
||||
<thead>
|
||||
<tr role="row">
|
||||
<th class="sorting_asc text-center dt-no-sorting" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">Sr no.</th>
|
||||
<th class="sorting_asc text-center" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">#</th>
|
||||
aria-sort="ascending" style="width: 50.2656px;">Record Id</th>
|
||||
<th class="sorting text-center" tabindex="1" aria-controls="style-3"
|
||||
colspan="1" style="width: 44.2344px;">User Symptoms</th>
|
||||
<th class="sorting text-center" tabindex="2" aria-controls="style-3"
|
||||
@@ -95,13 +97,23 @@ function initializeDataTable(dataTableInstance, mainUrl) {
|
||||
type: "GET",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: null,
|
||||
className: "text-center",
|
||||
render: function(data, type, row, meta) {
|
||||
// Calculate sequence number based on page, page length, and index
|
||||
var sequenceNumber = meta.row + meta.settings._iDisplayStart + 1;
|
||||
return sequenceNumber;
|
||||
}
|
||||
},
|
||||
{ data: "id", className: "text-center" },
|
||||
{ data: "name", className: "text-center" },
|
||||
{ data: "duration", className: "text-center" }
|
||||
],
|
||||
debug: true,
|
||||
columnDefs: [
|
||||
{ targets: [1, 2, 0], searchable: true, orderable: true }
|
||||
{ targets: [1, 2, 3], searchable: true, orderable: true },
|
||||
{ targets: [0], searchable: false, orderable: false }
|
||||
],
|
||||
dom: "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'Bf>>>" +
|
||||
"<'table-responsive'tr>" +
|
||||
|
||||
@@ -38,8 +38,10 @@
|
||||
|
||||
<thead>
|
||||
<tr role="row">
|
||||
<th class="sorting_asc text-center dt-no-sorting" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">Sr no</th>
|
||||
<th class="sorting_asc text-center" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">#</th>
|
||||
aria-sort="ascending" style="width: 50.2656px;">Record Id</th>
|
||||
<th class="sorting text-center" tabindex="1" aria-controls="style-3"
|
||||
colspan="1" style="width: 44.2344px;">User Intolerances</th>
|
||||
<th class="sorting text-center" tabindex="2" aria-controls="style-3"
|
||||
@@ -97,13 +99,23 @@ function initializeDataTable(tableName, mainUrl) {
|
||||
type: "GET",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: null,
|
||||
className: "text-center",
|
||||
render: function(data, type, row, meta) {
|
||||
// Calculate sequence number based on page, page length, and index
|
||||
var sequenceNumber = meta.row + meta.settings._iDisplayStart + 1;
|
||||
return sequenceNumber;
|
||||
}
|
||||
},
|
||||
{ data: "id", className: "text-center" },
|
||||
{ data: "name", className: "text-center" },
|
||||
{ data: "duration", className: "text-center" },
|
||||
],
|
||||
debug: true,
|
||||
columnDefs: [
|
||||
{ targets: [0, 1, 2], searchable: true, orderable: true }
|
||||
{ targets: [1, 2, 3], searchable: true, orderable: true },
|
||||
{ targets: [0], searchable: false, orderable: false }
|
||||
],
|
||||
dom: "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'Bf>>>" +
|
||||
"<'table-responsive'tr>" +
|
||||
|
||||
@@ -12,16 +12,12 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<h3>Meal Details</h3>
|
||||
</div>
|
||||
<div class="col text-end">
|
||||
{% comment %} <button class="btn btn-dark mb-2 me-4" onclick="history.back()">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
Back
|
||||
</button> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-success mb-2 me-4" href="{% url 'module_cms:faq_category_add' %}">Add
|
||||
Category</a> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-primary mb-2 me-4" href="">Add User</a> {% endcomment %}
|
||||
<a onclick="history.back()" style="height: fit-content;width: fit-content;display: inline-block;">
|
||||
<h3 class="card-title m-2 d-flex align-items-center gap-2" style="width: fit-content;">
|
||||
<span class="fw-bold material-symbols-outlined">
|
||||
arrow_back
|
||||
</span><span>Meal Details</span></h3>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,16 +12,12 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<h3>Meal Symptoms Details</h3>
|
||||
</div>
|
||||
<div class="col text-end">
|
||||
{% comment %} <button class="btn btn-dark mb-2 me-4" onclick="history.back()">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
Back
|
||||
</button> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-success mb-2 me-4" href="{% url 'module_cms:faq_category_add' %}">Add
|
||||
Category</a> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-primary mb-2 me-4" href="">Add User</a> {% endcomment %}
|
||||
<a onclick="history.back()" style="height: fit-content;width: fit-content;display: inline-block;">
|
||||
<h3 class="card-title m-2 d-flex align-items-center gap-2" style="width: fit-content;">
|
||||
<span class="fw-bold material-symbols-outlined">
|
||||
arrow_back
|
||||
</span><span>Meal Symptoms Details</span></h3>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,16 +12,12 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="row mb-2">
|
||||
<div class="col">
|
||||
<h3>Meal Details</h3>
|
||||
</div>
|
||||
<div class="col text-end">
|
||||
{% comment %} <button class="btn btn-dark mb-2 me-4" onclick="history.back()">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
Back
|
||||
</button> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-success mb-2 me-4" href="{% url 'module_cms:faq_category_add' %}">Add
|
||||
Category</a> {% endcomment %}
|
||||
{% comment %} <a class="btn btn-primary mb-2 me-4" href="">Add User</a> {% endcomment %}
|
||||
<a onclick="history.back()" style="height: fit-content;width: fit-content;display: inline-block;">
|
||||
<h3 class="card-title m-2 d-flex align-items-center gap-2" style="width: fit-content;">
|
||||
<span class="fw-bold material-symbols-outlined">
|
||||
arrow_back
|
||||
</span><span>Medication Details</span></h3>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
<thead>
|
||||
<tr role="row">
|
||||
|
||||
<th class="sorting_asc text-center dt-no-sorting" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">Sr no.</th>
|
||||
<th class="sorting_asc text-center" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">#</th>
|
||||
aria-sort="ascending" style="width: 50.2656px;">Record Id</th>
|
||||
<th class="sorting text-center" tabindex="1" aria-controls="style-3"
|
||||
colspan="1" style="width: 44.2344px;">User Past Treatment</th>
|
||||
<th class="sorting text-center" tabindex="2" aria-controls="style-3"
|
||||
@@ -97,13 +99,23 @@ function initializeDataTable(dataTableInstance, mainUrl) {
|
||||
type: "GET",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: null,
|
||||
className: "text-center",
|
||||
render: function(data, type, row, meta) {
|
||||
// Calculate sequence number based on page, page length, and index
|
||||
var sequenceNumber = meta.row + meta.settings._iDisplayStart + 1;
|
||||
return sequenceNumber;
|
||||
}
|
||||
},
|
||||
{ data: "id", className: "text-center" },
|
||||
{ data: "name", className: "text-center" },
|
||||
{ data: "duration", className: "text-center" },
|
||||
],
|
||||
debug: true,
|
||||
columnDefs: [
|
||||
{ targets: [1, 2, 0], searchable: true, orderable: true }
|
||||
{ targets: [1, 2, 3], searchable: true, orderable: true },
|
||||
{ targets: [0], searchable: false, orderable: false }
|
||||
],
|
||||
dom: "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'Bf>>>" +
|
||||
"<'table-responsive'tr>" +
|
||||
|
||||
@@ -38,8 +38,10 @@
|
||||
|
||||
<thead>
|
||||
<tr role="row">
|
||||
<th class="sorting_asc text-center dt-no-sorting" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">Sr no</th>
|
||||
<th class="sorting_asc text-center" tabindex="0" aria-controls="style-3"
|
||||
aria-sort="ascending" style="width: 50.2656px;">#</th>
|
||||
aria-sort="ascending" style="width: 50.2656px;">Record Id</th>
|
||||
<th class="sorting text-center" tabindex="1" aria-controls="style-3"
|
||||
colspan="1" style="width: 44.2344px;">User Symptoms</th>
|
||||
<th class="sorting text-center" tabindex="2" aria-controls="style-3"
|
||||
@@ -97,13 +99,23 @@ function initializeDataTable(dataTableInstance, mainUrl) {
|
||||
type: "GET",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: null,
|
||||
className: "text-center",
|
||||
render: function(data, type, row, meta) {
|
||||
// Calculate sequence number based on page, page length, and index
|
||||
var sequenceNumber = meta.row + meta.settings._iDisplayStart + 1;
|
||||
return sequenceNumber;
|
||||
}
|
||||
},
|
||||
{ data: "id", className: "text-center" },
|
||||
{ data: "name", className: "text-center" },
|
||||
{ data: "duration", className: "text-center" }
|
||||
],
|
||||
debug: true,
|
||||
columnDefs: [
|
||||
{ targets: [0, 1, 2], searchable: true, orderable: true }
|
||||
{ targets: [1, 2, 3], searchable: true, orderable: true },
|
||||
{ targets: [0], searchable: false, orderable: false }
|
||||
],
|
||||
dom: "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'Bf>>>" +
|
||||
"<'table-responsive'tr>" +
|
||||
|
||||
@@ -9,21 +9,21 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if validlink %}
|
||||
<form method="post">
|
||||
<form method="post" id="changePasswordForm">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<input type="hidden" class="form-control" id="id_username" name="username"
|
||||
value="{{ form.user.get_username }}" autocomplete="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.new_password1.errors }}
|
||||
<label for="id_new_password1">{% translate 'New password:' %}</label>
|
||||
<input type="password" class="form-control" id="id_new_password1" name="new_password1">
|
||||
{{ form.new_password1.errors }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.new_password2.errors }}
|
||||
<label for="id_new_password2">{% translate 'Confirm password:' %}</label>
|
||||
<input type="password" class="form-control" id="id_new_password2" name="new_password2">
|
||||
{{ form.new_password2.errors }}
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-4">{% translate 'Change my password' %}</button>
|
||||
</form>
|
||||
@@ -40,5 +40,49 @@
|
||||
|
||||
{% block javascript %}
|
||||
<!-- include required js cdn link through html here -->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#changePasswordForm').validate({
|
||||
rules: {
|
||||
new_password1: {
|
||||
required: true,
|
||||
// Add custom method for password complexity
|
||||
complexPassword: true
|
||||
},
|
||||
new_password2: {
|
||||
required: true,
|
||||
equalTo: '#id_new_password1'
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
new_password1: {
|
||||
required: "Please enter a new password."
|
||||
},
|
||||
new_password2: {
|
||||
required: "Please confirm your new password.",
|
||||
equalTo: "Passwords do not match."
|
||||
}
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function(error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
element.closest('.form-group').append(error);
|
||||
},
|
||||
highlight: function(element, errorClass, validClass) {
|
||||
$(element).addClass('is-invalid').removeClass('is-valid');
|
||||
},
|
||||
unhighlight: function(element, errorClass, validClass) {
|
||||
$(element).removeClass('is-invalid').addClass('is-valid');
|
||||
}
|
||||
});
|
||||
|
||||
// Add custom validation method for password complexity
|
||||
$.validator.addMethod("complexPassword", function(value, element) {
|
||||
return /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+}{":;'?/>.<,])(?=.*[^\w\d\s])/.test(value);
|
||||
}, "Password must include at least one uppercase letter, one lowercase letter, one number, and special characters.");
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<div class="statbox widget box box-shadow">
|
||||
<div class="widget-content widget-content-area">
|
||||
|
||||
<form method="post">
|
||||
<form method="post" id="userForm">
|
||||
{% csrf_token %}
|
||||
{% include 'base_structure/includes/dynamic_template_form.html' with form=form %}
|
||||
<div class="mt-4 mb-0">
|
||||
@@ -42,5 +42,81 @@
|
||||
|
||||
{% block javascript %}
|
||||
<!-- include required js cdn link through html here -->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
// Add custom validation method to check for special characters
|
||||
$.validator.addMethod("noSpecialChars", function(value, element) {
|
||||
return /^[a-zA-Z\s]*$/.test(value); // Allow only letters and whitespace
|
||||
}, "Please enter only letters and spaces.");
|
||||
|
||||
|
||||
// Add custom validation method to check for starting with a letter
|
||||
$.validator.addMethod("startsWithLetter", function(value, element) {
|
||||
return /^[a-zA-Z]/.test(value); // Check if the value starts with a letter
|
||||
}, "Please start with a letter.");
|
||||
|
||||
|
||||
// Add custom validation method for password complexity
|
||||
$.validator.addMethod("complexPassword", function(value, element) {
|
||||
return /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+}{":;'?/>.<,])(?=.*[^\w\d\s])/.test(value);
|
||||
}, "Password must include at least one uppercase letter, one lowercase letter, one number, and special characters.");
|
||||
|
||||
|
||||
// Initialize form validation
|
||||
$("#userForm").validate({
|
||||
rules: {
|
||||
first_name: {
|
||||
required: true,
|
||||
maxlength: 50, // Example: Set maximum length for first_name to 50 characters
|
||||
startsWithLetter: true,
|
||||
noSpecialChars: true,
|
||||
},
|
||||
email: {
|
||||
required: true,
|
||||
email: true // Check for valid email format
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
complexPassword: true
|
||||
},
|
||||
confirm_password: {
|
||||
required: true,
|
||||
equalTo: "#id_password" // Ensure confirm_password matches password field
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
first_name: {
|
||||
required: "Please enter your name.",
|
||||
maxlength: "Name must not exceed 50 characters.",
|
||||
startsWithLetter: "First name must start with a letter.",
|
||||
noSpecialChars: "Please enter only letters and spaces.",
|
||||
},
|
||||
email: {
|
||||
required: "Please enter your email address.",
|
||||
email: "Please enter a valid email address."
|
||||
},
|
||||
password: {
|
||||
required: "Please enter your password.",
|
||||
},
|
||||
confirm_password: {
|
||||
required: "Please confirm your password.",
|
||||
equalTo: "Passwords do not match."
|
||||
}
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function(error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
$(element).closest('.form-group').append(error);
|
||||
},
|
||||
highlight: function(element, errorClass, validClass) {
|
||||
$(element).addClass('is-invalid').removeClass('is-valid');
|
||||
},
|
||||
unhighlight: function(element, errorClass, validClass) {
|
||||
$(element).removeClass('is-invalid').addClass('is-valid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -24,7 +24,7 @@
|
||||
<div class="statbox widget box box-shadow">
|
||||
<div class="widget-content widget-content-area">
|
||||
|
||||
<form method="POST">
|
||||
<form method="POST" id="faqs_form">
|
||||
{% csrf_token %}
|
||||
{% include 'base_structure/includes/dynamic_template_form.html' with form=form %}
|
||||
<div class="mt-4 mb-0">
|
||||
@@ -47,6 +47,37 @@
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
// Initialize form validation
|
||||
$("#faqs_form").validate({
|
||||
rules: {
|
||||
question: {
|
||||
required: true
|
||||
},
|
||||
answer: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
question: {
|
||||
required: "Please enter a question."
|
||||
},
|
||||
answer: {
|
||||
required: "Please enter an answer."
|
||||
}
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function(error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
$(element).closest('.form-group').append(error);
|
||||
},
|
||||
highlight: function(element, errorClass, validClass) {
|
||||
$(element).addClass('is-invalid').removeClass('is-valid');
|
||||
},
|
||||
unhighlight: function(element, errorClass, validClass) {
|
||||
$(element).removeClass('is-invalid').addClass('is-valid');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -3,8 +3,8 @@
|
||||
{% block stylesheet %}
|
||||
<!-- include required css cdn link through html here -->
|
||||
|
||||
{% include "cdn_through_html/quill_cdn_css.html" %}
|
||||
{{form.media}}
|
||||
{% include "cdn_through_html/quill_cdn_css.html" %}
|
||||
{{form.media}}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -26,9 +26,10 @@
|
||||
<div class="statbox widget box box-shadow">
|
||||
<div class="widget-content widget-content-area">
|
||||
|
||||
<form method="POST">
|
||||
<form method="POST" id="privacy_policy_form">
|
||||
{% csrf_token %}
|
||||
{% include 'base_structure/includes/dynamic_template_form.html' with form=form %}
|
||||
<div id="privacy_policy_error" class="text-danger"></div>
|
||||
<div class="mt-4 mb-0">
|
||||
<div class="d-grid"><button class="btn btn-primary btn-block" type="submit">Submit</button></div>
|
||||
</div>
|
||||
@@ -48,11 +49,22 @@
|
||||
<!-- include required css cdn link through html here -->
|
||||
|
||||
{% include "cdn_through_html/quill_cdn_js.html" %}
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
// Initialize form submission event handler
|
||||
$("#privacy_policy_form").submit(function(event) {
|
||||
console.log("function called")
|
||||
// Check if the Quill editor has any content
|
||||
var quillContent = $("#quill-id_privacy_policy .ql-editor").html().trim();
|
||||
if (quillContent === '<p><br></p>') {
|
||||
// If Quill editor content is empty, prevent form submission and display an error message
|
||||
event.preventDefault();
|
||||
$("#privacy_policy_error").text("Please enter some text.").show();
|
||||
} else {
|
||||
// If Quill editor content is not empty, allow form submission
|
||||
$("#privacy_policy_error").hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -26,9 +26,10 @@
|
||||
<div class="statbox widget box box-shadow">
|
||||
<div class="widget-content widget-content-area">
|
||||
|
||||
<form method="POST">
|
||||
<form method="POST" id="terms_and_condition">
|
||||
{% csrf_token %}
|
||||
{% include 'base_structure/includes/dynamic_template_form.html' with form=form %}
|
||||
<div id="terms_condition_error" class="text-danger"></div>
|
||||
<div class="mt-4 mb-0">
|
||||
<div class="d-grid"><button class="btn btn-primary btn-block" type="submit">Submit</button></div>
|
||||
</div>
|
||||
@@ -48,11 +49,21 @@
|
||||
<!-- include required css cdn link through html here -->
|
||||
|
||||
{% include "cdn_through_html/quill_cdn_js.html" %}
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
// Initialize form submission event handler
|
||||
$("#terms_and_condition").submit(function(event) {
|
||||
// Check if the Quill editor has any content
|
||||
var quillContent = $("#quill-id_terms_condition .ql-editor").html().trim();
|
||||
if (quillContent === '<p><br></p>') {
|
||||
// If Quill editor content is empty, prevent form submission and display an error message
|
||||
event.preventDefault();
|
||||
$("#terms_condition_error").text("Please enter some text for the Terms and Conditions.").show();
|
||||
} else {
|
||||
// If Quill editor content is not empty, allow form submission
|
||||
$("#terms_condition_error").hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -75,7 +75,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</form> -->
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<form method="POST" enctype="multipart/form-data" id="profileEditForm">
|
||||
{% csrf_token %}
|
||||
{% include 'base_structure/includes/dynamic_template_form.html' with form=form %}
|
||||
<div class="mt-4 mb-0">
|
||||
@@ -127,7 +127,96 @@
|
||||
if (profilePhotoUrl) {
|
||||
// If the URL exists, add the profile photo to FilePond
|
||||
pond.addFile(profilePhotoUrl);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Add custom validation method to check for special characters
|
||||
$.validator.addMethod("noSpecialChars", function(value, element) {
|
||||
return /^[a-zA-Z\s]*$/.test(value); // Allow only letters and whitespace
|
||||
}, "Please enter only letters and spaces.");
|
||||
|
||||
// Add custom validation method to check for starting with a letter
|
||||
$.validator.addMethod("startsWithLetter", function(value, element) {
|
||||
return /^[a-zA-Z]/.test(value); // Check if the value starts with a letter
|
||||
}, "Please start with a letter.");
|
||||
|
||||
// Initialize form validation
|
||||
$("#profileEditForm").validate({
|
||||
rules: {
|
||||
first_name: {
|
||||
required: true,
|
||||
minlength: 2,
|
||||
maxlength:15,
|
||||
noSpecialChars: true,
|
||||
startsWithLetter: true
|
||||
},
|
||||
last_name: {
|
||||
required: true,
|
||||
minlength: 2,
|
||||
maxlength: 15,
|
||||
noSpecialChars: true,
|
||||
startsWithLetter: true
|
||||
},
|
||||
date_of_birth: {
|
||||
required: true,
|
||||
date: true,
|
||||
dateISO: true, // Check for ISO date format (YYYY-MM-DD)
|
||||
pattern: /^\d{4}-\d{2}-\d{2}$/ // Custom pattern for YYYY-MM-DD format
|
||||
},
|
||||
gender: {
|
||||
required: true
|
||||
},
|
||||
phone_no: {
|
||||
required: true,
|
||||
digits: true,
|
||||
minlength: 10,
|
||||
maxlength: 10
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
first_name: {
|
||||
required: "Please enter your first name.",
|
||||
minlength: "First name must be at least 2 characters.",
|
||||
maxlength: "First name must not exceed 15 characters.",
|
||||
noSpecialChars: "Please enter only letters and spaces.",
|
||||
startsWithLetter: "First name must start with a letter."
|
||||
},
|
||||
last_name: {
|
||||
required: "Please enter your last name.",
|
||||
minlength: "Last name must be at least 2 characters.",
|
||||
maxlength: "First name must not exceed 15 characters.",
|
||||
noSpecialChars: "Please enter only letters and spaces.",
|
||||
startsWithLetter: "Last name must start with a letter."
|
||||
},
|
||||
date_of_birth: {
|
||||
required: "Please enter your date of birth.",
|
||||
date: "Please enter a valid date in the format YYYY-MM-DD.",
|
||||
dateISO: "Please enter a valid date in the format YYYY-MM-DD.",
|
||||
pattern: "Please enter a valid date in the format YYYY-MM-DD."
|
||||
},
|
||||
gender: {
|
||||
required: "Please select your gender."
|
||||
},
|
||||
phone_no: {
|
||||
required: "Please enter your phone number.",
|
||||
digits: "Please enter only digits.",
|
||||
minlength: "Phone number must be 10 digits long.",
|
||||
maxlength: "Phone number must be 10 digits long."
|
||||
}
|
||||
},
|
||||
errorElement: 'div',
|
||||
errorPlacement: function(error, element) {
|
||||
error.addClass('invalid-feedback');
|
||||
$(element).closest('.form-group').append(error);
|
||||
},
|
||||
highlight: function(element, errorClass, validClass) {
|
||||
$(element).addClass('is-invalid').removeClass('is-valid');
|
||||
},
|
||||
unhighlight: function(element, errorClass, validClass) {
|
||||
$(element).removeClass('is-invalid').addClass('is-valid');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -115,7 +115,7 @@
|
||||
<button class="nav-link" id="pills-reply-tab" data-bs-toggle="pill" data-bs-target="#pills-reply" type="button" role="tab" aria-controls="pills-reply" aria-selected="false">Reply</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="pills-tabContent">
|
||||
<div class="tab-content" id="pills-tabContent" style="max-height: 200px; overflow-y: auto;">
|
||||
<div class="tab-pane fade show active" id="pills-message" role="tabpanel" aria-labelledby="pills-message-tab" tabindex="0">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
||||
Reference in New Issue
Block a user