[UPDT] ATTENDANCE: Updated get_diff_dict function for improved performance and readability by reducing redundant operations
This commit is contained in:
@@ -98,53 +98,63 @@ def get_diff_dict(first_dict, other_dict, model=None):
|
||||
Args:
|
||||
first_dict: The first dictionary to compare.
|
||||
other_dict: The second dictionary to compare.
|
||||
model: The model class
|
||||
model: The model class (optional, for verbose names and type-specific formatting)
|
||||
|
||||
Returns:
|
||||
A dictionary of differing keys with their old and new values.
|
||||
"""
|
||||
# model is passed as argument if any need of verbose name instead of field name
|
||||
difference = {}
|
||||
if model is None:
|
||||
for key in first_dict:
|
||||
if first_dict[key] != other_dict[key]:
|
||||
# get the verbose name of the field
|
||||
difference[key] = (first_dict[key], other_dict[key])
|
||||
return difference
|
||||
for key in first_dict:
|
||||
if first_dict[key] != other_dict[key]:
|
||||
# get the verbose name of the field
|
||||
field = model._meta.get_field(key)
|
||||
verb_key = field.verbose_name
|
||||
value = first_dict[key]
|
||||
other_value = other_dict[key]
|
||||
if isinstance(field, models.DateField):
|
||||
if value is not None and value != "None":
|
||||
value = datetime.strptime(value, "%Y-%m-%d").strftime("%d %b %Y")
|
||||
if other_value is not None and other_value != "None":
|
||||
other_value = datetime.strptime(other_value, "%Y-%m-%d").strftime(
|
||||
"%d %b %Y"
|
||||
)
|
||||
elif isinstance(field, models.TimeField):
|
||||
if value is not None and value != "None":
|
||||
if len(value.split(":")) == 2:
|
||||
value = value + ":00"
|
||||
value = datetime.strptime(value, "%H:%M:%S").strftime("%I:%M %p")
|
||||
if other_value is not None and value != "None":
|
||||
if len(other_value.split(":")) == 2:
|
||||
other_value = other_value + ":00"
|
||||
if other_value != "None":
|
||||
other_value = datetime.strptime(
|
||||
other_value, "%H:%M:%S"
|
||||
).strftime("%I:%M %p")
|
||||
else:
|
||||
other_value = "None"
|
||||
elif isinstance(field, models.ForeignKey):
|
||||
if value is not None and len(str(value)):
|
||||
value = field.related_model.objects.get(id=value)
|
||||
if other_value is not None and len(str(other_value)):
|
||||
other_value = field.related_model.objects.get(id=other_value)
|
||||
difference[verb_key] = (value, other_value)
|
||||
|
||||
for key, value in first_dict.items():
|
||||
other_value = other_dict.get(key)
|
||||
if value == other_value:
|
||||
continue # Skip if values are the same
|
||||
|
||||
if not model:
|
||||
difference[key] = (value, other_value)
|
||||
continue
|
||||
|
||||
# Fetch the model field metadata
|
||||
field = model._meta.get_field(key)
|
||||
verbose_key = field.verbose_name
|
||||
|
||||
# Handle specific field types
|
||||
if isinstance(field, models.DateField):
|
||||
value = (
|
||||
datetime.strptime(value, "%Y-%m-%d").strftime("%d %b %Y")
|
||||
if value and value != "None"
|
||||
else value
|
||||
)
|
||||
other_value = (
|
||||
datetime.strptime(other_value, "%Y-%m-%d").strftime("%d %b %Y")
|
||||
if other_value and other_value != "None"
|
||||
else other_value
|
||||
)
|
||||
elif isinstance(field, models.TimeField):
|
||||
|
||||
def format_time(val):
|
||||
if val and val != "None":
|
||||
val += ":00" if len(val.split(":")) == 2 else ""
|
||||
return datetime.strptime(val, "%H:%M:%S").strftime("%I:%M %p")
|
||||
return val
|
||||
|
||||
value = format_time(value)
|
||||
other_value = format_time(other_value)
|
||||
elif isinstance(field, models.ForeignKey):
|
||||
value = (
|
||||
field.related_model.objects.get(id=value)
|
||||
if value and str(value).isdigit()
|
||||
else value
|
||||
)
|
||||
other_value = (
|
||||
field.related_model.objects.get(id=other_value)
|
||||
if other_value and str(other_value).isdigit()
|
||||
else other_value
|
||||
)
|
||||
|
||||
# Add the difference
|
||||
difference[verbose_key] = (value, other_value)
|
||||
|
||||
return difference
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
position: sticky;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="oh-wrapper">
|
||||
<div class="oh-dashboard__left col-12 col-sm-12 col-md-12 col-lg-12 pb-5">
|
||||
@@ -14,89 +14,191 @@
|
||||
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--neutral">
|
||||
<div class="oh-card-dashboard__header">
|
||||
<span class="oh-card-dashboard__title"
|
||||
>{% trans "Today's Attendances" %}</span
|
||||
>
|
||||
<span class="oh-card-dashboard__title">{% trans "Today's Attendances" %}</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body">
|
||||
<div class="oh-card-dashboard__counts">
|
||||
<span class="oh-card-dashboard__count"
|
||||
>{{marked_attendances_ratio}}%</span
|
||||
>
|
||||
<span class="oh-card-dashboard__count">{{marked_attendances_ratio}}%</span>
|
||||
</div>
|
||||
{% comment %} <span class="oh-badge oh-card-dashboard__badge"
|
||||
>{{marked_attendances}}/{{expected_attendances}}</span
|
||||
> {% endcomment %}
|
||||
{% comment %}
|
||||
<span class="oh-badge oh-card-dashboard__badge">{{marked_attendances}}/{{expected_attendances}}</span>
|
||||
{% endcomment %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
|
||||
<div
|
||||
class="oh-card-dashboard oh-card-dashboard oh-card-dashboard--success"
|
||||
>
|
||||
<div class="oh-card-dashboard oh-card-dashboard oh-card-dashboard--success">
|
||||
<div class="oh-card-dashboard__header">
|
||||
<span class="oh-card-dashboard__title"
|
||||
>{% trans "On Time" %}</span
|
||||
>
|
||||
<span class="oh-card-dashboard__title">{% trans "On Time" %}</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body">
|
||||
<div class="oh-card-dashboard__counts">
|
||||
<span class="oh-card-dashboard__count"
|
||||
>{{on_time}}</span
|
||||
>
|
||||
<span class="oh-card-dashboard__count">{{on_time}}</span>
|
||||
</div>
|
||||
{% comment %} <span class="oh-badge oh-card-dashboard__badge"
|
||||
>{{on_time_ratio}}%</span
|
||||
> {% endcomment %}
|
||||
{% comment %}
|
||||
<span class="oh-badge oh-card-dashboard__badge">{{on_time_ratio}}%</span>
|
||||
{% endcomment %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if late_come_early_out_tracking %}
|
||||
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--danger">
|
||||
<div class="oh-card-dashboard__header">
|
||||
<span class="oh-card-dashboard__title"
|
||||
>{% trans "Late Come" %}</span
|
||||
>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body">
|
||||
<div class="oh-card-dashboard__counts">
|
||||
<span class="oh-card-dashboard__count"
|
||||
>{{late_come}}</span
|
||||
>
|
||||
{% if late_come_early_out_tracking %}
|
||||
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--danger">
|
||||
<div class="oh-card-dashboard__header">
|
||||
<span class="oh-card-dashboard__title">{% trans "Late Come" %}</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body">
|
||||
<div class="oh-card-dashboard__counts">
|
||||
<span class="oh-card-dashboard__count">{{late_come}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-dashboard row pt-3">
|
||||
<div class="oh-dashboard__movable-cards row mt-4">
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-4 "
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard__header oh-card-dashboard__header--divider" style="margin-bottom:2.25rem;"
|
||||
id="attendance_header"
|
||||
>
|
||||
<div class="oh-card-dashboard__title mb-2">
|
||||
{% trans "Attendance Analytic" %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<select
|
||||
id="type"
|
||||
class="oh-select"
|
||||
name="type"
|
||||
onchange="changeView(this)"
|
||||
style="
|
||||
<div class="oh-dashboard row pt-3">
|
||||
<div class="oh-dashboard__movable-cards row mt-4">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4 ">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
style="min-height: 423px;"
|
||||
>
|
||||
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
style="margin-bottom:2.25rem;" id="attendance_header">
|
||||
<div class="oh-card-dashboard__title mb-2">
|
||||
{% trans "Attendance Analytic" %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<select id="type" class="oh-select" name="type" onchange="changeView(this)" style="
|
||||
width: 150px;
|
||||
padding: 3px;
|
||||
color: #5e5c5c;
|
||||
"
|
||||
>
|
||||
">
|
||||
<option value="day">
|
||||
{% trans "Day" %}
|
||||
</option>
|
||||
<option value="weekly">
|
||||
{% trans "Weekly" %}
|
||||
</option>
|
||||
<option value="monthly">
|
||||
{% trans "Monthly" %}
|
||||
</option>
|
||||
<option value="date_range">
|
||||
{% trans "Date range" %}
|
||||
</option>
|
||||
</select>
|
||||
<span id="day_input">
|
||||
<input type="date" class="mb-2 float-end pointer oh-select"
|
||||
id="attendance_month" onchange="changeMonth()"
|
||||
style="width: 100px; color: #5e5c5c" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body">
|
||||
<canvas id="dailyAnalytic" style="cursor: pointer"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
style="min-height: 423px">
|
||||
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider">
|
||||
<span class="oh-card-dashboard__title">{% trans 'Offline Employees' %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body" hx-get="{% url 'not-in-yet' %}" hx-trigger="load"
|
||||
id="notInYetIdCardBody" style="height: 310px;">
|
||||
<div class="animated-background"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4 " id="pendingHours">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
style="min-height: 423px;">
|
||||
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
id="pendingHoursHeader">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="oh-card-dashboard__title mb-2">
|
||||
{% trans "Hours Chart" %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<input type="month" class="mb-2 float-end pointer oh-select"
|
||||
id="hourAccountMonth" onchange="dynamicMonth($(this))"
|
||||
style="width: 100px; color: #5e5c5c" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body" style="height:275px">
|
||||
<canvas id="pendingHoursCanvas" style="cursor: pointer"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="oh-dashboard row pt-3">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-3 ">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent">
|
||||
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider">
|
||||
<span class="oh-card-dashboard__title">{% trans "On Break" %}</span>
|
||||
</div>
|
||||
|
||||
<div class="oh-card-dashboard__body" style="height:400px">
|
||||
{% if on_break %}
|
||||
<ul class="oh-card-dashboard__user-list">
|
||||
{% for emp in on_break %}
|
||||
<li class="oh-card-dashboard__user-item">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
<div class="oh-profile__avatar mr-1">
|
||||
<img src="https://ui-avatars.com/api/?name={{emp.employee_id}}&background=random"
|
||||
class="oh-profile__image" alt="Amy Winehouse" />
|
||||
</div>
|
||||
<span class="oh-profile__name oh-text--dark">{{emp.employee_id}}</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div style="height: 380px; display:flex;align-items: center;justify-content: center;"
|
||||
class="">
|
||||
<div style="" class="">
|
||||
<img style=" display: block;width: 70px;margin: 20px auto ;" src="{% static '/images/ui/coffee-break.png' %}" class="" alt="" />
|
||||
<h3 style="font-size:16px" class="oh-404__subtitle">{% trans "No employees are currently taking a break." %}</h3>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-9">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent">
|
||||
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider">
|
||||
<span class="oh-card-dashboard__title">{% trans "Overtime To Validate" %}</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body" style="height:400px">
|
||||
{% include "attendance/dashboard/overtime_table.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-dashboard row pt-3">
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-8" id="validateTableCard">
|
||||
{% include "attendance/dashboard/to_validate_table.html" %}
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4 " id="departmentChartCard">
|
||||
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent">
|
||||
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
id="departmentChartHeader">
|
||||
<div class="oh-card-dashboard__title mb-2">
|
||||
{% trans "Department Overtime Chart" %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<select id="department_date_type" class="oh-select" name="type" style="
|
||||
width: 150px;
|
||||
padding: 3px;
|
||||
color: #5e5c5c;
|
||||
">
|
||||
<option value="day">
|
||||
{% trans "Day" %}
|
||||
</option>
|
||||
@@ -110,221 +212,36 @@
|
||||
{% trans "Date range" %}
|
||||
</option>
|
||||
</select>
|
||||
<span id="day_input">
|
||||
<input
|
||||
type="date"
|
||||
class="mb-2 float-end pointer oh-select"
|
||||
id="attendance_month"
|
||||
onchange="changeMonth()"
|
||||
style="width: 100px; color: #5e5c5c"
|
||||
/>
|
||||
<span id="department_day_input">
|
||||
<input type="date" class="mb-2 float-end pointer oh-select" id="department_month"
|
||||
style="width: 100px; color: #5e5c5c" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body">
|
||||
<canvas
|
||||
id="dailyAnalytic"
|
||||
style="cursor: pointer"
|
||||
></canvas>
|
||||
<div class="oh-card-dashboard__body" style="height:400px">
|
||||
<canvas id="departmentOverChart" style="cursor: pointer"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4"
|
||||
id="notInYetId"
|
||||
hx-get="{% url "not-in-yet" %}" hx-trigger="load" >
|
||||
{% include "dashboard/not_in_yet.html" %}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-4 "
|
||||
id="pendingHours"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent" style="min-height: 423px;"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
id="pendingHoursHeader"
|
||||
>
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="oh-card-dashboard__title mb-2">
|
||||
{% trans "Hours Chart" %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<input
|
||||
type="month"
|
||||
class="mb-2 float-end pointer oh-select"
|
||||
id="hourAccountMonth"
|
||||
onchange="dynamicMonth($(this))"
|
||||
style="width: 100px; color: #5e5c5c"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body" style="height:275px">
|
||||
<canvas
|
||||
id="pendingHoursCanvas"
|
||||
style="cursor: pointer"
|
||||
></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="oh-dashboard row pt-3">
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-3 "
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
>
|
||||
<span class="oh-card-dashboard__title"
|
||||
>{% trans "On Break" %}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="oh-card-dashboard__body" style="height:400px">
|
||||
{% if on_break %}
|
||||
<ul class="oh-card-dashboard__user-list">
|
||||
{% for emp in on_break %}
|
||||
<li class="oh-card-dashboard__user-item">
|
||||
<div class="oh-profile oh-profile--md">
|
||||
<div class="oh-profile__avatar mr-1">
|
||||
<img
|
||||
src="https://ui-avatars.com/api/?name={{emp.employee_id}}&background=random"
|
||||
class="oh-profile__image"
|
||||
alt="Amy Winehouse"
|
||||
/>
|
||||
</div>
|
||||
<span class="oh-profile__name oh-text--dark"
|
||||
>{{emp.employee_id}}</span
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div style="height: 380px; display:flex;align-items: center;justify-content: center;" class="">
|
||||
<div style="" class="">
|
||||
<img style=" display: block;width: 70px;margin: 20px auto ;" src="{% static "/images/ui/coffee-break.png" %}" class="" alt=""/>
|
||||
<h3 style="font-size:16px" class="oh-404__subtitle">{% trans "No employees on break...." %}</h3>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-9"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
>
|
||||
<span class="oh-card-dashboard__title"
|
||||
>{% trans "Overtime To Validate" %}</span
|
||||
>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body" style="height:400px">
|
||||
{% include "attendance/dashboard/overtime_table.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-dashboard row pt-3">
|
||||
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-8" id="validateTableCard"
|
||||
>
|
||||
{% include "attendance/dashboard/to_validate_table.html" %}
|
||||
</div>
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-4 "
|
||||
id="departmentChartCard"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
|
||||
>
|
||||
<div
|
||||
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
|
||||
id="departmentChartHeader"
|
||||
>
|
||||
<div class="oh-card-dashboard__title mb-2">
|
||||
{% trans "Department Overtime Chart" %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<select
|
||||
id="department_date_type"
|
||||
class="oh-select"
|
||||
name="type"
|
||||
style="
|
||||
width: 150px;
|
||||
padding: 3px;
|
||||
color: #5e5c5c;
|
||||
"
|
||||
>
|
||||
<option value="day">
|
||||
{% trans "Day" %}
|
||||
</option>
|
||||
<option value="weekly">
|
||||
{% trans "Weekly" %}
|
||||
</option>
|
||||
<option value="monthly">
|
||||
{% trans "Monthly" %}
|
||||
</option>
|
||||
<option value="date_range">
|
||||
{% trans "Date range" %}
|
||||
</option>
|
||||
</select>
|
||||
<span id="department_day_input">
|
||||
<input
|
||||
type="date"
|
||||
class="mb-2 float-end pointer oh-select"
|
||||
id="department_month"
|
||||
style="width: 100px; color: #5e5c5c"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="oh-card-dashboard__body" style="height:400px">
|
||||
<canvas
|
||||
id="departmentOverChart"
|
||||
style="cursor: pointer"
|
||||
></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="oh-modal"
|
||||
id="sendMailModal"
|
||||
role="dialog"
|
||||
aria-labelledby="sendMailModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<h5 class="oh-modal__dialog-title" id="sendMailModalLabel">
|
||||
{% trans "Send Mail" %}
|
||||
</h5>
|
||||
<button class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oh-modal__dialog-body" id="mail-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<div class="oh-modal" id="sendMailModal" role="dialog" aria-labelledby="sendMailModal" aria-hidden="true">
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<h5 class="oh-modal__dialog-title" id="sendMailModalLabel">
|
||||
{% trans "Send Mail" %}
|
||||
</h5>
|
||||
<button class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oh-modal__dialog-body" id="mail-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
|
||||
<script src="{% static 'dashboard/attendanceChart.js' %}"></script>
|
||||
<script src="{% static 'dashboard/attendanceChart.js' %}"></script>
|
||||
|
||||
{% endblock content %}
|
||||
{% endblock content %}
|
||||
|
||||
Reference in New Issue
Block a user