internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: kartoza/prj.app

Issue:
fix training hours text 
setting a number in the instruction hours field like this
![image](https://user-images.githubusercontent.com/233663/34878223-bad08582-f7a9-11e7-954a-4433f168fd3e.png)

will result in a certificate saying 
![image](https://user-images.githubusercontent.com/233663/34878273-e6d966e4-f7a9-11e7-9c5d-3b67d102f341.png)

the word hours is missing.

we should either add hours to the certificate template or simply change the `instruction hours` field to `course duration`
Remove redundant project name from certifying orgs list
![screen shot 2018-01-13 at 01 02 04](https://user-images.githubusercontent.com/178003/34900361-f60c65f4-f807-11e7-9141-b10a08f282de.png)


We can remove all the repeated QGIS text here and rather filter the cert orgs based on the active project.

Also please include the org url in their details summary so it is easy to go and cross reference who they are.

Regards

Tim


Discussion:

Resolving patch:
diff --git a/django_project/certification/migrations/0014_certifyingorganisation_url.py b/django_project/certification/migrations/0014_certifyingorganisation_url.py
new file mode 100644
--- /dev/null
+++ b/django_project/certification/migrations/0014_certifyingorganisation_url.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('certification', '0013_auto_20171014_1045'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='certifyingorganisation',
+            name='url',
+            field=models.URLField(help_text="Optional URL for the certifying organisation's home page", null=True, blank=True),
+        ),
+    ]
diff --git a/django_project/certification/models/certifying_organisation.py b/django_project/certification/models/certifying_organisation.py
--- a/django_project/certification/models/certifying_organisation.py
+++ b/django_project/certification/models/certifying_organisation.py
@@ -92,6 +92,12 @@ class CertifyingOrganisation(models.Model):
         validators=[validate_email_address],
     )
 
+    url = models.URLField(
+        help_text=u'Optional URL for the certifying organisation\'s home page',
+        blank=True,
+        null=True
+    )
+
     address = models.TextField(
         help_text=_('Address of Organisation or Institution.'),
         max_length=1000,
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -231,7 +231,7 @@ def generate_pdf(
 
     if course.course_type.instruction_hours:
         course_duration = \
-            '{} ({} of instruction)'.format(
+            '{} ({} hours of instruction)'.format(
                 course_duration,
                 course.course_type.instruction_hours)
 


Test patch:
Repository: kartoza/prj.app

Issue:
fix training hours text 
setting a number in the instruction hours field like this
![image](https://user-images.githubusercontent.com/233663/34878223-bad08582-f7a9-11e7-954a-4433f168fd3e.png)

will result in a certificate saying 
![image](https://user-images.githubusercontent.com/233663/34878273-e6d966e4-f7a9-11e7-9c5d-3b67d102f341.png)

the word hours is missing.

we should either add hours to the certificate template or simply change the `instruction hours` field to `course duration`
Remove redundant project name from certifying orgs list
![screen shot 2018-01-13 at 01 02 04](https://user-images.githubusercontent.com/178003/34900361-f60c65f4-f807-11e7-9141-b10a08f282de.png)


We can remove all the repeated QGIS text here and rather filter the cert orgs based on the active project.

Also please include the org url in their details summary so it is easy to go and cross reference who they are.

Regards

Tim


Discussion:

Resolving patch:
diff --git a/django_project/certification/forms.py b/django_project/certification/forms.py
--- a/django_project/certification/forms.py
+++ b/django_project/certification/forms.py
@@ -46,6 +46,7 @@ class Meta:
         fields = (
             'name',
             'organisation_email',
+            'url',
             'address',
             'country',
             'organisation_phone',
@@ -64,6 +65,7 @@ def __init__(self, *args, **kwargs):
                 form_title,
                 Field('name', css_class='form-control'),
                 Field('organisation_email', css_class='form-control'),
+                Field('url', css_class='form-control'),
                 Field('address', css_class='form-control'),
                 Field('country', css_class='form-control chosen-select'),
                 Field('organisation_phone', css_class='form-control'),


Test patch:
Repository: kartoza/prj.app

Issue:
logged out user is allowed to regenerate certificate
Is this ment to be?

![screenshot from 2018-01-26 11-18-42](https://user-images.githubusercontent.com/233663/35436080-58f482ca-028d-11e8-8fd7-48799ccd99ac.png)



Discussion:
No definately not - @ann26 can you fix this with high priority please?

Resolving patch:
diff --git a/django_project/certification/views/certificate.py b/django_project/certification/views/certificate.py
--- a/django_project/certification/views/certificate.py
+++ b/django_project/certification/views/certificate.py
@@ -579,12 +579,23 @@ def regenerate_certificate(request, **kwargs):
     """Regenerate a pdf certificate for an attendee."""
 
     project_slug = kwargs.pop('project_slug', None)
+    organisation_slug = kwargs.pop('organisation_slug', None)
     course_slug = kwargs.pop('course_slug', None)
     pk = kwargs.pop('pk')
     course = Course.objects.get(slug=course_slug)
     attendee = Attendee.objects.get(pk=pk)
     project = Project.objects.get(slug=project_slug)
     certificate = Certificate.objects.get(course=course, attendee=attendee)
+    certifying_organisation = \
+        CertifyingOrganisation.objects.get(slug=organisation_slug)
+
+    # Checking user permissions.
+    if request.user.is_staff or request.user == project.owner or \
+            request.user in project.certification_manager.all() or \
+            request.user in certifying_organisation.organisation_owners.all():
+        pass
+    else:
+        raise Http404
 
     filename = "{}.{}".format(certificate.certificateID, "pdf")
     project_folder = (project.name.lower()).replace(' ', '_')
@@ -636,6 +647,17 @@ def regenerate_all_certificate(request, **kwargs):
     organisation_slug = kwargs.get('organisation_slug', None)
     course = Course.objects.get(slug=course_slug)
     project = Project.objects.get(slug=project_slug)
+    certifying_organisation = \
+        CertifyingOrganisation.objects.get(slug=organisation_slug)
+
+    # Checking user permissions.
+    if request.user.is_staff or request.user == project.owner or \
+            request.user in project.certification_manager.all() or \
+            request.user in certifying_organisation.organisation_owners.all():
+        pass
+    else:
+        raise Http404
+
     attendees_pk = \
         Certificate.objects.filter(
             course=course).values_list('attendee', flat=True)


Test patch:
Repository: kartoza/prj.app

Issue:
description field is too short
the description field is super short. It would be good to allow a bit more of text so that a course can be explained


Discussion:
+1 I just noticed this yesterday.
@ann26 should be a quick fix, can you do this?
@mbernasocchi btw can you give a bit more context or a screenshot so we can be sure that we are all talking about the same thing....
![image](https://user-images.githubusercontent.com/233663/35726301-b732f8d6-0804-11e8-827b-cd3dfb32f7d9.png)


Resolving patch:
diff --git a/django_project/certification/migrations/0015_auto_20180207_1243.py b/django_project/certification/migrations/0015_auto_20180207_1243.py
new file mode 100644
--- /dev/null
+++ b/django_project/certification/migrations/0015_auto_20180207_1243.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('certification', '0014_certifyingorganisation_url'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='coursetype',
+            name='description',
+            field=models.TextField(help_text='Course type description - 1000 characters limit.', max_length=1000, null=True, blank=True),
+        ),
+    ]
diff --git a/django_project/certification/models/course_type.py b/django_project/certification/models/course_type.py
--- a/django_project/certification/models/course_type.py
+++ b/django_project/certification/models/course_type.py
@@ -40,8 +40,8 @@ class CourseType(models.Model):
     )
 
     description = models.TextField(
-        help_text=_('Course type description.'),
-        max_length=250,
+        help_text=_('Course type description - 1000 characters limit.'),
+        max_length=1000,
         null=True,
         blank=True,
     )


Test patch:
Repository: kartoza/prj.app

Issue:
Duplicated Unapproved Certifying Orgs
There have been duplicate entries for some organizations showing up on the Unapproved Certifying Organisations page
[http://changelog.qgis.org/en/qgis/pending-certifyingorganisation/list/](url)

For example, there were duplicate CampToCamp and CampToCamp SA organizations.  
Deleting one CampToCamp entry removed the other. 
Approving one CampToCampSA entry resulting in one approved organization and removed both entries from the Unapproved Certifying Organisations page.
This behavior indicates that while showing up as duplicates they in fact represent single entries.




Discussion:

Resolving patch:
diff --git a/django_project/certification/views/certifying_organisation.py b/django_project/certification/views/certifying_organisation.py
--- a/django_project/certification/views/certifying_organisation.py
+++ b/django_project/certification/views/certifying_organisation.py
@@ -680,7 +680,7 @@ def get_queryset(self):
                             (Q(project__owner=self.request.user) |
                              Q(organisation_owners=self.request.user) |
                              Q(project__certification_manager=self.request.user
-                               )))
+                               ))).distinct()
                 return queryset
             else:
                 raise Http404(


Test patch:
Repository: kartoza/prj.app

Issue:
We need another url field 
A project currently has a 'project url' field 'for this project\s [sic] home page'

I think there should be another field and they should be
- project website
- project code repository


Discussion:

Resolving patch:
diff --git a/django_project/base/forms.py b/django_project/base/forms.py
--- a/django_project/base/forms.py
+++ b/django_project/base/forms.py
@@ -93,6 +93,7 @@ class Meta:
             'accent_color',
             'description',
             'project_url',
+            'project_repository_url',
             'precis',
             'gitter_room',
             'signature',
@@ -118,6 +119,7 @@ def __init__(self, *args, **kwargs):
                 Field('accent_color', css_class="form-control"),
                 Field('description', css_class="form-control"),
                 Field('project_url', css_class="form-control"),
+                Field('project_repository_url', css_class="form-control"),
                 Field('precis', css_class="form-control"),
                 Field('signature', css_class="form-control"),
                 Field('changelog_managers', css_class="form-control"),
diff --git a/django_project/base/migrations/0019_project_project_repository_url.py b/django_project/base/migrations/0019_project_project_repository_url.py
new file mode 100644
--- /dev/null
+++ b/django_project/base/migrations/0019_project_project_repository_url.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('base', '0018_auto_20180220_0339'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='project',
+            name='project_repository_url',
+            field=models.URLField(help_text="A repository URL for this project. For instance a path to the project's GitHub repository.", null=True, blank=True),
+        ),
+    ]
diff --git a/django_project/base/models/project.py b/django_project/base/models/project.py
--- a/django_project/base/models/project.py
+++ b/django_project/base/models/project.py
@@ -158,6 +158,14 @@ class Project(models.Model):
         null=True
     )
 
+    project_repository_url = models.URLField(
+        help_text=_(
+            'A repository URL for this project. '
+            'For instance a path to the project\'s GitHub repository.'),
+        blank=True,
+        null=True
+    )
+
     sponsorship_programme = models.TextField(
         help_text=_(
             'Please describe the sponsorship programme for this project '


Test patch:
Repository: kartoza/prj.app

Issue:
We need to specify preferred size for logos in project view
specify logo image size else resize

It becomes a guessing game otherwise...


Discussion:
funny enough after writing a mail to @timlinux  I came to say: only thing not super good is the quality of our logo. we should give recommendations on size.
@sonlinux lets recommend  squaare logo at e.g. 2048x2018  (make a test certificate to see if that gives good quality)

Resolving patch:
diff --git a/django_project/base/migrations/0020_auto_20180226_1401.py b/django_project/base/migrations/0020_auto_20180226_1401.py
new file mode 100644
--- /dev/null
+++ b/django_project/base/migrations/0020_auto_20180226_1401.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('base', '0019_project_project_repository_url'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='project',
+            name='image_file',
+            field=models.ImageField(help_text='A logo image for this project. Most browsers support dragging the image directly on to the "Choose File" button above. The ideal size for your image is 512 x 512 pixels.', upload_to=b'images/projects', blank=True),
+        ),
+    ]
diff --git a/django_project/base/models/project.py b/django_project/base/models/project.py
--- a/django_project/base/models/project.py
+++ b/django_project/base/models/project.py
@@ -103,9 +103,10 @@ class Project(models.Model):
     )
 
     image_file = models.ImageField(
-        help_text=_('A logo image for this project. '
-                    'Most browsers support dragging the image directly on to '
-                    'the "Choose File" button above.'),
+        help_text=_(
+            'A logo image for this project. Most browsers support dragging '
+            'the image directly on to the "Choose File" button above. The '
+            'ideal size for your image is 512 x 512 pixels.'),
         upload_to=os.path.join(MEDIA_ROOT, 'images/projects'),
         blank=True
     )
@@ -117,9 +118,9 @@ class Project(models.Model):
         default='#FF0000')
 
     signature = models.ImageField(
-        help_text=_('Signature of the project owner. '
-                    'Most browsers support dragging the image directly on to '
-                    'the "Choose File" button above.'),
+        help_text=_(
+            'Signature of the project owner. Most browsers support dragging '
+            'the image directly on to the "Choose File" button above.'),
         upload_to=os.path.join(MEDIA_ROOT, 'images/projects/signatures'),
         blank=True
     )


Test patch:
Repository: kartoza/prj.app

Issue:
Review items in #770 need to be addressed
Please address the comments in this PR: https://github.com/kartoza/projecta/pull/770


Discussion:

Resolving patch:
diff --git a/django_project/base/views/custom_domain.py b/django_project/base/views/custom_domain.py
--- a/django_project/base/views/custom_domain.py
+++ b/django_project/base/views/custom_domain.py
@@ -1,7 +1,5 @@
 # coding=utf-8
 from braces.views import LoginRequiredMixin, StaffuserRequiredMixin
-from django.db import IntegrityError
-from django.core.exceptions import ValidationError
 from django.core.urlresolvers import reverse
 from django.http import Http404
 from django.views.generic import (
@@ -193,21 +191,8 @@ def get_queryset(self):
         else:
             return qs.filter(user=self.request.user)
 
-    def get_context_data(self, **kwargs):
-        context = super(DomainUpdateView, self).get_context_data(**kwargs)
-        return context
-
     def get_success_url(self):
         if self.object.approved:
             return reverse('domain-list')
         else:
             return reverse('domain-pending-list')
-
-    def form_valid(self, form):
-        """Check that there is no referential integrity error when saving."""
-
-        try:
-            return super(DomainUpdateView, self).form_valid(form)
-        except IntegrityError:
-            return ValidationError(
-                'ERROR: Domain by this name is already exists!')
diff --git a/django_project/base/views/organisation.py b/django_project/base/views/organisation.py
--- a/django_project/base/views/organisation.py
+++ b/django_project/base/views/organisation.py
@@ -1,7 +1,5 @@
 # coding=utf-8
 from braces.views import LoginRequiredMixin, StaffuserRequiredMixin
-from django.db import IntegrityError
-from django.core.exceptions import ValidationError
 from django.core.urlresolvers import reverse
 from django.http import Http404
 from django.views.generic import (
@@ -189,22 +187,8 @@ def get_queryset(self):
         else:
             return qs.filter(owner=self.request.user)
 
-    def get_context_data(self, **kwargs):
-        context = super(
-            OrganisationUpdateView, self).get_context_data(**kwargs)
-        return context
-
     def get_success_url(self):
         if self.object.approved:
             return reverse('list-organisation')
         else:
             return reverse('pending-list-organisation')
-
-    def form_valid(self, form):
-        """Check that there is no referential integrity error when saving."""
-
-        try:
-            return super(OrganisationUpdateView, self).form_valid(form)
-        except IntegrityError:
-            return ValidationError(
-                'ERROR: Organisation by this name is already exists!')


Test patch:
Repository: kartoza/prj.app

Issue:
Adding a category shows multiple duplicate entries in the pending queue
I just added a new catagory to the version app

When I went to the pending queue I saw this:

![screen shot 2018-02-28 at 22 17 13](https://user-images.githubusercontent.com/178003/36811119-62c69af6-1cd5-11e8-8689-f6475ff61d5a.png)

When I approved the first item, all the categories were removed from the pending list.

Please make sure we only take unique categories in the pending list. 


Discussion:

Resolving patch:
diff --git a/django_project/changes/views/category.py b/django_project/changes/views/category.py
--- a/django_project/changes/views/category.py
+++ b/django_project/changes/views/category.py
@@ -601,7 +601,8 @@ def get_queryset(self):
                 self.queryset = Category.unapproved_objects.filter(
                     Q(project=self.project) &
                     (Q(project__owner=self.request.user) |
-                     Q(project__changelog_managers=self.request.user)))
+                     Q(project__changelog_managers=self.request.user))
+                ).distinct()
                 return self.queryset
             else:
                 raise Http404(


Test patch:
Repository: kartoza/prj.app

Issue:
Error 500: Editing Answers.
# Problem

When I select the edit option for the answers on http://changelog.qgis.org/id/inasafe-realtime2/
Then I get error 500.


Discussion:
Linked to Sentry http://sentry.kartoza.com/sentry/projecta/issues/22/

Resolving patch:
diff --git a/django_project/lesson/views/answer.py b/django_project/lesson/views/answer.py
--- a/django_project/lesson/views/answer.py
+++ b/django_project/lesson/views/answer.py
@@ -104,7 +104,7 @@ def get_form_kwargs(self):
         :rtype: dict
         """
         kwargs = super(AnswerUpdateView, self).get_form_kwargs()
-        answer = get_object_or_404(Answer, self.pk_url_kwarg)
+        answer = get_object_or_404(Answer, pk=kwargs['instance'].pk)
         kwargs['question'] = answer.question
         return kwargs
 


Test patch:
Repository: kartoza/prj.app

Issue:
'Add new entry' button not visible on version detail.
## Problem 
Add new entry button is missing (can not be seen) on version detail page.

## Solution
Fix permission to view the button

![add_new_entry](https://user-images.githubusercontent.com/10270148/37201147-8396d3de-238f-11e8-9f72-4d7f4ac034b7.png)



Discussion:

Resolving patch:
diff --git a/django_project/changes/views/version.py b/django_project/changes/views/version.py
--- a/django_project/changes/views/version.py
+++ b/django_project/changes/views/version.py
@@ -170,11 +170,30 @@ def get_context_data(self, **kwargs):
                 sponsors[sponsor.sponsorship_level].append(sponsor.sponsor)
 
         context['sponsors'] = sponsors
+        context['user_can_edit'] = False
+        context['user_can_delete'] = False
         project_slug = self.kwargs.get('project_slug', None)
         context['project_slug'] = project_slug
         if project_slug:
             context['project'] = Project.objects.get(slug=project_slug)
 
+        # lets check for specific user permissions here.
+        if self.request.user.is_staff:
+            context['user_can_edit'] = True
+            context['user_can_delete'] = True
+
+        if self.request.user.is_superuser:
+            context['user_can_edit'] = True
+            context['user_can_delete'] = True
+
+        if context['project'].changelog_managers.filter(
+                project__owner=self.request.user.id).exists():
+            context['user_can_edit'] = True
+            context['user_can_delete'] = True
+
+        if self.request.user == context['project'].owner:
+            context['user_can_edit'] = True
+            context['user_can_delete'] = True
         return context
 
     def get_queryset(self):


Test patch: