From 710863202d95393b183dcd414ca328d3bf1c7a4e Mon Sep 17 00:00:00 2001 From: Horilla Date: Mon, 18 Dec 2023 17:18:54 +0530 Subject: [PATCH] [ADD] BASE: Date format selection methods --- base/forms.py | 2 + base/models.py | 1 + base/static/base/date_formatting.js | 81 +++++++++++++++++++ base/static/base/date_settings.js | 22 +++++ base/templates/base/company/date.html | 72 +++++++++++++++++ .../leave_request_template.html | 4 +- .../base/rotating_shift/htmx/group_by.html | 18 ++--- .../base/rotating_shift/individual_view.html | 18 ++--- .../rotating_shift_assign_view.html | 18 ++--- .../rotating_work_type/htmx/group_by.html | 4 +- .../htmx/rotating_work_type_assign_form.html | 2 - .../rotating_work_type/individual_view.html | 18 ++--- .../rotating_work_type_assign_view.html | 4 +- .../shift_request/htmx/group_by.html | 4 +- .../shift_request/htmx/requests.html | 4 +- .../htmx/shift_request_detail.html | 4 +- .../work_type_request/htmx/group_by.html | 4 +- .../work_type_request/htmx/requests.html | 4 +- .../htmx/work_type_request_single_view.html | 4 +- base/urls.py | 7 +- base/views.py | 68 ++++++++++++++++ static/build/js/moment.js | 2 + templates/index.html | 6 +- templates/settings.html | 8 ++ 24 files changed, 320 insertions(+), 59 deletions(-) create mode 100644 base/static/base/date_formatting.js create mode 100644 base/static/base/date_settings.js create mode 100644 base/templates/base/company/date.html create mode 100644 static/build/js/moment.js diff --git a/base/forms.py b/base/forms.py index a03754c6e..cc752f056 100644 --- a/base/forms.py +++ b/base/forms.py @@ -345,6 +345,8 @@ class CompanyForm(ModelForm): model = Company fields = "__all__" + excluded_fields=["date_format"] + def validate_image(self, file): max_size = 5 * 1024 * 1024 diff --git a/base/models.py b/base/models.py index a86ca0cb9..832a0053f 100644 --- a/base/models.py +++ b/base/models.py @@ -46,6 +46,7 @@ class Company(models.Model): null=True, ) objects = models.Manager() + date_format = models.CharField(max_length=10, blank=True, null=True) class Meta: """ diff --git a/base/static/base/date_formatting.js b/base/static/base/date_formatting.js new file mode 100644 index 000000000..025e73ef5 --- /dev/null +++ b/base/static/base/date_formatting.js @@ -0,0 +1,81 @@ +class DateFormattingUtility { + constructor() { + // Default date format + this.dateFormat = 'MMM. D, YYYY'; + } + + setDateFormat(format) { + // Save the selected format to localStorage + localStorage.setItem('selectedDateFormat', format); + this.dateFormat = format; + } + + getFormattedDate(date) { + + if (localStorage.getItem('selectedDateFormat')){ + + } + else{ + function fetchData(callback) { + + $.ajax({ + url: '/settings/get-date-format/', + method: 'GET', + data: { csrfmiddlewaretoken: getCookie('csrftoken') }, + success: function(response) { + var date_format = response.selected_format; + + // Call the callback function and pass the value of 'date_format' + callback(date_format); + }, + }); + } + + // Use the fetchData function with a callback + fetchData(function(date_format) { + + // If any date format is found setting it to the local storage. + if(date_format){ + localStorage.setItem('selectedDateFormat', date_format); + + } + // Setting a default date format MMM. D, YYYY + else{ + localStorage.setItem('selectedDateFormat', 'MMM. D, YYYY'); + } + }); + + } + // Use the stored date format + const storedDateFormat = localStorage.getItem('selectedDateFormat') || 'MMM. D, YYYY'; + + + // Preprocess the date string based on the selected format + let processedDate = date; + if (storedDateFormat === 'DD-MM-YYYY') { + processedDate = date.replace(/(\d{2})-(\d{2})-(\d{4})/, '$3-$2-$1'); + } else if (storedDateFormat === 'DD.MM.YYYY') { + processedDate = date.replace(/(\d{2})\.(\d{2})\.(\d{4})/, '$3-$2-$1'); + } else if (storedDateFormat === 'DD/MM/YYYY') { + processedDate = date.replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1'); + } + + // Format the processed date using moment.js + const formattedDate = moment(processedDate).format(storedDateFormat); + + return formattedDate; + } + + +} + +// Create an instance of the utility +const dateFormatter = new DateFormattingUtility(); + +// Retrieve the selected date format from localStorage +const storedDateFormat = localStorage.getItem('selectedDateFormat'); + +if (storedDateFormat) { + // If a date format is stored, set it in the utility + dateFormatter.setDateFormat(storedDateFormat); +} diff --git a/base/static/base/date_settings.js b/base/static/base/date_settings.js new file mode 100644 index 000000000..2f7d1aaa8 --- /dev/null +++ b/base/static/base/date_settings.js @@ -0,0 +1,22 @@ +function saveDateFormat() { + var dateFormatSelector = document.getElementById('dateFormat'); + const selectedFormat = dateFormatSelector.value; + + // Set the selected date format in the utility + dateFormatter.setDateFormat(selectedFormat); + + // Save the date format to the backend + saveDateFormatToBackend(selectedFormat); + +} + +function saveDateFormatToBackend(selectedFormat) { + $.ajax({ + url: '/settings/save-date/', + method: 'POST', + data: { selected_format: selectedFormat, csrfmiddlewaretoken:getCookie('csrftoken') }, + success: function(response) { + window.location.reload(); + }, + }); +} diff --git a/base/templates/base/company/date.html b/base/templates/base/company/date.html new file mode 100644 index 000000000..5b9e55927 --- /dev/null +++ b/base/templates/base/company/date.html @@ -0,0 +1,72 @@ +{% extends 'settings.html' %} +{% load i18n %} +{% load static %} +{% block settings %} + +
+

{% trans "Date Format" %}

+
+ + + + + + + + +
+ {% trans "Current Date Format"%}   :   + +
+ + + + + + + + +{% endblock %} + diff --git a/base/templates/base/mail_templates/leave_request_template.html b/base/templates/base/mail_templates/leave_request_template.html index 3eae19ff1..99a5153a4 100644 --- a/base/templates/base/mail_templates/leave_request_template.html +++ b/base/templates/base/mail_templates/leave_request_template.html @@ -27,10 +27,10 @@ {{leave_request.reject_reason }}

- {% trans "Start Date:" %} {{ leave_request.start_date }} + {% trans "Start Date:" %} {{ leave_request.start_date }}

- {% trans "End Date:" %} {{ leave_request.end_date }} + {% trans "End Date:" %} {{ leave_request.end_date }}

diff --git a/base/templates/base/rotating_shift/htmx/group_by.html b/base/templates/base/rotating_shift/htmx/group_by.html index cfecaa263..d03a7de43 100644 --- a/base/templates/base/rotating_shift/htmx/group_by.html +++ b/base/templates/base/rotating_shift/htmx/group_by.html @@ -100,26 +100,26 @@

{{rshift.get_based_on_display }}
{% if rshift.based_on == 'after' %} - Rotate after {{rshift.rotate_after_day}} days + {% trans "Rotate after" %} {{rshift.rotate_after_day}} {% trans "days" %} {% elif rshift.based_on == "weekly" %} - Weekly every {{rshift.rotate_every_weekend}} + {% trans "Weekly every" %} {{rshift.rotate_every_weekend}} {% elif rshift.based_on == "monthly" %} {% if rshift.rotate_every == "1" %} - Rotate every {{rshift.rotate_every}}st day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}st {% trans "day of month" %} {% elif rshift.rotate_every == "2" %} - Rotate every {{rshift.rotate_every}}nd day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}nd {% trans "day of month" %} {% elif rshift.rotate_every == "3" %} - Rotate every {{rshift.rotate_every}}rd day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}rd {% trans "day of month" %} {% elif rshift.rotate_every == "last" %} - Rotate every last day of month + {% trans "Rotate every last day of month" %} {% else %} - Rotate every {{rshift.rotate_every}}th day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}th {% trans "day of month" %} {% endif %} {% endif %}
-
{{rshift.start_date}}
+
{{rshift.start_date}}
{{rshift.current_shift}}
-
{{rshift.next_change_date}}
+
{{rshift.next_change_date}}
{{rshift.next_shift}}
diff --git a/base/templates/base/rotating_shift/individual_view.html b/base/templates/base/rotating_shift/individual_view.html index 4b9969eb1..36c7ba2f0 100644 --- a/base/templates/base/rotating_shift/individual_view.html +++ b/base/templates/base/rotating_shift/individual_view.html @@ -55,27 +55,27 @@ {% trans "Rotate" %} {% if instance.based_on == 'after' %} - Rotate after {{instance.rotate_after_day}} days + {% trans "Rotate after" %} {{instance.rotate_after_day}} {% trans "days" %} {% elif instance.based_on == "weekly" %} - Weekly every {{instance.rotate_every_weekend}} + {% trans "Weekly every" %} {{instance.rotate_every_weekend}} {% elif instance.based_on == "monthly" %} {% if instance.rotate_every == "1" %} - Rotate every {{instance.rotate_every}}st day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "st day of month" %} {% elif instance.rotate_every == "2" %} - Rotate every {{instance.rotate_every}}nd day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "nd day of month" %} {% elif instance.rotate_every == "3" %} - Rotate every {{instance.rotate_every}}rd day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "rd day of month" %} {% elif instance.rotate_every == "last" %} - Rotate every last day of month + {% trans "Rotate every last day of month" %} {% else %} - Rotate every {{instance.rotate_every}}th day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "th day of month" %} {% endif %} {% endif %}
{% trans "Start Date" %} - {{instance.start_date}} + {{instance.start_date}}
@@ -94,7 +94,7 @@
{% trans "Next Change Date" %} - + {{instance.next_change_date}}
diff --git a/base/templates/base/rotating_shift/rotating_shift_assign_view.html b/base/templates/base/rotating_shift/rotating_shift_assign_view.html index 272bdf801..b10747b85 100644 --- a/base/templates/base/rotating_shift/rotating_shift_assign_view.html +++ b/base/templates/base/rotating_shift/rotating_shift_assign_view.html @@ -84,26 +84,26 @@
{{rshift.get_based_on_display }}
{% if rshift.based_on == 'after' %} - Rotate after {{rshift.rotate_after_day}} days + {% trans "Rotate after" %} {{rshift.rotate_after_day}} {% trans "days" %} {% elif rshift.based_on == "weekly" %} - Weekly every {{rshift.rotate_every_weekend}} + {% trans "Weekly every" %} {{rshift.rotate_every_weekend}} {% elif rshift.based_on == "monthly" %} {% if rshift.rotate_every == "1" %} - Rotate every {{rshift.rotate_every}}st day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}{% trans "st day of month" %} {% elif rshift.rotate_every == "2" %} - Rotate every {{rshift.rotate_every}}nd day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}{% trans "nd day of month" %} {% elif rshift.rotate_every == "3" %} - Rotate every {{rshift.rotate_every}}rd day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}{% trans "rd day of month" %} {% elif rshift.rotate_every == "last" %} - Rotate every last day of month + {% trans "Rotate every last day of month" %} {% else %} - Rotate every {{rshift.rotate_every}}th day of month + {% trans "Rotate every" %} {{rshift.rotate_every}}{% trans "th day of month" %} {% endif %} {% endif %}
-
{{rshift.start_date}}
+
{{rshift.start_date}}
{{rshift.current_shift}}
-
{{rshift.next_change_date}}
+
{{rshift.next_change_date}}
{{rshift.next_shift}}
diff --git a/base/templates/base/rotating_work_type/htmx/group_by.html b/base/templates/base/rotating_work_type/htmx/group_by.html index f075ab9da..a5262cff8 100644 --- a/base/templates/base/rotating_work_type/htmx/group_by.html +++ b/base/templates/base/rotating_work_type/htmx/group_by.html @@ -118,9 +118,9 @@ style="cursor: pointer; display: none" {% endif %} {% endif %}
-
{{rwork_type.start_date}}
+
{{rwork_type.start_date}}
{{rwork_type.current_work_type}}
-
{{rwork_type.next_change_date}}
+
{{rwork_type.next_change_date}}
{{rwork_type.next_work_type}}
diff --git a/base/templates/base/rotating_work_type/htmx/rotating_work_type_assign_form.html b/base/templates/base/rotating_work_type/htmx/rotating_work_type_assign_form.html index 27b33ba2b..2fd658519 100644 --- a/base/templates/base/rotating_work_type/htmx/rotating_work_type_assign_form.html +++ b/base/templates/base/rotating_work_type/htmx/rotating_work_type_assign_form.html @@ -11,5 +11,3 @@ - - \ No newline at end of file diff --git a/base/templates/base/rotating_work_type/individual_view.html b/base/templates/base/rotating_work_type/individual_view.html index c8bcb3c62..1d7f8f64d 100644 --- a/base/templates/base/rotating_work_type/individual_view.html +++ b/base/templates/base/rotating_work_type/individual_view.html @@ -53,27 +53,27 @@ {% trans "Rotate" %} {% if instance.based_on == 'after' %} - Rotate after {{instance.rotate_after_day}} days + {% trans "Rotate after" %} {{instance.rotate_after_day}} {% trans "days" %} {% elif instance.based_on == "weekly" %} - Weekly every {{instance.rotate_every_weekend}} + {% trans "Weekly every" %} {{instance.rotate_every_weekend}} {% elif instance.based_on == "monthly" %} {% if instance.rotate_every == "1" %} - Rotate every {{instance.rotate_every}}st day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "st day of month" %} {% elif instance.rotate_every == "2" %} - Rotate every {{instance.rotate_every}}nd day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "nd day of month" %} {% elif instance.rotate_every == "3" %} - Rotate every {{instance.rotate_every}}rd day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "rd day of month" %} {% elif instance.rotate_every == "last" %} - Rotate every last day of month + {% trans "Rotate every last day of month" %} {% else %} - Rotate every {{instance.rotate_every}}th day of month + {% trans "Rotate every" %} {{instance.rotate_every}}{% trans "th day of month" %} {% endif %} {% endif %}
{% trans "Start Date" %} - {{instance.start_date}} + {{instance.start_date}}
@@ -92,7 +92,7 @@
{% trans "Next Change Date" %} - + {{instance.next_change_date}}
diff --git a/base/templates/base/rotating_work_type/rotating_work_type_assign_view.html b/base/templates/base/rotating_work_type/rotating_work_type_assign_view.html index b5b54c790..da7c90fb1 100644 --- a/base/templates/base/rotating_work_type/rotating_work_type_assign_view.html +++ b/base/templates/base/rotating_work_type/rotating_work_type_assign_view.html @@ -101,9 +101,9 @@ style="cursor: pointer; display: none" {% endif %} {% endif %}
-
{{rwork_type.start_date}}
+
{{rwork_type.start_date}}
{{rwork_type.current_work_type}}
-
{{rwork_type.next_change_date}}
+
{{rwork_type.next_change_date}}
{{rwork_type.next_work_type}}
diff --git a/base/templates/shift_request/htmx/group_by.html b/base/templates/shift_request/htmx/group_by.html index 076cdf9a4..8cbf95843 100644 --- a/base/templates/shift_request/htmx/group_by.html +++ b/base/templates/shift_request/htmx/group_by.html @@ -101,8 +101,8 @@ style="cursor: pointer;"
{{shift_request.shift_id}}
{{shift_request.previous_shift_id}}
-
{{shift_request.requested_date}}
-
{{shift_request.requested_till}}
+
{{shift_request.requested_date}}
+
{{shift_request.requested_till}}
{{shift_request.description}}
diff --git a/base/templates/shift_request/htmx/requests.html b/base/templates/shift_request/htmx/requests.html index ccf82b5b8..bf1f08aae 100755 --- a/base/templates/shift_request/htmx/requests.html +++ b/base/templates/shift_request/htmx/requests.html @@ -85,8 +85,8 @@ style="cursor: pointer;"
{{shift_request.shift_id}}
{{shift_request.previous_shift_id}}
-
{{shift_request.requested_date}}
-
{{shift_request.requested_till}}
+
{{shift_request.requested_date}}
+
{{shift_request.requested_till}}
{{shift_request.description}}
diff --git a/base/templates/shift_request/htmx/shift_request_detail.html b/base/templates/shift_request/htmx/shift_request_detail.html index f9fc3a5f5..3424877cf 100644 --- a/base/templates/shift_request/htmx/shift_request_detail.html +++ b/base/templates/shift_request/htmx/shift_request_detail.html @@ -45,11 +45,11 @@
{% trans "Requested date" %} - {{shift_request.requested_date}} + {{shift_request.requested_date}}
{% trans "Requested till" %} - {{shift_request.requested_till}} + {{shift_request.requested_till}}
diff --git a/base/templates/work_type_request/htmx/group_by.html b/base/templates/work_type_request/htmx/group_by.html index 4f998cdd5..5c15d0416 100644 --- a/base/templates/work_type_request/htmx/group_by.html +++ b/base/templates/work_type_request/htmx/group_by.html @@ -101,8 +101,8 @@ style="cursor: pointer; display: none"
{{work_type_request.work_type_id}}
{{work_type_request.previous_work_type_id}}
-
{{work_type_request.requested_date}}
-
{{work_type_request.requested_till}}
+
{{work_type_request.requested_date}}
+
{{work_type_request.requested_till}}
{{work_type_request.description}}
diff --git a/base/templates/work_type_request/htmx/requests.html b/base/templates/work_type_request/htmx/requests.html index 3ec0a5437..d92f1c680 100755 --- a/base/templates/work_type_request/htmx/requests.html +++ b/base/templates/work_type_request/htmx/requests.html @@ -85,8 +85,8 @@ style="cursor: pointer; display: none"
{{work_type_request.work_type_id}}
{{work_type_request.previous_work_type_id}}
-
{{work_type_request.requested_date}}
-
{{work_type_request.requested_till}}
+
{{work_type_request.requested_date}}
+
{{work_type_request.requested_till}}
{{work_type_request.description}}
diff --git a/base/templates/work_type_request/htmx/work_type_request_single_view.html b/base/templates/work_type_request/htmx/work_type_request_single_view.html index 984e5721a..4f4bd29d7 100644 --- a/base/templates/work_type_request/htmx/work_type_request_single_view.html +++ b/base/templates/work_type_request/htmx/work_type_request_single_view.html @@ -45,11 +45,11 @@
{% trans "Requested date" %} - {{work_type_request.requested_date}} + {{work_type_request.requested_date}}
{% trans "Requested till" %} - {{work_type_request.requested_till}} + {{work_type_request.requested_till}}
diff --git a/base/urls.py b/base/urls.py index 599f1e256..6b392052e 100644 --- a/base/urls.py +++ b/base/urls.py @@ -25,7 +25,7 @@ urlpatterns = [ path( "settings/user-group-create/", views.user_group_table, name="user-group-create" ), - path("user-group-view", views.user_group, name="user-group-view"), + path("settings/user-group-view/", views.user_group, name="user-group-view"), path( "settings/user-group-update//", views.user_group_update, @@ -78,7 +78,7 @@ urlpatterns = [ name="permission-table", ), path("settings/company-create/", views.company_create, name="company-create"), - path('company-view', views.company_view,name='company-view'), + path('settings/company-view/', views.company_view,name='company-view'), path( "settings/company-update//", views.company_update, @@ -490,6 +490,9 @@ urlpatterns = [ name="delete-notifications", ), path("settings/currency/", views.settings, name="currency-settings"), + path("settings/date/", views.date_settings, name="date-settings"), + path('settings/save-date/', views.save_date_format, name='save_date_format'), + path('settings/get-date-format/', views.get_date_format, name='get-date-format'), path( "settings/attendance-settings-view/", views.validation_condition_view, diff --git a/base/views.py b/base/views.py index 245d937ae..a1fea46df 100644 --- a/base/views.py +++ b/base/views.py @@ -20,6 +20,7 @@ from django.contrib.auth import authenticate, login, logout from django.contrib.auth.models import Group, User, Permission from attendance.forms import AttendanceValidationConditionForm from attendance.models import AttendanceValidationCondition +from django.views.decorators.csrf import csrf_exempt from notifications.signals import notify from horilla.decorators import ( delete_permission, @@ -2137,6 +2138,7 @@ def work_type_request_view(request): @login_required +@manager_can_enter("base.view_worktyperequest") def work_type_request_export(request): return export_data( request, @@ -2652,6 +2654,7 @@ def shift_request_view(request): ) @login_required +@manager_can_enter("base.view_shiftrequest") def shift_request_export(request): return export_data( request, @@ -3107,6 +3110,71 @@ def settings(request): return render(request, "payroll/settings/payroll_settings.html", {"form": form}) +@login_required +@permission_required("base.change_company") +def date_settings(request): + """ + This method is used to render Date format selector in settings + """ + return render(request, "base/company/date.html") + + +@permission_required("base.change_company") +@csrf_exempt # Use this decorator if CSRF protection is enabled +def save_date_format(request): + if request.method == 'POST': + + # Taking the selected Date Format + selected_format = request.POST.get('selected_format') + user= request.user + employee = user.employee_get + + # Taking the company_name of the user + info = EmployeeWorkInformation.objects.filter(employee_id=employee) + # Employee workinformation will not exists if he/she chnged the company, So can't save the date format. + if info.exists(): + for data in info: + employee_company = data.company_id + + company_name = Company.objects.filter(company=employee_company) + emp_company = company_name.first() + + # Save the selected format to the backend + emp_company.date_format = selected_format + emp_company.save() + messages.success(request, _('Date format saved successfully.')) + else: + messages.warning(request, _('Date format cannot saved. You are not in the company.')) + + # Return a JSON response indicating success + return JsonResponse({'success': True}) + + # Return a JSON response for unsupported methods + return JsonResponse({'success': False, 'error': 'Unsupported method'}, status=405) + + +@login_required +def get_date_format(request): + + user= request.user + employee = user.employee_get + + # Taking the company_name of the user + info = EmployeeWorkInformation.objects.filter(employee_id=employee) + if info.exists(): + for data in info: + employee_company = data.company_id + company_name = Company.objects.filter(company=employee_company) + emp_company = company_name.first() + + # Access the date_format attribute directly + date_format = emp_company.date_format + else: + date_format = 'MMM. D, YYYY' + # Return the date format as JSON response + return JsonResponse({'selected_format': date_format}) + + @login_required @permission_required("attendance.add_attendancevalidationcondition") def validation_condition_view(request): diff --git a/static/build/js/moment.js b/static/build/js/moment.js new file mode 100644 index 000000000..57cd2d4f3 --- /dev/null +++ b/static/build/js/moment.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function f(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function l(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;for(var t in e)if(m(e,t))return;return 1}function r(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function a(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function d(e,t){for(var n=[],s=0;s>>0,s=0;sFe(e)?(r=e+1,a-Fe(e)):(r=e,a);return{year:r,dayOfYear:o}}function Ae(e,t,n){var s,i,r=Ge(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+je(i=e.year()-1,t,n):a>je(e.year(),t,n)?(s=a-je(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function je(e,t,n){var s=Ge(e,t,n),i=Ge(e+1,t,n);return(Fe(e)-s+i)/7}C("w",["ww",2],"wo","week"),C("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),A("week",5),A("isoWeek",5),ce("w",te),ce("ww",te,Q),ce("W",te),ce("WW",te,Q),ge(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=Z(e)});function Ie(e,t){return e.slice(t,7).concat(e.slice(0,t))}C("d",0,"do","day"),C("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),C("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),C("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),C("e",0,0,"weekday"),C("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),A("day",11),A("weekday",11),A("isoWeekday",11),ce("d",te),ce("e",te),ce("E",te),ce("dd",function(e,t){return t.weekdaysMinRegex(e)}),ce("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ce("dddd",function(e,t){return t.weekdaysRegex(e)}),ge(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:y(n).invalidWeekday=e}),ge(["d","e","E"],function(e,t,n,s){t[s]=Z(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),$e="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),qe=de,Be=de,Je=de;function Qe(){function e(e,t){return t.length-e.length}for(var t,n,s,i,r=[],a=[],o=[],u=[],l=0;l<7;l++)t=_([2e3,1]).day(l),n=me(this.weekdaysMin(t,"")),s=me(this.weekdaysShort(t,"")),i=me(this.weekdays(t,"")),r.push(n),a.push(s),o.push(i),u.push(n),u.push(s),u.push(i);r.sort(e),a.sort(e),o.sort(e),u.sort(e),this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+r.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){C(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}C("H",["HH",2],0,"hour"),C("h",["hh",2],0,Xe),C("k",["kk",2],0,function(){return this.hours()||24}),C("hmm",0,0,function(){return""+Xe.apply(this)+T(this.minutes(),2)}),C("hmmss",0,0,function(){return""+Xe.apply(this)+T(this.minutes(),2)+T(this.seconds(),2)}),C("Hmm",0,0,function(){return""+this.hours()+T(this.minutes(),2)}),C("Hmmss",0,0,function(){return""+this.hours()+T(this.minutes(),2)+T(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),L("hour","h"),A("hour",13),ce("a",et),ce("A",et),ce("H",te),ce("h",te),ce("k",te),ce("HH",te,Q),ce("hh",te,Q),ce("kk",te,Q),ce("hmm",ne),ce("hmmss",se),ce("Hmm",ne),ce("Hmmss",se),ye(["H","HH"],Me),ye(["k","kk"],function(e,t,n){var s=Z(e);t[Me]=24===s?0:s}),ye(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ye(["h","hh"],function(e,t,n){t[Me]=Z(e),y(n).bigHour=!0}),ye("hmm",function(e,t,n){var s=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s)),y(n).bigHour=!0}),ye("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s,2)),t[Se]=Z(e.substr(i)),y(n).bigHour=!0}),ye("Hmm",function(e,t,n){var s=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s))}),ye("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s,2)),t[Se]=Z(e.substr(i))});var tt=z("Hours",!0);var nt,st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Te,monthsShort:Ne,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){for(var t,n,s,i,r=0;r=t&&function(e,t){for(var n=Math.min(e.length,t.length),s=0;s=t-1)break;t--}r++}return nt}function ut(t){var e;if(void 0===it[t]&&"undefined"!=typeof module&&module&&module.exports)try{e=nt._abbr,require("./locale/"+t),lt(e)}catch(e){it[t]=null}return it[t]}function lt(e,t){var n;return e&&((n=r(t)?dt(e):ht(e,t))?nt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),nt._abbr}function ht(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])Y("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ut(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new x(b(s,t)),rt[e]&&rt[e].forEach(function(e){ht(e.name,e.config)}),lt(e),it[e]}function dt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return nt;if(!o(e)){if(t=ut(e))return t;e=[e]}return ot(e)}function ct(e){var t,n=e._a;return n&&-2===y(e).overflow&&(t=n[ve]<0||11xe(n[pe],n[ve])?ke:n[Me]<0||24je(n,r,a)?y(e)._overflowWeeks=!0:null!=u?y(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[pe]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=St(e._a[pe],s[pe]),(e._dayOfYear>Fe(r)||0===e._dayOfYear)&&(y(e)._overflowDayOfYear=!0),n=Ve(r,0,e._dayOfYear),e._a[ve]=n.getUTCMonth(),e._a[ke]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=u[t]=s[t];for(;t<7;t++)e._a[t]=u[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[Me]&&0===e._a[De]&&0===e._a[Se]&&0===e._a[Ye]&&(e._nextDay=!0,e._a[Me]=0),e._d=(e._useUTC?Ve:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,u),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Me]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(y(e).weekdayMismatch=!0)}}function Ot(e){if(e._f!==f.ISO_8601)if(e._f!==f.RFC_2822){e._a=[],y(e).empty=!0;for(var t,n,s,i,r,a,o,u=""+e._i,l=u.length,h=0,d=H(e._f,e._locale).match(N)||[],c=0;cn.valueOf():n.valueOf()"}),pn.toJSON=function(){return this.isValid()?this.toISOString():null},pn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},pn.unix=function(){return Math.floor(this.valueOf()/1e3)},pn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},pn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},pn.eraName=function(){for(var e,t=this.localeData().eras(),n=0,s=t.length;nthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},pn.isLocal=function(){return!!this.isValid()&&!this._isUTC},pn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},pn.isUtc=At,pn.isUTC=At,pn.zoneAbbr=function(){return this._isUTC?"UTC":""},pn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},pn.dates=n("dates accessor is deprecated. Use date instead.",fn),pn.months=n("months accessor is deprecated. Use month instead",Ue),pn.years=n("years accessor is deprecated. Use year instead",Le),pn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),pn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!r(this._isDSTShifted))return this._isDSTShifted;var e,t={};return v(t,this),(t=bt(t))._a?(e=(t._isUTC?_:Tt)(t._a),this._isDSTShifted=this.isValid()&&0 {% if request.user|is_clocked_in %}