diff --git a/smash/web/api_urls.py b/smash/web/api_urls.py index 1e857c912c3ff06ac327010207edaf1c69b8febe..22f3d57d57fc202b1e9cf0a6a780e15265c5602b 100644 --- a/smash/web/api_urls.py +++ b/smash/web/api_urls.py @@ -54,6 +54,15 @@ urlpatterns = [ url(r'^specializations$', worker.specializations, name='web.api.specializations'), url(r'^units$', worker.units, name='web.api.units'), + # workers + url(r'^workers/(?P<worker_role>[A-z]+)/$', worker.get_workers, name='web.api.workers'), + + url(r'^workers/add_availability/(?P<worker_id>\d+)/(?P<weekday>[0-9])/(?P<start_hour>\d{2}:\d{2})/(?P<end_hour>\d{2}:\d{2})/$', + worker.add_worker_availability, name='web.api.workers.add_availability'), + + url(r'^workers/add_extra_availability/(?P<worker_id>\d+)/(?P<start_str_date>\d{4}-\d{2}-\d{2}-\d{2}-\d{2})/(?P<end_str_date>\d{4}-\d{2}-\d{2}-\d{2}-\d{2})/$', + worker.add_worker_extra_availability, name='web.api.workers.add_extra_availability'), + # daily planning data url(r'^daily_planning/workers/$', worker.workers_for_daily_planning, name='web.api.workers.daily_planning'), url(r'^daily_planning/workers/availabilities$', worker.availabilities, name='web.api.workers.daily_planning.availabilities'), @@ -62,7 +71,8 @@ urlpatterns = [ url(r'^workers/(?P<worker_role>[A-z]+)/$', worker.get_workers, name='web.api.workers'), # daily planning events - url(r'^events/(?P<date>\d{4}-\d{2}-\d{2})/$', daily_planning.events, name='web.api.events'), + url(r'^events/(?P<date>\d{4}-\d{2}-\d{2})/include_all$', daily_planning.events, {'include_all': True}, name='web.api.events_all'), + url(r'^events/(?P<date>\d{4}-\d{2}-\d{2})/$', daily_planning.events, {'include_all': False}, name='web.api.events'), url(r'^availabilities/(?P<date>\d{4}-\d{2}-\d{2})/$', daily_planning.availabilities, name='web.api.availabilities'), url(r'^events_persist$', daily_planning.events_persist, name='web.api.events_persist'), diff --git a/smash/web/api_views/appointment.py b/smash/web/api_views/appointment.py index cdc4e8e499f7f06dd9277e3895b1a11b077e9060..23547b625a624aed307e05739f268b97a1e953cf 100644 --- a/smash/web/api_views/appointment.py +++ b/smash/web/api_views/appointment.py @@ -173,6 +173,7 @@ def serialize_appointment(appointment): last_name = "" subject_type = "" nd_number = screening_number = phone_numbers = appointment_type_names = None + status = appointment.status if appointment.visit is not None: title = "Visit " + str(appointment.visit.visit_number) study_subject = appointment.visit.subject @@ -198,6 +199,7 @@ def serialize_appointment(appointment): flying_team = flying_team_to_str(appointment.flying_team) result = { + "status": status, "subject": subject_string, "title": title, "nd_number": nd_number, diff --git a/smash/web/api_views/daily_planning.py b/smash/web/api_views/daily_planning.py index d7a64bfb3676beae78641f8d9b85b0abf8acc190..0b6589660e30ff3dc6005b24ecbaddbadee35f04 100644 --- a/smash/web/api_views/daily_planning.py +++ b/smash/web/api_views/daily_planning.py @@ -203,10 +203,16 @@ def get_conflicts(worker, date): return result -def get_generic_appointment_events(request, date): +def get_generic_appointment_events(request, date, include_all=False): result = {} - appointments = Appointment.objects.filter( + if include_all: + appointments = Appointment.objects.filter( + datetime_when__date=date, + location__in=get_filter_locations(request.user), + visit__isnull=True).all() + else: + appointments = Appointment.objects.filter( datetime_when__date=date, location__in=get_filter_locations(request.user), status=Appointment.APPOINTMENT_STATUS_SCHEDULED, @@ -217,6 +223,7 @@ def get_generic_appointment_events(request, date): appointment_data = { 'name': "GENERAL", 'id': appointment.id, + 'status': appointment.status, 'color': RANDOM_COLORS[len(RANDOM_COLORS) - 1], 'start': "", 'location': str(appointment.location), @@ -233,6 +240,7 @@ def get_generic_appointment_events(request, date): event = { 'title': appointment.title(), 'short_title': appointment.title(), + 'status': appointment.status, 'duration': build_duration(appointment.length), 'id': 'app-{}'.format(appointment.id), 'appointment_id': appointment.id, @@ -250,24 +258,40 @@ def get_generic_appointment_events(request, date): return result.values() -def events(request, date): - appointments = Appointment.objects.filter( +def events(request, date, include_all=False): + #fetch appointments + if include_all: + appointments = Appointment.objects.filter( + datetime_when__date=date, + location__in=get_filter_locations(request.user), + visit__isnull=False).all() + else: + appointments = Appointment.objects.filter( datetime_when__date=date, location__in=get_filter_locations(request.user), status=Appointment.APPOINTMENT_STATUS_SCHEDULED, visit__isnull=False).all() + #store subjects subjects = {} + #for each appointment for i, appointment in enumerate(appointments): + #get its subject appointment_subject = appointment.visit.subject + #if there is a subject we add it to the subjects dict if appointment_subject.id not in subjects: # create subject + flag_set = set([language.image.url for language in appointment_subject.subject.languages.all() if language.image is not None]) + default_language = appointment_subject.subject.default_written_communication_language + if default_language is not None and default_language.image is not None: + flag_set.add(default_language.image.url) + subject = { 'name': unicode(appointment_subject), 'id': appointment_subject.id, 'appointment_id': appointment.id, 'color': RANDOM_COLORS[i], 'start': appointment.datetime_when.replace(tzinfo=None).strftime("%H:%M"), - 'flags': [language.image.url for language in appointment_subject.subject.languages.all()], + 'flags': list(flag_set), # this indicates only location of the first appointment # (there is small chance to have two appointments in two different places at the same day) 'location': str(appointment.location), @@ -275,8 +299,10 @@ def events(request, date): } subjects[appointment_subject.id] = subject + #get appointment type link of the appointment links = AppointmentTypeLink.objects.filter( appointment=appointment).all() + #for the AppointmentTypeLink, get all the info and create the event object for j, link in enumerate(links): link_when = link.date_when link_end = None @@ -287,6 +313,7 @@ def events(request, date): minutes=link.appointment_type.default_duration) event = { 'title': link.appointment_type.description, + 'status': link.appointment.status, 'short_title': link.appointment_type.code, 'duration': build_duration(link.appointment_type.default_duration), 'subject': unicode(appointment_subject), @@ -303,7 +330,7 @@ def events(request, date): subject_events = subjects[appointment_subject.id]['events'] subject_events.append(event) - generic_appointment_events = get_generic_appointment_events(request, date) + generic_appointment_events = get_generic_appointment_events(request, date, include_all=include_all) availabilities = [] holidays = [] diff --git a/smash/web/api_views/worker.py b/smash/web/api_views/worker.py index b2b69403825c232a9f0db883c0c90d8bf7ce9b5f..7b7d99e84103e4939ca4544e733d82dfdc7f5b9e 100644 --- a/smash/web/api_views/worker.py +++ b/smash/web/api_views/worker.py @@ -7,8 +7,9 @@ from django.utils import timezone from django.shortcuts import get_object_or_404 from web.models.constants import GLOBAL_STUDY_ID from web.api_views.daily_planning import get_workers_for_daily_planning, get_availabilities -from ..models import Worker from ..models.worker_study_role import WORKER_STAFF, WORKER_HEALTH_PARTNER, WORKER_VOUCHER_PARTNER +from ..models import Worker, Availability, Holiday +from web.models.constants import AVAILABILITY_EXTRA logger = logging.getLogger(__name__) @@ -111,6 +112,43 @@ def serialize_worker(worker): } return result +def add_worker_availability(request, worker_id, weekday, start_hour, end_hour): + + if worker_id is None or weekday is None or start_hour is None or end_hour is None: + context = { + 'status': '400', 'reason': 'Either worker_id, weekday, start_hour, end_hour or all of them are invalid.' + } + response = HttpResponse(json.dumps(context), content_type='application/json') + response.status_code = 400 + return response + + worker = get_object_or_404(Worker, id=int(worker_id)) + + availability, _ = Availability.objects.update_or_create(person=worker, day_number=weekday, + defaults={'available_from': start_hour, 'available_till': end_hour}) + availability.save() + + return JsonResponse({}, status=200) + +def add_worker_extra_availability(request, worker_id, start_str_date, end_str_date): + + if start_str_date is None or end_str_date is None or worker_id is None: + context = { + 'status': '400', 'reason': 'Either start_date, end_str_date, worker_id or all of them are invalid.' + } + response = HttpResponse(json.dumps(context), content_type='application/json') + response.status_code = 400 + return response + + start_date = datetime.datetime.strptime(start_str_date, "%Y-%m-%d-%H-%M").replace(tzinfo=timezone.now().tzinfo) + end_date = datetime.datetime.strptime(end_str_date, "%Y-%m-%d-%H-%M").replace(tzinfo=timezone.now().tzinfo) + worker = get_object_or_404(Worker, id=int(worker_id)) + + extra_availability, _ = Holiday.objects.update_or_create(person=worker, datetime_start=start_date, datetime_end=end_date, kind=AVAILABILITY_EXTRA) + extra_availability.save() + + return JsonResponse({}, status=200) + def get_worker_availability(request): start_str_date = request.GET.get("start_date") end_str_date = request.GET.get("end_date") diff --git a/smash/web/decorators.py b/smash/web/decorators.py index fed40f38b0a7cb104e0256d282581d09a204ba30..b3124a1fb1f939be60a2b623405a514f4015a3a7 100644 --- a/smash/web/decorators.py +++ b/smash/web/decorators.py @@ -60,6 +60,13 @@ class PermissionDecorator: permissions_queryset = None n_decorators = 0 + ''' + IMPORTANT !! Be careful when adding new decorator. You must check the codename in the Permission list + This Permission list is automatically created by Django and you can list it with the following code: + + from django.contrib.auth.models import Permission + logger.warn([p.codename for p in Permission.objects.all()]) + ''' @staticmethod def get_permissions(): if PermissionDecorator.permissions_queryset is None or len(PermissionDecorator.codenames) > len(PermissionDecorator.permissions_queryset): @@ -103,7 +110,7 @@ class PermissionDecorator: permissions = roles[0].permissions.filter(codename=self.perm_codename) if len(permissions) > 0: return func(thing, *args, **kwargs) - messages.error(request, 'You are not authorized to view this page. Request permissions to the system administrator.') + messages.error(request, 'You are not authorized to view this page or perform this action. Request permissions to the system administrator.') #avoid loops if the HTTP_REFERER header is set to the visited URL http_referer = request.META.get('HTTP_REFERER', 'web.views.index') if http_referer == request.build_absolute_uri() or http_referer == request.path: diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py index bc97e8b069bc1abefce9d7628d9384392f8c5995..208410ad403725a147ea1e63a133fb3c5e57bab6 100644 --- a/smash/web/forms/study_subject_forms.py +++ b/smash/web/forms/study_subject_forms.py @@ -192,7 +192,9 @@ def validate_subject_screening_number(self, cleaned_data): def validate_subject_nd_number(self, cleaned_data): if self.study.columns.nd_number: nd_number = cleaned_data['nd_number'] - if nd_number != "": + if nd_number is None: + self.add_error('nd_number', "None ND number. ND number can be blank but not None.") + elif nd_number: if not self.study.check_nd_number(nd_number): self.add_error('nd_number', "Invalid ND number") else: @@ -201,7 +203,7 @@ def validate_subject_nd_number(self, cleaned_data): if subjects_from_db: if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''): self.add_error('nd_number', "ND number already in use") - + #else: #empty nd_number is valid def validate_subject_resign_reason(self, cleaned_data): if self.study.columns.resigned and self.study.columns.resign_reason: diff --git a/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.min.css b/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.min.css new file mode 100755 index 0000000000000000000000000000000000000000..efccc47678ca63f71469a80f41451544d8b0caf9 --- /dev/null +++ b/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.min.css @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.11.4 - 2015-03-11 +* http://jqueryui.com +* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url("images/ui-bg_highlight-soft_100_eeeeee_1x100.png") 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url("images/ui-bg_gloss-wave_35_f6a828_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url("images/ui-bg_glass_100_f6f6f6_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url("images/ui-bg_glass_100_fdf5ce_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url("images/ui-bg_highlight-soft_75_ffe45c_1x100.png") 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url("images/ui-bg_diagonals-thick_18_b81900_40x40.png") 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_228ef1_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_ffd27a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url("images/ui-bg_diagonals-thick_20_666666_40x40.png") 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url("images/ui-bg_flat_10_000000_40x100.png") 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px} \ No newline at end of file diff --git a/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.structure.min.css b/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.structure.min.css new file mode 100755 index 0000000000000000000000000000000000000000..46f0ac900b0af7a38bf5043f7940e8350d88a291 --- /dev/null +++ b/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.structure.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.11.4 - 2015-03-11 +* http://jqueryui.com +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px} \ No newline at end of file diff --git a/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.theme.min.css b/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.theme.min.css new file mode 100755 index 0000000000000000000000000000000000000000..7ccfb2fde1de18f2368f59073ec51dec818f844b --- /dev/null +++ b/smash/web/static/AdminLTE/plugins/jQueryUI/jquery-ui.theme.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.11.4 - 2015-03-11 +* http://jqueryui.com +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url("images/ui-bg_highlight-soft_100_eeeeee_1x100.png") 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url("images/ui-bg_gloss-wave_35_f6a828_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url("images/ui-bg_glass_100_f6f6f6_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url("images/ui-bg_glass_100_fdf5ce_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url("images/ui-bg_highlight-soft_75_ffe45c_1x100.png") 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url("images/ui-bg_diagonals-thick_18_b81900_40x40.png") 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_228ef1_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_ffd27a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url("images/ui-bg_diagonals-thick_20_666666_40x40.png") 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url("images/ui-bg_flat_10_000000_40x100.png") 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px} \ No newline at end of file diff --git a/smash/web/static/AdminLTE/plugins/moment.js/moment-range.min.js b/smash/web/static/AdminLTE/plugins/moment.js/moment-range.min.js new file mode 100644 index 0000000000000000000000000000000000000000..8fb1bf2a30c49148e217a35ecfa780716fbfff2f --- /dev/null +++ b/smash/web/static/AdminLTE/plugins/moment.js/moment-range.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("moment")):"function"==typeof define&&define.amd?define("moment-range",["moment"],e):"object"==typeof exports?exports["moment-range"]=e(require("moment")):t["moment-range"]=e(t.moment)}(this,function(t){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=19)}([function(t,e,n){"use strict";t.exports=n(15)()?Symbol:n(17)},function(e,n){e.exports=t},function(t,e,n){"use strict";var r,o=n(3),i=n(10),u=n(6),a=n(12);r=t.exports=function(t,e){var n,r,u,s,c;return arguments.length<2||"string"!=typeof t?(s=e,e=t,t=null):s=arguments[2],null==t?(n=u=!0,r=!1):(n=a.call(t,"c"),r=a.call(t,"e"),u=a.call(t,"w")),c={value:e,configurable:n,enumerable:r,writable:u},s?o(i(s),c):c},r.gs=function(t,e,n){var r,s,c,f;return"string"!=typeof t?(c=n,n=e,e=t,t=null):c=arguments[3],null==e?e=void 0:u(e)?null==n?n=void 0:u(n)||(c=n,n=void 0):(c=e,e=n=void 0),null==t?(r=!0,s=!1):(r=a.call(t,"c"),s=a.call(t,"e")),f={get:e,set:n,configurable:r,enumerable:s},c?o(i(c),f):f}},function(t,e,n){"use strict";t.exports=n(4)()?Object.assign:n(5)},function(t,e,n){"use strict";t.exports=function(){var t,e=Object.assign;return"function"==typeof e&&(t={foo:"raz"},e(t,{bar:"dwa"},{trzy:"trzy"}),t.foo+t.bar+t.trzy==="razdwatrzy")}},function(t,e,n){"use strict";var r=n(7),o=n(11),i=Math.max;t.exports=function(t,e){var n,u,a,s=i(arguments.length,2);for(t=Object(o(t)),a=function(r){try{t[r]=e[r]}catch(t){n||(n=t)}},u=1;u<s;++u)e=arguments[u],r(e).forEach(a);if(void 0!==n)throw n;return t}},function(t,e,n){"use strict";t.exports=function(t){return"function"==typeof t}},function(t,e,n){"use strict";t.exports=n(8)()?Object.keys:n(9)},function(t,e,n){"use strict";t.exports=function(){try{return Object.keys("primitive"),!0}catch(t){return!1}}},function(t,e,n){"use strict";var r=Object.keys;t.exports=function(t){return r(null==t?t:Object(t))}},function(t,e,n){"use strict";var r=Array.prototype.forEach,o=Object.create,i=function(t,e){var n;for(n in t)e[n]=t[n]};t.exports=function(t){var e=o(null);return r.call(arguments,function(t){null!=t&&i(Object(t),e)}),e}},function(t,e,n){"use strict";t.exports=function(t){if(null==t)throw new TypeError("Cannot use null or undefined");return t}},function(t,e,n){"use strict";t.exports=n(13)()?String.prototype.contains:n(14)},function(t,e,n){"use strict";var r="razdwatrzy";t.exports=function(){return"function"==typeof r.contains&&(r.contains("dwa")===!0&&r.contains("foo")===!1)}},function(t,e,n){"use strict";var r=String.prototype.indexOf;t.exports=function(t){return r.call(this,t,arguments[1])>-1}},function(t,e,n){"use strict";var r={object:!0,symbol:!0};t.exports=function(){var t;if("function"!=typeof Symbol)return!1;t=Symbol("test symbol");try{String(t)}catch(t){return!1}return!!r[typeof Symbol.iterator]&&(!!r[typeof Symbol.toPrimitive]&&!!r[typeof Symbol.toStringTag])}},function(t,e,n){"use strict";t.exports=function(t){return!!t&&("symbol"==typeof t||!!t.constructor&&("Symbol"===t.constructor.name&&"Symbol"===t[t.constructor.toStringTag]))}},function(t,e,n){"use strict";var r,o,i,u,a=n(2),s=n(18),c=Object.create,f=Object.defineProperties,l=Object.defineProperty,v=Object.prototype,p=c(null);if("function"==typeof Symbol){r=Symbol;try{String(r()),u=!0}catch(t){}}var y=function(){var t=c(null);return function(e){for(var n,r,o=0;t[e+(o||"")];)++o;return e+=o||"",t[e]=!0,n="@@"+e,l(v,n,a.gs(null,function(t){r||(r=!0,l(this,n,a(t)),r=!1)})),n}}();i=function(t){if(this instanceof i)throw new TypeError("TypeError: Symbol is not a constructor");return o(t)},t.exports=o=function t(e){var n;if(this instanceof t)throw new TypeError("TypeError: Symbol is not a constructor");return u?r(e):(n=c(i.prototype),e=void 0===e?"":String(e),f(n,{__description__:a("",e),__name__:a("",y(e))}))},f(o,{for:a(function(t){return p[t]?p[t]:p[t]=o(String(t))}),keyFor:a(function(t){var e;s(t);for(e in p)if(p[e]===t)return e}),hasInstance:a("",r&&r.hasInstance||o("hasInstance")),isConcatSpreadable:a("",r&&r.isConcatSpreadable||o("isConcatSpreadable")),iterator:a("",r&&r.iterator||o("iterator")),match:a("",r&&r.match||o("match")),replace:a("",r&&r.replace||o("replace")),search:a("",r&&r.search||o("search")),species:a("",r&&r.species||o("species")),split:a("",r&&r.split||o("split")),toPrimitive:a("",r&&r.toPrimitive||o("toPrimitive")),toStringTag:a("",r&&r.toStringTag||o("toStringTag")),unscopables:a("",r&&r.unscopables||o("unscopables"))}),f(i.prototype,{constructor:a(o),toString:a("",function(){return this.__name__})}),f(o.prototype,{toString:a(function(){return"Symbol ("+s(this).__description__+")"}),valueOf:a(function(){return s(this)})}),l(o.prototype,o.toPrimitive,a("",function(){var t=s(this);return"symbol"==typeof t?t:t.toString()})),l(o.prototype,o.toStringTag,a("c","Symbol")),l(i.prototype,o.toStringTag,a("c",o.prototype[o.toStringTag])),l(i.prototype,o.toPrimitive,a("c",o.prototype[o.toPrimitive]))},function(t,e,n){"use strict";var r=n(16);t.exports=function(t){if(!r(t))throw new TypeError(t+" is not a symbol");return t}},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{default:t}}function o(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function u(t){return t.range=function(e,n){var r=this;return y.hasOwnProperty(e)?new d(t(r).startOf(e),t(r).endOf(e)):new d(e,n)},t.fn.range=t.range,t.range.constructor=d,t.fn.within=function(t){return t.contains(this.toDate())},t}Object.defineProperty(e,"__esModule",{value:!0}),e.DateRange=void 0;var a=function(){function t(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var u,a=t[Symbol.iterator]();!(r=(u=a.next()).done)&&(n.push(u.value),!e||n.length!==e);r=!0);}catch(t){o=!0,i=t}finally{try{!r&&a.return&&a.return()}finally{if(o)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},c=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}();e.extendMoment=u;var f=n(1),l=r(f),v=n(0),p=r(v),y={year:!0,quarter:!0,month:!0,week:!0,day:!0,hour:!0,minute:!0,second:!0},d=e.DateRange=function(){function t(e,n){i(this,t);var r=e,o=n;if(1===arguments.length||void 0===n)if("object"===("undefined"==typeof e?"undefined":s(e))&&2===e.length){var u=a(e,2);r=u[0],o=u[1]}else if("string"==typeof e){var c=e.split("/"),f=a(c,2);r=f[0],o=f[1]}this.start=null===r?(0,l.default)(-864e13):(0,l.default)(r),this.end=null===o?(0,l.default)(864e13):(0,l.default)(o)}return c(t,[{key:"adjacent",value:function(t){var e=this.start.isSame(t.end),n=this.end.isSame(t.start);return e&&t.start.valueOf()<=this.start.valueOf()||n&&t.end.valueOf()>=this.end.valueOf()}},{key:"add",value:function(t){return this.overlaps(t)?new this.constructor(l.default.min(this.start,t.start),l.default.max(this.end,t.end)):null}},{key:"by",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{exclusive:!1,step:1},n=this;return o({},p.default.iterator,function(){var r=e.exclusive||!1,o=e.step||1,i=Math.abs(n.start.diff(n.end,t))/o,u=0;return{next:function(){var e=n.start.clone().add(u*o,t),a=r?!(u<i):!(u<=i);return u++,{done:a,value:a?void 0:e}}}})}},{key:"byRange",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{exclusive:!1,step:1},n=this,r=e.step||1,i=this.valueOf()/t.valueOf()/r,u=e.exclusive||!1,a=Math.floor(i),s=0;return o({},p.default.iterator,function(){return a===1/0?{done:!0}:{next:function(){var e=(0,l.default)(n.start.valueOf()+t.valueOf()*s*r),o=a===i&&u?!(s<a):!(s<=a);return s++,{done:o,value:o?void 0:e}}}})}},{key:"center",value:function t(){var t=this.start.valueOf()+this.diff()/2;return(0,l.default)(t)}},{key:"clone",value:function(){return new this.constructor(this.start,this.end)}},{key:"contains",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{exclusive:!1},r=this.start.valueOf(),o=this.end.valueOf(),i=e.valueOf(),u=e.valueOf();e instanceof t&&(i=e.start.valueOf(),u=e.end.valueOf());var a=r<i||r<=i&&!n.exclusive,s=o>u||o>=u&&!n.exclusive;return a&&s}},{key:"diff",value:function(t,e){return this.end.diff(this.start,t,e)}},{key:"duration",value:function(t,e){return this.diff(t,e)}},{key:"intersect",value:function(t){var e=this.start.valueOf(),n=this.end.valueOf(),r=t.start.valueOf(),o=t.end.valueOf();return e<=r&&r<n&&n<o?new this.constructor(r,n):r<e&&e<o&&o<=n?new this.constructor(e,o):r<e&&e<=n&&n<o?this:e<=r&&r<=o&&o<=n?t:null}},{key:"isEqual",value:function(t){return this.start.isSame(t.start)&&this.end.isSame(t.end)}},{key:"isSame",value:function(t){return this.isEqual(t)}},{key:"overlaps",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{adjacent:!1},n=null!==this.intersect(t);return e.adjacent&&!n?this.adjacent(t):n}},{key:"reverseBy",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{exclusive:!1,step:1},n=this;return o({},p.default.iterator,function(){var r=e.exclusive||!1,o=e.step||1,i=Math.abs(n.start.diff(n.end,t))/o,u=0;return{next:function(){var e=n.end.clone().subtract(u*o,t),a=r?!(u<i):!(u<=i);return u++,{done:a,value:a?void 0:e}}}})}},{key:"reverseByRange",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{exclusive:!1,step:1},n=this,r=e.step||1,i=this.valueOf()/t.valueOf()/r,u=e.exclusive||!1,a=Math.floor(i),s=0;return o({},p.default.iterator,function(){return a===1/0?{done:!0}:{next:function(){var e=(0,l.default)(n.end.valueOf()-t.valueOf()*s*r),o=a===i&&u?!(s<a):!(s<=a);return s++,{done:o,value:o?void 0:e}}}})}},{key:"subtract",value:function(t){var e=this.start.valueOf(),n=this.end.valueOf(),r=t.start.valueOf(),o=t.end.valueOf();return null===this.intersect(t)?[this]:r<=e&&e<n&&n<=o?[]:r<=e&&e<o&&o<n?[new this.constructor(o,n)]:e<r&&r<n&&n<=o?[new this.constructor(e,r)]:e<r&&r<o&&o<n?[new this.constructor(e,r),new this.constructor(o,n)]:e<r&&r<n&&o<n?[new this.constructor(e,r),new this.constructor(r,n)]:[]}},{key:"toDate",value:function(){return[this.start.toDate(),this.end.toDate()]}},{key:"toString",value:function(){return this.start.format()+"/"+this.end.format()}},{key:"valueOf",value:function(){return this.end.valueOf()-this.start.valueOf()}}]),t}()}])}); +//# sourceMappingURL=moment-range.min.js.map \ No newline at end of file diff --git a/smash/web/static/css/daily_planning.css b/smash/web/static/css/daily_planning.css index 0fef5841305f2622e97ed7c698fa8a998a790960..fc61fd5cc3e62103e2a77d9569048b5e9f7f8ca8 100644 --- a/smash/web/static/css/daily_planning.css +++ b/smash/web/static/css/daily_planning.css @@ -5,7 +5,6 @@ .subjects-events h4 { font-size: 16px; margin-top: 0; - padding-top: 1em; } .subjects-events .fc-event { diff --git a/smash/web/static/js/appointment.js b/smash/web/static/js/appointment.js index 86ad7cd8848bb9b1752d434a6c72cd799438e141..120abf0f6a8a9058db72a64a6444388fb8a921a1 100644 --- a/smash/web/static/js/appointment.js +++ b/smash/web/static/js/appointment.js @@ -250,6 +250,7 @@ function get_calendar_events_function(source, allow_url_redirection, day_headers } var event = { title: title, + status: entry.status, start: entry.datetime_when, end: entry.datetime_until, id: entry.id, diff --git a/smash/web/static/js/daily_planning.js b/smash/web/static/js/daily_planning.js index 24f3f1d3a72470dcf2c464f402d92706c9675178..e568751fe87058d317f97f4efb6f4b55417728a8 100644 --- a/smash/web/static/js/daily_planning.js +++ b/smash/web/static/js/daily_planning.js @@ -1,3 +1,4 @@ +window['moment-range'].extendMoment(moment); const TIME_FORMAT = 'HH:mm'; const FLYING_TEAM_LABEL = 'Flying Team'; const FLYING_TEAM_BORDER_COLOR = "orange"; @@ -77,27 +78,34 @@ function add_event(event, color, subjectId, locationId, boxBody) { } eventElement.data('event', event_data); - eventElement.draggable({ - zIndex: 999, - revert: true, - revertDuration: 0, - start: function (event, ui) { - $(this).popover('disable'); - } - }); - eventElement.css('background-color', color); + if(is_event_not_finished(event)){ + eventElement.draggable({ + zIndex: 999, + revert: true, + revertDuration: 0, + start: function (event, ui) { + console.log('Ey'); + $(this).popover('disable'); + } + }); + eventElement.css('background-color', color); + }else{ + eventElement.css('background', `repeating-linear-gradient( -45deg, ${color}, ${color} 10px, #333 10px, #333 20px )`); + eventElement.css('text-shadow', '0px 0px 12px #000000'); + } + eventElement.css('width', event.width); boxBody.append(eventElement); eventElement.popover({ container: 'body', trigger: 'click', - content: location + ', appointment starts at ' + constraintStart.format(TIME_FORMAT) + content: `${location}, appointment starts at ${constraintStart.format(TIME_FORMAT)} (${event.status})` }); } function get_subjects_events(day) { - $.get('/api/events/' + day, function (data) { + $.get(`/api/events/${day}/include_all`, function (data) { $("#subjects").empty(); var availabilities = data.availabilities; $.each(availabilities, function (index, event) { @@ -188,7 +196,7 @@ function get_subjects_events(day) { var boxSubject = $("<div class='box box-primary'/>").css('border-top-color', location.color); var boxBody = $("<div class='box-body' id='location_" + location.id + "'>"); var boxHeader = $("<div class='box-header with-border'/>"); - var title_location = $(`<h4>${location.name}<span style='padding-right:5px;'>${location.location}</span></h4> + var title_location = $(`<h4>${location.name}</h4><span style='padding-right:5px;'>${location.location}</span> <span style='padding-right:5px;'> <a title="Edit Appointment" target="_blank" href="/appointments/edit/${location.id}"> <i class="fa fa-pencil-square"></i> @@ -231,6 +239,91 @@ function get_subjects_events(day) { }); } +//receives dates in momentjs format +//first the longest range, then the shortest +//this function returns true if rangeB is entirely within rangeA +function are_events_overlapping(start_a, end_a, start_b, end_b){ + start_a = moment(start_a.format("Y-MM-DD-HH-mm"), "Y-MM-DD-HH-mm"); + end_a = moment(end_a.format("Y-MM-DD-HH-mm"), "Y-MM-DD-HH-mm"); + start_b = moment(start_b.format("Y-MM-DD-HH-mm"), "Y-MM-DD-HH-mm"); + end_b = moment(end_b.format("Y-MM-DD-HH-mm"), "Y-MM-DD-HH-mm"); + + console.log('checking', start_a, end_a, start_b, end_b); + + var rangeA = moment.range( start_a, end_a ); + var rangeB = moment.range( start_b, end_b ); + + return rangeA.contains(rangeB); +} + +function availabilityAjaxCall(url, calendar_selector, dialog_element){ + return $.ajax({ + 'url': url, + success: function(result){ + saveEvents(calendar_selector); + $(calendar_selector).fullCalendar('refetchResources'); + $(dialog_element).dialog('close'); + }, + error: function(jqXHR, textStatus, errorThrown){ + console.log(`Request ${url} failed: ${textStatus}`); + alert('Request failed'); + $(dialog_element).dialog('close'); + } + }); +} + +function checkResourceAvailability(calendar_selector, resourceId, event){ + $('.popover').popover('hide'); + var events = $(calendar_selector).fullCalendar( 'getResourceEvents', resourceId ); + + //var event = events[events.length-1]; //last event is the last added event + var date = event.start; + var duration = event.original_duration; + var start_date = date.clone().format("Y-MM-DD-HH-mm"); + var end_date = date.clone().add(duration.split(':')[0], 'hours').add(duration.split(':')[1], 'minutes') + + var background_events = events.filter(function(event){ + if(event.className.includes('background-event') && event.kind != 'H'){ //background and not holiday + return are_events_overlapping(event.start, event.end, date, end_date); + }else{ + return false; + } + }); + + end_date = end_date.format("Y-MM-DD-HH-mm"); + + //event was dropped over area without availability + if(background_events.length == 0){ + var third_option = `Add availability for all ${date.format('dddd')}s (9:00 to 18:00)`; + + var buttons = { + 'Continue without adding any availability': function() { + $(this).dialog('close'); + }, + 'Add extra availability for the event time': function() { + var url = `/api/workers/add_extra_availability/${resourceId}/${start_date}/${end_date}/`; + availabilityAjaxCall(url, calendar_selector, this); + } + }; + + //Add availability for all weekday (9:00 to 18:00) + buttons[third_option] = function() { + var url = `/api/workers/add_availability/${resourceId}/${date.isoWeekday()}/09:00/18:00/`; + availabilityAjaxCall(url, calendar_selector, this); + }; + + $("#mydialog").dialog({ + title: 'Worker not available', + modal: true, + width: 450, + resizable: false, + draggable: false, + dialogClass: "no-close", + buttons: buttons + }); + }//otherwise event was dropped over area with availability +} + function remove_event(event) { if(event.className.includes("background-event")){ //avoid removing availabilities return; @@ -260,6 +353,64 @@ function remove_event(event) { add_event(event, event.color, event.subject_id, event.location_id, boxBody); } +function saveEvents(calendar_selector) { + calendarEvents = $(calendar_selector).fullCalendar('clientEvents'); + eventsToPersist = []; + var saveButton = $(".fc-save-button"); + var currentBorder = saveButton.css('border-color'); + $.each(calendarEvents, function (i, calendar_event) { + if (calendar_event.rendering !== "background") { + eventsToPersist.push({ + 'link_id': calendar_event.link_id, + 'appointment_id': calendar_event.appointment_id, + 'link_who': parseInt(calendar_event.resourceId), + 'start': calendar_event.start.format() + }); + if (calendar_event.link_id !== undefined) { + var index = eventsCleared.indexOf(calendar_event.link_id); + if (index > -1) { + eventsCleared.splice(index, 1); + } + } else { + var index = appointmentsCleared.indexOf(calendar_event.appointment_id); + if (index > -1) { + appointmentsCleared.splice(index, 1); + } + } + } + }); + $.post({ + url: events_url, //this is defined in daily_planning.html (not sure why) + data: { + events_to_persist: JSON.stringify(eventsToPersist), + events_to_clear: JSON.stringify(eventsCleared), + appointments_to_clear: JSON.stringify(appointmentsCleared) + }, + dataType: "json" + }).done(function (data) { + + saveButton.css('border-color', 'green'); + setTimeout(function () { + saveButton.css('border-color', currentBorder); + }, 200); + }).error(function (data) { + + saveButton.css('border-color', 'red'); + showErrorInfo("There was an unexpected problem with saving data. " + "Please contact administrators."); + setTimeout(function () { + saveButton.delay(200).css('border-color', currentBorder); + }, 200); + }); +} + +function is_event_not_finished(event){ + if( event.status == undefined || event.status == 'SCHEDULED' ){ + return true; + }else{ + return false; + } +} + function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_props){ var customButtons = { @@ -281,55 +432,8 @@ function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_ }, save: { text: 'Save', - click: function () { - calendarEvents = $(calendar_selector).fullCalendar('clientEvents'); - eventsToPersist = []; - var saveButton = $(".fc-save-button"); - var currentBorder = saveButton.css('border-color'); - $.each(calendarEvents, function (i, calendar_event) { - if (calendar_event.rendering !== "background") { - eventsToPersist.push({ - 'link_id': calendar_event.link_id, - 'appointment_id': calendar_event.appointment_id, - 'link_who': parseInt(calendar_event.resourceId), - 'start': calendar_event.start.format() - }); - if (calendar_event.link_id !== undefined) { - var index = eventsCleared.indexOf(calendar_event.link_id); - if (index > -1) { - eventsCleared.splice(index, 1); - } - } else { - var index = appointmentsCleared.indexOf(calendar_event.appointment_id); - if (index > -1) { - appointmentsCleared.splice(index, 1); - } - } - } - }); - $.post({ - url: events_url, - data: { - events_to_persist: JSON.stringify(eventsToPersist), - events_to_clear: JSON.stringify(eventsCleared), - appointments_to_clear: JSON.stringify(appointmentsCleared) - }, - dataType: "json" - }).done(function (data) { - - saveButton.css('border-color', 'green'); - setTimeout(function () { - saveButton.css('border-color', currentBorder); - }, 200); - }).error(function (data) { - - console.log(data); - saveButton.css('border-color', 'red'); - showErrorInfo("There was an unexpected problem with saving data. " + "Please contact administrators."); - setTimeout(function () { - saveButton.delay(200).css('border-color', currentBorder); - }, 200); - }); + click: function(){ + saveEvents(calendar_selector) } }, clear: { @@ -337,7 +441,9 @@ function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_ click: function () { calendarEvents = $(calendar_selector).fullCalendar('clientEvents'); $.each(calendarEvents, function (i, calendar_event) { - remove_event(calendar_event); + if(is_event_not_finished(calendar_event)){ //do not delete finished events + remove_event(calendar_event); + } }); } }, @@ -365,8 +471,8 @@ function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_ var default_properties = { schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives', defaultView: 'agendaDay', - eventDurationEditable: false, eventStartEditable: true, + eventDurationEditable: false, editable: true, selectable: true, droppable: true, @@ -430,30 +536,39 @@ function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_ $(labelTds).find('a[title]').tooltip(); }, resources: function(callback){ - setTimeout(function(){ - var view = $(calendar_selector).fullCalendar('getView'); - $.ajax({ - url: resources_url, - type: 'GET', - cache: false, - data: { - start_date: view.start.format('YYYY-MM-DD'), - } - }).then(function(resources){ - //Filter out roles - var checked_roles = $('.role_list_item > input:checked').map(function(i,e){ - return e.value; - }).toArray(); - resources = resources.filter(function(resource){ - return checked_roles.includes(resource.role); - }); - callback(resources) - }); - }, 0); + setTimeout(function(){ + var view = $(calendar_selector).fullCalendar('getView'); + $.ajax({ + url: resources_url, + type: 'GET', + cache: false, + data: { + start_date: view.start.format('YYYY-MM-DD'), + } + }).then(function(resources){ + //Filter out roles + var checked_roles = $('.role_list_item > input:checked').map(function(i,e){ + return e.value; + }).toArray(); + resources = resources.filter(function(resource){ + return checked_roles.includes(resource.role); + }); + callback(resources) + }); + }, 0); }, eventRender: function (event, element) { if (event.rendering !== 'background') { - var content = + if(!is_event_not_finished(event)){ + event.editable = false; + event.startEditable = false; + var color = event.color.replace('!important', '').trim(); + element.css({ + 'background': `repeating-linear-gradient( -45deg, ${color}, ${color} 10px, #333 10px, #333 20px )`, + 'font-weight': 'bold', + 'text-shadow': '0px 0px 12px #000000' + }); + } element.popover({ title: event.short_title, container: 'body', @@ -464,6 +579,7 @@ function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_ '<li>' + event.start.format(TIME_FORMAT) + ' - ' + event.end.format(TIME_FORMAT) + '</li>' + (event.subject !== undefined ? '<li>Appointment starts: ' + event.constraint.start.format(TIME_FORMAT) + '</li>' : '') + '<li>Location: ' + (event.location !== FLYING_TEAM_LABEL ? event.location : event.flying_team_location + ' (FT)') + '</li>' + + '<li>Status: ' + event.status + '</ul>', html: true }); @@ -488,10 +604,19 @@ function addDailyPlanningCalendar(calendar_selector, replace_all, calendar_dict_ remove_event(event); } }, + eventDrop: function ( event, delta, revertFunc, jsEvent, ui, view ){ + var resourceId = event.resourceId; + //this case applies when the event is moved from resource to resource (change of worker) + checkResourceAvailability(calendar_selector, resourceId, event); // in this case we have the event + }, eventDragStart: function (event, jsEvent, view) { $('.popover').popover('hide'); }, drop: function (date, jsEvent, ui, resourceId) { + var events = $(calendar_selector).fullCalendar( 'getResourceEvents', resourceId ); + //this case applies when the event is moved to a resource for the first time (first assingment to a worker) + var event = events[events.length-1]; //in this case, the dropped event will be the last event + checkResourceAvailability(calendar_selector, resourceId, event); $(this).remove(); }, eventAfterAllRender: function(view){ diff --git a/smash/web/templates/appointment_types/add.html b/smash/web/templates/appointment_types/add.html new file mode 100644 index 0000000000000000000000000000000000000000..6c9f45d2f28b31d12b44fa4fb60f074d9655790e --- /dev/null +++ b/smash/web/templates/appointment_types/add.html @@ -0,0 +1,9 @@ +{% extends "appointment_types/add_edit.html" %} + +{% block page_header %}New appointment type{% endblock page_header %} + +{% block title %}{{ block.super }} - Add new appointment type{% endblock %} + +{% block form-title %}Enter appointment type details{% endblock %} + +{% block save-button %}Add{% endblock %} diff --git a/smash/web/templates/appointment_types/add_edit.html b/smash/web/templates/appointment_types/add_edit.html new file mode 100644 index 0000000000000000000000000000000000000000..6cbee0e0868722ac233f7d8f442e9f878bb11019 --- /dev/null +++ b/smash/web/templates/appointment_types/add_edit.html @@ -0,0 +1,77 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block styles %} + {{ block.super }} + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/awesomplete/awesomplete.css' %}"/> + +{% endblock styles %} + +{% block ui_active_tab %}'appointment_types'{% endblock ui_active_tab %} +{% block page_description %}{% endblock page_description %} + +{% block breadcrumb %} + {% include "appointment_types/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + {% block content %} + <div class="row"> + <div class="col-md-12"> + <div class="box box-success"> + <div class="box-header with-border"> + <h3 class="box-title">{% block form-title %}Enter appointment type details{% endblock %}</h3> + </div> + + + <form method="post" action="" class="form-horizontal" enctype="multipart/form-data"> + {% csrf_token %} + + <div class="box-body"> + {% for field in form %} + <div class="form-group {% if field.errors %}has-error{% endif %}"> + <label class="col-sm-4 col-lg-offset-1 col-lg-2 control-label"> + {{ field.label }} + </label> + + <div class="col-sm-8 col-lg-4"> + {{ field|add_class:'form-control' }} + {% if field.errors %} + <span class="help-block">{{ field.errors }}</span> + {% endif %} + </div> + + + </div> + {% endfor %} + </div><!-- /.box-body --> + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-success">{% block save-button %} + Add{% endblock %} + </button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.appointment_types' %}" + class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + + </div> + </div> + + {% endblock %} + + +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/awesomplete/awesomplete.min.js' %}"></script> + +{% endblock scripts %} \ No newline at end of file diff --git a/smash/web/templates/appointment_types/breadcrumb.html b/smash/web/templates/appointment_types/breadcrumb.html new file mode 100644 index 0000000000000000000000000000000000000000..2ab1c8ec997ca0ccf01b576afb751c3a92981c95 --- /dev/null +++ b/smash/web/templates/appointment_types/breadcrumb.html @@ -0,0 +1,5 @@ +<li><a href="{% url 'web.views.appointments' %}"><i class="fa fa-dashboard"></i> Dashboard</a></li> +<li><a href="{% url 'web.views.equipment_and_rooms' %}">Equipment and rooms</a></li> +<li class="active"> + <a href="{% url 'web.views.appointment_types' %}">Appointment Types</a> +</li> \ No newline at end of file diff --git a/smash/web/templates/appointment_types/confirm_delete.html b/smash/web/templates/appointment_types/confirm_delete.html new file mode 100644 index 0000000000000000000000000000000000000000..4a7bea4efefec6928bbc3b78db7965aa337e2c02 --- /dev/null +++ b/smash/web/templates/appointment_types/confirm_delete.html @@ -0,0 +1,62 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block styles %} + {{ block.super }} + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/awesomplete/awesomplete.css' %}"/> + +{% endblock styles %} + +{% block ui_active_tab %}'appointment_types'{% endblock ui_active_tab %} +{% block page_header %}Delete appointment type{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Delete appointment type{% endblock %} + +{% block breadcrumb %} + {% include "languages/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + {% block content %} + <div class="row"> + <div class="col-md-12"> + <div class="box box-success"> + <div class="box-header with-border"> + <h3 class="box-title">Confirm deletion</h3> + </div> + + <form action="" method="post" class="form-horizontal">{% csrf_token %} + <div class="box-body"> + <p>Are you sure you want to delete appointment type "{{ object.description }}"?</p> + </div><!-- /.box-body --> + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-danger">Delete</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.appointment_types' %}" + class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + + </div> + </div> + + {% endblock %} + + +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/awesomplete/awesomplete.min.js' %}"></script> + +{% endblock scripts %} + + diff --git a/smash/web/templates/appointment_types/edit.html b/smash/web/templates/appointment_types/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..cad34b054725e8e20acc309c6a3f34e875b59492 --- /dev/null +++ b/smash/web/templates/appointment_types/edit.html @@ -0,0 +1,10 @@ +{% extends "languages/add_edit.html" %} + +{% block page_header %}Edit appointment type "{{ appointment_type.code }}"{% endblock page_header %} + +{% block title %}{{ block.super }} - Edit appointment type "{{ language.description }}"{% endblock %} + +{% block form-title %}Enter appointment type details{% endblock %} + +{% block save-button %}Save{% endblock %} + diff --git a/smash/web/templates/appointment_types/index.html b/smash/web/templates/appointment_types/index.html new file mode 100644 index 0000000000000000000000000000000000000000..0d44cac8932204c9b36e9ea5c0d89108d91807dd --- /dev/null +++ b/smash/web/templates/appointment_types/index.html @@ -0,0 +1,118 @@ +{% extends "_base.html" %} +{% load static %} + +{% block styles %} + {{ block.super }} + <!-- DataTables --> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> + <style type="text/css"> + .no_leave{ + height: 100%; + line-height: 2.5; + text-align: center; + background-color: #00a65b; + } + .on_leave{ + height: 100%; + line-height: 2.5; + text-align: center; + background-color: #dd4b39; + } + .description{ + margin: 0; + padding: 0; + line-height: 1.5; + font-variant: small-caps; + font-weight: 400; + font-size: 12pt; + text-align: justify; + padding-top: 5px; + } + </style> +{% endblock styles %} + +{% block ui_active_tab %} +'appointment_types' +{% endblock ui_active_tab %} + +{% block page_header %} + +{% if worker_type == 'STAFF' %} + Workers +{% elif worker_type == 'HEALTH_PARTNER' %} + Health Partners +{% elif worker_type == 'VOUCHER_PARTNER' %} + Voucher Partners +{% endif %} + +{% endblock page_header %} +{% block breadcrumb %} + {% include "appointment_types/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + <div class="row"> + <div class="col-lg-2 col-md-3 col-xs-4"> + <a class="btn btn-app" href="{% url 'web.views.appointment_type_add' %}"> + <i class="fa fa-plus"></i> Add new appointment type + </a> + </div> + <div class="col-xs-4"> + <p class="description"> + Appointment Types represent the different <u>assesments</u> (i.e. blood test) to be conducted during an appointment. + </p> + </div> + </div> + + <div class="box-body"> + <table id="table" class="table table-bordered table-striped"> + <thead> + <tr> + <th>Required Equipment</th> + <th>Code</th> + <th>Description</th> + <th>Default Duration</th> + <th>Rest Time</th> + <th>Edit</th> + <th>Delete</th> + </tr> + </thead> + <tbody> + {% for appointment_type in appointment_types %} + <tr> + <td>{{ appointment_type.required_equipment.all|join:"; " }}</td> + <td>{{ appointment_type.code }}</td> + <td>{{ appointment_type.description }}</td> + <td>{{ appointment_type.default_duration }}</td> + <td>{{ appointment_type.rest_time }}</td> + <td><a href="{% url 'web.views.appointment_type_edit' appointment_type.id %}"><i + class="fa fa-edit"></i></a></td> + <td><a href="{% url 'web.views.appointment_type_delete' appointment_type.id %}"><i + class="fa fa-trash text-danger"></i></a></td> + </tr> + {% endfor %} + </tbody> + </table> + </div> + +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script> + <script> + $(function () { + $('#table').DataTable({ + "paging": true, + "lengthChange": false, + "searching": true, + "ordering": true, + "info": true, + "autoWidth": false + }); + }); + </script> +{% endblock scripts %} diff --git a/smash/web/templates/appointments/add.html b/smash/web/templates/appointments/add.html index 9fc04985e5e152a2daf9db4790479f9bff949f36..06d3a3a7667df392971f50cf72256e49864be558 100644 --- a/smash/web/templates/appointments/add.html +++ b/smash/web/templates/appointments/add.html @@ -33,6 +33,13 @@ background-color: #fafafa; border: solid 1px #ccc; } + .visit-period { + background: repeating-linear-gradient( -45deg, white, white 5px, #F5F5F5 5px, #F5F5F5 7px ); + } + .fc-today > .fc-day-number{ + font-weight: 600; + text-decoration: underline; + } </style> {% endblock styles %} @@ -127,6 +134,7 @@ New appointment for visit from {{visit_start}} to {{visit_end}} <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script> <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/moment.js/moment-range.min.js' %}"></script> <script src="{% static 'AdminLTE/plugins/moment.js/moment.min.js' %}"></script> <script src="{% static 'js/appointment.js' %}"></script> <script src="{% static 'fullcalendar-scheduler/lib/fullcalendar.min.js' %}"></script> @@ -151,6 +159,23 @@ New appointment for visit from {{visit_start}} to {{visit_end}} center: 'title', right: 'month,agendaWeek' }, + {% if isGeneral %} + {% else %} + dayRender: function(daysOfWeek, cell) { + + + var visit_start = moment('{{visit_start}}'); + var visit_end = moment('{{visit_end}}'); + if(visit_start <= daysOfWeek && daysOfWeek <= visit_end){ + $(cell).addClass('visit-period'); + if($(cell).hasClass('fc-today')){ + $(cell).css('background', 'repeating-linear-gradient( -45deg, #fcf8e3, #fcf8e3 5px, #e8e2c2 5px, #e8e2c2 7px )'); + } + }else{ + $(cell).removeClass('visit-period'); + } + }, + {% endif %} dayClick: function (date, jsEvent, view) { var dateString = date.format(); if (dateString.indexOf("T") >= 0) { diff --git a/smash/web/templates/appointments/confirm_delete.html b/smash/web/templates/appointments/confirm_delete.html new file mode 100644 index 0000000000000000000000000000000000000000..ba2394895df57c20d7fd3272cad51e26d21d88f4 --- /dev/null +++ b/smash/web/templates/appointments/confirm_delete.html @@ -0,0 +1,62 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block styles %} + {{ block.super }} + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/awesomplete/awesomplete.css' %}"/> + +{% endblock styles %} + +{% block ui_active_tab %}'appointments'{% endblock ui_active_tab %} +{% block page_header %}Delete appointment{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Delete appointment{% endblock %} + +{% block breadcrumb %} + {% include "languages/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + {% block content %} + <div class="row"> + <div class="col-md-12"> + <div class="box box-success"> + <div class="box-header with-border"> + <h3 class="box-title">Confirm deletion</h3> + </div> + + <form action="" method="post" class="form-horizontal">{% csrf_token %} + <div class="box-body"> + <p>Are you sure you want to delete the appointment at "{{ object.location }}" ?</p> + </div><!-- /.box-body --> + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-danger">Delete</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.appointment_types' %}" + class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + + </div> + </div> + + {% endblock %} + + +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + <script src="{% static 'AdminLTE/plugins/awesomplete/awesomplete.min.js' %}"></script> + +{% endblock scripts %} + + diff --git a/smash/web/templates/appointments/edit.html b/smash/web/templates/appointments/edit.html index dc1df827cfd7967dbad32f7e7e69ae79545bacd9..77c145c1754c418d76e50dc61bad371510e11e7f 100644 --- a/smash/web/templates/appointments/edit.html +++ b/smash/web/templates/appointments/edit.html @@ -125,13 +125,11 @@ <a href="{% url 'web.views.appointments' %}" class="btn btn-block btn-default" onclick="history.back()">Cancel</a> </div> - {% if not appointment.visit %} - {% ifequal appointment.status "SCHEDULED" %} - <div class="col-sm-3"> - <a href="{% url 'web.views.appointment_delete' appointment.id %}" - class="btn btn-block btn-danger">Delete</a> - </div> - {% endifequal %} + {% if appointment.status == "SCHEDULED" and 'delete_appointment' in permissions %} + <div class="col-sm-3"> + <a href="{% url 'web.views.appointment_delete' appointment.id %}" + class="btn btn-block btn-danger">Delete</a> + </div> {% endif %} </div><!-- /.box-footer --> </form> diff --git a/smash/web/templates/appointments/index.html b/smash/web/templates/appointments/index.html index 486e731ff0479bd13bd7aab1dc6077154c532d35..5bf212e5f4f3ad6278e88087efec2688b0613d5b 100644 --- a/smash/web/templates/appointments/index.html +++ b/smash/web/templates/appointments/index.html @@ -74,6 +74,7 @@ <script src="{% static 'js/appointment.js' %}"></script> <script> + $.ajaxSetup({ cache: false }); $(function () { var dayHeaders = {}; var approachingTable = $('#approaching_table'); @@ -143,6 +144,10 @@ } content += '<li>Location: ' + location + '</li>' } + if (event.status) { + content += '<li>Status: ' + event.status + '</li>' + } + content += "</ul>"; $(element).popover({ title: event.title, @@ -152,7 +157,6 @@ trigger: 'hover', placement: 'bottom' }); - console.log(event); }, events: get_calendar_events_function( "{% url 'web.api.appointments' full_list %}", diff --git a/smash/web/templates/configuration/index.html b/smash/web/templates/configuration/index.html index d5580458239aeb03c3cd24323d5be81f70cfc513..5c6e24c28054eecb2287785875d9a29d260f04e7 100644 --- a/smash/web/templates/configuration/index.html +++ b/smash/web/templates/configuration/index.html @@ -9,7 +9,7 @@ {% endblock styles %} -{% block ui_active_tab %}'general_conf'{% endblock ui_active_tab %} +{% block ui_active_tab %}'settings'{% endblock ui_active_tab %} {% block page_header %}Configuration{% endblock page_header %} {% block page_description %}{% endblock page_description %} diff --git a/smash/web/templates/daily_planning.html b/smash/web/templates/daily_planning.html index 4d6cc2058df16128406951a76d9223d55730fbeb..8d0eeff9e119dfeeee57dd518e4d1107a4ed48e4 100644 --- a/smash/web/templates/daily_planning.html +++ b/smash/web/templates/daily_planning.html @@ -4,6 +4,11 @@ {% block styles %} {{ block.super }} <!-- DataTables --> + <script src="{% static 'AdminLTE/plugins/jQuery/jquery-2.2.3.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/jQueryUI/jquery-ui.min.js' %}"></script> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/jQueryUI/jquery-ui.min.css' %}"> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/jQueryUI/jquery-ui.theme.min.css' %}"> + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/jQueryUI/jquery-ui.structure.min.css' %}"> <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> <!-- fullCalendar 2.2.5--> @@ -37,6 +42,39 @@ background-color: #fafafa; border: solid 1px #ccc; } + /*dialog*/ + .no-close .ui-dialog-titlebar-close { + display: none; + } + .ui-dialog .ui-dialog-title { + color: black; + width: 100%; + text-align: center; + } + .ui-dialog-titlebar{ + background: #ffc261 50% 50% repeat-x; + } + .ui-dialog{ + /*background-color: #ccc; + border-radius: 5px; + border-color: black; + border-style: solid; + color: black; + */ + z-index: 10000; + } + #mydialog{ + display: none; + } + #mydialog > p { + font-size: 12pt; + } + #mydialog > i { + font-size: 10pt; + } + .ui-dialog-buttonset > button { + width: 100%; + } </style> {% include "includes/datepicker.css.html" %} {% endblock styles %} @@ -52,6 +90,14 @@ {% endblock breadcrumb %} {% block maincontent %} + <div id="mydialog"> + <p>The worker you chose is not available at that time. + Do you want to add an availability for the Worker?</p> </br> + <i> + <b>Adding an availability will save the current status of the board.</b> </br> + Keep in mind that the availability will have to be removed manually to undo this action. + </i> + </div> <div class="row" id="subjects"> </div> <div class="row"> @@ -75,6 +121,7 @@ {% block scripts %} {{ block.super }} <script src="{% static 'AdminLTE/plugins/moment.js/moment.min.js' %}"></script> + <script src="{% static 'AdminLTE/plugins/moment.js/moment-range.min.js' %}"></script> <script src="{% static 'fullcalendar-scheduler/lib/fullcalendar.min.js' %}"></script> <script src="{% static 'fullcalendar-scheduler/scheduler.min.js' %}"></script> <script> @@ -86,7 +133,7 @@ } $(document).ready(function () { - addDailyPlanningCalendar('#calendar', false, {}); + addDailyPlanningCalendar('#calendar', false, {slotDuration: '00:15'}); }); </script> diff --git a/smash/web/templates/doctors/index.html b/smash/web/templates/doctors/index.html index e1b0fef9d130e9837600cea02f05ca0e849de70d..2e14e5095e8127daabdb0038b548a5f6a14460cf 100644 --- a/smash/web/templates/doctors/index.html +++ b/smash/web/templates/doctors/index.html @@ -25,9 +25,9 @@ {% if worker_type == 'STAFF' %} 'workers' {% elif worker_type == 'HEALTH_PARTNER' %} -'health_partners' +'health_partner' {% elif worker_type == 'VOUCHER_PARTNER' %} -'voucher_partners' +'voucher_partner' {% endif %} {% endblock ui_active_tab %} diff --git a/smash/web/templates/equipment_and_rooms/equipment/index.html b/smash/web/templates/equipment_and_rooms/equipment/index.html index d1869fa9d4264eca843d55d4f78ffce7cb0a1685..2a62cf45a2256837d094bc50572200bac2369882 100644 --- a/smash/web/templates/equipment_and_rooms/equipment/index.html +++ b/smash/web/templates/equipment_and_rooms/equipment/index.html @@ -7,7 +7,7 @@ <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> {% endblock styles %} -{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block ui_active_tab %}'equipment_items'{% endblock ui_active_tab %} {% block page_header %}Equipment definitions{% endblock page_header %} {% block page_description %}{% endblock page_description %} diff --git a/smash/web/templates/equipment_and_rooms/flying_teams/index.html b/smash/web/templates/equipment_and_rooms/flying_teams/index.html index df8165b16339e330b96565d457ae17b17b241672..c815e3eadbf0e26e407470b48279bece1c1f06d4 100644 --- a/smash/web/templates/equipment_and_rooms/flying_teams/index.html +++ b/smash/web/templates/equipment_and_rooms/flying_teams/index.html @@ -7,7 +7,7 @@ <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> {% endblock styles %} -{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block ui_active_tab %}'flying_teams'{% endblock ui_active_tab %} {% block page_header %}Flying teams{% endblock page_header %} {% block page_description %}management{% endblock page_description %} diff --git a/smash/web/templates/equipment_and_rooms/kit_requests/kit_requests.html b/smash/web/templates/equipment_and_rooms/kit_requests/kit_requests.html index 16b7dbf0f41659911ec26e81d9e95a75728175a4..2e3beade15126929fe26f78953645c7bb949726e 100644 --- a/smash/web/templates/equipment_and_rooms/kit_requests/kit_requests.html +++ b/smash/web/templates/equipment_and_rooms/kit_requests/kit_requests.html @@ -1,6 +1,6 @@ {% extends "_base.html" %} -{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block ui_active_tab %}'kit_requests'{% endblock ui_active_tab %} {% block page_header %} Kits required between {{ start_date | date:"Y-m-d" }} and {% if end_date %} {{ end_date | date:"Y-m-d" }} {% else %} end of time {% endif %} diff --git a/smash/web/templates/equipment_and_rooms/rooms/index.html b/smash/web/templates/equipment_and_rooms/rooms/index.html index c5d34b728335f9d22e64f83474116d62ab101022..7cb6f5f4204a2037c4ea9648a463beb27f169faf 100644 --- a/smash/web/templates/equipment_and_rooms/rooms/index.html +++ b/smash/web/templates/equipment_and_rooms/rooms/index.html @@ -7,7 +7,7 @@ <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}"> {% endblock styles %} -{% block ui_active_tab %}'equipment_and_rooms'{% endblock ui_active_tab %} +{% block ui_active_tab %}'rooms'{% endblock ui_active_tab %} {% block page_header %}Rooms{% endblock page_header %} {% block page_description %}management{% endblock page_description %} diff --git a/smash/web/templates/sidebar.html b/smash/web/templates/sidebar.html index 89c8b23ba6c1f8bbf72801253c61a9fab6d1c663..a91be3d75937d828cecab8216c779c3b557271a7 100644 --- a/smash/web/templates/sidebar.html +++ b/smash/web/templates/sidebar.html @@ -34,16 +34,19 @@ <li data-desc="equipment_and_rooms" class="treeview"> <a href="{% url 'web.views.equipment_and_rooms' %}"> - <i class="fa fa-building-o"></i> <span>Equipment&rooms</span> + <i class="fa fa-building-o"></i> <span>Equipment & Rooms</span> <span class="pull-right-container"> <i class="fa fa-angle-left pull-right"></i> </span> </a> <ul class="treeview-menu"> - <li><a href="{% url 'web.views.equipment' %}">Equipment items</a></li> - <li><a href="{% url 'web.views.equipment_and_rooms.flying_teams' %}">Flying teams</a></li> - <li><a href="{% url 'web.views.kit_requests' %}">Kit requests</a></li> - <li><a href="{% url 'web.views.equipment_and_rooms.rooms' %}">Rooms</a></li> + <li data-desc="equipment_items"><a href="{% url 'web.views.equipment' %}">Equipment items</a></li> + {% if "change_appointmenttype" in permissions %} + <li data-desc="appointment_types"><a href="{% url 'web.views.appointment_types' %}">Appointment Types</a></li> + {% endif %} + <li data-desc="flying_teams"><a href="{% url 'web.views.equipment_and_rooms.flying_teams' %}">Flying teams</a></li> + <li data-desc="kit_requests"><a href="{% url 'web.views.kit_requests' %}">Kit requests</a></li> + <li data-desc="rooms"><a href="{% url 'web.views.equipment_and_rooms.rooms' %}">Rooms</a></li> </ul> </li> @@ -88,27 +91,27 @@ </a> <ul class="treeview-menu"> {% if "change_configurationitem" in permissions %} - <li><a href="{% url 'web.views.configuration' %}">General</a></li> + <li data-desc="settings"><a href="{% url 'web.views.configuration' %}">General</a></li> {% endif %} {% if "change_language" in permissions %} - <li><a href="{% url 'web.views.languages' %}">Languages</a></li> + <li data-desc="languages"><a href="{% url 'web.views.languages' %}">Languages</a></li> {% endif %} {% if study.has_voucher_types and "change_vouchertype" in permissions %} - <li><a href="{% url 'web.views.voucher_types' %}">Voucher types</a></li> + <li data-desc="voucher_types"><a href="{% url 'web.views.voucher_types' %}">Voucher types</a></li> {% endif %} {% if study.has_vouchers and "change_worker" in permissions %} - <li><a href="{% url 'web.views.workers' 'VOUCHER_PARTNER' %}">Voucher partners</a></li> + <li data-desc="voucher_partner"><a href="{% url 'web.views.workers' 'VOUCHER_PARTNER' %}">Voucher partners</a></li> {% endif %} {% if "change_worker" in permissions %} - <li><a href="{% url 'web.views.workers' 'HEALTH_PARTNER' %}">Health partners</a></li> + <li data-desc="health_partner"><a href="{% url 'web.views.workers' 'HEALTH_PARTNER' %}">Health partners</a></li> {% endif %} {% if "change_study" in permissions %} - <li><a href="{% url 'web.views.edit_study' study_id %}">Study</a></li> + <li data-desc="study_conf"><a href="{% url 'web.views.edit_study' study_id %}">Study</a></li> {% endif %} </ul> </li> diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py index cbe911f8f932e81aeed5924dd7377cfd9d7bbf99..b42207956fb950d746a93181ca3b38b4d48f1b8f 100644 --- a/smash/web/tests/functions.py +++ b/smash/web/tests/functions.py @@ -198,7 +198,7 @@ def create_study_subject(subject_id=1, subject=None, nd_number='ND0001'): study=get_test_study(), subject=subject ) - if nd_number is not None: + if nd_number is not None: #null value in column "nd_number" violates not-null constraint study_subject.nd_number = nd_number study_subject.save() diff --git a/smash/web/tests/view/test_appointments.py b/smash/web/tests/view/test_appointments.py index 4acf168d587ae17c78e9748b54e56fb6e6220d10..9c7630b210886be359f86f1fcc3aac09687ca303 100644 --- a/smash/web/tests/view/test_appointments.py +++ b/smash/web/tests/view/test_appointments.py @@ -137,7 +137,7 @@ class AppointmentsViewTests(LoggedInTestCase): self.assertEqual(Appointment.APPOINTMENT_STATUS_FINISHED, appointment_result.status) def test_save_appointments_edit_with_invalid_nd_number(self): - subject = create_study_subject(nd_number=None) + subject = create_study_subject(nd_number='DUMB_ND_NUMBER') visit = create_visit(subject) appointment = create_appointment(visit, get_today_midnight_date()) @@ -239,13 +239,42 @@ class AppointmentsViewTests(LoggedInTestCase): appointment.visit = None appointment.save() - self.client.post(reverse('web.views.appointment_delete', kwargs={'appointment_id': appointment.id})) + #without permission + self.login_as_staff() + self.client.post(reverse('web.views.appointment_delete', kwargs={'pk': appointment.id})) + self.assertEqual(1, Appointment.objects.all().count()) + #with permission + self.login_as_super() + self.client.post(reverse('web.views.appointment_delete', kwargs={'pk': appointment.id})) self.assertEqual(0, Appointment.objects.all().count()) - def test_delete_invalid_appointment_with_visit(self): + + def test_delete_appointment_with_visit(self): + self.login_as_super() appointment = create_appointment() - self.client.post(reverse('web.views.appointment_delete', kwargs={'appointment_id': appointment.id})) + self.client.post(reverse('web.views.appointment_delete', kwargs={'pk': appointment.id})) + + self.assertEqual(0, Appointment.objects.all().count()) + + def test_delete_invalid_finished_appointment(self): + self.login_as_super() + appointment = create_appointment() + appointment.status = Appointment.APPOINTMENT_STATUS_FINISHED + appointment.visit = None + appointment.save() + + self.client.post(reverse('web.views.appointment_delete', kwargs={'pk': appointment.id})) + + self.assertEqual(1, Appointment.objects.all().count()) + + def test_delete_invalid_finished_appointment_with_visit(self): + self.login_as_super() + appointment = create_appointment() + appointment.status = Appointment.APPOINTMENT_STATUS_FINISHED + appointment.save() + + self.client.post(reverse('web.views.appointment_delete', kwargs={'pk': appointment.id})) self.assertEqual(1, Appointment.objects.all().count()) diff --git a/smash/web/urls.py b/smash/web/urls.py index 9535617e2553ac24623eb791e74bd2704f9ae726..bbbdfbcde4fee7032359ec9a7030ab98e83e96ff 100644 --- a/smash/web/urls.py +++ b/smash/web/urls.py @@ -35,6 +35,11 @@ urlpatterns = [ url(r'^change_password/$', views.password.change_password, name='change_password'), + url(r'^appointment_types/$', views.appointment_type.AppointmentTypeListView.as_view(), name='web.views.appointment_types'), + url(r'^appointment_types/add$', views.appointment_type.AppointmentTypeCreateView.as_view(), name='web.views.appointment_type_add'), + url(r'^appointment_types/(?P<pk>\d+)/edit$', views.appointment_type.AppointmentTypeEditView.as_view(), name='web.views.appointment_type_edit'), + url(r'^appointment_types/(?P<pk>\d+)/delete$', views.appointment_type.AppointmentTypeDeleteView.as_view(), name='web.views.appointment_type_delete'), + #################### # APPOINTMENTS # #################### @@ -47,7 +52,7 @@ urlpatterns = [ url(r'^appointments/add/(?P<visit_id>\d+)$', views.appointment.appointment_add, name='web.views.appointment_add'), url(r'^appointments/add/general$', views.appointment.appointment_add, name='web.views.appointment_add_general'), url(r'^appointments/edit/(?P<id>\d+)$', views.appointment.appointment_edit, name='web.views.appointment_edit'), - url(r'^appointments/delete/(?P<appointment_id>\d+)$', views.appointment.appointment_delete, + url(r'^appointments/delete/(?P<pk>\d+)$', views.appointment.AppointmentDeleteView.as_view(), name='web.views.appointment_delete'), #################### diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py index c028b0f6f9f84363d444ebe19ffa637f83d81836..6fc26504ae191e39da81ca42b892de7ee451ae16 100644 --- a/smash/web/views/__init__.py +++ b/smash/web/views/__init__.py @@ -102,4 +102,5 @@ import redcap import rooms import uploaded_files import study -import password \ No newline at end of file +import password +import appointment_type \ No newline at end of file diff --git a/smash/web/views/appointment.py b/smash/web/views/appointment.py index 788fc10aaa892917a9f4f598087381397c2c789e..d370c13a5022f5248cdddbb86ce1ed30c57983ba 100644 --- a/smash/web/views/appointment.py +++ b/smash/web/views/appointment.py @@ -13,10 +13,16 @@ from . import wrap_response from web.forms import AppointmentDetailForm, AppointmentEditForm, AppointmentAddForm, SubjectEditForm, \ StudySubjectEditForm from ..models import Appointment, StudySubject, MailTemplate, Visit, Study +from django.views.generic import DeleteView +from . import WrappedView +from django.urls import reverse_lazy +from web.decorators import PermissionDecorator +from django.views.decorators.cache import never_cache logger = logging.getLogger(__name__) +@never_cache #https://docs.djangoproject.com/en/1.8/topics/cache/#controlling-cache-using-other-headers def appointments(request): context = { 'approaching_list': APPOINTMENT_LIST_APPROACHING, @@ -101,10 +107,7 @@ def appointment_edit(request, id): Appointment.objects.filter(visit=the_appointment.visit, status=Appointment.APPOINTMENT_STATUS_FINISHED).count() == 0: adjust_date = True - if appointment_form.cleaned_data["status"] == Appointment.APPOINTMENT_STATUS_FINISHED: - if not study.check_nd_number(study_subject_form.cleaned_data["nd_number"]): - study_subject_form.add_error('nd_number', ValidationError("invalid ND number")) - is_valid_form = False + if is_valid_form: appointment_form.save() if study_subject_form is not None: @@ -158,13 +161,20 @@ def appointment_edit(request, id): 'mail_templates': MailTemplate.get_appointment_mail_templates(languages) }) +class AppointmentDeleteView(DeleteView, WrappedView): + model = Appointment + success_url = reverse_lazy('web.views.appointments') + template_name = 'appointments/confirm_delete.html' -def appointment_delete(request, appointment_id): - appointment = get_object_or_404(Appointment, id=appointment_id) - if appointment.visit is not None or appointment.status != Appointment.APPOINTMENT_STATUS_SCHEDULED: - messages.error(request, "Appointment cannot be deleted") - return redirect('web.views.appointment_edit', id=appointment_id) - else: - appointment.delete() - messages.success(request, "Appointment deleted successfully") - return redirect('web.views.appointments') + def delete(self, request, *args, **kwargs): + appointment = self.get_object() + if appointment.status != Appointment.APPOINTMENT_STATUS_SCHEDULED: + messages.error(request, "Appointment cannot be deleted because is already finished") + return redirect('web.views.appointment_edit', id=appointment.id) + else: + messages.success(request, "Appointment deleted") + return super(AppointmentDeleteView, self).delete(request, *args, **kwargs) + + @PermissionDecorator('delete_appointment', 'configuration') + def dispatch(self, *args, **kwargs): + return super(AppointmentDeleteView, self).dispatch(*args, **kwargs) \ No newline at end of file diff --git a/smash/web/views/appointment_type.py b/smash/web/views/appointment_type.py new file mode 100644 index 0000000000000000000000000000000000000000..9aa924d1af11b85b9aa54d6a0594866325898277 --- /dev/null +++ b/smash/web/views/appointment_type.py @@ -0,0 +1,52 @@ +# coding=utf-8 +from django.views.generic import ListView, UpdateView, CreateView, DeleteView +from . import WrappedView +from ..models import AppointmentType +from django.urls import reverse_lazy +from django.contrib import messages +from web.decorators import PermissionDecorator + +class AppointmentTypeListView(ListView, WrappedView): + model = AppointmentType + template_name = 'appointment_types/index.html' + context_object_name = "appointment_types" + + @PermissionDecorator('change_appointmenttype', 'configuration') + def dispatch(self, *args, **kwargs): + return super(AppointmentTypeListView, self).dispatch(*args, **kwargs) + +class AppointmentTypeCreateView(CreateView, WrappedView): + model = AppointmentType + template_name = "appointment_types/add.html" + fields = '__all__' + success_url = reverse_lazy('web.views.appointment_types') + success_message = "Appointment type created" + + @PermissionDecorator('change_appointmenttype', 'configuration') + def dispatch(self, *args, **kwargs): + return super(AppointmentTypeCreateView, self).dispatch(*args, **kwargs) + +class AppointmentTypeEditView(UpdateView, WrappedView): + model = AppointmentType + success_url = reverse_lazy('web.views.appointment_types') + fields = '__all__' + success_message = "Appointment Type edited" + template_name = "appointment_types/edit.html" + context_object_name = "appointment_types" + + @PermissionDecorator('change_appointmenttype', 'configuration') + def dispatch(self, *args, **kwargs): + return super(AppointmentTypeEditView, self).dispatch(*args, **kwargs) + +class AppointmentTypeDeleteView(DeleteView, WrappedView): + model = AppointmentType + success_url = reverse_lazy('web.views.appointment_types') + template_name = 'appointment_types/confirm_delete.html' + + def delete(self, request, *args, **kwargs): + messages.success(request, "Appointment Type deleted") + return super(AppointmentTypeDeleteView, self).delete(request, *args, **kwargs) + + @PermissionDecorator('change_appointmenttype', 'configuration') + def dispatch(self, *args, **kwargs): + return super(AppointmentTypeDeleteView, self).dispatch(*args, **kwargs) \ No newline at end of file