8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-25 22:22:26 +00:00

Create dormitory with buildings

This commit is contained in:
detraz 2019-02-18 21:11:51 +01:00
parent 565f57967c
commit 8d799ed92d
10 changed files with 313 additions and 6 deletions

View file

@ -194,12 +194,17 @@ class SortTable:
} }
TOPOLOGIE_INDEX_ROOM = { TOPOLOGIE_INDEX_ROOM = {
'room_name': ['name'], 'room_name': ['name'],
'default': ['name'] 'building_name': ['building__name'],
'default': ['building__name', 'name']
} }
TOPOLOGIE_INDEX_BUILDING = { TOPOLOGIE_INDEX_BUILDING = {
'building_name': ['name'], 'building_name': ['name'],
'default': ['name'] 'default': ['name']
} }
TOPOLOGIE_INDEX_DORMITORY = {
'dormitory_name': ['name'],
'default': ['name']
}
TOPOLOGIE_INDEX_BORNE = { TOPOLOGIE_INDEX_BORNE = {
'ap_name': ['interface__domain__name'], 'ap_name': ['interface__domain__name'],
'ap_ip': ['interface__ipv4__ipv4'], 'ap_ip': ['interface__ipv4__ipv4'],

View file

@ -54,6 +54,7 @@ from .models import (
AccessPoint, AccessPoint,
SwitchBay, SwitchBay,
Building, Building,
Dormitory,
PortProfile, PortProfile,
ModuleSwitch, ModuleSwitch,
ModuleOnSwitch, ModuleOnSwitch,
@ -259,6 +260,18 @@ class EditBuildingForm(FormRevMixin, ModelForm):
prefix = kwargs.pop('prefix', self.Meta.model.__name__) prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(EditBuildingForm, self).__init__(*args, prefix=prefix, **kwargs) super(EditBuildingForm, self).__init__(*args, prefix=prefix, **kwargs)
class EditDormitoryForm(FormRevMixin, ModelForm):
"""Permet d'éditer la residence"""
class Meta:
model = Dormitory
fields = '__all__'
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(EditDormitoryForm, self).__init__(*args, prefix=prefix, **kwargs)
class EditPortProfileForm(FormRevMixin, ModelForm): class EditPortProfileForm(FormRevMixin, ModelForm):
"""Form to edit a port profile""" """Form to edit a port profile"""
class Meta: class Meta:

View file

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-02-18 16:43
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import re2o.mixins
class Migration(migrations.Migration):
dependencies = [
('topologie', '0069_auto_20190108_1439'),
]
def create_dormitory(apps, schema_editor):
db_alias = schema_editor.connection.alias
dormitory = apps.get_model("topologie", "Dormitory")
building = apps.get_model("topologie", "Building")
dorm = dormitory.objects.using(db_alias).create(name="Residence")
building.objects.using(db_alias).update(dormitory=dorm)
def delete_dormitory(apps, schema_editor):
pass
operations = [
migrations.CreateModel(
name='Dormitory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
],
options={
'verbose_name': 'dormitory',
'permissions': (('view_dormitory', 'Can view a dormitory object'),),
'verbose_name_plural': 'dormitories',
},
bases=(re2o.mixins.AclMixin, re2o.mixins.RevMixin, models.Model),
),
migrations.AddField(
model_name='building',
name='dormitory',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='topologie.Dormitory'),
preserve_default=False,
),
migrations.RunPython(create_dormitory, delete_dormitory)
]

View file

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2019-02-18 18:36
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('topologie', '0070_auto_20190218_1743'),
]
def transfer_room(apps, schema_editor):
db_alias = schema_editor.connection.alias
room_obj = apps.get_model("topologie", "Room")
building_obj = apps.get_model("topologie", "Building")
dorm_obj = apps.get_model("topologie", "Dormitory")
dorm = dorm_obj.objects.using(db_alias).first()
for room in room_obj.objects.using(db_alias).all():
building, created = building_obj.objects.using(db_alias).get_or_create(name=room.name[0].upper(), dormitory=dorm)
room.building = building
room.name = room.name[1:]
room.save()
def untransfer_room(apps, schema_editor):
pass
operations = [
migrations.AlterField(
model_name='room',
name='name',
field=models.CharField(max_length=255),
),
migrations.AddField(
model_name='room',
name='building',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='topologie.Building'),
),
migrations.AlterUniqueTogether(
name='room',
unique_together=set([('name', 'building')]),
),
migrations.AlterField(
model_name='building',
name='dormitory',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='topologie.Dormitory'),
),
migrations.RunPython(transfer_room, untransfer_room),
migrations.AlterField(
model_name='room',
name='building',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='topologie.Building'),
)
]

View file

@ -516,10 +516,36 @@ class SwitchBay(AclMixin, RevMixin, models.Model):
return self.name return self.name
class Dormitory(AclMixin, RevMixin, models.Model):
"""Une résidence universitaire
A residence"""
name = models.CharField(max_length=255)
class Meta:
permissions = (
("view_dormitory", _("Can view a dormitory object")),
)
verbose_name = _("dormitory")
verbose_name_plural = _("dormitories")
def all_ap_in(self):
"""Returns all ap of the dorms"""
return AccessPoint.all_ap_in(self.building_set.all())
def __str__(self):
return self.name
class Building(AclMixin, RevMixin, models.Model): class Building(AclMixin, RevMixin, models.Model):
"""Un batiment""" """Un batiment"""
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
dormitory = models.ForeignKey(
'Dormitory',
on_delete=models.PROTECT,
)
class Meta: class Meta:
permissions = ( permissions = (
@ -533,6 +559,9 @@ class Building(AclMixin, RevMixin, models.Model):
return AccessPoint.all_ap_in(self) return AccessPoint.all_ap_in(self)
def __str__(self): def __str__(self):
if Dormitory.objects.count() > 1:
return self.dormitory.name + " : " + self.name
else:
return self.name return self.name
@ -703,19 +732,27 @@ class Port(AclMixin, RevMixin, models.Model):
class Room(AclMixin, RevMixin, models.Model): class Room(AclMixin, RevMixin, models.Model):
"""Une chambre/local contenant une prise murale""" """Une chambre/local contenant une prise murale"""
name = models.CharField(max_length=255, unique=True) name = models.CharField(max_length=255)
details = models.CharField(max_length=255, blank=True) details = models.CharField(max_length=255, blank=True)
building = models.ForeignKey(
'Building',
on_delete=models.PROTECT,
)
class Meta: class Meta:
ordering = ['name'] ordering = ['building__name']
permissions = ( permissions = (
("view_room", _("Can view a room object")), ("view_room", _("Can view a room object")),
) )
verbose_name = _("room") verbose_name = _("room")
verbose_name_plural = _("rooms") verbose_name_plural = _("rooms")
unique_together = ('name', 'building')
def __str__(self): def __str__(self):
return self.name if Dormitory.objects.count() > 1:
return self.building.dormitory.name + " : " + self.building.name + self.name
else:
return self.building.name + self.name
class PortProfile(AclMixin, RevMixin, models.Model): class PortProfile(AclMixin, RevMixin, models.Model):

View file

@ -34,6 +34,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<thead> <thead>
<tr> <tr>
{% trans "Room" as tr_room %} {% trans "Room" as tr_room %}
{% trans "Building" as tr_building %}
<th>{% include 'buttons/sort.html' with prefix='building' col='name' text=tr_building %}</th>
<th>{% include 'buttons/sort.html' with prefix='room' col='name' text=tr_room %}</th> <th>{% include 'buttons/sort.html' with prefix='room' col='name' text=tr_room %}</th>
<th>{% trans "Details" %}</th> <th>{% trans "Details" %}</th>
<th></th> <th></th>
@ -41,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</thead> </thead>
{% for room in room_list %} {% for room in room_list %}
<tr> <tr>
<td>{{ room.building }}</td>
<td>{{ room.name }}</td> <td>{{ room.name }}</td>
<td>{{ room.details }}</td> <td>{{ room.details }}</td>
<td class="text-right"> <td class="text-right">

View file

@ -0,0 +1,62 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load acl %}
{% load logs_extra %}
{% load i18n %}
{% if dormitory_list.paginator %}
{% include 'pagination.html' with list=dormitory_list %}
{% endif %}
<table class="table table-striped">
<thead>
<tr>
{% trans "Dormitory" as tr_dormitory %}
<th>{% include 'buttons/sort.html' with prefix='dormitory' col='name' text=tr_dormitory %}</th>
<th>{% trans "Building" %}</th>
<th></th>
</tr>
</thead>
{% for dormitory in dormitory_list %}
<tr>
<td>{{ dormitory.name }}</td>
<td>{% for building in dormitory.building_set.all %} {{ building }} {% endfor %}</td>
<td class="text-right">
{% can_edit dormitory %}
{% include 'buttons/edit.html' with href='topologie:edit-dormitory' id=dormitory.id %}
{% acl_end %}
{% history_button dormitory %}
{% can_delete dormitory %}
{% include 'buttons/suppr.html' with href='topologie:del-dormitory' id=dormitory.id %}
{% acl_end %}
</td>
</tr>
{% endfor %}
</table>
{% if dormitory_list.paginator %}
{% include 'pagination.html' with list=dormitory_list %}
{% endif %}

View file

@ -55,5 +55,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<hr> <hr>
{% acl_end %} {% acl_end %}
{% include 'topologie/aff_building.html' with building_list=building_list %} {% include 'topologie/aff_building.html' with building_list=building_list %}
<h2>{% trans "Dormitories" %}</h2>
{% can_create Dormitory %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:new-dormitory' %}">
<i class="fa fa-plus"></i>{% trans " Add a dormitory" %}
</a>
<hr>
{% acl_end %}
{% include 'topologie/aff_dormitory.html' with dormitory_list=dormitory_list %}
{% endblock %} {% endblock %}

View file

@ -108,6 +108,15 @@ urlpatterns = [
url(r'^del_building/(?P<buildingid>[0-9]+)$', url(r'^del_building/(?P<buildingid>[0-9]+)$',
views.del_building, views.del_building,
name='del-building'), name='del-building'),
url(r'^new_dormitory/$',
views.new_dormitory,
name='new-dormitory'),
url(r'^edit_dormitory/(?P<dormitoryid>[0-9]+)$',
views.edit_dormitory,
name='edit-dormitory'),
url(r'^del_dormitory/(?P<dormitoryid>[0-9]+)$',
views.del_dormitory,
name='del-dormitory'),
url(r'^index_port_profile/$', url(r'^index_port_profile/$',
views.index_port_profile, views.index_port_profile,
name='index-port-profile'), name='index-port-profile'),

View file

@ -84,6 +84,7 @@ from .models import (
AccessPoint, AccessPoint,
SwitchBay, SwitchBay,
Building, Building,
Dormitory,
Server, Server,
PortProfile, PortProfile,
ModuleSwitch, ModuleSwitch,
@ -103,6 +104,7 @@ from .forms import (
EditAccessPointForm, EditAccessPointForm,
EditSwitchBayForm, EditSwitchBayForm,
EditBuildingForm, EditBuildingForm,
EditDormitoryForm,
EditPortProfileForm, EditPortProfileForm,
EditModuleForm, EditModuleForm,
EditSwitchModuleForm, EditSwitchModuleForm,
@ -254,7 +256,7 @@ def index_ap(request):
@login_required @login_required
@can_view_all(Stack, Building, SwitchBay) @can_view_all(Stack, Building, Dormitory, SwitchBay)
def index_physical_grouping(request): def index_physical_grouping(request):
"""Affichage de la liste des stacks (affiche l'ensemble des switches)""" """Affichage de la liste des stacks (affiche l'ensemble des switches)"""
stack_list = (Stack.objects stack_list = (Stack.objects
@ -262,6 +264,7 @@ def index_physical_grouping(request):
'switch_set__interface_set__domain__extension' 'switch_set__interface_set__domain__extension'
)) ))
building_list = Building.objects.all() building_list = Building.objects.all()
dormitory_list = Dormitory.objects.all()
switch_bay_list = SwitchBay.objects.select_related('building') switch_bay_list = SwitchBay.objects.select_related('building')
stack_list = SortTable.sort( stack_list = SortTable.sort(
stack_list, stack_list,
@ -275,6 +278,12 @@ def index_physical_grouping(request):
request.GET.get('order'), request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_BUILDING SortTable.TOPOLOGIE_INDEX_BUILDING
) )
dormitory_list = SortTable.sort(
dormitory_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.TOPOLOGIE_INDEX_DORMITORY
)
switch_bay_list = SortTable.sort( switch_bay_list = SortTable.sort(
switch_bay_list, switch_bay_list,
request.GET.get('col'), request.GET.get('col'),
@ -288,6 +297,7 @@ def index_physical_grouping(request):
'stack_list': stack_list, 'stack_list': stack_list,
'switch_bay_list': switch_bay_list, 'switch_bay_list': switch_bay_list,
'building_list': building_list, 'building_list': building_list,
'dormitory_list': dormitory_list,
} }
) )
@ -956,6 +966,61 @@ def del_building(request, building, **_kwargs):
) )
@login_required
@can_create(Dormitory)
def new_dormitory(request):
"""Nouvelle residence"""
dormitory = EditDormitoryForm(request.POST or None)
if dormitory.is_valid():
dormitory.save()
messages.success(request, _("The dormitory was created."))
return redirect(reverse('topologie:index-physical-grouping'))
return form(
{'topoform': dormitory, 'action_name': _("Create")},
'topologie/topo.html',
request
)
@login_required
@can_edit(Dormitory)
def edit_dormitory(request, dormitory, **_kwargs):
""" Edition d'une residence"""
dormitory = EditDormitoryForm(request.POST or None, instance=dormitory)
if dormitory.is_valid():
if dormitory.changed_data:
dormitory.save()
messages.success(request, _("The dormitory was edited."))
return redirect(reverse('topologie:index-physical-grouping'))
return form(
{'topoform': dormitory, 'action_name': _("Edit")},
'topologie/topo.html',
request
)
@login_required
@can_delete(Dormitory)
def del_dormitory(request, dormitory, **_kwargs):
""" Suppression d'une residence"""
if request.method == "POST":
try:
dormitory.delete()
messages.success(request, _("The dormitory was deleted."))
except ProtectedError:
messages.error(
request,
(_("The dormitory %s is used by another object, impossible"
" to delete it.") % dormitory)
)
return redirect(reverse('topologie:index-physical-grouping'))
return form(
{'objet': dormitory, 'objet_name': _("Dormitory")},
'topologie/delete.html',
request
)
@login_required @login_required
@can_create(ConstructorSwitch) @can_create(ConstructorSwitch)
def new_constructor_switch(request): def new_constructor_switch(request):