Skip to content
27 changes: 27 additions & 0 deletions employees/common/strings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
from enum import Enum

from django.utils.translation import ugettext_lazy

from utils.decorators import notCallable


MAX_DECIMAL_VALUE_VALIDATOR_MESSAGE = ugettext_lazy('Ensure this value is less than or equal to ')


@notCallable
class ReportListStrings(Enum):
PAGE_TITLE = ugettext_lazy("Reports")
CREATE_REPORT_BUTTON = ugettext_lazy("Create")
DATE_COLUMN_HEADER = ugettext_lazy("Date")
PROJECT_COLUMN_HEADER = ugettext_lazy("Project")
WORK_HOURS_COLUMN_HEADER = ugettext_lazy("Work hours")
DESCRIPTION_COLUMN_HEADER = ugettext_lazy("Description")
EDIT_REPORT_BUTTON = ugettext_lazy("Edit")


@notCallable
class ReportDetailStrings(Enum):
PAGE_TITLE = ugettext_lazy("Report - ")
UPDATE_REPORT_BUTTON = ugettext_lazy("Update")
DISCARD_CHANGES_BUTTON = ugettext_lazy("Discard")
DELETE_REPORT_BUTTON = ugettext_lazy("Delete")
DELETE_POPUP_MESSAGE = ugettext_lazy("Are you sure you want to delete this report?")
DELETE_POPUP_TITLE = ugettext_lazy("Delete report")
DELETE_POPUP_YES = ugettext_lazy("Yes")
DELETE_POPUP_NO = ugettext_lazy("No")
24 changes: 24 additions & 0 deletions employees/static/employees/scripts/basic_popup_window.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$(function () {
$("#dialog").dialog ({
modal: true,
autoOpen: false,
buttons : [
{
text: discard_text,
click: function () {
$(this).dialog('close');
}
},
{
text: confirmation_text,
click: function () {
window.location.href = redirect_url;
}
}
]
}).prev().find(".ui-dialog-titlebar-close").hide ();

$("#opener").click(function () {
$('#dialog').dialog('open');
});
});
44 changes: 44 additions & 0 deletions employees/static/employees/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#dialog {
display: none;
text-align: center;
}

.modal-dialog {
margin-bottom: 0;
}

.date-header {
width: 11.23%;
}

.project-header {
width: 20.18%;
}

.work-hours-header {
width: 8.16%;
}

.edit-button-header {
width: 8.77%;
}

.date-column {
text-align: left;
}

.project-column {
text-align: left;
}

.description-column {
text-align: left;
}

.work-hours-column {
text-align: right;
}

.edit-button-column {
text-align: right;
}
34 changes: 34 additions & 0 deletions employees/templates/employees/report_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{% extends 'base.html' %}
{% load i18n %}
{% block content %}
{% load rest_framework %}
{% load static %}

<head>
<link rel="stylesheet" type="text/css" href="{% static 'employees/style.css' %}">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.12.4.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="text/javascript">
var discard_text = "{{ UI_text.DELETE_POPUP_NO.value }}";
var confirmation_text = "{{ UI_text.DELETE_POPUP_YES.value }}";
var redirect_url ="{% url 'custom-report-delete' pk=report.pk %}";
</script>
<script src="{% static 'employees/scripts/basic_popup_window.js' %}"></script>
</head>

<h1>{{ UI_text.PAGE_TITLE.value }}{{ report.project }} ({{ report.date }})</h1>
</br>
<div class="modal-dialog">
<form action="{% url 'custom-report-detail' pk=report.pk %}" method="POST">
{% csrf_token %}
{% render_form serializer template_pack='rest_framework/vertical' %}
<input type="submit" value="{{ UI_text.UPDATE_REPORT_BUTTON.value }}">
<input type="submit" name="discard" value="{{ UI_text.DISCARD_CHANGES_BUTTON.value }}">
<input type="button" id="opener" value="{{ UI_text.DELETE_REPORT_BUTTON.value }}">
</form>
</div>
<div id="dialog" title="{{ UI_text.DELETE_POPUP_TITLE.value }}">
{{ UI_text.DELETE_POPUP_MESSAGE.value }}
</div>
{% endblock %}
60 changes: 60 additions & 0 deletions employees/templates/employees/report_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{% extends 'base.html' %}
{% load i18n %}
{% block content %}
{% load rest_framework %}
{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'employees/style.css' %}">

<h1>{{ UI_text.PAGE_TITLE.value }}</h1>

<div class="modal-dialog">
<form action="{% url 'custom-report-list' %}" method="POST">
{% csrf_token %}
{% render_form serializer template_pack='rest_framework/vertical' %}
<input type="submit" value="{{ UI_text.CREATE_REPORT_BUTTON.value }}">
</form>
</div>
</br>
<div class="container">
<div class="table-responsive">
<table class="table">
<tr>
<th class="date-header">{{ UI_text.DATE_COLUMN_HEADER.value }}</th>
<th class="project-header">{{ UI_text.PROJECT_COLUMN_HEADER.value }}</th>
<th class="work-hours-header">{{ UI_text.WORK_HOURS_COLUMN_HEADER.value }}</th>
<th>{{ UI_text.DESCRIPTION_COLUMN_HEADER.value }}</th>
<td class="edit-button-header Invisible"></td>
</tr>
{% for date, reports in reports_dict.items %}
<tr>
<td class="date-column" rowspan={{ reports|length }}>
{{ date }}
</td>
{% for report in reports %}
{% if forloop.counter > 1 %}
Comment thread
kbeker marked this conversation as resolved.
<tr>
{% endif %}
<td class="project-column">
{{ report.project }}
</td>
<td class="work-hours-column">
{{ report.work_hours }}
</td>
<td class="description-column">
{{ report.description }}
</td>
<td class="edit-button-column Invisible">
{% if report.editable %}
<a href="{% url 'custom-report-detail' pk=report.id %}" class="btn btn-info">
<span class="glyphicon glyphicon-pencil"></span>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
</div>
</div>
{% endblock %}
70 changes: 70 additions & 0 deletions employees/tests/test_unit_report_view_helper_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import datetime
from decimal import Decimal
from django.test import TestCase

from employees.models import Report
from employees.views import query_as_dict
from managers.models import Project
from users.models import CustomUser


class TestListHelpers(TestCase):
def setUp(self):
self.user = CustomUser(
email="testuser@codepoets.it",
password='newuserpasswd',
first_name='John',
last_name='Doe',
country='PL'
)
self.user.full_clean()
self.user.save()

self.project = Project(
name="Test Project",
start_date=datetime.datetime.now(),
)
self.project.full_clean()
self.project.save()

report = Report(
date=datetime.datetime.now().date(),
description='Some description',
author=self.user,
project=self.project,
work_hours=Decimal('8.00'),
)
report.full_clean()
report.save()

report = Report(
date=datetime.datetime.now().date(),
description='Some description',
author=self.user,
project=self.project,
work_hours=Decimal('8.00'),
)
report.full_clean()
report.save()

report = Report(
date=datetime.date(2001, 1, 1),
description='Some description',
author=self.user,
project=self.project,
work_hours=Decimal('8.00'),
)
report.full_clean()
report.save()

def test_queryset_as_dict_should_return_dictionary_where_keys_are_dates_and_values_are_lists_of_reports(self):
queryset = Report.objects.all()
dictionary = query_as_dict(queryset)
self.assertEqual(len(dictionary), 2)
self.assertEqual(len(list(dictionary.values())[0]), 2)
self.assertEqual(len(list(dictionary.values())[1]), 1)
self.assertIsInstance(list(dictionary.keys())[0], datetime.date)
self.assertIsInstance(list(dictionary.keys())[1], datetime.date)
self.assertIsInstance(list(dictionary.values())[0][0], Report)
self.assertIsInstance(list(dictionary.values())[0][1], Report)
self.assertIsInstance(list(dictionary.values())[1][0], Report)
Loading