Commit 6dfa35dabde6863ff12a1284152acc862766e417

Authored by filipecmedeiros
2 parents 1b549bf9 fa3bb953

Merge branch 'dev' of https://github.com/amadeusproject/amadeuslms into dev

Showing 102 changed files with 4944 additions and 779 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 102 files displayed.

amadeus/settings.py
@@ -53,6 +53,8 @@ INSTALLED_APPS = [ @@ -53,6 +53,8 @@ INSTALLED_APPS = [
53 'courses', 53 'courses',
54 'users', 54 'users',
55 'forum', 55 'forum',
  56 + 'poll',
  57 + 's3direct',
56 ] 58 ]
57 59
58 MIDDLEWARE_CLASSES = [ 60 MIDDLEWARE_CLASSES = [
@@ -178,6 +180,31 @@ MESSAGE_TAGS = { @@ -178,6 +180,31 @@ MESSAGE_TAGS = {
178 messages_constants.ERROR: 'danger', 180 messages_constants.ERROR: 'danger',
179 } 181 }
180 182
  183 +#Send email for forgot Password
  184 +EMAIL_USE_TLS = True
  185 +EMAIL_HOST = 'smtp.gmail.com'
  186 +EMAIL_PORT = 25
  187 +EMAIL_HOST_USER = 'amadeusteste@gmail.com'
  188 +EMAIL_HOST_PASSWORD = 'amadeusteste'
  189 +# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
  190 +
  191 +#s3direct
  192 +
  193 +# AWS keys
  194 +AWS_SECRET_ACCESS_KEY = ''
  195 +AWS_ACCESS_KEY_ID = ''
  196 +AWS_STORAGE_BUCKET_NAME = ''
  197 +
  198 +S3DIRECT_REGION = 'sa-east-1'
  199 +
  200 +from uuid import uuid4
  201 +
  202 +S3DIRECT_DESTINATIONS = {
  203 + # Specify a non-default bucket for PDFs
  204 + 'material': (lambda original_filename: 'uploads/material/'+str(uuid4())+'.pdf', lambda u: True, ['application/pdf']),
  205 +
  206 +}
  207 +
181 208
182 try: 209 try:
183 from .local_settings import * 210 from .local_settings import *
amadeus/urls.py
@@ -26,6 +26,9 @@ urlpatterns = [ @@ -26,6 +26,9 @@ urlpatterns = [
26 url(r'^forum/', include('forum.urls', namespace = 'forum')), 26 url(r'^forum/', include('forum.urls', namespace = 'forum')),
27 url(r'^admin/', admin.site.urls), 27 url(r'^admin/', admin.site.urls),
28 url(r'^', include('core.urls', namespace = 'core')), 28 url(r'^', include('core.urls', namespace = 'core')),
  29 +
  30 + #S3Direct
  31 + url(r'^s3direct/', include('s3direct.urls')),
29 ] 32 ]
30 33
31 urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) 34 urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
core/context_processors.py
@@ -5,6 +5,6 @@ def notifications(request): @@ -5,6 +5,6 @@ def notifications(request):
5 context['notifications'] = None 5 context['notifications'] = None
6 if request.user.is_authenticated: 6 if request.user.is_authenticated:
7 return { 7 return {
8 - 'notifications': Notification.objects.filter(user= request.user, read=False).order_by('-datetime') 8 + 'notifications': Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[0:5]
9 } 9 }
10 return context 10 return context
@@ -15,31 +15,7 @@ class RegisterUserForm(forms.ModelForm): @@ -15,31 +15,7 @@ class RegisterUserForm(forms.ModelForm):
15 15
16 def validate_cpf(self, cpf): 16 def validate_cpf(self, cpf):
17 cpf = ''.join(re.findall('\d', str(cpf))) 17 cpf = ''.join(re.findall('\d', str(cpf)))
18 - # print(cpf)  
19 -  
20 - # if (not cpf) or (len(cpf) < 11):  
21 - # return False  
22 -  
23 - # #Get only the first 9 digits and generate other 2  
24 - # _int = map(int, cpf)  
25 - # integer = list(map(int, cpf))  
26 - # new = integer[:9]  
27 -  
28 - # while len(new) < 11:  
29 - # r = sum([(len(new) + 1 - i)* v for i, v in enumerate(new)]) % 11  
30 -  
31 - # if r > 1:  
32 - # f = 11 - r  
33 - # else:  
34 - # f = 0  
35 - # new.append(f)  
36 -  
37 - # #if generated number is the same(original) the cpf is valid  
38 - # new2 = list(new)  
39 - # if new2 == _int:  
40 - # return cpf  
41 - # else:  
42 - # return False 18 +
43 if cpfcnpj.validate(cpf): 19 if cpfcnpj.validate(cpf):
44 return True 20 return True
45 return False 21 return False
core/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 -# Generated by Django 1.10 on 2016-09-22 05:46 2 +# Generated by Django 1.10 on 2016-10-02 00:17
3 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 import autoslug.fields 5 import autoslug.fields
6 -from django.conf import settings  
7 from django.db import migrations, models 6 from django.db import migrations, models
8 import django.db.models.deletion 7 import django.db.models.deletion
9 8
@@ -13,7 +12,6 @@ class Migration(migrations.Migration): @@ -13,7 +12,6 @@ class Migration(migrations.Migration):
13 initial = True 12 initial = True
14 13
15 dependencies = [ 14 dependencies = [
16 - migrations.swappable_dependency(settings.AUTH_USER_MODEL),  
17 ] 15 ]
18 16
19 operations = [ 17 operations = [
@@ -33,7 +31,6 @@ class Migration(migrations.Migration): @@ -33,7 +31,6 @@ class Migration(migrations.Migration):
33 name='Action_Resource', 31 name='Action_Resource',
34 fields=[ 32 fields=[
35 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 33 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
36 - ('action', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied')),  
37 ], 34 ],
38 options={ 35 options={
39 'verbose_name': 'Action_Resource', 36 'verbose_name': 'Action_Resource',
@@ -45,8 +42,6 @@ class Migration(migrations.Migration): @@ -45,8 +42,6 @@ class Migration(migrations.Migration):
45 fields=[ 42 fields=[
46 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 43 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
47 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), 44 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')),
48 - ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')),  
49 - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor')),  
50 ], 45 ],
51 options={ 46 options={
52 'verbose_name': 'Log', 47 'verbose_name': 'Log',
@@ -61,8 +56,6 @@ class Migration(migrations.Migration): @@ -61,8 +56,6 @@ class Migration(migrations.Migration):
61 ('read', models.BooleanField(default=False, verbose_name='Read')), 56 ('read', models.BooleanField(default=False, verbose_name='Read')),
62 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), 57 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')),
63 ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')), 58 ('action_resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource')),
64 - ('actor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer')),  
65 - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User')),  
66 ], 59 ],
67 options={ 60 options={
68 'verbose_name': 'Notification', 61 'verbose_name': 'Notification',
@@ -74,7 +67,7 @@ class Migration(migrations.Migration): @@ -74,7 +67,7 @@ class Migration(migrations.Migration):
74 fields=[ 67 fields=[
75 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 68 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
76 ('name', models.CharField(max_length=100, verbose_name='Name')), 69 ('name', models.CharField(max_length=100, verbose_name='Name')),
77 - ('slug', autoslug.fields.AutoSlugField(editable=False, null=True, populate_from='name', unique=True, verbose_name='Slug')), 70 + ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')),
78 ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')), 71 ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')),
79 ('url', models.CharField(default='', max_length=100, verbose_name='URL')), 72 ('url', models.CharField(default='', max_length=100, verbose_name='URL')),
80 ], 73 ],
@@ -83,9 +76,4 @@ class Migration(migrations.Migration): @@ -83,9 +76,4 @@ class Migration(migrations.Migration):
83 'verbose_name_plural': 'Resources', 76 'verbose_name_plural': 'Resources',
84 }, 77 },
85 ), 78 ),
86 - migrations.AddField(  
87 - model_name='action_resource',  
88 - name='resource',  
89 - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'),  
90 - ),  
91 ] 79 ]
core/migrations/0002_auto_20161001_2117.py 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-02 00:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  16 + ('core', '0001_initial'),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='notification',
  22 + name='actor',
  23 + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_Performer', to=settings.AUTH_USER_MODEL, verbose_name='Perfomer'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='notification',
  27 + name='user',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_Actor', to=settings.AUTH_USER_MODEL, verbose_name='User'),
  29 + ),
  30 + migrations.AddField(
  31 + model_name='log',
  32 + name='action_resource',
  33 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action_Resource', verbose_name='Action_Resource'),
  34 + ),
  35 + migrations.AddField(
  36 + model_name='log',
  37 + name='user',
  38 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor'),
  39 + ),
  40 + migrations.AddField(
  41 + model_name='action_resource',
  42 + name='action',
  43 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Action', verbose_name='Action_Applied'),
  44 + ),
  45 + migrations.AddField(
  46 + model_name='action_resource',
  47 + name='resource',
  48 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Resource', verbose_name='Resource'),
  49 + ),
  50 + ]
core/models.py
@@ -6,20 +6,20 @@ from autoslug.fields import AutoSlugField @@ -6,20 +6,20 @@ from autoslug.fields import AutoSlugField
6 6
7 class Action(models.Model): 7 class Action(models.Model):
8 """ 8 """
9 - It represents an Action on the program by a User such as "create post", 9 + It represents an Action on the program by a User such as "create post",
10 "visualize post", etc. It is supposed to be created everytime we want an aciton 10 "visualize post", etc. It is supposed to be created everytime we want an aciton
11 """ 11 """
12 12
13 name = models.CharField(_('Name'), max_length = 100) 13 name = models.CharField(_('Name'), max_length = 100)
14 created_date = models.DateField(_('Created Date'), auto_now_add=True) 14 created_date = models.DateField(_('Created Date'), auto_now_add=True)
15 - 15 +
16 class Meta: 16 class Meta:
17 verbose_name = "Action" 17 verbose_name = "Action"
18 verbose_name_plural = "Actions" 18 verbose_name_plural = "Actions"
19 19
20 def __str__(self): 20 def __str__(self):
21 return self.name 21 return self.name
22 - 22 +
23 23
24 class Resource(models.Model): 24 class Resource(models.Model):
25 """ 25 """
@@ -27,38 +27,38 @@ class Resource(models.Model): @@ -27,38 +27,38 @@ class Resource(models.Model):
27 Example: Pool was answered (Resource: Pool), PDF was visualized(Resource: PDF). 27 Example: Pool was answered (Resource: Pool), PDF was visualized(Resource: PDF).
28 28
29 Attributes: 29 Attributes:
30 - @name: name of the resource affected, it will be unique because a resource can be affecte 30 + @name: name of the resource affected, it will be unique because a resource can be affecte
31 by a huge amount of actions 31 by a huge amount of actions
32 @created_date: The date the resource was created 32 @created_date: The date the resource was created
33 @link: Which URL made that resource able to find 33 @link: Which URL made that resource able to find
34 """ 34 """
35 35
36 name = models.CharField(_('Name'), max_length =100) 36 name = models.CharField(_('Name'), max_length =100)
37 - slug = AutoSlugField(_("Slug"), populate_from='name', unique=True, null=True) 37 + slug = AutoSlugField(_("Slug"), populate_from='name', unique=True)
38 created_date = models.DateField(_('Created Date'), auto_now_add=True) 38 created_date = models.DateField(_('Created Date'), auto_now_add=True)
39 url = models.CharField(_('URL'), max_length =100, default="") 39 url = models.CharField(_('URL'), max_length =100, default="")
40 40
41 41
42 class Meta: 42 class Meta:
43 verbose_name = "Resource" 43 verbose_name = "Resource"
44 - verbose_name_plural = "Resources" 44 + verbose_name_plural = "Resources"
45 45
46 def __str__(self): 46 def __str__(self):
47 return self.name 47 return self.name
48 48
49 49
50 class Action_Resource(models.Model): 50 class Action_Resource(models.Model):
51 - 51 +
52 action = models.ForeignKey(Action , verbose_name= _('Action_Applied')) 52 action = models.ForeignKey(Action , verbose_name= _('Action_Applied'))
53 resource = models.ForeignKey(Resource, verbose_name = _('Resource')) 53 resource = models.ForeignKey(Resource, verbose_name = _('Resource'))
54 - 54 +
55 class Meta: 55 class Meta:
56 verbose_name = "Action_Resource" 56 verbose_name = "Action_Resource"
57 verbose_name_plural = "Action_Resources" 57 verbose_name_plural = "Action_Resources"
58 58
59 def __str__(self): 59 def __str__(self):
60 return ''.join([self.action.name, " / ", self.resource.name]) 60 return ''.join([self.action.name, " / ", self.resource.name])
61 - 61 +
62 62
63 class Notification(models.Model): 63 class Notification(models.Model):
64 """ 64 """
@@ -77,7 +77,7 @@ class Notification(models.Model): @@ -77,7 +77,7 @@ class Notification(models.Model):
77 datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True) 77 datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True)
78 action_resource = models.ForeignKey(Action_Resource, verbose_name = _('Action_Resource')) 78 action_resource = models.ForeignKey(Action_Resource, verbose_name = _('Action_Resource'))
79 actor = models.ForeignKey(User, related_name = _('%(class)s_Performer'), verbose_name= _('Perfomer'), null = True) 79 actor = models.ForeignKey(User, related_name = _('%(class)s_Performer'), verbose_name= _('Perfomer'), null = True)
80 - 80 +
81 class Meta: 81 class Meta:
82 verbose_name = _("Notification") 82 verbose_name = _("Notification")
83 verbose_name_plural = _("Notifications") 83 verbose_name_plural = _("Notifications")
core/static/css/base/amadeus.css
@@ -266,7 +266,6 @@ li.alert_li:hover{background-color:#eee} @@ -266,7 +266,6 @@ li.alert_li:hover{background-color:#eee}
266 a.alert_message{color : grey} 266 a.alert_message{color : grey}
267 a.alert_message:hover{color : grey} 267 a.alert_message:hover{color : grey}
268 268
269 -/*=================== Ailson - Please Don't touch*/  
270 .breadcrumb .divider{ 269 .breadcrumb .divider{
271 display: none; 270 display: none;
272 } 271 }
@@ -321,3 +320,5 @@ body .container .jumbotron-inverse, body .container .well-inverse, body .contain @@ -321,3 +320,5 @@ body .container .jumbotron-inverse, body .container .well-inverse, body .contain
321 .notification-count { 320 .notification-count {
322 background-color: #FF0000; 321 background-color: #FF0000;
323 } 322 }
  323 +
  324 +.datepicker{z-index:9999 !important}
324 \ No newline at end of file 325 \ No newline at end of file
core/static/css/vendor/alertifyjs/alertify.css 0 → 100644
@@ -0,0 +1,884 @@ @@ -0,0 +1,884 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer {
  7 + position: fixed;
  8 + z-index: 1981;
  9 + top: 0;
  10 + right: 0;
  11 + bottom: 0;
  12 + left: 0;
  13 + padding: 0;
  14 + margin: 0;
  15 + background-color: #252525;
  16 + opacity: .5;
  17 +}
  18 +.alertify .ajs-modal {
  19 + position: fixed;
  20 + top: 0;
  21 + right: 0;
  22 + left: 0;
  23 + bottom: 0;
  24 + padding: 0;
  25 + overflow-y: auto;
  26 + z-index: 1981;
  27 +}
  28 +.alertify .ajs-dialog {
  29 + position: relative;
  30 + margin: 5% auto;
  31 + min-height: 110px;
  32 + max-width: 500px;
  33 + padding: 24px 24px 0 24px;
  34 + outline: 0;
  35 + background-color: #fff;
  36 +}
  37 +.alertify .ajs-dialog.ajs-capture:before {
  38 + content: '';
  39 + position: absolute;
  40 + top: 0;
  41 + right: 0;
  42 + bottom: 0;
  43 + left: 0;
  44 + display: block;
  45 + z-index: 1;
  46 +}
  47 +.alertify .ajs-reset {
  48 + position: absolute !important;
  49 + display: inline !important;
  50 + width: 0 !important;
  51 + height: 0 !important;
  52 + opacity: 0 !important;
  53 +}
  54 +.alertify .ajs-commands {
  55 + position: absolute;
  56 + right: 4px;
  57 + margin: -14px 24px 0 0;
  58 + z-index: 2;
  59 +}
  60 +.alertify .ajs-commands button {
  61 + display: none;
  62 + width: 10px;
  63 + height: 10px;
  64 + margin-left: 10px;
  65 + padding: 10px;
  66 + border: 0;
  67 + background-color: transparent;
  68 + background-repeat: no-repeat;
  69 + background-position: center;
  70 + cursor: pointer;
  71 +}
  72 +.alertify .ajs-commands button.ajs-close {
  73 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC);
  74 +}
  75 +.alertify .ajs-commands button.ajs-maximize {
  76 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC);
  77 +}
  78 +.alertify .ajs-header {
  79 + margin: -24px;
  80 + margin-bottom: 0;
  81 + padding: 16px 24px;
  82 + background-color: #fff;
  83 +}
  84 +.alertify .ajs-body {
  85 + min-height: 56px;
  86 +}
  87 +.alertify .ajs-body .ajs-content {
  88 + padding: 16px 24px 16px 16px;
  89 +}
  90 +.alertify .ajs-footer {
  91 + padding: 4px;
  92 + margin-left: -24px;
  93 + margin-right: -24px;
  94 + min-height: 43px;
  95 + background-color: #fff;
  96 +}
  97 +.alertify .ajs-footer .ajs-buttons.ajs-primary {
  98 + text-align: right;
  99 +}
  100 +.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button {
  101 + margin: 4px;
  102 +}
  103 +.alertify .ajs-footer .ajs-buttons.ajs-auxiliary {
  104 + float: left;
  105 + clear: none;
  106 + text-align: left;
  107 +}
  108 +.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button {
  109 + margin: 4px;
  110 +}
  111 +.alertify .ajs-footer .ajs-buttons .ajs-button {
  112 + min-width: 88px;
  113 + min-height: 35px;
  114 +}
  115 +.alertify .ajs-handle {
  116 + position: absolute;
  117 + display: none;
  118 + width: 10px;
  119 + height: 10px;
  120 + right: 0;
  121 + bottom: 0;
  122 + z-index: 1;
  123 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);
  124 + -webkit-transform: scaleX(1) /*rtl:scaleX(-1)*/;
  125 + transform: scaleX(1) /*rtl:scaleX(-1)*/;
  126 + cursor: se-resize;
  127 +}
  128 +.alertify.ajs-no-overflow .ajs-body .ajs-content {
  129 + overflow: hidden !important;
  130 +}
  131 +.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content {
  132 + left: 0;
  133 + right: 0;
  134 + padding: 0;
  135 +}
  136 +.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body {
  137 + margin-left: -24px;
  138 + margin-right: -24px;
  139 +}
  140 +.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content {
  141 + padding: 0;
  142 +}
  143 +.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content {
  144 + left: 0;
  145 + right: 0;
  146 +}
  147 +.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,
  148 +.alertify.ajs-maximizable .ajs-commands button.ajs-restore {
  149 + display: inline-block;
  150 +}
  151 +.alertify.ajs-closable .ajs-commands button.ajs-close {
  152 + display: inline-block;
  153 +}
  154 +.alertify.ajs-maximized .ajs-dialog {
  155 + width: 100% !important;
  156 + height: 100% !important;
  157 + max-width: none !important;
  158 + margin: 0 auto !important;
  159 + top: 0 !important;
  160 + left: 0 !important;
  161 +}
  162 +.alertify.ajs-maximized.ajs-modeless .ajs-modal {
  163 + position: fixed !important;
  164 + min-height: 100% !important;
  165 + max-height: none !important;
  166 + margin: 0 !important;
  167 +}
  168 +.alertify.ajs-maximized .ajs-commands button.ajs-maximize {
  169 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=);
  170 +}
  171 +.alertify.ajs-resizable .ajs-dialog,
  172 +.alertify.ajs-maximized .ajs-dialog {
  173 + padding: 0;
  174 +}
  175 +.alertify.ajs-resizable .ajs-commands,
  176 +.alertify.ajs-maximized .ajs-commands {
  177 + margin: 14px 24px 0 0;
  178 +}
  179 +.alertify.ajs-resizable .ajs-header,
  180 +.alertify.ajs-maximized .ajs-header {
  181 + position: absolute;
  182 + top: 0;
  183 + left: 0;
  184 + right: 0;
  185 + margin: 0;
  186 + padding: 16px 24px;
  187 +}
  188 +.alertify.ajs-resizable .ajs-body,
  189 +.alertify.ajs-maximized .ajs-body {
  190 + min-height: 224px;
  191 + display: inline-block;
  192 +}
  193 +.alertify.ajs-resizable .ajs-body .ajs-content,
  194 +.alertify.ajs-maximized .ajs-body .ajs-content {
  195 + position: absolute;
  196 + top: 50px;
  197 + right: 24px;
  198 + bottom: 50px;
  199 + left: 24px;
  200 + overflow: auto;
  201 +}
  202 +.alertify.ajs-resizable .ajs-footer,
  203 +.alertify.ajs-maximized .ajs-footer {
  204 + position: absolute;
  205 + left: 0;
  206 + right: 0;
  207 + bottom: 0;
  208 + margin: 0;
  209 +}
  210 +.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog {
  211 + min-width: 548px;
  212 +}
  213 +.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle {
  214 + display: block;
  215 +}
  216 +.alertify.ajs-movable:not(.ajs-maximized) .ajs-header {
  217 + cursor: move;
  218 +}
  219 +.alertify.ajs-modeless .ajs-dimmer,
  220 +.alertify.ajs-modeless .ajs-reset {
  221 + display: none;
  222 +}
  223 +.alertify.ajs-modeless .ajs-modal {
  224 + overflow: visible;
  225 + max-width: none;
  226 + max-height: 0;
  227 +}
  228 +.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin {
  229 + display: inline-block;
  230 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC);
  231 +}
  232 +.alertify.ajs-modeless.ajs-unpinned .ajs-modal {
  233 + position: absolute;
  234 +}
  235 +.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin {
  236 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=);
  237 +}
  238 +.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body {
  239 + max-height: 500px;
  240 + overflow: auto;
  241 +}
  242 +.alertify.ajs-basic .ajs-header {
  243 + opacity: 0;
  244 +}
  245 +.alertify.ajs-basic .ajs-footer {
  246 + visibility: hidden;
  247 +}
  248 +.alertify.ajs-frameless .ajs-header {
  249 + position: absolute;
  250 + top: 0;
  251 + left: 0;
  252 + right: 0;
  253 + min-height: 60px;
  254 + margin: 0;
  255 + padding: 0;
  256 + opacity: 0;
  257 + z-index: 1;
  258 +}
  259 +.alertify.ajs-frameless .ajs-footer {
  260 + display: none;
  261 +}
  262 +.alertify.ajs-frameless .ajs-body .ajs-content {
  263 + position: absolute;
  264 + top: 0;
  265 + right: 0;
  266 + bottom: 0;
  267 + left: 0;
  268 +}
  269 +.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog {
  270 + padding-top: 0;
  271 +}
  272 +.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands {
  273 + margin-top: 0;
  274 +}
  275 +.ajs-no-overflow {
  276 + overflow: hidden !important;
  277 + outline: none;
  278 +}
  279 +.ajs-no-overflow.ajs-fixed {
  280 + position: fixed;
  281 + top: 0;
  282 + right: 0;
  283 + bottom: 0;
  284 + left: 0;
  285 + overflow-y: scroll!important;
  286 +}
  287 +.ajs-no-selection,
  288 +.ajs-no-selection * {
  289 + -webkit-user-select: none;
  290 + -moz-user-select: none;
  291 + -ms-user-select: none;
  292 + user-select: none;
  293 +}
  294 +@media screen and (max-width: 568px) {
  295 + .alertify .ajs-dialog {
  296 + min-width: 150px;
  297 + }
  298 + .alertify:not(.ajs-maximized) .ajs-modal {
  299 + padding: 0 5%;
  300 + }
  301 + .alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog {
  302 + min-width: initial;
  303 + min-width: auto /*IE fallback*/;
  304 + }
  305 +}
  306 +@-moz-document url-prefix() {
  307 + .alertify button:focus {
  308 + outline: 1px dotted #3593D2;
  309 + }
  310 +}
  311 +.alertify .ajs-dimmer,
  312 +.alertify .ajs-modal {
  313 + -webkit-transform: translate3d(0, 0, 0);
  314 + transform: translate3d(0, 0, 0);
  315 + transition-property: opacity, visibility;
  316 + transition-timing-function: linear;
  317 + transition-duration: 250ms;
  318 +}
  319 +.alertify.ajs-hidden .ajs-dimmer,
  320 +.alertify.ajs-hidden .ajs-modal {
  321 + visibility: hidden;
  322 + opacity: 0;
  323 +}
  324 +.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog {
  325 + -webkit-animation-duration: 500ms;
  326 + animation-duration: 500ms;
  327 +}
  328 +.alertify.ajs-out.ajs-hidden .ajs-dialog {
  329 + -webkit-animation-duration: 250ms;
  330 + animation-duration: 250ms;
  331 +}
  332 +.alertify .ajs-dialog.ajs-shake {
  333 + -webkit-animation-name: ajs-shake;
  334 + animation-name: ajs-shake;
  335 + -webkit-animation-duration: .1s;
  336 + animation-duration: .1s;
  337 + -webkit-animation-fill-mode: both;
  338 + animation-fill-mode: both;
  339 +}
  340 +@-webkit-keyframes ajs-shake {
  341 + 0%,
  342 + 100% {
  343 + -webkit-transform: translate3d(0, 0, 0);
  344 + transform: translate3d(0, 0, 0);
  345 + }
  346 + 10%,
  347 + 30%,
  348 + 50%,
  349 + 70%,
  350 + 90% {
  351 + -webkit-transform: translate3d(-10px, 0, 0);
  352 + transform: translate3d(-10px, 0, 0);
  353 + }
  354 + 20%,
  355 + 40%,
  356 + 60%,
  357 + 80% {
  358 + -webkit-transform: translate3d(10px, 0, 0);
  359 + transform: translate3d(10px, 0, 0);
  360 + }
  361 +}
  362 +@keyframes ajs-shake {
  363 + 0%,
  364 + 100% {
  365 + -webkit-transform: translate3d(0, 0, 0);
  366 + transform: translate3d(0, 0, 0);
  367 + }
  368 + 10%,
  369 + 30%,
  370 + 50%,
  371 + 70%,
  372 + 90% {
  373 + -webkit-transform: translate3d(-10px, 0, 0);
  374 + transform: translate3d(-10px, 0, 0);
  375 + }
  376 + 20%,
  377 + 40%,
  378 + 60%,
  379 + 80% {
  380 + -webkit-transform: translate3d(10px, 0, 0);
  381 + transform: translate3d(10px, 0, 0);
  382 + }
  383 +}
  384 +.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog {
  385 + -webkit-animation-name: ajs-slideIn;
  386 + animation-name: ajs-slideIn;
  387 + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  388 + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  389 +}
  390 +.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog {
  391 + -webkit-animation-name: ajs-slideOut;
  392 + animation-name: ajs-slideOut;
  393 + -webkit-animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
  394 + animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
  395 +}
  396 +.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog {
  397 + -webkit-animation-name: ajs-zoomIn;
  398 + animation-name: ajs-zoomIn;
  399 +}
  400 +.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog {
  401 + -webkit-animation-name: ajs-zoomOut;
  402 + animation-name: ajs-zoomOut;
  403 +}
  404 +.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog {
  405 + -webkit-animation-name: ajs-fadeIn;
  406 + animation-name: ajs-fadeIn;
  407 +}
  408 +.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog {
  409 + -webkit-animation-name: ajs-fadeOut;
  410 + animation-name: ajs-fadeOut;
  411 +}
  412 +.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog {
  413 + -webkit-animation-name: ajs-pulseIn;
  414 + animation-name: ajs-pulseIn;
  415 +}
  416 +.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog {
  417 + -webkit-animation-name: ajs-pulseOut;
  418 + animation-name: ajs-pulseOut;
  419 +}
  420 +.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog {
  421 + -webkit-animation-name: ajs-flipInX;
  422 + animation-name: ajs-flipInX;
  423 +}
  424 +.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog {
  425 + -webkit-animation-name: ajs-flipOutX;
  426 + animation-name: ajs-flipOutX;
  427 +}
  428 +.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog {
  429 + -webkit-animation-name: ajs-flipInY;
  430 + animation-name: ajs-flipInY;
  431 +}
  432 +.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog {
  433 + -webkit-animation-name: ajs-flipOutY;
  434 + animation-name: ajs-flipOutY;
  435 +}
  436 +@-webkit-keyframes ajs-pulseIn {
  437 + 0%,
  438 + 20%,
  439 + 40%,
  440 + 60%,
  441 + 80%,
  442 + 100% {
  443 + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  444 + }
  445 + 0% {
  446 + opacity: 0;
  447 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  448 + transform: scale3d(0.3, 0.3, 0.3);
  449 + }
  450 + 20% {
  451 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  452 + transform: scale3d(1.1, 1.1, 1.1);
  453 + }
  454 + 40% {
  455 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  456 + transform: scale3d(0.9, 0.9, 0.9);
  457 + }
  458 + 60% {
  459 + opacity: 1;
  460 + -webkit-transform: scale3d(1.03, 1.03, 1.03);
  461 + transform: scale3d(1.03, 1.03, 1.03);
  462 + }
  463 + 80% {
  464 + -webkit-transform: scale3d(0.97, 0.97, 0.97);
  465 + transform: scale3d(0.97, 0.97, 0.97);
  466 + }
  467 + 100% {
  468 + opacity: 1;
  469 + -webkit-transform: scale3d(1, 1, 1);
  470 + transform: scale3d(1, 1, 1);
  471 + }
  472 +}
  473 +@keyframes ajs-pulseIn {
  474 + 0%,
  475 + 20%,
  476 + 40%,
  477 + 60%,
  478 + 80%,
  479 + 100% {
  480 + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  481 + }
  482 + 0% {
  483 + opacity: 0;
  484 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  485 + transform: scale3d(0.3, 0.3, 0.3);
  486 + }
  487 + 20% {
  488 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  489 + transform: scale3d(1.1, 1.1, 1.1);
  490 + }
  491 + 40% {
  492 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  493 + transform: scale3d(0.9, 0.9, 0.9);
  494 + }
  495 + 60% {
  496 + opacity: 1;
  497 + -webkit-transform: scale3d(1.03, 1.03, 1.03);
  498 + transform: scale3d(1.03, 1.03, 1.03);
  499 + }
  500 + 80% {
  501 + -webkit-transform: scale3d(0.97, 0.97, 0.97);
  502 + transform: scale3d(0.97, 0.97, 0.97);
  503 + }
  504 + 100% {
  505 + opacity: 1;
  506 + -webkit-transform: scale3d(1, 1, 1);
  507 + transform: scale3d(1, 1, 1);
  508 + }
  509 +}
  510 +@-webkit-keyframes ajs-pulseOut {
  511 + 20% {
  512 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  513 + transform: scale3d(0.9, 0.9, 0.9);
  514 + }
  515 + 50%,
  516 + 55% {
  517 + opacity: 1;
  518 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  519 + transform: scale3d(1.1, 1.1, 1.1);
  520 + }
  521 + 100% {
  522 + opacity: 0;
  523 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  524 + transform: scale3d(0.3, 0.3, 0.3);
  525 + }
  526 +}
  527 +@keyframes ajs-pulseOut {
  528 + 20% {
  529 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  530 + transform: scale3d(0.9, 0.9, 0.9);
  531 + }
  532 + 50%,
  533 + 55% {
  534 + opacity: 1;
  535 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  536 + transform: scale3d(1.1, 1.1, 1.1);
  537 + }
  538 + 100% {
  539 + opacity: 0;
  540 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  541 + transform: scale3d(0.3, 0.3, 0.3);
  542 + }
  543 +}
  544 +@-webkit-keyframes ajs-zoomIn {
  545 + 0% {
  546 + opacity: 0;
  547 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  548 + transform: scale3d(0.25, 0.25, 0.25);
  549 + }
  550 + 100% {
  551 + opacity: 1;
  552 + -webkit-transform: scale3d(1, 1, 1);
  553 + transform: scale3d(1, 1, 1);
  554 + }
  555 +}
  556 +@keyframes ajs-zoomIn {
  557 + 0% {
  558 + opacity: 0;
  559 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  560 + transform: scale3d(0.25, 0.25, 0.25);
  561 + }
  562 + 100% {
  563 + opacity: 1;
  564 + -webkit-transform: scale3d(1, 1, 1);
  565 + transform: scale3d(1, 1, 1);
  566 + }
  567 +}
  568 +@-webkit-keyframes ajs-zoomOut {
  569 + 0% {
  570 + opacity: 1;
  571 + -webkit-transform: scale3d(1, 1, 1);
  572 + transform: scale3d(1, 1, 1);
  573 + }
  574 + 100% {
  575 + opacity: 0;
  576 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  577 + transform: scale3d(0.25, 0.25, 0.25);
  578 + }
  579 +}
  580 +@keyframes ajs-zoomOut {
  581 + 0% {
  582 + opacity: 1;
  583 + -webkit-transform: scale3d(1, 1, 1);
  584 + transform: scale3d(1, 1, 1);
  585 + }
  586 + 100% {
  587 + opacity: 0;
  588 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  589 + transform: scale3d(0.25, 0.25, 0.25);
  590 + }
  591 +}
  592 +@-webkit-keyframes ajs-fadeIn {
  593 + 0% {
  594 + opacity: 0;
  595 + }
  596 + 100% {
  597 + opacity: 1;
  598 + }
  599 +}
  600 +@keyframes ajs-fadeIn {
  601 + 0% {
  602 + opacity: 0;
  603 + }
  604 + 100% {
  605 + opacity: 1;
  606 + }
  607 +}
  608 +@-webkit-keyframes ajs-fadeOut {
  609 + 0% {
  610 + opacity: 1;
  611 + }
  612 + 100% {
  613 + opacity: 0;
  614 + }
  615 +}
  616 +@keyframes ajs-fadeOut {
  617 + 0% {
  618 + opacity: 1;
  619 + }
  620 + 100% {
  621 + opacity: 0;
  622 + }
  623 +}
  624 +@-webkit-keyframes ajs-flipInX {
  625 + 0% {
  626 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  627 + transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  628 + transition-timing-function: ease-in;
  629 + opacity: 0;
  630 + }
  631 + 40% {
  632 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  633 + transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  634 + transition-timing-function: ease-in;
  635 + }
  636 + 60% {
  637 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
  638 + transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
  639 + opacity: 1;
  640 + }
  641 + 80% {
  642 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  643 + transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  644 + }
  645 + 100% {
  646 + -webkit-transform: perspective(400px);
  647 + transform: perspective(400px);
  648 + }
  649 +}
  650 +@keyframes ajs-flipInX {
  651 + 0% {
  652 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  653 + transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  654 + transition-timing-function: ease-in;
  655 + opacity: 0;
  656 + }
  657 + 40% {
  658 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  659 + transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  660 + transition-timing-function: ease-in;
  661 + }
  662 + 60% {
  663 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
  664 + transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
  665 + opacity: 1;
  666 + }
  667 + 80% {
  668 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  669 + transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
  670 + }
  671 + 100% {
  672 + -webkit-transform: perspective(400px);
  673 + transform: perspective(400px);
  674 + }
  675 +}
  676 +@-webkit-keyframes ajs-flipOutX {
  677 + 0% {
  678 + -webkit-transform: perspective(400px);
  679 + transform: perspective(400px);
  680 + }
  681 + 30% {
  682 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  683 + transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  684 + opacity: 1;
  685 + }
  686 + 100% {
  687 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  688 + transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  689 + opacity: 0;
  690 + }
  691 +}
  692 +@keyframes ajs-flipOutX {
  693 + 0% {
  694 + -webkit-transform: perspective(400px);
  695 + transform: perspective(400px);
  696 + }
  697 + 30% {
  698 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  699 + transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
  700 + opacity: 1;
  701 + }
  702 + 100% {
  703 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  704 + transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
  705 + opacity: 0;
  706 + }
  707 +}
  708 +@-webkit-keyframes ajs-flipInY {
  709 + 0% {
  710 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  711 + transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  712 + transition-timing-function: ease-in;
  713 + opacity: 0;
  714 + }
  715 + 40% {
  716 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
  717 + transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
  718 + transition-timing-function: ease-in;
  719 + }
  720 + 60% {
  721 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
  722 + transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
  723 + opacity: 1;
  724 + }
  725 + 80% {
  726 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
  727 + transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
  728 + }
  729 + 100% {
  730 + -webkit-transform: perspective(400px);
  731 + transform: perspective(400px);
  732 + }
  733 +}
  734 +@keyframes ajs-flipInY {
  735 + 0% {
  736 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  737 + transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  738 + transition-timing-function: ease-in;
  739 + opacity: 0;
  740 + }
  741 + 40% {
  742 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
  743 + transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
  744 + transition-timing-function: ease-in;
  745 + }
  746 + 60% {
  747 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
  748 + transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
  749 + opacity: 1;
  750 + }
  751 + 80% {
  752 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
  753 + transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
  754 + }
  755 + 100% {
  756 + -webkit-transform: perspective(400px);
  757 + transform: perspective(400px);
  758 + }
  759 +}
  760 +@-webkit-keyframes ajs-flipOutY {
  761 + 0% {
  762 + -webkit-transform: perspective(400px);
  763 + transform: perspective(400px);
  764 + }
  765 + 30% {
  766 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
  767 + transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
  768 + opacity: 1;
  769 + }
  770 + 100% {
  771 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  772 + transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  773 + opacity: 0;
  774 + }
  775 +}
  776 +@keyframes ajs-flipOutY {
  777 + 0% {
  778 + -webkit-transform: perspective(400px);
  779 + transform: perspective(400px);
  780 + }
  781 + 30% {
  782 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
  783 + transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
  784 + opacity: 1;
  785 + }
  786 + 100% {
  787 + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  788 + transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
  789 + opacity: 0;
  790 + }
  791 +}
  792 +@-webkit-keyframes ajs-slideIn {
  793 + 0% {
  794 + margin-top: -100%;
  795 + }
  796 + 100% {
  797 + margin-top: 5%;
  798 + }
  799 +}
  800 +@keyframes ajs-slideIn {
  801 + 0% {
  802 + margin-top: -100%;
  803 + }
  804 + 100% {
  805 + margin-top: 5%;
  806 + }
  807 +}
  808 +@-webkit-keyframes ajs-slideOut {
  809 + 0% {
  810 + margin-top: 5%;
  811 + }
  812 + 100% {
  813 + margin-top: -100%;
  814 + }
  815 +}
  816 +@keyframes ajs-slideOut {
  817 + 0% {
  818 + margin-top: 5%;
  819 + }
  820 + 100% {
  821 + margin-top: -100%;
  822 + }
  823 +}
  824 +.alertify-notifier {
  825 + position: fixed;
  826 + width: 0;
  827 + overflow: visible;
  828 + z-index: 1982;
  829 + -webkit-transform: translate3d(0, 0, 0);
  830 + transform: translate3d(0, 0, 0);
  831 +}
  832 +.alertify-notifier .ajs-message {
  833 + position: relative;
  834 + width: 260px;
  835 + max-height: 0;
  836 + padding: 0;
  837 + opacity: 0;
  838 + margin: 0;
  839 + -webkit-transform: translate3d(0, 0, 0);
  840 + transform: translate3d(0, 0, 0);
  841 + transition-duration: 250ms;
  842 + transition-timing-function: linear;
  843 +}
  844 +.alertify-notifier .ajs-message.ajs-visible {
  845 + transition-duration: 500ms;
  846 + transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  847 + opacity: 1;
  848 + max-height: 100%;
  849 + padding: 15px;
  850 + margin-top: 10px;
  851 +}
  852 +.alertify-notifier .ajs-message.ajs-success {
  853 + background: rgba(91, 189, 114, 0.95);
  854 +}
  855 +.alertify-notifier .ajs-message.ajs-error {
  856 + background: rgba(217, 92, 92, 0.95);
  857 +}
  858 +.alertify-notifier .ajs-message.ajs-warning {
  859 + background: rgba(252, 248, 215, 0.95);
  860 +}
  861 +.alertify-notifier.ajs-top {
  862 + top: 10px;
  863 +}
  864 +.alertify-notifier.ajs-bottom {
  865 + bottom: 10px;
  866 +}
  867 +.alertify-notifier.ajs-right {
  868 + right: 10px;
  869 +}
  870 +.alertify-notifier.ajs-right .ajs-message {
  871 + right: -320px;
  872 +}
  873 +.alertify-notifier.ajs-right .ajs-message.ajs-visible {
  874 + right: 290px;
  875 +}
  876 +.alertify-notifier.ajs-left {
  877 + left: 10px;
  878 +}
  879 +.alertify-notifier.ajs-left .ajs-message {
  880 + left: -300px;
  881 +}
  882 +.alertify-notifier.ajs-left .ajs-message.ajs-visible {
  883 + left: 0;
  884 +}
core/static/css/vendor/alertifyjs/alertify.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer,.alertify .ajs-modal{position:fixed;padding:0;z-index:1981;top:0;right:0;bottom:0;left:0}.alertify .ajs-dimmer{margin:0;background-color:#252525;opacity:.5}.alertify .ajs-modal{overflow-y:auto}.alertify .ajs-dialog{position:relative;margin:5% auto;min-height:110px;max-width:500px;padding:24px 24px 0;outline:0;background-color:#fff}.alertify .ajs-dialog.ajs-capture:before{content:'';position:absolute;top:0;right:0;bottom:0;left:0;display:block;z-index:1}.alertify .ajs-reset{position:absolute!important;display:inline!important;width:0!important;height:0!important;opacity:0!important}.alertify .ajs-commands{position:absolute;right:4px;margin:-14px 24px 0 0;z-index:2}.alertify .ajs-commands button{display:none;width:10px;height:10px;margin-left:10px;padding:10px;border:0;background-color:transparent;background-repeat:no-repeat;background-position:center;cursor:pointer}.alertify .ajs-commands button.ajs-close{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC)}.alertify .ajs-commands button.ajs-maximize{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC)}.alertify .ajs-header{margin:-24px -24px 0;padding:16px 24px;background-color:#fff}.alertify .ajs-body{min-height:56px}.alertify .ajs-body .ajs-content{padding:16px 24px 16px 16px}.alertify .ajs-footer{padding:4px;margin-left:-24px;margin-right:-24px;min-height:43px;background-color:#fff}.alertify.ajs-maximized .ajs-dialog,.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content,.alertify.ajs-resizable .ajs-dialog{padding:0}.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button,.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button{margin:4px}.alertify .ajs-footer .ajs-buttons.ajs-primary{text-align:right}.alertify .ajs-footer .ajs-buttons.ajs-auxiliary{float:left;clear:none;text-align:left}.alertify .ajs-footer .ajs-buttons .ajs-button{min-width:88px;min-height:35px}.alertify .ajs-handle{position:absolute;display:none;width:10px;height:10px;right:0;bottom:0;z-index:1;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);-webkit-transform:scaleX(1);transform:scaleX(1);cursor:se-resize}.alertify.ajs-no-overflow .ajs-body .ajs-content{overflow:hidden!important}.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content{left:0;right:0;padding:0}.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body{margin-left:-24px;margin-right:-24px}.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content{left:0;right:0}.alertify.ajs-closable .ajs-commands button.ajs-close,.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,.alertify.ajs-maximizable .ajs-commands button.ajs-restore{display:inline-block}.alertify.ajs-maximized .ajs-dialog{width:100%!important;height:100%!important;max-width:none!important;margin:0 auto!important;top:0!important;left:0!important}.alertify.ajs-maximized.ajs-modeless .ajs-modal{position:fixed!important;min-height:100%!important;max-height:none!important;margin:0!important}.alertify.ajs-maximized .ajs-commands button.ajs-maximize{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=)}.alertify.ajs-maximized .ajs-commands,.alertify.ajs-resizable .ajs-commands{margin:14px 24px 0 0}.alertify.ajs-maximized .ajs-header,.alertify.ajs-resizable .ajs-header{position:absolute;top:0;left:0;right:0;margin:0;padding:16px 24px}.alertify.ajs-maximized .ajs-body,.alertify.ajs-resizable .ajs-body{min-height:224px;display:inline-block}.alertify.ajs-maximized .ajs-body .ajs-content,.alertify.ajs-resizable .ajs-body .ajs-content{position:absolute;top:50px;right:24px;bottom:50px;left:24px;overflow:auto}.alertify.ajs-maximized .ajs-footer,.alertify.ajs-resizable .ajs-footer{position:absolute;left:0;right:0;bottom:0;margin:0}.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog{min-width:548px}.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle{display:block}.alertify.ajs-movable:not(.ajs-maximized) .ajs-header{cursor:move}.alertify.ajs-modeless .ajs-dimmer,.alertify.ajs-modeless .ajs-reset{display:none}.alertify.ajs-modeless .ajs-modal{overflow:visible;max-width:none;max-height:0}.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin{display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC)}.alertify.ajs-modeless.ajs-unpinned .ajs-modal{position:absolute}.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=)}.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body{max-height:500px;overflow:auto}.alertify.ajs-basic .ajs-header{opacity:0}.alertify.ajs-basic .ajs-footer{visibility:hidden}.alertify.ajs-frameless .ajs-header{position:absolute;top:0;left:0;right:0;min-height:60px;margin:0;padding:0;opacity:0;z-index:1}.alertify.ajs-frameless .ajs-footer{display:none}.alertify.ajs-frameless .ajs-body .ajs-content{position:absolute;top:0;right:0;bottom:0;left:0}.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog{padding-top:0}.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands{margin-top:0}.ajs-no-overflow{overflow:hidden!important;outline:0}.ajs-no-overflow.ajs-fixed{position:fixed;top:0;right:0;bottom:0;left:0;overflow-y:scroll!important}.ajs-no-selection,.ajs-no-selection *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-width:568px){.alertify .ajs-dialog{min-width:150px}.alertify:not(.ajs-maximized) .ajs-modal{padding:0 5%}.alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog{min-width:initial;min-width:auto}}@-moz-document url-prefix(){.alertify button:focus{outline:#3593D2 dotted 1px}}.alertify .ajs-dimmer,.alertify .ajs-modal{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);transition-property:opacity,visibility;transition-timing-function:linear;transition-duration:250ms}.alertify.ajs-hidden .ajs-dimmer,.alertify.ajs-hidden .ajs-modal{visibility:hidden;opacity:0}.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-duration:.5s;animation-duration:.5s}.alertify.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-duration:250ms;animation-duration:250ms}.alertify .ajs-dialog.ajs-shake{-webkit-animation-name:ajs-shake;animation-name:ajs-shake;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}@-webkit-keyframes ajs-shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes ajs-shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-slideIn;animation-name:ajs-slideIn;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1.275);animation-timing-function:cubic-bezier(.175,.885,.32,1.275)}.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-slideOut;animation-name:ajs-slideOut;-webkit-animation-timing-function:cubic-bezier(.6,-.28,.735,.045);animation-timing-function:cubic-bezier(.6,-.28,.735,.045)}.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-zoomIn;animation-name:ajs-zoomIn}.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-zoomOut;animation-name:ajs-zoomOut}.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-fadeIn;animation-name:ajs-fadeIn}.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-fadeOut;animation-name:ajs-fadeOut}.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-pulseIn;animation-name:ajs-pulseIn}.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-pulseOut;animation-name:ajs-pulseOut}.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-flipInX;animation-name:ajs-flipInX}.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-flipOutX;animation-name:ajs-flipOutX}.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-flipInY;animation-name:ajs-flipInY}.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-flipOutY;animation-name:ajs-flipOutY}@-webkit-keyframes ajs-pulseIn{0%,100%,20%,40%,60%,80%{transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes ajs-pulseIn{0%,100%,20%,40%,60%,80%{transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@-webkit-keyframes ajs-pulseOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes ajs-pulseOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@-webkit-keyframes ajs-zoomIn{0%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes ajs-zoomIn{0%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@-webkit-keyframes ajs-zoomOut{0%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}100%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}}@keyframes ajs-zoomOut{0%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}100%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}}@-webkit-keyframes ajs-fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes ajs-fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes ajs-fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes ajs-fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes ajs-flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes ajs-flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@-webkit-keyframes ajs-flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes ajs-flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@-webkit-keyframes ajs-flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes ajs-flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@-webkit-keyframes ajs-flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes ajs-flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@-webkit-keyframes ajs-slideIn{0%{margin-top:-100%}100%{margin-top:5%}}@keyframes ajs-slideIn{0%{margin-top:-100%}100%{margin-top:5%}}@-webkit-keyframes ajs-slideOut{0%{margin-top:5%}100%{margin-top:-100%}}@keyframes ajs-slideOut{0%{margin-top:5%}100%{margin-top:-100%}}.alertify-notifier{position:fixed;width:0;overflow:visible;z-index:1982;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.alertify-notifier .ajs-message{position:relative;width:260px;max-height:0;padding:0;opacity:0;margin:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);transition-duration:250ms;transition-timing-function:linear}.alertify-notifier .ajs-message.ajs-visible{transition-duration:.5s;transition-timing-function:cubic-bezier(.175,.885,.32,1.275);opacity:1;max-height:100%;padding:15px;margin-top:10px}.alertify-notifier .ajs-message.ajs-success{background:rgba(91,189,114,.95)}.alertify-notifier .ajs-message.ajs-error{background:rgba(217,92,92,.95)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95)}.alertify-notifier.ajs-top{top:10px}.alertify-notifier.ajs-bottom{bottom:10px}.alertify-notifier.ajs-right{right:10px}.alertify-notifier.ajs-right .ajs-message{right:-320px}.alertify-notifier.ajs-right .ajs-message.ajs-visible{right:290px}.alertify-notifier.ajs-left{left:10px}.alertify-notifier.ajs-left .ajs-message{left:-300px}.alertify-notifier.ajs-left .ajs-message.ajs-visible{left:0}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/alertify.rtl.css 0 → 100644
@@ -0,0 +1,884 @@ @@ -0,0 +1,884 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer {
  7 + position: fixed;
  8 + z-index: 1981;
  9 + top: 0;
  10 + left: 0;
  11 + bottom: 0;
  12 + right: 0;
  13 + padding: 0;
  14 + margin: 0;
  15 + background-color: #252525;
  16 + opacity: .5;
  17 +}
  18 +.alertify .ajs-modal {
  19 + position: fixed;
  20 + top: 0;
  21 + left: 0;
  22 + right: 0;
  23 + bottom: 0;
  24 + padding: 0;
  25 + overflow-y: auto;
  26 + z-index: 1981;
  27 +}
  28 +.alertify .ajs-dialog {
  29 + position: relative;
  30 + margin: 5% auto;
  31 + min-height: 110px;
  32 + max-width: 500px;
  33 + padding: 24px 24px 0 24px;
  34 + outline: 0;
  35 + background-color: #fff;
  36 +}
  37 +.alertify .ajs-dialog.ajs-capture:before {
  38 + content: '';
  39 + position: absolute;
  40 + top: 0;
  41 + left: 0;
  42 + bottom: 0;
  43 + right: 0;
  44 + display: block;
  45 + z-index: 1;
  46 +}
  47 +.alertify .ajs-reset {
  48 + position: absolute !important;
  49 + display: inline !important;
  50 + width: 0 !important;
  51 + height: 0 !important;
  52 + opacity: 0 !important;
  53 +}
  54 +.alertify .ajs-commands {
  55 + position: absolute;
  56 + left: 4px;
  57 + margin: -14px 0 0 24px;
  58 + z-index: 2;
  59 +}
  60 +.alertify .ajs-commands button {
  61 + display: none;
  62 + width: 10px;
  63 + height: 10px;
  64 + margin-right: 10px;
  65 + padding: 10px;
  66 + border: 0;
  67 + background-color: transparent;
  68 + background-repeat: no-repeat;
  69 + background-position: center;
  70 + cursor: pointer;
  71 +}
  72 +.alertify .ajs-commands button.ajs-close {
  73 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC);
  74 +}
  75 +.alertify .ajs-commands button.ajs-maximize {
  76 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC);
  77 +}
  78 +.alertify .ajs-header {
  79 + margin: -24px;
  80 + margin-bottom: 0;
  81 + padding: 16px 24px;
  82 + background-color: #fff;
  83 +}
  84 +.alertify .ajs-body {
  85 + min-height: 56px;
  86 +}
  87 +.alertify .ajs-body .ajs-content {
  88 + padding: 16px 16px 16px 24px;
  89 +}
  90 +.alertify .ajs-footer {
  91 + padding: 4px;
  92 + margin-right: -24px;
  93 + margin-left: -24px;
  94 + min-height: 43px;
  95 + background-color: #fff;
  96 +}
  97 +.alertify .ajs-footer .ajs-buttons.ajs-primary {
  98 + text-align: left;
  99 +}
  100 +.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button {
  101 + margin: 4px;
  102 +}
  103 +.alertify .ajs-footer .ajs-buttons.ajs-auxiliary {
  104 + float: right;
  105 + clear: none;
  106 + text-align: right;
  107 +}
  108 +.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button {
  109 + margin: 4px;
  110 +}
  111 +.alertify .ajs-footer .ajs-buttons .ajs-button {
  112 + min-width: 88px;
  113 + min-height: 35px;
  114 +}
  115 +.alertify .ajs-handle {
  116 + position: absolute;
  117 + display: none;
  118 + width: 10px;
  119 + height: 10px;
  120 + left: 0;
  121 + bottom: 0;
  122 + z-index: 1;
  123 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);
  124 + -webkit-transform: scaleX(-1);
  125 + transform: scaleX(-1);
  126 + cursor: sw-resize;
  127 +}
  128 +.alertify.ajs-no-overflow .ajs-body .ajs-content {
  129 + overflow: hidden !important;
  130 +}
  131 +.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content {
  132 + right: 0;
  133 + left: 0;
  134 + padding: 0;
  135 +}
  136 +.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body {
  137 + margin-right: -24px;
  138 + margin-left: -24px;
  139 +}
  140 +.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content {
  141 + padding: 0;
  142 +}
  143 +.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content {
  144 + right: 0;
  145 + left: 0;
  146 +}
  147 +.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,
  148 +.alertify.ajs-maximizable .ajs-commands button.ajs-restore {
  149 + display: inline-block;
  150 +}
  151 +.alertify.ajs-closable .ajs-commands button.ajs-close {
  152 + display: inline-block;
  153 +}
  154 +.alertify.ajs-maximized .ajs-dialog {
  155 + width: 100% !important;
  156 + height: 100% !important;
  157 + max-width: none !important;
  158 + margin: 0 auto !important;
  159 + top: 0 !important;
  160 + right: 0 !important;
  161 +}
  162 +.alertify.ajs-maximized.ajs-modeless .ajs-modal {
  163 + position: fixed !important;
  164 + min-height: 100% !important;
  165 + max-height: none !important;
  166 + margin: 0 !important;
  167 +}
  168 +.alertify.ajs-maximized .ajs-commands button.ajs-maximize {
  169 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=);
  170 +}
  171 +.alertify.ajs-resizable .ajs-dialog,
  172 +.alertify.ajs-maximized .ajs-dialog {
  173 + padding: 0;
  174 +}
  175 +.alertify.ajs-resizable .ajs-commands,
  176 +.alertify.ajs-maximized .ajs-commands {
  177 + margin: 14px 0 0 24px;
  178 +}
  179 +.alertify.ajs-resizable .ajs-header,
  180 +.alertify.ajs-maximized .ajs-header {
  181 + position: absolute;
  182 + top: 0;
  183 + right: 0;
  184 + left: 0;
  185 + margin: 0;
  186 + padding: 16px 24px;
  187 +}
  188 +.alertify.ajs-resizable .ajs-body,
  189 +.alertify.ajs-maximized .ajs-body {
  190 + min-height: 224px;
  191 + display: inline-block;
  192 +}
  193 +.alertify.ajs-resizable .ajs-body .ajs-content,
  194 +.alertify.ajs-maximized .ajs-body .ajs-content {
  195 + position: absolute;
  196 + top: 50px;
  197 + left: 24px;
  198 + bottom: 50px;
  199 + right: 24px;
  200 + overflow: auto;
  201 +}
  202 +.alertify.ajs-resizable .ajs-footer,
  203 +.alertify.ajs-maximized .ajs-footer {
  204 + position: absolute;
  205 + right: 0;
  206 + left: 0;
  207 + bottom: 0;
  208 + margin: 0;
  209 +}
  210 +.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog {
  211 + min-width: 548px;
  212 +}
  213 +.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle {
  214 + display: block;
  215 +}
  216 +.alertify.ajs-movable:not(.ajs-maximized) .ajs-header {
  217 + cursor: move;
  218 +}
  219 +.alertify.ajs-modeless .ajs-dimmer,
  220 +.alertify.ajs-modeless .ajs-reset {
  221 + display: none;
  222 +}
  223 +.alertify.ajs-modeless .ajs-modal {
  224 + overflow: visible;
  225 + max-width: none;
  226 + max-height: 0;
  227 +}
  228 +.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin {
  229 + display: inline-block;
  230 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC);
  231 +}
  232 +.alertify.ajs-modeless.ajs-unpinned .ajs-modal {
  233 + position: absolute;
  234 +}
  235 +.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin {
  236 + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=);
  237 +}
  238 +.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body {
  239 + max-height: 500px;
  240 + overflow: auto;
  241 +}
  242 +.alertify.ajs-basic .ajs-header {
  243 + opacity: 0;
  244 +}
  245 +.alertify.ajs-basic .ajs-footer {
  246 + visibility: hidden;
  247 +}
  248 +.alertify.ajs-frameless .ajs-header {
  249 + position: absolute;
  250 + top: 0;
  251 + right: 0;
  252 + left: 0;
  253 + min-height: 60px;
  254 + margin: 0;
  255 + padding: 0;
  256 + opacity: 0;
  257 + z-index: 1;
  258 +}
  259 +.alertify.ajs-frameless .ajs-footer {
  260 + display: none;
  261 +}
  262 +.alertify.ajs-frameless .ajs-body .ajs-content {
  263 + position: absolute;
  264 + top: 0;
  265 + left: 0;
  266 + bottom: 0;
  267 + right: 0;
  268 +}
  269 +.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog {
  270 + padding-top: 0;
  271 +}
  272 +.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands {
  273 + margin-top: 0;
  274 +}
  275 +.ajs-no-overflow {
  276 + overflow: hidden !important;
  277 + outline: none;
  278 +}
  279 +.ajs-no-overflow.ajs-fixed {
  280 + position: fixed;
  281 + top: 0;
  282 + left: 0;
  283 + bottom: 0;
  284 + right: 0;
  285 + overflow-y: scroll!important;
  286 +}
  287 +.ajs-no-selection,
  288 +.ajs-no-selection * {
  289 + -webkit-user-select: none;
  290 + -moz-user-select: none;
  291 + -ms-user-select: none;
  292 + user-select: none;
  293 +}
  294 +@media screen and (max-width: 568px) {
  295 + .alertify .ajs-dialog {
  296 + min-width: 150px;
  297 + }
  298 + .alertify:not(.ajs-maximized) .ajs-modal {
  299 + padding: 0 5%;
  300 + }
  301 + .alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog {
  302 + min-width: initial;
  303 + min-width: auto /*IE fallback*/;
  304 + }
  305 +}
  306 +@-moz-document url-prefix() {
  307 + .alertify button:focus {
  308 + outline: 1px dotted #3593D2;
  309 + }
  310 +}
  311 +.alertify .ajs-dimmer,
  312 +.alertify .ajs-modal {
  313 + -webkit-transform: translate3d(0, 0, 0);
  314 + transform: translate3d(0, 0, 0);
  315 + transition-property: opacity, visibility;
  316 + transition-timing-function: linear;
  317 + transition-duration: 250ms;
  318 +}
  319 +.alertify.ajs-hidden .ajs-dimmer,
  320 +.alertify.ajs-hidden .ajs-modal {
  321 + visibility: hidden;
  322 + opacity: 0;
  323 +}
  324 +.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog {
  325 + -webkit-animation-duration: 500ms;
  326 + animation-duration: 500ms;
  327 +}
  328 +.alertify.ajs-out.ajs-hidden .ajs-dialog {
  329 + -webkit-animation-duration: 250ms;
  330 + animation-duration: 250ms;
  331 +}
  332 +.alertify .ajs-dialog.ajs-shake {
  333 + -webkit-animation-name: ajs-shake;
  334 + animation-name: ajs-shake;
  335 + -webkit-animation-duration: .1s;
  336 + animation-duration: .1s;
  337 + -webkit-animation-fill-mode: both;
  338 + animation-fill-mode: both;
  339 +}
  340 +@-webkit-keyframes ajs-shake {
  341 + 0%,
  342 + 100% {
  343 + -webkit-transform: translate3d(0, 0, 0);
  344 + transform: translate3d(0, 0, 0);
  345 + }
  346 + 10%,
  347 + 30%,
  348 + 50%,
  349 + 70%,
  350 + 90% {
  351 + -webkit-transform: translate3d(10px, 0, 0);
  352 + transform: translate3d(10px, 0, 0);
  353 + }
  354 + 20%,
  355 + 40%,
  356 + 60%,
  357 + 80% {
  358 + -webkit-transform: translate3d(-10px, 0, 0);
  359 + transform: translate3d(-10px, 0, 0);
  360 + }
  361 +}
  362 +@keyframes ajs-shake {
  363 + 0%,
  364 + 100% {
  365 + -webkit-transform: translate3d(0, 0, 0);
  366 + transform: translate3d(0, 0, 0);
  367 + }
  368 + 10%,
  369 + 30%,
  370 + 50%,
  371 + 70%,
  372 + 90% {
  373 + -webkit-transform: translate3d(10px, 0, 0);
  374 + transform: translate3d(10px, 0, 0);
  375 + }
  376 + 20%,
  377 + 40%,
  378 + 60%,
  379 + 80% {
  380 + -webkit-transform: translate3d(-10px, 0, 0);
  381 + transform: translate3d(-10px, 0, 0);
  382 + }
  383 +}
  384 +.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog {
  385 + -webkit-animation-name: ajs-slideIn;
  386 + animation-name: ajs-slideIn;
  387 + -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  388 + animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  389 +}
  390 +.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog {
  391 + -webkit-animation-name: ajs-slideOut;
  392 + animation-name: ajs-slideOut;
  393 + -webkit-animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
  394 + animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
  395 +}
  396 +.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog {
  397 + -webkit-animation-name: ajs-zoomIn;
  398 + animation-name: ajs-zoomIn;
  399 +}
  400 +.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog {
  401 + -webkit-animation-name: ajs-zoomOut;
  402 + animation-name: ajs-zoomOut;
  403 +}
  404 +.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog {
  405 + -webkit-animation-name: ajs-fadeIn;
  406 + animation-name: ajs-fadeIn;
  407 +}
  408 +.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog {
  409 + -webkit-animation-name: ajs-fadeOut;
  410 + animation-name: ajs-fadeOut;
  411 +}
  412 +.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog {
  413 + -webkit-animation-name: ajs-pulseIn;
  414 + animation-name: ajs-pulseIn;
  415 +}
  416 +.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog {
  417 + -webkit-animation-name: ajs-pulseOut;
  418 + animation-name: ajs-pulseOut;
  419 +}
  420 +.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog {
  421 + -webkit-animation-name: ajs-flipInX;
  422 + animation-name: ajs-flipInX;
  423 +}
  424 +.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog {
  425 + -webkit-animation-name: ajs-flipOutX;
  426 + animation-name: ajs-flipOutX;
  427 +}
  428 +.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog {
  429 + -webkit-animation-name: ajs-flipInY;
  430 + animation-name: ajs-flipInY;
  431 +}
  432 +.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog {
  433 + -webkit-animation-name: ajs-flipOutY;
  434 + animation-name: ajs-flipOutY;
  435 +}
  436 +@-webkit-keyframes ajs-pulseIn {
  437 + 0%,
  438 + 20%,
  439 + 40%,
  440 + 60%,
  441 + 80%,
  442 + 100% {
  443 + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  444 + }
  445 + 0% {
  446 + opacity: 0;
  447 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  448 + transform: scale3d(0.3, 0.3, 0.3);
  449 + }
  450 + 20% {
  451 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  452 + transform: scale3d(1.1, 1.1, 1.1);
  453 + }
  454 + 40% {
  455 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  456 + transform: scale3d(0.9, 0.9, 0.9);
  457 + }
  458 + 60% {
  459 + opacity: 1;
  460 + -webkit-transform: scale3d(1.03, 1.03, 1.03);
  461 + transform: scale3d(1.03, 1.03, 1.03);
  462 + }
  463 + 80% {
  464 + -webkit-transform: scale3d(0.97, 0.97, 0.97);
  465 + transform: scale3d(0.97, 0.97, 0.97);
  466 + }
  467 + 100% {
  468 + opacity: 1;
  469 + -webkit-transform: scale3d(1, 1, 1);
  470 + transform: scale3d(1, 1, 1);
  471 + }
  472 +}
  473 +@keyframes ajs-pulseIn {
  474 + 0%,
  475 + 20%,
  476 + 40%,
  477 + 60%,
  478 + 80%,
  479 + 100% {
  480 + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  481 + }
  482 + 0% {
  483 + opacity: 0;
  484 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  485 + transform: scale3d(0.3, 0.3, 0.3);
  486 + }
  487 + 20% {
  488 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  489 + transform: scale3d(1.1, 1.1, 1.1);
  490 + }
  491 + 40% {
  492 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  493 + transform: scale3d(0.9, 0.9, 0.9);
  494 + }
  495 + 60% {
  496 + opacity: 1;
  497 + -webkit-transform: scale3d(1.03, 1.03, 1.03);
  498 + transform: scale3d(1.03, 1.03, 1.03);
  499 + }
  500 + 80% {
  501 + -webkit-transform: scale3d(0.97, 0.97, 0.97);
  502 + transform: scale3d(0.97, 0.97, 0.97);
  503 + }
  504 + 100% {
  505 + opacity: 1;
  506 + -webkit-transform: scale3d(1, 1, 1);
  507 + transform: scale3d(1, 1, 1);
  508 + }
  509 +}
  510 +@-webkit-keyframes ajs-pulseOut {
  511 + 20% {
  512 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  513 + transform: scale3d(0.9, 0.9, 0.9);
  514 + }
  515 + 50%,
  516 + 55% {
  517 + opacity: 1;
  518 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  519 + transform: scale3d(1.1, 1.1, 1.1);
  520 + }
  521 + 100% {
  522 + opacity: 0;
  523 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  524 + transform: scale3d(0.3, 0.3, 0.3);
  525 + }
  526 +}
  527 +@keyframes ajs-pulseOut {
  528 + 20% {
  529 + -webkit-transform: scale3d(0.9, 0.9, 0.9);
  530 + transform: scale3d(0.9, 0.9, 0.9);
  531 + }
  532 + 50%,
  533 + 55% {
  534 + opacity: 1;
  535 + -webkit-transform: scale3d(1.1, 1.1, 1.1);
  536 + transform: scale3d(1.1, 1.1, 1.1);
  537 + }
  538 + 100% {
  539 + opacity: 0;
  540 + -webkit-transform: scale3d(0.3, 0.3, 0.3);
  541 + transform: scale3d(0.3, 0.3, 0.3);
  542 + }
  543 +}
  544 +@-webkit-keyframes ajs-zoomIn {
  545 + 0% {
  546 + opacity: 0;
  547 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  548 + transform: scale3d(0.25, 0.25, 0.25);
  549 + }
  550 + 100% {
  551 + opacity: 1;
  552 + -webkit-transform: scale3d(1, 1, 1);
  553 + transform: scale3d(1, 1, 1);
  554 + }
  555 +}
  556 +@keyframes ajs-zoomIn {
  557 + 0% {
  558 + opacity: 0;
  559 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  560 + transform: scale3d(0.25, 0.25, 0.25);
  561 + }
  562 + 100% {
  563 + opacity: 1;
  564 + -webkit-transform: scale3d(1, 1, 1);
  565 + transform: scale3d(1, 1, 1);
  566 + }
  567 +}
  568 +@-webkit-keyframes ajs-zoomOut {
  569 + 0% {
  570 + opacity: 1;
  571 + -webkit-transform: scale3d(1, 1, 1);
  572 + transform: scale3d(1, 1, 1);
  573 + }
  574 + 100% {
  575 + opacity: 0;
  576 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  577 + transform: scale3d(0.25, 0.25, 0.25);
  578 + }
  579 +}
  580 +@keyframes ajs-zoomOut {
  581 + 0% {
  582 + opacity: 1;
  583 + -webkit-transform: scale3d(1, 1, 1);
  584 + transform: scale3d(1, 1, 1);
  585 + }
  586 + 100% {
  587 + opacity: 0;
  588 + -webkit-transform: scale3d(0.25, 0.25, 0.25);
  589 + transform: scale3d(0.25, 0.25, 0.25);
  590 + }
  591 +}
  592 +@-webkit-keyframes ajs-fadeIn {
  593 + 0% {
  594 + opacity: 0;
  595 + }
  596 + 100% {
  597 + opacity: 1;
  598 + }
  599 +}
  600 +@keyframes ajs-fadeIn {
  601 + 0% {
  602 + opacity: 0;
  603 + }
  604 + 100% {
  605 + opacity: 1;
  606 + }
  607 +}
  608 +@-webkit-keyframes ajs-fadeOut {
  609 + 0% {
  610 + opacity: 1;
  611 + }
  612 + 100% {
  613 + opacity: 0;
  614 + }
  615 +}
  616 +@keyframes ajs-fadeOut {
  617 + 0% {
  618 + opacity: 1;
  619 + }
  620 + 100% {
  621 + opacity: 0;
  622 + }
  623 +}
  624 +@-webkit-keyframes ajs-flipInX {
  625 + 0% {
  626 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  627 + transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  628 + transition-timing-function: ease-in;
  629 + opacity: 0;
  630 + }
  631 + 40% {
  632 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  633 + transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  634 + transition-timing-function: ease-in;
  635 + }
  636 + 60% {
  637 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
  638 + transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
  639 + opacity: 1;
  640 + }
  641 + 80% {
  642 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
  643 + transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
  644 + }
  645 + 100% {
  646 + -webkit-transform: perspective(400px);
  647 + transform: perspective(400px);
  648 + }
  649 +}
  650 +@keyframes ajs-flipInX {
  651 + 0% {
  652 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  653 + transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  654 + transition-timing-function: ease-in;
  655 + opacity: 0;
  656 + }
  657 + 40% {
  658 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  659 + transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  660 + transition-timing-function: ease-in;
  661 + }
  662 + 60% {
  663 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
  664 + transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
  665 + opacity: 1;
  666 + }
  667 + 80% {
  668 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
  669 + transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
  670 + }
  671 + 100% {
  672 + -webkit-transform: perspective(400px);
  673 + transform: perspective(400px);
  674 + }
  675 +}
  676 +@-webkit-keyframes ajs-flipOutX {
  677 + 0% {
  678 + -webkit-transform: perspective(400px);
  679 + transform: perspective(400px);
  680 + }
  681 + 30% {
  682 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  683 + transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  684 + opacity: 1;
  685 + }
  686 + 100% {
  687 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  688 + transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  689 + opacity: 0;
  690 + }
  691 +}
  692 +@keyframes ajs-flipOutX {
  693 + 0% {
  694 + -webkit-transform: perspective(400px);
  695 + transform: perspective(400px);
  696 + }
  697 + 30% {
  698 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  699 + transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
  700 + opacity: 1;
  701 + }
  702 + 100% {
  703 + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  704 + transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
  705 + opacity: 0;
  706 + }
  707 +}
  708 +@-webkit-keyframes ajs-flipInY {
  709 + 0% {
  710 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  711 + transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  712 + transition-timing-function: ease-in;
  713 + opacity: 0;
  714 + }
  715 + 40% {
  716 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
  717 + transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
  718 + transition-timing-function: ease-in;
  719 + }
  720 + 60% {
  721 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
  722 + transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
  723 + opacity: 1;
  724 + }
  725 + 80% {
  726 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
  727 + transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
  728 + }
  729 + 100% {
  730 + -webkit-transform: perspective(400px);
  731 + transform: perspective(400px);
  732 + }
  733 +}
  734 +@keyframes ajs-flipInY {
  735 + 0% {
  736 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  737 + transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  738 + transition-timing-function: ease-in;
  739 + opacity: 0;
  740 + }
  741 + 40% {
  742 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
  743 + transform: perspective(400px) rotate3d(0, -1, 0, 20deg);
  744 + transition-timing-function: ease-in;
  745 + }
  746 + 60% {
  747 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
  748 + transform: perspective(400px) rotate3d(0, -1, 0, -10deg);
  749 + opacity: 1;
  750 + }
  751 + 80% {
  752 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
  753 + transform: perspective(400px) rotate3d(0, -1, 0, 5deg);
  754 + }
  755 + 100% {
  756 + -webkit-transform: perspective(400px);
  757 + transform: perspective(400px);
  758 + }
  759 +}
  760 +@-webkit-keyframes ajs-flipOutY {
  761 + 0% {
  762 + -webkit-transform: perspective(400px);
  763 + transform: perspective(400px);
  764 + }
  765 + 30% {
  766 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
  767 + transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
  768 + opacity: 1;
  769 + }
  770 + 100% {
  771 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  772 + transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  773 + opacity: 0;
  774 + }
  775 +}
  776 +@keyframes ajs-flipOutY {
  777 + 0% {
  778 + -webkit-transform: perspective(400px);
  779 + transform: perspective(400px);
  780 + }
  781 + 30% {
  782 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
  783 + transform: perspective(400px) rotate3d(0, -1, 0, 15deg);
  784 + opacity: 1;
  785 + }
  786 + 100% {
  787 + -webkit-transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  788 + transform: perspective(400px) rotate3d(0, -1, 0, -90deg);
  789 + opacity: 0;
  790 + }
  791 +}
  792 +@-webkit-keyframes ajs-slideIn {
  793 + 0% {
  794 + margin-top: -100%;
  795 + }
  796 + 100% {
  797 + margin-top: 5%;
  798 + }
  799 +}
  800 +@keyframes ajs-slideIn {
  801 + 0% {
  802 + margin-top: -100%;
  803 + }
  804 + 100% {
  805 + margin-top: 5%;
  806 + }
  807 +}
  808 +@-webkit-keyframes ajs-slideOut {
  809 + 0% {
  810 + margin-top: 5%;
  811 + }
  812 + 100% {
  813 + margin-top: -100%;
  814 + }
  815 +}
  816 +@keyframes ajs-slideOut {
  817 + 0% {
  818 + margin-top: 5%;
  819 + }
  820 + 100% {
  821 + margin-top: -100%;
  822 + }
  823 +}
  824 +.alertify-notifier {
  825 + position: fixed;
  826 + width: 0;
  827 + overflow: visible;
  828 + z-index: 1982;
  829 + -webkit-transform: translate3d(0, 0, 0);
  830 + transform: translate3d(0, 0, 0);
  831 +}
  832 +.alertify-notifier .ajs-message {
  833 + position: relative;
  834 + width: 260px;
  835 + max-height: 0;
  836 + padding: 0;
  837 + opacity: 0;
  838 + margin: 0;
  839 + -webkit-transform: translate3d(0, 0, 0);
  840 + transform: translate3d(0, 0, 0);
  841 + transition-duration: 250ms;
  842 + transition-timing-function: linear;
  843 +}
  844 +.alertify-notifier .ajs-message.ajs-visible {
  845 + transition-duration: 500ms;
  846 + transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  847 + opacity: 1;
  848 + max-height: 100%;
  849 + padding: 15px;
  850 + margin-top: 10px;
  851 +}
  852 +.alertify-notifier .ajs-message.ajs-success {
  853 + background: rgba(91, 189, 114, 0.95);
  854 +}
  855 +.alertify-notifier .ajs-message.ajs-error {
  856 + background: rgba(217, 92, 92, 0.95);
  857 +}
  858 +.alertify-notifier .ajs-message.ajs-warning {
  859 + background: rgba(252, 248, 215, 0.95);
  860 +}
  861 +.alertify-notifier.ajs-top {
  862 + top: 10px;
  863 +}
  864 +.alertify-notifier.ajs-bottom {
  865 + bottom: 10px;
  866 +}
  867 +.alertify-notifier.ajs-right {
  868 + left: 10px;
  869 +}
  870 +.alertify-notifier.ajs-right .ajs-message {
  871 + left: -320px;
  872 +}
  873 +.alertify-notifier.ajs-right .ajs-message.ajs-visible {
  874 + left: 290px;
  875 +}
  876 +.alertify-notifier.ajs-left {
  877 + right: 10px;
  878 +}
  879 +.alertify-notifier.ajs-left .ajs-message {
  880 + right: -300px;
  881 +}
  882 +.alertify-notifier.ajs-left .ajs-message.ajs-visible {
  883 + right: 0;
  884 +}
core/static/css/vendor/alertifyjs/alertify.rtl.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer,.alertify .ajs-modal{position:fixed;padding:0;z-index:1981;top:0;left:0;bottom:0;right:0}.alertify .ajs-dimmer{margin:0;background-color:#252525;opacity:.5}.alertify .ajs-modal{overflow-y:auto}.alertify .ajs-dialog{position:relative;margin:5% auto;min-height:110px;max-width:500px;padding:24px 24px 0;outline:0;background-color:#fff}.alertify .ajs-dialog.ajs-capture:before{content:'';position:absolute;top:0;left:0;bottom:0;right:0;display:block;z-index:1}.alertify .ajs-reset{position:absolute!important;display:inline!important;width:0!important;height:0!important;opacity:0!important}.alertify .ajs-commands{position:absolute;left:4px;margin:-14px 0 0 24px;z-index:2}.alertify .ajs-commands button{display:none;width:10px;height:10px;margin-right:10px;padding:10px;border:0;background-color:transparent;background-repeat:no-repeat;background-position:center;cursor:pointer}.alertify .ajs-commands button.ajs-close{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC)}.alertify .ajs-commands button.ajs-maximize{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC)}.alertify .ajs-header{margin:-24px -24px 0;padding:16px 24px;background-color:#fff}.alertify .ajs-body{min-height:56px}.alertify .ajs-body .ajs-content{padding:16px 16px 16px 24px}.alertify .ajs-footer{padding:4px;margin-right:-24px;margin-left:-24px;min-height:43px;background-color:#fff}.alertify.ajs-maximized .ajs-dialog,.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content,.alertify.ajs-resizable .ajs-dialog{padding:0}.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button,.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button{margin:4px}.alertify .ajs-footer .ajs-buttons.ajs-primary{text-align:left}.alertify .ajs-footer .ajs-buttons.ajs-auxiliary{float:right;clear:none;text-align:right}.alertify .ajs-footer .ajs-buttons .ajs-button{min-width:88px;min-height:35px}.alertify .ajs-handle{position:absolute;display:none;width:10px;height:10px;left:0;bottom:0;z-index:1;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);-webkit-transform:scaleX(-1);transform:scaleX(-1);cursor:sw-resize}.alertify.ajs-no-overflow .ajs-body .ajs-content{overflow:hidden!important}.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content{right:0;left:0;padding:0}.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body{margin-right:-24px;margin-left:-24px}.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content{right:0;left:0}.alertify.ajs-closable .ajs-commands button.ajs-close,.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,.alertify.ajs-maximizable .ajs-commands button.ajs-restore{display:inline-block}.alertify.ajs-maximized .ajs-dialog{width:100%!important;height:100%!important;max-width:none!important;margin:0 auto!important;top:0!important;right:0!important}.alertify.ajs-maximized.ajs-modeless .ajs-modal{position:fixed!important;min-height:100%!important;max-height:none!important;margin:0!important}.alertify.ajs-maximized .ajs-commands button.ajs-maximize{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=)}.alertify.ajs-maximized .ajs-commands,.alertify.ajs-resizable .ajs-commands{margin:14px 0 0 24px}.alertify.ajs-maximized .ajs-header,.alertify.ajs-resizable .ajs-header{position:absolute;top:0;right:0;left:0;margin:0;padding:16px 24px}.alertify.ajs-maximized .ajs-body,.alertify.ajs-resizable .ajs-body{min-height:224px;display:inline-block}.alertify.ajs-maximized .ajs-body .ajs-content,.alertify.ajs-resizable .ajs-body .ajs-content{position:absolute;top:50px;left:24px;bottom:50px;right:24px;overflow:auto}.alertify.ajs-maximized .ajs-footer,.alertify.ajs-resizable .ajs-footer{position:absolute;right:0;left:0;bottom:0;margin:0}.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog{min-width:548px}.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle{display:block}.alertify.ajs-movable:not(.ajs-maximized) .ajs-header{cursor:move}.alertify.ajs-modeless .ajs-dimmer,.alertify.ajs-modeless .ajs-reset{display:none}.alertify.ajs-modeless .ajs-modal{overflow:visible;max-width:none;max-height:0}.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin{display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC)}.alertify.ajs-modeless.ajs-unpinned .ajs-modal{position:absolute}.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=)}.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body{max-height:500px;overflow:auto}.alertify.ajs-basic .ajs-header{opacity:0}.alertify.ajs-basic .ajs-footer{visibility:hidden}.alertify.ajs-frameless .ajs-header{position:absolute;top:0;right:0;left:0;min-height:60px;margin:0;padding:0;opacity:0;z-index:1}.alertify.ajs-frameless .ajs-footer{display:none}.alertify.ajs-frameless .ajs-body .ajs-content{position:absolute;top:0;left:0;bottom:0;right:0}.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog{padding-top:0}.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands{margin-top:0}.ajs-no-overflow{overflow:hidden!important;outline:0}.ajs-no-overflow.ajs-fixed{position:fixed;top:0;left:0;bottom:0;right:0;overflow-y:scroll!important}.ajs-no-selection,.ajs-no-selection *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-width:568px){.alertify .ajs-dialog{min-width:150px}.alertify:not(.ajs-maximized) .ajs-modal{padding:0 5%}.alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog{min-width:initial;min-width:auto}}@-moz-document url-prefix(){.alertify button:focus{outline:#3593D2 dotted 1px}}.alertify .ajs-dimmer,.alertify .ajs-modal{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);transition-property:opacity,visibility;transition-timing-function:linear;transition-duration:250ms}.alertify.ajs-hidden .ajs-dimmer,.alertify.ajs-hidden .ajs-modal{visibility:hidden;opacity:0}.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-duration:.5s;animation-duration:.5s}.alertify.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-duration:250ms;animation-duration:250ms}.alertify .ajs-dialog.ajs-shake{-webkit-animation-name:ajs-shake;animation-name:ajs-shake;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}@-webkit-keyframes ajs-shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}}@keyframes ajs-shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}}.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-slideIn;animation-name:ajs-slideIn;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1.275);animation-timing-function:cubic-bezier(.175,.885,.32,1.275)}.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-slideOut;animation-name:ajs-slideOut;-webkit-animation-timing-function:cubic-bezier(.6,-.28,.735,.045);animation-timing-function:cubic-bezier(.6,-.28,.735,.045)}.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-zoomIn;animation-name:ajs-zoomIn}.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-zoomOut;animation-name:ajs-zoomOut}.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-fadeIn;animation-name:ajs-fadeIn}.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-fadeOut;animation-name:ajs-fadeOut}.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-pulseIn;animation-name:ajs-pulseIn}.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-pulseOut;animation-name:ajs-pulseOut}.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-flipInX;animation-name:ajs-flipInX}.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-flipOutX;animation-name:ajs-flipOutX}.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog{-webkit-animation-name:ajs-flipInY;animation-name:ajs-flipInY}.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog{-webkit-animation-name:ajs-flipOutY;animation-name:ajs-flipOutY}@-webkit-keyframes ajs-pulseIn{0%,100%,20%,40%,60%,80%{transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes ajs-pulseIn{0%,100%,20%,40%,60%,80%{transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@-webkit-keyframes ajs-pulseOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes ajs-pulseOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@-webkit-keyframes ajs-zoomIn{0%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes ajs-zoomIn{0%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@-webkit-keyframes ajs-zoomOut{0%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}100%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}}@keyframes ajs-zoomOut{0%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}100%{opacity:0;-webkit-transform:scale3d(.25,.25,.25);transform:scale3d(.25,.25,.25)}}@-webkit-keyframes ajs-fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes ajs-fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes ajs-fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes ajs-fadeOut{0%{opacity:1}100%{opacity:0}}@-webkit-keyframes ajs-flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-90deg);transform:perspective(400px) rotate3d(1,0,0,-90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,20deg);transform:perspective(400px) rotate3d(1,0,0,20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-10deg);transform:perspective(400px) rotate3d(1,0,0,-10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,5deg);transform:perspective(400px) rotate3d(1,0,0,5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes ajs-flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-90deg);transform:perspective(400px) rotate3d(1,0,0,-90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,20deg);transform:perspective(400px) rotate3d(1,0,0,20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-10deg);transform:perspective(400px) rotate3d(1,0,0,-10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,5deg);transform:perspective(400px) rotate3d(1,0,0,5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@-webkit-keyframes ajs-flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,20deg);transform:perspective(400px) rotate3d(1,0,0,20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-90deg);transform:perspective(400px) rotate3d(1,0,0,-90deg);opacity:0}}@keyframes ajs-flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,20deg);transform:perspective(400px) rotate3d(1,0,0,20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-90deg);transform:perspective(400px) rotate3d(1,0,0,-90deg);opacity:0}}@-webkit-keyframes ajs-flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,-90deg);transform:perspective(400px) rotate3d(0,-1,0,-90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,20deg);transform:perspective(400px) rotate3d(0,-1,0,20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,-10deg);transform:perspective(400px) rotate3d(0,-1,0,-10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,5deg);transform:perspective(400px) rotate3d(0,-1,0,5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes ajs-flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,-90deg);transform:perspective(400px) rotate3d(0,-1,0,-90deg);transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,20deg);transform:perspective(400px) rotate3d(0,-1,0,20deg);transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,-10deg);transform:perspective(400px) rotate3d(0,-1,0,-10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,5deg);transform:perspective(400px) rotate3d(0,-1,0,5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@-webkit-keyframes ajs-flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,15deg);transform:perspective(400px) rotate3d(0,-1,0,15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,-90deg);transform:perspective(400px) rotate3d(0,-1,0,-90deg);opacity:0}}@keyframes ajs-flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,15deg);transform:perspective(400px) rotate3d(0,-1,0,15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,-1,0,-90deg);transform:perspective(400px) rotate3d(0,-1,0,-90deg);opacity:0}}@-webkit-keyframes ajs-slideIn{0%{margin-top:-100%}100%{margin-top:5%}}@keyframes ajs-slideIn{0%{margin-top:-100%}100%{margin-top:5%}}@-webkit-keyframes ajs-slideOut{0%{margin-top:5%}100%{margin-top:-100%}}@keyframes ajs-slideOut{0%{margin-top:5%}100%{margin-top:-100%}}.alertify-notifier{position:fixed;width:0;overflow:visible;z-index:1982;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.alertify-notifier .ajs-message{position:relative;width:260px;max-height:0;padding:0;opacity:0;margin:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);transition-duration:250ms;transition-timing-function:linear}.alertify-notifier .ajs-message.ajs-visible{transition-duration:.5s;transition-timing-function:cubic-bezier(.175,.885,.32,1.275);opacity:1;max-height:100%;padding:15px;margin-top:10px}.alertify-notifier .ajs-message.ajs-success{background:rgba(91,189,114,.95)}.alertify-notifier .ajs-message.ajs-error{background:rgba(217,92,92,.95)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95)}.alertify-notifier.ajs-top{top:10px}.alertify-notifier.ajs-bottom{bottom:10px}.alertify-notifier.ajs-right{left:10px}.alertify-notifier.ajs-right .ajs-message{left:-320px}.alertify-notifier.ajs-right .ajs-message.ajs-visible{left:290px}.alertify-notifier.ajs-left{right:10px}.alertify-notifier.ajs-left .ajs-message{right:-300px}.alertify-notifier.ajs-left .ajs-message.ajs-visible{right:0}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/themes/bootstrap.css 0 → 100644
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer {
  7 + background-color: #000;
  8 + opacity: .5;
  9 +}
  10 +.alertify .ajs-dialog {
  11 + max-width: 600px;
  12 + min-height: 122px;
  13 + background-color: #fff;
  14 + border: 1px solid rgba(0, 0, 0, 0.2);
  15 + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
  16 + border-radius: 6px;
  17 +}
  18 +.alertify .ajs-header {
  19 + color: #333;
  20 + border-bottom: 1px solid #e5e5e5;
  21 + border-radius: 6px 6px 0 0;
  22 + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  23 + font-size: 18px;
  24 +}
  25 +.alertify .ajs-body {
  26 + font-family: 'Roboto', sans-serif;
  27 + color: black;
  28 +}
  29 +.alertify.ajs-resizable .ajs-content,
  30 +.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
  31 + top: 58px;
  32 + bottom: 68px;
  33 +}
  34 +.alertify .ajs-footer {
  35 + background-color: #fff;
  36 + padding: 15px;
  37 + border-top: 1px solid #e5e5e5;
  38 + border-radius: 0 0 6px 6px;
  39 +}
  40 +.alertify-notifier .ajs-message {
  41 + background: rgba(255, 255, 255, 0.95);
  42 + color: #000;
  43 + text-align: center;
  44 + border: solid 1px #ddd;
  45 + border-radius: 2px;
  46 +}
  47 +.alertify-notifier .ajs-message.ajs-success {
  48 + color: #fff;
  49 + background: rgba(91, 189, 114, 0.95);
  50 + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
  51 +}
  52 +.alertify-notifier .ajs-message.ajs-error {
  53 + color: #fff;
  54 + background: rgba(217, 92, 92, 0.95);
  55 + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
  56 +}
  57 +.alertify-notifier .ajs-message.ajs-warning {
  58 + background: rgba(252, 248, 215, 0.95);
  59 + border-color: #999;
  60 +}
core/static/css/vendor/alertifyjs/themes/bootstrap.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer{background-color:#000;opacity:.5}.alertify .ajs-dialog{max-width:600px;min-height:122px;background-color:#fff;border:1px solid rgba(0,0,0,.2);box-shadow:0 5px 15px rgba(0,0,0,.5);border-radius:6px}.alertify .ajs-header{color:#333;border-bottom:1px solid #e5e5e5;border-radius:6px 6px 0 0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#000}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:58px;bottom:68px}.alertify .ajs-footer{background-color:#fff;padding:15px;border-top:1px solid #e5e5e5;border-radius:0 0 6px 6px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:1px solid #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/themes/bootstrap.rtl.css 0 → 100644
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer {
  7 + background-color: #000;
  8 + opacity: .5;
  9 +}
  10 +.alertify .ajs-dialog {
  11 + max-width: 600px;
  12 + min-height: 122px;
  13 + background-color: #fff;
  14 + border: 1px solid rgba(0, 0, 0, 0.2);
  15 + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
  16 + border-radius: 6px;
  17 +}
  18 +.alertify .ajs-header {
  19 + color: #333;
  20 + border-bottom: 1px solid #e5e5e5;
  21 + border-radius: 6px 6px 0 0;
  22 + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  23 + font-size: 18px;
  24 +}
  25 +.alertify .ajs-body {
  26 + font-family: 'Roboto', sans-serif;
  27 + color: black;
  28 +}
  29 +.alertify.ajs-resizable .ajs-content,
  30 +.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
  31 + top: 58px;
  32 + bottom: 68px;
  33 +}
  34 +.alertify .ajs-footer {
  35 + background-color: #fff;
  36 + padding: 15px;
  37 + border-top: 1px solid #e5e5e5;
  38 + border-radius: 0 0 6px 6px;
  39 +}
  40 +.alertify-notifier .ajs-message {
  41 + background: rgba(255, 255, 255, 0.95);
  42 + color: #000;
  43 + text-align: center;
  44 + border: solid 1px #ddd;
  45 + border-radius: 2px;
  46 +}
  47 +.alertify-notifier .ajs-message.ajs-success {
  48 + color: #fff;
  49 + background: rgba(91, 189, 114, 0.95);
  50 + text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
  51 +}
  52 +.alertify-notifier .ajs-message.ajs-error {
  53 + color: #fff;
  54 + background: rgba(217, 92, 92, 0.95);
  55 + text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
  56 +}
  57 +.alertify-notifier .ajs-message.ajs-warning {
  58 + background: rgba(252, 248, 215, 0.95);
  59 + border-color: #999;
  60 +}
core/static/css/vendor/alertifyjs/themes/bootstrap.rtl.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer{background-color:#000;opacity:.5}.alertify .ajs-dialog{max-width:600px;min-height:122px;background-color:#fff;border:1px solid rgba(0,0,0,.2);box-shadow:0 5px 15px rgba(0,0,0,.5);border-radius:6px}.alertify .ajs-header{color:#333;border-bottom:1px solid #e5e5e5;border-radius:6px 6px 0 0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#000}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:58px;bottom:68px}.alertify .ajs-footer{background-color:#fff;padding:15px;border-top:1px solid #e5e5e5;border-radius:0 0 6px 6px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:1px solid #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/themes/default.css 0 → 100644
@@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dialog {
  7 + background-color: white;
  8 + box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25);
  9 + border-radius: 2px;
  10 +}
  11 +.alertify .ajs-header {
  12 + color: black;
  13 + font-weight: bold;
  14 + background: #fafafa;
  15 + border-bottom: #eee 1px solid;
  16 + border-radius: 2px 2px 0 0;
  17 +}
  18 +.alertify .ajs-body {
  19 + color: black;
  20 +}
  21 +.alertify .ajs-body .ajs-content .ajs-input {
  22 + display: block;
  23 + width: 100%;
  24 + padding: 8px;
  25 + margin: 4px;
  26 + border-radius: 2px;
  27 + border: 1px solid #CCC;
  28 +}
  29 +.alertify .ajs-body .ajs-content p {
  30 + margin: 0;
  31 +}
  32 +.alertify .ajs-footer {
  33 + background: #fbfbfb;
  34 + border-top: #eee 1px solid;
  35 + border-radius: 0 0 2px 2px;
  36 +}
  37 +.alertify .ajs-footer .ajs-buttons .ajs-button {
  38 + background-color: transparent;
  39 + color: #000;
  40 + border: 0;
  41 + font-size: 14px;
  42 + font-weight: bold;
  43 + text-transform: uppercase;
  44 +}
  45 +.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok {
  46 + color: #3593D2;
  47 +}
  48 +.alertify-notifier .ajs-message {
  49 + background: rgba(255, 255, 255, 0.95);
  50 + color: #000;
  51 + text-align: center;
  52 + border: solid 1px #ddd;
  53 + border-radius: 2px;
  54 +}
  55 +.alertify-notifier .ajs-message.ajs-success {
  56 + color: #fff;
  57 + background: rgba(91, 189, 114, 0.95);
  58 + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
  59 +}
  60 +.alertify-notifier .ajs-message.ajs-error {
  61 + color: #fff;
  62 + background: rgba(217, 92, 92, 0.95);
  63 + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
  64 +}
  65 +.alertify-notifier .ajs-message.ajs-warning {
  66 + background: rgba(252, 248, 215, 0.95);
  67 + border-color: #999;
  68 +}
core/static/css/vendor/alertifyjs/themes/default.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dialog{background-color:#fff;box-shadow:0 15px 20px 0 rgba(0,0,0,.25);border-radius:2px}.alertify .ajs-header{color:#000;font-weight:700;background:#fafafa;border-bottom:#eee 1px solid;border-radius:2px 2px 0 0}.alertify .ajs-body{color:#000}.alertify .ajs-body .ajs-content .ajs-input{display:block;width:100%;padding:8px;margin:4px;border-radius:2px;border:1px solid #CCC}.alertify .ajs-body .ajs-content p{margin:0}.alertify .ajs-footer{background:#fbfbfb;border-top:#eee 1px solid;border-radius:0 0 2px 2px}.alertify .ajs-footer .ajs-buttons .ajs-button{background-color:transparent;color:#000;border:0;font-size:14px;font-weight:700;text-transform:uppercase}.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok{color:#3593D2}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:1px solid #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/themes/default.rtl.css 0 → 100644
@@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dialog {
  7 + background-color: white;
  8 + box-shadow: 0px 15px 20px 0px rgba(0, 0, 0, 0.25);
  9 + border-radius: 2px;
  10 +}
  11 +.alertify .ajs-header {
  12 + color: black;
  13 + font-weight: bold;
  14 + background: #fafafa;
  15 + border-bottom: #eee 1px solid;
  16 + border-radius: 2px 2px 0 0;
  17 +}
  18 +.alertify .ajs-body {
  19 + color: black;
  20 +}
  21 +.alertify .ajs-body .ajs-content .ajs-input {
  22 + display: block;
  23 + width: 100%;
  24 + padding: 8px;
  25 + margin: 4px;
  26 + border-radius: 2px;
  27 + border: 1px solid #CCC;
  28 +}
  29 +.alertify .ajs-body .ajs-content p {
  30 + margin: 0;
  31 +}
  32 +.alertify .ajs-footer {
  33 + background: #fbfbfb;
  34 + border-top: #eee 1px solid;
  35 + border-radius: 0 0 2px 2px;
  36 +}
  37 +.alertify .ajs-footer .ajs-buttons .ajs-button {
  38 + background-color: transparent;
  39 + color: #000;
  40 + border: 0;
  41 + font-size: 14px;
  42 + font-weight: bold;
  43 + text-transform: uppercase;
  44 +}
  45 +.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok {
  46 + color: #3593D2;
  47 +}
  48 +.alertify-notifier .ajs-message {
  49 + background: rgba(255, 255, 255, 0.95);
  50 + color: #000;
  51 + text-align: center;
  52 + border: solid 1px #ddd;
  53 + border-radius: 2px;
  54 +}
  55 +.alertify-notifier .ajs-message.ajs-success {
  56 + color: #fff;
  57 + background: rgba(91, 189, 114, 0.95);
  58 + text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
  59 +}
  60 +.alertify-notifier .ajs-message.ajs-error {
  61 + color: #fff;
  62 + background: rgba(217, 92, 92, 0.95);
  63 + text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
  64 +}
  65 +.alertify-notifier .ajs-message.ajs-warning {
  66 + background: rgba(252, 248, 215, 0.95);
  67 + border-color: #999;
  68 +}
core/static/css/vendor/alertifyjs/themes/default.rtl.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dialog{background-color:#fff;box-shadow:0 15px 20px 0 rgba(0,0,0,.25);border-radius:2px}.alertify .ajs-header{color:#000;font-weight:700;background:#fafafa;border-bottom:#eee 1px solid;border-radius:2px 2px 0 0}.alertify .ajs-body{color:#000}.alertify .ajs-body .ajs-content .ajs-input{display:block;width:100%;padding:8px;margin:4px;border-radius:2px;border:1px solid #CCC}.alertify .ajs-body .ajs-content p{margin:0}.alertify .ajs-footer{background:#fbfbfb;border-top:#eee 1px solid;border-radius:0 0 2px 2px}.alertify .ajs-footer .ajs-buttons .ajs-button{background-color:transparent;color:#000;border:0;font-size:14px;font-weight:700;text-transform:uppercase}.alertify .ajs-footer .ajs-buttons .ajs-button.ajs-ok{color:#3593D2}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:1px solid #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/themes/semantic.css 0 → 100644
@@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer {
  7 + background-color: rgba(0, 0, 0, 0.85);
  8 + opacity: 1;
  9 +}
  10 +.alertify .ajs-dialog {
  11 + max-width: 50%;
  12 + min-height: 137px;
  13 + background-color: #F4F4F4;
  14 + border: 1px solid #DDD;
  15 + box-shadow: none;
  16 + border-radius: 5px;
  17 +}
  18 +.alertify .ajs-header {
  19 + padding: 1.5rem 2rem;
  20 + border-bottom: none;
  21 + border-radius: 5px 5px 0 0;
  22 + color: #555;
  23 + background-color: #fff;
  24 + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  25 + font-size: 1.6em;
  26 + font-weight: 700;
  27 +}
  28 +.alertify .ajs-body {
  29 + font-family: 'Roboto', sans-serif;
  30 + color: #555;
  31 +}
  32 +.alertify .ajs-body .ajs-content .ajs-input {
  33 + width: 100%;
  34 + margin: 0;
  35 + padding: .65em 1em;
  36 + font-size: 1em;
  37 + background-color: #FFF;
  38 + border: 1px solid rgba(0, 0, 0, 0.15);
  39 + outline: 0;
  40 + color: rgba(0, 0, 0, 0.7);
  41 + border-radius: .3125em;
  42 + transition: background-color 0.3s ease-out, box-shadow 0.2s ease, border-color 0.2s ease;
  43 + box-sizing: border-box;
  44 +}
  45 +.alertify .ajs-body .ajs-content .ajs-input:active {
  46 + border-color: rgba(0, 0, 0, 0.3);
  47 + background-color: #FAFAFA;
  48 +}
  49 +.alertify .ajs-body .ajs-content .ajs-input:focus {
  50 + border-color: rgba(0, 0, 0, 0.2);
  51 + color: rgba(0, 0, 0, 0.85);
  52 +}
  53 +.alertify.ajs-resizable .ajs-content,
  54 +.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
  55 + top: 64px;
  56 + bottom: 74px;
  57 +}
  58 +.alertify .ajs-footer {
  59 + background-color: #fff;
  60 + padding: 1rem 2rem;
  61 + border-top: none;
  62 + border-radius: 0 0 5px 5px;
  63 +}
  64 +.alertify-notifier .ajs-message {
  65 + background: rgba(255, 255, 255, 0.95);
  66 + color: #000;
  67 + text-align: center;
  68 + border: solid 1px #ddd;
  69 + border-radius: 2px;
  70 +}
  71 +.alertify-notifier .ajs-message.ajs-success {
  72 + color: #fff;
  73 + background: rgba(91, 189, 114, 0.95);
  74 + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
  75 +}
  76 +.alertify-notifier .ajs-message.ajs-error {
  77 + color: #fff;
  78 + background: rgba(217, 92, 92, 0.95);
  79 + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
  80 +}
  81 +.alertify-notifier .ajs-message.ajs-warning {
  82 + background: rgba(252, 248, 215, 0.95);
  83 + border-color: #999;
  84 +}
core/static/css/vendor/alertifyjs/themes/semantic.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer{background-color:rgba(0,0,0,.85);opacity:1}.alertify .ajs-dialog{max-width:50%;min-height:137px;background-color:#F4F4F4;border:1px solid #DDD;box-shadow:none;border-radius:5px}.alertify .ajs-header{padding:1.5rem 2rem;border-bottom:none;border-radius:5px 5px 0 0;color:#555;background-color:#fff;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:1.6em;font-weight:700}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#555}.alertify .ajs-body .ajs-content .ajs-input{width:100%;margin:0;padding:.65em 1em;font-size:1em;background-color:#FFF;border:1px solid rgba(0,0,0,.15);outline:0;color:rgba(0,0,0,.7);border-radius:.3125em;transition:background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease;box-sizing:border-box}.alertify .ajs-body .ajs-content .ajs-input:active{border-color:rgba(0,0,0,.3);background-color:#FAFAFA}.alertify .ajs-body .ajs-content .ajs-input:focus{border-color:rgba(0,0,0,.2);color:rgba(0,0,0,.85)}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:64px;bottom:74px}.alertify .ajs-footer{background-color:#fff;padding:1rem 2rem;border-top:none;border-radius:0 0 5px 5px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:1px solid #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:-1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/css/vendor/alertifyjs/themes/semantic.rtl.css 0 → 100644
@@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer {
  7 + background-color: rgba(0, 0, 0, 0.85);
  8 + opacity: 1;
  9 +}
  10 +.alertify .ajs-dialog {
  11 + max-width: 50%;
  12 + min-height: 137px;
  13 + background-color: #F4F4F4;
  14 + border: 1px solid #DDD;
  15 + box-shadow: none;
  16 + border-radius: 5px;
  17 +}
  18 +.alertify .ajs-header {
  19 + padding: 1.5rem 2rem;
  20 + border-bottom: none;
  21 + border-radius: 5px 5px 0 0;
  22 + color: #555;
  23 + background-color: #fff;
  24 + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  25 + font-size: 1.6em;
  26 + font-weight: 700;
  27 +}
  28 +.alertify .ajs-body {
  29 + font-family: 'Roboto', sans-serif;
  30 + color: #555;
  31 +}
  32 +.alertify .ajs-body .ajs-content .ajs-input {
  33 + width: 100%;
  34 + margin: 0;
  35 + padding: .65em 1em;
  36 + font-size: 1em;
  37 + background-color: #FFF;
  38 + border: 1px solid rgba(0, 0, 0, 0.15);
  39 + outline: 0;
  40 + color: rgba(0, 0, 0, 0.7);
  41 + border-radius: .3125em;
  42 + transition: background-color 0.3s ease-out, box-shadow 0.2s ease, border-color 0.2s ease;
  43 + box-sizing: border-box;
  44 +}
  45 +.alertify .ajs-body .ajs-content .ajs-input:active {
  46 + border-color: rgba(0, 0, 0, 0.3);
  47 + background-color: #FAFAFA;
  48 +}
  49 +.alertify .ajs-body .ajs-content .ajs-input:focus {
  50 + border-color: rgba(0, 0, 0, 0.2);
  51 + color: rgba(0, 0, 0, 0.85);
  52 +}
  53 +.alertify.ajs-resizable .ajs-content,
  54 +.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content {
  55 + top: 64px;
  56 + bottom: 74px;
  57 +}
  58 +.alertify .ajs-footer {
  59 + background-color: #fff;
  60 + padding: 1rem 2rem;
  61 + border-top: none;
  62 + border-radius: 0 0 5px 5px;
  63 +}
  64 +.alertify-notifier .ajs-message {
  65 + background: rgba(255, 255, 255, 0.95);
  66 + color: #000;
  67 + text-align: center;
  68 + border: solid 1px #ddd;
  69 + border-radius: 2px;
  70 +}
  71 +.alertify-notifier .ajs-message.ajs-success {
  72 + color: #fff;
  73 + background: rgba(91, 189, 114, 0.95);
  74 + text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
  75 +}
  76 +.alertify-notifier .ajs-message.ajs-error {
  77 + color: #fff;
  78 + background: rgba(217, 92, 92, 0.95);
  79 + text-shadow: 1px -1px 0 rgba(0, 0, 0, 0.5);
  80 +}
  81 +.alertify-notifier .ajs-message.ajs-warning {
  82 + background: rgba(252, 248, 215, 0.95);
  83 + border-color: #999;
  84 +}
core/static/css/vendor/alertifyjs/themes/semantic.rtl.min.css 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +/**
  2 + * alertifyjs 1.8.0 http://alertifyjs.com
  3 + * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4 + * Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5 + * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6 +.alertify .ajs-dimmer{background-color:rgba(0,0,0,.85);opacity:1}.alertify .ajs-dialog{max-width:50%;min-height:137px;background-color:#F4F4F4;border:1px solid #DDD;box-shadow:none;border-radius:5px}.alertify .ajs-header{padding:1.5rem 2rem;border-bottom:none;border-radius:5px 5px 0 0;color:#555;background-color:#fff;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:1.6em;font-weight:700}.alertify .ajs-body{font-family:Roboto,sans-serif;color:#555}.alertify .ajs-body .ajs-content .ajs-input{width:100%;margin:0;padding:.65em 1em;font-size:1em;background-color:#FFF;border:1px solid rgba(0,0,0,.15);outline:0;color:rgba(0,0,0,.7);border-radius:.3125em;transition:background-color .3s ease-out,box-shadow .2s ease,border-color .2s ease;box-sizing:border-box}.alertify .ajs-body .ajs-content .ajs-input:active{border-color:rgba(0,0,0,.3);background-color:#FAFAFA}.alertify .ajs-body .ajs-content .ajs-input:focus{border-color:rgba(0,0,0,.2);color:rgba(0,0,0,.85)}.alertify.ajs-maximized:not(.ajs-resizable) .ajs-content,.alertify.ajs-resizable .ajs-content{top:64px;bottom:74px}.alertify .ajs-footer{background-color:#fff;padding:1rem 2rem;border-top:none;border-radius:0 0 5px 5px}.alertify-notifier .ajs-message{background:rgba(255,255,255,.95);color:#000;text-align:center;border:1px solid #ddd;border-radius:2px}.alertify-notifier .ajs-message.ajs-success{color:#fff;background:rgba(91,189,114,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-error{color:#fff;background:rgba(217,92,92,.95);text-shadow:1px -1px 0 rgba(0,0,0,.5)}.alertify-notifier .ajs-message.ajs-warning{background:rgba(252,248,215,.95);border-color:#999}
0 \ No newline at end of file 7 \ No newline at end of file
core/static/js/base/amadeus.js
@@ -126,4 +126,18 @@ function validarCpfSemAlert(campo,nome,idElementoMensagemErro){ @@ -126,4 +126,18 @@ function validarCpfSemAlert(campo,nome,idElementoMensagemErro){
126 return true; 126 return true;
127 } 127 }
128 return retorno; 128 return retorno;
129 -}  
130 \ No newline at end of file 129 \ No newline at end of file
  130 +}
  131 +
  132 +/*
  133 +This functions get the next 5 notifications from the user given a "step"(an amount) of previous notifications
  134 +*/
  135 +function getNotifications(step){
  136 + $.get('/getNotifications',
  137 + {'steps':step, 'amount': 5}, function(data){
  138 + $("#notification-dropdown").append(data);
  139 + $('#notification-see-more').remove();
  140 + var seemore = '<li><a onclick="getNotifications('+(step+5)+')"> <div id="notification-see-more" class="list-group-item"> <div class="row-content"><p class="list-group-item-text">See More</p> </div> </a></li>';
  141 + $("#notification-dropdown").append(seemore);
  142 + $("#notification-count").text(step+5);
  143 + });
  144 +}
core/static/js/base/header.js
1 $(document).ready(function(){ 1 $(document).ready(function(){
2 $('[data-toggle="tooltip"]').tooltip(); //activate tooltip on all elements that has attribute data-toggle 2 $('[data-toggle="tooltip"]').tooltip(); //activate tooltip on all elements that has attribute data-toggle
3 -});  
4 \ No newline at end of file 3 \ No newline at end of file
  4 +});
  5 +
  6 +
  7 +/*
  8 +
  9 +*/
  10 +function getNotifications(step){
  11 + $.ajax('/getNotifications',{
  12 + steps: step,
  13 + amount: 5,
  14 + sucess: function(response){
  15 +
  16 + }
  17 + });
  18 +}
  19 +
  20 +
  21 +/*
  22 +
  23 +*/
  24 +function checkIfNewNotification(){
  25 +
  26 +}
5 \ No newline at end of file 27 \ No newline at end of file
core/static/js/vendor/alertify.min.js 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +/*! alertifyjs - v1.8.0 - Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com) */
  2 +!function(a){"use strict";function b(a,b){a.className+=" "+b}function c(a,b){for(var c=a.className.split(" "),d=b.split(" "),e=0;e<d.length;e+=1){var f=c.indexOf(d[e]);f>-1&&c.splice(f,1)}a.className=c.join(" ")}function d(){return"rtl"===a.getComputedStyle(document.body).direction}function e(){return document.documentElement&&document.documentElement.scrollTop||document.body.scrollTop}function f(){return document.documentElement&&document.documentElement.scrollLeft||document.body.scrollLeft}function g(a){for(;a.lastChild;)a.removeChild(a.lastChild)}function h(a){if(null===a)return a;var b;if(Array.isArray(a)){b=[];for(var c=0;c<a.length;c+=1)b.push(h(a[c]));return b}if(a instanceof Date)return new Date(a.getTime());if(a instanceof RegExp)return b=new RegExp(a.source),b.global=a.global,b.ignoreCase=a.ignoreCase,b.multiline=a.multiline,b.lastIndex=a.lastIndex,b;if("object"==typeof a){b={};for(var d in a)a.hasOwnProperty(d)&&(b[d]=h(a[d]));return b}return a}function i(a,b){var c=a.elements.root;c.parentNode.removeChild(c),delete a.elements,a.settings=h(a.__settings),a.__init=b,delete a.__internal}function j(a,b){return function(){if(arguments.length>0){for(var c=[],d=0;d<arguments.length;d+=1)c.push(arguments[d]);return c.push(a),b.apply(a,c)}return b.apply(a,[null,a])}}function k(a,b){return{index:a,button:b,cancel:!1}}function l(a,b){"function"==typeof b.get(a)&&b.get(a).call(b)}function m(){function a(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}function b(a){var b=d[a].dialog;return b&&"function"==typeof b.__init&&b.__init(b),b}function c(b,c,e,f){var g={dialog:null,factory:c};return void 0!==f&&(g.factory=function(){return a(new d[f].factory,new c)}),e||(g.dialog=a(new g.factory,t)),d[b]=g}var d={};return{defaults:o,dialog:function(d,e,f,g){if("function"!=typeof e)return b(d);if(this.hasOwnProperty(d))throw new Error("alertify.dialog: name already exists");var h=c(d,e,f,g);f?this[d]=function(){if(0===arguments.length)return h.dialog;var b=a(new h.factory,t);return b&&"function"==typeof b.__init&&b.__init(b),b.main.apply(b,arguments),b.show.apply(b)}:this[d]=function(){if(h.dialog&&"function"==typeof h.dialog.__init&&h.dialog.__init(h.dialog),0===arguments.length)return h.dialog;var a=h.dialog;return a.main.apply(h.dialog,arguments),a.show.apply(h.dialog)}},closeAll:function(a){for(var b=p.slice(0),c=0;c<b.length;c+=1){var d=b[c];(void 0===a||a!==d)&&d.close()}},setting:function(a,c,d){if("notifier"===a)return u.setting(c,d);var e=b(a);return e?e.setting(c,d):void 0},set:function(a,b,c){return this.setting(a,b,c)},get:function(a,b){return this.setting(a,b)},notify:function(a,b,c,d){return u.create(b,d).push(a,c)},message:function(a,b,c){return u.create(null,c).push(a,b)},success:function(a,b,c){return u.create("success",c).push(a,b)},error:function(a,b,c){return u.create("error",c).push(a,b)},warning:function(a,b,c){return u.create("warning",c).push(a,b)},dismissAll:function(){u.dismissAll()}}}var n={ENTER:13,ESC:27,F1:112,F12:123,LEFT:37,RIGHT:39},o={autoReset:!0,basic:!1,closable:!0,closableByDimmer:!0,frameless:!1,maintainFocus:!0,maximizable:!0,modal:!0,movable:!0,moveBounded:!1,overflow:!0,padding:!0,pinnable:!0,pinned:!0,preventBodyShift:!1,resizable:!0,startMaximized:!1,transition:"pulse",notifier:{delay:5,position:"bottom-right"},glossary:{title:"AlertifyJS",ok:"OK",cancel:"Cancel",acccpt:"Accept",deny:"Deny",confirm:"Confirm",decline:"Decline",close:"Close",maximize:"Maximize",restore:"Restore"},theme:{input:"ajs-input",ok:"ajs-ok",cancel:"ajs-cancel"}},p=[],q=function(){return document.addEventListener?function(a,b,c,d){a.addEventListener(b,c,d===!0)}:document.attachEvent?function(a,b,c){a.attachEvent("on"+b,c)}:void 0}(),r=function(){return document.removeEventListener?function(a,b,c,d){a.removeEventListener(b,c,d===!0)}:document.detachEvent?function(a,b,c){a.detachEvent("on"+b,c)}:void 0}(),s=function(){var a,b,c=!1,d={animation:"animationend",OAnimation:"oAnimationEnd oanimationend",msAnimation:"MSAnimationEnd",MozAnimation:"animationend",WebkitAnimation:"webkitAnimationEnd"};for(a in d)if(void 0!==document.documentElement.style[a]){b=d[a],c=!0;break}return{type:b,supported:c}}(),t=function(){function m(a){if(!a.__internal){delete a.__init,a.__settings||(a.__settings=h(a.settings)),null===za&&document.body.setAttribute("tabindex","0");var c;"function"==typeof a.setup?(c=a.setup(),c.options=c.options||{},c.focus=c.focus||{}):c={buttons:[],focus:{element:null,select:!1},options:{}},"object"!=typeof a.hooks&&(a.hooks={});var d=[];if(Array.isArray(c.buttons))for(var e=0;e<c.buttons.length;e+=1){var f=c.buttons[e],g={};for(var i in f)f.hasOwnProperty(i)&&(g[i]=f[i]);d.push(g)}var k=a.__internal={isOpen:!1,activeElement:document.body,timerIn:void 0,timerOut:void 0,buttons:d,focus:c.focus,options:{title:void 0,modal:void 0,basic:void 0,frameless:void 0,pinned:void 0,movable:void 0,moveBounded:void 0,resizable:void 0,autoReset:void 0,closable:void 0,closableByDimmer:void 0,maximizable:void 0,startMaximized:void 0,pinnable:void 0,transition:void 0,padding:void 0,overflow:void 0,onshow:void 0,onclose:void 0,onfocus:void 0,onmove:void 0,onmoved:void 0,onresize:void 0,onresized:void 0,onmaximize:void 0,onmaximized:void 0,onrestore:void 0,onrestored:void 0},resetHandler:void 0,beginMoveHandler:void 0,beginResizeHandler:void 0,bringToFrontHandler:void 0,modalClickHandler:void 0,buttonsClickHandler:void 0,commandsClickHandler:void 0,transitionInHandler:void 0,transitionOutHandler:void 0,destroy:void 0},l={};l.root=document.createElement("div"),l.root.className=Ca.base+" "+Ca.hidden+" ",l.root.innerHTML=Ba.dimmer+Ba.modal,l.dimmer=l.root.firstChild,l.modal=l.root.lastChild,l.modal.innerHTML=Ba.dialog,l.dialog=l.modal.firstChild,l.dialog.innerHTML=Ba.reset+Ba.commands+Ba.header+Ba.body+Ba.footer+Ba.resizeHandle+Ba.reset,l.reset=[],l.reset.push(l.dialog.firstChild),l.reset.push(l.dialog.lastChild),l.commands={},l.commands.container=l.reset[0].nextSibling,l.commands.pin=l.commands.container.firstChild,l.commands.maximize=l.commands.pin.nextSibling,l.commands.close=l.commands.maximize.nextSibling,l.header=l.commands.container.nextSibling,l.body=l.header.nextSibling,l.body.innerHTML=Ba.content,l.content=l.body.firstChild,l.footer=l.body.nextSibling,l.footer.innerHTML=Ba.buttons.auxiliary+Ba.buttons.primary,l.resizeHandle=l.footer.nextSibling,l.buttons={},l.buttons.auxiliary=l.footer.firstChild,l.buttons.primary=l.buttons.auxiliary.nextSibling,l.buttons.primary.innerHTML=Ba.button,l.buttonTemplate=l.buttons.primary.firstChild,l.buttons.primary.removeChild(l.buttonTemplate);for(var m=0;m<a.__internal.buttons.length;m+=1){var n=a.__internal.buttons[m];ya.indexOf(n.key)<0&&ya.push(n.key),n.element=l.buttonTemplate.cloneNode(),n.element.innerHTML=n.text,"string"==typeof n.className&&""!==n.className&&b(n.element,n.className);for(var o in n.attrs)"className"!==o&&n.attrs.hasOwnProperty(o)&&n.element.setAttribute(o,n.attrs[o]);"auxiliary"===n.scope?l.buttons.auxiliary.appendChild(n.element):l.buttons.primary.appendChild(n.element)}a.elements=l,k.resetHandler=j(a,X),k.beginMoveHandler=j(a,aa),k.beginResizeHandler=j(a,ga),k.bringToFrontHandler=j(a,B),k.modalClickHandler=j(a,R),k.buttonsClickHandler=j(a,T),k.commandsClickHandler=j(a,F),k.transitionInHandler=j(a,Y),k.transitionOutHandler=j(a,Z);for(var p in k.options)void 0!==c.options[p]?a.set(p,c.options[p]):v.defaults.hasOwnProperty(p)?a.set(p,v.defaults[p]):"title"===p&&a.set(p,v.defaults.glossary[p]);"function"==typeof a.build&&a.build()}document.body.appendChild(a.elements.root)}function o(){wa=f(),xa=e()}function t(){a.scrollTo(wa,xa)}function u(){for(var a=0,d=0;d<p.length;d+=1){var e=p[d];(e.isModal()||e.isMaximized())&&(a+=1)}0===a&&document.body.className.indexOf(Ca.noOverflow)>=0?(c(document.body,Ca.noOverflow),w(!1)):a>0&&document.body.className.indexOf(Ca.noOverflow)<0&&(w(!0),b(document.body,Ca.noOverflow))}function w(d){v.defaults.preventBodyShift&&document.documentElement.scrollHeight>document.documentElement.clientHeight&&(d?(Ea=xa,Da=a.getComputedStyle(document.body).top,b(document.body,Ca.fixed),document.body.style.top=-xa+"px"):(xa=Ea,document.body.style.top=Da,c(document.body,Ca.fixed),t()))}function x(a,d,e){"string"==typeof e&&c(a.elements.root,Ca.prefix+e),b(a.elements.root,Ca.prefix+d),za=a.elements.root.offsetWidth}function y(a){a.get("modal")?(c(a.elements.root,Ca.modeless),a.isOpen()&&(pa(a),N(a),u())):(b(a.elements.root,Ca.modeless),a.isOpen()&&(oa(a),N(a),u()))}function z(a){a.get("basic")?b(a.elements.root,Ca.basic):c(a.elements.root,Ca.basic)}function A(a){a.get("frameless")?b(a.elements.root,Ca.frameless):c(a.elements.root,Ca.frameless)}function B(a,b){for(var c=p.indexOf(b),d=c+1;d<p.length;d+=1)if(p[d].isModal())return;return document.body.lastChild!==b.elements.root&&(document.body.appendChild(b.elements.root),p.splice(p.indexOf(b),1),p.push(b),W(b)),!1}function C(a,d,e,f){switch(d){case"title":a.setHeader(f);break;case"modal":y(a);break;case"basic":z(a);break;case"frameless":A(a);break;case"pinned":O(a);break;case"closable":Q(a);break;case"maximizable":P(a);break;case"pinnable":K(a);break;case"movable":ea(a);break;case"resizable":ka(a);break;case"transition":x(a,f,e);break;case"padding":f?c(a.elements.root,Ca.noPadding):a.elements.root.className.indexOf(Ca.noPadding)<0&&b(a.elements.root,Ca.noPadding);break;case"overflow":f?c(a.elements.root,Ca.noOverflow):a.elements.root.className.indexOf(Ca.noOverflow)<0&&b(a.elements.root,Ca.noOverflow);break;case"transition":x(a,f,e)}"function"==typeof a.hooks.onupdate&&a.hooks.onupdate.call(a,d,e,f)}function D(a,b,c,d,e){var f={op:void 0,items:[]};if("undefined"==typeof e&&"string"==typeof d)f.op="get",b.hasOwnProperty(d)?(f.found=!0,f.value=b[d]):(f.found=!1,f.value=void 0);else{var g;if(f.op="set","object"==typeof d){var h=d;for(var i in h)b.hasOwnProperty(i)?(b[i]!==h[i]&&(g=b[i],b[i]=h[i],c.call(a,i,g,h[i])),f.items.push({key:i,value:h[i],found:!0})):f.items.push({key:i,value:h[i],found:!1})}else{if("string"!=typeof d)throw new Error("args must be a string or object");b.hasOwnProperty(d)?(b[d]!==e&&(g=b[d],b[d]=e,c.call(a,d,g,e)),f.items.push({key:d,value:e,found:!0})):f.items.push({key:d,value:e,found:!1})}}return f}function E(a){var b;S(a,function(a){return b=a.invokeOnClose===!0}),!b&&a.isOpen()&&a.close()}function F(a,b){var c=a.srcElement||a.target;switch(c){case b.elements.commands.pin:b.isPinned()?H(b):G(b);break;case b.elements.commands.maximize:b.isMaximized()?J(b):I(b);break;case b.elements.commands.close:E(b)}return!1}function G(a){a.set("pinned",!0)}function H(a){a.set("pinned",!1)}function I(a){l("onmaximize",a),b(a.elements.root,Ca.maximized),a.isOpen()&&u(),l("onmaximized",a)}function J(a){l("onrestore",a),c(a.elements.root,Ca.maximized),a.isOpen()&&u(),l("onrestored",a)}function K(a){a.get("pinnable")?b(a.elements.root,Ca.pinnable):c(a.elements.root,Ca.pinnable)}function L(a){var b=f();a.elements.modal.style.marginTop=e()+"px",a.elements.modal.style.marginLeft=b+"px",a.elements.modal.style.marginRight=-b+"px"}function M(a){var b=parseInt(a.elements.modal.style.marginTop,10),c=parseInt(a.elements.modal.style.marginLeft,10);if(a.elements.modal.style.marginTop="",a.elements.modal.style.marginLeft="",a.elements.modal.style.marginRight="",a.isOpen()){var d=0,g=0;""!==a.elements.dialog.style.top&&(d=parseInt(a.elements.dialog.style.top,10)),a.elements.dialog.style.top=d+(b-e())+"px",""!==a.elements.dialog.style.left&&(g=parseInt(a.elements.dialog.style.left,10)),a.elements.dialog.style.left=g+(c-f())+"px"}}function N(a){a.get("modal")||a.get("pinned")?M(a):L(a)}function O(a){a.get("pinned")?(c(a.elements.root,Ca.unpinned),a.isOpen()&&M(a)):(b(a.elements.root,Ca.unpinned),a.isOpen()&&!a.isModal()&&L(a))}function P(a){a.get("maximizable")?b(a.elements.root,Ca.maximizable):c(a.elements.root,Ca.maximizable)}function Q(a){a.get("closable")?(b(a.elements.root,Ca.closable),ua(a)):(c(a.elements.root,Ca.closable),va(a))}function R(a,b){var c=a.srcElement||a.target;return Fa||c!==b.elements.modal||b.get("closableByDimmer")!==!0||E(b),Fa=!1,!1}function S(a,b){for(var c=0;c<a.__internal.buttons.length;c+=1){var d=a.__internal.buttons[c];if(!d.element.disabled&&b(d)){var e=k(c,d);"function"==typeof a.callback&&a.callback.apply(a,[e]),e.cancel===!1&&a.close();break}}}function T(a,b){var c=a.srcElement||a.target;S(b,function(a){return a.element===c&&(Ga=!0)})}function U(a){if(Ga)return void(Ga=!1);var b=p[p.length-1],c=a.keyCode;return 0===b.__internal.buttons.length&&c===n.ESC&&b.get("closable")===!0?(E(b),!1):ya.indexOf(c)>-1?(S(b,function(a){return a.key===c}),!1):void 0}function V(a){var b=p[p.length-1],c=a.keyCode;if(c===n.LEFT||c===n.RIGHT){for(var d=b.__internal.buttons,e=0;e<d.length;e+=1)if(document.activeElement===d[e].element)switch(c){case n.LEFT:return void d[(e||d.length)-1].element.focus();case n.RIGHT:return void d[(e+1)%d.length].element.focus()}}else if(c<n.F12+1&&c>n.F1-1&&ya.indexOf(c)>-1)return a.preventDefault(),a.stopPropagation(),S(b,function(a){return a.key===c}),!1}function W(a,b){if(b)b.focus();else{var c=a.__internal.focus,d=c.element;switch(typeof c.element){case"number":a.__internal.buttons.length>c.element&&(d=a.get("basic")===!0?a.elements.reset[0]:a.__internal.buttons[c.element].element);break;case"string":d=a.elements.body.querySelector(c.element);break;case"function":d=c.element.call(a)}"undefined"!=typeof d&&null!==d||0!==a.__internal.buttons.length||(d=a.elements.reset[0]),d&&d.focus&&(d.focus(),c.select&&d.select&&d.select())}}function X(a,b){if(!b)for(var c=p.length-1;c>-1;c-=1)if(p[c].isModal()){b=p[c];break}if(b&&b.isModal()){var d,e=a.srcElement||a.target,f=e===b.elements.reset[1]||0===b.__internal.buttons.length&&e===document.body;f&&(b.get("maximizable")?d=b.elements.commands.maximize:b.get("closable")&&(d=b.elements.commands.close)),void 0===d&&("number"==typeof b.__internal.focus.element?e===b.elements.reset[0]?d=b.elements.buttons.auxiliary.firstChild||b.elements.buttons.primary.firstChild:f&&(d=b.elements.reset[0]):e===b.elements.reset[0]&&(d=b.elements.buttons.primary.lastChild||b.elements.buttons.auxiliary.lastChild)),W(b,d)}}function Y(a,b){clearTimeout(b.__internal.timerIn),W(b),t(),Ga=!1,l("onfocus",b),r(b.elements.dialog,s.type,b.__internal.transitionInHandler),c(b.elements.root,Ca.animationIn)}function Z(a,b){clearTimeout(b.__internal.timerOut),r(b.elements.dialog,s.type,b.__internal.transitionOutHandler),da(b),ja(b),b.isMaximized()&&!b.get("startMaximized")&&J(b),v.defaults.maintainFocus&&b.__internal.activeElement&&(b.__internal.activeElement.focus(),b.__internal.activeElement=null),"function"==typeof b.__internal.destroy&&b.__internal.destroy.apply(b)}function $(a,b){var c=a[Ka]-Ia,d=a[La]-Ja;Na&&(d-=document.body.scrollTop),b.style.left=c+"px",b.style.top=d+"px"}function _(a,b){var c=a[Ka]-Ia,d=a[La]-Ja;Na&&(d-=document.body.scrollTop),b.style.left=Math.min(Ma.maxLeft,Math.max(Ma.minLeft,c))+"px",Na?b.style.top=Math.min(Ma.maxTop,Math.max(Ma.minTop,d))+"px":b.style.top=Math.max(Ma.minTop,d)+"px"}function aa(a,c){if(null===Pa&&!c.isMaximized()&&c.get("movable")){var d,e=0,f=0;if("touchstart"===a.type?(a.preventDefault(),d=a.targetTouches[0],Ka="clientX",La="clientY"):0===a.button&&(d=a),d){var g=c.elements.dialog;if(b(g,Ca.capture),g.style.left&&(e=parseInt(g.style.left,10)),g.style.top&&(f=parseInt(g.style.top,10)),Ia=d[Ka]-e,Ja=d[La]-f,c.isModal()?Ja+=c.elements.modal.scrollTop:c.isPinned()&&(Ja-=document.body.scrollTop),c.get("moveBounded")){var h=g,i=-e,j=-f;do i+=h.offsetLeft,j+=h.offsetTop;while(h=h.offsetParent);Ma={maxLeft:i,minLeft:-i,maxTop:document.documentElement.clientHeight-g.clientHeight-j,minTop:-j},Oa=_}else Ma=null,Oa=$;return l("onmove",c),Na=!c.isModal()&&c.isPinned(),Ha=c,Oa(d,g),b(document.body,Ca.noSelection),!1}}}function ba(a){if(Ha){var b;"touchmove"===a.type?(a.preventDefault(),b=a.targetTouches[0]):0===a.button&&(b=a),b&&Oa(b,Ha.elements.dialog)}}function ca(){if(Ha){var a=Ha;Ha=Ma=null,c(document.body,Ca.noSelection),c(a.elements.dialog,Ca.capture),l("onmoved",a)}}function da(a){Ha=null;var b=a.elements.dialog;b.style.left=b.style.top=""}function ea(a){a.get("movable")?(b(a.elements.root,Ca.movable),a.isOpen()&&qa(a)):(da(a),c(a.elements.root,Ca.movable),a.isOpen()&&ra(a))}function fa(a,b,c){var e=b,f=0,g=0;do f+=e.offsetLeft,g+=e.offsetTop;while(e=e.offsetParent);var h,i;c===!0?(h=a.pageX,i=a.pageY):(h=a.clientX,i=a.clientY);var j=d();if(j&&(h=document.body.offsetWidth-h,isNaN(Qa)||(f=document.body.offsetWidth-f-b.offsetWidth)),b.style.height=i-g+Ta+"px",b.style.width=h-f+Ta+"px",!isNaN(Qa)){var k=.5*Math.abs(b.offsetWidth-Ra);j&&(k*=-1),b.offsetWidth>Ra?b.style.left=Qa+k+"px":b.offsetWidth>=Sa&&(b.style.left=Qa-k+"px")}}function ga(a,c){if(!c.isMaximized()){var d;if("touchstart"===a.type?(a.preventDefault(),d=a.targetTouches[0]):0===a.button&&(d=a),d){l("onresize",c),Pa=c,Ta=c.elements.resizeHandle.offsetHeight/2;var e=c.elements.dialog;return b(e,Ca.capture),Qa=parseInt(e.style.left,10),e.style.height=e.offsetHeight+"px",e.style.minHeight=c.elements.header.offsetHeight+c.elements.footer.offsetHeight+"px",e.style.width=(Ra=e.offsetWidth)+"px","none"!==e.style.maxWidth&&(e.style.minWidth=(Sa=e.offsetWidth)+"px"),e.style.maxWidth="none",b(document.body,Ca.noSelection),!1}}}function ha(a){if(Pa){var b;"touchmove"===a.type?(a.preventDefault(),b=a.targetTouches[0]):0===a.button&&(b=a),b&&fa(b,Pa.elements.dialog,!Pa.get("modal")&&!Pa.get("pinned"))}}function ia(){if(Pa){var a=Pa;Pa=null,c(document.body,Ca.noSelection),c(a.elements.dialog,Ca.capture),Fa=!0,l("onresized",a)}}function ja(a){Pa=null;var b=a.elements.dialog;"none"===b.style.maxWidth&&(b.style.maxWidth=b.style.minWidth=b.style.width=b.style.height=b.style.minHeight=b.style.left="",Qa=Number.Nan,Ra=Sa=Ta=0)}function ka(a){a.get("resizable")?(b(a.elements.root,Ca.resizable),a.isOpen()&&sa(a)):(ja(a),c(a.elements.root,Ca.resizable),a.isOpen()&&ta(a))}function la(){for(var a=0;a<p.length;a+=1){var b=p[a];b.get("autoReset")&&(da(b),ja(b))}}function ma(b){1===p.length&&(q(a,"resize",la),q(document.body,"keyup",U),q(document.body,"keydown",V),q(document.body,"focus",X),q(document.documentElement,"mousemove",ba),q(document.documentElement,"touchmove",ba),q(document.documentElement,"mouseup",ca),q(document.documentElement,"touchend",ca),q(document.documentElement,"mousemove",ha),q(document.documentElement,"touchmove",ha),q(document.documentElement,"mouseup",ia),q(document.documentElement,"touchend",ia)),q(b.elements.commands.container,"click",b.__internal.commandsClickHandler),q(b.elements.footer,"click",b.__internal.buttonsClickHandler),q(b.elements.reset[0],"focus",b.__internal.resetHandler),q(b.elements.reset[1],"focus",b.__internal.resetHandler),Ga=!0,q(b.elements.dialog,s.type,b.__internal.transitionInHandler),b.get("modal")||oa(b),b.get("resizable")&&sa(b),b.get("movable")&&qa(b)}function na(b){1===p.length&&(r(a,"resize",la),r(document.body,"keyup",U),r(document.body,"keydown",V),r(document.body,"focus",X),r(document.documentElement,"mousemove",ba),r(document.documentElement,"mouseup",ca),r(document.documentElement,"mousemove",ha),r(document.documentElement,"mouseup",ia)),r(b.elements.commands.container,"click",b.__internal.commandsClickHandler),r(b.elements.footer,"click",b.__internal.buttonsClickHandler),r(b.elements.reset[0],"focus",b.__internal.resetHandler),r(b.elements.reset[1],"focus",b.__internal.resetHandler),q(b.elements.dialog,s.type,b.__internal.transitionOutHandler),b.get("modal")||pa(b),b.get("movable")&&ra(b),b.get("resizable")&&ta(b)}function oa(a){q(a.elements.dialog,"focus",a.__internal.bringToFrontHandler,!0)}function pa(a){r(a.elements.dialog,"focus",a.__internal.bringToFrontHandler,!0)}function qa(a){q(a.elements.header,"mousedown",a.__internal.beginMoveHandler),q(a.elements.header,"touchstart",a.__internal.beginMoveHandler)}function ra(a){r(a.elements.header,"mousedown",a.__internal.beginMoveHandler),r(a.elements.header,"touchstart",a.__internal.beginMoveHandler)}function sa(a){q(a.elements.resizeHandle,"mousedown",a.__internal.beginResizeHandler),q(a.elements.resizeHandle,"touchstart",a.__internal.beginResizeHandler)}function ta(a){r(a.elements.resizeHandle,"mousedown",a.__internal.beginResizeHandler),r(a.elements.resizeHandle,"touchstart",a.__internal.beginResizeHandler)}function ua(a){q(a.elements.modal,"click",a.__internal.modalClickHandler)}function va(a){r(a.elements.modal,"click",a.__internal.modalClickHandler)}var wa,xa,ya=[],za=null,Aa=a.navigator.userAgent.indexOf("Safari")>-1&&a.navigator.userAgent.indexOf("Chrome")<0,Ba={dimmer:'<div class="ajs-dimmer"></div>',modal:'<div class="ajs-modal" tabindex="0"></div>',dialog:'<div class="ajs-dialog" tabindex="0"></div>',reset:'<button class="ajs-reset"></button>',commands:'<div class="ajs-commands"><button class="ajs-pin"></button><button class="ajs-maximize"></button><button class="ajs-close"></button></div>',header:'<div class="ajs-header"></div>',body:'<div class="ajs-body"></div>',content:'<div class="ajs-content"></div>',footer:'<div class="ajs-footer"></div>',buttons:{primary:'<div class="ajs-primary ajs-buttons"></div>',auxiliary:'<div class="ajs-auxiliary ajs-buttons"></div>'},button:'<button class="ajs-button"></button>',resizeHandle:'<div class="ajs-handle"></div>'},Ca={animationIn:"ajs-in",animationOut:"ajs-out",base:"alertify",basic:"ajs-basic",capture:"ajs-capture",closable:"ajs-closable",fixed:"ajs-fixed",frameless:"ajs-frameless",hidden:"ajs-hidden",maximize:"ajs-maximize",maximized:"ajs-maximized",maximizable:"ajs-maximizable",modeless:"ajs-modeless",movable:"ajs-movable",noSelection:"ajs-no-selection",noOverflow:"ajs-no-overflow",noPadding:"ajs-no-padding",pin:"ajs-pin",pinnable:"ajs-pinnable",prefix:"ajs-",resizable:"ajs-resizable",restore:"ajs-restore",shake:"ajs-shake",unpinned:"ajs-unpinned"},Da="",Ea=0,Fa=!1,Ga=!1,Ha=null,Ia=0,Ja=0,Ka="pageX",La="pageY",Ma=null,Na=!1,Oa=null,Pa=null,Qa=Number.Nan,Ra=0,Sa=0,Ta=0;return{__init:m,isOpen:function(){return this.__internal.isOpen},isModal:function(){return this.elements.root.className.indexOf(Ca.modeless)<0},isMaximized:function(){return this.elements.root.className.indexOf(Ca.maximized)>-1},isPinned:function(){return this.elements.root.className.indexOf(Ca.unpinned)<0},maximize:function(){return this.isMaximized()||I(this),this},restore:function(){return this.isMaximized()&&J(this),this},pin:function(){return this.isPinned()||G(this),this},unpin:function(){return this.isPinned()&&H(this),this},bringToFront:function(){return B(null,this),this},moveTo:function(a,b){if(!isNaN(a)&&!isNaN(b)){l("onmove",this);var c=this.elements.dialog,e=c,f=0,g=0;c.style.left&&(f-=parseInt(c.style.left,10)),c.style.top&&(g-=parseInt(c.style.top,10));do f+=e.offsetLeft,g+=e.offsetTop;while(e=e.offsetParent);var h=a-f,i=b-g;d()&&(h*=-1),c.style.left=h+"px",c.style.top=i+"px",l("onmoved",this)}return this},resizeTo:function(a,b){var c=parseFloat(a),d=parseFloat(b),e=/(\d*\.\d+|\d+)%/;if(!isNaN(c)&&!isNaN(d)&&this.get("resizable")===!0){l("onresize",this),(""+a).match(e)&&(c=c/100*document.documentElement.clientWidth),(""+b).match(e)&&(d=d/100*document.documentElement.clientHeight);var f=this.elements.dialog;"none"!==f.style.maxWidth&&(f.style.minWidth=(Sa=f.offsetWidth)+"px"),f.style.maxWidth="none",f.style.minHeight=this.elements.header.offsetHeight+this.elements.footer.offsetHeight+"px",f.style.width=c+"px",f.style.height=d+"px",l("onresized",this)}return this},setting:function(a,b){var c=this,d=D(this,this.__internal.options,function(a,b,d){C(c,a,b,d)},a,b);if("get"===d.op)return d.found?d.value:"undefined"!=typeof this.settings?D(this,this.settings,this.settingUpdated||function(){},a,b).value:void 0;if("set"===d.op){if(d.items.length>0)for(var e=this.settingUpdated||function(){},f=0;f<d.items.length;f+=1){var g=d.items[f];g.found||"undefined"==typeof this.settings||D(this,this.settings,e,g.key,g.value)}return this}},set:function(a,b){return this.setting(a,b),this},get:function(a){return this.setting(a)},setHeader:function(b){return"string"==typeof b?(g(this.elements.header),this.elements.header.innerHTML=b):b instanceof a.HTMLElement&&this.elements.header.firstChild!==b&&(g(this.elements.header),this.elements.header.appendChild(b)),this},setContent:function(b){return"string"==typeof b?(g(this.elements.content),this.elements.content.innerHTML=b):b instanceof a.HTMLElement&&this.elements.content.firstChild!==b&&(g(this.elements.content),this.elements.content.appendChild(b)),this},showModal:function(a){return this.show(!0,a)},show:function(a,d){if(m(this),this.__internal.isOpen){da(this),ja(this),b(this.elements.dialog,Ca.shake);var e=this;setTimeout(function(){c(e.elements.dialog,Ca.shake)},200)}else{if(this.__internal.isOpen=!0,p.push(this),v.defaults.maintainFocus&&(this.__internal.activeElement=document.activeElement),"function"==typeof this.prepare&&this.prepare(),ma(this),void 0!==a&&this.set("modal",a),o(),u(),"string"==typeof d&&""!==d&&(this.__internal.className=d,b(this.elements.root,d)),this.get("startMaximized")?this.maximize():this.isMaximized()&&J(this),N(this),c(this.elements.root,Ca.animationOut),b(this.elements.root,Ca.animationIn),clearTimeout(this.__internal.timerIn),this.__internal.timerIn=setTimeout(this.__internal.transitionInHandler,s.supported?1e3:100),Aa){var f=this.elements.root;f.style.display="none",setTimeout(function(){f.style.display="block"},0)}za=this.elements.root.offsetWidth,c(this.elements.root,Ca.hidden),"function"==typeof this.hooks.onshow&&this.hooks.onshow.call(this),l("onshow",this)}return this},close:function(){return this.__internal.isOpen&&(na(this),c(this.elements.root,Ca.animationIn),b(this.elements.root,Ca.animationOut),clearTimeout(this.__internal.timerOut),this.__internal.timerOut=setTimeout(this.__internal.transitionOutHandler,s.supported?1e3:100),b(this.elements.root,Ca.hidden),za=this.elements.modal.offsetWidth,"undefined"!=typeof this.__internal.className&&""!==this.__internal.className&&c(this.elements.root,this.__internal.className),"function"==typeof this.hooks.onclose&&this.hooks.onclose.call(this),l("onclose",this),p.splice(p.indexOf(this),1),this.__internal.isOpen=!1,u()),this},closeOthers:function(){return v.closeAll(this),this},destroy:function(){return this.__internal.isOpen?(this.__internal.destroy=function(){i(this,m)},this.close()):i(this,m),this}}}(),u=function(){function d(a){a.__internal||(a.__internal={position:v.defaults.notifier.position,delay:v.defaults.notifier.delay},l=document.createElement("DIV"),h(a)),l.parentNode!==document.body&&document.body.appendChild(l)}function e(a){a.__internal.pushed=!0,m.push(a)}function f(a){m.splice(m.indexOf(a),1),a.__internal.pushed=!1}function h(a){switch(l.className=n.base,a.__internal.position){case"top-right":b(l,n.top+" "+n.right);break;case"top-left":b(l,n.top+" "+n.left);break;case"bottom-left":b(l,n.bottom+" "+n.left);break;default:case"bottom-right":b(l,n.bottom+" "+n.right)}}function i(d,h){function i(a,b){b.dismiss(!0)}function m(a,b){r(b.element,s.type,m),l.removeChild(b.element)}function o(a){return a.__internal||(a.__internal={pushed:!1,delay:void 0,timer:void 0,clickHandler:void 0,transitionEndHandler:void 0,transitionTimeout:void 0},a.__internal.clickHandler=j(a,i),a.__internal.transitionEndHandler=j(a,m)),a}function p(a){clearTimeout(a.__internal.timer),clearTimeout(a.__internal.transitionTimeout)}return o({element:d,push:function(a,c){if(!this.__internal.pushed){e(this),p(this);var d,f;switch(arguments.length){case 0:f=this.__internal.delay;break;case 1:"number"==typeof a?f=a:(d=a,f=this.__internal.delay);break;case 2:d=a,f=c}return"undefined"!=typeof d&&this.setContent(d),u.__internal.position.indexOf("top")<0?l.appendChild(this.element):l.insertBefore(this.element,l.firstChild),k=this.element.offsetWidth,b(this.element,n.visible),q(this.element,"click",this.__internal.clickHandler),this.delay(f)}return this},ondismiss:function(){},callback:h,dismiss:function(a){return this.__internal.pushed&&(p(this),("function"!=typeof this.ondismiss||this.ondismiss.call(this)!==!1)&&(r(this.element,"click",this.__internal.clickHandler),"undefined"!=typeof this.element&&this.element.parentNode===l&&(this.__internal.transitionTimeout=setTimeout(this.__internal.transitionEndHandler,s.supported?1e3:100),c(this.element,n.visible),"function"==typeof this.callback&&this.callback.call(this,a)),f(this))),this},delay:function(a){if(p(this),this.__internal.delay="undefined"==typeof a||isNaN(+a)?u.__internal.delay:+a,this.__internal.delay>0){var b=this;this.__internal.timer=setTimeout(function(){b.dismiss()},1e3*this.__internal.delay)}return this},setContent:function(b){return"string"==typeof b?(g(this.element),this.element.innerHTML=b):b instanceof a.HTMLElement&&this.element.firstChild!==b&&(g(this.element),this.element.appendChild(b)),this},dismissOthers:function(){return u.dismissAll(this),this}})}var k,l,m=[],n={base:"alertify-notifier",message:"ajs-message",top:"ajs-top",right:"ajs-right",bottom:"ajs-bottom",left:"ajs-left",visible:"ajs-visible",hidden:"ajs-hidden"};return{setting:function(a,b){if(d(this),"undefined"==typeof b)return this.__internal[a];switch(a){case"position":this.__internal.position=b,h(this);break;case"delay":this.__internal.delay=b}return this},set:function(a,b){return this.setting(a,b),this},get:function(a){return this.setting(a)},create:function(a,b){d(this);var c=document.createElement("div");return c.className=n.message+("string"==typeof a&&""!==a?" ajs-"+a:""),i(c,b)},dismissAll:function(a){for(var b=m.slice(0),c=0;c<b.length;c+=1){var d=b[c];(void 0===a||a!==d)&&d.dismiss()}}}}(),v=new m;v.dialog("alert",function(){return{main:function(a,b,c){var d,e,f;switch(arguments.length){case 1:e=a;break;case 2:"function"==typeof b?(e=a,f=b):(d=a,e=b);break;case 3:d=a,e=b,f=c}return this.set("title",d),this.set("message",e),this.set("onok",f),this},setup:function(){return{buttons:[{text:v.defaults.glossary.ok,key:n.ESC,invokeOnClose:!0,className:v.defaults.theme.ok}],focus:{element:0,select:!1},options:{maximizable:!1,resizable:!1}}},build:function(){},prepare:function(){},setMessage:function(a){this.setContent(a)},settings:{message:void 0,onok:void 0,label:void 0},settingUpdated:function(a,b,c){switch(a){case"message":this.setMessage(c);break;case"label":this.__internal.buttons[0].element&&(this.__internal.buttons[0].element.innerHTML=c)}},callback:function(a){if("function"==typeof this.get("onok")){var b=this.get("onok").call(this,a);"undefined"!=typeof b&&(a.cancel=!b)}}}}),v.dialog("confirm",function(){function a(a){null!==c.timer&&(clearInterval(c.timer),c.timer=null,a.__internal.buttons[c.index].element.innerHTML=c.text)}function b(b,d,e){a(b),c.duration=e,c.index=d,c.text=b.__internal.buttons[d].element.innerHTML,c.timer=setInterval(j(b,c.task),1e3),c.task(null,b)}var c={timer:null,index:null,text:null,duration:null,task:function(b,d){if(d.isOpen()){if(d.__internal.buttons[c.index].element.innerHTML=c.text+" (&#8207;"+c.duration+"&#8207;) ",c.duration-=1,-1===c.duration){a(d);var e=d.__internal.buttons[c.index],f=k(c.index,e);"function"==typeof d.callback&&d.callback.apply(d,[f]),f.close!==!1&&d.close()}}else a(d)}};return{main:function(a,b,c,d){var e,f,g,h;switch(arguments.length){case 1:f=a;break;case 2:f=a,g=b;break;case 3:f=a,g=b,h=c;break;case 4:e=a,f=b,g=c,h=d}return this.set("title",e),this.set("message",f),this.set("onok",g),this.set("oncancel",h),this},setup:function(){return{buttons:[{text:v.defaults.glossary.ok,key:n.ENTER,className:v.defaults.theme.ok},{text:v.defaults.glossary.cancel,key:n.ESC,invokeOnClose:!0,className:v.defaults.theme.cancel}],focus:{element:0,select:!1},options:{maximizable:!1,resizable:!1}}},build:function(){},prepare:function(){},setMessage:function(a){this.setContent(a)},settings:{message:null,labels:null,onok:null,oncancel:null,defaultFocus:null,reverseButtons:null},settingUpdated:function(a,b,c){switch(a){case"message":this.setMessage(c);
  3 +break;case"labels":"ok"in c&&this.__internal.buttons[0].element&&(this.__internal.buttons[0].text=c.ok,this.__internal.buttons[0].element.innerHTML=c.ok),"cancel"in c&&this.__internal.buttons[1].element&&(this.__internal.buttons[1].text=c.cancel,this.__internal.buttons[1].element.innerHTML=c.cancel);break;case"reverseButtons":c===!0?this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element):this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);break;case"defaultFocus":this.__internal.focus.element="ok"===c?0:1}},callback:function(b){a(this);var c;switch(b.index){case 0:"function"==typeof this.get("onok")&&(c=this.get("onok").call(this,b),"undefined"!=typeof c&&(b.cancel=!c));break;case 1:"function"==typeof this.get("oncancel")&&(c=this.get("oncancel").call(this,b),"undefined"!=typeof c&&(b.cancel=!c))}},autoOk:function(a){return b(this,0,a),this},autoCancel:function(a){return b(this,1,a),this}}}),v.dialog("prompt",function(){var b=document.createElement("INPUT"),c=document.createElement("P");return{main:function(a,b,c,d,e){var f,g,h,i,j;switch(arguments.length){case 1:g=a;break;case 2:g=a,h=b;break;case 3:g=a,h=b,i=c;break;case 4:g=a,h=b,i=c,j=d;break;case 5:f=a,g=b,h=c,i=d,j=e}return this.set("title",f),this.set("message",g),this.set("value",h),this.set("onok",i),this.set("oncancel",j),this},setup:function(){return{buttons:[{text:v.defaults.glossary.ok,key:n.ENTER,className:v.defaults.theme.ok},{text:v.defaults.glossary.cancel,key:n.ESC,invokeOnClose:!0,className:v.defaults.theme.cancel}],focus:{element:b,select:!0},options:{maximizable:!1,resizable:!1}}},build:function(){b.className=v.defaults.theme.input,b.setAttribute("type","text"),b.value=this.get("value"),this.elements.content.appendChild(c),this.elements.content.appendChild(b)},prepare:function(){},setMessage:function(b){"string"==typeof b?(g(c),c.innerHTML=b):b instanceof a.HTMLElement&&c.firstChild!==b&&(g(c),c.appendChild(b))},settings:{message:void 0,labels:void 0,onok:void 0,oncancel:void 0,value:"",type:"text",reverseButtons:void 0},settingUpdated:function(a,c,d){switch(a){case"message":this.setMessage(d);break;case"value":b.value=d;break;case"type":switch(d){case"text":case"color":case"date":case"datetime-local":case"email":case"month":case"number":case"password":case"search":case"tel":case"time":case"week":b.type=d;break;default:b.type="text"}break;case"labels":d.ok&&this.__internal.buttons[0].element&&(this.__internal.buttons[0].element.innerHTML=d.ok),d.cancel&&this.__internal.buttons[1].element&&(this.__internal.buttons[1].element.innerHTML=d.cancel);break;case"reverseButtons":d===!0?this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element):this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element)}},callback:function(a){var c;switch(a.index){case 0:this.settings.value=b.value,"function"==typeof this.get("onok")&&(c=this.get("onok").call(this,a,this.settings.value),"undefined"!=typeof c&&(a.cancel=!c));break;case 1:"function"==typeof this.get("oncancel")&&(c=this.get("oncancel").call(this,a),"undefined"!=typeof c&&(a.cancel=!c)),a.cancel||(b.value=this.settings.value)}}}}),"object"==typeof module&&"object"==typeof module.exports?module.exports=v:"function"==typeof define&&define.amd?define([],function(){return v}):a.alertify||(a.alertify=v)}("undefined"!=typeof window?window:this);
0 \ No newline at end of file 4 \ No newline at end of file
core/templates/base.html
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 8
9 <meta http-equiv="Cache-Control" content="no-cache, no-store" /> 9 <meta http-equiv="Cache-Control" content="no-cache, no-store" />
10 <link href="{% static 'img/favicon.ico' %}" rel="shortcut icon" /> 10 <link href="{% static 'img/favicon.ico' %}" rel="shortcut icon" />
11 - 11 +
12 <!-- Roboto font --> 12 <!-- Roboto font -->
13 <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css"> 13 <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
14 <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> 14 <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
@@ -18,15 +18,18 @@ @@ -18,15 +18,18 @@
18 <script type="text/javascript" src="{% static 'js/vendor/jquery-ui.js' %}"></script> 18 <script type="text/javascript" src="{% static 'js/vendor/jquery-ui.js' %}"></script>
19 19
20 <!-- Bootstrap and themes (material) --> 20 <!-- Bootstrap and themes (material) -->
21 - <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/bootstrap.min.css' %}"> 21 + <link rel="stylesheet" type="text/css" href="{% static 'bootstrap-3.3.7/css/bootstrap.css' %}">
22 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/material.min.css' %}"> 22 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/material.min.css' %}">
23 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/ripples.min.css' %}"> 23 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/ripples.min.css' %}">
24 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/datepicker.css' %}"> 24 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/datepicker.css' %}">
25 - <script type="text/javascript" src="{% static 'js/vendor/bootstrap.min.js' %}"></script> 25 + <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/alertifyjs/alertify.min.css' %}">
  26 + <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/alertifyjs/themes/bootstrap.css' %}">
  27 + <script type="text/javascript" src="{% static 'bootstrap-3.3.7/js/bootstrap.js' %}"></script>
26 <script type="text/javascript" src="{% static 'js/vendor/bootstrap-acessibility.min.js' %}"></script> 28 <script type="text/javascript" src="{% static 'js/vendor/bootstrap-acessibility.min.js' %}"></script>
27 <script type="text/javascript" src="{% static 'js/vendor/material.min.js' %}"></script> 29 <script type="text/javascript" src="{% static 'js/vendor/material.min.js' %}"></script>
28 <script type="text/javascript" src="{% static 'js/vendor/ripples.min.js' %}"></script> 30 <script type="text/javascript" src="{% static 'js/vendor/ripples.min.js' %}"></script>
29 <script type="text/javascript" src="{% static 'js/vendor/bootstrap-datepicker.js' %}"></script> 31 <script type="text/javascript" src="{% static 'js/vendor/bootstrap-datepicker.js' %}"></script>
  32 + <script type="text/javascript" src="{% static 'js/vendor/alertify.min.js' %}"></script>
30 33
31 <!-- Font awesome --> 34 <!-- Font awesome -->
32 <link rel="stylesheet" type="text/css" href="{% static 'font-awesome-4.6.3/css/font-awesome.min.css' %}"> 35 <link rel="stylesheet" type="text/css" href="{% static 'font-awesome-4.6.3/css/font-awesome.min.css' %}">
@@ -38,6 +41,8 @@ @@ -38,6 +41,8 @@
38 <script type="text/javascript">$.material.init()</script> 41 <script type="text/javascript">$.material.init()</script>
39 42
40 <!--Javascript block for specific-app ones --> 43 <!--Javascript block for specific-app ones -->
  44 + <script src="{% static 'js/main.js' %}"></script>
  45 + <script src="{% static 'js/base/amadeus.js' %}"></script>
41 {% block style %} 46 {% block style %}
42 {% endblock %} 47 {% endblock %}
43 </head> 48 </head>
@@ -57,44 +62,14 @@ @@ -57,44 +62,14 @@
57 <div class="navbar-collapse collapse navbar-responsive-collapse"> 62 <div class="navbar-collapse collapse navbar-responsive-collapse">
58 <ul class="nav navbar-nav navbar-right notifications"> 63 <ul class="nav navbar-nav navbar-right notifications">
59 <li class="" data-toggle="tooltip" data-placement="bottom" title data-original-title="notifications"> 64 <li class="" data-toggle="tooltip" data-placement="bottom" title data-original-title="notifications">
60 - <a class="dropdown-toggle" data-toggle="dropdown"> <span class="badge notification-count">{{notifications.count}}</span><i class="fa fa-bell" aria-hidden="true"></i></a> 65 + <a class="dropdown-toggle" data-toggle="dropdown"> <span id="notification-count" class="badge notification-count">{{notifications.count}}</span><i class="fa fa-bell" aria-hidden="true"></i></a>
61 <ul id="notification-dropdown" class="dropdown-menu"> 66 <ul id="notification-dropdown" class="dropdown-menu">
62 <li class="dropdown-header">Notifications</li> 67 <li class="dropdown-header">Notifications</li>
63 - {% for notification in notifications %}  
64 - {% if notification.actor %} <!-- if the notification has a user-->  
65 - <li>  
66 - <a href="{% url 'core:notification_read' notification.id %}"><div class="list-group-item">  
67 - <div class="row-picture">  
68 - <img class="circle" src="http://lorempixel.com/56/56/people/1" alt="icon">  
69 - <div class="least-content pull-right">{{ notification.datetime }}</div>  
70 - </div>  
71 - <div class="row-content">  
72 - <p class="list-group-item-text">{{ notification.message }}</p>  
73 - </div>  
74 - </div>  
75 - </a>  
76 - </li>  
77 - {% else %}  
78 - <li>  
79 - <a href="{% url 'core:notification_read' notification.id %}">  
80 - <div class="list-group-item">  
81 - <div class="row-action-primary">  
82 - <i class="material-icons">folder</i>  
83 - </div>  
84 - <div class="row-content">  
85 -  
86 - <div class="least-content pull-right">{{ notification.datetime }}</div>  
87 -  
88 - <p class="list-group-item-text">{{ notification.message }}</p>  
89 - </div>  
90 - </a>  
91 - </li>  
92 - {% endif %}  
93 - {% endfor %} 68 + {% include "notifications.html" %}
94 69
95 <li> 70 <li>
96 - <a>  
97 - <div class="list-group-item"> 71 + <a onclick="getNotifications(5)">
  72 + <div id="notification-see-more" class="list-group-item">
98 <div class="row-content"> 73 <div class="row-content">
99 <p class="list-group-item-text">See More</p> 74 <p class="list-group-item-text">See More</p>
100 </div> 75 </div>
@@ -141,8 +116,6 @@ @@ -141,8 +116,6 @@
141 </div> 116 </div>
142 </div> 117 </div>
143 </div> 118 </div>
144 -  
145 -  
146 </div> 119 </div>
147 </div> 120 </div>
148 </body> 121 </body>
core/templates/index.html
@@ -59,7 +59,7 @@ @@ -59,7 +59,7 @@
59 </div> 59 </div>
60 </form> 60 </form>
61 <div class="col-md-10 col-sm-10 col-xs-10 col-lg-10"> 61 <div class="col-md-10 col-sm-10 col-xs-10 col-lg-10">
62 - <a href="{% url 'core:remember_password' %}">{% trans "Forgot your password?" %}</a> 62 + <a href="{% url 'core:password_reset' %}">{% trans "Forgot your password?" %}</a>
63 </div> 63 </div>
64 {# </div> #} 64 {# </div> #}
65 {# <div class="row"> #} 65 {# <div class="row"> #}
core/templates/notifications.html 0 → 100644
@@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
  1 +
  2 +<!-- This templates is responsible to display the list of notifications at the top of the page. -->
  3 +{% for notification in notifications %}
  4 + {% if notification.actor %} <!-- if the notification has a user-->
  5 + <li>
  6 + <a href="{% url 'core:notification_read' notification.id %}"><div class="list-group-item">
  7 + <div class="row-picture">
  8 + <img class="circle" src="http://lorempixel.com/56/56/people/1" alt="icon">
  9 + <div class="least-content pull-right">{{ notification.datetime }}</div>
  10 + </div>
  11 + <div class="row-content">
  12 + <p class="list-group-item-text">{{ notification.message }}</p>
  13 + </div>
  14 + </div>
  15 + </a>
  16 + </li>
  17 + {% else %}
  18 + <li>
  19 + <a href="{% url 'core:notification_read' notification.id %}">
  20 + <div class="list-group-item">
  21 + <div class="row-action-primary">
  22 + <i class="material-icons">folder</i>
  23 + </div>
  24 + <div class="row-content">
  25 +
  26 + <div class="least-content pull-right">{{ notification.datetime }}</div>
  27 +
  28 + <p class="list-group-item-text">{{ notification.message }}</p>
  29 + </div>
  30 + </a>
  31 + </li>
  32 + {% endif %}
  33 +{% endfor %}
0 \ No newline at end of file 34 \ No newline at end of file
core/templates/register_user.html
@@ -8,11 +8,16 @@ @@ -8,11 +8,16 @@
8 8
9 9
10 {% block content %} 10 {% block content %}
11 - {% if message %}  
12 - <div class="alert alert-danger">  
13 - {{message}}  
14 - </div>  
15 - {% endif %} 11 + {% if messages %}
  12 + {% for message in messages %}
  13 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  14 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  15 + <span aria-hidden="true">&times;</span>
  16 + </button>
  17 + <p>{{ message }}</p>
  18 + </div>
  19 + {% endfor %}
  20 + {% endif %}
16 <div class="row logo-row"> 21 <div class="row logo-row">
17 <div class="col-lg-offset-2 col-lg-9"> 22 <div class="col-lg-offset-2 col-lg-9">
18 <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus" id="logo"> 23 <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus" id="logo">
@@ -29,7 +34,11 @@ @@ -29,7 +34,11 @@
29 <legend>{% trans 'User Register' %}</legend> 34 <legend>{% trans 'User Register' %}</legend>
30 {% for field in form %} 35 {% for field in form %}
31 <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput"> 36 <div class="form-group is-empy{% if form.has_error %} has-error {% endif %} is-fileinput">
32 - <label for="{{ field.auto_id }}" class="col-md-4 control-label">{{ field.label }}</label> 37 + {% if field.field.required %}
  38 + <label for="{{ field.auto_id }}" class="col-md-4 control-label">{{ field.label }}<span>*</span></label>
  39 + {% else %}
  40 + <label for="{{ field.auto_id }}" class="col-md-4 control-label">{{ field.label }}</label>
  41 + {% endif %}
33 <div class="col-md-8"> 42 <div class="col-md-8">
34 {% if field.auto_id == 'id_birth_date' %} 43 {% if field.auto_id == 'id_birth_date' %}
35 {% render_field field class='form-control input-sm' type='date' %} 44 {% render_field field class='form-control input-sm' type='date' %}
@@ -81,5 +90,4 @@ @@ -81,5 +90,4 @@
81 </div> 90 </div>
82 91
83 <br clear="all" /> 92 <br clear="all" />
84 - <script src="{% static 'js/base/amadeus.js' %}"></script>  
85 {% endblock %} 93 {% endblock %}
core/templates/registration/passwor_reset_complete.html 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +{% extends "index.html" %}
  2 +{% load i18n static %}
  3 +
  4 +{% block content %}
  5 +
  6 + <div class="row">
  7 + <div class="col-md-4 col-md-offset-4 col-xs-4 col-xs-offset-4 col-sm-4 col-sm-offset-4 col-lg-4 col-lg-offset-4 col-xl-4 col-xl-offset-4">
  8 + <div class="row">
  9 + <div class="col-md-offset-2 col-md-8 col-sm-offset-2 col-sm-8 col-xs-offset-2 col-xs-8 col-lg-offset-2 col-lg-8 col-xs-offset-2 col-xs-8">
  10 + </br>
  11 + </br>
  12 + <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus">
  13 + </br>
  14 + </div>
  15 + </div>
  16 + </div>
  17 + <div class="row ">
  18 + <div class="col-lg-9 col-lg-offset-2 col-xs-9 col-xs-offset-2 col-sm-9 col-sm-offset-2 col-md-9 col-md-offset-2 col-xl-9 col-xl-offset-2">
  19 + <div class="card">
  20 + <div class="card-block">
  21 + <div class="col-md-12 col-xs-12 col-sm-12 col-lg-12 col-xl-12">
  22 + <form class="form-group " method="post" action="">
  23 + {% csrf_token %}
  24 + <div class="form-group is-empty">
  25 + <p>
  26 + Sua senha foi definida. Você pode ir em frente e entrar agora.
  27 + </p>
  28 + </div>
  29 + </form>
  30 + </div>
  31 + </div>
  32 + </div>
  33 + </div>
  34 + </div>
  35 + </div>
  36 +
  37 +{% endblock content %}
core/templates/registration/passwor_reset_confirm.html 0 → 100644
@@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
  1 +{% extends "index.html" %}
  2 +{% load i18n static %}
  3 +
  4 +{% block content%}
  5 +
  6 + <div class="row">
  7 + <div class="col-md-4 col-md-offset-4 col-xs-4 col-xs-offset-4 col-sm-4 col-sm-offset-4 col-lg-4 col-lg-offset-4 col-xl-4 col-xl-offset-4">
  8 + <div class="row">
  9 + <div class="col-md-offset-2 col-md-8 col-sm-offset-2 col-sm-8 col-xs-offset-2 col-xs-8 col-lg-offset-2 col-lg-8 col-xs-offset-2 col-xs-8">
  10 + </br>
  11 + </br>
  12 + <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus">
  13 + </br>
  14 + </div>
  15 + </div>
  16 + </div>
  17 + <div class="row ">
  18 + <div class="col-lg-9 col-lg-offset-2 col-xs-9 col-xs-offset-2 col-sm-9 col-sm-offset-2 col-md-9 col-md-offset-2 col-xl-9 col-xl-offset-2">
  19 +
  20 +
  21 + {% if validlink %}
  22 + <h3>Nova Senha</h3>
  23 + <form method="post">
  24 + {% csrf_token %}
  25 + {{ form.new_password1.erros }}
  26 + <label for="id_password1"> Nova Senha: </label>
  27 + {form.new_password1}
  28 +
  29 + {{ form.new_password2.erros }}
  30 + <label for="id_password2"> Confirmar Senha: </label>
  31 + {form.new_password2}
  32 +
  33 +
  34 + <button type="submit">Confirmar</button>
  35 + </form>
  36 +
  37 + {% else %}
  38 + <p>
  39 + O link de redefinição de senha está inválido, possivelmente porque ele já foi utilizado.
  40 + Por favor, solicite uma nova redefinição de senha.
  41 + </p>
  42 + {% endif %}
  43 +
  44 + </div>
  45 + </div>
  46 +</div>
  47 +
  48 +{% endblock content %}
core/templates/registration/passwor_reset_done.html 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +{% extends "index.html" %}
  2 +{% load i18n static %}
  3 +
  4 +{% block content %}
  5 +
  6 + <div class="row">
  7 + <div class="col-md-4 col-md-offset-4 col-xs-4 col-xs-offset-4 col-sm-4 col-sm-offset-4 col-lg-4 col-lg-offset-4 col-xl-4 col-xl-offset-4">
  8 + <div class="row">
  9 + <div class="col-md-offset-2 col-md-8 col-sm-offset-2 col-sm-8 col-xs-offset-2 col-xs-8 col-lg-offset-2 col-lg-8 col-xs-offset-2 col-xs-8">
  10 + </br>
  11 + </br>
  12 + <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus">
  13 + </br>
  14 + </div>
  15 + </div>
  16 + </div>
  17 + <div class="row ">
  18 + <div class="col-lg-9 col-lg-offset-2 col-xs-9 col-xs-offset-2 col-sm-9 col-sm-offset-2 col-md-9 col-md-offset-2 col-xl-9 col-xl-offset-2">
  19 + <div class="card">
  20 + <div class="card-block">
  21 + <div class="col-md-12 col-xs-12 col-sm-12 col-lg-12 col-xl-12">
  22 + <form class="form-group " method="post" action="">
  23 + {% csrf_token %}
  24 + <div class="form-group is-empty">
  25 + <p>
  26 + Temos enviado instruções para configurar sua senha, se uma conta existe com o e-mail inserido.
  27 + Você deve recebê-los em breve.
  28 + </p>
  29 + <p>
  30 + Se você não receber um e-mail, por favor, certifique-se de que introduziu o endereço que você registrou,
  31 + e verifique a pasta de spam.
  32 + </p>
  33 + </div>
  34 + </form>
  35 + </div>
  36 + </div>
  37 + </div>
  38 + </div>
  39 + </div>
  40 +
  41 +{% endblock %}
core/templates/registration/passwor_reset_email.html 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +To initiate the password reset process for your {{ user.get_username }} TestSite Account,
  2 +click the link below:
  3 +
  4 +{% block reset_link %}
  5 +{{ protocol }}://{{ domain }}{% url 'core:passwor_reset_confirm' uidb36=uid token=token %}
  6 +
  7 +{% endblock %}
  8 +
  9 +If clicking the link above doesn't work, please copy and paste the URL in a new browser
  10 +window instead.
  11 +
  12 +
  13 +Sincerely,
  14 +Amadeus.
core/templates/registration/passwor_reset_form.html 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +{% extends "index.html" %}
  2 +{% load i18n static %}
  3 +
  4 +{% block content %}
  5 +
  6 + <div class="row">
  7 + < <div class="col-md-4 col-md-offset-4 col-xs-4 col-xs-offset-4 col-sm-4 col-sm-offset-4 col-lg-4 col-lg-offset-4 col-xl-4 col-xl-offset-4">
  8 + <div class="row">
  9 + <div class="col-md-offset-2 col-md-8 col-sm-offset-2 col-sm-8 col-xs-offset-2 col-xs-8 col-lg-offset-2 col-lg-8 col-xs-offset-2 col-xs-8">
  10 + </br>
  11 + </br>
  12 + <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus">
  13 + </br>
  14 + </div>
  15 + </div>
  16 + </div>
  17 + <div class="row ">
  18 + <div class="col-lg-9 col-lg-offset-2 col-xs-9 col-xs-offset-2 col-sm-9 col-sm-offset-2 col-md-9 col-md-offset-2 col-xl-9 col-xl-offset-2">
  19 +
  20 +
  21 + <h3>Recuperar a senha</h3>
  22 + <form method="post">
  23 + {% csrf_token %}
  24 + <label for="id_email">E-mail: </label> {{ form.email }}
  25 + <input type="submit" value="Enviar" /></p>
  26 + </form>
  27 +
  28 + </div>
  29 + </div>
  30 + </div>
  31 +
  32 +{% endblock content %}
@@ -89,7 +89,7 @@ class RegisterUserTestCase(TestCase): @@ -89,7 +89,7 @@ class RegisterUserTestCase(TestCase):
89 } 89 }
90 90
91 response = self.client.post(self.url, data) 91 response = self.client.post(self.url, data)
92 - self.assertFormError(response, 'form', 'email', 'Insira um endereço de email válido.') 92 + self.assertFormError(response, 'form', 'email', 'Enter a valid email address.')
93 93
94 data = { 94 data = {
95 'username': '', 95 'username': '',
@@ -102,7 +102,7 @@ class RegisterUserTestCase(TestCase): @@ -102,7 +102,7 @@ class RegisterUserTestCase(TestCase):
102 'gender': 'F', 102 'gender': 'F',
103 } 103 }
104 response = self.client.post(self.url, data) 104 response = self.client.post(self.url, data)
105 - self.assertFormError(response, 'form', 'username', 'Este campo é obrigatório.') 105 + self.assertFormError(response, 'form', 'username', 'This field is required.')
106 106
107 class RememberPasswordTestCase(TestCase): 107 class RememberPasswordTestCase(TestCase):
108 108
@@ -194,7 +194,7 @@ class UpdateUserTestCase(TestCase): @@ -194,7 +194,7 @@ class UpdateUserTestCase(TestCase):
194 'gender': 'F', 194 'gender': 'F',
195 } 195 }
196 response = self.client.post(self.url, data) 196 response = self.client.post(self.url, data)
197 - self.assertFormError(response, 'form', 'username', 'Este campo é obrigatório.') 197 + self.assertFormError(response, 'form', 'username', 'This field is required.')
198 198
199 199
200 class DeleteUserTestCase(TestCase): 200 class DeleteUserTestCase(TestCase):
1 from django.conf.urls import url, include 1 from django.conf.urls import url, include
2 from django.contrib.auth import views as auth_views 2 from django.contrib.auth import views as auth_views
  3 +from django.contrib.auth.views import password_reset, password_reset_done,password_reset_confirm, password_reset_complete
3 4
4 from . import views 5 from . import views
5 6
@@ -9,5 +10,12 @@ urlpatterns = [ @@ -9,5 +10,12 @@ urlpatterns = [
9 url(r'^register/$', views.RegisterUser.as_view(), name='register'), 10 url(r'^register/$', views.RegisterUser.as_view(), name='register'),
10 url(r'^remember_password/$', views.remember_password, name='remember_password'), 11 url(r'^remember_password/$', views.remember_password, name='remember_password'),
11 url(r'^logout/$', auth_views.logout, {'next_page': 'core:home'}, name='logout'), 12 url(r'^logout/$', auth_views.logout, {'next_page': 'core:home'}, name='logout'),
12 - url(r'^notification/([0-9]+)/$', views.processNotification, name='notification_read') 13 + url(r'^notification/([0-9]+)/$', views.processNotification, name='notification_read'),
  14 + url(r'^getNotifications/$', views.getNotifications, name='getNotifications'),
  15 +
  16 + url(r'^reset/$', password_reset, {'template_name':'registration/passwor_reset_form.html','email_template_name':'registration/password_reset_email.html','post_reset_redirect':'done/'}, name="password_reset"),
  17 + url(r'^reset/done/$', password_reset_done, {'template_name':'registration/passwor_reset_done.html'}),
  18 + url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', password_reset_confirm, {'template_name':'registration/password_reset_confirm.html'}),
  19 + url(r'^done/$', password_reset_complete,{'template_name':'registration/passwor_reset_complete.html'}),
  20 +
13 ] 21 ]
@@ -5,8 +5,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin @@ -5,8 +5,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin
5 from .decorators import log_decorator 5 from .decorators import log_decorator
6 from django.contrib import messages 6 from django.contrib import messages
7 from django.shortcuts import render, redirect 7 from django.shortcuts import render, redirect
  8 +from django.template.loader import render_to_string
8 from django.views.generic import CreateView, UpdateView 9 from django.views.generic import CreateView, UpdateView
9 -from django.http import HttpResponse 10 +from django.http import HttpResponse, JsonResponse
10 from django.core.mail import send_mail,BadHeaderError 11 from django.core.mail import send_mail,BadHeaderError
11 from django.conf import settings 12 from django.conf import settings
12 from core.mixins import NotificationMixin 13 from core.mixins import NotificationMixin
@@ -95,6 +96,28 @@ def processNotification(self, notificationId): @@ -95,6 +96,28 @@ def processNotification(self, notificationId):
95 notification.save() 96 notification.save()
96 return redirect(notification.action_resource.resource.url) 97 return redirect(notification.action_resource.resource.url)
97 98
  99 +
  100 +
  101 +
  102 +def getNotifications(request):
  103 + context = {}
  104 + if request.user.is_authenticated:
  105 +
  106 + steps = int(request.GET['steps'])
  107 + amount = int(request.GET['amount'])
  108 + notifications = Notification.objects.filter(user= request.user, read=False).order_by('-datetime')[steps:steps+amount]
  109 + context['notifications'] = notifications
  110 + else: #go to login page
  111 + return HttpResponse('teste')
  112 +
  113 +
  114 + html = render_to_string("notifications.html", context)
  115 + print(html)
  116 + return HttpResponse(html)
  117 +
  118 +
  119 +
  120 +
98 # class LoginClass(LoginView): 121 # class LoginClass(LoginView):
99 # template_name='index.html' 122 # template_name='index.html'
100 # 123 #
courses/admin.py
1 from django.contrib import admin 1 from django.contrib import admin
2 2
3 -from .models import Category, Course, Subject,Topic 3 +from .models import Category, Course, Subject,Topic, Activity, Material
4 4
5 class CategoryAdmin(admin.ModelAdmin): 5 class CategoryAdmin(admin.ModelAdmin):
6 list_display = ['name', 'slug'] 6 list_display = ['name', 'slug']
@@ -18,7 +18,17 @@ class TopicAdmin(admin.ModelAdmin): @@ -18,7 +18,17 @@ class TopicAdmin(admin.ModelAdmin):
18 list_display = ['name', 'slug'] 18 list_display = ['name', 'slug']
19 search_fields = ['name', 'slug'] 19 search_fields = ['name', 'slug']
20 20
  21 +class ActivityAdmin(admin.ModelAdmin):
  22 + list_display = ['name', 'slug']
  23 + search_fields = ['name', 'slug']
  24 +
  25 +class MaterialAdmin(admin.ModelAdmin):
  26 + list_display = ['name', 'slug']
  27 + search_fields = ['name', 'slug']
  28 +
21 admin.site.register(Category, CategoryAdmin) 29 admin.site.register(Category, CategoryAdmin)
22 admin.site.register(Course, CourseAdmin) 30 admin.site.register(Course, CourseAdmin)
23 admin.site.register(Subject, SubjectAdmin) 31 admin.site.register(Subject, SubjectAdmin)
24 admin.site.register(Topic, TopicAdmin) 32 admin.site.register(Topic, TopicAdmin)
  33 +admin.site.register(Activity,ActivityAdmin)
  34 +admin.site.register(Material,MaterialAdmin)
courses/forms.py
1 -  
2 from django import forms 1 from django import forms
3 from django.utils.translation import ugettext_lazy as _ 2 from django.utils.translation import ugettext_lazy as _
4 -from .models import Category, Course, Subject, Topic 3 +from .models import Category, Course, Subject, Topic, ActivityFile, Activity
  4 +from s3direct.widgets import S3DirectWidget
5 5
6 6
7 class CategoryForm(forms.ModelForm): 7 class CategoryForm(forms.ModelForm):
@@ -153,3 +153,38 @@ class TopicForm(forms.ModelForm): @@ -153,3 +153,38 @@ class TopicForm(forms.ModelForm):
153 'name': _("Topic's name"), 153 'name': _("Topic's name"),
154 'description': _("Topic's description"), 154 'description': _("Topic's description"),
155 } 155 }
  156 +
  157 +class ActivityFileForm(forms.ModelForm):
  158 + name = forms.CharField(
  159 + required=False,
  160 + max_length=100,
  161 + widget=forms.TextInput(attrs={
  162 + 'placeholder': 'Nome',
  163 + 'class': 'form-control'
  164 + },
  165 + )
  166 + )
  167 + pdf = forms.URLField(required=True, widget=S3DirectWidget(
  168 + dest='activitys',
  169 + html=(
  170 + '<div class="s3direct" data-policy-url="{policy_url}">'
  171 + ' <a class="file-link" target="_blank" href="{file_url}">{file_name}</a>'
  172 + ' <a class="file-remove" href="#remove">Remover</a>'
  173 + ' <input class="file-url" type="hidden" value="{file_url}" id="{element_id}" name="{name}" />'
  174 + ' <input class="file-dest" type="hidden" value="{dest}">'
  175 + ' <input class="file-input" type="file" />'
  176 + ' <div class="progress">'
  177 + ' <div class="progress-bar progress-bar-success progress-bar-striped active bar">'
  178 + ' </div>'
  179 + ' </div>'
  180 + '</div>'
  181 + )))
  182 +
  183 + class Meta:
  184 + model = ActivityFile
  185 + fields = ['pdf','name']
  186 +
  187 +class ActivityForm(forms.ModelForm):
  188 + class Meta:
  189 + model = Activity
  190 + fields = ['topic', 'limit_date', 'students','all_students']
courses/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 -# Generated by Django 1.10 on 2016-09-22 05:46 2 +# Generated by Django 1.10 on 2016-10-02 00:17
3 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 import autoslug.fields 5 import autoslug.fields
6 -from django.conf import settings  
7 from django.db import migrations, models 6 from django.db import migrations, models
8 import django.db.models.deletion 7 import django.db.models.deletion
9 8
@@ -13,7 +12,6 @@ class Migration(migrations.Migration): @@ -13,7 +12,6 @@ class Migration(migrations.Migration):
13 initial = True 12 initial = True
14 13
15 dependencies = [ 14 dependencies = [
16 - migrations.swappable_dependency(settings.AUTH_USER_MODEL),  
17 ('core', '0001_initial'), 15 ('core', '0001_initial'),
18 ] 16 ]
19 17
@@ -22,9 +20,8 @@ class Migration(migrations.Migration): @@ -22,9 +20,8 @@ class Migration(migrations.Migration):
22 name='Activity', 20 name='Activity',
23 fields=[ 21 fields=[
24 ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), 22 ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')),
25 - ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),  
26 ('limit_date', models.DateTimeField(verbose_name='Deliver Date')), 23 ('limit_date', models.DateTimeField(verbose_name='Deliver Date')),
27 - ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='student')), 24 + ('all_students', models.BooleanField(default=False, verbose_name='All Students')),
28 ], 25 ],
29 bases=('core.resource',), 26 bases=('core.resource',),
30 ), 27 ),
@@ -37,8 +34,8 @@ class Migration(migrations.Migration): @@ -37,8 +34,8 @@ class Migration(migrations.Migration):
37 ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')), 34 ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')),
38 ], 35 ],
39 options={ 36 options={
40 - 'verbose_name_plural': 'Categories',  
41 'verbose_name': 'Category', 37 'verbose_name': 'Category',
  38 + 'verbose_name_plural': 'Categories',
42 }, 39 },
43 ), 40 ),
44 migrations.CreateModel( 41 migrations.CreateModel(
@@ -56,22 +53,18 @@ class Migration(migrations.Migration): @@ -56,22 +53,18 @@ class Migration(migrations.Migration):
56 ('init_date', models.DateField(verbose_name='Begin of Course Date')), 53 ('init_date', models.DateField(verbose_name='Begin of Course Date')),
57 ('end_date', models.DateField(verbose_name='End of Course Date')), 54 ('end_date', models.DateField(verbose_name='End of Course Date')),
58 ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')), 55 ('image', models.ImageField(blank=True, upload_to='courses/', verbose_name='Image')),
59 - ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Category', verbose_name='Category')),  
60 - ('professors', models.ManyToManyField(related_name='courses', to=settings.AUTH_USER_MODEL, verbose_name='Professors')),  
61 - ('students', models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students')),  
62 ], 56 ],
63 options={ 57 options={
64 - 'verbose_name_plural': 'Courses',  
65 'ordering': ('create_date', 'name'), 58 'ordering': ('create_date', 'name'),
66 'verbose_name': 'Course', 59 'verbose_name': 'Course',
  60 + 'verbose_name_plural': 'Courses',
67 }, 61 },
68 ), 62 ),
69 migrations.CreateModel( 63 migrations.CreateModel(
70 name='Material', 64 name='Material',
71 fields=[ 65 fields=[
72 ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')), 66 ('resource_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.Resource')),
73 - ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),  
74 - ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='student')), 67 + ('all_students', models.BooleanField(default=False, verbose_name='All Students')),
75 ], 68 ],
76 bases=('core.resource',), 69 bases=('core.resource',),
77 ), 70 ),
@@ -87,13 +80,24 @@ class Migration(migrations.Migration): @@ -87,13 +80,24 @@ class Migration(migrations.Migration):
87 ('end_date', models.DateField(verbose_name='End of Subject Date')), 80 ('end_date', models.DateField(verbose_name='End of Subject Date')),
88 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), 81 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),
89 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), 82 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')),
90 - ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course')),  
91 - ('professors', models.ManyToManyField(related_name='subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors')),  
92 ], 83 ],
93 options={ 84 options={
94 - 'verbose_name_plural': 'Subjects',  
95 'ordering': ('create_date', 'name'), 85 'ordering': ('create_date', 'name'),
96 'verbose_name': 'Subject', 86 'verbose_name': 'Subject',
  87 + 'verbose_name_plural': 'Subjects',
  88 + },
  89 + ),
  90 + migrations.CreateModel(
  91 + name='SubjectCategory',
  92 + fields=[
  93 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  94 + ('name', models.CharField(max_length=100, verbose_name='Name')),
  95 + ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')),
  96 + ('description', models.TextField(blank=True, verbose_name='Description')),
  97 + ],
  98 + options={
  99 + 'verbose_name': 'subject category',
  100 + 'verbose_name_plural': 'subject categories',
97 }, 101 },
98 ), 102 ),
99 migrations.CreateModel( 103 migrations.CreateModel(
@@ -106,23 +110,11 @@ class Migration(migrations.Migration): @@ -106,23 +110,11 @@ class Migration(migrations.Migration):
106 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')), 110 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),
107 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')), 111 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')),
108 ('visible', models.BooleanField(default=False, verbose_name='Visible')), 112 ('visible', models.BooleanField(default=False, verbose_name='Visible')),
109 - ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner')),  
110 - ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject')),  
111 ], 113 ],
112 options={ 114 options={
113 - 'verbose_name_plural': 'Topics',  
114 'ordering': ('create_date', 'name'), 115 'ordering': ('create_date', 'name'),
115 'verbose_name': 'Topic', 116 'verbose_name': 'Topic',
  117 + 'verbose_name_plural': 'Topics',
116 }, 118 },
117 ), 119 ),
118 - migrations.AddField(  
119 - model_name='material',  
120 - name='topic',  
121 - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Topic', verbose_name='Topic'),  
122 - ),  
123 - migrations.AddField(  
124 - model_name='activity',  
125 - name='topic',  
126 - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Topic', verbose_name='Topic'),  
127 - ),  
128 ] 120 ]
courses/migrations/0002_auto_20160926_0026.py
@@ -1,38 +0,0 @@ @@ -1,38 +0,0 @@
1 -# -*- coding: utf-8 -*-  
2 -# Generated by Django 1.10 on 2016-09-26 03:26  
3 -from __future__ import unicode_literals  
4 -  
5 -import autoslug.fields  
6 -from django.db import migrations, models  
7 -  
8 -  
9 -class Migration(migrations.Migration):  
10 -  
11 - dependencies = [  
12 - ('courses', '0001_initial'),  
13 - ]  
14 -  
15 - operations = [  
16 - migrations.CreateModel(  
17 - name='SubjectCategory',  
18 - fields=[  
19 - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),  
20 - ('name', models.CharField(max_length=100, verbose_name='Name')),  
21 - ('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name', unique=True, verbose_name='Slug')),  
22 - ('description', models.TextField(blank=True, verbose_name='Description')),  
23 - ('subjects', models.ManyToManyField(to='courses.Subject')),  
24 - ],  
25 - options={  
26 - 'verbose_name_plural': 'subject categories',  
27 - 'verbose_name': 'subject category',  
28 - },  
29 - ),  
30 - migrations.RemoveField(  
31 - model_name='activity',  
32 - name='create_date',  
33 - ),  
34 - migrations.RemoveField(  
35 - model_name='material',  
36 - name='create_date',  
37 - ),  
38 - ]  
courses/migrations/0002_auto_20161001_2117.py 0 → 100644
@@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-02 00:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + ('courses', '0001_initial'),
  16 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='topic',
  22 + name='owner',
  23 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='topic',
  27 + name='subject',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Subject', verbose_name='Subject'),
  29 + ),
  30 + migrations.AddField(
  31 + model_name='subjectcategory',
  32 + name='subjects',
  33 + field=models.ManyToManyField(to='courses.Subject'),
  34 + ),
  35 + migrations.AddField(
  36 + model_name='subject',
  37 + name='course',
  38 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='courses.Course', verbose_name='Course'),
  39 + ),
  40 + migrations.AddField(
  41 + model_name='subject',
  42 + name='professors',
  43 + field=models.ManyToManyField(related_name='subjects', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
  44 + ),
  45 + migrations.AddField(
  46 + model_name='material',
  47 + name='students',
  48 + field=models.ManyToManyField(related_name='materials', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  49 + ),
  50 + migrations.AddField(
  51 + model_name='material',
  52 + name='topic',
  53 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='materials', to='courses.Topic', verbose_name='Topic'),
  54 + ),
  55 + migrations.AddField(
  56 + model_name='course',
  57 + name='category',
  58 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Category', verbose_name='Category'),
  59 + ),
  60 + migrations.AddField(
  61 + model_name='course',
  62 + name='professors',
  63 + field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),
  64 + ),
  65 + migrations.AddField(
  66 + model_name='course',
  67 + name='students',
  68 + field=models.ManyToManyField(related_name='courses_student', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  69 + ),
  70 + migrations.AddField(
  71 + model_name='activity',
  72 + name='students',
  73 + field=models.ManyToManyField(related_name='activities', to=settings.AUTH_USER_MODEL, verbose_name='Students'),
  74 + ),
  75 + migrations.AddField(
  76 + model_name='activity',
  77 + name='topic',
  78 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='courses.Topic', verbose_name='Topic'),
  79 + ),
  80 + ]
courses/migrations/0003_activityfile.py 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-03 16:10
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +import django.db.models.deletion
  7 +import s3direct.fields
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + dependencies = [
  13 + ('courses', '0002_auto_20161001_2117'),
  14 + ]
  15 +
  16 + operations = [
  17 + migrations.CreateModel(
  18 + name='ActivityFile',
  19 + fields=[
  20 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  21 + ('pdf', s3direct.fields.S3DirectField()),
  22 + ('name', models.CharField(max_length=100)),
  23 + ('diet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='courses.Activity')),
  24 + ],
  25 + options={
  26 + 'verbose_name_plural': 'Activitys Files',
  27 + 'verbose_name': 'Activity File',
  28 + },
  29 + ),
  30 + ]
courses/migrations/0003_auto_20160927_1945.py
@@ -1,52 +0,0 @@ @@ -1,52 +0,0 @@
1 -# -*- coding: utf-8 -*-  
2 -# Generated by Django 1.10 on 2016-09-27 22:45  
3 -from __future__ import unicode_literals  
4 -  
5 -from django.conf import settings  
6 -from django.db import migrations, models  
7 -import django.db.models.deletion  
8 -  
9 -  
10 -class Migration(migrations.Migration):  
11 -  
12 - dependencies = [  
13 - ('courses', '0002_auto_20160926_0026'),  
14 - ]  
15 -  
16 - operations = [  
17 - migrations.CreateModel(  
18 - name='Answer',  
19 - fields=[  
20 - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),  
21 - ('answer', models.CharField(max_length=200, verbose_name='Answer')),  
22 - ('order', models.PositiveSmallIntegerField(verbose_name='Order')),  
23 - ],  
24 - options={  
25 - 'verbose_name_plural': 'Answers',  
26 - 'verbose_name': 'Answer',  
27 - 'ordering': ('order',),  
28 - },  
29 - ),  
30 - migrations.CreateModel(  
31 - name='Poll',  
32 - fields=[  
33 - ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')),  
34 - ('question', models.CharField(max_length=300, verbose_name='Question')),  
35 - ],  
36 - options={  
37 - 'verbose_name_plural': 'Polls',  
38 - 'verbose_name': 'Poll',  
39 - },  
40 - bases=('courses.activity',),  
41 - ),  
42 - migrations.AlterField(  
43 - model_name='course',  
44 - name='professors',  
45 - field=models.ManyToManyField(related_name='courses_professors', to=settings.AUTH_USER_MODEL, verbose_name='Professors'),  
46 - ),  
47 - migrations.AddField(  
48 - model_name='answer',  
49 - name='poll',  
50 - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='courses.Poll', verbose_name='Answers'),  
51 - ),  
52 - ]  
courses/models.py
@@ -3,6 +3,7 @@ from django.db import models @@ -3,6 +3,7 @@ from django.db import models
3 from autoslug.fields import AutoSlugField 3 from autoslug.fields import AutoSlugField
4 from users.models import User 4 from users.models import User
5 from core.models import Resource 5 from core.models import Resource
  6 +from s3direct.fields import S3DirectField
6 7
7 class Category(models.Model): 8 class Category(models.Model):
8 9
@@ -88,52 +89,40 @@ It is one kind of possible resources available inside a Topic. @@ -88,52 +89,40 @@ It is one kind of possible resources available inside a Topic.
88 Activity is something that has a deadline and has to be delivered by the student 89 Activity is something that has a deadline and has to be delivered by the student
89 """ 90 """
90 class Activity(Resource): 91 class Activity(Resource):
91 - topic = models.ForeignKey(Topic, verbose_name = _('Topic')) 92 + topic = models.ForeignKey(Topic, verbose_name = _('Topic'), related_name='activities')
92 limit_date = models.DateTimeField(_('Deliver Date')) 93 limit_date = models.DateTimeField(_('Deliver Date'))
93 - student = models.ForeignKey(User, verbose_name = _('student')) 94 + students = models.ManyToManyField(User, verbose_name = _('Students'), related_name='activities')
  95 + all_students = models.BooleanField(_('All Students'), default=False)
94 96
  97 +class ActivityFile(models.Model):
  98 + pdf = S3DirectField(dest='activitys')
  99 + diet = models.ForeignKey('Activity', related_name='files')
  100 + name = models.CharField(max_length=100)
  101 +
  102 + def __str__(self):
  103 + return self.name
  104 +
  105 + class Meta:
  106 + verbose_name = u"Activity File"
  107 + verbose_name_plural = u"Activitys Files"
95 108
96 """ 109 """
97 It represents any Material inside a topic, be it a file, a link, etc. 110 It represents any Material inside a topic, be it a file, a link, etc.
98 """ 111 """
99 class Material(Resource): 112 class Material(Resource):
100 - topic = models.ForeignKey(Topic, verbose_name = _('Topic'))  
101 - student = models.ForeignKey(User, verbose_name = _('student')) 113 + topic = models.ForeignKey(Topic, verbose_name = _('Topic'), related_name='materials')
  114 + students = models.ManyToManyField(User, verbose_name = _('Students'), related_name='materials')
  115 + all_students = models.BooleanField(_('All Students'), default=False)
102 116
103 """ 117 """
104 It is a category for each subject. 118 It is a category for each subject.
105 """ 119 """
106 class SubjectCategory(models.Model): 120 class SubjectCategory(models.Model):
107 name = models.CharField(_('Name'), max_length= 100) 121 name = models.CharField(_('Name'), max_length= 100)
108 - slug = AutoSlugField(_("Slug"),populate_from='name',unique=True) 122 + slug = AutoSlugField(_("Slug"),populate_from='name',unique=True)
109 description = models.TextField(_('Description'), blank = True) 123 description = models.TextField(_('Description'), blank = True)
110 subjects = models.ManyToManyField(Subject) 124 subjects = models.ManyToManyField(Subject)
111 125
112 class Meta: 126 class Meta:
113 verbose_name = _('subject category') 127 verbose_name = _('subject category')
114 verbose_name_plural = _('subject categories') 128 verbose_name_plural = _('subject categories')
115 -  
116 -class Poll(Activity):  
117 - question = models.CharField(_('Question'), max_length = 300)  
118 -  
119 - class Meta:  
120 - #ordering = ('create_date','name')  
121 - verbose_name = _('Poll')  
122 - verbose_name_plural = _('Polls')  
123 -  
124 - def __str__(self):  
125 - return str(self.question) + str("/") + str(self.topic)  
126 -  
127 -class Answer(models.Model):  
128 - answer = models.CharField(_("Answer"), max_length = 200)  
129 - order = models.PositiveSmallIntegerField(_("Order"))  
130 - poll = models.ForeignKey(Poll, verbose_name = _('Answers'), related_name='answers')  
131 -  
132 - class Meta:  
133 - ordering = ('order',)  
134 - verbose_name = _('Answer')  
135 - verbose_name_plural = _('Answers')  
136 -  
137 - def __str__(self):  
138 - return str(self.question) + str("/") + str(self.topic)  
139 -  
courses/templates/course/index.html
@@ -22,6 +22,23 @@ @@ -22,6 +22,23 @@
22 </ul> 22 </ul>
23 </div> 23 </div>
24 </div> 24 </div>
  25 +
  26 +{% if user|has_role:'professor, system_admin' %}
  27 +
  28 + <div class="panel panel-primary navigation">
  29 + <div class="panel-heading">
  30 + <h3 class="panel-title">Actions</h3>
  31 + </div>
  32 + <div class="panel-body">
  33 + <ul class="nav nav-pills nav-stacked">
  34 + <li><a href="javascript:void(0)">Replicate Course</a></li>
  35 + <li><a href="{% url 'course:create' %}">Create Course</a></li>
  36 + </ul>
  37 + </div>
  38 + </div>
  39 +
  40 +{% endif %}
  41 +
25 {% endblock %} 42 {% endblock %}
26 43
27 {% block content %} 44 {% block content %}
@@ -35,18 +52,101 @@ @@ -35,18 +52,101 @@
35 </div> 52 </div>
36 {% endfor %} 53 {% endfor %}
37 {% endif %} 54 {% endif %}
  55 +
  56 +{% if user|has_role:'professor, system_admin' %}
  57 +
  58 + <div class="col-md-12">
  59 + {% if courses_teacher|length > 0 %}
  60 + {% for course in courses_teacher %}
  61 + <!-- Put your content here! -->
  62 + <div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false">
  63 + <div class="group">
  64 + <div class="panel panel-info">
  65 + <div class="panel-heading headingOne ui-sortable-handle" role="tab">
  66 + <div class="row">
  67 + <div class="col-xs-9 col-md-10 titleTopic">
  68 + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseOne" aria-expanded="false" aria-controls="collapseOne" class="collapsed">
  69 + <h4>{{course.name}}</h4>
  70 + </a>
  71 + </div>
  72 + <div class="col-xs-4 col-md-2" id="divMoreActions">
  73 + <div class="btn-group">
  74 + <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
  75 + <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
  76 + </button>
  77 +
  78 + </div>
  79 + <div class="btn-group">
  80 + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  81 + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
  82 + </button>
  83 + <ul class="dropdown-menu" aria-labelledby="moreActions">
  84 + <li><a href="{% url 'course:view' course.slug %}"><i class="fa fa-angle-double-right fa-fw" aria-hidden="true"></i>&nbsp; Access</a></li>
  85 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal4"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; Replicate</a></li>
  86 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeCourse"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
  87 + </ul>
  88 + </div>
  89 + </div>
  90 + </div>
  91 + </div>
  92 + <div class="panel-collapse collapseOne collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true" aria-hidden="false" tabindex="0">
  93 + <div class="panel-body">
  94 + <p><b>Course Name: </b>{{course.name}}</p>
  95 + <p><b>Duration (in semesters): </b>09</p>
  96 + <p><b>Coordinator: </b>{{course.professors}}</p>
  97 + <p>
  98 + <b>Description:</b>
  99 + <i>
  100 + {{course.description}}
  101 + </i>
  102 + </p>
  103 +
  104 + </div>
  105 + </div>
  106 + </div>
  107 + </div>
  108 + </div>
  109 + {% endfor %}
  110 + {% else %}
  111 + {% trans 'No courses found' %}
  112 + {% endif %}
  113 + <div class="group">
  114 + <div class="modal" id="removeCourse">
  115 + <div class="modal-dialog">
  116 + <div class="modal-content">
  117 + <div class="modal-header">
  118 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
  119 + <h4 class="modal-title"></h4>
  120 + </div>
  121 + <div class="modal-body">
  122 + <p>Delete your course?</p>
  123 + </div>
  124 + <div class="modal-footer">
  125 +
  126 + <a href="http://127.0.0.1:8080/html/screens/users/profile_user.html" target="_self"><button type="button" class="btn btn-primary">Confirm</button></a>
  127 +
  128 + </div>
  129 + </div>
  130 + </div>
  131 + </div>
  132 + </div>
  133 + </div>
  134 +
  135 +{% else %}
  136 +
38 <div class="col-md-12"> 137 <div class="col-md-12">
39 <div class="input-group"> 138 <div class="input-group">
40 - <div class="form-group is-empty"><input type="search" class="form-control" placeholder="Search Courses"></div>  
41 - <span class="input-group-btn input-group-sm">  
42 - <button type="button" class="btn btn-fab btn-fab-mini">  
43 - <i class="material-icons">search</i>  
44 - </button>  
45 - </span>  
46 -</div> 139 + <div class="form-group is-empty"><input type="search" class="form-control" placeholder="Search Courses"></div>
  140 + <span class="input-group-btn input-group-sm">
  141 + <button type="button" class="btn btn-fab btn-fab-mini">
  142 + <i class="material-icons">search</i>
  143 + </button>
  144 + </span>
  145 + </div>
47 </div> 146 </div>
48 - {% if courses|length > 0 %}  
49 - {% for course in courses %} 147 +
  148 + {% if subjects_student|length > 0 %}
  149 + {% for course in courses_student %}
50 <div class="col-md-12"> 150 <div class="col-md-12">
51 <div class="panel panel-info"> 151 <div class="panel panel-info">
52 <!--{% if course.image %} 152 <!--{% if course.image %}
@@ -80,7 +180,6 @@ @@ -80,7 +180,6 @@
80 {% endif %} 180 {% endif %}
81 181
82 <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">View Course</a> 182 <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">View Course</a>
83 -  
84 </div> 183 </div>
85 </div> 184 </div>
86 </div> 185 </div>
@@ -100,4 +199,5 @@ @@ -100,4 +199,5 @@
100 {% else %} 199 {% else %}
101 {% trans 'No courses found' %} 200 {% trans 'No courses found' %}
102 {% endif %} 201 {% endif %}
  202 +{% endif %}
103 {% endblock %} 203 {% endblock %}
courses/templates/course/view.html
@@ -15,120 +15,206 @@ @@ -15,120 +15,206 @@
15 {% endblock %} 15 {% endblock %}
16 16
17 {% block sidebar %} 17 {% block sidebar %}
18 -<div class="panel panel-primary">  
19 - <div class="panel-heading">  
20 - <img src="{{ user.image_url }}" id="img" class="img-circle img-responsive">  
21 - </br>  
22 - <div class="row">  
23 - <div class="col-xs-3 col-md-3">  
24 - <i class="fa fa-facebook-official fa-2x" aria-hidden="true"></i> 18 + <div class="panel panel-primary navigation">
  19 + <div class="panel-heading">
  20 + <h5>{% trans 'Menu' %}</h5>
  21 + </div>
  22 + <div class="panel-body">
  23 + <ul class="nav nav-pills nav-stacked">
  24 + <li><a href="{% url 'users:profile' %}">{% trans 'Profile' %}</a></li>
  25 + <li><a href="{% url 'course:manage' %}">{% trans 'My Courses' %}</a></li>
  26 + </ul>
  27 + </div>
25 </div> 28 </div>
26 - <div class="col-xs-3 col-md-3">  
27 - <i class="fa fa-twitter fa-2x" aria-hidden="true"></i>  
28 - </div>  
29 - <div class="col-xs-3 col-md-3">  
30 - <i class="fa fa-linkedin-square fa-2x" aria-hidden="true"></i>  
31 - </div>  
32 - <div class="col-xs-3 col-md-3">  
33 - <i class="fa fa-google-plus-official fa-2x" aria-hidden="true"></i>  
34 - </div> 29 +
  30 +{% if user|has_role:'professor, system_admin' %}
  31 +
  32 + <div class="panel panel-primary navigation">
  33 + <div class="panel-heading">
  34 + <h3 class="panel-title">Actions</h3>
  35 + </div>
  36 + <div class="panel-body">
  37 + <ul class="nav nav-pills nav-stacked">
  38 + <li><a href="teacher/course_participants_teacher.html" target="_self">Participants</a></li>
  39 + <li><a href="javascript:void(0)">Replicate Subject</a></li>
  40 + <li><a href="javascript:void(0)">Create Subject</a></li>
  41 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal">Create Topic</a></li>
  42 + </ul>
35 </div> 43 </div>
36 - </div>  
37 - <div class="panel-body">  
38 - <ul class="nav nav-pills nav-stacked">  
39 - <li><a href="{% url 'app:index' %}">{% trans "Home" %}</a></li>  
40 - <li><a href="{% url 'users:profile' %}">{% trans "Profile" %}</a></li>  
41 - {# <li><a href="">{% trans "Courses" %}</a></li>#}  
42 - </ul>  
43 - </div>  
44 -</div>  
45 -{% if courses.count > 0 %}  
46 -<div class="panel panel-primary">  
47 - <div class="panel-heading">  
48 - <h5>{% trans "Courses" %}</h5>  
49 - </div>  
50 - <div class="panel-body">  
51 - <ul class="nav nav-pills nav-stacked">  
52 - {% for course in courses %}  
53 - <li><a href="{% url 'course:view' course.slug %}">{{course}}</a></li>  
54 - {% endfor %}  
55 - </ul>  
56 - </div>  
57 </div> 44 </div>
58 {% endif %} 45 {% endif %}
  46 +
59 {% endblock %} 47 {% endblock %}
60 48
61 {% block content %} 49 {% block content %}
62 50
63 -<div class="panel panel-info">  
64 - <div class="panel-heading">  
65 - <div class="row">  
66 - <div class="col-xs-10 col-md-11">  
67 - <h3 class="panel-title">{{course.name}}</h3>  
68 - </div>  
69 - <div class="col-xs-2 col-md-1">  
70 - {% if user|has_role:'professor, system_admin' %}  
71 -  
72 - <div class="btn-group icon-more-horiz">  
73 - <button class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">  
74 - <i class="material-icons">more_horiz</i>  
75 - </button>  
76 - <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">  
77 - <li><a href="{% url 'course:update' course.slug %}"><i class="material-icons">create</i> Edit</a></li>  
78 - <li><a href="{% url 'course:delete' course.slug %}"><i class="material-icons">delete_sweep</i> Remove</a></li>  
79 - </ul> 51 + <div class="col-md-12">
  52 + <div class="panel panel-info">
  53 + <div class="panel-heading headingOne">
  54 + <div class="row">
  55 + <div class="col-xs-8 col-md-10 titleTopic">
  56 + <h4>{{course}}</h4>
  57 + </div>
  58 + <div class="col-xs-4 col-md-2" id="divMoreActions">
  59 + <div class="btn-group">
  60 + <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
  61 + <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
  62 + </button>
80 63
  64 + </div>
  65 + <div class="btn-group">
  66 + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  67 + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
  68 + <div class="ripple-container"></div></button>
  69 + <ul class="dropdown-menu" aria-labelledby="moreActions">
  70 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#createSubject"><i class="fa fa-plus-square-o" aria-hidden="true"></i>&nbsp; Create Subject</a></li>
  71 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal4"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; Replicate</a></li>
  72 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; Edit</a></li>
  73 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
  74 + </ul>
  75 + </div>
81 </div> 76 </div>
82 - {% endif %}  
83 - </div>  
84 </div> 77 </div>
  78 + </div>
  79 + <div class="panel-body">
  80 + <p><b>Course Name: </b>{{course.name}}</p>
  81 + <p><b>Duration (in semesters): </b>09</p>
  82 + <p><b>Coordinator: </b>{{course.professors}}</p>
  83 + <p>
  84 + <b>Description:</b>
  85 + <i>
  86 + {{course.description}}
  87 + </i>
  88 + </p>
  89 +
  90 + </div>
85 </div> 91 </div>
86 - <div class="panel-body">  
87 - <p><b>Course Name: </b>{{course.name}}</p>  
88 - <p><b>Duration (in semesters): </b></p>  
89 - {% for professor in course.professors.all %}  
90 - <p><b>Professor: </b>{{professor.name}}</p>  
91 - {% endfor %}  
92 -  
93 - <p>  
94 - <b>Description:</b>  
95 - <i>  
96 - {{course.content}}  
97 - </i>  
98 - </p>  
99 92
  93 +<!-- MODAL CREATE SUBJECT -->
  94 +<div class="modal" tabindex="-1" role="dialog " id="createSubject">
  95 + <div class="modal-dialog">
  96 + <div class="modal-content">
  97 + <div class="modal-header">
  98 + <h4 class="modal-title">Create a New Subject</h4>
  99 + </div>
  100 + <div class="modal-body">
  101 + <div>
  102 + <form class="form-horizontal">
  103 + <div class="form-group is-empty">
  104 + <label class="control-label col-md-2 col-md-offset-1 col-xs-2 col-xs-offset-1">Name</label>
  105 + <div class="col-md-8 col-xs-8">
  106 + <input type="text" class="form-control" name="nameSubject">
  107 + </div>
  108 + </div>
  109 + <div class="form-group is-empty">
  110 + <label class="control-label col-md-2 col-md-offset-1 col-xs-2 col-xs-offset-1">Description</label>
  111 + <div class="col-md-8 col-xs-8">
  112 + <textarea class="form-control" rows="3" id="textAreaSubject"></textarea>
  113 + <span class="help-block">Sign the description of the course.</span>
  114 + </div>
  115 + </div>
  116 + <div class="form-group is-empty">
  117 + <label class="control-label col-md-2 col-md-offset-1 col-xs-2 col-xs-offset-1">Goals</label>
  118 + <div class="col-md-8 col-xs-8">
  119 + <textarea class="form-control" rows="3" id="textAreaSubject"></textarea>
  120 + <span class="help-block">Sign the objectives of the course until the end of the course.</span>
  121 + </div>
  122 + </div>
  123 + <div class="form-group is-empty">
  124 + <label class="control-label col-md-2 col-md-offset-1 col-xs-2 col-xs-offset-1">Students Limit</label>
  125 + <div class="col-md-8 col-xs-8">
  126 + <input type="number" class="form-control" name="StudentLimit">
  127 + </div>
  128 + </div>
  129 + <div class="row">
  130 + <div class="col-md-6 col-xs-12">
  131 + <div class="row">
  132 + <div class="form-group is-empty">
  133 + <label class="control-label col-md-4 col-xs-4 col-xs-offset-1">Begining</label>
  134 + <div class="col-md-8 col-xs-6">
  135 + <input type="date" class="form-control" name="BeginDate">
  136 + </div>
  137 + </div>
  138 + </div>
  139 + </div>
  140 + <div class="col-md-6 col-xs-12">
  141 + <div class="row">
  142 + <div class="form-group is-empty">
  143 + <label class="control-label col-md-4 col-xs-4 col-xs-offset-1">End</label>
  144 + <div class="col-md-8 col-xs-6">
  145 + <input type="date" class="form-control" name="EndDate">
  146 + </div>
  147 + </div>
  148 + </div>
  149 + </div>
  150 + </div>
  151 + </form>
  152 + </div>
  153 + <div class="modal-footer">
  154 + <button type="button" data-dismiss="modal" class="btn btn-default">Cancel</button>
  155 + <a href="#" target="_self"><button type="button" class="btn btn-primary">Confirm</button></a>
  156 + </div>
  157 + </div>
  158 + </div>
100 </div> 159 </div>
101 </div> 160 </div>
102 161
  162 +<div class="panel-group ui-accordion ui-widget ui-helper-reset ui-sortable" id="accordion" role="tablist" aria-multiselectable="false">
  163 + <div><div class="panel panel-info">
  164 +</div>
103 165
104 -{% for subject in subjects %}  
105 - <div class="panel panel-info">  
106 - <div class="panel-heading">  
107 - <div class="row">  
108 - <a href="{% url 'course:view_subject' subject.slug %}">  
109 - <div class="col-md-11">  
110 166
111 - <h3 class="panel-title">{{subject}}</h3> 167 +<!-- MODAL REMOVE -->
  168 +<div class="modal" id="removeSubject">
  169 + <div class="modal-dialog">
  170 + <div class="modal-content">
  171 + <div class="modal-header">
  172 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
  173 + <h4 class="modal-title"></h4>
  174 + </div>
  175 + <div class="modal-body">
  176 + <p>Are you sure you want to remove this subject?</p>
  177 + </div>
  178 + <div class="modal-footer">
  179 +
  180 + <a href="http://127.0.0.1:8080/html/screens/users/teacher/home_course_teacher.html" target="_self"><button type="button" class="btn btn-primary">Confirm</button></a>
112 181
  182 + </div>
  183 + </div>
  184 + </div>
  185 +</div>
  186 +</div>
  187 +<div>
  188 +
  189 +{% for subject in subjects %}
  190 +<div class="panel panel-info">
  191 + <div class="panel-heading headingTwo ui-sortable-handle" role="tab">
  192 + <div class="row">
  193 + <div class="col-xs-9 col-md-10 titleTopic">
  194 + <a role="button" data-toggle="collapse" data-parent="#accordion" href=".collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
  195 + <h4>{{subject.name}}</h4>
  196 + </a>
113 </div> 197 </div>
114 - </a>  
115 - <div class="col-md-1 text-right">  
116 - {% if user|has_role:'professor, system_admin' %}  
117 - <div class="btn-group icon-more-horiz">  
118 - <button class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">  
119 - <i class="material-icons">more_horiz</i> 198 + <div class="col-xs-3 col-md-2" id="divMoreActions">
  199 + <div class="btn-group">
  200 + <button type="button" class="btn btn-default btn-sm eye" data-toggle="tooltip" data-placement="bottom" title="Visible">
  201 + <i class="fa fa-eye fa-2x" aria-hidden="true"></i>
120 </button> 202 </button>
121 - <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">  
122 - <li><a href="{% url 'course:update_subject' subject.slug %}"><i class="material-icons">create</i> {% trans "Edit" %}</a></li>  
123 - <li><a href="{% url 'course:delete_subject' subject.slug %}"><i class="material-icons">delete_sweep</i> {% trans "Remove" %}</a></li> 203 + </div>
  204 + <div class="btn-group">
  205 + <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="moreActions" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  206 + <i class="fa fa-ellipsis-v fa-2x" aria-hidden="true"></i>
  207 + </button>
  208 + <ul class="dropdown-menu" aria-labelledby="moreActions">
  209 + <li><a href="{% url 'course:view_subject' subject.slug %}"><i class="fa fa-files-o fa-fw" aria-hidden="true"></i>&nbsp; Access</a></li>
  210 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#myModal3"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>&nbsp; Replicate</a></li>
  211 + <li><a href="javascript:void(0)" data-toggle="modal" data-target="#removeSubject2"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>&nbsp; Remove</a></li>
124 </ul> 212 </ul>
125 -  
126 </div> 213 </div>
127 - {% endif %}  
128 </div> 214 </div>
129 </div> 215 </div>
130 - </div>  
131 - <div class="panel-body"> 216 + </div>
  217 + <div class="panel-body">
132 <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %} 218 <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %}
133 {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p> 219 {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p>
134 <p> 220 <p>
@@ -146,11 +232,33 @@ @@ -146,11 +232,33 @@
146 </div> 232 </div>
147 </div> 233 </div>
148 </div> 234 </div>
149 - </div> 235 +</div>
150 {% endfor %} 236 {% endfor %}
151 -<a class="btn-floating btn-large waves-effect waves-light red" href="{% url 'course:create' %}">  
152 - <i class="fa fa-plus" aria-hidden="true"></i>  
153 - </a> 237 +
  238 +
  239 +<!-- MODAL REMOVE -->
  240 + <div class="modal" id="removeSubject2">
  241 + <div class="modal-dialog">
  242 + <div class="modal-content">
  243 + <div class="modal-header">
  244 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
  245 + <h4 class="modal-title"></h4>
  246 + </div>
  247 + <div class="modal-body">
  248 + <p>Are you sure you want to remove this subject?</p>
  249 + </div>
  250 + <div class="modal-footer">
  251 +
  252 + <a href="http://127.0.0.1:8080/html/screens/users/teacher/home_course_teacher.html" target="_self"><button type="button" class="btn btn-primary">Confirm</button></a>
  253 +
  254 + </div>
  255 + </div>
  256 + </div>
  257 + </div>
  258 +</div>
  259 +</div>
  260 +</div>
  261 +
154 {% endblock %} 262 {% endblock %}
155 263
156 264
courses/templates/poll/poll.html
@@ -1,53 +0,0 @@ @@ -1,53 +0,0 @@
1 -{% extends "topic/index.html" %}  
2 -  
3 -{% load i18n %}  
4 -  
5 -{% block style %}  
6 - <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>  
7 -{% endblock %}  
8 -  
9 -{% block content %}  
10 -<div class="col-md-8 col-md-offset-2">  
11 - <div class="panel panel-primary">  
12 - <div class="panel-heading">  
13 - <h3 class="panel-title">  
14 - <span class="glyphicon glyphicon-hand-right"></span> Question?</h3>  
15 - </div>  
16 - <div class="container-fluid">  
17 - <form id="form" class="" action="" method="post">  
18 - <div class="row form-group">  
19 - <div class="col-md-1">  
20 - </br>  
21 - <label><span class="glyphicon glyphicon-menu-hamburger"></span></label>  
22 - </div>  
23 - <div class="col-md-10">  
24 - <div class="form-control-md has-success is-empty">  
25 - <input type="text" class="form-control" placeholder="Email address default size">  
26 - <span class="help-block">Please enter a valid email address</span>  
27 - </div>  
28 - </div>  
29 - <div class="col-md-1">  
30 - </br>  
31 - <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>  
32 - </div>  
33 - </div>  
34 - </form>  
35 - </br>  
36 - </div>  
37 -  
38 - </div>  
39 - <div class="panel-footer text-center">  
40 - <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button>  
41 - <a href="#" class="small">View Result</a>  
42 - </div>  
43 - </div>  
44 -<script type="text/javascript">  
45 -$( "#form" ).sortable({  
46 - delay: 100,  
47 - distance: 5,  
48 -});  
49 -$("#add").click(function() {  
50 - $("#form").append('<div class="row form-group"><div class="col-md-1"></br><label><span class="glyphicon glyphicon-menu-hamburger"></span></label></div><div class="col-md-10"><div class="form-group-md has-success is-empty"><input type="text" class="form-control" placeholder="Email address default size"><span class="help-block">Please enter a valid email address</span></div></div><div class="col-md-1"></br><label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label></div></br></div>');  
51 -});  
52 -</script>  
53 -{% endblock content %}  
courses/templates/subject/form_view_student.html
1 {% load i18n %} 1 {% load i18n %}
2 2
  3 +{% block javascript %}
  4 + <script type="text/javascript" src="{% static 'js/forum.js' %}"></script>
  5 +{% endblock %}
  6 +
3 <div class="panel panel-default"> 7 <div class="panel panel-default">
4 <a href="{% url 'course:view_topic' topic.slug %}"> 8 <a href="{% url 'course:view_topic' topic.slug %}">
5 <div class="panel-heading"> 9 <div class="panel-heading">
@@ -13,4 +17,24 @@ @@ -13,4 +17,24 @@
13 </div> 17 </div>
14 <div class="panel-body"> 18 <div class="panel-body">
15 <p>{{topic.description|linebreaks}}</p> 19 <p>{{topic.description|linebreaks}}</p>
  20 + {% list_topic_foruns request topic %}
  21 +</div>
  22 +
  23 +<div class="modal fade" id="forumModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  24 + <div class="modal-dialog" role="document">
  25 + <div class="modal-content">
  26 + <div class="modal-header">
  27 + <h4 class="modal-title" id="myModalLabel">{% trans 'Forum' %}</h4>
  28 + </div>
  29 + <div class="modal-body">
  30 + <section>
  31 + <div class="forum_topics"></div>
  32 + </section>
  33 + </div>
  34 + <div class="modal-footer">
  35 + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans 'Close' %}</button>
  36 + <button type="button" class="btn btn-primary btn-raised">{% trans 'Save changes' %}</button>
  37 + </div>
  38 + </div>
  39 + </div>
16 </div> 40 </div>
17 \ No newline at end of file 41 \ No newline at end of file
courses/templates/subject/form_view_teacher.html
@@ -19,7 +19,10 @@ @@ -19,7 +19,10 @@
19 </a> 19 </a>
20 <div class="panel-body"> 20 <div class="panel-body">
21 <p>{{ topic.description|linebreaks }}</p> 21 <p>{{ topic.description|linebreaks }}</p>
22 - {% list_topic_foruns request topic %} 22 + <button class="btn btn-primary btn-raised" onclick="createForum('{% url 'forum:create' %}', '{{ topic.id }}')">{% trans '+ Create Forum' %}</button>
  23 + <div class="foruns_list">
  24 + {% list_topic_foruns request topic %}
  25 + </div>
23 </div> 26 </div>
24 </div> 27 </div>
25 28
@@ -27,21 +30,11 @@ @@ -27,21 +30,11 @@
27 <div class="modal-dialog" role="document"> 30 <div class="modal-dialog" role="document">
28 <div class="modal-content"> 31 <div class="modal-content">
29 <div class="modal-header"> 32 <div class="modal-header">
30 - <h4 class="modal-title" id="myModalLabel">Forum</h4> 33 + <h4 class="modal-title" id="myModalLabel">{% trans 'Forum' %}</h4>
31 </div> 34 </div>
32 <div class="modal-body"> 35 <div class="modal-body">
33 <section> 36 <section>
34 <div class="forum_topics"></div> 37 <div class="forum_topics"></div>
35 - <div class="form-group">  
36 - <div class="input-group">  
37 - <textarea type="text" id="addon3a" class="form-control" placeholder="{% trans 'Post a comment...' %}"></textarea>  
38 - <span class="input-group-btn">  
39 - <button type="button" class="btn btn-fab btn-fab-mini">  
40 - <i class="material-icons">send</i>  
41 - </button>  
42 - </span>  
43 - </div>  
44 - </div>  
45 </section> 38 </section>
46 </div> 39 </div>
47 <div class="modal-footer"> 40 <div class="modal-footer">
@@ -50,4 +43,23 @@ @@ -50,4 +43,23 @@
50 </div> 43 </div>
51 </div> 44 </div>
52 </div> 45 </div>
  46 +</div>
  47 +
  48 +<div class="modal fade" id="createForum" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  49 + <div class="modal-dialog" role="document">
  50 + <div class="modal-content">
  51 + <div class="modal-header">
  52 + <h4 class="modal-title" id="myModalLabel">{% trans 'Forum' %}</h4>
  53 + </div>
  54 + <div class="modal-body">
  55 + <section>
  56 + <div class="forum_form"></div>
  57 + </section>
  58 + </div>
  59 + <div class="modal-footer">
  60 + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans 'Close' %}</button>
  61 + <button type="button" onclick="$('#forum_create').submit();" class="btn btn-primary btn-raised">{% trans 'Create' %}</button>
  62 + </div>
  63 + </div>
  64 + </div>
53 </div> 65 </div>
54 \ No newline at end of file 66 \ No newline at end of file
courses/templates/topic/index.html
@@ -73,116 +73,62 @@ @@ -73,116 +73,62 @@
73 </div> 73 </div>
74 <div class="panel panel-default"> 74 <div class="panel panel-default">
75 <div class="panel-body"> 75 <div class="panel-body">
76 - <form class="form-horizontal"> 76 + {% for activit in activitys %}
  77 + <form class="form-horizontal" enctype='multipart/form-data'>{% csrf_token %}
77 <fieldset> 78 <fieldset>
78 - <legend>Atividade 1</legend> 79 + <legend>{{activit.name}}</legend>
79 80
80 <div class="container-fluid"> 81 <div class="container-fluid">
81 <div class="row"> 82 <div class="row">
82 - <div class="col-md-4">  
83 - 83 + <div class="col-md-8">
84 <div class="form-group is-empty"> 84 <div class="form-group is-empty">
85 - <input type="text" class="form-control col-md-8" placeholder="Search Student"> 85 + <input type="text" class="form-control col-md-4" placeholder="Search Student">
86 </div> 86 </div>
87 -  
88 - </div>  
89 - </div> 87 + </div>
  88 + </div>
  89 + {% for student in students_activit %}
90 <div class="panel-group" id="accordion"> 90 <div class="panel-group" id="accordion">
91 <div class="panel panel-info"> 91 <div class="panel panel-info">
92 <div class="panel-heading"> 92 <div class="panel-heading">
93 <h4 class="panel-title"> 93 <h4 class="panel-title">
94 <a data-toggle="collapse" data-parent="#accordion" href="#collapse1"> 94 <a data-toggle="collapse" data-parent="#accordion" href="#collapse1">
95 - Aluno Maria<i class="fa fa-plus-square" aria-hidden="true"></i></a> 95 + {{student.name}} <i class="fa fa-plus-square" aria-hidden="true"></i></a>
96 </h4> 96 </h4>
97 </div> 97 </div>
98 <div id="collapse1" class="panel-collapse collapse"> 98 <div id="collapse1" class="panel-collapse collapse">
99 <div class="panel-body"> 99 <div class="panel-body">
100 <div class="row"> 100 <div class="row">
101 - <div class="col-md-6"> 101 + <div class="col-md-4">
102 <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i> 102 <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i>
103 -  
104 </div> 103 </div>
105 - <div class="col-md-6">  
106 - <label> Nota:</label>  
107 - <input type="number" step="0.01">  
108 - </div> 104 + {% if user|has_role:'professor, system_admin' %}
  105 + <div class="col-md-4">
  106 + <label> Nota:</label>
  107 + <input type="number" step="0.01">
  108 + </div>
  109 + {% else %}
  110 + <div class="col-md-4">
  111 + <input type="hidden" name="id" value="">
  112 + <input type="hidden" name="student" value="">
  113 + <div class="form-group {% if form.pdf.errors %} has-error {% endif %}">
  114 + <label for="id_pdf">PDF</label>
  115 + {{form.pdf}}
  116 + </div>
  117 + <button type="submit" class="btn btn-success" id="send_button">Enviar</button>
  118 + </div>
  119 + {% endif %}
109 </div> 120 </div>
110 </div> 121 </div>
111 </div> 122 </div>
112 </div> 123 </div>
113 - <div class="panel panel-info">  
114 - <div class="panel-heading">  
115 - <h4 class="panel-title">  
116 - <a data-toggle="collapse" data-parent="#accordion" href="#collapse2">  
117 - Aluno Joao<i class="fa fa-plus-square" aria-hidden="true"></i></a>  
118 - </h4>  
119 - </div>  
120 - <div id="collapse2" class="panel-collapse collapse">  
121 - <div class="panel-body">  
122 - <div class="row">  
123 - <div class="col-md-6">  
124 - <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i>  
125 -  
126 - </div>  
127 - <div class="col-md-6">  
128 - <label> Nota:</label>  
129 - <input type="number" step="0.01">  
130 - </div>  
131 - </div>  
132 -  
133 - </div>  
134 </div> 124 </div>
  125 + {% endfor %}
135 </div> 126 </div>
136 - <div class="panel panel-info">  
137 - <div class="panel-heading">  
138 - <h4 class="panel-title">  
139 - <a data-toggle="collapse" data-parent="#accordion" href="#collapse3">  
140 - Aluno Santos<i class="fa fa-plus-square" aria-hidden="true"></i></a>  
141 - </h4>  
142 - </div>  
143 - <div id="collapse3" class="panel-collapse collapse">  
144 - <div class="panel-body">  
145 - <div class="row">  
146 - <div class="col-md-6">  
147 - <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i>  
148 -  
149 - </div>  
150 - <div class="col-md-6">  
151 - <label> Nota:</label>  
152 - <input type="number" step="0.01">  
153 - </div>  
154 - </div>  
155 - </div>  
156 - </div>  
157 - </div>  
158 - <div class="panel panel-info">  
159 - <div class="panel-heading">  
160 - <h4 class="panel-title">  
161 - <a data-toggle="collapse" data-parent="#accordion" href="#collapse4">  
162 - Aluno Ruam<i class="fa fa-plus-square" aria-hidden="true"></i></a>  
163 - </h4>  
164 - </div>  
165 - <div id="collapse4" class="panel-collapse collapse">  
166 - <div class="panel-body">  
167 - <div class="row">  
168 - <div class="col-md-6">  
169 - <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i>  
170 -  
171 - </div>  
172 - <div class="col-md-6">  
173 - <label> Nota:</label>  
174 - <input type="number" step="0.01">  
175 - </div>  
176 - </div>  
177 -  
178 - </div>  
179 - </div>  
180 - </div>  
181 -  
182 -</div>  
183 -</div>  
184 -  
185 -</fieldset></form> 127 + </fieldset>
  128 + </form>
  129 +{% empty %}
  130 + {% trans 'No activity found' %}
  131 +{% endfor %}
186 132
187 <ul class="pagination pagination-sm"> 133 <ul class="pagination pagination-sm">
188 <li class="disabled"><a href="javascript:void(0)">«</a></li> 134 <li class="disabled"><a href="javascript:void(0)">«</a></li>
courses/templates/topic/list_topic_foruns.html
1 {% for forum in foruns %} 1 {% for forum in foruns %}
2 - <a href="javascript:showForum('{% url 'forum:index' %}', '{{forum.id}}')">{{ forum }}</a><br /> 2 + <a id="forum_{{ forum.id }}" href="javascript:showForum('{% url 'forum:index' %}', '{{forum.id}}')">{{ forum }}<br /></a>
3 {% endfor %} 3 {% endfor %}
4 \ No newline at end of file 4 \ No newline at end of file
courses/urls.py
1 -from django.conf.urls import url 1 +from django.conf.urls import url, include
2 2
3 from . import views 3 from . import views
4 4
@@ -22,6 +22,8 @@ urlpatterns = [ @@ -22,6 +22,8 @@ urlpatterns = [
22 url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'), 22 url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'),
23 url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'), 23 url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'),
24 url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'), 24 url(r'^subjects/categories$',views.IndexSubjectCategoryView.as_view(), name='subject_category_index'),
25 - url(r'^to/poll/to/$', views.Poll.as_view(), name='poll'), 25 +
  26 +
  27 + url(r'^poll/', include('poll.urls', namespace = 'poll'))
26 28
27 ] 29 ]
courses/views.py
@@ -11,8 +11,8 @@ from rolepermissions.verifications import has_role @@ -11,8 +11,8 @@ from rolepermissions.verifications import has_role
11 from django.db.models import Q 11 from django.db.models import Q
12 from rolepermissions.verifications import has_object_permission 12 from rolepermissions.verifications import has_object_permission
13 13
14 -from .forms import CourseForm, UpdateCourseForm, CategoryForm, SubjectForm,TopicForm  
15 -from .models import Course, Subject, Category,Topic, SubjectCategory 14 +from .forms import CourseForm, UpdateCourseForm, CategoryForm, SubjectForm,TopicForm,ActivityForm
  15 +from .models import Course, Subject, Category,Topic, SubjectCategory,Activity
16 from core.mixins import NotificationMixin 16 from core.mixins import NotificationMixin
17 from users.models import User 17 from users.models import User
18 18
@@ -24,15 +24,14 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView): @@ -24,15 +24,14 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
24 redirect_field_name = 'next' 24 redirect_field_name = 'next'
25 queryset = Course.objects.all() 25 queryset = Course.objects.all()
26 template_name = 'course/index.html' 26 template_name = 'course/index.html'
27 - context_object_name = 'courses' 27 + context_object_name = 'courses_student'
28 paginate_by = 3 28 paginate_by = 3
29 29
30 def get_context_data(self, **kwargs): 30 def get_context_data(self, **kwargs):
31 context = super(IndexView, self).get_context_data(**kwargs) 31 context = super(IndexView, self).get_context_data(**kwargs)
32 context['categories'] = Category.objects.all() 32 context['categories'] = Category.objects.all()
  33 + context['courses_teacher'] = Course.objects.filter(professors__name = self.request.user.name)
33 34
34 - # context['professors'] = Course.objects.all().select_related('professors__name')  
35 - # super.createNotification(users= User.obejcts.all(), message="testando a notificacao em login")  
36 return context 35 return context
37 36
38 class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView): 37 class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView):
@@ -283,18 +282,27 @@ class TopicsView(LoginRequiredMixin, generic.ListView): @@ -283,18 +282,27 @@ class TopicsView(LoginRequiredMixin, generic.ListView):
283 def get_queryset(self): 282 def get_queryset(self):
284 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) 283 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
285 subject = topic.subject 284 subject = topic.subject
286 - context = Topic.objects.filter(subject = subject, visible=True) 285 + topics_q = Topic.objects.filter(subject = subject, visible=True)
287 #if (self.request.user in subject.professors.all() or has_role(self.request.user,'system_admin')): 286 #if (self.request.user in subject.professors.all() or has_role(self.request.user,'system_admin')):
288 #context = subject.topics.all() <- Change it By Activities 287 #context = subject.topics.all() <- Change it By Activities
289 - return context 288 + return topics_q
290 289
291 def get_context_data(self, **kwargs): 290 def get_context_data(self, **kwargs):
292 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug')) 291 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
293 context = super(TopicsView, self).get_context_data(**kwargs) 292 context = super(TopicsView, self).get_context_data(**kwargs)
  293 + activitys = Activity.objects.filter(topic__name = topic.name)
  294 + students_activit = User.objects.filter(activities = Activity.objects.all())
  295 + # page_user = User.objects.get(id= self.kwargs['user_id'])
294 context['topic'] = topic 296 context['topic'] = topic
295 context['subject'] = topic.subject 297 context['subject'] = topic.subject
  298 + context['activitys'] = activitys
  299 + context['students_activit'] = students_activit
  300 + context['form'] = ActivityForm
  301 + # context['user_activity_id'] = Activity.objects.filter(students__id = self.kwargs['students_id'])
  302 + # context['page_user'] = page_user
296 return context 303 return context
297 304
  305 +
298 class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView): 306 class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView):
299 307
300 allowed_roles = ['professor', 'system_admin'] 308 allowed_roles = ['professor', 'system_admin']
@@ -339,7 +347,7 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView): @@ -339,7 +347,7 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
339 return super(UpdateTopicView, self).dispatch(*args, **kwargs) 347 return super(UpdateTopicView, self).dispatch(*args, **kwargs)
340 348
341 def get_object(self, queryset=None): 349 def get_object(self, queryset=None):
342 - return get_object_or_404(Topic, slug = self.kwargs.get('slug')) 350 + return get_object_or_404(Topic, slug = self.kwargs.get('slug'))
343 351
344 def get_success_url(self): 352 def get_success_url(self):
345 return reverse_lazy('course:view_subject', kwargs={'slug' : self.object.subject.slug}) 353 return reverse_lazy('course:view_subject', kwargs={'slug' : self.object.subject.slug})
@@ -455,27 +463,3 @@ class IndexSubjectCategoryView(LoginRequiredMixin, generic.ListView): @@ -455,27 +463,3 @@ class IndexSubjectCategoryView(LoginRequiredMixin, generic.ListView):
455 context = super(IndexSubjectCategoryView, self).get_context_data(**kwargs) 463 context = super(IndexSubjectCategoryView, self).get_context_data(**kwargs)
456 context['subject_categories'] = SubjectCategory.objects.all() 464 context['subject_categories'] = SubjectCategory.objects.all()
457 return context 465 return context
458 -  
459 -  
460 -class Poll(generic.TemplateView):  
461 -  
462 - # login_url = reverse_lazy("core:home")  
463 - # redirect_field_name = 'next'  
464 - # model = Course  
465 - # context_object_name = 'course'  
466 - template_name = 'poll/poll.html'  
467 - # queryset = Course.objects.all()  
468 -  
469 - # def get_queryset(self):  
470 - # return Course.objects.all()[0]  
471 -  
472 - def get_context_data(self, **kwargs):  
473 - context = super(Poll, self).get_context_data(**kwargs)  
474 - course = Course.objects.all()[0]  
475 - context['course'] = course  
476 - context['subject'] = course.subjects.all()[0]  
477 - context['subjects'] = course.subjects.all()  
478 - # if (has_role(self.request.user,'system_admin')):  
479 - # context['subjects'] = self.object.course.subjects.all()  
480 - return context  
481 -  
forum/forms.py
1 from django import forms 1 from django import forms
2 from django.utils.translation import ugettext_lazy as _ 2 from django.utils.translation import ugettext_lazy as _
3 -from .models import Forum 3 +from .models import Forum, Post, PostAnswer
4 4
5 class ForumForm(forms.ModelForm): 5 class ForumForm(forms.ModelForm):
6 6
7 class Meta: 7 class Meta:
8 model = Forum 8 model = Forum
9 - fields = ('name', 'description') 9 + fields = ('name', 'limit_date', 'description', 'topic', )
10 labels = { 10 labels = {
11 'name': _('Title'), 11 'name': _('Title'),
12 - 'description': _('Description') 12 + 'description': _('Description'),
  13 + 'limit_date': _('Limit Date'),
13 } 14 }
14 help_texts = { 15 help_texts = {
15 'name': _('Forum title'), 16 'name': _('Forum title'),
16 - 'description': _('What is this forum about?') 17 + 'description': _('What is this forum about?'),
  18 + 'limit_date': _('Limit date for students post on this forum'),
17 } 19 }
18 widgets = { 20 widgets = {
19 - 'description': forms.Textarea(attrs={'cols': 80, 'rows': 5}), 21 + 'name': forms.TextInput(attrs={'class': 'form-control'}),
  22 + 'description': forms.Textarea(attrs={'cols': 80, 'rows': 5, 'class': 'form-control'}),
  23 + 'topic': forms.HiddenInput(),
  24 + 'limit_date': forms.DateInput(attrs={'class': 'date-picker form-control'}),
  25 + }
  26 +
  27 +class PostForm(forms.ModelForm):
  28 +
  29 + class Meta:
  30 + model = Post
  31 + fields = ('message', 'forum', )
  32 + labels = {
  33 + 'message': _('Message')
  34 + }
  35 + widgets = {
  36 + 'message': forms.Textarea(attrs={'cols': 80, 'rows': 3}),
  37 + 'forum': forms.HiddenInput(),
  38 + }
  39 +
  40 +class PostAnswerForm(forms.ModelForm):
  41 +
  42 + class Meta:
  43 + model = PostAnswer
  44 + fields = ('message', )
  45 + labels = {
  46 + 'message': _('Message')
  47 + }
  48 + widgets = {
  49 + 'message': forms.Textarea(attrs={'cols': 80, 'rows': 3}),
20 } 50 }
21 \ No newline at end of file 51 \ No newline at end of file
forum/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 -# Generated by Django 1.10 on 2016-09-22 20:41 2 +# Generated by Django 1.10 on 2016-10-02 00:17
3 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 -from django.conf import settings  
6 from django.db import migrations, models 5 from django.db import migrations, models
7 import django.db.models.deletion 6 import django.db.models.deletion
8 7
@@ -12,7 +11,6 @@ class Migration(migrations.Migration): @@ -12,7 +11,6 @@ class Migration(migrations.Migration):
12 initial = True 11 initial = True
13 12
14 dependencies = [ 13 dependencies = [
15 - migrations.swappable_dependency(settings.AUTH_USER_MODEL),  
16 ('courses', '0001_initial'), 14 ('courses', '0001_initial'),
17 ] 15 ]
18 16
@@ -21,8 +19,9 @@ class Migration(migrations.Migration): @@ -21,8 +19,9 @@ class Migration(migrations.Migration):
21 name='Forum', 19 name='Forum',
22 fields=[ 20 fields=[
23 ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')), 21 ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')),
24 - ('title', models.CharField(max_length=100, verbose_name='Title')),  
25 ('description', models.TextField(blank=True, verbose_name='Description')), 22 ('description', models.TextField(blank=True, verbose_name='Description')),
  23 + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
  24 + ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')),
26 ], 25 ],
27 options={ 26 options={
28 'verbose_name': 'Forum', 27 'verbose_name': 'Forum',
@@ -35,9 +34,8 @@ class Migration(migrations.Migration): @@ -35,9 +34,8 @@ class Migration(migrations.Migration):
35 fields=[ 34 fields=[
36 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 35 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
37 ('message', models.TextField(verbose_name='Post message')), 36 ('message', models.TextField(verbose_name='Post message')),
  37 + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
38 ('post_date', models.DateTimeField(auto_now_add=True, verbose_name='Post Date')), 38 ('post_date', models.DateTimeField(auto_now_add=True, verbose_name='Post Date')),
39 - ('forum', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum')),  
40 - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')),  
41 ], 39 ],
42 options={ 40 options={
43 'verbose_name': 'Post', 41 'verbose_name': 'Post',
@@ -49,9 +47,9 @@ class Migration(migrations.Migration): @@ -49,9 +47,9 @@ class Migration(migrations.Migration):
49 fields=[ 47 fields=[
50 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 48 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
51 ('message', models.TextField(verbose_name='Answer message')), 49 ('message', models.TextField(verbose_name='Answer message')),
  50 + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
52 ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')), 51 ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')),
53 ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Post', verbose_name='Post')), 52 ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Post', verbose_name='Post')),
54 - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor')),  
55 ], 53 ],
56 options={ 54 options={
57 'verbose_name': 'Post Answer', 55 'verbose_name': 'Post Answer',
forum/migrations/0002_auto_20161001_2117.py 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-02 00:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + initial = True
  13 +
  14 + dependencies = [
  15 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  16 + ('forum', '0001_initial'),
  17 + ]
  18 +
  19 + operations = [
  20 + migrations.AddField(
  21 + model_name='postanswer',
  22 + name='user',
  23 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'),
  24 + ),
  25 + migrations.AddField(
  26 + model_name='post',
  27 + name='forum',
  28 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Forum', verbose_name='Forum'),
  29 + ),
  30 + migrations.AddField(
  31 + model_name='post',
  32 + name='user',
  33 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Autor'),
  34 + ),
  35 + ]
forum/migrations/0002_remove_forum_title.py
@@ -1,19 +0,0 @@ @@ -1,19 +0,0 @@
1 -# -*- coding: utf-8 -*-  
2 -# Generated by Django 1.10 on 2016-09-22 20:43  
3 -from __future__ import unicode_literals  
4 -  
5 -from django.db import migrations  
6 -  
7 -  
8 -class Migration(migrations.Migration):  
9 -  
10 - dependencies = [  
11 - ('forum', '0001_initial'),  
12 - ]  
13 -  
14 - operations = [  
15 - migrations.RemoveField(  
16 - model_name='forum',  
17 - name='title',  
18 - ),  
19 - ]  
forum/migrations/0003_forum_create_date.py
@@ -1,22 +0,0 @@ @@ -1,22 +0,0 @@
1 -# -*- coding: utf-8 -*-  
2 -# Generated by Django 1.10 on 2016-09-28 02:17  
3 -from __future__ import unicode_literals  
4 -  
5 -from django.db import migrations, models  
6 -import django.utils.timezone  
7 -  
8 -  
9 -class Migration(migrations.Migration):  
10 -  
11 - dependencies = [  
12 - ('forum', '0002_remove_forum_title'),  
13 - ]  
14 -  
15 - operations = [  
16 - migrations.AddField(  
17 - model_name='forum',  
18 - name='create_date',  
19 - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='Create Date'),  
20 - preserve_default=False,  
21 - ),  
22 - ]  
forum/models.py
@@ -12,6 +12,7 @@ It works like a &#39;topic&#39; of forum, which users can post to it and answer posts of @@ -12,6 +12,7 @@ It works like a &#39;topic&#39; of forum, which users can post to it and answer posts of
12 """ 12 """
13 class Forum(Activity): 13 class Forum(Activity):
14 description = models.TextField(_('Description'), blank = True) 14 description = models.TextField(_('Description'), blank = True)
  15 + modification_date = models.DateTimeField(_('Modification Date'), auto_now = True)
15 create_date = models.DateTimeField(_('Create Date'), auto_now_add = True) 16 create_date = models.DateTimeField(_('Create Date'), auto_now_add = True)
16 17
17 class Meta: 18 class Meta:
@@ -22,12 +23,14 @@ class Forum(Activity): @@ -22,12 +23,14 @@ class Forum(Activity):
22 def __str__(self): 23 def __str__(self):
23 return self.name 24 return self.name
24 25
  26 +
25 """ 27 """
26 It represents a post made in a forum (topic) 28 It represents a post made in a forum (topic)
27 """ 29 """
28 class Post(models.Model): 30 class Post(models.Model):
29 user = models.ForeignKey(User, verbose_name = _('Autor')) 31 user = models.ForeignKey(User, verbose_name = _('Autor'))
30 message = models.TextField(_('Post message'), blank = False) 32 message = models.TextField(_('Post message'), blank = False)
  33 + modification_date = models.DateTimeField(_('Modification Date'), auto_now = True)
31 post_date = models.DateTimeField(_('Post Date'), auto_now_add = True) 34 post_date = models.DateTimeField(_('Post Date'), auto_now_add = True)
32 forum = models.ForeignKey(Forum, verbose_name = _('Forum')) 35 forum = models.ForeignKey(Forum, verbose_name = _('Forum'))
33 36
@@ -39,6 +42,15 @@ class Post(models.Model): @@ -39,6 +42,15 @@ class Post(models.Model):
39 def __str__(self): 42 def __str__(self):
40 return ''.join([self.user.name, " / ", str(self.post_date)]) 43 return ''.join([self.user.name, " / ", str(self.post_date)])
41 44
  45 + def is_modified(self):
  46 + create = self.post_date.strftime("%Y-%m-%d %H:%M:%S")
  47 + edit = self.modification_date.strftime("%Y-%m-%d %H:%M:%S")
  48 +
  49 + if create != edit:
  50 + return True
  51 +
  52 + return False
  53 +
42 """ 54 """
43 It represents an answer to a forum's post 55 It represents an answer to a forum's post
44 """ 56 """
@@ -46,6 +58,7 @@ class PostAnswer(models.Model): @@ -46,6 +58,7 @@ class PostAnswer(models.Model):
46 user = models.ForeignKey(User, verbose_name = _('Autor')) 58 user = models.ForeignKey(User, verbose_name = _('Autor'))
47 post = models.ForeignKey(Post, verbose_name = _('Post')) 59 post = models.ForeignKey(Post, verbose_name = _('Post'))
48 message = models.TextField(_('Answer message'), blank = False) 60 message = models.TextField(_('Answer message'), blank = False)
  61 + modification_date = models.DateTimeField(_('Modification Date'), auto_now = True)
49 answer_date = models.DateTimeField(_('Answer Date'), auto_now_add = True) 62 answer_date = models.DateTimeField(_('Answer Date'), auto_now_add = True)
50 63
51 class Meta: 64 class Meta:
forum/static/js/forum.js
  1 +function getCookie(name) {
  2 + var cookieValue = null;
  3 + if (document.cookie && document.cookie !== '') {
  4 + var cookies = document.cookie.split(';');
  5 + for (var i = 0; i < cookies.length; i++) {
  6 + var cookie = jQuery.trim(cookies[i]);
  7 + // Does this cookie string begin with the name we want?
  8 + if (cookie.substring(0, name.length + 1) === (name + '=')) {
  9 + cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  10 + break;
  11 + }
  12 + }
  13 + }
  14 + return cookieValue;
  15 +}
  16 +
1 /* 17 /*
2 * 18 *
3 -* Function to load forum to modal 19 +* Function to load create forum's form and set the submit function
4 * 20 *
5 */ 21 */
6 -function showForum(url, forum_id) { 22 +function createForum(url, topic) {
7 $.ajax({ 23 $.ajax({
8 url: url, 24 url: url,
9 - data: {'forum_id': forum_id}, 25 + data: {'topic': topic},
10 success: function(data) { 26 success: function(data) {
11 - $(".forum_topics").html(data); 27 + $(".forum_form").html(data);
  28 + $("#id_topic").val(topic);
  29 +
  30 + $('.date-picker').datepicker();
  31 +
  32 + var frm = $('#forum_create');
  33 + frm.submit(function () {
  34 + $.ajax({
  35 + type: frm.attr('method'),
  36 + url: frm.attr('action'),
  37 + data: frm.serialize(),
  38 + success: function (data) {
  39 + console.log(data);
  40 + data = data.split('-');
  41 +
  42 + $('.foruns_list').append("<a id='forum_"+data[1]+"' href='javascript:showForum("+data[0]+","+data[1]+")'>"+data[2]+"<br /></a>");
  43 +
  44 + $("#createForum").modal('hide');
  45 +
  46 + showForum(data[0], data[1]);
  47 + },
  48 + error: function(data) {
  49 + $(".forum_form").html(data.responseText);
  50 + }
  51 + });
  52 + return false;
  53 + });
12 } 54 }
13 }); 55 });
14 56
15 - $('#forumModal').modal(); 57 + $("#createForum").modal();
16 } 58 }
17 59
18 -function getForm(url) { 60 +/*
  61 +*
  62 +* Function to load forum to modal
  63 +*
  64 +*/
  65 +function showForum(url, forum_id) {
19 $.ajax({ 66 $.ajax({
20 url: url, 67 url: url,
  68 + data: {'forum_id': forum_id},
21 success: function(data) { 69 success: function(data) {
22 - $(".forum_form").html(data); 70 + $(".forum_topics").html(data);
  71 +
  72 + var frm = $('#form_post');
  73 + frm.submit(function () {
  74 + $.ajax({
  75 + type: frm.attr('method'),
  76 + url: frm.attr('action'),
  77 + data: frm.serialize(),
  78 + success: function (data) {
  79 + $("#posts_list").append(data);
  80 + frm[0].reset();
  81 + },
  82 + error: function(data) {
  83 + console.log(frm.serialize());
  84 + console.log('Error');
  85 + }
  86 + });
  87 + return false;
  88 + });
23 } 89 }
24 }); 90 });
25 91
26 - $(".forum_form").show(); 92 + $('#forumModal').modal();
27 } 93 }
28 94
29 -function showPosts(url, forum) {  
30 - if ($("#collapse" + forum).hasClass('in')) {  
31 - $("#collapse" + forum).collapse('hide');  
32 - } else { 95 +function delete_forum(url, forum, message) {
  96 + alertify.confirm(message, function(){
  97 + var csrftoken = getCookie('csrftoken');
  98 +
33 $.ajax({ 99 $.ajax({
  100 + method: 'post',
  101 + beforeSend: function (request) {
  102 + request.setRequestHeader('X-CSRFToken', csrftoken);
  103 + },
34 url: url, 104 url: url,
35 - data: {'forum': forum},  
36 success: function(data) { 105 success: function(data) {
37 - $("#collapse" + forum).find(".well").html(data); 106 + $("#forum_"+forum).remove();
  107 + $('#forumModal').modal('hide');
38 } 108 }
39 }); 109 });
  110 + });
  111 +}
40 112
41 - $("#collapse" + forum).collapse('show');  
42 - } 113 +/*
  114 +*
  115 +* Function to load form to edit post
  116 +*
  117 +*/
  118 +function edit_post(url, post_id) {
  119 + $.ajax({
  120 + url: url,
  121 + success: function(data) {
  122 + $("#post_"+post_id).find(".post_content").hide();
  123 + $("#post_"+post_id).find(".post_content").after(data);
  124 +
  125 + var frm = $("#post_"+post_id).find(".edit_post_form");
  126 + frm.submit(function () {
  127 + $.ajax({
  128 + type: frm.attr('method'),
  129 + url: frm.attr('action'),
  130 + data: frm.serialize(),
  131 + success: function (data) {
  132 + $("#post_"+post_id).parent().after(data);
  133 + frm.parent().parent().remove();
  134 + },
  135 + error: function(data) {
  136 + console.log(frm.serialize());
  137 + console.log('Error');
  138 + }
  139 + });
  140 + return false;
  141 + });
  142 + }
  143 + });
43 } 144 }
44 145
45 -function showPostsAnswers(url, post) {  
46 - if ($("#collapse" + post).hasClass('in')) {  
47 - $("#collapse" + post).collapse('hide');  
48 - } else {  
49 - $.ajax({  
50 - url: url,  
51 - data: {'post': post},  
52 - success: function(data) {  
53 - $("#collapse" + post).find(".well").html(data);  
54 - }  
55 - }); 146 +/*
  147 +*
  148 +* Function to cancel post edition
  149 +*
  150 +*/
  151 +function cancelEditPost(post_id) {
  152 + $("#post_"+post_id).find(".post_content").show();
  153 + $("#post_"+post_id).find(".edit_post_form").remove();
  154 +}
56 155
57 - $("#collapse" + post).collapse('show');  
58 - } 156 +/*
  157 +*
  158 +* Function to delete a post
  159 +*
  160 +*/
  161 +function delete_post(url, post) {
  162 + var csrftoken = getCookie('csrftoken');
  163 +
  164 + $.ajax({
  165 + method: 'post',
  166 + beforeSend: function (request) {
  167 + request.setRequestHeader('X-CSRFToken', csrftoken);
  168 + },
  169 + url: url,
  170 + success: function(data) {
  171 + $("#post_"+post).remove();
  172 + }
  173 + });
  174 +}
  175 +
  176 +function answer(id, url) {
  177 + $.ajax({
  178 + url: url,
  179 + success: function(data) {
  180 + $("#post_"+id).find(".answer_post").html(data);
  181 + }
  182 + });
  183 +
  184 + $("#post_"+id).find(".answer_post").show();
59 } 185 }
60 \ No newline at end of file 186 \ No newline at end of file
forum/templates/forum/forum_form.html
1 {% load static i18n %} 1 {% load static i18n %}
2 {% load widget_tweaks %} 2 {% load widget_tweaks %}
3 3
4 -<form method="post" action="" enctype="multipart/form-data"> 4 +<form id="forum_create" method="post" action="{% url 'forum:create' %}" enctype="multipart/form-data">
5 {% csrf_token %} 5 {% csrf_token %}
6 {% for field in form %} 6 {% for field in form %}
7 <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> 7 <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
8 - <label for="{{ field.auto_id }}">{{ field.label }}</label>  
9 - {% render_field field class='form-control' %}  
10 - <span class="help-block">{{ field.help_text }}</span>  
11 - {% if field.errors %}  
12 - <div class="row">  
13 - <br />  
14 - <div class="alert alert-danger alert-dismissible" role="alert">  
15 - <button type="button" class="close" data-dismiss="alert" aria-label="Close">  
16 - <span aria-hidden="true">&times;</span>  
17 - </button>  
18 - <ul>  
19 - {% for error in field.errors %}  
20 - <li>{{ error }}</li>  
21 - {% endfor %}  
22 - </ul> 8 + {% if field.field.widget.input_type == 'hidden' %}
  9 + {% render_field field class='form-control' %}
  10 + {% else %}
  11 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  12 + {% render_field field %}
  13 + <span class="help-block">{{ field.help_text }}</span>
  14 + {% if field.errors %}
  15 + <div class="row">
  16 + <br />
  17 + <div class="alert alert-danger alert-dismissible" role="alert">
  18 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  19 + <span aria-hidden="true">&times;</span>
  20 + </button>
  21 + <ul>
  22 + {% for error in field.errors %}
  23 + <li>{{ error }}</li>
  24 + {% endfor %}
  25 + </ul>
  26 + </div>
23 </div> 27 </div>
24 - </div> 28 + {% endif %}
25 {% endif %} 29 {% endif %}
26 </div> 30 </div>
27 {% endfor %} 31 {% endfor %}
28 -  
29 - <input type="submit" value="{% trans 'Create' %}" class="btn btn-primary" />  
30 </form> 32 </form>
31 \ No newline at end of file 33 \ No newline at end of file
forum/templates/forum/forum_list.html
1 {% load i18n permission_tags list_post %} 1 {% load i18n permission_tags list_post %}
  2 +{% load widget_tweaks %}
2 3
3 <div class="comments-list"> 4 <div class="comments-list">
4 <div class="section-heading"> 5 <div class="section-heading">
5 - <h1>{{ forum }}</h1> 6 + <h1>
  7 + {{ forum }}
  8 + <div class="pull-right">
  9 + {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %}
  10 + {% csrf_token %}
  11 + <div class="btn-group icon-more-horiz">
  12 + <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  13 + <i class="material-icons">more_horiz</i>
  14 + </a>
  15 + <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
  16 + <li><a href="javascript:edit_forum('{% url 'forum:index' %}', '{{ forum.id }}')"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
  17 + <li><a href="javascript:delete_forum('{% url 'forum:delete' forum.id %}', '{{ forum.id }}', '{% trans "Are you sure you want to delete this forum?" %}')"><i class="material-icons">delete_sweep</i> {% trans 'Delete' %}</a></li>
  18 + </ul>
  19 + </div>
  20 + {% endif %}
  21 + </div>
  22 + </h1>
6 <h4><b>{% trans 'Description' %}:</b> {{ forum.description }}</h4> 23 <h4><b>{% trans 'Description' %}:</b> {{ forum.description }}</h4>
7 <h4><b>{% trans 'Opened in' %}:</b> {{ forum.create_date }}</h4> 24 <h4><b>{% trans 'Opened in' %}:</b> {{ forum.create_date }}</h4>
8 </div> 25 </div>
9 </div> 26 </div>
10 27
11 -{% list_posts request forum %} 28 +<div id="posts_list">
  29 + {% list_posts request forum %}
  30 +</div>
  31 +
  32 +<form id="form_post" method="post" action="{% url 'forum:create_post' %}" enctype="multipart/form-data">
  33 + {% csrf_token %}
  34 + {% for field in form %}
  35 + {% if field.field.widget.input_type == 'hidden' %}
  36 + {% render_field field class='form-control' value=forum.id %}
  37 + {% else %}
  38 + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
  39 + <div class="input-group">
  40 + {% render_field field class='form-control' placeholder="Post a message" %}
  41 + <span class="help-block">{{ field.help_text }}</span>
  42 + {% if field.errors %}
  43 + <div class="row">
  44 + <br />
  45 + <div class="alert alert-danger alert-dismissible" role="alert">
  46 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  47 + <span aria-hidden="true">&times;</span>
  48 + </button>
  49 + <ul>
  50 + {% for error in field.errors %}
  51 + <li>{{ error }}</li>
  52 + {% endfor %}
  53 + </ul>
  54 + </div>
  55 + </div>
  56 + {% endif %}
  57 + <span class="input-group-btn">
  58 + <button type="submit" class="btn btn-fab btn-fab-mini">
  59 + <i class="material-icons">send</i>
  60 + </button>
  61 + </span>
  62 + </div>
  63 + </div>
  64 + {% endif %}
  65 + {% endfor %}
  66 +</form>
12 67
13 <!--{% if foruns|length > 0 %} 68 <!--{% if foruns|length > 0 %}
14 {% for forum in foruns %} 69 {% for forum in foruns %}
forum/templates/post/post_list.html
@@ -2,28 +2,40 @@ @@ -2,28 +2,40 @@
2 2
3 {% if posts|length > 0 %} 3 {% if posts|length > 0 %}
4 {% for post in posts %} 4 {% for post in posts %}
5 - <div class="row">  
6 - <div class="col-sm-12 col-xs-12"> 5 + <div class="row">
  6 + <div id="post_{{ post.id }}" class="col-sm-12 col-xs-12">
7 <h3 class="user-name"> 7 <h3 class="user-name">
8 {{ post.user }} 8 {{ post.user }}
9 - {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %}  
10 - <div class="pull-right"> 9 + <div class="pull-right">
  10 + <a href="javascript:answer('{{ post.id }}', '{% url 'forum:reply_post' %}');">
  11 + <i class="material-icons">reply</i>
  12 + </a>
  13 + {% if request.user|has_role:'system_admin' or request.user == post.user %}
  14 + {% csrf_token %}
11 <div class="btn-group icon-more-horiz"> 15 <div class="btn-group icon-more-horiz">
12 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> 16 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
13 <i class="material-icons">more_horiz</i> 17 <i class="material-icons">more_horiz</i>
14 </a> 18 </a>
15 <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> 19 <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
16 - <li><a href="javascript:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>  
17 - <li><a href="javascript:void(0)"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li> 20 + <li><a href="javascript:edit_post('{% url 'forum:update_post' post.id %}', '{{ post.id }}')"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li>
  21 + <li><a href="javascript:javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
18 </ul> 22 </ul>
19 </div> 23 </div>
20 - </div>  
21 - {% endif %} 24 + {% endif %}
  25 + </div>
22 </h3> 26 </h3>
23 - <div class="card-data">  
24 - <p class="comment-date"><i class="fa fa-clock-o"></i> {{ post.post_date }}</p> 27 + <div class="post_content">
  28 + <div class="card-data">
  29 + <p class="comment-date">
  30 + <i class="fa fa-clock-o"></i> {{ post.post_date }}
  31 + {% if post.is_modified %}
  32 + <em> - {% trans 'Edited' %}</em>
  33 + {% endif %}
  34 + </p>
  35 + </div>
  36 + <p class="comment-text">{{ post.message|linebreaks }}</p>
25 </div> 37 </div>
26 - <p class="comment-text">{{ post.message|linebreaks }}</p> 38 + <div class="answer_post"></div>
27 </div> 39 </div>
28 </div> 40 </div>
29 {% list_post_answer request post %} 41 {% list_post_answer request post %}
forum/templates/post/post_render.html 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +{% load i18n permission_tags %}
  2 +
  3 +<div class="row">
  4 + <div id="post_{{ post.id }}" class="col-sm-12 col-xs-12">
  5 + <h3 class="user-name">
  6 + {{ post.user }}
  7 + <div class="pull-right">
  8 + <a href="javascript:answer('{{ post.id }}', '{% url 'forum:reply_post' %}');">
  9 + <i class="material-icons">reply</i>
  10 + </a>
  11 + {% if request.user|has_role:'system_admin' or request.user|has_role:'professor' and request.user == post.user %}
  12 + {% csrf_token %}
  13 + <div class="btn-group icon-more-horiz">
  14 + <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  15 + <i class="material-icons">more_horiz</i>
  16 + </a>
  17 + <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
  18 + <li><a href="javascript:edit_post('{% url 'forum:update_post' post.id %}', '{{ post.id }}')"></li>
  19 + <li><a href="javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li>
  20 + </ul>
  21 + </div>
  22 + {% endif %}
  23 + </div>
  24 + </h3>
  25 + <div class="post_content">
  26 + <div class="card-data">
  27 + <p class="comment-date">
  28 + <i class="fa fa-clock-o"></i> {{ post.post_date }}
  29 + {% if post.post_date != post.modifiction_date %}
  30 + <em> - {% trans 'Edited' %}</em>
  31 + {% endif %}
  32 + </p>
  33 + </div>
  34 + <p class="comment-text">{{ post.message|linebreaks }}</p>
  35 + </div>
  36 + <div class="answer_post"></div>
  37 + </div>
  38 +</div>
0 \ No newline at end of file 39 \ No newline at end of file
forum/templates/post/post_update_form.html 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +{% load i18n permission_tags list_post %}
  2 +{% load widget_tweaks %}
  3 +
  4 +<form class="edit_post_form" method="post" action="{% url 'forum:update_post' post.id %}" enctype="multipart/form-data">
  5 + {% csrf_token %}
  6 + {% for field in form %}
  7 + {% if field.field.widget.input_type == 'hidden' %}
  8 + {% render_field field class='form-control' %}
  9 + {% else %}
  10 + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
  11 + <div class="input-group">
  12 + {% render_field field class='form-control' placeholder="Post a message" %}
  13 + <span class="help-block">{{ field.help_text }}</span>
  14 + {% if field.errors %}
  15 + <div class="row">
  16 + <br />
  17 + <div class="alert alert-danger alert-dismissible" role="alert">
  18 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  19 + <span aria-hidden="true">&times;</span>
  20 + </button>
  21 + <ul>
  22 + {% for error in field.errors %}
  23 + <li>{{ error }}</li>
  24 + {% endfor %}
  25 + </ul>
  26 + </div>
  27 + </div>
  28 + {% endif %}
  29 + </div>
  30 + </div>
  31 + <div class="pull-right">
  32 + <button type="button" onclick="cancelEditPost('{{ post.id }}')" class="btn btn-danger btn-raised">{% trans 'Cancel' %}</button>
  33 + <button type="submit" class="btn btn-primary btn-raised">{% trans 'Save changes' %}</button>
  34 + </div>
  35 + {% endif %}
  36 + {% endfor %}
  37 +</form>
0 \ No newline at end of file 38 \ No newline at end of file
forum/templates/post_answers/post_answer_form.html 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +{% load static i18n %}
  2 +{% load widget_tweaks %}
  3 +
  4 +<form method="post" action="#" enctype="multipart/form-data">
  5 + {% csrf_token %}
  6 + {% for field in form %}
  7 + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput">
  8 + <div class="input-group">
  9 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  10 + {% render_field field class='form-control' %}
  11 + <span class="help-block">{{ field.help_text }}</span>
  12 + {% if field.errors %}
  13 + <div class="row">
  14 + <br />
  15 + <div class="alert alert-danger alert-dismissible" role="alert">
  16 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  17 + <span aria-hidden="true">&times;</span>
  18 + </button>
  19 + <ul>
  20 + {% for error in field.errors %}
  21 + <li>{{ error }}</li>
  22 + {% endfor %}
  23 + </ul>
  24 + </div>
  25 + </div>
  26 + {% endif %}
  27 + <span class="input-group-btn">
  28 + <button type="submit" class="btn btn-fab btn-fab-mini">
  29 + <i class="material-icons">send</i>
  30 + </button>
  31 + </span>
  32 + </div>
  33 + </div>
  34 + {% endfor %}
  35 +
  36 +</form>
0 \ No newline at end of file 37 \ No newline at end of file
forum/templatetags/list_post.py
@@ -14,6 +14,6 @@ def list_posts(request, forum): @@ -14,6 +14,6 @@ def list_posts(request, forum):
14 'request': request, 14 'request': request,
15 } 15 }
16 16
17 - context['posts'] = Post.objects.filter(forum = forum) 17 + context['posts'] = Post.objects.filter(forum = forum).order_by('post_date')
18 18
19 return context 19 return context
20 \ No newline at end of file 20 \ No newline at end of file
forum/tests.py
@@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
1 -from django.test import TestCase  
2 -  
3 -# Create your tests here.  
forum/tests/__init__.py 0 → 100644
forum/tests/test_model_answer.py 0 → 100644
@@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
  1 +from django.test import TestCase
  2 +from rolepermissions.shortcuts import assign_role
  3 +
  4 +from users.models import User
  5 +from courses.models import Category, Course, Subject, Topic
  6 +from forum.models import Forum, Post, PostAnswer
  7 +
  8 +class PostAnswerTestCase (TestCase):
  9 +
  10 + def setUp (self):
  11 + self.user_professor = User.objects.create_user(
  12 + username = 'professor',
  13 + email = 'professor@amadeus.com',
  14 + is_staff = False,
  15 + is_active = True,
  16 + password = 'testing',
  17 + type_profile = 1
  18 + )
  19 + assign_role(self.user_professor, 'professor')
  20 +
  21 + self.user_student = User.objects.create_user(
  22 + username = 'student',
  23 + email = 'student@amadeus.com',
  24 + is_staff = False,
  25 + is_active = True,
  26 + password = 'testing',
  27 + type_profile = 2
  28 + )
  29 + assign_role(self.user_student, 'student')
  30 +
  31 + self.category = Category.objects.create(
  32 + name = 'Categoria Teste',
  33 + slug = 'categoria_teste'
  34 + )
  35 + self.category.save()
  36 +
  37 + self.course = Course.objects.create(
  38 + name = 'Curso Teste',
  39 + slug = 'curso_teste',
  40 + max_students = 50,
  41 + init_register_date = '2016-08-26',
  42 + end_register_date = '2016-10-01',
  43 + init_date = '2016-10-05',
  44 + end_date = '2017-10-05',
  45 + category = self.category
  46 + )
  47 + self.course.save()
  48 +
  49 + self.subject = Subject.objects.create(
  50 + name = 'Subject Test',
  51 + description = "description of the subject test",
  52 + visible = True,
  53 + course = self.course,
  54 + init_date = '2016-10-05',
  55 + end_date = '2017-10-05',
  56 + )
  57 + self.subject.save()
  58 + self.subject.professors.add(self.user_professor)
  59 +
  60 + self.topic = Topic.objects.create(
  61 + name = 'Topic Test',
  62 + description = "description of the topic test",
  63 + subject = self.subject,
  64 + owner = self.user_professor,
  65 + )
  66 + self.topic.save()
  67 +
  68 + self.forum = Forum.objects.create(
  69 + topic=self.topic,
  70 + name = 'forum test',
  71 + description = 'description of the forum test',
  72 + create_date = '2016-10-02',
  73 + modification_date = '2016-10-03',
  74 + limit_date = '2017-10-05',
  75 + )
  76 + self.forum.save()
  77 +
  78 + self.post_professor = Post.objects.create(
  79 + user = self.user_professor,
  80 + message = 'posting a test on forum as professor',
  81 + modification_date = '2016-11-09',
  82 + post_date = '2016-10-03',
  83 + forum = self.forum,
  84 + )
  85 + self.post_professor.save()
  86 +
  87 + self.post_student = Post.objects.create(
  88 + user = self.user_student,
  89 + message = 'posting a test on forum as student',
  90 + modification_date = '2016-11-09',
  91 + post_date = '2016-10-03',
  92 + forum = self.forum,
  93 + )
  94 + self.post_student.save()
  95 +
  96 + self.answer = PostAnswer.objects.create(
  97 + user = self.user_student,
  98 + post = self.post_professor,
  99 + message = 'testing a post answer',
  100 + modification_date = '2016-10-05',
  101 + answer_date = '2016-10-04',
  102 + )
  103 +
  104 +
  105 + def test_create_answer_post (self):
  106 + answer = PostAnswer.objects.create(
  107 + user = self.user_professor,
  108 + post = self.post_student,
  109 + message = 'testing a post answer2',
  110 + modification_date = '2016-10-05',
  111 + answer_date = '2016-10-04',
  112 + )
  113 + answer.save()
  114 +
  115 + self.assertEquals (answer, PostAnswer.objects.get(user=self.user_professor, post=self.post_student))
  116 +
  117 + def test_update_answer_post (self):
  118 + self.answer.message = 'updating a answer post'
  119 + self.answer.save()
  120 +
  121 + self.assertEquals(self.answer, PostAnswer.objects.all()[0])
  122 +
  123 + def test_delete_answer_post (self):
  124 + answer = PostAnswer.objects.get(user=self.user_student, post=self.post_professor)
  125 + self.answer.delete()
  126 +
  127 + try:
  128 + answer = PostAnswer.objects.get(user=self.user_student, post=self.post_professor)
  129 + except:
  130 + pass
0 \ No newline at end of file 131 \ No newline at end of file
forum/tests/test_model_forum.py 0 → 100644
@@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
  1 +from django.test import TestCase, Client
  2 +from django.core.urlresolvers import reverse
  3 +from rolepermissions.shortcuts import assign_role
  4 +
  5 +from users.models import User
  6 +from courses.models import Category, Course, Subject, Topic
  7 +from forum.models import Forum
  8 +
  9 +class ForumTestCase (TestCase):
  10 +
  11 + def setUp(self):
  12 + self.user_professor = User.objects.create_user(
  13 + username = 'professor',
  14 + email = 'professor@amadeus.com',
  15 + is_staff = False,
  16 + is_active = True,
  17 + password = 'testing',
  18 + type_profile = 1
  19 + )
  20 + assign_role(self.user_professor, 'professor')
  21 +
  22 + self.user_student = User.objects.create_user(
  23 + username = 'student',
  24 + email = 'student@amadeus.com',
  25 + is_staff = False,
  26 + is_active = True,
  27 + password = 'testing',
  28 + type_profile = 2
  29 + )
  30 + assign_role(self.user_student, 'student')
  31 +
  32 + self.category = Category.objects.create(
  33 + name = 'Categoria Teste',
  34 + slug = 'categoria_teste'
  35 + )
  36 + self.category.save()
  37 +
  38 + self.course = Course.objects.create(
  39 + name = 'Curso Teste',
  40 + slug = 'curso_teste',
  41 + max_students = 50,
  42 + init_register_date = '2016-08-26',
  43 + end_register_date = '2016-10-01',
  44 + init_date = '2016-10-05',
  45 + end_date = '2017-10-05',
  46 + category = self.category
  47 + )
  48 + self.course.save()
  49 +
  50 + self.subject = Subject.objects.create(
  51 + name = 'Subject Test',
  52 + description = "description of the subject test",
  53 + visible = True,
  54 + course = self.course,
  55 + init_date = '2016-10-05',
  56 + end_date = '2017-10-05',
  57 + )
  58 + self.subject.save()
  59 + self.subject.professors.add(self.user_professor)
  60 +
  61 + self.topic = Topic.objects.create(
  62 + name = 'Topic Test',
  63 + description = "description of the topic test",
  64 + subject = self.subject,
  65 + owner = self.user_professor,
  66 + )
  67 + self.topic.save()
  68 +
  69 + self.forum = Forum.objects.create(
  70 + topic=self.topic,
  71 + name = 'forum test',
  72 + description = 'description of the forum test',
  73 + create_date = '2016-10-02',
  74 + modification_date = '2016-10-03',
  75 + limit_date = '2017-10-05',
  76 + )
  77 + self.forum.save()
  78 +
  79 + def test_create_forum (self):
  80 + forum = Forum.objects.create(
  81 + topic=self.topic,
  82 + name = 'forum test2',
  83 + description = 'description of the forum test',
  84 + create_date = '2016-10-02',
  85 + modification_date = '2016-10-03',
  86 + limit_date = '2017-10-05',
  87 + )
  88 + forum.save()
  89 +
  90 + self.assertEquals(forum, Forum.objects.filter(name='forum test2')[0])
  91 +
  92 + def test_update_forum(self):
  93 + self.forum.name = 'forum test updated'
  94 + self.forum.save()
  95 +
  96 + self.assertEquals(self.forum, Forum.objects.get(name='forum test updated'))
  97 +
  98 + def test_delete_forum (self):
  99 + forum = Forum.objects.get(name='forum test')
  100 + self.forum.delete()
  101 +
  102 + try:
  103 + forum = Forum.objects.get(name='forum test')
  104 + except:
  105 + pass
  106 +
0 \ No newline at end of file 107 \ No newline at end of file
forum/tests/test_model_post.py 0 → 100644
@@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
  1 +from django.test import TestCase
  2 +from rolepermissions.shortcuts import assign_role
  3 +
  4 +from users.models import User
  5 +from courses.models import Category, Course, Subject, Topic
  6 +from forum.models import Forum, Post
  7 +
  8 +class PostTestCase (TestCase):
  9 +
  10 + def setUp (self):
  11 + self.user_professor = User.objects.create_user(
  12 + username = 'professor',
  13 + email = 'professor@amadeus.com',
  14 + is_staff = False,
  15 + is_active = True,
  16 + password = 'testing',
  17 + type_profile = 1
  18 + )
  19 + assign_role(self.user_professor, 'professor')
  20 +
  21 + self.user_student = User.objects.create_user(
  22 + username = 'student',
  23 + email = 'student@amadeus.com',
  24 + is_staff = False,
  25 + is_active = True,
  26 + password = 'testing',
  27 + type_profile = 2
  28 + )
  29 + assign_role(self.user_student, 'student')
  30 +
  31 + self.category = Category.objects.create(
  32 + name = 'Categoria Teste',
  33 + slug = 'categoria_teste'
  34 + )
  35 + self.category.save()
  36 +
  37 + self.course = Course.objects.create(
  38 + name = 'Curso Teste',
  39 + slug = 'curso_teste',
  40 + max_students = 50,
  41 + init_register_date = '2016-08-26',
  42 + end_register_date = '2016-10-01',
  43 + init_date = '2016-10-05',
  44 + end_date = '2017-10-05',
  45 + category = self.category
  46 + )
  47 + self.course.save()
  48 +
  49 + self.subject = Subject.objects.create(
  50 + name = 'Subject Test',
  51 + description = "description of the subject test",
  52 + visible = True,
  53 + course = self.course,
  54 + init_date = '2016-10-05',
  55 + end_date = '2017-10-05',
  56 + )
  57 + self.subject.save()
  58 + self.subject.professors.add(self.user_professor)
  59 +
  60 + self.topic = Topic.objects.create(
  61 + name = 'Topic Test',
  62 + description = "description of the topic test",
  63 + subject = self.subject,
  64 + owner = self.user_professor,
  65 + )
  66 + self.topic.save()
  67 +
  68 + self.forum = Forum.objects.create(
  69 + topic=self.topic,
  70 + name = 'forum test',
  71 + description = 'description of the forum test',
  72 + create_date = '2016-10-02',
  73 + modification_date = '2016-10-03',
  74 + limit_date = '2017-10-05',
  75 + )
  76 + self.forum.save()
  77 +
  78 + self.post_professor = Post.objects.create(
  79 + user = self.user_professor,
  80 + message = 'posting a test on forum as professor',
  81 + modification_date = '2016-11-09',
  82 + post_date = '2016-10-03',
  83 + forum = self.forum,
  84 + )
  85 + self.post_professor.save()
  86 +
  87 + self.post_student = Post.objects.create(
  88 + user = self.user_student,
  89 + message = 'posting a test on forum as student',
  90 + modification_date = '2016-11-09',
  91 + post_date = '2016-10-03',
  92 + forum = self.forum,
  93 + )
  94 + self.post_student.save()
  95 +
  96 + def test_create_post_professor (self):
  97 + post_professor = Post.objects.create(
  98 + user = self.user_professor,
  99 + message = 'posting',
  100 + modification_date = '2016-11-09',
  101 + post_date = '2016-10-03',
  102 + forum = self.forum,
  103 + )
  104 + post_professor.save()
  105 +
  106 + self.assertEquals (post_professor, Post.objects.get(user=self.user_professor, message='posting'))
  107 +
  108 + def test_create_post_student (self):
  109 + post_student = Post.objects.create(
  110 + user = self.user_student,
  111 + message = 'posting',
  112 + modification_date = '2016-11-09',
  113 + post_date = '2016-10-03',
  114 + forum = self.forum,
  115 + )
  116 + post_student.save()
  117 +
  118 + self.assertEquals (post_student, Post.objects.get(user=self.user_student, message='posting'))
  119 +
  120 + def test_update_post_professor (self):
  121 + self.post_professor.message = 'updating a post as professor'
  122 + self.post_professor.save()
  123 +
  124 + self.assertEquals(self.post_professor, Post.objects.all()[1])
  125 +
  126 + def test_update_post_student (self):
  127 + self.post_student.message = 'updating a post as student'
  128 + self.post_student.save()
  129 +
  130 + self.assertEquals(self.post_student, Post.objects.all()[1])
  131 +
  132 + def test_delete_post_professor (self):
  133 + post = Post.objects.get(user=self.user_professor, message='posting a test on forum as professor')
  134 + self.post_professor.delete()
  135 +
  136 + try:
  137 + post = Post.objects.get(user=self.user_professor, message='posting a test on forum as professor')
  138 + except:
  139 + pass
  140 +
  141 + def test_delete_post_student (self):
  142 + post = Post.objects.get(user=self.user_student, message='posting a test on forum as student')
  143 + self.post_student.delete()
  144 +
  145 + try:
  146 + post = Post.objects.get(user=self.user_student, message='posting a test on forum as student')
  147 + except:
  148 + pass
0 \ No newline at end of file 149 \ No newline at end of file
@@ -5,7 +5,15 @@ from . import views @@ -5,7 +5,15 @@ from . import views
5 5
6 urlpatterns = [ 6 urlpatterns = [
7 url(r'^$', views.ForumIndex.as_view(), name='index'), 7 url(r'^$', views.ForumIndex.as_view(), name='index'),
8 - url(r'^create$', views.CreateForumView.as_view(), name='create'),  
9 - url(r'^posts$', views.PostIndex.as_view(), name='posts'),  
10 - url(r'^post_answers$', views.PostAnswerIndex.as_view(), name='post_answers'), 8 + url(r'^create/$', views.CreateForumView.as_view(), name='create'),
  9 + url(r'^delete/(?P<pk>[\w_-]+)/$', views.ForumDeleteView.as_view(), name='delete'),
  10 + url(r'^render_forum/([\w_-]+)/$', views.render_forum, name='render_forum'),
  11 + url(r'^forum_deleted/$', views.forum_deleted, name='deleted_forum'),
  12 + url(r'^create_post/$', views.CreatePostView.as_view(), name='create_post'),
  13 + url(r'^update_post/(?P<pk>[\w_-]+)/$', views.PostUpdateView.as_view(), name='update_post'),
  14 + url(r'^delete_post/(?P<pk>[\w_-]+)/$', views.PostDeleteView.as_view(), name='delete_post'),
  15 + url(r'^render_post/([\w_-]+)/$', views.render_post, name='render_post'),
  16 + url(r'^post_deleted/$', views.post_deleted, name='deleted_post'),
  17 + url(r'^post_answers/$', views.PostAnswerIndex.as_view(), name='post_answers'),
  18 + url(r'^reply_post/$', views.CreatePostAnswerView.as_view(), name='reply_post'),
11 ] 19 ]
forum/views.py
  1 +from django.http import HttpResponse
1 from django.shortcuts import render, get_object_or_404 2 from django.shortcuts import render, get_object_or_404
2 -from django.core.urlresolvers import reverse_lazy 3 +from django.core.urlresolvers import reverse, reverse_lazy
3 from django.utils.translation import ugettext_lazy as _ 4 from django.utils.translation import ugettext_lazy as _
4 from django.views import generic 5 from django.views import generic
5 from django.contrib.auth.mixins import LoginRequiredMixin 6 from django.contrib.auth.mixins import LoginRequiredMixin
@@ -7,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin @@ -7,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
7 from .models import Forum, Post, PostAnswer 8 from .models import Forum, Post, PostAnswer
8 from courses.models import Topic 9 from courses.models import Topic
9 10
10 -from .forms import ForumForm 11 +from .forms import ForumForm, PostForm, PostAnswerForm
11 12
12 class ForumIndex(LoginRequiredMixin, generic.ListView): 13 class ForumIndex(LoginRequiredMixin, generic.ListView):
13 login_url = reverse_lazy("core:home") 14 login_url = reverse_lazy("core:home")
@@ -20,28 +21,97 @@ class ForumIndex(LoginRequiredMixin, generic.ListView): @@ -20,28 +21,97 @@ class ForumIndex(LoginRequiredMixin, generic.ListView):
20 forum_id = self.request.GET.get('forum_id', 0) 21 forum_id = self.request.GET.get('forum_id', 0)
21 22
22 context = Forum.objects.get(id = forum_id) 23 context = Forum.objects.get(id = forum_id)
  24 +
  25 + return context
  26 +
  27 + def get_context_data(self, **kwargs):
  28 + context = super(ForumIndex, self).get_context_data(**kwargs)
  29 + context['form'] = PostForm()
23 30
24 return context 31 return context
25 32
26 class CreateForumView(LoginRequiredMixin, generic.edit.CreateView): 33 class CreateForumView(LoginRequiredMixin, generic.edit.CreateView):
  34 + login_url = reverse_lazy("core:home")
  35 + redirect_field_name = 'next'
27 36
28 template_name = 'forum/forum_form.html' 37 template_name = 'forum/forum_form.html'
29 form_class = ForumForm 38 form_class = ForumForm
30 - success_url = reverse_lazy('forum:index') 39 +
  40 + def form_invalid(self, form):
  41 + return self.render_to_response(self.get_context_data(form = form), status = 400)
31 42
32 -class PostIndex(LoginRequiredMixin, generic.ListView): 43 + def get_success_url(self):
  44 + print("Pass")
  45 + self.success_url = reverse('forum:render_forum', args = (self.object.id, ))
  46 +
  47 + return self.success_url
  48 +
  49 +def render_forum(request, forum):
  50 + last_forum = get_object_or_404(Forum, id = forum)
  51 +
  52 + return HttpResponse(str(reverse_lazy('forum:index')) + '-' + str(forum) + '-' + str(last_forum.name))
  53 +
  54 +class ForumDeleteView(LoginRequiredMixin, generic.DeleteView):
  55 + login_url = reverse_lazy("core:home")
  56 + redirect_field_name = 'next'
  57 +
  58 + model = Forum
  59 + pk_url_kwarg = 'pk'
  60 + success_url = reverse_lazy('forum:deleted_forum')
  61 +
  62 +def forum_deleted(request):
  63 + return HttpResponse(_("Forum deleted successfully."))
  64 +
  65 +class CreatePostView(LoginRequiredMixin, generic.edit.CreateView):
33 login_url = reverse_lazy("core:home") 66 login_url = reverse_lazy("core:home")
34 redirect_field_name = 'next' 67 redirect_field_name = 'next'
35 68
36 - template_name = "post/post_list.html"  
37 - context_object_name = 'posts' 69 + form_class = PostForm
38 70
39 - def get_queryset(self):  
40 - forum = get_object_or_404(Forum, slug = self.request.GET.get('forum', '')) 71 + def form_valid(self, form):
  72 + self.object = form.save(commit = False)
  73 + self.object.user = self.request.user
41 74
42 - context = Post.objects.filter(forum = forum) 75 + self.object.save()
43 76
44 - return context 77 + return super(CreatePostView, self).form_valid(form)
  78 +
  79 + def get_success_url(self):
  80 + self.success_url = reverse('forum:render_post', args = (self.object.id, ))
  81 +
  82 + return self.success_url
  83 +
  84 +def render_post(request, post):
  85 + last_post = get_object_or_404(Post, id = post)
  86 +
  87 + context = {}
  88 + context['post'] = last_post
  89 +
  90 + return render(request, "post/post_render.html", context)
  91 +
  92 +class PostUpdateView(LoginRequiredMixin, generic.UpdateView):
  93 + login_url = reverse_lazy("core:home")
  94 + redirect_field_name = 'next'
  95 +
  96 + form_class = PostForm
  97 + model = Post
  98 + template_name = "post/post_update_form.html"
  99 +
  100 + def get_success_url(self):
  101 + self.success_url = reverse('forum:render_post', args = (self.object.id, ))
  102 +
  103 + return self.success_url
  104 +
  105 +class PostDeleteView(LoginRequiredMixin, generic.DeleteView):
  106 + login_url = reverse_lazy("core:home")
  107 + redirect_field_name = 'next'
  108 +
  109 + model = Post
  110 + pk_url_kwarg = 'pk'
  111 + success_url = reverse_lazy('forum:deleted_post')
  112 +
  113 +def post_deleted(request):
  114 + return HttpResponse(_("Post deleted successfully."))
45 115
46 class PostAnswerIndex(LoginRequiredMixin, generic.ListView): 116 class PostAnswerIndex(LoginRequiredMixin, generic.ListView):
47 login_url = reverse_lazy("core:home") 117 login_url = reverse_lazy("core:home")
@@ -55,4 +125,10 @@ class PostAnswerIndex(LoginRequiredMixin, generic.ListView): @@ -55,4 +125,10 @@ class PostAnswerIndex(LoginRequiredMixin, generic.ListView):
55 125
56 context = PostAnswer.objects.filter(post = post) 126 context = PostAnswer.objects.filter(post = post)
57 127
58 - return context  
59 \ No newline at end of file 128 \ No newline at end of file
  129 + return context
  130 +
  131 +class CreatePostAnswerView(LoginRequiredMixin, generic.edit.CreateView):
  132 +
  133 + template_name = 'post_answers/post_answer_form.html'
  134 + form_class = PostAnswerForm
  135 + success_url = reverse_lazy('forum:index')
60 \ No newline at end of file 136 \ No newline at end of file
poll/__init__.py 0 → 100644
poll/admin.py 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +from django.contrib import admin
  2 +
  3 +from .models import Poll, Answer
  4 +
  5 +class PollAdmin(admin.ModelAdmin):
  6 + list_display = ['name', 'slug','limit_date']
  7 + search_fields = ['name','slug']
  8 +
  9 +class AnswerAdmin(admin.ModelAdmin):
  10 + list_display = ['answer','order']
  11 + search_fields = ['answer']
  12 +
  13 +admin.site.register(Poll, PollAdmin)
  14 +admin.site.register(Answer, AnswerAdmin)
poll/apps.py 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +from django.apps import AppConfig
  2 +
  3 +
  4 +class PollConfig(AppConfig):
  5 + name = 'poll'
poll/forms.py 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +from django import forms
  2 +from django.utils.translation import ugettext_lazy as _
  3 +from users.models import User
  4 +from .models import Poll
  5 +
  6 +class PollForm(forms.ModelForm):
  7 +
  8 + def __init__(self, *args, **kwargs):
  9 + super(PollForm, self).__init__(*args, **kwargs)
  10 + self.fields["all_students"].required = False
  11 + self.fields["all_students"].initial = False
  12 + self.fields["students"].required = False
  13 +
  14 + def clean_all_students(self):
  15 + if('all_students' not in self.data):
  16 + if('students' in self.data):
  17 + return False
  18 + raise forms.ValidationError(_('It is required one these fields.'))
  19 + else:
  20 + all_students = self.data['all_students']
  21 + if(not all_students):
  22 + raise forms.ValidationError(_('It is required one these fields.'))
  23 + return True
  24 +
  25 +
  26 + class Meta:
  27 + model = Poll
  28 + fields = ['name','limit_date','students','all_students']
  29 +
  30 + widgets = {
  31 + 'name': forms.TextInput(attrs={'placeholder': 'Question?'}),
  32 + 'limit_date': forms.DateTimeInput(
  33 + attrs={'placeholder': 'Maximum date permited to resolve the poll'}),
  34 + 'student': forms.Select(),
  35 + }
poll/migrations/0001_initial.py 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2016-10-02 00:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +import django.db.models.deletion
  7 +
  8 +
  9 +class Migration(migrations.Migration):
  10 +
  11 + initial = True
  12 +
  13 + dependencies = [
  14 + ('courses', '0001_initial'),
  15 + ]
  16 +
  17 + operations = [
  18 + migrations.CreateModel(
  19 + name='Answer',
  20 + fields=[
  21 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  22 + ('answer', models.CharField(max_length=200, verbose_name='Answer')),
  23 + ('order', models.PositiveSmallIntegerField(verbose_name='Order')),
  24 + ],
  25 + options={
  26 + 'ordering': ('order',),
  27 + 'verbose_name': 'Answer',
  28 + 'verbose_name_plural': 'Answers',
  29 + },
  30 + ),
  31 + migrations.CreateModel(
  32 + name='Poll',
  33 + fields=[
  34 + ('activity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='courses.Activity')),
  35 + ],
  36 + options={
  37 + 'verbose_name': 'Poll',
  38 + 'verbose_name_plural': 'Polls',
  39 + },
  40 + bases=('courses.activity',),
  41 + ),
  42 + migrations.AddField(
  43 + model_name='answer',
  44 + name='poll',
  45 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='poll.Poll', verbose_name='Answers'),
  46 + ),
  47 + ]
poll/migrations/__init__.py 0 → 100644
poll/models.py 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +from django.utils.translation import ugettext_lazy as _
  2 +from django.db import models
  3 +from autoslug.fields import AutoSlugField
  4 +from users.models import User
  5 +from core.models import Resource
  6 +from courses.models import Activity
  7 +
  8 +class Poll(Activity):
  9 +
  10 + class Meta:
  11 + #ordering = ('create_date','name')
  12 + verbose_name = _('Poll')
  13 + verbose_name_plural = _('Polls')
  14 +
  15 + def __str__(self):
  16 + return str(self.name) + str("/") + str(self.topic)
  17 +
  18 +class Answer(models.Model):
  19 + answer = models.CharField(_("Answer"), max_length = 200)
  20 + order = models.PositiveSmallIntegerField(_("Order"))
  21 + poll = models.ForeignKey(Poll, verbose_name = _('Answers'), related_name='answers')
  22 +
  23 + class Meta:
  24 + ordering = ('order',)
  25 + verbose_name = _('Answer')
  26 + verbose_name_plural = _('Answers')
  27 +
  28 + def __str__(self):
  29 + return str(self.answer) + str("/") + str(self.poll)
poll/permissions.py 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +from rolepermissions.permissions import register_object_checker
  2 +from amadeus.roles import SystemAdmin
  3 +
  4 +@register_object_checker()
  5 +def edit_poll(role, user, poll):
  6 + if (role == SystemAdmin):
  7 + return True
  8 +
  9 + if (user in poll.topic.subject.professors.all()):
  10 + return True
  11 +
  12 + return False
poll/templates/poll/create_update.html 0 → 100644
@@ -0,0 +1,206 @@ @@ -0,0 +1,206 @@
  1 +{% extends "topic/index.html" %}
  2 +
  3 +{% load i18n widget_tweaks dict_access static%}
  4 +
  5 +{% block style %}
  6 + <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  7 +{% endblock %}
  8 +
  9 +{% block content %}
  10 +<!-- Modal (remember to change the ids!!!) -->
  11 +<div class="modal fade" id="poll" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  12 + <div class="modal-dialog" role="document">
  13 + <div class="modal-content">
  14 +
  15 + <!-- Modal Header -->
  16 + <div class="modal-header">
  17 +
  18 + <!-- Put your title here!!! -->
  19 + <h4 class="modal-title" id="myModalLabel">{% trans "Create a Poll" %}</h4>
  20 +
  21 + </div>
  22 + <!-- Modal Body -->
  23 + <div class="modal-body">
  24 +
  25 + <!-- Put ONLY your content here!!! -->
  26 + <div class="conteiner">
  27 + <div class="row form-group">
  28 + <div class="col-md-1">
  29 + </br>
  30 + <label><span class="glyphicon glyphicon-hand-right"></span></label>
  31 + </div>
  32 + <div class="col-md-10">
  33 + <div class="has-success">
  34 + <input form="form" type="text" name="{{form.name.name}}" {% if form.name.value != None %}value="{{form.name.value}}" {% endif %} class="form-control" placeholder='{% trans "Question?" %}'>
  35 + <span class="help-block">{% trans "A Question to be answered" %}</span>
  36 + </div>
  37 + </div>
  38 + {% if form.name.errors %}
  39 + <div class="col-md-10 not_submited">
  40 + </br>
  41 + <div class="alert alert-danger alert-dismissible" role="alert">
  42 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  43 + <span aria-hidden="true">&times;</span>
  44 + </button>
  45 + <ul>
  46 + {% for error in form.name.errors %}
  47 + <li>{{ error }}</li>
  48 + {% endfor %}
  49 + </ul>
  50 + </div>
  51 + </div>
  52 + {% endif %}
  53 + </div>
  54 + <form id="form" class="" action="" method="post">
  55 + {% csrf_token %}
  56 + {% for key in keys %}
  57 + <div class="row form-group">
  58 + <div class="col-md-1">
  59 + </br>
  60 + <label><span class="glyphicon glyphicon-move"></span></label>
  61 + </div>
  62 + <div class="col-md-10">
  63 + <div class="has-success is-empty">
  64 + <input type="text" name="{{key}}" class="form-control" placeholder='{% trans "Answer" %}' value="{{ answers|value:key }}">
  65 + <span class="help-block">{% trans "Possible answer for the question" %}</span>
  66 + </div>
  67 + </div>
  68 + <div class="col-md-1">
  69 + </br>
  70 + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>
  71 + </div>
  72 + </div>
  73 + {% empty %}
  74 + <div class="row form-group">
  75 + <div class="col-md-1">
  76 + </br>
  77 + <label><span class="glyphicon glyphicon-move"></span></label>
  78 + </div>
  79 + <div class="col-md-10">
  80 + <div class="has-success is-empty">
  81 + <input type="text" name="1" class="form-control" placeholder='{% trans "Answer" %}'>
  82 + <span class="help-block">{% trans "Possible answer for the question" %}</span>
  83 + </div>
  84 + </div>
  85 + <div class="col-md-1">
  86 + </br>
  87 + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>
  88 + </div>
  89 + </div>
  90 + {% endfor %}
  91 + </form>
  92 + </br>
  93 + </div>
  94 + <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button>
  95 + <div class="row form-group">
  96 + <label for="{{ form.limit_date.auto_id }}">{{ form.limit_date.label }}</label>
  97 + {% render_field form.limit_date class="form-control" form="form"%}
  98 + {# <input form="form" class="form-control" type="date" name="{{form.limit_date.name}}" {% if form.limit_date.value != None %}value="{% if form.limit_date.value.year %}{{form.limit_date.value|date:'Y-m-d'}}{% else %}{{form.limit_date.value}}{% endif %}"{% endif %}>#}
  99 + {% if form.limit_date.errors %}
  100 + <div class="not_submited">
  101 + </br>
  102 + <div class="alert alert-danger alert-dismissible" role="alert">
  103 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  104 + <span aria-hidden="true">&times;</span>
  105 + </button>
  106 + <ul>
  107 + {% for error in form.limit_date.errors %}
  108 + <li>{{ error }}</li>
  109 + {% endfor %}
  110 + </ul>
  111 + </div>
  112 + </div>
  113 + {% endif %}
  114 + </div>
  115 +
  116 + <div class="row form-group">
  117 + <label for="{{ form.students.auto_id }}">{{ form.students.label }}</label>
  118 + {% render_field form.students class="form-control" form="form"%}
  119 + </div>
  120 + <div class="row form-group">
  121 + <div class="checkbox">
  122 + <label>
  123 + {% render_field form.all_students class="form-control" form="form" %}<span class="checkbox-material"><span class="check"></span></span> {{form.all_students.label }}
  124 + {# <input form="form" type="checkbox" name="{{form.all_students.name}}"><span class="checkbox-material"><span class="check"></span></span> {{ form.all_students.label }}#}
  125 + </label>
  126 + </div>
  127 + {% if form.all_students.errors %}
  128 + <div class="not_submited">
  129 + </br>
  130 + <div class="alert alert-danger alert-dismissible" role="alert">
  131 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  132 + <span aria-hidden="true">&times;</span>
  133 + </button>
  134 + <ul>
  135 + {% for error in form.all_students.errors %}
  136 + <li>{{ error }}</li>
  137 + {% endfor %}
  138 + </ul>
  139 + </div>
  140 + </div>
  141 + {% endif %}
  142 +
  143 + {# <label for="{{ form.all_students.auto_id }}">{{ form.all_students.label }}</label>#}
  144 + {# {% render_field form.all_students class="form-control" form="form"%}#}
  145 + </div>
  146 +
  147 + </div>
  148 +
  149 + <!-- Modal Footer -->
  150 + <div class="modal-footer">
  151 +
  152 + <!-- Don't remove that!!! -->
  153 + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  154 +
  155 + <!-- Put curtom buttons here!!! -->
  156 + <button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Create" %}</button>
  157 + </div>
  158 +
  159 + </div>
  160 + </div>
  161 +</div>
  162 +<script type="text/javascript">
  163 +// Este js tem que ficar aqui se não a tag "trans" não vai funcionar
  164 +$(window).ready(function() { // utilizado para abrir o modal quando tiver tido algum erro no preenchimento do formulario
  165 + if($('.not_submited').length){
  166 + $('#poll').modal('show');
  167 + }
  168 +});
  169 +$( "#form" ).sortable({ // utilizado para fazer a re-organização das respostas
  170 + delay: 100,
  171 + distance: 5,
  172 + update: function( event, ui ) {
  173 + var cont = 1;
  174 + $("#form div div div input").each(function(){
  175 + $(this).attr('name',cont++);
  176 + });
  177 + },
  178 +});
  179 +name = 2;
  180 +$("#add").click(function() { // utilizado para adicionar um novo campo de resposta
  181 + //Obs: não funcionar se estiver importado no head, só funciona se estiver no final do arquivo
  182 + $("#form").append('\
  183 + <div class="row form-group">\
  184 + <div class="col-md-1">\
  185 + </br>\
  186 + <label><span class="glyphicon glyphicon-move"></span></label>\
  187 + </div>\
  188 + <div class="col-md-10">\
  189 + <div class="has-success is-empty">\
  190 + <input type="text" name="1" class="form-control" placeholder="{% trans "Answer" %}">\
  191 + <span class="help-block">{% trans "Possible answer for the question" %}</span>\
  192 + </div>\
  193 + </div>\
  194 + <div class="col-md-1">\
  195 + </br>\
  196 + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>\
  197 + </div>\
  198 + </div>');
  199 + var cont = 1;
  200 + $("#form div div div input").each(function(){
  201 + $(this).attr('name',cont++);
  202 + });
  203 +});
  204 +</script>
  205 +<a href="" data-toggle="modal" data-target="#poll">modal</a>
  206 +{% endblock content %}
poll/templates/poll/view.html 0 → 100644
@@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
  1 +{% extends "topic/index.html" %}
  2 +
  3 +{% load i18n widget_tweaks dict_access static%}
  4 +{% block content %}
  5 +<!-- Modal (remember to change the ids!!!) -->
  6 +<div class="modal fade" id="poll" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  7 + <div class="modal-dialog" role="document">
  8 + <div class="modal-content">
  9 +
  10 + <!-- Modal Header -->
  11 + <div class="modal-header">
  12 +
  13 + <!-- Put your title here!!! -->
  14 + <h4 class="modal-title" id="myModalLabel">{{form.question}}</h4>
  15 +
  16 + </div>
  17 + <!-- Modal Body -->
  18 + <div class="modal-body">
  19 +
  20 + <!-- Put ONLY your content here!!! -->
  21 + <div class="conteiner">
  22 + </div>
  23 + <form id="form" method="post">
  24 + {% csrf_token %}
  25 + {% for key in keys %}
  26 + <div class="row form-group">
  27 + <div class="col-md-1">
  28 + </br>
  29 + <label><span class="glyphicon glyphicon-move"></span></label>
  30 + </div>
  31 + <div class="col-md-10">
  32 + <div class="has-success is-empty">
  33 + <input type="text" name="{{key}}" class="form-control" placeholder='{% trans "Answer" %}' value="{{ answers|value:key }}">
  34 + <span class="help-block">{% trans "Possible answer for the question" %}</span>
  35 + </div>
  36 + </div>
  37 + <div class="col-md-1">
  38 + </br>
  39 + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>
  40 + </div>
  41 + </div>
  42 + {% empty %}
  43 + <div class="row form-group">
  44 + <div class="col-md-1">
  45 + </br>
  46 + <label><span class="glyphicon glyphicon-move"></span></label>
  47 + </div>
  48 + <div class="col-md-10">
  49 + <div class="has-success is-empty">
  50 + <input type="text" name="1" class="form-control" placeholder='{% trans "Answer" %}'>
  51 + <span class="help-block">{% trans "Possible answer for the question" %}</span>
  52 + </div>
  53 + </div>
  54 + <div class="col-md-1">
  55 + </br>
  56 + <label><span class="glyphicon glyphicon-remove" onclick="this.parentNode.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode.parentNode);"></span></label>
  57 + </div>
  58 + </div>
  59 + {% endfor %}
  60 + </form>
  61 + </br>
  62 + </div>
  63 + <button type="button" id="add" class="btn btn-primary btn-block btn-sm">add</button>
  64 + <div class="row form-group">
  65 + <input form="form" class="form-control" type="date" name="{{form.limit_date.name}}" {% if form.limit_date.value != None %}value="{% if form.limit_date.value.year %}{{form.limit_date.value|date:'Y-m-d'}}{% else %}{{form.limit_date.value}}{% endif %}"{% endif %}>
  66 + {% if form.limit_date.errors %}
  67 + <div class="not_submited">
  68 + </br>
  69 + <div class="alert alert-danger alert-dismissible" role="alert">
  70 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  71 + <span aria-hidden="true">&times;</span>
  72 + </button>
  73 + <ul>
  74 + {% for error in form.limit_date.errors %}
  75 + <li>{{ error }}</li>
  76 + {% endfor %}
  77 + </ul>
  78 + </div>
  79 + </div>
  80 + {% endif %}
  81 + </div>
  82 +
  83 + </div>
  84 +
  85 + <!-- Modal Footer -->
  86 + <div class="modal-footer">
  87 +
  88 + <!-- Don't remove that!!! -->
  89 + <button type="button" class="btn btn-danger btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  90 +
  91 + <!-- Put curtom buttons here!!! -->
  92 + <button type="submite" id="button" form="form" class="btn btn-primary btn-raised">{% trans "Create" %}</button>
  93 + </div>
  94 +
  95 + </div>
  96 + </div>
  97 +</div>
  98 +<a href="" data-toggle="modal" data-target="#poll">modal</a>
  99 +{% endblock content %}
poll/templatetags/__init__.py 0 → 100644
poll/templatetags/dict_access.py 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +from django import template
  2 +
  3 +from forum.models import Forum
  4 +
  5 +register = template.Library()
  6 +
  7 +"""
  8 + Template tag to load all the foruns of a post
  9 +"""
  10 +
  11 +@register.filter
  12 +def value(dictionary, key):
  13 + return dictionary[key]
poll/tests.py 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
poll/urls.py 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +from django.conf.urls import url
  2 +
  3 +from . import views
  4 +
  5 +urlpatterns = [
  6 + url(r'^create/(?P<slug>[\w\-_]+)/$', views.CreatePoll.as_view(), name='create_poll'), # topic slug
  7 + url(r'^update/(?P<slug>[\w\-_]+)/$', views.UpdatePoll.as_view(), name='update_poll'), # poll slug
  8 +
  9 +]
poll/views.py 0 → 100644
@@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
  1 +from django.shortcuts import render, get_object_or_404, redirect
  2 +from django.views import generic
  3 +from django.contrib.auth.decorators import login_required
  4 +from django.core.paginator import Paginator, EmptyPage
  5 +from django.contrib.auth.mixins import LoginRequiredMixin
  6 +from rolepermissions.mixins import HasRoleMixin
  7 +from django.core.urlresolvers import reverse_lazy
  8 +from django.utils.translation import ugettext_lazy as _
  9 +from rolepermissions.verifications import has_role
  10 +from rolepermissions.verifications import has_object_permission
  11 +# from django.views.generic.edit import FormMixin
  12 +
  13 +from .forms import PollForm
  14 +from .models import Poll, Answer
  15 +from core.mixins import NotificationMixin
  16 +from users.models import User
  17 +from courses.models import Course, Topic
  18 +
  19 +class CreatePoll(LoginRequiredMixin,generic.CreateView):
  20 +
  21 + login_url = reverse_lazy("core:home")
  22 + redirect_field_name = 'next'
  23 + model = Poll
  24 + form_class = PollForm
  25 + context_object_name = 'poll'
  26 + template_name = 'poll/create_update.html'
  27 + success_url = reverse_lazy('core:home')
  28 +
  29 + def form_invalid(self, form,**kwargs):
  30 + context = super(CreatePoll, self).form_invalid(form)
  31 + answers = {}
  32 + for key in self.request.POST:
  33 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  34 + answers[key] = self.request.POST[key]
  35 +
  36 + keys = sorted(answers)
  37 + context.context_data['answers'] = answers
  38 + context.context_data['keys'] = keys
  39 + return context
  40 +
  41 + def form_valid(self, form):
  42 + self.object = form.save(commit = False)
  43 + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
  44 + self.object.topic = topic
  45 + self.object.save()
  46 +
  47 + for key in self.request.POST:
  48 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  49 + answer = Answer(answer=self.request.POST[key],order=key,poll=self.object)
  50 + answer.save()
  51 +
  52 + return super(CreatePoll, self).form_valid(form)
  53 +
  54 + def get_context_data(self, **kwargs):
  55 + context = super(CreatePoll, self).get_context_data(**kwargs)
  56 + topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
  57 + context['course'] = topic.subject.course
  58 + context['subject'] = topic.subject
  59 + context['subjects'] = topic.subject.course.subjects.all()
  60 + return context
  61 +
  62 +class UpdatePoll(LoginRequiredMixin,generic.UpdateView):
  63 +
  64 + login_url = reverse_lazy("core:home")
  65 + redirect_field_name = 'next'
  66 + model = Poll
  67 + form_class = PollForm
  68 + context_object_name = 'poll'
  69 + template_name = 'poll/create_update.html'
  70 + success_url = reverse_lazy('core:home')
  71 +
  72 + def dispatch(self, *args, **kwargs):
  73 + poll = get_object_or_404(Poll, slug = self.kwargs.get('slug'))
  74 + if(not has_object_permission('edit_poll', self.request.user, poll)):
  75 + return self.handle_no_permission()
  76 + return super(UpdatePoll, self).dispatch(*args, **kwargs)
  77 +
  78 + def get_object(self, queryset=None):
  79 + return get_object_or_404(Poll, slug = self.kwargs.get('slug'))
  80 +
  81 + def form_invalid(self, form,**kwargs):
  82 + context = super(UpdatePoll, self).form_invalid(form)
  83 + answers = {}
  84 + for key in self.request.POST:
  85 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  86 + answers[key] = self.request.POST[key]
  87 +
  88 + keys = sorted(answers)
  89 + context.context_data['answers'] = answers
  90 + context.context_data['keys'] = keys
  91 + return context
  92 +
  93 + def form_valid(self, form):
  94 + poll = self.object
  95 + poll = form.save(commit = False)
  96 + poll.answers.all().delete()
  97 + poll.save()
  98 +
  99 +
  100 + for key in self.request.POST:
  101 + if(key != 'csrfmiddlewaretoken' and key != 'name' and key != 'limit_date' and key != 'all_students' and key != 'students'):
  102 + answer = Answer(answer=self.request.POST[key],order=key,poll=poll)
  103 + answer.save()
  104 +
  105 + return super(UpdatePoll, self).form_valid(form)
  106 +
  107 + def get_context_data(self, **kwargs):
  108 + context = super(UpdatePoll, self).get_context_data(**kwargs)
  109 + poll = self.object
  110 + context['course'] = poll.topic.subject.course
  111 + context['subject'] = poll.topic.subject
  112 + context['subjects'] = poll.topic.subject.course.subjects.all()
  113 +
  114 + answers = {}
  115 + for answer in poll.answers.all():
  116 + # print (key.answer)
  117 + answers[answer.order] = answer.answer
  118 +
  119 + keys = sorted(answers)
  120 + context['answers'] = answers
  121 + context['keys'] = keys
  122 +
  123 + return context
requirements.txt
@@ -5,12 +5,16 @@ Django==1.10 @@ -5,12 +5,16 @@ Django==1.10
5 django-autoslug==1.9.3 5 django-autoslug==1.9.3
6 django-bootstrap-breadcrumbs==0.8 6 django-bootstrap-breadcrumbs==0.8
7 django-discover-runner==1.0 7 django-discover-runner==1.0
  8 +django-floppyforms==1.7.0
8 django-role-permissions==1.2.1 9 django-role-permissions==1.2.1
  10 +django-s3direct==0.4.2
9 django-widget-tweaks==1.4.1 11 django-widget-tweaks==1.4.1
10 djangorestframework==3.4.6 12 djangorestframework==3.4.6
11 Jinja2==2.8 13 Jinja2==2.8
12 MarkupSafe==0.23 14 MarkupSafe==0.23
13 Pillow==3.3.1 15 Pillow==3.3.1
  16 +pkg-resources==0.0.0
  17 +psycopg2==2.6.2
14 pycpfcnpj==1.0.2 18 pycpfcnpj==1.0.2
15 six==1.10.0 19 six==1.10.0
16 -psycopg2==2.6.2  
17 \ No newline at end of file 20 \ No newline at end of file
  21 +psycopg2==2.6.2
users/forms.py
@@ -27,25 +27,6 @@ class ProfileForm(forms.ModelForm): @@ -27,25 +27,6 @@ class ProfileForm(forms.ModelForm):
27 } 27 }
28 28
29 class UserForm(RegisterUserForm): 29 class UserForm(RegisterUserForm):
30 - def save(self, commit=True):  
31 - super(UserForm, self).save()  
32 -  
33 - if not self.instance.image:  
34 - self.instance.image = os.path.join(os.path.dirname(settings.BASE_DIR), 'uploads', 'no_image.jpg')  
35 -  
36 - self.instance.set_password(self.cleaned_data['password1'])  
37 - self.instance.save()  
38 -  
39 - if self.instance.is_staff:  
40 - assign_role(self.instance, 'system_admin')  
41 - elif self.instance.type_profile == 2:  
42 - assign_role(self.instance, 'student')  
43 - elif self.instance.type_profile == 1:  
44 - assign_role(self.instance, 'professor')  
45 -  
46 - self.instance.save()  
47 -  
48 - return self.instance  
49 30
50 class Meta: 31 class Meta:
51 model = User 32 model = User
@@ -59,7 +40,8 @@ class EditUserForm(forms.ModelForm): @@ -59,7 +40,8 @@ class EditUserForm(forms.ModelForm):
59 40
60 # Ailson 41 # Ailson
61 class UpdateUserForm(forms.ModelForm): 42 class UpdateUserForm(forms.ModelForm):
  43 + company_logo = forms.ImageField(label=_('Company Logo'),required=False, error_messages = {'invalid':_("Image files only")})
62 44
63 - class Meta:  
64 - model = User  
65 - fields = ['username', 'name', 'email', 'city', 'state', 'birth_date', 'gender', 'cpf', 'phone', 'image'] 45 + class Meta:
  46 + model = User
  47 + fields = ['username', 'name', 'email', 'city', 'state', 'birth_date', 'gender', 'cpf', 'phone', 'image']
66 \ No newline at end of file 48 \ No newline at end of file
users/migrations/0001_initial.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 -# Generated by Django 1.10 on 2016-09-21 02:52 2 +# Generated by Django 1.10 on 2016-10-02 00:17
3 from __future__ import unicode_literals 3 from __future__ import unicode_literals
4 4
5 import django.contrib.auth.models 5 import django.contrib.auth.models
users/templates/list_users.html
@@ -63,9 +63,29 @@ @@ -63,9 +63,29 @@
63 <p>{% trans 'Contact' %}: {{ acc.phone }}</p> 63 <p>{% trans 'Contact' %}: {{ acc.phone }}</p>
64 <div align="right"> 64 <div align="right">
65 <a href="{% url 'users:update' acc.username %}" class="btn btn-raised btn-success">{% trans 'Edit' %}</a> 65 <a href="{% url 'users:update' acc.username %}" class="btn btn-raised btn-success">{% trans 'Edit' %}</a>
66 - <a href="javascript:void(0)" class="btn btn-raised btn-primary">{% trans 'Delete' %}</a> 66 + <a href="javascript:void(0)" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#DeleteModal{{ forloop.counter }}">{% trans 'Delete' %}</a>
67 </div> 67 </div>
68 </div> 68 </div>
  69 +
  70 +
  71 + <!-- Modal -->
  72 + <div class="modal fade" id="DeleteModal{{ forloop.counter }}" tabindex="-1" role="dialog" aria-labelledby="DeleteModalLabel">
  73 + <div class="modal-dialog" role="document">
  74 + <div class="modal-content">
  75 + <div class="modal-header">
  76 + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  77 + <h4 class="modal-title" id="DeleteModalLabel">Confirm delete</h4>
  78 + </div>
  79 + <div class="modal-body">
  80 + Are you sure you want to delete the user <b>{{acc.name}}</b>?
  81 + </div>
  82 + <div class="modal-footer">
  83 + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  84 + <button type="button" class="btn btn-primary"> <a href="{% url 'users:delete' acc.username %}">Delete</a></button>
  85 + </div>
  86 + </div>
  87 + </div>
  88 + </div>
69 </div> 89 </div>
70 </div> 90 </div>
71 {% endfor %} 91 {% endfor %}
users/templates/users/create.html
@@ -33,10 +33,18 @@ @@ -33,10 +33,18 @@
33 {% for field in form %} 33 {% for field in form %}
34 <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput"> 34 <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
35 {% if field.auto_id == 'id_birth_date' %} 35 {% if field.auto_id == 'id_birth_date' %}
36 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 36 + {% if field.field.required %}
  37 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  38 + {% else %}
  39 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  40 + {% endif %}
37 <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}"> 41 <input type="date" class="form-control"name="{{field.name}}" value="{% if field.value.year %}{{field.value|date:'Y-m-d'}}{% else %}{{field.value}}{% endif %}">
38 {% elif field.auto_id == 'id_image' %} 42 {% elif field.auto_id == 'id_image' %}
39 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 43 + {% if field.field.required %}
  44 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  45 + {% else %}
  46 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  47 + {% endif %}
40 {% render_field field class='form-control' %} 48 {% render_field field class='form-control' %}
41 <div class="input-group"> 49 <div class="input-group">
42 <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}"> 50 <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}">
@@ -53,15 +61,23 @@ @@ -53,15 +61,23 @@
53 </label> 61 </label>
54 </div> 62 </div>
55 {% elif field.auto_id == 'id_cpf' %} 63 {% elif field.auto_id == 'id_cpf' %}
56 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 64 + {% if field.field.required %}
  65 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  66 + {% else %}
  67 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  68 + {% endif %}
57 {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %} 69 {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %}
58 {% else %} 70 {% else %}
59 - <label for="{{ field.auto_id }}">{{ field.label }}</label> 71 + {% if field.field.required %}
  72 + <label for="{{ field.auto_id }}">{{ field.label }}<span>*</span></label>
  73 + {% else %}
  74 + <label for="{{ field.auto_id }}">{{ field.label }}</label>
  75 + {% endif %}
60 {% render_field field class='form-control' %} 76 {% render_field field class='form-control' %}
61 {% endif %} 77 {% endif %}
62 <span id="helpBlock" class="help-block">{{ field.help_text }}</span> 78 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
63 - {% if field.errors.length > 0 %}  
64 - <div class="alert alert-danger alert-dismissible" role="alert"> 79 + {% if field.errors %}
  80 + <div class="alert alert-danger alert-dismissible col-md-offset-4 col-md-8" role="alert">
65 <button type="button" class="close" data-dismiss="alert" aria-label="Close"> 81 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
66 <span aria-hidden="true">&times;</span> 82 <span aria-hidden="true">&times;</span>
67 </button> 83 </button>
users/templates/users/profile.html
@@ -28,10 +28,8 @@ @@ -28,10 +28,8 @@
28 28
29 {% block content %} 29 {% block content %}
30 <div class="row"> 30 <div class="row">
31 - <div class="row">  
32 - <div class="col-lg-offset-4 col-lg-2">  
33 - <img src="" class="img-responsive center-block " alt="logo amadeus">  
34 - </div> 31 + <div class="col-lg-offset-4 col-lg-2">
  32 + <img src="" class="img-responsive center-block " alt="logo amadeus">
35 </div> 33 </div>
36 </div> 34 </div>
37 <div class="row"> 35 <div class="row">
users/templates/users/update.html
@@ -46,18 +46,14 @@ @@ -46,18 +46,14 @@
46 </button> 46 </button>
47 </span> 47 </span>
48 </div> 48 </div>
49 - {% elif field.auto_id == 'id_is_staff' or field.auto_id == 'id_is_active' %}  
50 - <div class="checkbox">  
51 - <label>  
52 - {% render_field field type='checkbox' %}  
53 - </label>  
54 - </div> 49 + {% elif field.auto_id == 'id_cpf' %}
  50 + {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %}
55 {% else %} 51 {% else %}
56 {% render_field field class='form-control' %} 52 {% render_field field class='form-control' %}
57 <span id="helpBlock" class="help-block">{{ field.help_text }}</span> 53 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
58 {% endif %} 54 {% endif %}
59 - {% if field.errors.length > 0 %}  
60 - <div class="alert alert-danger alert-dismissible" role="alert"> 55 + {% if field.errors %}
  56 + <div class="alert alert-danger alert-dismissible col-md-offset-4 col-md-8" role="alert">
61 <button type="button" class="close" data-dismiss="alert" aria-label="Close"> 57 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
62 <span aria-hidden="true">&times;</span> 58 <span aria-hidden="true">&times;</span>
63 </button> 59 </button>
@@ -67,7 +63,6 @@ @@ -67,7 +63,6 @@
67 {% endfor %} 63 {% endfor %}
68 </ul> 64 </ul>
69 </div> 65 </div>
70 - </div>  
71 {% endif %} 66 {% endif %}
72 </div> 67 </div>
73 {% endfor %} 68 {% endfor %}
users/tests.py
@@ -4,31 +4,60 @@ from django.core.urlresolvers import reverse @@ -4,31 +4,60 @@ from django.core.urlresolvers import reverse
4 from .models import * 4 from .models import *
5 from .forms import * 5 from .forms import *
6 6
7 -# Create your tests here.  
8 -# class TestCreateUser(TestCase):  
9 -  
10 -# def setUp(self):  
11 -# self.client = Client()  
12 -  
13 -# self.user = User.objects.create_user(  
14 -# username = 'test',  
15 -# email = 'testing@amadeus.com',  
16 -# is_staff = True,  
17 -# is_active = True,  
18 -# password = 'testing'  
19 -# )  
20 -# assign_role(self.user, 'system_admin')  
21 -  
22 -# def test_edit_users(self):  
23 -# self.client.login(username='test', password='testing')  
24 -  
25 -# url = reverse('users:edit_profile', kwargs={'username': self.user.username})  
26 -# data = EditUserForm().data  
27 -# data['email'] = "testing2@amadeus.com"  
28 -  
29 -# # response = self.client.put(url, data, format='json')  
30 -# self.assertEqual(response.status_code, 200)  
31 -# self.assertEqual(response.data['email'], data['email']) 7 +#Create your tests here.
  8 +class TestUserCase(TestCase):
  9 +
  10 + def setUp(self):
  11 + self.client = Client()
  12 +
  13 + self.user = User.objects.create_user(
  14 + username = 'test',
  15 + email = 'testing@amadeus.com',
  16 + is_staff = True,
  17 + is_active = True,
  18 + password = 'testing'
  19 + )
  20 + assign_role(self.user, 'system_admin')
  21 +
  22 + # def test_edit_users(self):
  23 + # self.client.login(username='test', password='testing')
  24 +
  25 + # url = reverse('users:edit_profile', kwargs={'username': self.user.username})
  26 + # data = EditUserForm().data
  27 + # data['email'] = "testing2@amadeus.com"
  28 +
  29 + # response = self.client.put(url, data, format='json')
  30 + # self.assertEqual(response.status_code, 200)
  31 + # self.assertEqual(response.data['email'], data['email'])
  32 +
  33 + def test_delete_users(self):
  34 + self.user1 = User.objects.create_user(
  35 + username = "user1",
  36 + email = 'user1@user1.com',
  37 + password = 'user1test',
  38 + cpf = '11111111111'
  39 + )
  40 + self.user2 = User.objects.create_user(
  41 + username = "user2",
  42 + email = 'user2@user2.com',
  43 + password = 'user2test',
  44 + cpf = '53574660332'
  45 + )
  46 + self.user3 = User.objects.create_user(
  47 + username = "user3",
  48 + email = 'user3@user3.com',
  49 + password = 'user3test',
  50 + cpf = '63638052281'
  51 + )
  52 + self.client.login(username='user', password = 'testing')
  53 + users = User.objects.all().count()
  54 + url = reverse('users:delete',kwargs={'username': self.user2.username})
  55 + self.assertEqual(User.objects.all().count(),users) #Before deleting
  56 + response = self.client.post(url)
  57 + self.assertEqual(User.objects.all().count(),users - 1) #After deleting one user, if OK, the user was removed successfully.
  58 +
  59 +
  60 +
32 61
33 62
34 63