diff --git a/smash/web/forms/forms.py b/smash/web/forms/forms.py index 7fc95986747cdbaf859f928cde493ebd9f53a661..b426058577ffc456434243d69c8e61e94adcf8ac 100644 --- a/smash/web/forms/forms.py +++ b/smash/web/forms/forms.py @@ -6,8 +6,8 @@ from django.forms import ModelForm, Form from django.utils.dates import MONTHS from web.models import Appointment, AppointmentType, AppointmentTypeLink, \ - Availability, ContactAttempt, FlyingTeam, Holiday, StudySubject, \ - Worker, Visit, VoucherType, VoucherTypePrice + Availability, ContactAttempt, FlyingTeam, Holiday, Item, \ + StudySubject, Room, Worker, Visit, VoucherType, VoucherTypePrice from web.models.constants import SUBJECT_TYPE_CHOICES """ @@ -185,6 +185,12 @@ def validate_availability_conflict(self, cleaned_data, availability): self.add_error('available_till', error) +class ItemForm(ModelForm): + class Meta: + model = Item + fields = "__all__" + + class FlyingTeamAddForm(ModelForm): class Meta: model = FlyingTeam @@ -214,3 +220,9 @@ class HolidayAddForm(ModelForm): availabilities = worker.availability_set.all() for availability in availabilities: validate_availability_conflict(self, self.cleaned_data, availability) + + +class RoomForm(ModelForm): + class Meta: + model = Room + fields = '__all__' diff --git a/smash/web/templates/eqdef/breadcrumb.html b/smash/web/templates/eqdef/breadcrumb.html deleted file mode 100644 index 888621e6be83367fffadf57ad5f5d6fb7130e823..0000000000000000000000000000000000000000 --- a/smash/web/templates/eqdef/breadcrumb.html +++ /dev/null @@ -1,2 +0,0 @@ -<li><a href="{% url 'web.views.appointments' %}"><i class="fa fa-dashboard"></i> Dashboard</a></li> -<li class="active"><a href="{% url 'web.views.equipment_def' %}">Equipment definitions</a></li> \ No newline at end of file diff --git a/smash/web/templates/equipment_and_rooms/equipment/add.html b/smash/web/templates/equipment_and_rooms/equipment/add.html new file mode 100644 index 0000000000000000000000000000000000000000..104530ac08654a6cd0ae46fbee4ecc8f4ddf0517 --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/equipment/add.html @@ -0,0 +1,56 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block page_header %}New equipment definition{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Add new equipment definition{% endblock %} + +{% block breadcrumb %} + {% include "equipment_and_rooms/equipment/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + <div class="box box-info"> + <div class="box-header with-border"> + <a href="{% url 'web.views.equipment' %}" class="btn btn-block btn-default">Go back (without changes)</a> + </div> + + <form method="post" action="" class="form-horizontal"> + {% csrf_token %} + + <div class="box-body"> + <div class="col-sm-6"> + {% for field in form %} + <div class="form-group {% if field.errors %}has-error{% endif %}"> + <label for="{# TODO #}" class="col-sm-4 control-label"> + {{ field.label }} + </label> + + <div class="col-sm-8"> + {{ field|add_class:'form-control' }} + </div> + + {% if field.errors %} + <span class="help-block"> + {{ field.errors }} + </span> + {% endif %} + </div> + {% endfor %} + </div> + </div><!-- /.box-body --> + + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-success">Add</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.equipment' %}" class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + {% endblock %} diff --git a/smash/web/templates/equipment_and_rooms/equipment/breadcrumb.html b/smash/web/templates/equipment_and_rooms/equipment/breadcrumb.html new file mode 100644 index 0000000000000000000000000000000000000000..7205568ff1353fbfe2d409cbca64aabf9489aa31 --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/equipment/breadcrumb.html @@ -0,0 +1,3 @@ +<li><a href="{% url 'web.views.appointments' %}"><i class="fa fa-dashboard"></i> Dashboard</a></li> +<li><a href="{% url 'web.views.equipment_and_rooms' %}">Equipment and rooms</a></li> +<li class="active"><a href="{% url 'web.views.equipment' %}">Equipment definitions</a></li> diff --git a/smash/web/templates/equipment_and_rooms/equipment/edit.html b/smash/web/templates/equipment_and_rooms/equipment/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..72ac27597bac687fbf8d0c3a1b41c86fa8700b32 --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/equipment/edit.html @@ -0,0 +1,57 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block page_header %}Edit equipment definition{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Edit equipment definition{% endblock %} + +{% block breadcrumb %} + {% include "equipment_and_rooms/equipment/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + <div class="box box-info"> + <div class="box-header with-border"> + <a href="{% url 'web.views.equipment' %}" class="btn btn-block btn-default">Go back (without changes)</a> + </div> + + <form method="post" action="" class="form-horizontal"> + {% csrf_token %} + + <div class="box-body"> + <div class="col-sm-6"> + {% for field in form %} + <div class="form-group {% if field.errors %}has-error{% endif %}"> + <label for="{# TODO #}" class="col-sm-4 control-label"> + {{ field.label }} + </label> + + <div class="col-sm-8"> + {{ field|add_class:'form-control' }} + </div> + + {% if field.errors %} + <span class="help-block"> + {{ field.errors }} + </span> + {% endif %} + </div> + {% endfor %} + </div> + </div><!-- /.box-body --> + + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-success">Save</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.equipment' %}" class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + {% endblock %} diff --git a/smash/web/templates/eqdef/index.html b/smash/web/templates/equipment_and_rooms/equipment/index.html similarity index 72% rename from smash/web/templates/eqdef/index.html rename to smash/web/templates/equipment_and_rooms/equipment/index.html index fbc0dc6e64592cb1a761246edc9c248d46beb7fa..d1869fa9d4264eca843d55d4f78ffce7cb0a1685 100644 --- a/smash/web/templates/eqdef/index.html +++ b/smash/web/templates/equipment_and_rooms/equipment/index.html @@ -7,18 +7,18 @@ <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> {% endblock styles %} -{% block ui_active_tab %}'eqdef'{% endblock ui_active_tab %} +{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} {% block page_header %}Equipment definitions{% endblock page_header %} {% block page_description %}{% endblock page_description %} {% block breadcrumb %} - {% include "eqdef/breadcrumb.html" %} + {% include "equipment_and_rooms/equipment/breadcrumb.html" %} {% endblock breadcrumb %} {% block maincontent %} <div> - <a class="btn btn-app"> + <a class="btn btn-app" href="{% url 'web.views.equipment_add' %}"> <i class="fa fa-plus"></i> Add new equipment type </a> </div> @@ -31,6 +31,7 @@ <th>No.</th> <th>Name</th> <th>Is fixed?</th> + <th>Is disposable?</th> <th>Edit</th> <th>Delete</th> </tr> @@ -42,16 +43,23 @@ <td>{{ equip.name }}</td> <td> {% if equip.isFixed %} - <button type="button" class="btn btn-block btn-danger">YES</button> + Yes {% else %} - <button type="button" class="btn btn-block btn-success">NO</button> + No {% endif %} </td> <td> - <button type="button" class="btn btn-block btn-default">Edit</button> + {% if equip.disposable %} + Yes + {% else %} + No + {% endif %} + </td> + <td> + <a href="{% url 'web.views.equipment_edit' equip.id %}" class="btn btn-block btn-default">Edit</button> </td> <td> - <button type="button" class="btn btn-block btn-default">Delete</button> + <a href="{% url 'web.views.equipment_delete' equip.id %}" class="btn btn-block btn-danger">Delete</button> </td> </tr> {% endfor %} diff --git a/smash/web/templates/equipment_and_rooms/flying_teams/index.html b/smash/web/templates/equipment_and_rooms/flying_teams/index.html index 4a55f8953d80f6144bb0112cebbebee8f1412882..df8165b16339e330b96565d457ae17b17b241672 100644 --- a/smash/web/templates/equipment_and_rooms/flying_teams/index.html +++ b/smash/web/templates/equipment_and_rooms/flying_teams/index.html @@ -50,3 +50,23 @@ <p>No flying teams found.</p> {% endif %} {% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script> + + <script> + $(function () { + $('#table').DataTable({ + "paging": true, + "lengthChange": false, + "searching": true, + "ordering": true, + "info": true, + "autoWidth": false + }); + }); + </script> +{% endblock scripts %} diff --git a/smash/web/templates/equipment_and_rooms/index.html b/smash/web/templates/equipment_and_rooms/index.html index d4e27c7147abcb32c52818c5358bd6d49d36ab36..365946c8c5c1f8e3a9bcf965760007b330aa7b98 100644 --- a/smash/web/templates/equipment_and_rooms/index.html +++ b/smash/web/templates/equipment_and_rooms/index.html @@ -43,21 +43,7 @@ <div class="icon"> <i class="ion ion-settings"></i> </div> - <a href="{% url 'web.views.equipment_def' %}" class="small-box-footer"> - Edit <i class="fa fa-arrow-circle-right"></i> - </a> - </div> - - <div class="bg-red small-box"> - <div class="inner"> - <h4>Rooms</h4> - - <p> </p> - </div> - <div class="icon"> - <i class="ion ion-android-home"></i> - </div> - <a href="#" class="small-box-footer"> + <a href="{% url 'web.views.equipment' %}" class="small-box-footer"> Edit <i class="fa fa-arrow-circle-right"></i> </a> </div> @@ -92,22 +78,35 @@ Manage <i class="fa fa-arrow-circle-right"></i> </a> </div> + </div> + <div class="col-md-3"> + <div class="bg-green small-box"> + <div class="inner"> + <h4>Rooms</h4> - {% comment %} - <div class="bg-yellow small-box"> - <div class="inner"> - <h4>Equipment in rooms</h4> + <p> </p> + </div> + <div class="icon"> + <i class="ion ion-android-home"></i> + </div> + <a href="{% url 'web.views.equipment_and_rooms.rooms' %}" class="small-box-footer"> + Manage <i class="fa fa-arrow-circle-right"></i> + </a> + </div> - <p> </p> - </div> - <div class="icon"> - <i class="ion ion-medkit"></i> - </div> - <a href="#" class="small-box-footer"> - Edit <i class="fa fa-arrow-circle-right"></i> - </a> - </div> - {% endcomment %} + <div class="bg-green small-box"> + <div class="inner"> + <h4>Equipment in rooms</h4> + + <p> </p> + </div> + <div class="icon"> + <i class="ion ion-medkit"></i> + </div> + <a href="{% url 'web.views.equipment' %}" class="small-box-footer"> + Edit <i class="fa fa-arrow-circle-right"></i> + </a> + </div> </div> {% comment %} diff --git a/smash/web/templates/equipment_and_rooms/rooms/add.html b/smash/web/templates/equipment_and_rooms/rooms/add.html new file mode 100644 index 0000000000000000000000000000000000000000..bd8406ec4e5410bda8da120ea543924eff943097 --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/rooms/add.html @@ -0,0 +1,57 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block page_header %}New room{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Add new room{% endblock %} + +{% block breadcrumb %} + {% include "equipment_and_rooms/rooms/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + <div class="box box-info"> + <div class="box-header with-border"> + <a href="{% url 'web.views.equipment_and_rooms.rooms' %}" class="btn btn-block btn-default">Go back (without changes)</a> + </div> + + <form method="post" action="" class="form-horizontal"> + {% csrf_token %} + + <div class="box-body"> + <div class="col-sm-6"> + {% for field in form %} + <div class="form-group {% if field.errors %}has-error{% endif %}"> + <label for="{{ field.id_for_label }}" class="col-sm-4 control-label"> + {{ field.label }} + </label> + + <div class="col-sm-8"> + {{ field|add_class:'form-control' }} + </div> + + {% if field.errors %} + <span class="help-block"> + {{ field.errors }} + </span> + {% endif %} + </div> + {% endfor %} + </div> + </div><!-- /.box-body --> + + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-success">Add</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.equipment_and_rooms.rooms' %}" class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + {% endblock %} diff --git a/smash/web/templates/equipment_and_rooms/rooms/breadcrumb.html b/smash/web/templates/equipment_and_rooms/rooms/breadcrumb.html new file mode 100644 index 0000000000000000000000000000000000000000..b2ecb34d76b1b2c14a78762297c46cbf855cf5cd --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/rooms/breadcrumb.html @@ -0,0 +1,3 @@ +<li><a href="{% url 'web.views.appointments' %}"><i class="fa fa-dashboard"></i> Dashboard</a></li> +<li><a href="{% url 'web.views.equipment_and_rooms' %}">Equipment and rooms</a></li> +<li class="active"><a href="{% url 'web.views.equipment_and_rooms.rooms' %}">Rooms</a></li> diff --git a/smash/web/templates/equipment_and_rooms/rooms/edit.html b/smash/web/templates/equipment_and_rooms/rooms/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..130720fc62efd99caadc2e5a2477a761a9f143dc --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/rooms/edit.html @@ -0,0 +1,57 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block page_header %}Edit room{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Edit room{% endblock %} + +{% block breadcrumb %} + {% include "equipment_and_rooms/rooms/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + <div class="box box-info"> + <div class="box-header with-border"> + <a href="{% url 'web.views.equipment_and_rooms.rooms' %}" class="btn btn-block btn-default">Go back (without changes)</a> + </div> + + <form method="post" action="" class="form-horizontal"> + {% csrf_token %} + + <div class="box-body"> + <div class="col-sm-6"> + {% for field in form %} + <div class="form-group {% if field.errors %}has-error{% endif %}"> + <label for="{# TODO #}" class="col-sm-4 control-label"> + {{ field.label }} + </label> + + <div class="col-sm-8"> + {{ field|add_class:'form-control' }} + </div> + + {% if field.errors %} + <span class="help-block"> + {{ field.errors }} + </span> + {% endif %} + </div> + {% endfor %} + </div> + </div><!-- /.box-body --> + + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-success">Save</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.equipment_and_rooms.rooms' %}" class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + {% endblock %} diff --git a/smash/web/templates/equipment_and_rooms/rooms/index.html b/smash/web/templates/equipment_and_rooms/rooms/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c5d34b728335f9d22e64f83474116d62ab101022 --- /dev/null +++ b/smash/web/templates/equipment_and_rooms/rooms/index.html @@ -0,0 +1,81 @@ +{% extends "_base.html" %} +{% load static %} + +{% block styles %} + {{ block.super }} + <!-- DataTables --> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> +{% endblock styles %} + +{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block page_header %}Rooms{% endblock page_header %} +{% block page_description %}management{% endblock page_description %} + +{% block breadcrumb %} + {% include "equipment_and_rooms/rooms/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} +<div> + <a href="{% url 'web.views.equipment_and_rooms.rooms_add' %}" class="btn btn-app"> + <i class="fa fa-plus"></i> + Add new room</a> +</div> + +<div class="box-body"> + {% if rooms_list %} + <table id="table" class="table table-bordered table-striped"> + <thead> + <tr> + <th>No.</th> + <th>City</th> + <th>Address</th> + <th>Owner</th> + <th>Details</th> + <th>Remove</th> + </tr> + </thead> + <tbody> + {% for room in rooms_list %} + <tr> + <td>{{ forloop.counter }}</td> + <td>{{ room.city }}</td> + <td>{{ room.address }}</td> + <td>{{ room.owner }}</td> + <td> + <a href="{% url 'web.views.equipment_and_rooms.rooms_edit' room.id %}" type="button" + class="btn btn-block btn-default">Details</a></td> + </td> + <td> + <a href="{% url 'web.views.equipment_and_rooms.rooms_delete' room.id %}" type="button" + class="btn btn-block btn-danger">Remove</a></td> + </td> + </tr> + {% endfor %} + + </tbody> + </table> + {% else %} + <p>No rooms found.</p> + {% endif %} +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script> + + <script> + $(function () { + $('#table').DataTable({ + "paging": true, + "lengthChange": false, + "searching": true, + "ordering": true, + "info": true, + "autoWidth": false + }); + }); + </script> +{% endblock scripts %} diff --git a/smash/web/templates/sidebar.html b/smash/web/templates/sidebar.html index 82a59e6aa4a8acfab2bc5cb6d9bd86af12ce506e..9a811637183b6d7b95a6446b249fe91cfba9419a 100644 --- a/smash/web/templates/sidebar.html +++ b/smash/web/templates/sidebar.html @@ -38,8 +38,10 @@ </span> </a> <ul class="treeview-menu"> - <li><a href="{% url 'web.views.kit_requests' %}">Kit requests</a></li> + <li><a href="{% url 'web.views.equipment' %}">Equipment items</a></li> <li><a href="{% url 'web.views.equipment_and_rooms.flying_teams' %}">Flying teams</a></li> + <li><a href="{% url 'web.views.kit_requests' %}">Kit requests</a></li> + <li><a href="{% url 'web.views.equipment_and_rooms.rooms' %}">Rooms</a></li> </ul> </li> diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py index eb9e87dd7ddca95144ef58a1337b67f141417dda..0bebd3af31ceefe79b5dcf8ee4aba7f230175144 100644 --- a/smash/web/tests/functions.py +++ b/smash/web/tests/functions.py @@ -6,7 +6,7 @@ from django.contrib.auth.models import User from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, \ Language, ContactAttempt, FlyingTeam, Availability, Subject, Study, StudyColumns, StudyNotificationParameters, \ - VoucherType, VoucherTypePrice, Voucher, WorkerStudyRole + VoucherType, VoucherTypePrice, Voucher, Room, Item, WorkerStudyRole from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \ SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, CONTACT_TYPES_PHONE, \ MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW, GLOBAL_STUDY_ID @@ -278,6 +278,23 @@ def create_flying_team(place=None): return result +def create_item(name='Test item', is_fixed=False, disposable=False): + item = Item(name=name, is_fixed=is_fixed, disposable=disposable) + item.save() + return item + + +def create_room(owner='Test owner', city='Test city', + address='Test address', equipment=[], + floor=1, is_vehicle=False, room_number=1): + room = Room(owner=owner, city=city, address=address, + floor=floor, is_vehicle=is_vehicle, room_number=room_number) + room.save() + room.equipment = equipment # Cannot be made in constructor/with single save + room.save() + return room + + def create_language(name="French", locale="fr_FR"): language = Language(name=name, locale=locale) language.save() diff --git a/smash/web/tests/view/test_equipments.py b/smash/web/tests/view/test_equipments.py new file mode 100644 index 0000000000000000000000000000000000000000..99e312a8c85d747a66ca3a90396f1c9ece48b9f5 --- /dev/null +++ b/smash/web/tests/view/test_equipments.py @@ -0,0 +1,75 @@ +import logging + +from django.urls import reverse + +from web.tests.functions import create_item +from web.models import Item +from web.tests import LoggedInTestCase + +logger = logging.getLogger(__name__) + + +class EquipmentTests(LoggedInTestCase): + def test_equipment_requests(self): + pages = [ + 'web.views.equipment', + 'web.views.equipment_add', + ] + + for page in pages: + response = self.client.get(reverse(page)) + self.assertEqual(response.status_code, 200) + + def test_equipment_edit_request(self): + item = create_item() + page = reverse('web.views.equipment_edit', + kwargs={'equipment_id': str(item.id)}) + response = self.client.get(page) + self.assertEqual(response.status_code, 200) + + def test_equipment_delete_request(self): + item = create_item() + page = reverse('web.views.equipment_delete', + kwargs={'equipment_id': str(item.id)}) + response = self.client.get(page) + self.assertEqual(response.status_code, 302) + + def test_equipment_add(self): + page = reverse('web.views.equipment_add') + data = { + 'name': 'The mysterious potion', + 'disposable': True, + 'is_fixed': False, + } + response = self.client.post(page, data) + self.assertEqual(response.status_code, 302) + + freshly_created = Item.objects.filter(name=data['name']) + self.assertEqual(len(freshly_created), 1) + + def test_equipment_edit(self): + item = create_item() + page = reverse('web.views.equipment_edit', + kwargs={'equipment_id': str(item.id)}) + data = { + 'name': 'Even more mysterious potion', + 'disposable': True, + 'is_fixed': True, + } + response = self.client.post(page, data) + self.assertEqual(response.status_code, 302) + + freshly_edited = Item.objects.get(id=item.id) + for key in data: + self.assertEqual(getattr(freshly_edited, key, ''), data[key]) + + def test_equipment_delete(self): + item = create_item() + page = reverse('web.views.equipment_delete', + kwargs={'equipment_id': str(item.id)}) + + response = self.client.get(page) + self.assertEqual(response.status_code, 302) + + freshly_deleted = Item.objects.filter(id=item.id) + self.assertEqual(len(freshly_deleted), 0) diff --git a/smash/web/tests/view/test_rooms.py b/smash/web/tests/view/test_rooms.py new file mode 100644 index 0000000000000000000000000000000000000000..ecf1161677c0a104d9861bd356c2c96416b81bf0 --- /dev/null +++ b/smash/web/tests/view/test_rooms.py @@ -0,0 +1,83 @@ +import logging + +from django.urls import reverse + +from web.tests.functions import create_room, create_item +from web.models import Item, Room +from web.tests import LoggedInTestCase + +logger = logging.getLogger(__name__) + + +class RoomsTests(LoggedInTestCase): + def test_rooms_requests(self): + pages = [ + 'web.views.equipment_and_rooms.rooms', + 'web.views.equipment_and_rooms.rooms_add', + ] + + for page in pages: + response = self.client.get(reverse(page)) + self.assertEqual(response.status_code, 200) + + def test_rooms_edit_request(self): + room = create_room() + page = reverse('web.views.equipment_and_rooms.rooms_edit', + kwargs={'room_id': str(room.id)}) + response = self.client.get(page) + self.assertEqual(response.status_code, 200) + + def test_rooms_delete_request(self): + room = create_room() + page = reverse('web.views.equipment_and_rooms.rooms_delete', + kwargs={'room_id': str(room.id)}) + response = self.client.get(page) + self.assertEqual(response.status_code, 302) + + def test_rooms_add(self): + page = reverse('web.views.equipment_and_rooms.rooms_add') + item = create_item() + data = { + 'city': 'Belval', + 'address': 'Av. du Swing 123456', + 'room_number': 123, + 'floor': 456, + 'is_vehicle': False, + 'owner': 'No one', + 'equipment': [item.id] + } + response = self.client.post(page, data) + self.assertEqual(response.status_code, 302) + + freshly_created = Room.objects.filter(address=data['address']) + self.assertEqual(len(freshly_created), 1) + + def test_rooms_edit(self): + room = create_room() + page = reverse('web.views.equipment_and_rooms.rooms_edit', + kwargs={'room_id': str(room.id)}) + data = { + 'city': 'Belval2', + 'address': 'Av. du Swing ABCDE', + 'room_number': 5, + 'floor': 8, + 'is_vehicle': True, + 'owner': 'Everyone', + } + response = self.client.post(page, data) + self.assertEqual(response.status_code, 302) + + freshly_edited = Room.objects.get(id=room.id) + for key in data: + self.assertEqual(getattr(freshly_edited, key, ''), data[key]) + + def test_rooms_delete(self): + room = create_room() + page = reverse('web.views.equipment_and_rooms.rooms_delete', + kwargs={'room_id': str(room.id)}) + + response = self.client.get(page) + self.assertEqual(response.status_code, 302) + + freshly_deleted = Room.objects.filter(id=room.id) + self.assertEqual(len(freshly_deleted), 0) diff --git a/smash/web/urls.py b/smash/web/urls.py index baa812987f233ae90767d6f5c139e7b33c2a49ff..9f26924b56f23a6d15bb98012914a9d5b686586e 100644 --- a/smash/web/urls.py +++ b/smash/web/urls.py @@ -124,17 +124,28 @@ urlpatterns = [ # EQUIPMENT # #################### - url(r'^equipment_and_rooms$', views.equipment.equipment_and_rooms, name='web.views.equipment_and_rooms'), - url(r'^equipment_and_rooms/equipment_def$', views.equipment.equipment_def, name='web.views.equipment_def'), + url(r'^equipment_and_rooms$', views.equipment_and_rooms.equipment_and_rooms, name='web.views.equipment_and_rooms'), + + url(r'^equipment_and_rooms/equipment$', views.equipment.equipment, name='web.views.equipment'), + url(r'^equipment_and_rooms/equipment/add$', views.equipment.equipment_add, name='web.views.equipment_add'), + url(r'^equipment_and_rooms/equipment/edit/(?P<equipment_id>\d+)$', views.equipment.equipment_edit, name='web.views.equipment_edit'), + url(r'^equipment_and_rooms/equipment/delete/(?P<equipment_id>\d+)$', views.equipment.equipment_delete, name='web.views.equipment_delete'), + url(r'^equipment_and_rooms/kit_requests$', views.kit.kit_requests, name='web.views.kit_requests'), url(r'^equipment_and_rooms/kit_requests/(?P<start_date>[\w-]+)/$', views.kit.kit_requests_send_mail, name='web.views.kit_requests_send_mail'), url(r'^equipment_and_rooms/kit_requests/(?P<start_date>[\w-]+)/(?P<end_date>[\w-]+)/$', views.kit.kit_requests_send_mail, name='web.views.kit_requests_send_mail'), + url(r'^equipment_and_rooms/flying_teams$', views.flying_teams.flying_teams, name='web.views.equipment_and_rooms.flying_teams'), url(r'^equipment_and_rooms/flying_teams/add$', views.flying_teams.flying_teams_add, name='web.views.equipment_and_rooms.flying_teams_add'), url(r'^equipment_and_rooms/flying_teams/edit/(?P<flying_team_id>\d+)$', views.flying_teams.flying_teams_edit, name='web.views.equipment_and_rooms.flying_teams_edit'), + url(r'^equipment_and_rooms/rooms$', views.rooms.rooms, name='web.views.equipment_and_rooms.rooms'), + url(r'^equipment_and_rooms/rooms/add$', views.rooms.rooms_add, name='web.views.equipment_and_rooms.rooms_add'), + url(r'^equipment_and_rooms/rooms/edit/(?P<room_id>\d+)$', views.rooms.rooms_edit, name='web.views.equipment_and_rooms.rooms_edit'), + url(r'^equipment_and_rooms/rooms/delete/(?P<room_id>\d+)$', views.rooms.rooms_delete, name='web.views.equipment_and_rooms.rooms_delete'), + #################### # MAIL # #################### diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py index 6ca5ef439294203655a29509a9fc29cb49c64e8f..95ce4b72e2088348eeb767ead94b273aef365673 100644 --- a/smash/web/views/__init__.py +++ b/smash/web/views/__init__.py @@ -70,6 +70,7 @@ import visit import worker import subject import equipment +import equipment_and_rooms import flying_teams import kit import mails @@ -82,4 +83,5 @@ import voucher import voucher_type import voucher_type_price import redcap +import rooms import uploaded_files diff --git a/smash/web/views/equipment.py b/smash/web/views/equipment.py index 579f8b98ee33fa02de552d22c4c96fd3a05f3dba..c7cf21bec25b7a95f521b71f58eff1df4334a0c3 100644 --- a/smash/web/views/equipment.py +++ b/smash/web/views/equipment.py @@ -1,18 +1,51 @@ # coding=utf-8 -from django.shortcuts import redirect +from django.shortcuts import redirect, get_object_or_404 +from django.contrib.auth.decorators import login_required from . import wrap_response from ..models import Item +from ..forms.forms import ItemForm -def equipment_def(request): +def equipment(request): equipment_list = Item.objects.order_by('-name') context = { 'equipment_list': equipment_list } - return wrap_response(request, "eqdef/index.html", context) + return wrap_response(request, "equipment_and_rooms/equipment/index.html", context) -def equipment_and_rooms(request): - return wrap_response(request, "equipment_and_rooms/index.html", {}) +@login_required +def equipment_add(request): + if request.method == 'POST': + form = ItemForm(request.POST) + if form.is_valid(): + form.save() + return redirect('web.views.equipment') + else: + form = ItemForm() + + return wrap_response(request, 'equipment_and_rooms/equipment/add.html', {'form': form}) + + +@login_required +def equipment_edit(request, equipment_id): + the_item = get_object_or_404(Item, id=equipment_id) + if request.method == 'POST': + form = ItemForm(request.POST, instance=the_item) + if form.is_valid(): + form.save() + return redirect('web.views.equipment') + else: + form = ItemForm(instance=the_item) + + return wrap_response(request, 'equipment_and_rooms/equipment/edit.html', {'form': form}) + + +@login_required +def equipment_delete(request, equipment_id): + the_item = get_object_or_404(Item, id=equipment_id) + the_item.delete() + + return redirect('web.views.equipment') diff --git a/smash/web/views/equipment_and_rooms.py b/smash/web/views/equipment_and_rooms.py new file mode 100644 index 0000000000000000000000000000000000000000..0d8092e6b2cf5d5c7b194030461dff7e636813cd --- /dev/null +++ b/smash/web/views/equipment_and_rooms.py @@ -0,0 +1,5 @@ +from . import wrap_response + + +def equipment_and_rooms(request): + return wrap_response(request, "equipment_and_rooms/index.html", {}) diff --git a/smash/web/views/flying_teams.py b/smash/web/views/flying_teams.py index 42d1400b1a8b7c11d074d98dd3a09b062d8b3d60..8a58cbf768abd76bbac00bff809541847974bbf2 100644 --- a/smash/web/views/flying_teams.py +++ b/smash/web/views/flying_teams.py @@ -1,5 +1,6 @@ # coding=utf-8 from django.shortcuts import redirect, get_object_or_404 +from django.contrib.auth.decorators import login_required from . import wrap_response from ..models import FlyingTeam @@ -16,7 +17,7 @@ def flying_teams(request): "equipment_and_rooms/flying_teams/index.html", context) - +@login_required def flying_teams_add(request): if request.method == 'POST': form = FlyingTeamAddForm(request.POST) @@ -29,6 +30,7 @@ def flying_teams_add(request): return wrap_response(request, 'equipment_and_rooms/flying_teams/add.html', {'form': form}) +@login_required def flying_teams_edit(request, flying_team_id): the_flying_team = get_object_or_404(FlyingTeam, id=flying_team_id) if request.method == 'POST': diff --git a/smash/web/views/rooms.py b/smash/web/views/rooms.py new file mode 100644 index 0000000000000000000000000000000000000000..124ff63bc68698fd9891b2c6ea31ca2f0b65e8d6 --- /dev/null +++ b/smash/web/views/rooms.py @@ -0,0 +1,52 @@ +# coding=utf-8 +from django.shortcuts import redirect, get_object_or_404 +from django.contrib.auth.decorators import login_required + +from . import wrap_response +from ..models import Room +from ..forms.forms import RoomForm + + +def rooms(request): + rooms_list = Room.objects.order_by('-city') + context = { + 'rooms_list': rooms_list + } + + return wrap_response(request, + "equipment_and_rooms/rooms/index.html", + context) + +@login_required +def rooms_add(request): + if request.method == 'POST': + form = RoomForm(request.POST) + if form.is_valid(): + form.save() + return redirect('web.views.equipment_and_rooms.rooms') + else: + form = RoomForm() + + return wrap_response(request, 'equipment_and_rooms/rooms/add.html', {'form': form}) + + +@login_required +def rooms_edit(request, room_id): + the_room = get_object_or_404(Room, id=room_id) + if request.method == 'POST': + form = RoomForm(request.POST, instance=the_room) + if form.is_valid(): + form.save() + return redirect('web.views.equipment_and_rooms.rooms') + else: + form = RoomForm(instance=the_room) + + return wrap_response(request, 'equipment_and_rooms/rooms/edit.html', {'form': form}) + + +@login_required +def rooms_delete(request, room_id): + the_room = get_object_or_404(Room, id=room_id) + the_room.delete() + + return redirect('web.views.equipment_and_rooms.rooms')