Refactoring to konova
This commit is contained in:
1 parent
a5e8bcfa8c
commit
4084373e2b
60 files changed
+103
-17901
No files matched your search
+15
-59
@@ -5,14 +5,13 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 17.11.20
|
Created on: 17.11.20
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.contrib.gis.db import models
|
from django.contrib.gis.db import models
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
from compensation.settings import COMPENSATION_IDENTIFIER_LENGTH, COMPENSATION_IDENTIFIER_TEMPLATE
|
from compensation.settings import COMPENSATION_IDENTIFIER_LENGTH, COMPENSATION_IDENTIFIER_TEMPLATE
|
||||||
from konova.models import BaseObject, BaseResource
|
from konova.models import BaseObject, BaseResource, Geometry
|
||||||
from konova.utils.generators import generate_random_string
|
from konova.utils.generators import generate_random_string
|
||||||
from process.models import Process
|
from organisation.models import Organisation
|
||||||
|
|
||||||
|
|
||||||
class CompensationControl(BaseResource):
|
class CompensationControl(BaseResource):
|
||||||
@@ -22,7 +21,7 @@ class CompensationControl(BaseResource):
|
|||||||
deadline = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True)
|
deadline = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
type = models.CharField(max_length=500, null=True, blank=True)
|
type = models.CharField(max_length=500, null=True, blank=True)
|
||||||
expected_result = models.CharField(max_length=500, null=True, blank=True, help_text="The expected outcome, that needs to be controlled")
|
expected_result = models.CharField(max_length=500, null=True, blank=True, help_text="The expected outcome, that needs to be controlled")
|
||||||
by_authority = models.CharField(max_length=500, null=True, blank=True)
|
by_authority = models.ForeignKey(Organisation, null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
comment = models.TextField()
|
comment = models.TextField()
|
||||||
|
|
||||||
|
|
||||||
@@ -31,8 +30,7 @@ class CompensationState(models.Model):
|
|||||||
Compensations must define the state of an area before and after the compensation.
|
Compensations must define the state of an area before and after the compensation.
|
||||||
"""
|
"""
|
||||||
biotope_type = models.CharField(max_length=500, null=True, blank=True)
|
biotope_type = models.CharField(max_length=500, null=True, blank=True)
|
||||||
amount = models.FloatField()
|
surface = models.FloatField()
|
||||||
unit = models.CharField(max_length=100, null=True, blank=True)
|
|
||||||
|
|
||||||
|
|
||||||
class CompensationAction(BaseResource):
|
class CompensationAction(BaseResource):
|
||||||
@@ -50,22 +48,21 @@ class Compensation(BaseObject):
|
|||||||
The compensation holds information about which actions have to be performed until which date, who is in charge
|
The compensation holds information about which actions have to be performed until which date, who is in charge
|
||||||
of this, which legal authority is the point of contact, and so on.
|
of this, which legal authority is the point of contact, and so on.
|
||||||
"""
|
"""
|
||||||
is_old_law = models.BooleanField(default=False)
|
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True)
|
||||||
type = models.CharField(max_length=500, null=True, blank=True)
|
conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True)
|
||||||
registration_office = models.CharField(max_length=500, null=True, blank=True) # ToDo: Really needed?
|
|
||||||
process = models.ForeignKey("process.Process", related_name="compensations", on_delete=models.CASCADE)
|
|
||||||
ground_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws!
|
ground_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws!
|
||||||
action_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws!
|
action_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws!
|
||||||
|
|
||||||
|
before_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
||||||
|
after_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
||||||
actions = models.ManyToManyField(CompensationAction)
|
actions = models.ManyToManyField(CompensationAction)
|
||||||
|
|
||||||
deadline_creation = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="deadline_creation")
|
deadline_creation = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="deadline_creation")
|
||||||
deadline_maintaining = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="deadline_maintaining")
|
deadline_maintaining = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="deadline_maintaining")
|
||||||
initial_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
|
||||||
final_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
|
||||||
geometry = models.MultiPolygonField(null=True, blank=True)
|
|
||||||
documents = models.ManyToManyField("konova.Document", blank=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
return "{} of {}".format(self.type, self.process)
|
documents = models.ManyToManyField("konova.Document", blank=True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __generate_new_identifier() -> str:
|
def __generate_new_identifier() -> str:
|
||||||
@@ -92,36 +89,8 @@ class Compensation(BaseObject):
|
|||||||
self.identifier = new_id
|
self.identifier = new_id
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_role_objects(user: User, order_by: str = "-created_on"):
|
|
||||||
""" Returns objects depending on the currently selected role of the user
|
|
||||||
|
|
||||||
* REGISTRATIONOFFICE
|
class EcoAccount(Compensation):
|
||||||
* User can see the processes where registration_office is set to the organisation of the currently selected role
|
|
||||||
* User can see self-created processes
|
|
||||||
* LICENSINGOFFICE
|
|
||||||
* same
|
|
||||||
* DATAPROVIDER
|
|
||||||
* User can see only self-created processes
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
order_by (str): Order by which Process attribute
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
role = user.current_role
|
|
||||||
if role is None:
|
|
||||||
return Compensation.objects.none()
|
|
||||||
processes = Process.get_role_objects(user, order_by)
|
|
||||||
processes.prefetch_related("compensations")
|
|
||||||
compensations = []
|
|
||||||
[compensations.extend(process.compensations.all()) for process in processes]
|
|
||||||
return compensations
|
|
||||||
|
|
||||||
|
|
||||||
class EcoAccount(BaseResource):
|
|
||||||
"""
|
"""
|
||||||
An eco account is a kind of 'prepaid' compensation. It can be compared to an account that already has been filled
|
An eco account is a kind of 'prepaid' compensation. It can be compared to an account that already has been filled
|
||||||
with some kind of currency. From this account one is able to 'withdraw' currency for current projects.
|
with some kind of currency. From this account one is able to 'withdraw' currency for current projects.
|
||||||
@@ -129,17 +98,4 @@ class EcoAccount(BaseResource):
|
|||||||
'Withdrawing' can only be applied by shrinking the size of the available geometry and declaring the withdrawed
|
'Withdrawing' can only be applied by shrinking the size of the available geometry and declaring the withdrawed
|
||||||
geometry as a compensation for a process.
|
geometry as a compensation for a process.
|
||||||
"""
|
"""
|
||||||
is_old_law = models.BooleanField(default=False)
|
handler = models.CharField(max_length=500, null=True, blank=True, help_text="Who is responsible for handling the actions")
|
||||||
type = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
licensing_authority_document_identifier = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
registration_office = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
handler = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
handler_comments = models.TextField()
|
|
||||||
geometry = models.GeometryCollectionField()
|
|
||||||
documents = models.ManyToManyField("konova.Document")
|
|
||||||
initial_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
|
||||||
final_states = models.ManyToManyField(CompensationState, blank=True, related_name='+')
|
|
||||||
actions = models.ManyToManyField(CompensationAction)
|
|
||||||
deadline_maintaining = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True)
|
|
||||||
deadline_other = models.ManyToManyField("konova.Deadline", blank=True, related_name='+')
|
|
||||||
comments = models.TextField()
|
|
||||||
@@ -9,7 +9,6 @@ from konova.decorators import *
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@resolve_user_role
|
|
||||||
def index_view(request: HttpRequest):
|
def index_view(request: HttpRequest):
|
||||||
"""
|
"""
|
||||||
Renders the index view for compensation
|
Renders the index view for compensation
|
||||||
@@ -22,7 +21,7 @@ def index_view(request: HttpRequest):
|
|||||||
"""
|
"""
|
||||||
template = "generic_index.html"
|
template = "generic_index.html"
|
||||||
user = request.user
|
user = request.user
|
||||||
compensations = Compensation.get_role_objects(user)
|
compensations = None # ToDo
|
||||||
table = CompensationTable(
|
table = CompensationTable(
|
||||||
request=request,
|
request=request,
|
||||||
queryset=compensations
|
queryset=compensations
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ class InterventionAdmin(admin.ModelAdmin):
|
|||||||
list_display = [
|
list_display = [
|
||||||
"id",
|
"id",
|
||||||
"title",
|
"title",
|
||||||
"type",
|
"process_type",
|
||||||
"handler",
|
"handler",
|
||||||
"created_on",
|
|
||||||
"is_active",
|
"is_active",
|
||||||
"is_deleted",
|
"created_on",
|
||||||
|
"deleted_on",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+19
-37
@@ -10,10 +10,9 @@ from django.contrib.gis.db import models
|
|||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
|
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
|
||||||
from konova.models import BaseObject
|
from konova.models import BaseObject, Geometry
|
||||||
from konova.utils.generators import generate_random_string
|
from konova.utils.generators import generate_random_string
|
||||||
from organisation.enums import RoleTypeEnum
|
from organisation.models import Organisation
|
||||||
from process.models import Process
|
|
||||||
|
|
||||||
|
|
||||||
class Intervention(BaseObject):
|
class Intervention(BaseObject):
|
||||||
@@ -22,21 +21,30 @@ class Intervention(BaseObject):
|
|||||||
|
|
||||||
A process consists of exactly one intervention and one or more compensation
|
A process consists of exactly one intervention and one or more compensation
|
||||||
"""
|
"""
|
||||||
type = models.CharField(max_length=500, null=True, blank=True)
|
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True)
|
||||||
|
registration_file_number = models.CharField(max_length=1000, blank=True, null=True)
|
||||||
|
registration_date = models.DateTimeField(null=True, blank=True)
|
||||||
|
|
||||||
|
conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True)
|
||||||
|
conservations_file_number = models.CharField(max_length=1000, blank=True, null=True)
|
||||||
|
|
||||||
|
process_type = models.CharField(max_length=500, null=True, blank=True)
|
||||||
law = models.CharField(max_length=500, null=True, blank=True)
|
law = models.CharField(max_length=500, null=True, blank=True)
|
||||||
handler = models.CharField(max_length=500, null=True, blank=True)
|
handler = models.CharField(max_length=500, null=True, blank=True)
|
||||||
data_provider = models.ForeignKey("organisation.Organisation", on_delete=models.SET_NULL, null=True, blank=True)
|
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
data_provider_detail = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
geometry = models.MultiPolygonField(null=True, blank=True)
|
|
||||||
process = models.OneToOneField("process.Process", on_delete=models.CASCADE, null=True, blank=True, related_name="intervention")
|
|
||||||
documents = models.ManyToManyField("konova.Document", blank=True)
|
documents = models.ManyToManyField("konova.Document", blank=True)
|
||||||
|
|
||||||
|
# Refers to "verzeichnen"
|
||||||
|
recorded_on = models.DateTimeField(default=None)
|
||||||
|
recorded_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
|
|
||||||
|
# Holds which intervention is simply a newer version of this dataset
|
||||||
|
next_version = models.ForeignKey("Intervention", null=True, on_delete=models.DO_NOTHING)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{} by {}".format(self.type, self.handler)
|
return "{} by {}".format(self.type, self.handler)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
if self.process is not None:
|
|
||||||
self.process.delete()
|
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -62,30 +70,4 @@ class Intervention(BaseObject):
|
|||||||
while Intervention.objects.filter(identifier=new_id).exists():
|
while Intervention.objects.filter(identifier=new_id).exists():
|
||||||
new_id = self.__generate_new_identifier()
|
new_id = self.__generate_new_identifier()
|
||||||
self.identifier = new_id
|
self.identifier = new_id
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_role_objects(user: User, order_by: str = "-created_on") -> list:
|
|
||||||
""" Returns objects depending on the currently selected role of the user
|
|
||||||
|
|
||||||
* REGISTRATIONOFFICE
|
|
||||||
* User can see the processes where registration_office is set to the organisation of the currently selected role
|
|
||||||
* User can see self-created processes
|
|
||||||
* LICENSINGOFFICE
|
|
||||||
* same
|
|
||||||
* DATAPROVIDER
|
|
||||||
* User can see only self-created processes
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
order_by (str): Order by which Process attribute
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
role = user.current_role
|
|
||||||
if role is None:
|
|
||||||
return Intervention.objects.none()
|
|
||||||
processes = Process.get_role_objects(user, order_by)
|
|
||||||
interventions = [process.intervention for process in processes]
|
|
||||||
return interventions
|
|
||||||
@@ -15,7 +15,7 @@ from process.models import Process
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@resolve_user_role
|
|
||||||
def index_view(request: HttpRequest):
|
def index_view(request: HttpRequest):
|
||||||
"""
|
"""
|
||||||
Renders the index view for process
|
Renders the index view for process
|
||||||
@@ -28,7 +28,7 @@ def index_view(request: HttpRequest):
|
|||||||
"""
|
"""
|
||||||
template = "generic_index.html"
|
template = "generic_index.html"
|
||||||
user = request.user
|
user = request.user
|
||||||
interventions = Intervention.get_role_objects(user)
|
interventions = Intervention # ToDo
|
||||||
table = InterventionTable(
|
table = InterventionTable(
|
||||||
request=request,
|
request=request,
|
||||||
queryset=interventions
|
queryset=interventions
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -7,9 +7,7 @@ Created on: 16.11.20
|
|||||||
"""
|
"""
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
|
||||||
from konova.models import RoleGroup
|
from konova.sub_settings.context_settings import BASE_TITLE, WIKI_URL, BASE_FRONTEND_TITLE
|
||||||
from konova.sub_settings.context_settings import BASE_TITLE, WIKI_URL, BASE_FRONTEND_TITLE, RENDER_HEADER
|
|
||||||
from konova.utils.session import set_session_user_role
|
|
||||||
|
|
||||||
|
|
||||||
class BaseContext:
|
class BaseContext:
|
||||||
@@ -22,7 +20,6 @@ class BaseContext:
|
|||||||
"language": "en",
|
"language": "en",
|
||||||
"wiki_url": WIKI_URL,
|
"wiki_url": WIKI_URL,
|
||||||
"user": None,
|
"user": None,
|
||||||
"render_header": RENDER_HEADER,
|
|
||||||
"current_role": None,
|
"current_role": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,21 +30,3 @@ class BaseContext:
|
|||||||
|
|
||||||
# Add additional context, derived from given parameters
|
# Add additional context, derived from given parameters
|
||||||
self.context.update(additional_context)
|
self.context.update(additional_context)
|
||||||
|
|
||||||
def __handle_current_role(self, request: HttpRequest):
|
|
||||||
""" Reads/Writes current role from/to session
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
# Store current role in session object to reduce amount of db access
|
|
||||||
current_role = request.session.get("current_role", {})
|
|
||||||
|
|
||||||
if len(current_role) == 0 and request.user.is_authenticated:
|
|
||||||
role_group = RoleGroup.get_users_role_groups(request.user).first()
|
|
||||||
current_role = set_session_user_role(request, role_group)
|
|
||||||
|
|
||||||
self.context["current_role"] = current_role
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||||
|
Created on: 16.11.20
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
def staff_required(function):
|
||||||
|
"""
|
||||||
|
A decorator for functions which shall only be usable for staff members of the system
|
||||||
|
"""
|
||||||
|
@wraps(function)
|
||||||
|
def wrap(request, *args, **kwargs):
|
||||||
|
user = request.user
|
||||||
|
if user.is_staff:
|
||||||
|
return function(request, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
messages.info(request, _("You need to be staff to perform this action!"))
|
||||||
|
return redirect(request.META.get("HTTP_REFERER", reverse("home")))
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
def superuser_required(function):
|
||||||
|
"""
|
||||||
|
A decorator for functions which shall only be usable for superusers of the system
|
||||||
|
"""
|
||||||
|
@wraps(function)
|
||||||
|
def wrap(request, *args, **kwargs):
|
||||||
|
user = request.user
|
||||||
|
if user.is_superuser:
|
||||||
|
return function(request, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
messages.info(request, _("You need to be administrator to perform this action!"))
|
||||||
|
return redirect(request.META.get("HTTP_REFERER", reverse("home")))
|
||||||
|
return wrap
|
||||||
File renamed without changes.
File renamed without changes.
@@ -13,7 +13,6 @@ from django.db import transaction
|
|||||||
|
|
||||||
from konova.management.commands.setup_test_data import TEST_ORGANISATION_DATA, TEST_ROLE_GROUPS_DATA
|
from konova.management.commands.setup_test_data import TEST_ORGANISATION_DATA, TEST_ROLE_GROUPS_DATA
|
||||||
from konova.models import RoleType, RoleGroup
|
from konova.models import RoleType, RoleGroup
|
||||||
from organisation.enums import RoleTypeEnum
|
|
||||||
from organisation.models import Organisation
|
from organisation.models import Organisation
|
||||||
|
|
||||||
CREATED_TEMPLATE = "{} created"
|
CREATED_TEMPLATE = "{} created"
|
||||||
@@ -27,7 +26,6 @@ class Command(BaseCommand):
|
|||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
self.__init_superuser()
|
self.__init_superuser()
|
||||||
self.__init_test_organisation()
|
self.__init_test_organisation()
|
||||||
self.__init_role_types()
|
|
||||||
self.__init_role_groups()
|
self.__init_role_groups()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.__break_line()
|
self.__break_line()
|
||||||
@@ -76,28 +74,6 @@ class Command(BaseCommand):
|
|||||||
)
|
)
|
||||||
self.__break_line()
|
self.__break_line()
|
||||||
|
|
||||||
def __init_role_types(self):
|
|
||||||
""" Initializes available role types according to RoleTypeEnum
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.stdout.write(
|
|
||||||
self.style.WARNING(
|
|
||||||
"--- Role types ---"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for role_type_enum in RoleTypeEnum:
|
|
||||||
role_type = RoleType.objects.get_or_create(
|
|
||||||
type=role_type_enum.value
|
|
||||||
)[0]
|
|
||||||
self.stdout.write(
|
|
||||||
self.style.SUCCESS(
|
|
||||||
CREATED_TEMPLATE.format(role_type.type)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.__break_line()
|
|
||||||
|
|
||||||
def __init_test_organisation(self):
|
def __init_test_organisation(self):
|
||||||
""" Creates test organisations from predefined data
|
""" Creates test organisations from predefined data
|
||||||
|
|
||||||
-9
@@ -5,32 +5,27 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 15.12.20
|
Created on: 15.12.20
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from organisation.enums import OrganisationTypeEnum, RoleTypeEnum
|
|
||||||
|
|
||||||
TEST_ORGANISATION_DATA = [
|
TEST_ORGANISATION_DATA = [
|
||||||
{
|
{
|
||||||
"name": "Test_Official_1",
|
"name": "Test_Official_1",
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
"is_deleted": False,
|
"is_deleted": False,
|
||||||
"type": OrganisationTypeEnum.OFFICIAL.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Test_Official_2",
|
"name": "Test_Official_2",
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
"is_deleted": False,
|
"is_deleted": False,
|
||||||
"type": OrganisationTypeEnum.OFFICIAL.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Test_NGO_1",
|
"name": "Test_NGO_1",
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
"is_deleted": False,
|
"is_deleted": False,
|
||||||
"type": OrganisationTypeEnum.NGO.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Test_Company_1",
|
"name": "Test_Company_1",
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
"is_deleted": False,
|
"is_deleted": False,
|
||||||
"type": OrganisationTypeEnum.COMPANY.value,
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -38,21 +33,17 @@ TEST_ROLE_GROUPS_DATA = [
|
|||||||
{
|
{
|
||||||
"name": "Registration office Test_Official_1",
|
"name": "Registration office Test_Official_1",
|
||||||
"organisation": "Test_Official_1",
|
"organisation": "Test_Official_1",
|
||||||
"role": RoleTypeEnum.REGISTRATIONOFFICE.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Licensing authority Test_Official_1",
|
"name": "Licensing authority Test_Official_1",
|
||||||
"organisation": "Test_Official_1",
|
"organisation": "Test_Official_1",
|
||||||
"role": RoleTypeEnum.LICENSINGAUTHORITY.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Dataprovider Test_Official_2",
|
"name": "Dataprovider Test_Official_2",
|
||||||
"organisation": "Test_Official_2",
|
"organisation": "Test_Official_2",
|
||||||
"role": RoleTypeEnum.LICENSINGAUTHORITY.value,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Dataprovider Test_Company_1",
|
"name": "Dataprovider Test_Company_1",
|
||||||
"organisation": "Test_Company_1",
|
"organisation": "Test_Company_1",
|
||||||
"role": RoleTypeEnum.DATAPROVIDER.value,
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -7,11 +7,9 @@ Created on: 17.11.20
|
|||||||
"""
|
"""
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.gis.db.models import MultiPolygonField
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import QuerySet
|
|
||||||
|
|
||||||
from organisation.enums import RoleTypeEnum
|
|
||||||
|
|
||||||
|
|
||||||
class BaseResource(models.Model):
|
class BaseResource(models.Model):
|
||||||
@@ -22,8 +20,6 @@ class BaseResource(models.Model):
|
|||||||
primary_key=True,
|
primary_key=True,
|
||||||
default=uuid.uuid4,
|
default=uuid.uuid4,
|
||||||
)
|
)
|
||||||
is_active = models.BooleanField(default=True)
|
|
||||||
is_deleted = models.BooleanField(default=False)
|
|
||||||
created_on = models.DateTimeField(auto_now_add=True, null=True)
|
created_on = models.DateTimeField(auto_now_add=True, null=True)
|
||||||
created_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
|
created_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
|
||||||
|
|
||||||
@@ -39,6 +35,9 @@ class BaseObject(BaseResource):
|
|||||||
"""
|
"""
|
||||||
identifier = models.CharField(max_length=1000, null=True, blank=True)
|
identifier = models.CharField(max_length=1000, null=True, blank=True)
|
||||||
title = models.CharField(max_length=1000, null=True, blank=True)
|
title = models.CharField(max_length=1000, null=True, blank=True)
|
||||||
|
deleted_on = models.DateTimeField(null=True)
|
||||||
|
deleted_by = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
|
||||||
|
comment = models.TextField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
@@ -64,41 +63,8 @@ class Document(BaseResource):
|
|||||||
comment = models.TextField()
|
comment = models.TextField()
|
||||||
|
|
||||||
|
|
||||||
class RoleType(BaseResource):
|
class Geometry(BaseResource):
|
||||||
"""
|
"""
|
||||||
Defines different role types
|
Outsourced geometry model so multiple versions of the same object can refer to the same geometry if it is not changed
|
||||||
"""
|
"""
|
||||||
type = models.CharField(max_length=255, choices=RoleTypeEnum.as_choices(drop_empty_choice=True), unique=True)
|
geom = MultiPolygonField(null=True, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.type
|
|
||||||
|
|
||||||
|
|
||||||
class RoleGroup(Group):
|
|
||||||
"""
|
|
||||||
Role groups are specialized groups which hold information on which users are related to a certain organisation and
|
|
||||||
a role
|
|
||||||
"""
|
|
||||||
organisation = models.ForeignKey("organisation.Organisation", on_delete=models.CASCADE)
|
|
||||||
role = models.ForeignKey(RoleType, on_delete=models.CASCADE)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
unique_together = [
|
|
||||||
["organisation", "role", ]
|
|
||||||
]
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_users_role_groups(user: User) -> QuerySet:
|
|
||||||
""" Get all role groups of a given user
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
qs (QuerySet)
|
|
||||||
"""
|
|
||||||
if user.is_anonymous:
|
|
||||||
return RoleGroup.objects.none()
|
|
||||||
return RoleGroup.objects.filter(
|
|
||||||
user=user
|
|
||||||
)
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -9,4 +9,3 @@ Created on: 16.11.20
|
|||||||
BASE_TITLE = "konova"
|
BASE_TITLE = "konova"
|
||||||
BASE_FRONTEND_TITLE = "Kompensationsverzeichnis Service Portal"
|
BASE_FRONTEND_TITLE = "Kompensationsverzeichnis Service Portal"
|
||||||
WIKI_URL = "https://dienste.naturschutz.rlp.de/doku/doku.php?id=ksp:start"
|
WIKI_URL = "https://dienste.naturschutz.rlp.de/doku/doku.php?id=ksp:start"
|
||||||
RENDER_HEADER = False
|
|
||||||
@@ -56,6 +56,7 @@ INSTALLED_APPS = [
|
|||||||
'simple_sso.sso_server',
|
'simple_sso.sso_server',
|
||||||
'django_tables2',
|
'django_tables2',
|
||||||
'fontawesome_5',
|
'fontawesome_5',
|
||||||
|
'bootstrap4',
|
||||||
'konova',
|
'konova',
|
||||||
'compensation',
|
'compensation',
|
||||||
'intervention',
|
'intervention',
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -28,7 +28,6 @@ urlpatterns = [
|
|||||||
path('login/', include(sso_client.get_urls())),
|
path('login/', include(sso_client.get_urls())),
|
||||||
path('logout/', logout_view, name="logout"),
|
path('logout/', logout_view, name="logout"),
|
||||||
path('', home_view, name="home"),
|
path('', home_view, name="home"),
|
||||||
path('process/', include("process.urls")),
|
|
||||||
path('intervention/', include("intervention.urls")),
|
path('intervention/', include("intervention.urls")),
|
||||||
path('compensation/', include("compensation.urls")),
|
path('compensation/', include("compensation.urls")),
|
||||||
path('eco-account/', include("process.urls")),
|
path('eco-account/', include("process.urls")),
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -43,25 +43,6 @@ def home_view(request: HttpRequest):
|
|||||||
"""
|
"""
|
||||||
template = "konova/home.html"
|
template = "konova/home.html"
|
||||||
|
|
||||||
if request.method == "POST":
|
additional_context = {}
|
||||||
form = ChangeUserRoleForm(
|
|
||||||
request.POST or None,
|
|
||||||
user=request.user,
|
|
||||||
)
|
|
||||||
if form.is_valid():
|
|
||||||
role = form.save(request)
|
|
||||||
messages.success(request, _("Role changed"))
|
|
||||||
else:
|
|
||||||
messages.error(request, _("Invalid role"))
|
|
||||||
return redirect("home")
|
|
||||||
else:
|
|
||||||
# GET
|
|
||||||
form = ChangeUserRoleForm(
|
|
||||||
user=request.user,
|
|
||||||
initial={"role": int(get_session_user_role(request).get("id", -1))},
|
|
||||||
)
|
|
||||||
additional_context = {
|
|
||||||
"form": form,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, additional_context).context
|
context = BaseContext(request, additional_context).context
|
||||||
return render(request, template, context)
|
return render(request, template, context)
|
||||||
File renamed without changes.
@@ -1,94 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 16.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from konova.models import RoleGroup
|
|
||||||
from konova.utils.session import get_session_user_role
|
|
||||||
from organisation.enums import RoleTypeEnum
|
|
||||||
from process.enums import PROCESS_EDITABLE_STATE
|
|
||||||
from process.models import Process
|
|
||||||
|
|
||||||
|
|
||||||
def staff_required(function):
|
|
||||||
"""
|
|
||||||
A decorator for functions which shall only be usable for staff members of the system
|
|
||||||
"""
|
|
||||||
@wraps(function)
|
|
||||||
def wrap(request, *args, **kwargs):
|
|
||||||
user = request.user
|
|
||||||
if user.is_staff:
|
|
||||||
return function(request, *args, **kwargs)
|
|
||||||
else:
|
|
||||||
messages.info(request, _("You need to be staff to perform this action!"))
|
|
||||||
return redirect(request.META.get("HTTP_REFERER", reverse("home")))
|
|
||||||
return wrap
|
|
||||||
|
|
||||||
|
|
||||||
def superuser_required(function):
|
|
||||||
"""
|
|
||||||
A decorator for functions which shall only be usable for superusers of the system
|
|
||||||
"""
|
|
||||||
@wraps(function)
|
|
||||||
def wrap(request, *args, **kwargs):
|
|
||||||
user = request.user
|
|
||||||
if user.is_superuser:
|
|
||||||
return function(request, *args, **kwargs)
|
|
||||||
else:
|
|
||||||
messages.info(request, _("You need to be administrator to perform this action!"))
|
|
||||||
return redirect(request.META.get("HTTP_REFERER", reverse("home")))
|
|
||||||
return wrap
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_user_role(function):
|
|
||||||
"""
|
|
||||||
A decorator for functions to resolve the current user role and store it in the user object
|
|
||||||
"""
|
|
||||||
@wraps(function)
|
|
||||||
def wrap(request, *args, **kwargs):
|
|
||||||
user = request.user
|
|
||||||
role = get_session_user_role(request)
|
|
||||||
try:
|
|
||||||
role = RoleGroup.objects.get(id=role.get("id", -1))
|
|
||||||
user.current_role = role
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
user.current_role = None
|
|
||||||
return function(request, *args, **kwargs)
|
|
||||||
return wrap
|
|
||||||
|
|
||||||
|
|
||||||
def valid_process_role_required(function):
|
|
||||||
"""
|
|
||||||
A decorator for functions to check whether the user has a valid role selected
|
|
||||||
"""
|
|
||||||
@wraps(function)
|
|
||||||
def wrap(request, *args, **kwargs):
|
|
||||||
user = request.user
|
|
||||||
if user.current_role is None:
|
|
||||||
role = get_session_user_role(request)
|
|
||||||
else:
|
|
||||||
role = user.current_role
|
|
||||||
try:
|
|
||||||
process = Process.objects.get(id=kwargs.get("id"))
|
|
||||||
editable = PROCESS_EDITABLE_STATE.get(process.state)
|
|
||||||
role_enum = RoleTypeEnum[role.role.type]
|
|
||||||
if role_enum in editable:
|
|
||||||
return function(request, *args, **kwargs)
|
|
||||||
else:
|
|
||||||
messages.error(request, _("Your current role is not allowed to do this"))
|
|
||||||
return redirect(request.META.get("HTTP_REFERER", "home"))
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
process = None
|
|
||||||
return function(request, *args, **kwargs)
|
|
||||||
return wrap
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
.body-content{
|
|
||||||
min-height: 75vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note{
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: lightgray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label-required{
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
table{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer{
|
|
||||||
width: 100%;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error{
|
|
||||||
color: #D8000C !important;
|
|
||||||
background-color: #FFBABA !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
i.true{
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
i.false{
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button{
|
|
||||||
margin: 0.5625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-col{
|
|
||||||
max-width: 8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-col .button{
|
|
||||||
margin: 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-role{
|
|
||||||
background: url('../images/menu-bg.png') repeat #871d33;
|
|
||||||
color: white;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
border-bottom: 4px solid #8e8e8e;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-role > a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
.info, .success, .warning, .error, .validation {
|
|
||||||
border: 1px solid;
|
|
||||||
margin: 10px 0px;
|
|
||||||
padding:15px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info:hover,
|
|
||||||
.success:hover,
|
|
||||||
.warning:hover,
|
|
||||||
.error:hover,
|
|
||||||
.validation:hover {
|
|
||||||
cursor: default;
|
|
||||||
filter: brightness(1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
color: #00529B;
|
|
||||||
background-color: #BDE5F8;
|
|
||||||
/*
|
|
||||||
background-image: url('../images/knobs/info.png');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
.success {
|
|
||||||
color: #4F8A10;
|
|
||||||
background-color: #DFF2BF;
|
|
||||||
/*
|
|
||||||
background-image:url('../images/knobs/success.png');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
.warning {
|
|
||||||
color: #9F6000;
|
|
||||||
background-color: #FEEFB3;
|
|
||||||
/*
|
|
||||||
background-image: url('../images/knobs/warning.png');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
.error {
|
|
||||||
color: #D8000C;
|
|
||||||
background-color: #FFBABA;
|
|
||||||
/*
|
|
||||||
background-image: url('../images/knobs/error.png');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */
|
|
||||||
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",B=new RegExp(M+"+","g"),$=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-lLine truncated
|
|
||||||
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
/*! jQuery UI - v1.12.1 - 2016-09-14
|
|
||||||
* http://jqueryui.com
|
|
||||||
* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
|
|
||||||
* Copyright jQuery Foundation and other contributors; Licensed MIT */
|
|
||||||
|
|
||||||
(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){function e(t){for(var e=t.css("visibility");"inherit"===e;)t=t.parent(),e=t.css("visibility");return"hidden"!==e}function i(t){for(var e,i;t.length&&t[0]!==document;){if(e=t.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(i=parseInt(t.css("zIndex"),10),!isNaN(i)&&0!==i))return i;t=t.parent()}return 0}function s(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.regional.en=t.extend(!0,{},this.regional[""]),this.regional["en-US"]=t.extend(!0,{},this.regional.en),this.dpDiv=n(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function n(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.on("mouseout",i,function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).on("mouseover",i,o)}function o(){t.datepicker._isDisabledDatepicker(m.inline?m.dpDiv.parent()[0]:m.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))}function a(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}function r(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.ui=t.ui||{},t.ui.version="1.12.1";var h=0,l=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},h=e.split(".")[0];e=e.split(".")[1];var l=h+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][l.toLowerCase()]=function(e){return!!t.data(e,l)},t[h]=t[h]||{},n=t[h][e],o=t[h][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:h,widgetName:e,widgetFullName:l}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var i,s,n=l.call(arguments,1),o=0,a=n.length;a>Line truncated
|
|
||||||
}}(t.fn.show),hide:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(t.fn.hide),toggle:function(t){return function(s){if(i(s)||"boolean"==typeof s)return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):s(this.css("clip"),this)},transfer:function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,h=o?a.scrollLeft():0,l=n.offset(),c={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo("body").addClass(e.className).css({top:u.top-r,left:u.left-h,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),t.isFunction(i)&&i()})}}),t.fx.step.clip=function(e){e.clipInit||(e.start=t(e.elem).cssClip(),"string"==typeof e.end&&(e.end=s(e.end,e.elem)),e.clipInit=!0),t(e.elem).cssClip({top:e.pos*(e.end.top-e.start.top)+e.start.top,right:e.pos*(e.end.right-e.start.right)+e.start.right,bottom:e.pos*(e.end.bottom-e.start.bottom)+e.start.bottom,left:e.pos*(e.end.left-e.start.left)+e.start.left})}}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}();var f=t.effects;t.effects.define("blind","hide",function(e,i){var s={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},n=t(this),o=e.direction||"up",a=n.cssClip(),r={clip:t.extend({},a)},h=t.effects.createPlaceholder(n);r.clip[s[o][0]]=r.clip[s[o][1]],"show"===e.mode&&(n.cssClip(r.clip),h&&h.css(t.effects.clipToBox(r)),r.clip=a),h&&h.animate(t.effects.clipToBox(r),e.duration,e.easing),n.animate(r,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("bounce",function(e,i){var s,n,o,a=t(this),r=e.mode,h="hide"===r,l="show"===r,c=e.direction||"up",u=e.distance,d=e.times||5,p=2*d+(l||h?1:0),f=e.duration/p,g=e.easing,m="up"===c||"down"===c?"top":"left",_="up"===c||"left"===c,v=0,b=a.queue().length;for(t.effects.createPlaceholder(a),o=a.css(m),u||(u=a["top"===m?"outerHeight":"outerWidth"]()/3),l&&(n={opacity:1},n[m]=o,a.css("opacity",0).css(m,_?2*-u:2*u).animate(n,f,g)),h&&(u/=Math.pow(2,d-1)),n={},n[m]=o;d>v;v++)s={},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g).animate(n,f,g),u=h?2*u:u/2;h&&(s={opacity:0},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g)),a.queue(i),t.effects.unshift(a,b,p+1)}),t.effects.define("clip","hide",function(e,i){var s,n={},o=t(this),a=e.direction||"vertical",r="both"===a,h=r||"horizontal"===a,l=r||"vertical"===a;s=o.cssClip(),n.clip={top:l?(s.bottom-s.top)/2:s.top,right:h?(s.right-s.left)/2:s.right,bottom:l?(s.bottom-s.top)/2:s.bottom,left:h?(s.right-s.left)/2:s.left},t.effects.createPlaceholder(o),"show"===e.mode&&(o.cssClip(n.clip),n.clip=s),o.animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("drop","hide",function(e,i){var s,n=t(this),o=e.mode,a="show"===o,r=e.direction||"left",h="up"===r||"down"===r?"top":"left",l="up"===r||"left"===r?"-=":"+=",c="+="===l?"-=":"+=",u={opacity:0};t.effects.createPlaceholder(n),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0)/2,u[h]=l+s,a&&(n.css(u),u[h]=c+s,u.opacity=1),n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("explode","hide",function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),i()}var o,a,r,h,l,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=e.mode,g="show"===f,m=p.show().css("visibility","hidden").offset(),_=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(h=m.top+o*v,c=o-(u-1)/2,a=0;d>a;a++)r=m.left+a*_,l=a-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-a*_,top:-o*v}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:_,height:v,left:r+(g?l*_:0),top:h+(g?c*v:0),opacity:g?0:1}).animate({left:r+(g?0:l*_),top:h+(g?0:c*v),opacLine truncated
|
|
||||||
this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("<ul>").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,this.element[0]!==t.ui.safeActiveElement(this.document[0])&&this.element.trigger("focus")})},menufocus:function(e,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",e,{item:n})&&e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&t.trim(s).length&&(this.liveRegion.children().hide(),t("<div>").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,i){var s=i.item.data("ui-autocomplete-item"),n=this.previous;this.element[0]!==t.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=n,this._delay(function(){this.previous=n,this.selectedItem=s})),!1!==this._trigger("select",e,{item:s})&&this._value(s.value),this.term=this._value(),this.close(e),this.selectedItem=s}}),this.liveRegion=t("<div>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(e){var i=this.menu.element[0];return e.target===this.element[0]||e.target===i||t.contains(i,e.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e&&e[0]||(e=this.element.closest(".ui-front, dialog")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){var e=this.term===this._value(),i=this.menu.element.is(":visible"),s=t.altKey||t.ctrlKey||t.metaKey||t.shiftKey;(!e||e&&!i&&!s)&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):this._trigger("search",e)!==!1?this._search(t):void 0},_search:function(t){this.pending++,this._addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var e=++this.requestIndex;return t.proxy(function(t){e===this.requestIndex&&this.__response(t),this.pendinLine truncated
|
|
||||||
}},_updateDatepicker:function(e){this.maxRows=4,m=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var i,s=this._getNumberOfMonths(e),n=s[1],a=17,r=e.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.trigger("focus"),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),o=e.dpDiv.outerHeight(),a=e.input?e.input.outerWidth():0,r=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-a:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+r?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+o>l&&l>o?Math.abs(o+r):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,o,a=this._curInst;!a||e&&a!==t.data(e,"datepicker")||this._datepickerShowing&&(i=this._get(a,"showAnim"),s=this._get(a,"duration"),n=function(){t.datepicker._tidyDialog(a)},t.effects&&(t.effects.effect[i]||t.effects[i])?a.dpDiv.hide(i,t.datepicker._get(a,"showOptions"),s,n):a.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,o=this._get(a,"onClose"),o&&o.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).off(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),o=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(o,i+("M"===s?this._get(o,"showCurrentAtPos"):0),s),this._updateDatepicker(o))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),o=this._getInst(n[0]);o["selected"+("M"===s?"Month":"Year")]=o["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(o),this._adjustDate(n)},_selectDay:function(e,i,s,n){var o,a=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(a[0])||(o=this._getInst(a[0]),o.selectedDay=o.currentDay=t("a",n).html(),o.selectedMonth=o.currentMonth=i,o.selectedYear=o.currentYear=s,this._selectDate(e,this._formatDate(o,o.currentDay,o.currentMonth,o.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),o=this._getInst(n[0]);i=null!=i?i:this._formatDate(o),o.input&&o.input.val(i),this._updateAlternate(o),s=this._get(o,"onSelect"),s?s.apply(o.input?o.input[0]:null,[i,o]):o.input&&o.input.trigger("change"),o.inline?this._updateDatepicker(o):(this._hideDatepicker(),this._lastInput=o.input[0],"object"!=typeof o.input[0]&&o.input.trigger("focus"),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,o=this._get(e,"altField");o&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(o).val(n))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7))Line truncated
|
|
||||||
},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),h=t.pageX,l=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,h=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(h=this.originalPageX),"x"===a.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.eleLine truncated
|
|
||||||
},disable:t.noop,enable:t.noop,close:function(e){var i=this;this._isOpen&&this._trigger("beforeClose",e)!==!1&&(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),this.opener.filter(":focusable").trigger("focus").length||t.ui.safeBlur(t.ui.safeActiveElement(this.document[0])),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",e)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+t(this).css("z-index")}).get(),o=Math.max.apply(null,n);return o>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",o+1),s=!0),s&&!i&&this._trigger("focus",e),s},open:function(){var e=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=t(t.ui.safeActiveElement(this.document[0])),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var t=this._focusedElement;t||(t=this.element.find("[autofocus]")),t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).trigger("focus")},_keepFocus:function(e){function i(){var e=t.ui.safeActiveElement(this.document[0]),i=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);i||this._focusTabbable()}e.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=t("<div>").hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._addClass(this.uiDialog,"ui-dialog","ui-widget ui-widget-content ui-front"),this._on(this.uiDialog,{keydown:function(e){if(this.options.closeOnEscape&&!e.isDefaultPrevented()&&e.keyCode&&e.keyCode===t.ui.keyCode.ESCAPE)return e.preventDefault(),this.close(e),void 0;if(e.keyCode===t.ui.keyCode.TAB&&!e.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");e.target!==n[0]&&e.target!==this.uiDialog[0]||e.shiftKey?e.target!==s[0]&&e.target!==this.uiDialog[0]||!e.shiftKey||(this._delay(function(){n.trigger("focus")}),e.preventDefault()):(this._delay(function(){s.trigger("focus")}),e.preventDefault())}},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var e;this.uiDialogTitlebar=t("<div>"),this._addClass(this.uiDialogTitlebar,"ui-dialog-titlebar","ui-widget-header ui-helper-clearfix"),this._on(this.uiDialogTitlebar,{mousedown:function(e){t(e.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.trigger("focus")}}),this.uiDialogTitlebarClose=t("<button type='button'></button>").button({label:t("<a>").text(this.options.closeText).html(),icon:"ui-icon-closethick",showLabel:!1}).appendTo(this.uiDialogTitlebar),this._addClass(this.uiDialogTitlebarClose,"ui-dialog-titlebar-close"),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),e=t("<span>").uniqueId().prependTo(this.uiDialogTitlebar),this._addClass(e,"ui-dialog-title"),this._title(e),this.uiDialogTitlebar.prependTo(this.uiDialog),this.uiDialog.attr({"aria-labelledby":e.attr("id")})},_title:function(t){this.options.title?t.text(this.options.title):t.html(" ")},_createButtonPane:function(){this.uiDialogButtonPane=t("<div>"),this._addClass(this.uiDialogButtonPane,"ui-dialog-buttonpane","ui-widget-content ui-helper-clearfix"),this.uiButtonSet=t("<div>").appendTo(this.uiDialogButtonPane),this._addClass(this.uiButtonSet,"ui-dialog-buttonset"),this._createButtons()},_createButtons:function(){var e=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),t.isEmptyObject(i)||t.isArray(i)&&!i.length?(this._removeClass(this.uiDialog,"ui-dialog-buttons"),void 0):(t.each(i,function(i,s){var n,o;s=t.isFunction(s)?{click:s,text:i}:s,s=t.extend({type:"button"},s),n=s.click,o={icon:s.icon,iconPosition:s.iconPosition,showLabel:s.showLabel,icons:s.icons,text:s.text},delete s.click,delete s.icon,delete s.iconPosition,delete s.showLabel,delete s.icons,"boolean"==typeof s.text&&delete s.text,t("<button></button>",s).button(o).appendTo(e.uiButtonSet).on("click",function(){n.apply(e.element[0],arguments)})}),this._addClass(this.uiDialog,"ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function e(t){return{position:t.position,offset:t.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:functionLine truncated
|
|
||||||
},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle"),o="<span tabindex='0'></span>",a=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)a.push(o);this.handles=n.add(t(a.join("")).appendTo(this.element)),this._addClass(this.handles,"ui-slider-handle","ui-state-default"),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e).attr("tabIndex",0)})},_createRange:function(){var e=this.options;e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?(this._removeClass(this.range,"ui-slider-range-min ui-slider-range-max"),this.range.css({left:"",bottom:""})):(this.range=t("<div>").appendTo(this.element),this._addClass(this.range,"ui-slider-range")),("min"===e.range||"max"===e.range)&&this._addClass(this.range,"ui-slider-range-"+e.range)):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,o,a,r,h,l,c=this,u=this.options;return u.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-c.values(e));(n>i||n===i&&(e===c._lastChangedValue||c.values(e)===u.min))&&(n=i,o=t(this),a=e)}),r=this._start(e,a),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=a,this._addClass(o,null,"ui-state-active"),o.trigger("focus"),h=o.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-o.width()/2,top:e.pageY-h.top-o.height()/2-(parseInt(o.css("borderTopWidth"),10)||0)-(parseInt(o.css("borderBottomWidth"),10)||0)+(parseInt(o.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,a,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this._removeClass(this.handles,null,"ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,o;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),o=this._valueMin()+s*n,this._trimAlignValue(o)},_uiHash:function(t,e,i){var s={handle:this.handles[t],handleIndex:t,value:void 0!==e?e:this.value()};return this._hasMultipleValues()&&(s.value=void 0!==e?e:this.values(t),s.values=i||this.values()),s},_hasMultipleValues:function(){return this.options.values&&this.options.values.length},_start:function(t,e){return this._trigger("start",t,this._uiHash(e))},_slide:function(t,e,i){var s,n,o=this.value(),a=this.values();this._hasMultipleValues()&&(n=this.values(e?0:1),o=this.values(e),2===this.options.values.length&&this.options.range===!0&&(i=0===e?Math.min(n,i):Math.max(n,i)),a[e]=i),i!==o&&(s=this._trigger("slide",t,this._uiHash(e,i,a)),s!==!1&&(this._hasMultipleValues()?this.values(e,i):this.value(i)))},_stop:function(t,e){this._trigger("stop",t,this._uiHash(e))},_change:function(t,e){this._keySliding||this._mouseSliding||(this._lastChangedValue=e,this._trigger("change",t,this._uiHash(e)))},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(e,i){var s,n,o;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),void 0;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this._hasMultipleValues()?this._values(e):this.value();for(s=this.options.values,n=arguments[0],o=0;s.length>o;o+=1)s[o]=this._trimAlignValue(n[o]),this._change(null,o);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.valuLine truncated
|
|
||||||
this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.spinner",{version:"1.12.1",defaultElement:"<input>",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e=this._super(),i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);null!=n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var e=this.element[0]===t.ui.safeActiveElement(this.document[0]);e||(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===t.ui.safeActiveElement(this.document[0])?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap("<span>").parent().append("<a></a><a></a>")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinnLine truncated
|
|
||||||
Vendored
-6445
File diff suppressed because it is too large.
Load diff
@@ -6,21 +6,3 @@ Created on: 07.12.20
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from konova.enums import BaseEnum
|
from konova.enums import BaseEnum
|
||||||
|
|
||||||
|
|
||||||
class RoleTypeEnum(BaseEnum):
|
|
||||||
"""
|
|
||||||
Defines the possible role types for organisation and users
|
|
||||||
"""
|
|
||||||
DATAPROVIDER = "DATAPROVIDER"
|
|
||||||
LICENSINGAUTHORITY = "LICENSINGAUTHORITY"
|
|
||||||
REGISTRATIONOFFICE = "REGISTRATIONOFFICE"
|
|
||||||
|
|
||||||
|
|
||||||
class OrganisationTypeEnum(BaseEnum):
|
|
||||||
"""
|
|
||||||
Defines the possible role types for organisation and users
|
|
||||||
"""
|
|
||||||
OFFICIAL = "OFFICIAL"
|
|
||||||
COMPANY = "COMPANY"
|
|
||||||
NGO = "NGO"
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from konova.models import BaseResource
|
from konova.models import BaseResource
|
||||||
from organisation.enums import OrganisationTypeEnum
|
|
||||||
|
|
||||||
|
|
||||||
class Organisation(BaseResource):
|
class Organisation(BaseResource):
|
||||||
@@ -12,7 +11,6 @@ class Organisation(BaseResource):
|
|||||||
phone = models.CharField(max_length=500, null=True, blank=True)
|
phone = models.CharField(max_length=500, null=True, blank=True)
|
||||||
email = models.EmailField(max_length=500, null=True, blank=True)
|
email = models.EmailField(max_length=500, null=True, blank=True)
|
||||||
facsimile = models.CharField(max_length=500, null=True, blank=True)
|
facsimile = models.CharField(max_length=500, null=True, blank=True)
|
||||||
type = models.CharField(max_length=255, choices=OrganisationTypeEnum.as_choices(drop_empty_choice=True), null=True, blank=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -6,17 +6,3 @@ Created on: 07.12.20
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from organisation.enums import OrganisationTypeEnum as ote
|
|
||||||
from organisation.enums import RoleTypeEnum as rte
|
|
||||||
|
|
||||||
ORGANISATION_ROLE_STRINGS = {
|
|
||||||
ote.OFFICIAL.value: _("Official"),
|
|
||||||
ote.COMPANY.value: _("Company"),
|
|
||||||
ote.NGO.value: _("NGO"),
|
|
||||||
}
|
|
||||||
|
|
||||||
ROLE_TYPE_STRINGS = {
|
|
||||||
rte.DATAPROVIDER.value: _("Data provider"),
|
|
||||||
rte.LICENSINGAUTHORITY.value: _("Licencing Authority"),
|
|
||||||
rte.REGISTRATIONOFFICE.value: _("Registration office"),
|
|
||||||
}
|
|
||||||
Whitespace-only changes.
@@ -1,38 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
from process.models import Process
|
|
||||||
|
|
||||||
|
|
||||||
def activate_process(modeladmin, request, queryset):
|
|
||||||
for process in queryset:
|
|
||||||
process.activate()
|
|
||||||
|
|
||||||
|
|
||||||
def deactivate_process(modeladmin, request, queryset):
|
|
||||||
for process in queryset:
|
|
||||||
process.deactivate()
|
|
||||||
|
|
||||||
|
|
||||||
activate_process.short_description = "Activate selected process"
|
|
||||||
deactivate_process.short_description = "Deactivate selected process"
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessAdmin(admin.ModelAdmin):
|
|
||||||
list_display = [
|
|
||||||
"id",
|
|
||||||
"licensing_authority",
|
|
||||||
"licensing_authority_document_identifier",
|
|
||||||
"registration_office",
|
|
||||||
"registration_office_document_identifier",
|
|
||||||
"is_active",
|
|
||||||
"is_deleted",
|
|
||||||
]
|
|
||||||
actions = [
|
|
||||||
activate_process,
|
|
||||||
deactivate_process,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Process, ProcessAdmin)
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessConfig(AppConfig):
|
|
||||||
name = 'process'
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 25.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
|
|
||||||
from konova.enums import BaseEnum
|
|
||||||
from organisation.enums import RoleTypeEnum
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessStateEnum(BaseEnum):
|
|
||||||
"""
|
|
||||||
ProcessStates define in which state a process can be:
|
|
||||||
|
|
||||||
private
|
|
||||||
Only the user can see and edit this process. Not viewable by any others
|
|
||||||
accessible
|
|
||||||
The user and all participated users can see this process. Only the responsible next user can edit
|
|
||||||
the process
|
|
||||||
licensed
|
|
||||||
The user and all participated users can see this process. Only the responsible next user can edit
|
|
||||||
the process
|
|
||||||
official
|
|
||||||
The user and all participated users can see this process. Only the registration office user can now
|
|
||||||
change details. If a process is changed in this state, the state will be set back to accessible, so all
|
|
||||||
participated users need to take a look on the changed data again.
|
|
||||||
recorded [Will be set automatically after certain time]
|
|
||||||
The user and all participated users can see this process. No one can edit data. To change any details,
|
|
||||||
the process has to be set to accessible manually again.
|
|
||||||
"""
|
|
||||||
PRIVATE = 0
|
|
||||||
ACCESSIBLE = 1
|
|
||||||
LICENSED = 2
|
|
||||||
OFFICIAL = 3
|
|
||||||
RECORDED = 4
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def as_choices(cls, drop_empty_choice: bool = False) -> list:
|
|
||||||
""" Extends as_choices, so choices will be translated
|
|
||||||
|
|
||||||
Args:
|
|
||||||
drop_empty_choice (bool): Whether the empty choice shall be dropped or not
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
trans_choices (list): Translated choices
|
|
||||||
"""
|
|
||||||
choices = super().as_choices(drop_empty_choice)
|
|
||||||
return ProcessStateEnum.__translate_choices(choices)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def __translate_choices(choices: list) -> list:
|
|
||||||
""" Translates a list of prepared but untranslated choices
|
|
||||||
|
|
||||||
Args:
|
|
||||||
choices (list): A list of tuple chocies
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
choices (list): The same list but translated
|
|
||||||
"""
|
|
||||||
from process.settings import PROCESS_STATE_STRINGS
|
|
||||||
trans_choices = []
|
|
||||||
# Translate
|
|
||||||
for choice in choices:
|
|
||||||
if choice[0] is not None:
|
|
||||||
choice = list(choice)
|
|
||||||
trans = PROCESS_STATE_STRINGS.get(choice[0])
|
|
||||||
choice[1] = trans
|
|
||||||
choice = tuple(choice)
|
|
||||||
trans_choices.append(choice)
|
|
||||||
return trans_choices
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def is_state(cls, state: int) -> bool:
|
|
||||||
""" Checks whether the given state is a valid Enum
|
|
||||||
|
|
||||||
Args:
|
|
||||||
state (int): The state to be checked
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
is_valid (bool)
|
|
||||||
"""
|
|
||||||
valid_vals = {enum.value for enum in cls}
|
|
||||||
return state in valid_vals
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def as_role_choices(cls, user: User) -> list:
|
|
||||||
""" Checks whether the given state is a valid Enum
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
is_valid (bool)
|
|
||||||
"""
|
|
||||||
role = user.current_role
|
|
||||||
if role is None:
|
|
||||||
return []
|
|
||||||
role_type = role.role.type
|
|
||||||
role_type_enum = RoleTypeEnum[role_type]
|
|
||||||
choices = PROCESS_ROLE_STATES.get(role_type_enum)
|
|
||||||
choices = [(enum.value, enum.name) for enum in choices]
|
|
||||||
choices = ProcessStateEnum.__translate_choices(choices)
|
|
||||||
return choices
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def as_next_role_choices(cls, user: User, current_state: int, is_owner: bool = False) -> list:
|
|
||||||
""" Returns a list of valid choices depending on the current role of the user and the current state
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
current_state (int): The current state of the process
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
choices (list): A list of valid choices
|
|
||||||
"""
|
|
||||||
role = user.current_role
|
|
||||||
if role is None:
|
|
||||||
return []
|
|
||||||
role_type = role.role.type
|
|
||||||
role_type_enum = RoleTypeEnum[role_type]
|
|
||||||
|
|
||||||
# Merge the possible choices depending on the current user role
|
|
||||||
# with the possible choices depending on the process state
|
|
||||||
role_choices = PROCESS_ROLE_STATES.get(role_type_enum)
|
|
||||||
status_choices = PROCESS_STATE_NEXT_CHOICES.get(current_state)
|
|
||||||
current_choice = {ProcessStateEnum(current_state)}
|
|
||||||
choices = (status_choices & role_choices) | current_choice
|
|
||||||
|
|
||||||
# If user is owner of this process, we shall add the private choice if not existing, yet
|
|
||||||
if is_owner:
|
|
||||||
choices = {ProcessStateEnum.PRIVATE} | choices
|
|
||||||
|
|
||||||
# Make sure enums are ordered by numerical value
|
|
||||||
choices = sorted(choices, key=lambda _enum: _enum.value)
|
|
||||||
|
|
||||||
# Create selectable and translated choices from enum list
|
|
||||||
choices = [(enum.value, enum.name) for enum in choices]
|
|
||||||
choices = ProcessStateEnum.__translate_choices(choices)
|
|
||||||
return choices
|
|
||||||
|
|
||||||
|
|
||||||
# DEFINES THE AVAILABLE STATES FOR EACH ROLE
|
|
||||||
PROCESS_ROLE_STATES = {
|
|
||||||
RoleTypeEnum.DATAPROVIDER: {
|
|
||||||
ProcessStateEnum.PRIVATE,
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
},
|
|
||||||
RoleTypeEnum.LICENSINGAUTHORITY: {
|
|
||||||
#ProcessStateEnum.PRIVATE,
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
ProcessStateEnum.LICENSED,
|
|
||||||
},
|
|
||||||
RoleTypeEnum.REGISTRATIONOFFICE: {
|
|
||||||
#ProcessStateEnum.PRIVATE,
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
ProcessStateEnum.OFFICIAL,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# DEFINES POSSIBLE NEXT STATES FOR EACH PROCESS STATE
|
|
||||||
PROCESS_STATE_NEXT_CHOICES = {
|
|
||||||
ProcessStateEnum.PRIVATE.value: {
|
|
||||||
ProcessStateEnum.PRIVATE,
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
},
|
|
||||||
ProcessStateEnum.ACCESSIBLE.value: {
|
|
||||||
ProcessStateEnum.PRIVATE,
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
ProcessStateEnum.LICENSED,
|
|
||||||
},
|
|
||||||
ProcessStateEnum.LICENSED.value: {
|
|
||||||
ProcessStateEnum.PRIVATE,
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
ProcessStateEnum.LICENSED,
|
|
||||||
ProcessStateEnum.OFFICIAL,
|
|
||||||
},
|
|
||||||
ProcessStateEnum.OFFICIAL.value: {
|
|
||||||
ProcessStateEnum.ACCESSIBLE,
|
|
||||||
ProcessStateEnum.OFFICIAL,
|
|
||||||
ProcessStateEnum.RECORDED,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# DEFINES FOR EACH STATE WHICH ROLE CAN EDIT THE PROCESS
|
|
||||||
PROCESS_EDITABLE_STATE = {
|
|
||||||
ProcessStateEnum.PRIVATE.value: {
|
|
||||||
RoleTypeEnum.DATAPROVIDER,
|
|
||||||
RoleTypeEnum.LICENSINGAUTHORITY,
|
|
||||||
},
|
|
||||||
ProcessStateEnum.ACCESSIBLE.value: {
|
|
||||||
RoleTypeEnum.LICENSINGAUTHORITY,
|
|
||||||
},
|
|
||||||
ProcessStateEnum.LICENSED.value: {
|
|
||||||
RoleTypeEnum.REGISTRATIONOFFICE,
|
|
||||||
},
|
|
||||||
ProcessStateEnum.OFFICIAL.value: {
|
|
||||||
RoleTypeEnum.REGISTRATIONOFFICE,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 30.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
from dal import autocomplete
|
|
||||||
from django import forms
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.db import transaction
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from intervention.models import Intervention
|
|
||||||
from konova.forms import BaseForm
|
|
||||||
from organisation.models import Organisation
|
|
||||||
from process.enums import ProcessStateEnum
|
|
||||||
from process.models import Process
|
|
||||||
|
|
||||||
|
|
||||||
class NewProcessForm(BaseForm):
|
|
||||||
"""
|
|
||||||
A form for new process
|
|
||||||
"""
|
|
||||||
identifier = forms.CharField(
|
|
||||||
max_length=255,
|
|
||||||
label=_("Identifier"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
help_text=_("Generated automatically if none was given"),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
title = forms.CharField(
|
|
||||||
max_length=255,
|
|
||||||
label=_("Title"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
help_text=_("Proper title of the process"),
|
|
||||||
required=True,
|
|
||||||
)
|
|
||||||
type = forms.CharField(
|
|
||||||
max_length=255,
|
|
||||||
label=_("Type"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
help_text=_("Which process type is this"),
|
|
||||||
required=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
licensing_authority = forms.ModelChoiceField(
|
|
||||||
label=_("Licencing Authority"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=True,
|
|
||||||
queryset=Organisation.objects.all(),
|
|
||||||
widget=autocomplete.ModelSelect2(
|
|
||||||
url="orgs-autocomplete",
|
|
||||||
attrs={
|
|
||||||
"data-placeholder": _("Organization"),
|
|
||||||
"data-minimum-input-length": 3,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
licensing_authority_document_identifier = forms.CharField(
|
|
||||||
max_length=255,
|
|
||||||
label=_("Licencing document identifier"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=True,
|
|
||||||
)
|
|
||||||
comment_licensing_authority = forms.CharField(
|
|
||||||
widget=forms.Textarea,
|
|
||||||
label=_("Comment licensing authority"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
registration_office = forms.ModelChoiceField(
|
|
||||||
label=_("Registration office"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=True,
|
|
||||||
queryset=Organisation.objects.all(),
|
|
||||||
widget=autocomplete.ModelSelect2(
|
|
||||||
url="orgs-autocomplete",
|
|
||||||
attrs={
|
|
||||||
"data-placeholder": _("Organization"),
|
|
||||||
"data-minimum-input-length": 3,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
registration_office_document_identifier = forms.CharField(
|
|
||||||
max_length=255,
|
|
||||||
label=_("Registration document identifier"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=True,
|
|
||||||
)
|
|
||||||
comment_registration_office = forms.CharField(
|
|
||||||
widget=forms.Textarea,
|
|
||||||
label=_("Comment registration office"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.action_url = reverse("process:new")
|
|
||||||
self.cancel_redirect = reverse("process:index")
|
|
||||||
self.form_title = _("Add new process")
|
|
||||||
self.form_caption = _("Enter these basic information for the new process.")
|
|
||||||
|
|
||||||
def save(self, user: User):
|
|
||||||
"""
|
|
||||||
Persists process objects into database
|
|
||||||
"""
|
|
||||||
with transaction.atomic():
|
|
||||||
identifier = self.cleaned_data.get("identifier", None)
|
|
||||||
title = self.cleaned_data.get("title", None)
|
|
||||||
_type = self.cleaned_data.get("type", None)
|
|
||||||
licencing_auth = self.cleaned_data.get("licensing_authority", None)
|
|
||||||
licencing_auth_doc_id = self.cleaned_data.get("licensing_authority_document_identifier", None)
|
|
||||||
reg_off = self.cleaned_data.get("registration_office", None)
|
|
||||||
reg_off_doc_id = self.cleaned_data.get("registration_office_document_identifier", None)
|
|
||||||
comment_license = self.cleaned_data.get("comment_licensing_authority", None)
|
|
||||||
comment_registration = self.cleaned_data.get("comment_registration_office", None)
|
|
||||||
|
|
||||||
process = Process()
|
|
||||||
process.licensing_authority = licencing_auth
|
|
||||||
process.licensing_authority_document_identifier = licencing_auth_doc_id
|
|
||||||
process.registration_office = reg_off
|
|
||||||
process.registration_office_document_identifier = reg_off_doc_id
|
|
||||||
process.state = ProcessStateEnum.PRIVATE.value
|
|
||||||
process.created_by = user
|
|
||||||
process.licensing_authority_comment = comment_license
|
|
||||||
process.registration_office_comment = comment_registration
|
|
||||||
process.save()
|
|
||||||
|
|
||||||
intervention = Intervention()
|
|
||||||
intervention.title = title
|
|
||||||
intervention.type = _type
|
|
||||||
intervention.created_by = user
|
|
||||||
intervention.process = process
|
|
||||||
intervention.identifier = identifier
|
|
||||||
intervention.save()
|
|
||||||
|
|
||||||
return process
|
|
||||||
|
|
||||||
|
|
||||||
class EditProcessForm(NewProcessForm):
|
|
||||||
status = forms.ChoiceField(
|
|
||||||
label=_("Status"),
|
|
||||||
label_suffix="",
|
|
||||||
choices=[],
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.user = kwargs.pop("user", None)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
if self.instance is not None:
|
|
||||||
self.action_url = reverse("process:edit", args=(self.instance.id,))
|
|
||||||
self.cancel_redirect = reverse("process:index")
|
|
||||||
self.form_title = _("Edit process")
|
|
||||||
self.form_caption = ""
|
|
||||||
self.fields["status"].choices = ProcessStateEnum.as_next_role_choices(self.user, self.instance.state)
|
|
||||||
|
|
||||||
# Initialize form data
|
|
||||||
form_data = {
|
|
||||||
"identifier": self.instance.intervention.identifier,
|
|
||||||
"title": self.instance.intervention.title,
|
|
||||||
"type": self.instance.intervention.type,
|
|
||||||
"licensing_authority": self.instance.licensing_authority,
|
|
||||||
"licensing_authority_document_identifier": self.instance.licensing_authority_document_identifier,
|
|
||||||
"registration_office": self.instance.registration_office,
|
|
||||||
"registration_office_document_identifier": self.instance.registration_office_document_identifier,
|
|
||||||
"comment_licensing_authority": self.instance.licensing_authority_comment,
|
|
||||||
"comment_registration_office": self.instance.registration_office_comment,
|
|
||||||
"status": self.instance.state,
|
|
||||||
}
|
|
||||||
disabled_fields = [
|
|
||||||
"identifier",
|
|
||||||
]
|
|
||||||
self.load_initial_data(
|
|
||||||
form_data,
|
|
||||||
disabled_fields,
|
|
||||||
)
|
|
||||||
|
|
||||||
def save(self, user: User):
|
|
||||||
""" Persists changes from form to instance
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
process (Process): The edited process instance
|
|
||||||
"""
|
|
||||||
with transaction.atomic():
|
|
||||||
title = self.cleaned_data.get("title", None)
|
|
||||||
_type = self.cleaned_data.get("type", None)
|
|
||||||
licencing_auth = self.cleaned_data.get("licensing_authority", None)
|
|
||||||
licencing_auth_doc_id = self.cleaned_data.get("licensing_authority_document_identifier", None)
|
|
||||||
reg_off = self.cleaned_data.get("registration_office", None)
|
|
||||||
reg_off_doc_id = self.cleaned_data.get("registration_office_document_identifier", None)
|
|
||||||
comment_license = self.cleaned_data.get("comment_licensing_authority", None)
|
|
||||||
comment_registration = self.cleaned_data.get("comment_registration_office", None)
|
|
||||||
new_state = self.cleaned_data.get("status", None)
|
|
||||||
|
|
||||||
self.instance.licensing_authority = licencing_auth
|
|
||||||
self.instance.licensing_authority_document_identifier = licencing_auth_doc_id
|
|
||||||
self.instance.registration_office = reg_off
|
|
||||||
self.instance.registration_office_document_identifier = reg_off_doc_id
|
|
||||||
self.instance.state = ProcessStateEnum.PRIVATE.value
|
|
||||||
self.instance.created_by = user
|
|
||||||
self.instance.licensing_authority_comment = comment_license
|
|
||||||
self.instance.registration_office_comment = comment_registration
|
|
||||||
self.instance.state = new_state
|
|
||||||
self.instance.save()
|
|
||||||
|
|
||||||
self.instance.intervention.title = title
|
|
||||||
self.instance.intervention.type = _type
|
|
||||||
self.instance.intervention.created_by = user
|
|
||||||
self.instance.intervention.save()
|
|
||||||
|
|
||||||
return self.instance
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 17.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.db import models, transaction
|
|
||||||
|
|
||||||
from konova.models import BaseResource
|
|
||||||
from organisation.enums import RoleTypeEnum
|
|
||||||
from organisation.models import Organisation
|
|
||||||
from process.enums import ProcessStateEnum
|
|
||||||
from process.settings import PROCESS_STATE_STRINGS
|
|
||||||
|
|
||||||
|
|
||||||
class Process(BaseResource):
|
|
||||||
"""
|
|
||||||
Process links compensation, intervention and eco accounts. These links are realized as ForeignKeys in their models.
|
|
||||||
|
|
||||||
This process model therefore just holds further information on participated legal organizations.
|
|
||||||
|
|
||||||
Attribute 'state' holds information on the current state of the process, which are defined in ProcessStateEnum
|
|
||||||
"""
|
|
||||||
licensing_authority = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, blank=True, related_name="+")
|
|
||||||
licensing_authority_document_identifier = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
licensing_authority_comment = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
registration_office_document_identifier = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, blank=True, related_name="+")
|
|
||||||
registration_office_comment = models.CharField(max_length=500, null=True, blank=True)
|
|
||||||
state = models.PositiveIntegerField(choices=ProcessStateEnum.as_choices(drop_empty_choice=True), default=0)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
try:
|
|
||||||
intervention = self.intervention
|
|
||||||
title = intervention.title
|
|
||||||
except AttributeError:
|
|
||||||
title = "NO TITLE"
|
|
||||||
return title
|
|
||||||
|
|
||||||
def get_state_str(self):
|
|
||||||
"""
|
|
||||||
Translates the numeric state into a string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
return PROCESS_STATE_STRINGS.get(self.state, None)
|
|
||||||
|
|
||||||
def deactivate(self):
|
|
||||||
""" Deactivates a process and it's related elements
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self.is_active and not self.is_deleted:
|
|
||||||
self.toggle_deletion()
|
|
||||||
|
|
||||||
def activate(self):
|
|
||||||
""" Activates a process and it's related elements
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not self.is_active and self.is_deleted:
|
|
||||||
self.toggle_deletion()
|
|
||||||
|
|
||||||
def toggle_deletion(self):
|
|
||||||
""" Enables or disables a process
|
|
||||||
|
|
||||||
Processes are not truly removed from the database, just toggled in their flags 'is_active' and 'is_deleted'
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
with transaction.atomic():
|
|
||||||
self.is_active = not self.is_active
|
|
||||||
self.is_deleted = not self.is_deleted
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
# toggle related elements
|
|
||||||
comps = self.compensation.all()
|
|
||||||
elements = list(comps)
|
|
||||||
if self.intervention is not None:
|
|
||||||
elements.append(self.intervention)
|
|
||||||
|
|
||||||
for elem in elements:
|
|
||||||
elem.is_active = self.is_active
|
|
||||||
elem.is_deleted = self.is_deleted
|
|
||||||
elem.save()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_role_objects(user: User, order_by: str = "-created_on"):
|
|
||||||
""" Returns processes depending on the currently selected role of the user
|
|
||||||
|
|
||||||
* REGISTRATIONOFFICE
|
|
||||||
* User can see the processes where registration_office is set to the organisation of the currently selected role
|
|
||||||
* User can see self-created processes
|
|
||||||
* LICENSINGOFFICE
|
|
||||||
* same
|
|
||||||
* DATAPROVIDER
|
|
||||||
* User can see only self-created processes
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
order_by (str): Order by which Process attribute
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
role = user.current_role
|
|
||||||
if role is None:
|
|
||||||
return Process.objects.none()
|
|
||||||
_filter = {
|
|
||||||
"is_deleted": False,
|
|
||||||
}
|
|
||||||
if role.role.type == RoleTypeEnum.REGISTRATIONOFFICE.value:
|
|
||||||
_filter["registration_office"] = role.organisation
|
|
||||||
elif role.role.type == RoleTypeEnum.LICENSINGAUTHORITY.value:
|
|
||||||
_filter["licensing_authority"] = role.organisation
|
|
||||||
elif role.role.type == RoleTypeEnum.DATAPROVIDER.value:
|
|
||||||
# Nothing special
|
|
||||||
_filter["created_by"] = user
|
|
||||||
else:
|
|
||||||
# None of the above
|
|
||||||
pass
|
|
||||||
|
|
||||||
other_processes = Process.objects.filter(
|
|
||||||
**_filter
|
|
||||||
)
|
|
||||||
user_created_processes = Process.objects.filter(
|
|
||||||
created_by=user,
|
|
||||||
is_deleted=False,
|
|
||||||
)
|
|
||||||
qs = (other_processes | user_created_processes).distinct()
|
|
||||||
qs = qs.order_by(order_by)
|
|
||||||
return qs
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def create_from_intervention(intervention):
|
|
||||||
""" Creates a process for an intervention, in case an intervention has been created without a process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
intervention (Intervention): The intervention
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
process (Process)
|
|
||||||
"""
|
|
||||||
process = Process()
|
|
||||||
process.identifier = intervention.identifier
|
|
||||||
process.title = intervention.title
|
|
||||||
process.created_by = intervention.created_by
|
|
||||||
process.save()
|
|
||||||
|
|
||||||
intervention.process = process
|
|
||||||
intervention.save()
|
|
||||||
return process
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 25.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from process.enums import ProcessStateEnum
|
|
||||||
|
|
||||||
# DEFINES TRANSLATIONS FOR EACH PROCESSSTATEENUM
|
|
||||||
PROCESS_STATE_STRINGS = {
|
|
||||||
ProcessStateEnum.PRIVATE.value: _("private"),
|
|
||||||
ProcessStateEnum.ACCESSIBLE.value: _("accessible"),
|
|
||||||
ProcessStateEnum.LICENSED.value: _("licensed"),
|
|
||||||
ProcessStateEnum.OFFICIAL.value: _("official"),
|
|
||||||
ProcessStateEnum.RECORDED.value: _("recorded"),
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 25.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.template.loader import render_to_string
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.utils.html import format_html
|
|
||||||
|
|
||||||
from konova.utils.tables import BaseTable, ChoicesColumnForm
|
|
||||||
import django_tables2 as tables
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from process.enums import ProcessStateEnum
|
|
||||||
from process.models import Process
|
|
||||||
from process.settings import PROCESS_STATE_STRINGS
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessTable(BaseTable):
|
|
||||||
id = tables.Column(
|
|
||||||
verbose_name=_("Intervention identifier"),
|
|
||||||
orderable=True,
|
|
||||||
accessor="intervention.identifier",
|
|
||||||
)
|
|
||||||
t = tables.Column(
|
|
||||||
verbose_name=_("Title"),
|
|
||||||
orderable=True,
|
|
||||||
accessor="intervention.title",
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
THESE COLUMNS MIGHT NOT BE OF INTEREST. TO REDUCE TABLE WIDTH THEY CAN BE REMOVED
|
|
||||||
|
|
||||||
dila = tables.Column(
|
|
||||||
verbose_name=_("Licensing authority document identifier"),
|
|
||||||
orderable=True,
|
|
||||||
accessor="licensing_authority_document_identifier",
|
|
||||||
)
|
|
||||||
diro = tables.Column(
|
|
||||||
verbose_name=_("Registration office document identifier"),
|
|
||||||
orderable=True,
|
|
||||||
accessor="registration_office_document_identifier",
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
s = tables.Column(
|
|
||||||
verbose_name=_("Status"),
|
|
||||||
orderable=True,
|
|
||||||
accessor="state",
|
|
||||||
)
|
|
||||||
d = tables.Column(
|
|
||||||
verbose_name=_("Created on"),
|
|
||||||
orderable=True,
|
|
||||||
accessor="created_on",
|
|
||||||
)
|
|
||||||
ac = tables.Column(
|
|
||||||
verbose_name=_("Actions"),
|
|
||||||
orderable=False,
|
|
||||||
empty_values=[],
|
|
||||||
attrs={"td": {"class": "action-col"}}
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.title = _("Processes")
|
|
||||||
self.add_new_url = reverse("process:new")
|
|
||||||
|
|
||||||
def render_id(self, value, record: Process):
|
|
||||||
""" Renders the id column for an intervention
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (str): The identifier value
|
|
||||||
record (Process): The process record
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
html = ""
|
|
||||||
html += self.render_link(
|
|
||||||
tooltip=_("Open {}").format(_("Process")),
|
|
||||||
href=reverse("process:open", args=(record.id,)),
|
|
||||||
txt=value,
|
|
||||||
new_tab=False,
|
|
||||||
)
|
|
||||||
return format_html(html)
|
|
||||||
|
|
||||||
def render_s(self, value, record, column) -> str:
|
|
||||||
""" Translates the record state to a desired language
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (str): The value of state inside record
|
|
||||||
record (Process): The whole record itself
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str
|
|
||||||
"""
|
|
||||||
state = record.state
|
|
||||||
is_owner = record.created_by == self.request.user
|
|
||||||
choices = ProcessStateEnum.as_next_role_choices(self.request.user, state, is_owner)
|
|
||||||
valid_choices = [choice[0] for choice in choices]
|
|
||||||
if state in valid_choices:
|
|
||||||
form = ChoicesColumnForm(
|
|
||||||
action_url=reverse("process:edit-status", args=(record.id,)),
|
|
||||||
choices=choices,
|
|
||||||
initial={"select": state},
|
|
||||||
)
|
|
||||||
rendered = render_to_string("konova/choiceColumnForm.html", context={"form": form}, request=self.request)
|
|
||||||
else:
|
|
||||||
rendered = PROCESS_STATE_STRINGS.get(state)
|
|
||||||
return rendered
|
|
||||||
|
|
||||||
def render_ac(self, value, record):
|
|
||||||
"""
|
|
||||||
Renders possible actions for this record, such as delete.
|
|
||||||
"""
|
|
||||||
process = _("Process")
|
|
||||||
html = ""
|
|
||||||
html += self.render_open_btn(
|
|
||||||
_("Open {}").format(process),
|
|
||||||
reverse("process:open", args=(record.id,)),
|
|
||||||
)
|
|
||||||
html += self.render_edit_btn(
|
|
||||||
_("Edit {}").format(process),
|
|
||||||
reverse("process:edit", args=(record.id,)),
|
|
||||||
)
|
|
||||||
html += self.render_delete_btn(
|
|
||||||
_("Delete {}").format(process),
|
|
||||||
reverse("process:remove", args=(record.id,)),
|
|
||||||
)
|
|
||||||
return format_html(html)
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% load i18n static custom_tags %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<div class="rows">
|
|
||||||
<div class="columns">
|
|
||||||
<div class="large-10 column">
|
|
||||||
<h3>{% trans 'Process' %}: {{process.intervention.identifier}}</h3>
|
|
||||||
<h4>{{process.intervention.title}}</h4>
|
|
||||||
</div>
|
|
||||||
<div class="large-2 column">
|
|
||||||
<a href="{% url 'process:edit' process.id %}">
|
|
||||||
<button class="button small" role="button" value="{% trans 'Edit' %}"><em class='fas fa-edit'></em> {% trans 'Edit' %}</button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="rows">
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans 'Licencing Authority' %}</th>
|
|
||||||
<td>{{ process.licensing_authority }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans 'Licencing document identifier' %}</th>
|
|
||||||
<td>{{ process.licensing_authority_document_identifier }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans 'Registration office' %}</th>
|
|
||||||
<td>{{ process.registration_office }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans 'Registration document identifier' %}</th>
|
|
||||||
<td>{{ process.registration_office_document_identifier }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans 'Status' %}</th>
|
|
||||||
<td>
|
|
||||||
<span class="small info" title="{% trans 'Status' %}">
|
|
||||||
<em class="fas fa-exclamation-triangle"></em>
|
|
||||||
{{process.state|resolve_process_state}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans 'Intervention' %}</th>
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'intervention:open' process.intervention.id %}" target="_blank">
|
|
||||||
<button class="button small" role="button" title="{{process.intervention.title}} - {{process.intervention.type}}">{{process.intervention.identifier}}</button>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row" style="vertical-align: baseline">
|
|
||||||
{% trans 'Compensations' %}
|
|
||||||
<br>
|
|
||||||
<a href="{% url 'process:add-compensation' process.id %}" target="_blank">
|
|
||||||
<button class="button small" role="button" title="{% trans 'Add a new compensation' %}">
|
|
||||||
<em class="fas fa-plus-circle"></em>
|
|
||||||
{% trans 'New' %}
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
{% for compensation in process.compensations.all %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a href="{% url 'compensation:open' compensation.id %}" target="_blank">
|
|
||||||
<button class="button small" role="button" title="{{compensation.title}} - {{compensation.type}}">{{compensation.identifier}}</button>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td class="action-col">
|
|
||||||
<a href="{% url 'compensation:edit' compensation.id %}" title="{% trans 'Edit' %}"><button class="button small" title="{% trans 'Edit' %}"><em class='fas fa-edit'></em></button></a>
|
|
||||||
<a href="{% url 'compensation:remove' compensation.id %}" title="{% trans 'Remove' %}"><button class="button small" title="{% trans 'Remove' %}"><em class='fas fa-trash-alt'></em></button></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% empty %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{% trans 'No compensation' %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 25.11.20
|
|
||||||
|
|
||||||
"""
|
|
||||||
from django.urls import path
|
|
||||||
|
|
||||||
from process.views import index_view, new_view, open_view, edit_view, remove_view, edit_status_view, \
|
|
||||||
add_compensation_view
|
|
||||||
|
|
||||||
app_name = "process"
|
|
||||||
urlpatterns = [
|
|
||||||
path('', index_view, name='index'),
|
|
||||||
path('new/', new_view, name='new'),
|
|
||||||
path('open/<id>', open_view, name='open'),
|
|
||||||
path('edit/<id>', edit_view, name='edit'),
|
|
||||||
path('edit/<id>/status', edit_status_view, name='edit-status'),
|
|
||||||
path('remove/<id>', remove_view, name='remove'),
|
|
||||||
path('ac/<id>', add_compensation_view, name='add-compensation'),
|
|
||||||
]
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
from django.contrib import messages
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.http import HttpRequest
|
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from compensation.models import Compensation
|
|
||||||
from konova.contexts import BaseContext
|
|
||||||
from konova.decorators import resolve_user_role, valid_process_role_required
|
|
||||||
from konova.forms import RemoveForm
|
|
||||||
from konova.utils.tables import ChoicesColumnForm
|
|
||||||
from process.enums import ProcessStateEnum
|
|
||||||
from process.forms import NewProcessForm, EditProcessForm
|
|
||||||
from process.models import Process
|
|
||||||
from process.settings import PROCESS_STATE_STRINGS
|
|
||||||
from process.tables import ProcessTable
|
|
||||||
|
|
||||||
# URL definitions
|
|
||||||
PROCESS_INDEX_URL = "process:index"
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@resolve_user_role
|
|
||||||
def index_view(request: HttpRequest):
|
|
||||||
"""
|
|
||||||
Renders the index view for process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A rendered view
|
|
||||||
"""
|
|
||||||
template = "generic_index.html"
|
|
||||||
user = request.user
|
|
||||||
processes = Process.get_role_objects(user)
|
|
||||||
table = ProcessTable(
|
|
||||||
request=request,
|
|
||||||
queryset=processes
|
|
||||||
)
|
|
||||||
context = {
|
|
||||||
"table": table,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def new_view(request: HttpRequest):
|
|
||||||
"""
|
|
||||||
Renders a view for a new process creation
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "konova/form.html"
|
|
||||||
form = NewProcessForm(request.POST or None)
|
|
||||||
if request.method == "POST":
|
|
||||||
if form.is_valid():
|
|
||||||
process = form.save(request.user)
|
|
||||||
intervention = process.intervention
|
|
||||||
messages.info(request, _("A process is based on an intervention. Please fill in the missing data for this intervention"))
|
|
||||||
return redirect("intervention:edit", id=intervention.id)
|
|
||||||
else:
|
|
||||||
messages.error(request, _("Invalid input"))
|
|
||||||
else:
|
|
||||||
# For clarification: Nothing to do here
|
|
||||||
pass
|
|
||||||
context = {
|
|
||||||
"form": form,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def open_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a detail view for this process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The uuid id as string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "process/open.html"
|
|
||||||
process = get_object_or_404(Process, id=id)
|
|
||||||
context = {
|
|
||||||
"process": process,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@resolve_user_role
|
|
||||||
def edit_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders an edit view for this process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The uuid id as string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "konova/form.html"
|
|
||||||
process = get_object_or_404(Process, id=id)
|
|
||||||
if request.method == "POST":
|
|
||||||
form = EditProcessForm(request.POST or None, instance=process, user=request.user)
|
|
||||||
if form.is_valid():
|
|
||||||
process = form.save(request.user)
|
|
||||||
messages.success(request, _("{} edited").format(process))
|
|
||||||
return redirect("process:index")
|
|
||||||
else:
|
|
||||||
messages.error(request, _("Invalid input"))
|
|
||||||
form = EditProcessForm(instance=process, user=request.user)
|
|
||||||
context = {
|
|
||||||
"form": form,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def remove_view(request: HttpRequest, id: str):
|
|
||||||
""" Renders a remove view for this process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The uuid id as string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
template = "konova/form.html"
|
|
||||||
process = get_object_or_404(Process, id=id)
|
|
||||||
if request.method == "POST":
|
|
||||||
form = RemoveForm(
|
|
||||||
request.POST or None,
|
|
||||||
object_to_remove=process,
|
|
||||||
remove_post_url=reverse("process:remove", args=(id,)),
|
|
||||||
cancel_url=reverse("process:index"),
|
|
||||||
)
|
|
||||||
if form.is_valid():
|
|
||||||
confirmed = form.is_checked()
|
|
||||||
if confirmed:
|
|
||||||
process.deactivate()
|
|
||||||
messages.success(request, _("Process {} removed").format(process))
|
|
||||||
return redirect("process:index")
|
|
||||||
else:
|
|
||||||
messages.error(request, _("Invalid input"))
|
|
||||||
|
|
||||||
form = RemoveForm(
|
|
||||||
object_to_remove=process,
|
|
||||||
remove_post_url=reverse("process:remove", args=(id,)),
|
|
||||||
cancel_url=reverse("process:index"),
|
|
||||||
)
|
|
||||||
context = {
|
|
||||||
"form": form,
|
|
||||||
}
|
|
||||||
context = BaseContext(request, context).context
|
|
||||||
return render(request, template, context)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def edit_status_view(request: HttpRequest, id: str):
|
|
||||||
""" Changes only the status of a process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (The incoming request):
|
|
||||||
id ():
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
process = get_object_or_404(Process, id=id)
|
|
||||||
old_state = process.state
|
|
||||||
form = ChoicesColumnForm(request.POST or None, choices=ProcessStateEnum.as_choices(drop_empty_choice=True))
|
|
||||||
if request.method == "POST":
|
|
||||||
if form.is_valid():
|
|
||||||
process.state = int(form.cleaned_data.get("select", -1))
|
|
||||||
process.save()
|
|
||||||
_from = PROCESS_STATE_STRINGS.get(old_state)
|
|
||||||
_to = PROCESS_STATE_STRINGS.get(process.state)
|
|
||||||
messages.info(request, _("{} status changed from {} to {}").format(process.intervention.title, _from, _to))
|
|
||||||
else:
|
|
||||||
messages.error(request, form.errors)
|
|
||||||
return redirect("process:index")
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def add_compensation_view(request: HttpRequest, id: str):
|
|
||||||
""" Adds a new compensation to a process
|
|
||||||
|
|
||||||
Args:
|
|
||||||
request (HttpRequest): The incoming request
|
|
||||||
id (str): The process' id
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
process = get_object_or_404(Process, id=id)
|
|
||||||
comp = Compensation()
|
|
||||||
comp.process = process
|
|
||||||
comp.save()
|
|
||||||
messages.info(request, _("Please fill in the data for this compensation"))
|
|
||||||
return redirect("compensation:edit", id=comp.id)
|
|
||||||
#template = ""
|
|
||||||
#context = {}
|
|
||||||
#context = BaseContext(request, context).context
|
|
||||||
#return render(request, template, context)
|
|
||||||
@@ -1,20 +1,25 @@
|
|||||||
asgiref==3.3.1
|
asgiref==3.3.1
|
||||||
|
beautifulsoup4==4.9.3
|
||||||
certifi==2020.11.8
|
certifi==2020.11.8
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
Django==3.1.3
|
Django==3.1.3
|
||||||
django-autocomplete-light==3.8.1
|
django-autocomplete-light==3.8.1
|
||||||
|
django-bootstrap4==3.0.1
|
||||||
django-debug-toolbar==3.1.1
|
django-debug-toolbar==3.1.1
|
||||||
django-filter==2.4.0
|
django-filter==2.4.0
|
||||||
django-fontawesome-5==1.0.18
|
django-fontawesome-5==1.0.18
|
||||||
django-simple-sso==0.14.1
|
django-simple-sso==0.14.1
|
||||||
django-tables2==2.3.3
|
django-tables2==2.3.3
|
||||||
idna==2.10
|
idna==2.10
|
||||||
|
importlib-metadata==2.1.1
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
pkg-resources==0.0.0
|
pkg-resources==0.0.0
|
||||||
psycopg2==2.8.6
|
psycopg2==2.8.6
|
||||||
pytz==2020.4
|
pytz==2020.4
|
||||||
requests==2.25.0
|
requests==2.25.0
|
||||||
six==1.15.0
|
six==1.15.0
|
||||||
|
soupsieve==2.2.1
|
||||||
sqlparse==0.4.1
|
sqlparse==0.4.1
|
||||||
urllib3==1.26.2
|
urllib3==1.26.2
|
||||||
webservices==0.7
|
webservices==0.7
|
||||||
|
zipp==3.4.1
|
||||||
+2
-6
@@ -4,12 +4,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{{ base_title }}</title>
|
<title>{{ base_title }}</title>
|
||||||
<link rel="stylesheet" href="{% static 'css/messages.css' %}">
|
{% bootstrap_css %}
|
||||||
<link rel="stylesheet" href="{% static 'css/mulewf.css' %}">
|
{% bootstrap_javascript jquery='full' %}
|
||||||
<link rel="stylesheet" href="{% static 'css/konova.css' %}">
|
|
||||||
<script type="text/javascript" src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'js/jquery-ui.min.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'js/mulewf.min.js' %}"></script>
|
|
||||||
{% fontawesome_5_static %}
|
{% fontawesome_5_static %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user