Commit 33390e61cf9ee78d1c4b8e46408bd11478e2f21b

Authored by Zambom
1 parent ea89e684

Adding goals submit (adjusts to be made)

amadeus/templatetags/util_tags.py 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +from django import template
  2 +
  3 +register = template.Library()
  4 +
  5 +@register.filter(name = 'zip')
  6 +def zip_lists(first, second):
  7 + return zip(first, second)
0 8 \ No newline at end of file
... ...
goals/forms.py
... ... @@ -10,7 +10,7 @@ from subjects.models import Tag
10 10 from pendencies.forms import PendenciesLimitedForm
11 11 from pendencies.models import Pendencies
12 12  
13   -from .models import Goals, GoalItem
  13 +from .models import Goals, GoalItem, MyGoals
14 14  
15 15 class GoalsForm(forms.ModelForm):
16 16 subject = None
... ... @@ -116,6 +116,15 @@ class GoalItemForm(forms.ModelForm):
116 116  
117 117 return cleaned_data
118 118  
  119 +class MyGoalsForm(forms.ModelForm):
  120 + def __init__(self, *args, **kwargs):
  121 + super(MyGoalsForm, self).__init__(*args, **kwargs)
  122 +
  123 + self.fields['item'].widget = forms.HiddenInput()
  124 +
  125 + class Meta:
  126 + model = MyGoals
  127 + fields = ['value', 'item']
119 128  
120 129 InlinePendenciesFormset = inlineformset_factory(Goals, Pendencies, form = PendenciesLimitedForm, extra = 1, max_num = 3, validate_max = True, can_delete = True)
121 130 InlineGoalItemFormset = inlineformset_factory(Goals, GoalItem, form = GoalItemForm, extra = 1, can_delete = True)
122 131 \ No newline at end of file
... ...
goals/migrations/0004_auto_20170228_0004.py 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2017-02-28 03:04
  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 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  14 + ('goals', '0003_auto_20170227_2014'),
  15 + ]
  16 +
  17 + operations = [
  18 + migrations.CreateModel(
  19 + name='MyGoals',
  20 + fields=[
  21 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  22 + ('value', models.IntegerField(verbose_name='My Value')),
  23 + ('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Create Date')),
  24 + ('last_update', models.DateTimeField(auto_now=True, verbose_name='Last Update')),
  25 + ('goal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mine_goals', to='goals.Goals', verbose_name='Goal')),
  26 + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_goals', to=settings.AUTH_USER_MODEL, verbose_name='User')),
  27 + ],
  28 + ),
  29 + migrations.AlterModelOptions(
  30 + name='goalitem',
  31 + options={'ordering': ['order']},
  32 + ),
  33 + ]
... ...
goals/migrations/0005_auto_20170301_1906.py 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2017-03-01 22:06
  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 + dependencies = [
  12 + ('goals', '0004_auto_20170228_0004'),
  13 + ]
  14 +
  15 + operations = [
  16 + migrations.AlterField(
  17 + model_name='mygoals',
  18 + name='goal',
  19 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mine_goals', to='goals.GoalItem', verbose_name='Goal'),
  20 + ),
  21 + ]
... ...
goals/migrations/0006_auto_20170301_1930.py 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10 on 2017-03-01 22:30
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('goals', '0005_auto_20170301_1906'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.RenameField(
  16 + model_name='mygoals',
  17 + old_name='goal',
  18 + new_name='item',
  19 + ),
  20 + ]
... ...
goals/models.py
... ... @@ -4,6 +4,7 @@ from django.utils.translation import ugettext_lazy as _
4 4 from django.core.urlresolvers import reverse_lazy
5 5  
6 6 from topics.models import Resource
  7 +from users.models import User
7 8  
8 9 class Goals(Resource):
9 10 presentation = models.TextField(_('Presentation'), blank = True)
... ... @@ -20,7 +21,7 @@ class Goals(Resource):
20 21 if self.show_window:
21 22 return reverse_lazy('goals:window_view', args = (), kwargs = {'slug': self.slug})
22 23  
23   - return reverse_lazy('goals:view', args = (), kwargs = {'slug': self.slug})
  24 + return reverse_lazy('goals:submit', args = (), kwargs = {'slug': self.slug})
24 25  
25 26 def update_link(self):
26 27 return 'goals:update'
... ... @@ -38,4 +39,11 @@ class GoalItem(models.Model):
38 39 goal = models.ForeignKey(Goals, verbose_name = _('Goal'), related_name = 'item_goal')
39 40  
40 41 class Meta:
41   - ordering = ['order']
42 42 \ No newline at end of file
  43 + ordering = ['order']
  44 +
  45 +class MyGoals(models.Model):
  46 + value = models.IntegerField(_('My Value'))
  47 + user = models.ForeignKey(User, verbose_name = _('User'), related_name = 'user_goals')
  48 + item = models.ForeignKey(GoalItem, verbose_name = _('Goal'), related_name = 'mine_goals')
  49 + create_date = models.DateTimeField(_('Create Date'), auto_now_add = True)
  50 + last_update = models.DateTimeField(_('Last Update'), auto_now = True)
43 51 \ No newline at end of file
... ...
goals/templates/goals/submit.html 0 → 100644
... ... @@ -0,0 +1,130 @@
  1 +{% extends 'subjects/view.html' %}
  2 +
  3 +{% load static i18n pagination permissions_tags subject_counter util_tags %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +{% load widget_tweaks %}
  6 +
  7 +{% block style %}
  8 + {{block.super}}
  9 + <link rel="stylesheet" type="text/css" href="{% static "css/bootstrap-slider.css" %}">
  10 +{% endblock %}
  11 +
  12 +{% block javascript%}
  13 + {{ block.super }}
  14 + <script type="text/javascript" src="{% static "js/bootstrap-slider.js" %} "></script>
  15 +{% endblock%}
  16 +
  17 +{% block breadcrumbs %}
  18 + {{ block.super }}
  19 + {% breadcrumb topic 'subjects:topic_view' subject.slug topic.slug %}
  20 + {% breadcrumb goals 'goals:view' goals.slug %}
  21 +{% endblock %}
  22 +
  23 +{% block content %}
  24 + {% if messages %}
  25 + {% for message in messages %}
  26 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  27 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  28 + <span aria-hidden="true">&times;</span>
  29 + </button>
  30 + <p>{{ message }}</p>
  31 + </div>
  32 + {% endfor %}
  33 + {% endif %}
  34 +
  35 + {% resource_permissions request.user goals as has_resource_permissions %}
  36 +
  37 + {% if goals.visible %}
  38 + <div class="panel panel-info topic-panel">
  39 + <div class="panel-heading">
  40 + {% elif has_resource_permissions %}
  41 + <div class="panel panel-info topic-panel-invisible">
  42 + <div class="panel-heading panel-invisible">
  43 + {% endif %}
  44 + <div class="row">
  45 + <div class="col-md-12 category-header">
  46 + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
  47 + <span>{{ goals }}</span>
  48 + </h4>
  49 +
  50 + <div class="col-md-5 pull-right category-card-items">
  51 + <a href="{% url 'mural:resource_view' goals.slug %}" class="pull-right action_icon">
  52 + <i class="fa fa-list" aria-hidden="true"></i>
  53 + {% resource_mural_number goals request.user %}
  54 + </a>
  55 + </div>
  56 + </div>
  57 + </div>
  58 + </div>
  59 + <div id="{{subject.slug}}" class="panel-collapse in collapse category-panel-content">
  60 + {% autoescape off %}
  61 + {{ goals.presentation }}
  62 + {% endautoescape %}
  63 +
  64 + <br clear="all" />
  65 +
  66 + <b>{% trans "Limit submission date" %}:</b> {{ goals.limit_submission_date }}
  67 +
  68 + <hr class="goal_divider" />
  69 +
  70 + <form id="mygoals_submit" method="post" action="" enctype="multipart/form-data">
  71 + {% csrf_token %}
  72 +
  73 + {{ my_goals_formset.management_form }}
  74 + {{ my_goals_formset.non_form_errors }}
  75 +
  76 + {% for form, item in my_goals_formset|zip:goals.item_goal.all %}
  77 + {% render_field form.id %}
  78 + {% render_field form.item %}
  79 + {{ form.errors }}
  80 +
  81 + {% if form.instance.pk %}{{ form.DELETE }}{% endif %}
  82 +
  83 + <div class="form-group{% if form.has_error %} has-error {% endif %} row goal_item">
  84 + <div class="col-md-12">
  85 + <h4>{% trans 'Goal' %} {{ item.order }}: {{ item.description }}</h4>
  86 + <p>{% trans 'Minimum percentage desired' %}: {{ item.ref_value }}%</p>
  87 + <br clear="all" />
  88 + <span class="label">0%</span>
  89 + {% with form.value.value|default:"0" as item_value %}
  90 + {% render_field form.value class='slider_value' data-slider-value=item_value data-slider-min="0" data-slider-max="100" %}
  91 + {% endwith %}
  92 + <span class="label">100%</span>
  93 + </div>
  94 +
  95 + <br clear="all" />
  96 +
  97 + <span id="helpBlock" class="help-block">{{ form.value.help_text }}</span>
  98 +
  99 + {% if form.value.errors %}
  100 + <div class="alert alert-danger alert-dismissible" role="alert">
  101 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  102 + <span aria-hidden="true">&times;</span>
  103 + </button>
  104 + <ul>
  105 + {% for error in form.value.errors %}
  106 + <li>{{ error }}</li>
  107 + {% endfor %}
  108 + </ul>
  109 + </div>
  110 + {% endif %}
  111 + </div>
  112 + {% endfor %}
  113 + </form>
  114 +
  115 + <hr />
  116 +
  117 + <div class="text-center">
  118 + <button type="submit" form="mygoals_submit" class="btn btn-success btn-raised">{% trans 'Save' %}</a>
  119 + </div>
  120 + </div>
  121 + </div>
  122 +
  123 + <script type="text/javascript">
  124 + $(function () {
  125 + $(".slider_value").bootstrapSlider({
  126 + tooltip: 'always',
  127 + });
  128 + });
  129 + </script>
  130 +{% endblock %}
... ...
goals/templates/goals/view.html
... ... @@ -5,18 +5,19 @@
5 5  
6 6 {% block style %}
7 7 {{block.super}}
8   - <link rel="stylesheet" type="text/css" href="{% static "css/bootstrap-slider.css" %}">
9 8 {% endblock %}
10 9  
11 10 {% block javascript%}
12 11 {{ block.super }}
13   - <script type="text/javascript" src="{% static "js/bootstrap-slider.js" %} "></script>
14 12 {% endblock%}
15 13  
16 14 {% block breadcrumbs %}
17 15 {{ block.super }}
18 16 {% breadcrumb topic 'subjects:topic_view' subject.slug topic.slug %}
19   - {% breadcrumb goals 'goals:view' goals.slug %}
  17 + {% breadcrumb goal 'goals:submit' goal.slug %}
  18 +
  19 + {% trans 'My Goals' as bread %}
  20 + {% breadcrumb bread 'goals:view' goal.slug %}
20 21 {% endblock %}
21 22  
22 23 {% block content %}
... ... @@ -31,9 +32,9 @@
31 32 {% endfor %}
32 33 {% endif %}
33 34  
34   - {% resource_permissions request.user goals as has_resource_permissions %}
  35 + {% resource_permissions request.user goal as has_resource_permissions %}
35 36  
36   - {% if goals.visible %}
  37 + {% if goal.visible %}
37 38 <div class="panel panel-info topic-panel">
38 39 <div class="panel-heading">
39 40 {% elif has_resource_permissions %}
... ... @@ -43,13 +44,13 @@
43 44 <div class="row">
44 45 <div class="col-md-12 category-header">
45 46 <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
46   - <span>{{ goals }}</span>
  47 + <span>{{ goal }}</span>
47 48 </h4>
48 49  
49 50 <div class="col-md-5 pull-right category-card-items">
50   - <a href="{% url 'mural:resource_view' goals.slug %}" class="pull-right action_icon">
  51 + <a href="{% url 'mural:resource_view' goal.slug %}" class="pull-right action_icon">
51 52 <i class="fa fa-list" aria-hidden="true"></i>
52   - {% resource_mural_number goals request.user %}
  53 + {% resource_mural_number goal request.user %}
53 54 </a>
54 55 </div>
55 56 </div>
... ... @@ -57,24 +58,21 @@
57 58 </div>
58 59 <div id="{{subject.slug}}" class="panel-collapse in collapse category-panel-content">
59 60 {% autoescape off %}
60   - {{ goals.presentation }}
  61 + {{ goal.presentation }}
61 62 {% endautoescape %}
62 63  
63 64 <br clear="all" />
64 65  
65   - <b>{% trans "Limit submission date" %}:</b> {{ goals.limit_submission_date }}
  66 + <b>{% trans "Limit submission date" %}:</b> {{ goal.limit_submission_date }}
66 67  
67 68 <hr class="goal_divider" />
68 69  
69   - {% for item in goals.item_goal.all %}
  70 + {% for mine in itens %}
70 71 <div class="row goal_item">
71 72 <div class="col-md-12">
72   - <h4>{% trans 'Goal' %} {{ item.order }}: {{ item.description }}</h4>
73   - <p>{% trans 'Minimum percentage desired' %}: {{ item.ref_value }}%</p>
74   - <br clear="all" />
75   - <span class="label">0%</span>
76   - <input type="text" class="slider_value" value="{{ item.ref_value }}" data-slider-value="{{ item.ref_value }}" data-slider-min="0" data-slider-max="100" />
77   - <span class="label">100%</span>
  73 + <h4>{% trans 'Goal' %} {{ mine.item.order }}: {{ mine.item.description }}</h4>
  74 + <p>{% trans 'Minimum percentage desired' %}: {{ mine.item.ref_value }}%</p>
  75 + <p><b>{% trans 'Goal stabilished' %}: {{ mine.value }}%</b></p>
78 76 </div>
79 77 </div>
80 78 {% endfor %}
... ... @@ -82,17 +80,8 @@
82 80 <hr />
83 81  
84 82 <div class="text-center">
85   - <a href="#" class="btn btn-success btn-raised">{% trans 'Save' %}</a>
  83 + <a href="#" class="btn btn-success btn-raised">{% trans 'Update Goals' %}</a>
86 84 </div>
87 85 </div>
88 86 </div>
89   -
90   - <script type="text/javascript">
91   - $(function () {
92   - $(".slider_value").bootstrapSlider({
93   - tooltip: 'always',
94   - enabled: false
95   - });
96   - });
97   - </script>
98 87 {% endblock %}
... ...
goals/urls.py
... ... @@ -9,4 +9,5 @@ urlpatterns = [
9 9 url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'),
10 10 url(r'^window_view/(?P<slug>[\w_-]+)/$', views.NewWindowView.as_view(), name = 'window_view'),
11 11 url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'),
  12 + url(r'^submit/(?P<slug>[\w_-]+)/$', views.SubmitView.as_view(), name = 'submit'),
12 13 ]
... ...
goals/views.py
... ... @@ -4,13 +4,14 @@ from django.contrib import messages
4 4 from django.core.urlresolvers import reverse, reverse_lazy
5 5 from django.utils.translation import ugettext_lazy as _
6 6 from django.contrib.auth.mixins import LoginRequiredMixin
  7 +from django.forms import formset_factory
7 8  
8 9 from amadeus.permissions import has_subject_permissions, has_resource_permissions
9 10  
10 11 from topics.models import Topic
11 12  
12   -from .forms import GoalsForm, InlinePendenciesFormset, InlineGoalItemFormset
13   -from .models import Goals
  13 +from .forms import GoalsForm, MyGoalsForm, InlinePendenciesFormset, InlineGoalItemFormset
  14 +from .models import Goals, MyGoals
14 15  
15 16 class NewWindowView(LoginRequiredMixin, generic.DetailView):
16 17 login_url = reverse_lazy("users:login")
... ... @@ -36,13 +37,21 @@ class NewWindowView(LoginRequiredMixin, generic.DetailView):
36 37  
37 38 return context
38 39  
39   -class InsideView(LoginRequiredMixin, generic.DetailView):
  40 +class InsideView(LoginRequiredMixin, generic.ListView):
40 41 login_url = reverse_lazy("users:login")
41 42 redirect_field_name = 'next'
42 43  
43 44 template_name = 'goals/view.html'
44 45 model = Goals
45   - context_object_name = 'goals'
  46 + context_object_name = 'itens'
  47 +
  48 + def get_queryset(self):
  49 + slug = self.kwargs.get('slug', '')
  50 + goal = get_object_or_404(Goals, slug = slug)
  51 +
  52 + goals = MyGoals.objects.filter(user = self.request.user)
  53 +
  54 + return goals
46 55  
47 56 def dispatch(self, request, *args, **kwargs):
48 57 slug = self.kwargs.get('slug', '')
... ... @@ -56,13 +65,100 @@ class InsideView(LoginRequiredMixin, generic.DetailView):
56 65 def get_context_data(self, **kwargs):
57 66 context = super(InsideView, self).get_context_data(**kwargs)
58 67  
59   - context['title'] = self.object.name
  68 + slug = self.kwargs.get('slug', '')
  69 + goals = get_object_or_404(Goals, slug = slug)
  70 +
  71 + context['title'] = _("My Goals")
  72 +
  73 + context['goal'] = goals
  74 + context['topic'] = goals.topic
  75 + context['subject'] = goals.topic.subject
  76 +
  77 + return context
  78 +
  79 +class SubmitView(LoginRequiredMixin, generic.edit.CreateView):
  80 + login_url = reverse_lazy("users:login")
  81 + redirect_field_name = 'next'
  82 +
  83 + template_name = 'goals/submit.html'
  84 + form_class = MyGoalsForm
  85 +
  86 + def dispatch(self, request, *args, **kwargs):
  87 + slug = self.kwargs.get('slug', '')
  88 + goals = get_object_or_404(Goals, slug = slug)
  89 +
  90 + if not has_resource_permissions(request.user, goals):
  91 + return redirect(reverse_lazy('subjects:home'))
  92 +
  93 + return super(SubmitView, self).dispatch(request, *args, **kwargs)
  94 +
  95 + def get(self, request, *args, **kwargs):
  96 + self.object = None
  97 +
  98 + form_class = self.get_form_class()
  99 + form = self.get_form(form_class)
  100 +
  101 + slug = self.kwargs.get('slug', '')
  102 + goals = get_object_or_404(Goals, slug = slug)
  103 +
  104 + MyGoalsFormset = formset_factory(MyGoalsForm, extra = 0)
  105 + my_goals_formset = MyGoalsFormset(initial = [{'item': x.id, 'value': x.ref_value} for x in goals.item_goal.all()])
60 106  
61   - context['topic'] = self.object.topic
62   - context['subject'] = self.object.topic.subject
  107 + return self.render_to_response(self.get_context_data(my_goals_formset = my_goals_formset))
  108 +
  109 + def post(self, request, *args, **kwargs):
  110 + self.object = None
  111 +
  112 + form_class = self.get_form_class()
  113 + form = self.get_form(form_class)
  114 +
  115 + slug = self.kwargs.get('slug', '')
  116 + goals = get_object_or_404(Goals, slug = slug)
  117 +
  118 + MyGoalsFormset = formset_factory(MyGoalsForm, extra = 0)
  119 + my_goals_formset = MyGoalsFormset(self.request.POST, initial = [{'item': x.id, 'value': x.ref_value} for x in goals.item_goal.all()])
  120 +
  121 + if (my_goals_formset.is_valid()):
  122 + return self.form_valid(my_goals_formset)
  123 + else:
  124 + return self.form_invalid(my_goals_formset)
  125 +
  126 + def form_invalid(self, my_goals_formset):
  127 + return self.render_to_response(self.get_context_data(my_goals_formset = my_goals_formset))
  128 +
  129 + def form_valid(self, my_goals_formset):
  130 + for forms in my_goals_formset.forms:
  131 + form = forms.save(commit = False)
  132 + form.user = self.request.user
  133 +
  134 + form.save()
  135 +
  136 + return redirect(self.get_success_url())
  137 +
  138 + def get_context_data(self, **kwargs):
  139 + context = super(SubmitView, self).get_context_data(**kwargs)
  140 +
  141 + slug = self.kwargs.get('slug', '')
  142 + goals = get_object_or_404(Goals, slug = slug)
  143 +
  144 + context['title'] = goals.name
  145 +
  146 + context['goals'] = goals
  147 + context['topic'] = goals.topic
  148 + context['subject'] = goals.topic.subject
63 149  
64 150 return context
65 151  
  152 + def get_success_url(self):
  153 + slug = self.kwargs.get('slug', '')
  154 + goals = get_object_or_404(Goals, slug = slug)
  155 +
  156 + messages.success(self.request, _('Your goals for %s was save successfully!')%(goals.topic.name))
  157 +
  158 + success_url = reverse_lazy('goals:view', kwargs = {'slug': slug})
  159 +
  160 + return success_url
  161 +
66 162 class CreateView(LoginRequiredMixin, generic.edit.CreateView):
67 163 login_url = reverse_lazy("users:login")
68 164 redirect_field_name = 'next'
... ... @@ -184,7 +280,7 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView):
184 280 def get_success_url(self):
185 281 messages.success(self.request, _('The Goals specification for the topic %s was realized successfully!')%(self.object.topic.name))
186 282  
187   - success_url = reverse_lazy('goals:view', kwargs = {'slug': self.object.slug})
  283 + success_url = reverse_lazy('goals:submit', kwargs = {'slug': self.object.slug})
188 284  
189 285 if self.object.show_window:
190 286 self.request.session['resources'] = {}
... ... @@ -299,7 +395,7 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView):
299 395 def get_success_url(self):
300 396 messages.success(self.request, _('The Goals specification for the topic %s was updated successfully!')%(self.object.topic.name))
301 397  
302   - success_url = reverse_lazy('goals:view', kwargs = {'slug': self.object.slug})
  398 + success_url = reverse_lazy('goals:submit', kwargs = {'slug': self.object.slug})
303 399  
304 400 if self.object.show_window:
305 401 self.request.session['resources'] = {}
... ...