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
amadeus/settings.py
... ... @@ -53,6 +53,8 @@ INSTALLED_APPS = [
53 53 'courses',
54 54 'users',
55 55 'forum',
  56 + 'poll',
  57 + 's3direct',
56 58 ]
57 59  
58 60 MIDDLEWARE_CLASSES = [
... ... @@ -178,6 +180,31 @@ MESSAGE_TAGS = {
178 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 209 try:
183 210 from .local_settings import *
... ...
amadeus/urls.py
... ... @@ -26,6 +26,9 @@ urlpatterns = [
26 26 url(r'^forum/', include('forum.urls', namespace = 'forum')),
27 27 url(r'^admin/', admin.site.urls),
28 28 url(r'^', include('core.urls', namespace = 'core')),
  29 +
  30 + #S3Direct
  31 + url(r'^s3direct/', include('s3direct.urls')),
29 32 ]
30 33  
31 34 urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
... ...
core/context_processors.py
... ... @@ -5,6 +5,6 @@ def notifications(request):
5 5 context['notifications'] = None
6 6 if request.user.is_authenticated:
7 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 10 return context
... ...
core/forms.py
... ... @@ -15,31 +15,7 @@ class RegisterUserForm(forms.ModelForm):
15 15  
16 16 def validate_cpf(self, cpf):
17 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 19 if cpfcnpj.validate(cpf):
44 20 return True
45 21 return False
... ...
core/migrations/0001_initial.py
1 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 3 from __future__ import unicode_literals
4 4  
5 5 import autoslug.fields
6   -from django.conf import settings
7 6 from django.db import migrations, models
8 7 import django.db.models.deletion
9 8  
... ... @@ -13,7 +12,6 @@ class Migration(migrations.Migration):
13 12 initial = True
14 13  
15 14 dependencies = [
16   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17 15 ]
18 16  
19 17 operations = [
... ... @@ -33,7 +31,6 @@ class Migration(migrations.Migration):
33 31 name='Action_Resource',
34 32 fields=[
35 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 35 options={
39 36 'verbose_name': 'Action_Resource',
... ... @@ -45,8 +42,6 @@ class Migration(migrations.Migration):
45 42 fields=[
46 43 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
47 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 46 options={
52 47 'verbose_name': 'Log',
... ... @@ -61,8 +56,6 @@ class Migration(migrations.Migration):
61 56 ('read', models.BooleanField(default=False, verbose_name='Read')),
62 57 ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')),
63 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 60 options={
68 61 'verbose_name': 'Notification',
... ... @@ -74,7 +67,7 @@ class Migration(migrations.Migration):
74 67 fields=[
75 68 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
76 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 71 ('created_date', models.DateField(auto_now_add=True, verbose_name='Created Date')),
79 72 ('url', models.CharField(default='', max_length=100, verbose_name='URL')),
80 73 ],
... ... @@ -83,9 +76,4 @@ class Migration(migrations.Migration):
83 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 @@
  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 6  
7 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 10 "visualize post", etc. It is supposed to be created everytime we want an aciton
11 11 """
12 12  
13 13 name = models.CharField(_('Name'), max_length = 100)
14 14 created_date = models.DateField(_('Created Date'), auto_now_add=True)
15   -
  15 +
16 16 class Meta:
17 17 verbose_name = "Action"
18 18 verbose_name_plural = "Actions"
19 19  
20 20 def __str__(self):
21 21 return self.name
22   -
  22 +
23 23  
24 24 class Resource(models.Model):
25 25 """
... ... @@ -27,38 +27,38 @@ class Resource(models.Model):
27 27 Example: Pool was answered (Resource: Pool), PDF was visualized(Resource: PDF).
28 28  
29 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 31 by a huge amount of actions
32 32 @created_date: The date the resource was created
33 33 @link: Which URL made that resource able to find
34 34 """
35 35  
36 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 38 created_date = models.DateField(_('Created Date'), auto_now_add=True)
39 39 url = models.CharField(_('URL'), max_length =100, default="")
40 40  
41 41  
42 42 class Meta:
43 43 verbose_name = "Resource"
44   - verbose_name_plural = "Resources"
  44 + verbose_name_plural = "Resources"
45 45  
46 46 def __str__(self):
47 47 return self.name
48 48  
49 49  
50 50 class Action_Resource(models.Model):
51   -
  51 +
52 52 action = models.ForeignKey(Action , verbose_name= _('Action_Applied'))
53 53 resource = models.ForeignKey(Resource, verbose_name = _('Resource'))
54   -
  54 +
55 55 class Meta:
56 56 verbose_name = "Action_Resource"
57 57 verbose_name_plural = "Action_Resources"
58 58  
59 59 def __str__(self):
60 60 return ''.join([self.action.name, " / ", self.resource.name])
61   -
  61 +
62 62  
63 63 class Notification(models.Model):
64 64 """
... ... @@ -77,7 +77,7 @@ class Notification(models.Model):
77 77 datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True)
78 78 action_resource = models.ForeignKey(Action_Resource, verbose_name = _('Action_Resource'))
79 79 actor = models.ForeignKey(User, related_name = _('%(class)s_Performer'), verbose_name= _('Perfomer'), null = True)
80   -
  80 +
81 81 class Meta:
82 82 verbose_name = _("Notification")
83 83 verbose_name_plural = _("Notifications")
... ...
core/static/css/base/amadeus.css
... ... @@ -266,7 +266,6 @@ li.alert_li:hover{background-color:#eee}
266 266 a.alert_message{color : grey}
267 267 a.alert_message:hover{color : grey}
268 268  
269   -/*=================== Ailson - Please Don't touch*/
270 269 .breadcrumb .divider{
271 270 display: none;
272 271 }
... ... @@ -321,3 +320,5 @@ body .container .jumbotron-inverse, body .container .well-inverse, body .contain
321 320 .notification-count {
322 321 background-color: #FF0000;
323 322 }
  323 +
  324 +.datepicker{z-index:9999 !important}
324 325 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/alertify.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/alertify.rtl.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/themes/bootstrap.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/themes/bootstrap.rtl.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/themes/default.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/themes/default.rtl.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/themes/semantic.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/css/vendor/alertifyjs/themes/semantic.rtl.css 0 → 100644
... ... @@ -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 @@
  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 7 \ No newline at end of file
... ...
core/static/js/base/amadeus.js
... ... @@ -126,4 +126,18 @@ function validarCpfSemAlert(campo,nome,idElementoMensagemErro){
126 126 return true;
127 127 }
128 128 return retorno;
129   -}
130 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 1 $(document).ready(function(){
2 2 $('[data-toggle="tooltip"]').tooltip(); //activate tooltip on all elements that has attribute data-toggle
3   -});
4 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 27 \ No newline at end of file
... ...
core/static/js/vendor/alertify.min.js 0 → 100644
... ... @@ -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 4 \ No newline at end of file
... ...
core/templates/base.html
... ... @@ -8,7 +8,7 @@
8 8  
9 9 <meta http-equiv="Cache-Control" content="no-cache, no-store" />
10 10 <link href="{% static 'img/favicon.ico' %}" rel="shortcut icon" />
11   -
  11 +
12 12 <!-- Roboto font -->
13 13 <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
14 14 <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
... ... @@ -18,15 +18,18 @@
18 18 <script type="text/javascript" src="{% static 'js/vendor/jquery-ui.js' %}"></script>
19 19  
20 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 22 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/material.min.css' %}">
23 23 <link rel="stylesheet" type="text/css" href="{% static 'css/vendor/ripples.min.css' %}">
24 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 28 <script type="text/javascript" src="{% static 'js/vendor/bootstrap-acessibility.min.js' %}"></script>
27 29 <script type="text/javascript" src="{% static 'js/vendor/material.min.js' %}"></script>
28 30 <script type="text/javascript" src="{% static 'js/vendor/ripples.min.js' %}"></script>
29 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 34 <!-- Font awesome -->
32 35 <link rel="stylesheet" type="text/css" href="{% static 'font-awesome-4.6.3/css/font-awesome.min.css' %}">
... ... @@ -38,6 +41,8 @@
38 41 <script type="text/javascript">$.material.init()</script>
39 42  
40 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 46 {% block style %}
42 47 {% endblock %}
43 48 </head>
... ... @@ -57,44 +62,14 @@
57 62 <div class="navbar-collapse collapse navbar-responsive-collapse">
58 63 <ul class="nav navbar-nav navbar-right notifications">
59 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 66 <ul id="notification-dropdown" class="dropdown-menu">
62 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 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 73 <div class="row-content">
99 74 <p class="list-group-item-text">See More</p>
100 75 </div>
... ... @@ -141,8 +116,6 @@
141 116 </div>
142 117 </div>
143 118 </div>
144   -
145   -
146 119 </div>
147 120 </div>
148 121 </body>
... ...
core/templates/index.html
... ... @@ -59,7 +59,7 @@
59 59 </div>
60 60 </form>
61 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 63 </div>
64 64 {# </div> #}
65 65 {# <div class="row"> #}
... ...
core/templates/notifications.html 0 → 100644
... ... @@ -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 34 \ No newline at end of file
... ...
core/templates/register_user.html
... ... @@ -8,11 +8,16 @@
8 8  
9 9  
10 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 21 <div class="row logo-row">
17 22 <div class="col-lg-offset-2 col-lg-9">
18 23 <img src="{% static 'img/amadeus.png' %}" class="img-responsive center-block " alt="logo amadeus" id="logo">
... ... @@ -29,7 +34,11 @@
29 34 <legend>{% trans 'User Register' %}</legend>
30 35 {% for field in form %}
31 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 42 <div class="col-md-8">
34 43 {% if field.auto_id == 'id_birth_date' %}
35 44 {% render_field field class='form-control input-sm' type='date' %}
... ... @@ -81,5 +90,4 @@
81 90 </div>
82 91  
83 92 <br clear="all" />
84   - <script src="{% static 'js/base/amadeus.js' %}"></script>
85 93 {% endblock %}
... ...
core/templates/registration/passwor_reset_complete.html 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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 %}
... ...
core/tests.py
... ... @@ -89,7 +89,7 @@ class RegisterUserTestCase(TestCase):
89 89 }
90 90  
91 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 94 data = {
95 95 'username': '',
... ... @@ -102,7 +102,7 @@ class RegisterUserTestCase(TestCase):
102 102 'gender': 'F',
103 103 }
104 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 107 class RememberPasswordTestCase(TestCase):
108 108  
... ... @@ -194,7 +194,7 @@ class UpdateUserTestCase(TestCase):
194 194 'gender': 'F',
195 195 }
196 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 200 class DeleteUserTestCase(TestCase):
... ...
core/urls.py
1 1 from django.conf.urls import url, include
2 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 5 from . import views
5 6  
... ... @@ -9,5 +10,12 @@ urlpatterns = [
9 10 url(r'^register/$', views.RegisterUser.as_view(), name='register'),
10 11 url(r'^remember_password/$', views.remember_password, name='remember_password'),
11 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 ]
... ...
core/views.py
... ... @@ -5,8 +5,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin
5 5 from .decorators import log_decorator
6 6 from django.contrib import messages
7 7 from django.shortcuts import render, redirect
  8 +from django.template.loader import render_to_string
8 9 from django.views.generic import CreateView, UpdateView
9   -from django.http import HttpResponse
  10 +from django.http import HttpResponse, JsonResponse
10 11 from django.core.mail import send_mail,BadHeaderError
11 12 from django.conf import settings
12 13 from core.mixins import NotificationMixin
... ... @@ -95,6 +96,28 @@ def processNotification(self, notificationId):
95 96 notification.save()
96 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 121 # class LoginClass(LoginView):
99 122 # template_name='index.html'
100 123 #
... ...
courses/admin.py
1 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 5 class CategoryAdmin(admin.ModelAdmin):
6 6 list_display = ['name', 'slug']
... ... @@ -18,7 +18,17 @@ class TopicAdmin(admin.ModelAdmin):
18 18 list_display = ['name', 'slug']
19 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 29 admin.site.register(Category, CategoryAdmin)
22 30 admin.site.register(Course, CourseAdmin)
23 31 admin.site.register(Subject, SubjectAdmin)
24 32 admin.site.register(Topic, TopicAdmin)
  33 +admin.site.register(Activity,ActivityAdmin)
  34 +admin.site.register(Material,MaterialAdmin)
... ...
courses/forms.py
1   -
2 1 from django import forms
3 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 7 class CategoryForm(forms.ModelForm):
... ... @@ -153,3 +153,38 @@ class TopicForm(forms.ModelForm):
153 153 'name': _("Topic's name"),
154 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 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 3 from __future__ import unicode_literals
4 4  
5 5 import autoslug.fields
6   -from django.conf import settings
7 6 from django.db import migrations, models
8 7 import django.db.models.deletion
9 8  
... ... @@ -13,7 +12,6 @@ class Migration(migrations.Migration):
13 12 initial = True
14 13  
15 14 dependencies = [
16   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17 15 ('core', '0001_initial'),
18 16 ]
19 17  
... ... @@ -22,9 +20,8 @@ class Migration(migrations.Migration):
22 20 name='Activity',
23 21 fields=[
24 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 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 26 bases=('core.resource',),
30 27 ),
... ... @@ -37,8 +34,8 @@ class Migration(migrations.Migration):
37 34 ('create_date', models.DateField(auto_now_add=True, verbose_name='Creation Date')),
38 35 ],
39 36 options={
40   - 'verbose_name_plural': 'Categories',
41 37 'verbose_name': 'Category',
  38 + 'verbose_name_plural': 'Categories',
42 39 },
43 40 ),
44 41 migrations.CreateModel(
... ... @@ -56,22 +53,18 @@ class Migration(migrations.Migration):
56 53 ('init_date', models.DateField(verbose_name='Begin of Course Date')),
57 54 ('end_date', models.DateField(verbose_name='End of Course Date')),
58 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 57 options={
64   - 'verbose_name_plural': 'Courses',
65 58 'ordering': ('create_date', 'name'),
66 59 'verbose_name': 'Course',
  60 + 'verbose_name_plural': 'Courses',
67 61 },
68 62 ),
69 63 migrations.CreateModel(
70 64 name='Material',
71 65 fields=[
72 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 69 bases=('core.resource',),
77 70 ),
... ... @@ -87,13 +80,24 @@ class Migration(migrations.Migration):
87 80 ('end_date', models.DateField(verbose_name='End of Subject Date')),
88 81 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),
89 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 84 options={
94   - 'verbose_name_plural': 'Subjects',
95 85 'ordering': ('create_date', 'name'),
96 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 103 migrations.CreateModel(
... ... @@ -106,23 +110,11 @@ class Migration(migrations.Migration):
106 110 ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation Date')),
107 111 ('update_date', models.DateTimeField(auto_now=True, verbose_name='Date of last update')),
108 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 114 options={
113   - 'verbose_name_plural': 'Topics',
114 115 'ordering': ('create_date', 'name'),
115 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   -# -*- 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 @@
  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 @@
  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   -# -*- 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 3 from autoslug.fields import AutoSlugField
4 4 from users.models import User
5 5 from core.models import Resource
  6 +from s3direct.fields import S3DirectField
6 7  
7 8 class Category(models.Model):
8 9  
... ... @@ -88,52 +89,40 @@ It is one kind of possible resources available inside a Topic.
88 89 Activity is something that has a deadline and has to be delivered by the student
89 90 """
90 91 class Activity(Resource):
91   - topic = models.ForeignKey(Topic, verbose_name = _('Topic'))
  92 + topic = models.ForeignKey(Topic, verbose_name = _('Topic'), related_name='activities')
92 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 110 It represents any Material inside a topic, be it a file, a link, etc.
98 111 """
99 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 118 It is a category for each subject.
105 119 """
106 120 class SubjectCategory(models.Model):
107 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 123 description = models.TextField(_('Description'), blank = True)
110 124 subjects = models.ManyToManyField(Subject)
111 125  
112 126 class Meta:
113 127 verbose_name = _('subject category')
114 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 22 </ul>
23 23 </div>
24 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 42 {% endblock %}
26 43  
27 44 {% block content %}
... ... @@ -35,18 +52,101 @@
35 52 </div>
36 53 {% endfor %}
37 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 137 <div class="col-md-12">
39 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 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 150 <div class="col-md-12">
51 151 <div class="panel panel-info">
52 152 <!--{% if course.image %}
... ... @@ -80,7 +180,6 @@
80 180 {% endif %}
81 181  
82 182 <a href="{% url 'course:view' course.slug %}" class="btn btn-raised btn-default center-block">View Course</a>
83   -
84 183 </div>
85 184 </div>
86 185 </div>
... ... @@ -100,4 +199,5 @@
100 199 {% else %}
101 200 {% trans 'No courses found' %}
102 201 {% endif %}
  202 +{% endif %}
103 203 {% endblock %}
... ...
courses/templates/course/view.html
... ... @@ -15,120 +15,206 @@
15 15 {% endblock %}
16 16  
17 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 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 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 44 </div>
58 45 {% endif %}
  46 +
59 47 {% endblock %}
60 48  
61 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 76 </div>
82   - {% endif %}
83   - </div>
84 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 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 159 </div>
101 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 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 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 212 </ul>
125   -
126 213 </div>
127   - {% endif %}
128 214 </div>
129 215 </div>
130   - </div>
131   - <div class="panel-body">
  216 + </div>
  217 + <div class="panel-body">
132 218 <p><b>{% trans "Professor" %}: </b>{% for professor in subject.professors.all %}{% if not forloop.first %},{% endif %}
133 219 {{professor}}{% if forloop.last %}.{% endif %}{% endfor %}</p>
134 220 <p>
... ... @@ -146,11 +232,33 @@
146 232 </div>
147 233 </div>
148 234 </div>
149   - </div>
  235 +</div>
150 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 262 {% endblock %}
155 263  
156 264  
... ...
courses/templates/poll/poll.html
... ... @@ -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 1 {% load i18n %}
2 2  
  3 +{% block javascript %}
  4 + <script type="text/javascript" src="{% static 'js/forum.js' %}"></script>
  5 +{% endblock %}
  6 +
3 7 <div class="panel panel-default">
4 8 <a href="{% url 'course:view_topic' topic.slug %}">
5 9 <div class="panel-heading">
... ... @@ -13,4 +17,24 @@
13 17 </div>
14 18 <div class="panel-body">
15 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 40 </div>
17 41 \ No newline at end of file
... ...
courses/templates/subject/form_view_teacher.html
... ... @@ -19,7 +19,10 @@
19 19 </a>
20 20 <div class="panel-body">
21 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 26 </div>
24 27 </div>
25 28  
... ... @@ -27,21 +30,11 @@
27 30 <div class="modal-dialog" role="document">
28 31 <div class="modal-content">
29 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 34 </div>
32 35 <div class="modal-body">
33 36 <section>
34 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 38 </section>
46 39 </div>
47 40 <div class="modal-footer">
... ... @@ -50,4 +43,23 @@
50 43 </div>
51 44 </div>
52 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 65 </div>
54 66 \ No newline at end of file
... ...
courses/templates/topic/index.html
... ... @@ -73,116 +73,62 @@
73 73 </div>
74 74 <div class="panel panel-default">
75 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 78 <fieldset>
78   - <legend>Atividade 1</legend>
  79 + <legend>{{activit.name}}</legend>
79 80  
80 81 <div class="container-fluid">
81 82 <div class="row">
82   - <div class="col-md-4">
83   -
  83 + <div class="col-md-8">
84 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 86 </div>
87   -
88   - </div>
89   - </div>
  87 + </div>
  88 + </div>
  89 + {% for student in students_activit %}
90 90 <div class="panel-group" id="accordion">
91 91 <div class="panel panel-info">
92 92 <div class="panel-heading">
93 93 <h4 class="panel-title">
94 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 96 </h4>
97 97 </div>
98 98 <div id="collapse1" class="panel-collapse collapse">
99 99 <div class="panel-body">
100 100 <div class="row">
101   - <div class="col-md-6">
  101 + <div class="col-md-4">
102 102 <i class="fa fa-file-archive-o fa-lg" aria-hidden="true">Atividade.doc</i>
103   -
104 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 120 </div>
110 121 </div>
111 122 </div>
112 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 124 </div>
  125 + {% endfor %}
135 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 133 <ul class="pagination pagination-sm">
188 134 <li class="disabled"><a href="javascript:void(0)">«</a></li>
... ...
courses/templates/topic/list_topic_foruns.html
1 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 3 {% endfor %}
4 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 3 from . import views
4 4  
... ... @@ -22,6 +22,8 @@ urlpatterns = [
22 22 url(r'^topics/update/(?P<slug>[\w_-]+)/$', views.UpdateTopicView.as_view(), name='update_topic'),
23 23 url(r'^topics/(?P<slug>[\w_-]+)/$', views.TopicsView.as_view(), name='view_topic'),
24 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 11 from django.db.models import Q
12 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 16 from core.mixins import NotificationMixin
17 17 from users.models import User
18 18  
... ... @@ -24,15 +24,14 @@ class IndexView(LoginRequiredMixin, NotificationMixin, generic.ListView):
24 24 redirect_field_name = 'next'
25 25 queryset = Course.objects.all()
26 26 template_name = 'course/index.html'
27   - context_object_name = 'courses'
  27 + context_object_name = 'courses_student'
28 28 paginate_by = 3
29 29  
30 30 def get_context_data(self, **kwargs):
31 31 context = super(IndexView, self).get_context_data(**kwargs)
32 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 35 return context
37 36  
38 37 class CreateCourseView(LoginRequiredMixin, HasRoleMixin, NotificationMixin,generic.edit.CreateView):
... ... @@ -283,18 +282,27 @@ class TopicsView(LoginRequiredMixin, generic.ListView):
283 282 def get_queryset(self):
284 283 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
285 284 subject = topic.subject
286   - context = Topic.objects.filter(subject = subject, visible=True)
  285 + topics_q = Topic.objects.filter(subject = subject, visible=True)
287 286 #if (self.request.user in subject.professors.all() or has_role(self.request.user,'system_admin')):
288 287 #context = subject.topics.all() <- Change it By Activities
289   - return context
  288 + return topics_q
290 289  
291 290 def get_context_data(self, **kwargs):
292 291 topic = get_object_or_404(Topic, slug = self.kwargs.get('slug'))
293 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 296 context['topic'] = topic
295 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 303 return context
297 304  
  305 +
298 306 class CreateTopicView(LoginRequiredMixin, HasRoleMixin, NotificationMixin, generic.edit.CreateView):
299 307  
300 308 allowed_roles = ['professor', 'system_admin']
... ... @@ -339,7 +347,7 @@ class UpdateTopicView(LoginRequiredMixin, HasRoleMixin, generic.UpdateView):
339 347 return super(UpdateTopicView, self).dispatch(*args, **kwargs)
340 348  
341 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 352 def get_success_url(self):
345 353 return reverse_lazy('course:view_subject', kwargs={'slug' : self.object.subject.slug})
... ... @@ -455,27 +463,3 @@ class IndexSubjectCategoryView(LoginRequiredMixin, generic.ListView):
455 463 context = super(IndexSubjectCategoryView, self).get_context_data(**kwargs)
456 464 context['subject_categories'] = SubjectCategory.objects.all()
457 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 1 from django import forms
2 2 from django.utils.translation import ugettext_lazy as _
3   -from .models import Forum
  3 +from .models import Forum, Post, PostAnswer
4 4  
5 5 class ForumForm(forms.ModelForm):
6 6  
7 7 class Meta:
8 8 model = Forum
9   - fields = ('name', 'description')
  9 + fields = ('name', 'limit_date', 'description', 'topic', )
10 10 labels = {
11 11 'name': _('Title'),
12   - 'description': _('Description')
  12 + 'description': _('Description'),
  13 + 'limit_date': _('Limit Date'),
13 14 }
14 15 help_texts = {
15 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 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 51 \ No newline at end of file
... ...
forum/migrations/0001_initial.py
1 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 3 from __future__ import unicode_literals
4 4  
5   -from django.conf import settings
6 5 from django.db import migrations, models
7 6 import django.db.models.deletion
8 7  
... ... @@ -12,7 +11,6 @@ class Migration(migrations.Migration):
12 11 initial = True
13 12  
14 13 dependencies = [
15   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
16 14 ('courses', '0001_initial'),
17 15 ]
18 16  
... ... @@ -21,8 +19,9 @@ class Migration(migrations.Migration):
21 19 name='Forum',
22 20 fields=[
23 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 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 26 options={
28 27 'verbose_name': 'Forum',
... ... @@ -35,9 +34,8 @@ class Migration(migrations.Migration):
35 34 fields=[
36 35 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
37 36 ('message', models.TextField(verbose_name='Post message')),
  37 + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
38 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 40 options={
43 41 'verbose_name': 'Post',
... ... @@ -49,9 +47,9 @@ class Migration(migrations.Migration):
49 47 fields=[
50 48 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
51 49 ('message', models.TextField(verbose_name='Answer message')),
  50 + ('modification_date', models.DateTimeField(auto_now=True, verbose_name='Modification Date')),
52 51 ('answer_date', models.DateTimeField(auto_now_add=True, verbose_name='Answer Date')),
53 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 54 options={
57 55 'verbose_name': 'Post Answer',
... ...
forum/migrations/0002_auto_20161001_2117.py 0 → 100644
... ... @@ -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   -# -*- 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   -# -*- 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 12 """
13 13 class Forum(Activity):
14 14 description = models.TextField(_('Description'), blank = True)
  15 + modification_date = models.DateTimeField(_('Modification Date'), auto_now = True)
15 16 create_date = models.DateTimeField(_('Create Date'), auto_now_add = True)
16 17  
17 18 class Meta:
... ... @@ -22,12 +23,14 @@ class Forum(Activity):
22 23 def __str__(self):
23 24 return self.name
24 25  
  26 +
25 27 """
26 28 It represents a post made in a forum (topic)
27 29 """
28 30 class Post(models.Model):
29 31 user = models.ForeignKey(User, verbose_name = _('Autor'))
30 32 message = models.TextField(_('Post message'), blank = False)
  33 + modification_date = models.DateTimeField(_('Modification Date'), auto_now = True)
31 34 post_date = models.DateTimeField(_('Post Date'), auto_now_add = True)
32 35 forum = models.ForeignKey(Forum, verbose_name = _('Forum'))
33 36  
... ... @@ -39,6 +42,15 @@ class Post(models.Model):
39 42 def __str__(self):
40 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 55 It represents an answer to a forum's post
44 56 """
... ... @@ -46,6 +58,7 @@ class PostAnswer(models.Model):
46 58 user = models.ForeignKey(User, verbose_name = _('Autor'))
47 59 post = models.ForeignKey(Post, verbose_name = _('Post'))
48 60 message = models.TextField(_('Answer message'), blank = False)
  61 + modification_date = models.DateTimeField(_('Modification Date'), auto_now = True)
49 62 answer_date = models.DateTimeField(_('Answer Date'), auto_now_add = True)
50 63  
51 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 23 $.ajax({
8 24 url: url,
9   - data: {'forum_id': forum_id},
  25 + data: {'topic': topic},
10 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 66 $.ajax({
20 67 url: url,
  68 + data: {'forum_id': forum_id},
21 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 99 $.ajax({
  100 + method: 'post',
  101 + beforeSend: function (request) {
  102 + request.setRequestHeader('X-CSRFToken', csrftoken);
  103 + },
34 104 url: url,
35   - data: {'forum': forum},
36 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 186 \ No newline at end of file
... ...
forum/templates/forum/forum_form.html
1 1 {% load static i18n %}
2 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 5 {% csrf_token %}
6 6 {% for field in form %}
7 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 27 </div>
24   - </div>
  28 + {% endif %}
25 29 {% endif %}
26 30 </div>
27 31 {% endfor %}
28   -
29   - <input type="submit" value="{% trans 'Create' %}" class="btn btn-primary" />
30 32 </form>
31 33 \ No newline at end of file
... ...
forum/templates/forum/forum_list.html
1 1 {% load i18n permission_tags list_post %}
  2 +{% load widget_tweaks %}
2 3  
3 4 <div class="comments-list">
4 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 23 <h4><b>{% trans 'Description' %}:</b> {{ forum.description }}</h4>
7 24 <h4><b>{% trans 'Opened in' %}:</b> {{ forum.create_date }}</h4>
8 25 </div>
9 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 68 <!--{% if foruns|length > 0 %}
14 69 {% for forum in foruns %}
... ...
forum/templates/post/post_list.html
... ... @@ -2,28 +2,40 @@
2 2  
3 3 {% if posts|length > 0 %}
4 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 7 <h3 class="user-name">
8 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 15 <div class="btn-group icon-more-horiz">
12 16 <a class="btn btn-default btn-xs dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
13 17 <i class="material-icons">more_horiz</i>
14 18 </a>
15 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 22 </ul>
19 23 </div>
20   - </div>
21   - {% endif %}
  24 + {% endif %}
  25 + </div>
22 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 37 </div>
26   - <p class="comment-text">{{ post.message|linebreaks }}</p>
  38 + <div class="answer_post"></div>
27 39 </div>
28 40 </div>
29 41 {% list_post_answer request post %}
... ...
forum/templates/post/post_render.html 0 → 100644
... ... @@ -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 39 \ No newline at end of file
... ...
forum/templates/post/post_update_form.html 0 → 100644
... ... @@ -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 38 \ No newline at end of file
... ...
forum/templates/post_answers/post_answer_form.html 0 → 100644
... ... @@ -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 37 \ No newline at end of file
... ...
forum/templatetags/list_post.py
... ... @@ -14,6 +14,6 @@ def list_posts(request, forum):
14 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 19 return context
20 20 \ No newline at end of file
... ...
forum/tests.py
... ... @@ -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 @@
  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 131 \ No newline at end of file
... ...
forum/tests/test_model_forum.py 0 → 100644
... ... @@ -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 107 \ No newline at end of file
... ...
forum/tests/test_model_post.py 0 → 100644
... ... @@ -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 149 \ No newline at end of file
... ...
forum/urls.py
... ... @@ -5,7 +5,15 @@ from . import views
5 5  
6 6 urlpatterns = [
7 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 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 4 from django.utils.translation import ugettext_lazy as _
4 5 from django.views import generic
5 6 from django.contrib.auth.mixins import LoginRequiredMixin
... ... @@ -7,7 +8,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
7 8 from .models import Forum, Post, PostAnswer
8 9 from courses.models import Topic
9 10  
10   -from .forms import ForumForm
  11 +from .forms import ForumForm, PostForm, PostAnswerForm
11 12  
12 13 class ForumIndex(LoginRequiredMixin, generic.ListView):
13 14 login_url = reverse_lazy("core:home")
... ... @@ -20,28 +21,97 @@ class ForumIndex(LoginRequiredMixin, generic.ListView):
20 21 forum_id = self.request.GET.get('forum_id', 0)
21 22  
22 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 31 return context
25 32  
26 33 class CreateForumView(LoginRequiredMixin, generic.edit.CreateView):
  34 + login_url = reverse_lazy("core:home")
  35 + redirect_field_name = 'next'
27 36  
28 37 template_name = 'forum/forum_form.html'
29 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 66 login_url = reverse_lazy("core:home")
34 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 116 class PostAnswerIndex(LoginRequiredMixin, generic.ListView):
47 117 login_url = reverse_lazy("core:home")
... ... @@ -55,4 +125,10 @@ class PostAnswerIndex(LoginRequiredMixin, generic.ListView):
55 125  
56 126 context = PostAnswer.objects.filter(post = post)
57 127  
58   - return context
59 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 136 \ No newline at end of file
... ...
poll/__init__.py 0 → 100644
poll/admin.py 0 → 100644
... ... @@ -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 @@
  1 +from django.apps import AppConfig
  2 +
  3 +
  4 +class PollConfig(AppConfig):
  5 + name = 'poll'
... ...
poll/forms.py 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
... ...
poll/urls.py 0 → 100644
... ... @@ -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 @@
  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 5 django-autoslug==1.9.3
6 6 django-bootstrap-breadcrumbs==0.8
7 7 django-discover-runner==1.0
  8 +django-floppyforms==1.7.0
8 9 django-role-permissions==1.2.1
  10 +django-s3direct==0.4.2
9 11 django-widget-tweaks==1.4.1
10 12 djangorestframework==3.4.6
11 13 Jinja2==2.8
12 14 MarkupSafe==0.23
13 15 Pillow==3.3.1
  16 +pkg-resources==0.0.0
  17 +psycopg2==2.6.2
14 18 pycpfcnpj==1.0.2
15 19 six==1.10.0
16   -psycopg2==2.6.2
17 20 \ No newline at end of file
  21 +psycopg2==2.6.2
... ...
users/forms.py
... ... @@ -27,25 +27,6 @@ class ProfileForm(forms.ModelForm):
27 27 }
28 28  
29 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 31 class Meta:
51 32 model = User
... ... @@ -59,7 +40,8 @@ class EditUserForm(forms.ModelForm):
59 40  
60 41 # Ailson
61 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 48 \ No newline at end of file
... ...
users/migrations/0001_initial.py
1 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 3 from __future__ import unicode_literals
4 4  
5 5 import django.contrib.auth.models
... ...
users/templates/list_users.html
... ... @@ -63,9 +63,29 @@
63 63 <p>{% trans 'Contact' %}: {{ acc.phone }}</p>
64 64 <div align="right">
65 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 67 </div>
68 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 89 </div>
70 90 </div>
71 91 {% endfor %}
... ...
users/templates/users/create.html
... ... @@ -33,10 +33,18 @@
33 33 {% for field in form %}
34 34 <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
35 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 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 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 48 {% render_field field class='form-control' %}
41 49 <div class="input-group">
42 50 <input type="text" readonly="" class="form-control" placeholder="{% trans 'Choose your photo...' %}">
... ... @@ -53,15 +61,23 @@
53 61 </label>
54 62 </div>
55 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 69 {% render_field field class='form-control' onkeypress='campoNumerico(this,event); formatarCpf(this,event);' %}
58 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 76 {% render_field field class='form-control' %}
61 77 {% endif %}
62 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 81 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
66 82 <span aria-hidden="true">&times;</span>
67 83 </button>
... ...
users/templates/users/profile.html
... ... @@ -28,10 +28,8 @@
28 28  
29 29 {% block content %}
30 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 33 </div>
36 34 </div>
37 35 <div class="row">
... ...
users/templates/users/update.html
... ... @@ -46,18 +46,14 @@
46 46 </button>
47 47 </span>
48 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 51 {% else %}
56 52 {% render_field field class='form-control' %}
57 53 <span id="helpBlock" class="help-block">{{ field.help_text }}</span>
58 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 57 <button type="button" class="close" data-dismiss="alert" aria-label="Close">
62 58 <span aria-hidden="true">&times;</span>
63 59 </button>
... ... @@ -67,7 +63,6 @@
67 63 {% endfor %}
68 64 </ul>
69 65 </div>
70   - </div>
71 66 {% endif %}
72 67 </div>
73 68 {% endfor %}
... ...
users/tests.py
... ... @@ -4,31 +4,60 @@ from django.core.urlresolvers import reverse
4 4 from .models import *
5 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  
... ...
users/urls.py
... ... @@ -7,6 +7,7 @@ urlpatterns = [
7 7 url(r'^create/$', views.Create.as_view(), name='create'),
8 8 url(r'^edit/(?P<username>[\w_-]+)/$', views.Update.as_view(), name='update'),
9 9 url(r'^view/(?P<username>[\w_-]+)/$', views.View.as_view(), name='view'),
  10 + url(r'^delete/(?P<username>[\w_-]+)/$', views.delete, name='delete'),
10 11 url(r'^profile/$', views.Profile.as_view(), name='profile'),
11 12 url(r'^profile/editar/(?P<username>[\w_-]+)/$', views.EditProfile.as_view(), name='edit_profile'),
12 13 #
... ...
users/views.py
1   -from django.shortcuts import get_object_or_404
  1 +from django.shortcuts import get_object_or_404,redirect
2 2 from django.db.models import Q
3 3 from django.views import generic
4 4 from django.contrib import messages
... ... @@ -10,6 +10,7 @@ from rolepermissions.shortcuts import assign_role
10 10 from .models import User
11 11 from .forms import UserForm, ProfileForm, UpdateUserForm
12 12  
  13 +# ================ ADMIN =======================
13 14 class UsersListView(HasRoleMixin, LoginRequiredMixin, generic.ListView):
14 15  
15 16 allowed_roles = ['system_admin']
... ... @@ -65,7 +66,7 @@ class Update(HasRoleMixin, LoginRequiredMixin, generic.UpdateView):
65 66 slug_url_kwarg = 'username'
66 67 context_object_name = 'acc'
67 68 model = User
68   - form_class = UserForm
  69 + form_class = UpdateUserForm
69 70 success_url = reverse_lazy('users:manage')
70 71  
71 72 def form_valid(self, form):
... ... @@ -94,6 +95,44 @@ class View(LoginRequiredMixin, generic.DetailView):
94 95 slug_field = 'username'
95 96 slug_url_kwarg = 'username'
96 97  
  98 +def delete(request,username):
  99 + user = get_object_or_404(User,username = username)
  100 + user.delete()
  101 + messages.success(request,_("User deleted Successfully!"))
  102 + return redirect('users:manage')
  103 +
  104 +
  105 +
  106 +class UpdateUser(LoginRequiredMixin, generic.edit.UpdateView):
  107 +
  108 + allowed_roles = ['student']
  109 + login_url = reverse_lazy("core:home")
  110 + template_name = 'users/edit_profile.html'
  111 + form_class = UpdateUserForm
  112 + success_url = reverse_lazy('users:update_profile')
  113 +
  114 + def get_object(self):
  115 + user = get_object_or_404(User, username = self.request.user.username)
  116 + return user
  117 +
  118 + def form_valid(self, form):
  119 + form.save()
  120 + messages.success(self.request, _('Profile edited successfully!'))
  121 +
  122 + return super(UpdateUser, self).form_valid(form)
  123 +
  124 +class DeleteUser(LoginRequiredMixin, generic.edit.DeleteView):
  125 + allowed_roles = ['student']
  126 + login_url = reverse_lazy("core:home")
  127 + model = User
  128 + success_url = reverse_lazy('core:index')
  129 + success_message = "Deleted Successfully"
  130 +
  131 + def get_queryset(self):
  132 + user = get_object_or_404(User, username = self.request.user.username)
  133 + return user
  134 +
  135 +
97 136 class Profile(LoginRequiredMixin, generic.DetailView):
98 137  
99 138 login_url = reverse_lazy("core:home")
... ... @@ -131,34 +170,4 @@ class EditProfile(LoginRequiredMixin, generic.UpdateView):
131 170  
132 171 messages.success(self.request, _('Profile edited successfully!'))
133 172  
134   - return super(EditProfile, self).form_valid(form)
135   -
136   -
137   -class UpdateUser(LoginRequiredMixin, generic.edit.UpdateView):
138   -
139   - allowed_roles = ['student']
140   - login_url = reverse_lazy("core:home")
141   - template_name = 'users/edit_profile.html'
142   - form_class = UpdateUserForm
143   - success_url = reverse_lazy('users:update_profile')
144   -
145   - def get_object(self):
146   - user = get_object_or_404(User, username = self.request.user.username)
147   - return user
148   -
149   - def form_valid(self, form):
150   - form.save()
151   - messages.success(self.request, _('Profile edited successfully!'))
152   -
153   - return super(UpdateUser, self).form_valid(form)
154   -
155   -class DeleteUser(LoginRequiredMixin, generic.edit.DeleteView):
156   - allowed_roles = ['student']
157   - login_url = reverse_lazy("core:home")
158   - model = User
159   - success_url = reverse_lazy('core:index')
160   - success_message = "Deleted Successfully"
161   -
162   - def get_queryset(self):
163   - user = get_object_or_404(User, username = self.request.user.username)
164   - return user
  173 + return super(EditProfile, self).form_valid(form)
165 174 \ No newline at end of file
... ...