6 |
7 |
{% blocktrans %}Choose a date from the list below to revert to a previous version of this object.{% endblocktrans %}
8 |
9 |
10 | {% if action_list %}
11 | {% include "reversion-compare/action_list_partial.html" with action="../history/compare/" %}
12 | {% else %}
13 |
{% trans "This object doesn't have a change history. It probably wasn't added via this admin site." %}
14 | {% endif %}
15 |
16 |
17 | {% endblock %}
18 |
19 |
--------------------------------------------------------------------------------
/templates/socialaccount/snippets/provider_list.html:
--------------------------------------------------------------------------------
1 | {% load socialaccount %}
2 |
3 | {% get_providers as socialaccount_providers %}
4 |
5 | {% for provider in socialaccount_providers %}
6 | {% if provider.id == "openid" %}
7 | {% for brand in provider.get_brands %}
8 |
5 | You're receiving this e-mail because you or someone else has requested a password for your user account at {{ site_domain }}.
6 | It can be safely ignored if you did not request a password reset. Click the link below to reset your password.{% endblocktrans %}
7 |
8 |
9 | {{ password_reset_url }}
10 |
11 | {% if username %}{% blocktrans %}In case you forgot, your username is {{ username }}.{% endblocktrans %}
12 |
13 | {% endif %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Thank you for using {{ site_name }}!
14 | {{ site_domain }}{% endblocktrans %}
15 |
--------------------------------------------------------------------------------
/app_faq/views/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | """
5 | to handle a huge import with multiple names.
6 |
7 | eg:
8 | >>> from app_faq.views.answer import AnswerFormView
9 | to:
10 | >>> from app_faq.views import AnswerFormView
11 | """
12 |
13 | __all__ = [
14 | 'AnswerFormView',
15 |
16 | 'CommentFormView', 'CommentQuestionFormView',
17 | 'CommentAnswerFormView', 'CommentsOffsetView',
18 |
19 | 'QuestionHomePage', 'QuestionsTagged', 'QuestionRedirectView',
20 | 'QuestionDetail', 'QuestionCreate', 'QuestionSuggestedEditsCreate',
21 | 'QuestionSuggestedEditsReversions',
22 |
23 | 'TagListView', 'TagSearchOffset', 'TagSearchJSON',
24 | ]
25 |
26 | from app_faq.views.answer import *
27 | from app_faq.views.comment import *
28 | from app_faq.views.question import *
29 | from app_faq.views.tag import *
30 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangofaq.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError:
10 | # The above import may fail for some other reason. Ensure that the
11 | # issue is really that Django is missing to avoid masking other
12 | # exceptions on Python 2.
13 | try:
14 | import django
15 | except ImportError:
16 | raise ImportError(
17 | "Couldn't import Django. Are you sure it's installed and "
18 | "available on your PYTHONPATH environment variable? Did you "
19 | "forget to activate a virtual environment?"
20 | )
21 | raise
22 | execute_from_command_line(sys.argv)
23 |
--------------------------------------------------------------------------------
/templates/includes/profile_menus_top.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 | {% if request.user.is_authenticated %}
4 |
7 |
8 |
9 |
{% trans 'Are you sure you want to sign out?' %}
10 |
18 |
19 |
20 | {% endblock %}
21 |
--------------------------------------------------------------------------------
/templates/account/password_reset_done.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n account %}
3 | {% block title %}{% trans "Password Reset" %} :: {{ block.super }}{% endblock %}
4 | {% block robot %}
9 |
10 |
11 |
{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
12 |
13 | {% if user.is_authenticated %}
14 |
15 | {% include "account/snippets/already_logged_in.html" %}
16 |
17 | {% endif %}
18 |
19 |
20 | {% endblock %}
21 |
--------------------------------------------------------------------------------
/app_faq/models/help.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.utils.encoding import python_2_unicode_compatible
7 | from django.utils.translation import ugettext_lazy as _
8 |
9 | from app_faq.models.time import TimeStampedModel
10 |
11 |
12 | @python_2_unicode_compatible
13 | class Help(TimeStampedModel):
14 | creator = models.ForeignKey(
15 | User, related_name='help_creator')
16 |
17 | parent = models.ForeignKey(
18 | 'self', blank=True, null=True,
19 | related_name='child')
20 |
21 | title = models.CharField(
22 | _('Title'), max_length=200)
23 |
24 | description = models.TextField(_('Description'))
25 |
26 | def __str__(self):
27 | return self.title
28 |
29 | class Meta:
30 | verbose_name_plural = _('helps')
31 | ordering = ['-created']
32 |
--------------------------------------------------------------------------------
/templates/includes/footer.html:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/app_faq/utils/json.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.http import JsonResponse
5 |
6 |
7 | class JSONResponseMixin(object):
8 | """
9 | A mixin that can be used to render a JSON response.
10 | """
11 |
12 | def render_to_json_response(self, context, **response_kwargs):
13 | """
14 | Returns a JSON response, transforming 'context' to make the payload.
15 | """
16 | return JsonResponse(self.get_data(context), **response_kwargs)
17 |
18 | def get_data(self, context):
19 | """
20 | Returns an object that will be serialized as JSON by json.dumps().
21 | """
22 | # Note: This is *EXTREMELY* naive; in reality, you'll need
23 | # to do much more complex handling to ensure that arbitrary
24 | # objects -- such as Django model instances or querysets
25 | # -- can be serialized as JSON.
26 | return context
27 |
--------------------------------------------------------------------------------
/static/plugins/css/resizable.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * resizable 1.0.0
3 | * https://github.com/tannernetwork/resizable
4 | *
5 | * Copyright 2015 Tanner (http://tanner.zone)
6 | * Released under the MIT license
7 | */
8 | .resizable{position:relative}.resizable .resizable-handle{position:absolute;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.resizable .resizable-l,.resizable .resizable-r{height:calc(100% - 10px);top:5px;width:10px}.resizable .resizable-l{cursor:w-resize;left:-5px}.resizable .resizable-r{cursor:e-resize;right:-5px}.resizable .resizable-t,.resizable .resizable-b{height:10px;left:5px;width:calc(100% - 10px);background: #e8e8e8}.resizable .resizable-t{cursor:n-resize;top:-5px}.resizable .resizable-b{cursor:s-resize;bottom:-5px}.resizable-resizing{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.resizable-resizing-l{cursor:w-resize}.resizable-resizing-r{cursor:e-resize}.resizable-resizing-t{cursor:n-resize}.resizable-resizing-b{cursor:s-resize}
9 |
--------------------------------------------------------------------------------
/app_faq/models/content_type.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 |
5 | class ContentTypeToGetModel(object):
6 |
7 | """
8 | requires fields:
9 | - content_type: FK(ContentType)
10 | - object_id: PositiveIntegerField()
11 | """
12 |
13 | def get_related_object(self):
14 | """
15 | return the related object of content_type.
16 | eg:
17 | """
18 | # This should return an error: MultipleObjectsReturned
19 | # return self.content_type.get_object_for_this_type()
20 | # So, i handle it with this one:
21 | model_class = self.content_type.model_class()
22 | return model_class.objects.get(id=self.object_id)
23 |
24 | @property
25 | def _model_name(self):
26 | """
27 | return lowercase of model name.
28 | eg: `question`, `answer`
29 | """
30 | return self.get_related_object()._meta.model_name
31 |
--------------------------------------------------------------------------------
/app_faq/models/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | """
5 | to handle a huge import with multiple names.
6 |
7 | eg:
8 | >>> from app_faq.models.answer import Answer
9 | to:
10 | >>> from app_faq.models import Answer
11 | """
12 |
13 | __all__ = [
14 | 'AnswerQuerySet', 'Answer', 'AnswerSuggestedEdits',
15 | 'Bounty', 'BountyAward', 'Comment', 'ContentTypeToGetModel',
16 | 'Favorite', 'Flag', 'Help', 'Message', 'QuestionQuerySet',
17 | 'Question', 'QuestionSuggestedEdits', 'Tag', 'TimeStampedModel'
18 | ]
19 |
20 | from app_faq.models.answer import *
21 | from app_faq.models.bounty import *
22 | from app_faq.models.comment import *
23 | from app_faq.models.content_type import *
24 | from app_faq.models.favorite import *
25 | from app_faq.models.flag import *
26 | from app_faq.models.help import *
27 | from app_faq.models.message import *
28 | from app_faq.models.question import *
29 | from app_faq.models.tag import *
30 | from app_faq.models.time import *
31 |
--------------------------------------------------------------------------------
/templates/nocaptcha_recaptcha/widget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/templates/reversion-compare/compare_generic_many_to_many.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 |
4 | {% for item1, item2 in change_info.changed_items %}
5 | {{ item1 }} → {{ item2 }}
6 | {% endfor %}
7 |
8 | {% for item in change_info.removed_items %}
9 | - {{ item }}
10 | {% endfor %}
11 | {% for item in change_info.removed_missing_objects %}
12 | - {{ item }}*
13 | {% endfor %}
14 |
15 | {% for item in change_info.deleted_items %}
16 | - {{ item }} → Deleted
17 | {% endfor %}
18 |
19 | {% for item in change_info.added_items %}
20 | + {{ item }}
21 | {% endfor %}
22 | {% for item in change_info.added_missing_objects %}
23 | + {{ item }} *
24 | {% endfor %}
25 |
26 | {% for item in change_info.same_items %}
27 | {{ item }}
28 | {% endfor %}
29 | {% for item in change_info.same_missing_objects %}
30 | {{ item }}*
31 | {% endfor %}
32 |
33 |
--------------------------------------------------------------------------------
/static/css/github/tab.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Tab
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.tab{display:none}.ui.tab.active,.ui.tab.open{display:block}.ui.tab.loading{position:relative;overflow:hidden;display:block;min-height:250px}.ui.tab.loading *{position:relative!important;left:-10000px!important}.ui.tab.loading.segment:before,.ui.tab.loading:before{position:absolute;content:'';top:100px;left:50%;margin:-1.25em 0 0 -1.25em;width:2.5em;height:2.5em;border-radius:500rem;border:.2em solid rgba(0,0,0,.1)}.ui.tab.loading.segment:after,.ui.tab.loading:after{position:absolute;content:'';top:100px;left:50%;margin:-1.25em 0 0 -1.25em;width:2.5em;height:2.5em;-webkit-animation:button-spin .6s linear;animation:button-spin .6s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;border-radius:500rem;border-color:#767676 transparent transparent;border-style:solid;border-width:.2em;box-shadow:0 0 0 1px transparent}
--------------------------------------------------------------------------------
/templates/reversion-compare/compare_partial.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% for field_diff in compare_data %}
3 | {% firstof field_diff.field.verbose_name field_diff.field.related_name %}{% if field_diff.is_related and not field_diff.follow %}* {% endif %}
4 | {% if field_diff.field.help_text %}{{ field_diff.field.help_text }}
{% endif %}
5 |
6 |
{{ field_diff.diff }}
7 |
8 | {% empty %}
9 |
10 |
{% trans "There are no differences." %}
11 |
12 | {% endfor %}
13 |
14 | {% trans "Edit comment:" %}
15 | {{ version2.revision.comment|default:"(no comment exists)" }}
16 |
17 | {% if has_unfollowed_fields %}
18 | {% trans "Note:" %}
19 |
20 | {% blocktrans %}
21 | Fields/entries marked with * are not under reversion control.
22 | It may be that not all marked information are correct.
23 | {% endblocktrans %}
24 |
25 | {% endif %}
26 |
--------------------------------------------------------------------------------
/templates/account/verified_email_required.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Verify Your E-mail Address" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 |
8 |
9 |
10 | {% url 'account_email' as email_url %}
11 |
12 |
{% blocktrans %}This part of the site requires us to verify that
13 | you are who you claim to be. For this purpose, we require that you
14 | verify ownership of your e-mail address. {% endblocktrans %}
15 |
16 |
{% blocktrans %}We have sent an e-mail to you for
17 | verification. Please click on the link inside this e-mail. Please
18 | contact us if you do not receive it within a few minutes.{% endblocktrans %}
19 |
20 |
{% blocktrans %}Note: you can still change your e-mail address .{% endblocktrans %}
21 |
22 |
23 | {% endblock %}
24 |
--------------------------------------------------------------------------------
/app_faq/views/answer.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.contrib import messages
5 | from django.core.urlresolvers import reverse
6 | from django.shortcuts import (get_object_or_404, redirect)
7 | from django.contrib.auth.mixins import LoginRequiredMixin
8 | from django.utils.translation import ugettext_lazy as _
9 | from django.views.generic import FormView
10 |
11 | from app_faq.models.question import Question
12 | from app_faq.forms.answer import AnswerForm
13 |
14 |
15 | class AnswerFormView(LoginRequiredMixin, FormView):
16 | template_name = 'app_faq/answer_create.html'
17 | http_method_names = [u'post', ]
18 | form_class = AnswerForm
19 |
20 | def form_valid(self, form):
21 | question = get_object_or_404(Question, pk=self.kwargs['question_id'])
22 | initial = form.save(commit=False)
23 | initial.author = self.request.user
24 | initial.question = question
25 | initial.save()
26 | messages.success(self.request, _('Your answer successfully created!'))
27 | return redirect(reverse('question_redirect', kwargs={'pk': question.pk}))
28 |
--------------------------------------------------------------------------------
/static/js/semantic-calendar-widget.js:
--------------------------------------------------------------------------------
1 | (function ($) {
2 | /*****
3 | semantic calendar widget
4 | require `semantic.min.js` and `semantic-calendar.min.js`
5 |
6 | html structure:
7 |
8 |
17 | *****/
18 | if (!$) {$ = django.jQuery;}
19 | $.fn.calendarWidget = function() {
20 | $(this).calendar({
21 | monthFirst: false,
22 | type: 'date',
23 | today: 'true',
24 | formatter: {
25 | date: function (date, settings) {
26 | if (!date) return '';
27 | return date.toLocaleString(
28 | 'en-us', {year: 'numeric', month: '2-digit', day: '2-digit'}
29 | ).replace(/(\d+)\/(\d+)\/(\d+)/, '$3-$1-$2');
30 | }
31 | }
32 | });
33 | }
34 | })(jQuery);
35 |
36 | $(document).ready(function(){
37 | $('.ui.calendar').calendarWidget();
38 | });
39 |
--------------------------------------------------------------------------------
/templates/account/password_reset_from_key.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Change Password" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 |
8 |
9 | {% if token_fail %}
10 | {% url 'account_reset_password' as passwd_reset_url %}
11 |
{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset .{% endblocktrans %}
12 | {% else %}
13 | {% if form %}
14 |
19 | {% else %}
20 |
{% trans 'Your password is now changed.' %}
21 | {% endif %}
22 | {% endif %}
23 |
24 |
25 | {% endblock %}
26 |
--------------------------------------------------------------------------------
/static/css/github/rail.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Rail
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.rail{position:absolute;top:0;width:300px;height:100%;font-size:1rem}.ui.left.rail{left:auto;right:100%;padding:0 2rem 0 0;margin:0 2rem 0 0}.ui.right.rail{left:100%;right:auto;padding:0 0 0 2rem;margin:0 0 0 2rem}.ui.left.internal.rail{left:0;right:auto;padding:0 0 0 2rem;margin:0 0 0 2rem}.ui.right.internal.rail{left:auto;right:0;padding:0 2rem 0 0;margin:0 2rem 0 0}.ui.dividing.rail{width:302.5px}.ui.left.dividing.rail{padding:0 2.5rem 0 0;margin:0 2.5rem 0 0;border-right:1px solid rgba(34,36,38,.15)}.ui.right.dividing.rail{border-left:1px solid rgba(34,36,38,.15);padding:0 0 0 2.5rem;margin:0 0 0 2.5rem}.ui.close.rail{width:301px}.ui.close.left.rail{padding:0 1em 0 0;margin:0 1em 0 0}.ui.close.right.rail{padding:0 0 0 1em;margin:0 0 0 1em}.ui.very.close.rail{width:300.5px}.ui.very.close.left.rail{padding:0 .5em 0 0;margin:0 .5em 0 0}.ui.very.close.right.rail{padding:0 0 0 .5em;margin:0 0 0 .5em}.ui.attached.left.rail,.ui.attached.right.rail{padding:0;margin:0}
--------------------------------------------------------------------------------
/app_faq/models/favorite.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.contrib.contenttypes.models import ContentType
7 | from django.contrib.contenttypes.fields import GenericForeignKey
8 | from django.utils.encoding import python_2_unicode_compatible
9 | from django.utils.translation import ugettext_lazy as _
10 |
11 | from app_faq.models.time import TimeStampedModel
12 | from app_faq.models.content_type import ContentTypeToGetModel
13 |
14 |
15 | @python_2_unicode_compatible
16 | class Favorite(TimeStampedModel, ContentTypeToGetModel):
17 | user = models.ForeignKey(
18 | User, related_name='user_favorite')
19 |
20 | content_type = models.ForeignKey(
21 | ContentType, related_name='favorites',
22 | on_delete=models.CASCADE)
23 |
24 | object_id = models.PositiveIntegerField(_('Object id'))
25 |
26 | content_object = GenericForeignKey('content_type', 'object_id')
27 |
28 | def __str__(self):
29 | return '%s' % self.get_related_object()
30 |
31 | class Meta:
32 | verbose_name_plural = _('favorites')
33 | ordering = ['-created']
34 |
--------------------------------------------------------------------------------
/static/css/github/breadcrumb.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Breadcrumb
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.breadcrumb{line-height:1;display:inline-block;margin:0;vertical-align:middle}.ui.breadcrumb:first-child{margin-top:0}.ui.breadcrumb:last-child{margin-bottom:0}.ui.breadcrumb .divider{display:inline-block;opacity:1;margin:0;font-size:1.38461538rem;color:inherit;vertical-align:baseline}.ui.breadcrumb a,.ui.breadcrumb a:hover{color:#4078C0}.ui.breadcrumb .icon.divider{font-size:.84615385em;vertical-align:baseline}.ui.breadcrumb a.section{cursor:pointer}.ui.breadcrumb .section{display:inline-block;margin:0;padding:0}.ui.breadcrumb.segment{display:inline-block;padding:.69230769em 1em}.ui.breadcrumb .active.section{font-weight:700}.ui.mini.breadcrumb{font-size:.69230769rem}.ui.tiny.breadcrumb{font-size:.84615385rem}.ui.small.breadcrumb{font-size:.92307692rem}.ui.breadcrumb{font-size:1rem}.ui.large.breadcrumb{font-size:1.15384615rem}.ui.big.breadcrumb{font-size:1.38461538rem}.ui.huge.breadcrumb{font-size:1.46153846rem}.ui.massive.breadcrumb{font-size:1.69230769rem}
--------------------------------------------------------------------------------
/app_faq/models/tag.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.utils.encoding import python_2_unicode_compatible
7 | from django.utils.translation import ugettext_lazy as _
8 |
9 | from app_faq.models.time import TimeStampedModel
10 |
11 |
12 | @python_2_unicode_compatible
13 | class Tag(TimeStampedModel):
14 | creator = models.ForeignKey(
15 | User, related_name='tag_creator')
16 |
17 | title = models.CharField(
18 | _('Title'), max_length=200)
19 |
20 | slug = models.SlugField(
21 | _('Slug'), max_length=200, unique=True)
22 |
23 | short_description = models.TextField(
24 | _('Short Description'))
25 |
26 | wiki = models.TextField(
27 | _('Wiki'), null=True, blank=True)
28 |
29 | edited = models.BooleanField(
30 | _('Edited?'), default=False)
31 |
32 | editor = models.ForeignKey(
33 | User, blank=True, null=True,
34 | on_delete=models.SET_NULL, related_name='tag_editor')
35 |
36 | def __str__(self):
37 | return self.title
38 |
39 | class Meta:
40 | verbose_name_plural = _('tags')
41 | ordering = ['-created']
42 |
--------------------------------------------------------------------------------
/templates/includes/profile_menus_left.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 | {% if request.user.is_authenticated %}
4 |
22 | {% endif %}
23 |
--------------------------------------------------------------------------------
/app_faq/templatetags/counter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django import template
5 |
6 | from app_faq.models.question import Question
7 | from app_faq.models.answer import Answer
8 |
9 | register = template.Library()
10 |
11 |
12 | @register.filter
13 | def get_total_questions_tagged(tag):
14 | """
15 | usage in: `app_faq/tags.html`
16 |
17 | {{ tag|get_total_questions_tagged }}
18 |
19 | return total questions tagged
20 | and excluded from status='deleted'
21 | """
22 | qs = Question.objects.exclude(status='deleted')
23 | return qs.filter(tags=tag).count()
24 |
25 |
26 | @register.filter
27 | def get_total_votes(question):
28 | """
29 | usage in: `app_faq/question_homepage.html`
30 |
31 | {{ question|get_total_votes }}
32 | """
33 | return question.rating_likes
34 |
35 |
36 | @register.filter
37 | def get_total_answers(question):
38 | """
39 | usage in: `app_faq/question_homepage.html`
40 |
41 | {{ question|get_total_answers }}
42 | """
43 | return Answer.objects.filter(question=question).count()
44 |
45 |
46 | @register.filter
47 | def get_total_views(question):
48 | """
49 | usage in: `app_faq/question_homepage.html`
50 |
51 | {{ question|get_total_views }}
52 | """
53 | return 0
54 |
--------------------------------------------------------------------------------
/static/css/spfjs.css:
--------------------------------------------------------------------------------
1 | /*** spfjs progress bar ***/
2 |
3 | @-webkit-keyframes pulse {
4 | 30% { opacity: 0.6; }
5 | 60% { opacity: 0; }
6 | 100% { opacity: 0.6; }
7 | }
8 | @keyframes pulse {
9 | 30% { opacity: 0.6; }
10 | 60% { opacity: 0; }
11 | 100% { opacity: 0.6; }
12 | }
13 |
14 | #spfjs-progress-bar {
15 | position: fixed;
16 | z-index: 1000;
17 | top: 0;
18 | left: -6px;
19 | width: 0%;
20 | height: 2px;
21 | background: #45C2FF;
22 | border-radius: 1px;
23 | /* the following transition times are overridden by JS */
24 | -webkit-transition: width 150ms ease-out;
25 | transition: width 150ms ease-out;
26 | }
27 | #spfjs-progress-bar.done {
28 | opacity: 0;
29 | }
30 | #spfjs-progress-bar dd,
31 | #spfjs-progress-bar dt {
32 | position: absolute;
33 | top: 0;
34 | height: 2px;
35 | box-shadow: #45C2FF 1px 0 6px 1px;
36 | border-radius: 100%;
37 | }
38 | #spfjs-progress-bar dd {
39 | opacity: 0.6;
40 | width: 20px;
41 | right: 0;
42 | clip: rect(-6px, 22px, 14px, 10px);
43 | }
44 | #spfjs-progress-bar dt {
45 | opacity: 0.6;
46 | width: 180px;
47 | right: -80px;
48 | clip: rect(-6px, 90px, 14px, -6px);
49 | }
50 | #spfjs-progress-bar.waiting dd,
51 | #spfjs-progress-bar.waiting dt {
52 | -webkit-animation: pulse 2s ease-out 0s infinite;
53 | animation: pulse 2s ease-out 0s infinite;
54 | }
55 |
--------------------------------------------------------------------------------
/templates/account/email_confirm.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n account %}
3 | {% block title %}{% trans "Confirm E-mail Address" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 |
8 |
9 | {% if confirmation %}
10 | {% user_display confirmation.email_address.user as user_display %}
11 |
12 |
{% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}
13 |
14 |
20 | {% else %}
21 | {% url 'account_email' as email_url %}
22 |
{% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request .{% endblocktrans %}
23 | {% endif %}
24 |
25 |
26 | {% endblock %}
27 |
--------------------------------------------------------------------------------
/templates/reversion-compare/question/compare_generic_many_to_many.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 |
4 | {% for item1, item2 in change_info.changed_items %}
5 | {{ item1 }} → {{ item2 }}
6 | {% endfor %}
7 |
8 | {% for item in change_info.removed_items %}
9 | - {{ item }}
10 | {% endfor %}
11 | {% for item in change_info.removed_missing_objects %}
12 | - {{ item }} *
13 | {% endfor %}
14 |
15 | {% for item in change_info.deleted_items %}
16 | - {{ item }} → Deleted
17 | {% endfor %}
18 |
19 | {% for item in change_info.added_items %}
20 | + {{ item }}
21 | {% endfor %}
22 | {% for item in change_info.added_missing_objects %}
23 | + {{ item }} *
24 | {% endfor %}
25 |
26 | {% for item in change_info.same_items %}
27 | {{ item }}
28 | {% endfor %}
29 | {% for item in change_info.same_missing_objects %}
30 | {{ item }} *
31 | {% endfor %}
32 |
33 |
--------------------------------------------------------------------------------
/templates/app_faq/comment_create.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load staticfiles %}
3 |
4 |
5 |
6 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/templates/reversion-compare/question/compare_partial.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 |
4 | {{ version2.revision.comment|default:"(no comment exists)" }}
5 |
6 | {% for field_diff in compare_data %}
7 |
8 | {% if field_diff.field.help_text %}{{ field_diff.field.help_text }}
{% endif %}
9 |
10 |
{{ field_diff.diff }}
11 |
16 |
17 | {% empty %}
18 |
19 |
{% trans "There are no differences." %}
20 |
21 | {% endfor %}
22 |
23 | {% if has_unfollowed_fields %}
24 |
25 |
26 |
27 | {% blocktrans %}
28 | Fields/entries marked with * are not under reversion control.
29 | It may be that not all marked information are correct.
30 | {% endblocktrans %}
31 |
32 |
33 | {% endif %}
34 |
--------------------------------------------------------------------------------
/app_faq/models/comment.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.contrib.contenttypes.models import ContentType
7 | from django.contrib.contenttypes.fields import GenericForeignKey
8 | from django.utils.encoding import python_2_unicode_compatible
9 | from django.utils.translation import ugettext_lazy as _
10 |
11 | from updown.fields import RatingField
12 | from app_faq.models.time import TimeStampedModel
13 | from app_faq.models.content_type import ContentTypeToGetModel
14 |
15 |
16 | @python_2_unicode_compatible
17 | class Comment(TimeStampedModel, ContentTypeToGetModel):
18 | author = models.ForeignKey(
19 | User, related_name='comment_author')
20 |
21 | content_type = models.ForeignKey(
22 | ContentType, related_name='comments',
23 | on_delete=models.CASCADE)
24 |
25 | object_id = models.PositiveIntegerField(_('Object id'))
26 |
27 | content_object = GenericForeignKey('content_type', 'object_id')
28 |
29 | comment = models.TextField(_('Comment'))
30 |
31 | rating = RatingField(can_change_vote=True)
32 |
33 | edited = models.BooleanField(
34 | _('Edited?'), default=False)
35 |
36 | def __str__(self):
37 | return '%s' % self.get_related_object()
38 |
39 | class Meta:
40 | verbose_name_plural = _('comments')
41 | ordering = ['-created']
42 |
--------------------------------------------------------------------------------
/app_user/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.utils.encoding import python_2_unicode_compatible
7 | from django.utils.translation import ugettext_lazy as _
8 |
9 |
10 | @python_2_unicode_compatible
11 | class Profile(models.Model):
12 | user = models.OneToOneField(
13 | User, related_name='profile_user')
14 |
15 | display_name = models.CharField(
16 | _('Display name'), max_length=200, null=True, blank=True)
17 |
18 | location = models.CharField(
19 | _('Location'), max_length=200, null=True, blank=True)
20 |
21 | about_me = models.TextField(
22 | _('About Me'), null=True, blank=True)
23 |
24 | website = models.URLField(
25 | _('Website'), null=True, blank=True)
26 |
27 | twitter = models.URLField(
28 | _('Twitter'), null=True, blank=True)
29 |
30 | linkedin = models.URLField(
31 | _('Linkedin'), null=True, blank=True)
32 |
33 | github = models.URLField(
34 | _('Github'), null=True, blank=True)
35 |
36 | birth_date = models.DateField(
37 | _('Birth date'), null=True, blank=True)
38 |
39 | def __str__(self):
40 | return self.user.username
41 |
42 | class Meta:
43 | verbose_name = _('Detail User Profile')
44 | verbose_name_plural = _('User Profiles')
45 | ordering = ['-user__date_joined']
46 |
--------------------------------------------------------------------------------
/static/css/github/nag.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Nag
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.nag{display:none;opacity:.95;position:relative;top:0;left:0;z-index:999;min-height:0;width:100%;margin:0;padding:.75em 1em;background:#555;box-shadow:0 1px 2px 0 rgba(0,0,0,.2);font-size:1rem;text-align:center;color:rgba(0,0,0,.87);border-radius:0 0 .28571429rem .28571429rem;-webkit-transition:.2s background ease;transition:.2s background ease}a.ui.nag{cursor:pointer}.ui.nag>.title{display:inline-block;margin:0 .5em;color:#FFF}.ui.nag>.close.icon{cursor:pointer;opacity:.4;position:absolute;top:50%;right:1em;font-size:1em;margin:-.5em 0 0;color:#FFF;-webkit-transition:opacity .2s ease;transition:opacity .2s ease}.ui.nag:hover{background:#555;opacity:1}.ui.nag .close:hover{opacity:1}.ui.overlay.nag{position:absolute;display:block}.ui.fixed.nag{position:fixed}.ui.bottom.nag,.ui.bottom.nags{border-radius:.28571429rem .28571429rem 0 0;top:auto;bottom:0}.ui.inverted.nag,.ui.inverted.nags .nag{background-color:#F3F4F5;color:rgba(0,0,0,.85)}.ui.inverted.nag .close,.ui.inverted.nag .title,.ui.inverted.nags .nag .close,.ui.inverted.nags .nag .title{color:rgba(0,0,0,.4)}.ui.nags .nag{border-radius:0!important}.ui.nags .nag:last-child{border-radius:0 0 .28571429rem .28571429rem}.ui.bottom.nags .nag:last-child{border-radius:.28571429rem .28571429rem 0 0}
--------------------------------------------------------------------------------
/app_faq/forms/question.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django import forms
5 | from django.utils.translation import ugettext_lazy as _
6 |
7 | from martor.widgets import AdminMartorWidget
8 | from app_faq.models.question import Question, QuestionSuggestedEdits
9 |
10 |
11 | class QuestionForm(forms.ModelForm):
12 |
13 | class Meta:
14 | model = Question
15 | fields = ['title', 'description', 'tags']
16 | widgets = {
17 | 'tags': forms.SelectMultiple(attrs={'class': 'ui search fluid dropdown tags-dropdown'}),
18 | 'title': forms.TextInput(attrs={'placeholder': _("What's your programming question? Be specific.")}),
19 | 'description': AdminMartorWidget()
20 | }
21 |
22 | # def __init__(self, *args, **kwargs):
23 | # super(QuestionForm, self).__init__(*args, **kwargs)
24 | # self.fields['tags'].widget.attrs = {'class': 'ui search fluid dropdown tags-dropdown'}
25 |
26 |
27 | class QuestionSuggestedEditsForm(forms.ModelForm):
28 |
29 | class Meta:
30 | model = QuestionSuggestedEdits
31 | fields = ['title', 'description', 'tags', 'comment']
32 | widgets = {
33 | 'tags': forms.SelectMultiple(attrs={'class': 'ui search fluid dropdown tags-dropdown'}),
34 | 'title': forms.TextInput(attrs={'placeholder': _("What's your programming question? Be specific.")}),
35 | 'description': AdminMartorWidget()
36 | }
37 |
--------------------------------------------------------------------------------
/app_faq/models/message.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.contrib.contenttypes.models import ContentType
7 | from django.contrib.contenttypes.fields import GenericForeignKey
8 | from django.utils.encoding import python_2_unicode_compatible
9 | from django.utils.translation import ugettext_lazy as _
10 |
11 | from updown.fields import RatingField
12 | from app_faq.models.time import TimeStampedModel
13 | from app_faq.models.content_type import ContentTypeToGetModel
14 |
15 |
16 | @python_2_unicode_compatible
17 | class Message(TimeStampedModel, ContentTypeToGetModel):
18 | sender = models.ForeignKey(
19 | User, related_name='message_sender')
20 |
21 | receiver = models.ForeignKey(
22 | User, related_name='message_receiver')
23 |
24 | content_type = models.ForeignKey(
25 | ContentType, related_name='messages',
26 | on_delete=models.CASCADE)
27 |
28 | object_id = models.PositiveIntegerField(_('Object id'))
29 |
30 | content_object = GenericForeignKey('content_type', 'object_id')
31 |
32 | message = models.TextField(
33 | _('Message'), null=True, blank=True)
34 |
35 | read = models.BooleanField(
36 | _('is read?'), default=False)
37 |
38 | def __str__(self):
39 | return '%s' % self.get_related_object()
40 |
41 | class Meta:
42 | verbose_name_plural = _('messages')
43 | ordering = ['-created']
44 |
--------------------------------------------------------------------------------
/djangofaq/urls.py:
--------------------------------------------------------------------------------
1 | """djangoforum URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.conf.urls import url, include
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
15 | """
16 | from django.conf import settings
17 | from django.contrib import admin
18 | from django.conf.urls import include, url
19 | from django.conf.urls.static import static
20 | from django.views.i18n import JavaScriptCatalog
21 |
22 | urlpatterns = [
23 | url(r'^admin/', admin.site.urls),
24 | url(r'^badges/', include('badges.urls')),
25 |
26 | # internationalization
27 | url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'),
28 | url(r'^i18n/', include('django.conf.urls.i18n')),
29 |
30 | # 3d party apps
31 | url(r'^accounts/', include('allauth.urls')),
32 | url(r'^martor/', include('martor.urls')),
33 |
34 | # major apps
35 | url(r'^', include('app_faq.urls')),
36 | url(r'^', include('app_user.urls')),
37 | ]
38 |
39 | if settings.DEBUG:
40 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
41 |
--------------------------------------------------------------------------------
/templates/app_faq/question_revisions_old.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load i18n staticfiles %}
3 | {% load common_tags %}
4 | {% block title %}{% trans "Revision for" %} {{ question.title }} :: {{ block.super }}{% endblock %}
5 |
6 | {% block css %}
7 |
17 | {% endblock %}
18 |
19 | {% block content %}
20 |
21 |
22 |
23 |
{% trans "Revision for" %} "{{ question.title }}"
24 |
29 |
30 |
31 |
32 | {% include "reversion-compare/question/action_list_partial.html" %}
33 | {% if request.GET.version_id1 %}
34 | {% include "reversion-compare/question/compare_partial.html" %}
35 | {% include "reversion-compare/question/compare_links_partial.html" %}
36 | {% endif %}
37 |
38 |
39 | {% endblock %}
40 |
41 | {% block js %}
42 |
43 | {% endblock %}
44 |
--------------------------------------------------------------------------------
/static/css/github/site.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Site
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */body,html{height:100%}html{font-size:13px}body{margin:0;padding:0;overflow-x:visible;min-width:1049px;background:#FFF;font-family:Arial,'Helvetica Neue',Arial,Helvetica,sans-serif;font-size:13px;line-height:1.4285em;color:rgba(0,0,0,.87);font-smoothing:antialiased}h1,h2,h3,h4,h5{font-family:Arial,'Helvetica Neue',Arial,Helvetica,sans-serif;line-height:1.2857em;margin:calc(2rem - .14285em) 0 1rem;font-weight:700;padding:0}h1{min-height:1rem;font-size:2rem}h2{font-size:1.714rem}h3{font-size:1.28rem}h4{font-size:1.071rem}h5{font-size:1rem}h1:first-child,h2:first-child,h3:first-child,h4:first-child,h5:first-child,p:first-child{margin-top:0}h1:last-child,h2:last-child,h3:last-child,h4:last-child,h5:last-child,p:last-child{margin-bottom:0}p{margin:0 0 1em;line-height:1.4285em}a{color:#4078C0;text-decoration:none}a:hover{color:#4078C0;text-decoration:underline}::-webkit-selection{background-color:#CCE2FF;color:rgba(0,0,0,.87)}::-moz-selection{background-color:#CCE2FF;color:rgba(0,0,0,.87)}::selection{background-color:#CCE2FF;color:rgba(0,0,0,.87)}input::-webkit-selection,textarea::-webkit-selection{background-color:rgba(100,100,100,.4);color:rgba(0,0,0,.87)}input::-moz-selection,textarea::-moz-selection{background-color:rgba(100,100,100,.4);color:rgba(0,0,0,.87)}input::selection,textarea::selection{background-color:rgba(100,100,100,.4);color:rgba(0,0,0,.87)}
--------------------------------------------------------------------------------
/static/css/github/container.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Container
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.container{display:block;max-width:100%!important}@media only screen and (max-width:1048px){.ui.container{width:auto!important;margin-left:1em!important;margin-right:1em!important}.ui.grid.container,.ui.relaxed.grid.container,.ui.very.relaxed.grid.container{width:auto!important}}@media only screen and (min-width:1049px) and (max-width:1048px){.ui.container{width:993px;margin-left:auto!important;margin-right:auto!important}.ui.grid.container{width:calc(993px + 2rem)!important}.ui.relaxed.grid.container{width:calc(993px + 3rem)!important}.ui.very.relaxed.grid.container{width:calc(993px + 5rem)!important}}@media only screen and (min-width:1049px){.ui.container{width:980px;margin-left:auto!important;margin-right:auto!important}.ui.grid.container{width:calc(980px + 2rem)!important}.ui.relaxed.grid.container{width:calc(980px + 3rem)!important}.ui.very.relaxed.grid.container{width:calc(980px + 5rem)!important}}.ui.text.container{font-family:Arial,'Helvetica Neue',Arial,Helvetica,sans-serif;max-width:700px!important;line-height:1.5;font-size:1.15384615rem}.ui.fluid.container{width:100%}.ui[class*="left aligned"].container{text-align:left}.ui[class*="center aligned"].container{text-align:center}.ui[class*="right aligned"].container{text-align:right}.ui.justified.container{text-align:justify;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto}
--------------------------------------------------------------------------------
/templates/app_faq/question_revisions.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load i18n staticfiles %}
3 | {% load common_tags %}
4 | {% block title %}{% trans "Revision for" %} {{ question_suggested_edits.title }} :: {{ block.super }}{% endblock %}
5 |
6 | {% block css %}
7 |
17 | {% endblock %}
18 |
19 | {% block content %}
20 |
21 |
22 |
23 |
{% trans "Revision for" %} "{{ question_suggested_edits.title }}"
24 |
29 |
30 |
31 |
32 | {% include "reversion-compare/question/action_list_partial.html" %}
33 | {% if request.GET.version_id1 %}
34 | {% include "reversion-compare/question/compare_partial.html" %}
35 | {% include "reversion-compare/question/compare_links_partial.html" %}
36 | {% endif %}
37 |
38 |
39 | {% endblock %}
40 |
41 | {% block js %}
42 |
43 | {% endblock %}
44 |
--------------------------------------------------------------------------------
/static/js/djangofaq.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 | var
3 | $userDropdown = $('.user.dropdown'),
4 | $addDropdown = $('.add.dropdown'),
5 | $button = $('.ui.button'),
6 | $watchButton = $('.watch.button'),
7 | $search = $('.page.header input'),
8 | $popup = $('[data-content]'),
9 | $checkbox = $('.ui.checkbox')
10 | ;
11 |
12 | $.fn.dropdown.settings.onShow = function() {
13 | $('body').popup('hide all');
14 | };
15 |
16 | $popup.popup({
17 | duration : 0,
18 | delay : {
19 | show : 10,
20 | hide : 0
21 | },
22 | variation : 'inverted',
23 | position : 'bottom center'
24 | });
25 |
26 | $addDropdown.dropdown({
27 | duration : 0,
28 | action : 'hide'
29 | });
30 |
31 | $userDropdown.dropdown({
32 | duration : 0,
33 | transition : 'drop',
34 | action : 'hide'
35 | });
36 |
37 | $watchButton.dropdown({
38 | allowTab: false,
39 | transition: 'scale',
40 | onChange: function(value) {
41 | console.log('New watch value', value);
42 | }
43 | });
44 |
45 | $checkbox.checkbox();
46 |
47 | // Focus wrapper
48 | $search.on('focus', function() {
49 | $(this).closest('.input').addClass('focused');
50 | })
51 | .on('blur', function() {
52 | $(this).closest('.input').removeClass('focused');
53 | });
54 |
55 | // Close a message
56 | $('.message .close').on('click', function() {
57 | $(this).closest('.message').hide();
58 | $('.main-messages').css({'padding': 0, 'border-bottom': 'none'});
59 | });
60 | setTimeout(function(){
61 | $('.main-messages').find('.message .close').trigger('click');
62 | }, 5000);
63 | });
64 |
--------------------------------------------------------------------------------
/app_faq/models/flag.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.contrib.auth.models import User
6 | from django.contrib.contenttypes.models import ContentType
7 | from django.contrib.contenttypes.fields import GenericForeignKey
8 | from django.utils.encoding import python_2_unicode_compatible
9 | from django.utils.translation import ugettext_lazy as _
10 |
11 | from app_faq.models.time import TimeStampedModel
12 | from app_faq.models.content_type import ContentTypeToGetModel
13 |
14 |
15 | @python_2_unicode_compatible
16 | class Flag(TimeStampedModel, ContentTypeToGetModel):
17 | creator = models.ForeignKey(
18 | User, related_name='flag_creator')
19 |
20 | content_type = models.ForeignKey(
21 | ContentType, related_name='flags',
22 | on_delete=models.CASCADE)
23 |
24 | object_id = models.PositiveIntegerField(_('Object id'))
25 |
26 | content_object = GenericForeignKey('content_type', 'object_id')
27 |
28 | FLAG_CHOICES = (
29 | ('spam', _('as spam')),
30 | ('rude', _('as rude or abusive')),
31 | ('duplicated', _('as duplicate')),
32 | ('low-quality', _('as very low quality')),
33 | ('protected', _('as protected')),
34 | ('normal', _('as normal'))
35 | )
36 | status = models.CharField(
37 | _('Status'), max_length=20,
38 | choices=FLAG_CHOICES, default='normal')
39 |
40 | def __str__(self):
41 | title = _('%(creator)s flagged %(status)s to %(model)s:%(id)s')
42 | return title % {'creator': self.creator.username, 'status': self.status,
43 | 'model': self._model_name, 'id': self.object_id}
44 |
45 | class Meta:
46 | verbose_name_plural = _('flags')
47 | ordering = ['-created']
48 |
--------------------------------------------------------------------------------
/static/css/github/embed.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Video
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.embed{position:relative;max-width:100%;height:0;overflow:hidden;background:#DCDDDE;padding-bottom:56.25%}.ui.embed embed,.ui.embed iframe,.ui.embed object{position:absolute;border:none;width:100%;height:100%;top:0;left:0;margin:0;padding:0}.ui.embed>.embed{display:none}.ui.embed>.placeholder{position:absolute;cursor:pointer;top:0;left:0;display:block;width:100%;height:100%;background-color:radial-gradient(transparent 45%,rgba(0,0,0,.3))}.ui.embed>.icon{cursor:pointer;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2}.ui.embed>.icon:after{position:absolute;top:0;left:0;width:100%;height:100%;z-index:3;content:'';background:-webkit-radial-gradient(transparent 45%,rgba(0,0,0,.3));background:radial-gradient(transparent 45%,rgba(0,0,0,.3));opacity:.5;-webkit-transition:opacity .5s ease;transition:opacity .5s ease}.ui.embed>.icon:before{position:absolute;top:50%;left:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);color:#FFF;font-size:6rem;text-shadow:0 2px 10px rgba(34,36,38,.2);-webkit-transition:opacity .5s ease,color .5s ease;transition:opacity .5s ease,color .5s ease;z-index:10}.ui.embed .icon:hover:after{background:-webkit-radial-gradient(transparent 45%,rgba(0,0,0,.3));background:radial-gradient(transparent 45%,rgba(0,0,0,.3));opacity:1}.ui.embed .icon:hover:before{color:#FFF}.ui.active.embed>.icon,.ui.active.embed>.placeholder{display:none}.ui.active.embed>.embed{display:block}.ui.square.embed{padding-bottom:100%}.ui[class*="4:3"].embed{padding-bottom:75%}.ui[class*="16:9"].embed{padding-bottom:56.25%}.ui[class*="21:9"].embed{padding-bottom:42.85714286%}
--------------------------------------------------------------------------------
/static/plugins/js/snippets/markdown.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/snippets/markdown",["require","exports","module"],function(e,t,n){"use strict";t.snippetText='# Markdown\n\n# Includes octopress (http://octopress.org/) snippets\n\nsnippet [\n [${1:text}](http://${2:address} "${3:title}")\nsnippet [*\n [${1:link}](${2:`@*`} "${3:title}")${4}\n\nsnippet [:\n [${1:id}]: http://${2:url} "${3:title}"\nsnippet [:*\n [${1:id}]: ${2:`@*`} "${3:title}"\n\nsnippet \nsnippet ${4}\n\nsnippet ![:\n ![${1:id}]: ${2:url} "${3:title}"\nsnippet ![:*\n ![${1:id}]: ${2:`@*`} "${3:title}"\n\nsnippet ===\nregex /^/=+/=*//\n ${PREV_LINE/./=/g}\n \n ${0}\nsnippet ---\nregex /^/-+/-*//\n ${PREV_LINE/./-/g}\n \n ${0}\nsnippet blockquote\n {% blockquote %}\n ${1:quote}\n {% endblockquote %}\n\nsnippet blockquote-author\n {% blockquote ${1:author}, ${2:title} %}\n ${3:quote}\n {% endblockquote %}\n\nsnippet blockquote-link\n {% blockquote ${1:author} ${2:URL} ${3:link_text} %}\n ${4:quote}\n {% endblockquote %}\n\nsnippet bt-codeblock-short\n ```\n ${1:code_snippet}\n ```\n\nsnippet bt-codeblock-full\n ``` ${1:language} ${2:title} ${3:URL} ${4:link_text}\n ${5:code_snippet}\n ```\n\nsnippet codeblock-short\n {% codeblock %}\n ${1:code_snippet}\n {% endcodeblock %}\n\nsnippet codeblock-full\n {% codeblock ${1:title} lang:${2:language} ${3:URL} ${4:link_text} %}\n ${5:code_snippet}\n {% endcodeblock %}\n\nsnippet gist-full\n {% gist ${1:gist_id} ${2:filename} %}\n\nsnippet gist-short\n {% gist ${1:gist_id} %}\n\nsnippet img\n {% img ${1:class} ${2:URL} ${3:width} ${4:height} ${5:title_text} ${6:alt_text} %}\n\nsnippet youtube\n {% youtube ${1:video_id} %}\n\n# The quote should appear only once in the text. It is inherently part of it.\n# See http://octopress.org/docs/plugins/pullquote/ for more info.\n\nsnippet pullquote\n {% pullquote %}\n ${1:text} {" ${2:quote} "} ${3:text}\n {% endpullquote %}\n',t.scope="markdown"})
2 |
--------------------------------------------------------------------------------
/static/css/semantic-calendar.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 0.0.8 - Calendar
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Released under the MIT license
7 | * http://opensource.org/licenses/MIT
8 | *
9 | */.ui.calendar .ui.popup{max-width:none;padding:0;border:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui.calendar .calendar:focus{outline:0}.ui.calendar .ui.popup .ui.grid{display:block;white-space:nowrap}.ui.calendar .ui.popup .ui.grid>.column{width:auto}.ui.calendar .ui.table.minute,.ui.calendar .ui.table.month,.ui.calendar .ui.table.year{min-width:15em}.ui.calendar .ui.table.day{min-width:18em}.ui.calendar .ui.table.hour{min-width:20em}.ui.calendar .ui.table tr td,.ui.calendar .ui.table tr th{padding:.5em;white-space:nowrap}.ui.calendar .ui.table tr th{border-left:none}.ui.calendar .ui.table tr th .icon{margin:0}.ui.calendar .ui.table tr:first-child th{position:relative;padding-left:0;padding-right:0}.ui.calendar .ui.table.day tr:first-child th{border:none}.ui.calendar .ui.table.day tr:nth-child(2) th{padding-top:.2em;padding-bottom:.3em}.ui.calendar .ui.table tr td{padding-left:.1em;padding-right:.1em}.ui.calendar .ui.table tr .link{cursor:pointer}.ui.calendar .ui.table tr .prev.link{width:14.28571429%;position:absolute;left:0}.ui.calendar .ui.table tr .next.link{width:14.28571429%;position:absolute;right:0}.ui.calendar .ui.table tr .disabled{pointer-events:none;color:rgba(40,40,40,.3)}.ui.calendar .ui.table tr td.today{font-weight:700}.ui.calendar .ui.table tr td.range{background:rgba(0,0,0,.05);color:rgba(0,0,0,.95);box-shadow:none}.ui.calendar .ui.table.inverted tr td.range{background:rgba(255,255,255,.08);color:#fff;box-shadow:none}.ui.calendar .calendar.active .ui.table tbody tr td.focus,.ui.calendar .calendar.active .ui.table.inverted tbody tr td.focus,.ui.calendar .calendar:focus .ui.table tbody tr td.focus,.ui.calendar .calendar:focus .ui.table.inverted tbody tr td.focus{box-shadow:inset 0 0 0 1px #85B7D9}
10 |
--------------------------------------------------------------------------------
/templates/reversion-compare/compare.html:
--------------------------------------------------------------------------------
1 | {% extends "admin/base_site.html" %}
2 | {% load i18n %}
3 |
4 | {% block extrastyle %}{{ block.super }}
5 |
15 | {% endblock %}
16 |
17 | {% block breadcrumbs %}
18 |
26 | {% endblock %}
27 |
28 |
29 | {% block content %}
30 |
31 |
32 | {% block object-tools %}
33 |
38 | {% endblock %}
39 |
40 |
41 | {% blocktrans with date1=version1.revision.date_created|date:_("DATETIME_FORMAT") date2=version2.revision.date_created|date:_("DATETIME_FORMAT") %}
42 | Compare {{ date1 }} with {{ date2 }} :
43 | {% endblocktrans %}
44 |
45 | ‹
{% trans "Go back to history list" %}
46 |
47 | {% include "reversion-compare/compare_partial.html" %}
48 |
49 | ‹
{% trans "Go back to history list" %}
50 |
51 | {% endblock %}
52 |
--------------------------------------------------------------------------------
/app_faq/admin/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.contrib import admin
5 |
6 | from app_faq.models.answer import Answer, AnswerSuggestedEdits
7 | from app_faq.models.bounty import (Bounty, BountyAward)
8 | from app_faq.models.comment import Comment
9 | from app_faq.models.favorite import Favorite
10 | from app_faq.models.flag import Flag
11 | from app_faq.models.help import Help
12 | from app_faq.models.message import Message
13 | from app_faq.models.question import Question, QuestionSuggestedEdits
14 | from app_faq.models.tag import Tag
15 |
16 |
17 | from app_faq.admin.answer import AnswerAdmin, AnswerSuggestedEditsAdmin
18 | from app_faq.admin.bounty import (BountyAdmin, BountyAwardAdmin)
19 | from app_faq.admin.comment import CommentAdmin
20 | from app_faq.admin.favorite import FavoriteAdmin
21 | from app_faq.admin.flag import FlagAdmin
22 | from app_faq.admin.help import HelpAdmin
23 | from app_faq.admin.message import MessageAdmin
24 | from app_faq.admin.tag import TagAdmin
25 | from app_faq.admin.question import QuestionAdmin, QuestionSuggestedEditsAdmin
26 |
27 | admin.site.register(Answer, AnswerAdmin)
28 | admin.site.register(AnswerSuggestedEdits, AnswerSuggestedEditsAdmin)
29 | admin.site.register(Bounty, BountyAdmin)
30 | admin.site.register(BountyAward, BountyAwardAdmin)
31 | admin.site.register(Comment, CommentAdmin)
32 | admin.site.register(Favorite, FavoriteAdmin)
33 | admin.site.register(Flag, FlagAdmin)
34 | admin.site.register(Help, HelpAdmin)
35 | admin.site.register(Message, MessageAdmin)
36 | admin.site.register(Question, QuestionAdmin)
37 | admin.site.register(QuestionSuggestedEdits, QuestionSuggestedEditsAdmin)
38 | admin.site.register(Tag, TagAdmin)
39 |
40 | """
41 | admin.site.register(Bounty)
42 | admin.site.register(BountyAward)
43 | admin.site.register(Comment)
44 | admin.site.register(Favorite)
45 | admin.site.register(Flag)
46 | admin.site.register(Help)
47 | admin.site.register(Message)
48 | admin.site.register(Question)
49 | admin.site.register(Tag)
50 | """
51 |
--------------------------------------------------------------------------------
/static/css/github/ad.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Ad
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2013 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.ad{display:block;overflow:hidden;margin:1em 0}.ui.ad:first-child,.ui.ad:last-child{margin:0}.ui.ad iframe{margin:0;padding:0;border:none;overflow:hidden}.ui.leaderboard.ad{width:728px;height:90px}.ui[class*="medium rectangle"].ad{width:300px;height:250px}.ui[class*="large rectangle"].ad{width:336px;height:280px}.ui[class*="half page"].ad{width:300px;height:600px}.ui.square.ad{width:250px;height:250px}.ui[class*="small square"].ad{width:200px;height:200px}.ui[class*="small rectangle"].ad{width:180px;height:150px}.ui[class*="vertical rectangle"].ad{width:240px;height:400px}.ui.button.ad{width:120px;height:90px}.ui[class*="square button"].ad{width:125px;height:125px}.ui[class*="small button"].ad{width:120px;height:60px}.ui.skyscraper.ad{width:120px;height:600px}.ui[class*="wide skyscraper"].ad{width:160px}.ui.banner.ad{width:468px;height:60px}.ui[class*="vertical banner"].ad{width:120px;height:240px}.ui[class*="top banner"].ad{width:930px;height:180px}.ui[class*="half banner"].ad{width:234px;height:60px}.ui[class*="large leaderboard"].ad{width:970px;height:90px}.ui.billboard.ad{width:970px;height:250px}.ui.panorama.ad{width:980px;height:120px}.ui.netboard.ad{width:580px;height:400px}.ui[class*="large mobile banner"].ad{width:320px;height:100px}.ui[class*="mobile leaderboard"].ad{width:320px;height:50px}.ui.mobile.ad{display:none}@media only screen and (max-width:767px){.ui.mobile.ad{display:block}}.ui.centered.ad{margin-left:auto;margin-right:auto}.ui.test.ad{position:relative;background:#545454}.ui.test.ad:after{position:absolute;top:50%;left:50%;width:100%;text-align:center;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);content:'Ad';color:#FFF;font-size:1em;font-weight:700}.ui.mobile.test.ad:after{font-size:.85714286em}.ui.test.ad[data-text]:after{content:attr(data-text)}
--------------------------------------------------------------------------------
/templates/socialaccount/signup.html:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Signup" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 |
{% trans "Sign Up" %}
8 |
9 |
10 | {% blocktrans with provider_name=account.get_provider.name site_name=site.name %}
11 | You are about to use your {{provider_name}} account to login to {{site_name}}. As a final step, please complete the following form:
12 | {% endblocktrans %}
13 |
14 |
15 |
51 |
52 | {% endblock %}
53 |
--------------------------------------------------------------------------------
/static/plugins/js/theme-github.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/theme/github",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-github",t.cssText='.ace-github .ace_gutter {background: #e8e8e8;color: #AAA;}.ace-github {background: #fff;color: #000;}.ace-github .ace_keyword {font-weight: bold;}.ace-github .ace_string {color: #D14;}.ace-github .ace_variable.ace_class {color: teal;}.ace-github .ace_constant.ace_numeric {color: #099;}.ace-github .ace_constant.ace_buildin {color: #0086B3;}.ace-github .ace_support.ace_function {color: #0086B3;}.ace-github .ace_comment {color: #998;font-style: italic;}.ace-github .ace_variable.ace_language {color: #0086B3;}.ace-github .ace_paren {font-weight: bold;}.ace-github .ace_boolean {font-weight: bold;}.ace-github .ace_string.ace_regexp {color: #009926;font-weight: normal;}.ace-github .ace_variable.ace_instance {color: teal;}.ace-github .ace_constant.ace_language {font-weight: bold;}.ace-github .ace_cursor {color: black;}.ace-github.ace_focus .ace_marker-layer .ace_active-line {background: rgb(255, 255, 204);}.ace-github .ace_marker-layer .ace_active-line {background: rgb(245, 245, 245);}.ace-github .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-github.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-github.ace_nobold .ace_line > span {font-weight: normal !important;}.ace-github .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-github .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-github .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-github .ace_gutter-active-line {background-color : rgba(0, 0, 0, 0.07);}.ace-github .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-github .ace_invisible {color: #BFBFBF}.ace-github .ace_print-margin {/*width: 1px;background: #e8e8e8;*/}.ace-github .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
2 |
--------------------------------------------------------------------------------
/static/css/github/reset.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Reset
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */*,:after,:before{box-sizing:inherit}html{box-sizing:border-box;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}input[type=text],input[type=email],input[type=search],input[type=password]{-webkit-appearance:none;-moz-appearance:none}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,optgroup,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre,textarea{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
--------------------------------------------------------------------------------
/static/plugins/js/resizable.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * resizable 1.0.1
3 | * https://github.com/tannernetwork/resizable
4 | *
5 | * Copyright 2015-2017 Tanner (http://tanner.zone)
6 | * Released under the MIT license
7 | */
8 | !function(a){a.fn.resizable=function(b){var c=a.extend({direction:["top","right","bottom","left"]},b),d=null;return this.each(function(){var b=this,e=a(this),f=!1,g={},h={top:!1,right:!1,bottom:!1,left:!1},i={};if(e.addClass("resizable"),c.direction instanceof Array)for(var j=c.direction.length-1;j>=0;j--)switch(c.direction[j]){case"top":case"t":h.top=!0;break;case"right":case"r":h.right=!0;break;case"bottom":case"b":h.bottom=!0;break;case"left":case"l":h.left=!0}else if("string"==typeof c.direction)switch(c.direction){case"vertical":case"v":h.top=!0,h.bottom=!0;break;case"horizontal":case"h":h.right=!0,h.left=!0;break;case"top":case"t":h.top=!0;break;case"right":case"r":h.right=!0;break;case"bottom":case"b":h.bottom=!0;break;case"left":case"l":h.left=!0}h.top&&(i.top=a("
").addClass("resizable-handle resizable-t").appendTo(e)),h.right&&(i.right=a("
").addClass("resizable-handle resizable-r").appendTo(e)),h.bottom&&(i.bottom=a("
").addClass("resizable-handle resizable-b").appendTo(e)),h.left&&(i.left=a("
").addClass("resizable-handle resizable-l").appendTo(e)),a(this).children(".resizable-l, .resizable-r, .resizable-t, .resizable-b").mousedown(function(h){d=b;var i;switch(!0){case a(this).hasClass("resizable-l"):i="l";break;case a(this).hasClass("resizable-r"):i="r";break;case a(this).hasClass("resizable-t"):i="t";break;case a(this).hasClass("resizable-b"):i="b"}f=!0,g={x:h.clientX,y:h.clientY,height:e.height(),width:e.width(),direction:i},a("html").addClass("resizable-resizing resizable-resizing-"+g.direction),d==b&&"function"==typeof c.start&&c.start.apply(b)}),a(window).mousemove(function(a){if(f){var h=a.clientX-g.x,i=a.clientY-g.y;switch(g.direction){case"r":e.width(g.width+h);break;case"l":e.width(g.width-h);break;case"b":e.height(g.height+i);break;case"t":e.height(g.height-i)}d==b&&"function"==typeof c.resize&&c.resize.apply(b)}}).mouseup(function(e){f=!1,a("html").removeClass("resizable-resizing resizable-resizing-"+g.direction),d==b&&"function"==typeof c.stop&&c.stop.apply(b),_current=null})})}}(jQuery);
9 |
--------------------------------------------------------------------------------
/templates/account/password_reset.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n account %}
3 | {% block title %}{% trans "Password Reset" %} :: {{ block.super }}{% endblock %}
4 | {% block robot %} {% endblock %}
5 | {% block canonical %}{% url 'account_reset_password' %}{% endblock %}
6 |
7 | {% block content %}
8 |
9 |
10 |
46 |
47 | {% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}
48 |
49 |
50 | {% endblock %}
51 |
52 | {% block js %}
53 |
54 | {% endblock %}
55 |
--------------------------------------------------------------------------------
/templates/base.html:
--------------------------------------------------------------------------------
1 | {% load staticfiles %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {% block robot %}
11 |
12 | {% endblock %}
13 |
14 |
15 |
16 |
17 | {% block title %}Django F.A.Q{% endblock %}
18 |
19 |
20 | {% block seo %}
21 |
22 |
23 |
24 | {% endblock %}
25 |
26 | {% block core_css %}
27 |
28 |
29 | {% endblock %}
30 |
31 |
32 |
33 | {% block css %}{% endblock %}
34 |
35 |
36 |
37 |
38 |
39 |
40 | {% include "includes/navs.html" %}
41 | {% include "includes/messages.html" %}
42 |
43 |
44 | {% block content %}{% endblock %}
45 |
46 |
47 | {% block footer %}
48 | {% include "includes/footer.html" %}
49 | {% endblock %}
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | {% block js %}{% endblock %}
58 |
59 |
60 |
--------------------------------------------------------------------------------
/templates/account/password_set.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Set Password" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 | {% include "includes/profile_menus_top.html" %}
8 |
9 |
10 | {% include "includes/profile_menus_left.html" %}
11 |
12 |
49 |
50 |
51 | {% endblock %}
52 |
53 | {% block js %}
54 |
58 | {% endblock %}
59 |
--------------------------------------------------------------------------------
/static/css/github/shape.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Shape
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.shape{position:relative;vertical-align:top;display:inline-block;-webkit-perspective:2000px;perspective:2000px;-webkit-transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out}.ui.shape .sides{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.ui.shape .side{opacity:1;width:100%;margin:0!important;-webkit-backface-visibility:hidden;backface-visibility:hidden;display:none}.ui.shape .side *{-webkit-backface-visibility:visible!important;backface-visibility:visible!important}.ui.cube.shape .side{min-width:15em;height:15em;padding:2em;background-color:#E6E6E6;color:rgba(0,0,0,.87);box-shadow:0 0 2px rgba(0,0,0,.3)}.ui.cube.shape .side>.content{width:100%;height:100%;display:table;text-align:center;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ui.cube.shape .side>.content>div{display:table-cell;vertical-align:middle;font-size:2em}.ui.text.shape.animating .sides{position:static}.ui.text.shape .side{white-space:nowrap}.ui.text.shape .side>*{white-space:normal}.ui.loading.shape{position:absolute;top:-9999px;left:-9999px}.ui.shape .animating.side{position:absolute;top:0;left:0;display:block;z-index:100}.ui.shape .hidden.side{opacity:.6}.ui.shape.animating .sides{position:absolute;-webkit-transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out}.ui.shape.animating .side{-webkit-transition:opacity .6s ease-in-out;transition:opacity .6s ease-in-out}.ui.shape .active.side{display:block}
--------------------------------------------------------------------------------
/app_faq/models/bounty.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.utils import timezone
6 | from django.contrib.auth.models import User
7 | from django.utils.encoding import python_2_unicode_compatible
8 | from django.utils.translation import ugettext_lazy as _
9 |
10 | from app_faq.models.answer import Answer
11 | from app_faq.models.question import Question
12 | from app_faq.models.time import TimeStampedModel
13 |
14 |
15 | class Bounty(models.Model):
16 | """
17 | user create a bounty for the question
18 | """
19 | user = models.ForeignKey(
20 | User, related_name='bounty_user')
21 |
22 | question = models.ForeignKey(
23 | Question, related_name='bounty_question')
24 |
25 | price = models.PositiveIntegerField(_('Price'))
26 |
27 | is_active = models.BooleanField(
28 | _('is active bounty?'), default=True)
29 |
30 | start_date = models.DateTimeField(auto_now_add=True)
31 |
32 | end_date = models.DateTimeField()
33 |
34 | def save(self, *args, **kwargs):
35 | """
36 | setup `self.end_date` of bounty for 7 days.
37 | so the bounty would `is_active=False` after 7 days creation.
38 | """
39 | self.end_date = self.start_date + timezone.timedelta(days=7)
40 |
41 | # if timezone.now().date() == self.end_date.date():
42 | # self.is_active = False
43 |
44 | super(Bounty, self).save(*args, **kwargs)
45 |
46 | def __str__(self):
47 | return _('%(user)s bounted a question %(question)s with price %(price)s') % {
48 | 'user': self.user, 'question': self.question, 'price': self.price}
49 |
50 | class Meta:
51 | verbose_name_plural = _('bounties')
52 | ordering = ['-start_date']
53 |
54 |
55 | class BountyAward(TimeStampedModel):
56 | """
57 | answer to get a bounty from the bounty.
58 | """
59 | bounty = models.ForeignKey(
60 | Bounty, related_name='bounty_award')
61 |
62 | answer = models.ForeignKey(
63 | Answer, related_name='bounty_award_for_answer')
64 |
65 | price = models.PositiveIntegerField(_('Price'))
66 |
67 | def __str__(self):
68 | return _('%(receiver)s awarded a bounty +%(price)s from %(sender)s') % {
69 | 'receiver': self.answer.author, 'price': self.price, 'sender': self.bounty.user}
70 |
71 | class Meta:
72 | verbose_name_plural = _('bounty awards')
73 | ordering = ['-created']
74 |
--------------------------------------------------------------------------------
/static/css/github/dimmer.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Dimmer
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.dimmable{position:relative}.ui.dimmer{display:none;position:absolute;top:0!important;left:0!important;width:100%;height:100%;text-align:center;vertical-align:middle;background-color:rgba(0,0,0,.85);opacity:0;line-height:1;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-transition:background-color .5s linear;transition:background-color .5s linear;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:opacity;z-index:1000}.ui.dimmer>.content{width:100%;height:100%;display:table;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ui.dimmer>.content>*{display:table-cell;vertical-align:middle;color:#FFF}.ui.segment>.ui.dimmer{border-radius:inherit!important}.animating.dimmable:not(body),.dimmed.dimmable:not(body){overflow:hidden}.dimmed.dimmable>.ui.animating.dimmer,.dimmed.dimmable>.ui.visible.dimmer,.ui.active.dimmer{display:block;opacity:1}.ui.disabled.dimmer{width:0!important;height:0!important}.ui.page.dimmer{position:fixed;-webkit-transform-style:'';transform-style:'';-webkit-perspective:2000px;perspective:2000px;-webkit-transform-origin:center center;transform-origin:center center}body.animating.in.dimmable,body.dimmed.dimmable{overflow:hidden}body.dimmable>.dimmer{position:fixed}.blurring.dimmable>:not(.dimmer){-webkit-filter:blur(0) grayscale(0);filter:blur(0) grayscale(0);-webkit-transition:.8s filter ease;transition:.8s filter ease}.blurring.dimmed.dimmable>:not(.dimmer){-webkit-filter:blur(5px) grayscale(.7);filter:blur(5px) grayscale(.7)}.blurring.dimmable>.dimmer{background-color:rgba(0,0,0,.6)}.blurring.dimmable>.inverted.dimmer{background-color:rgba(255,255,255,.6)}.ui.dimmer>.top.aligned.content>*{vertical-align:top}.ui.dimmer>.bottom.aligned.content>*{vertical-align:bottom}.ui.inverted.dimmer{background-color:rgba(255,255,255,.85)}.ui.inverted.dimmer>.content>*{color:#FFF}.ui.simple.dimmer{display:block;overflow:hidden;opacity:1;width:0;height:0%;z-index:-100;background-color:rgba(0,0,0,0)}.dimmed.dimmable>.ui.simple.dimmer{overflow:visible;opacity:1;width:100%;height:100%;background-color:rgba(0,0,0,.85);z-index:1}.ui.simple.inverted.dimmer{background-color:rgba(255,255,255,0)}.dimmed.dimmable>.ui.simple.inverted.dimmer{background-color:rgba(255,255,255,.85)}
--------------------------------------------------------------------------------
/templates/reversion-compare/action_list_partial.html:
--------------------------------------------------------------------------------
1 | {% load i18n l10n %}
2 | {% if compare_view %}{% endif %}
52 |
--------------------------------------------------------------------------------
/app_faq/utils/revision.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | import difflib
5 |
6 | from django.utils.html import escape
7 | from django.utils.safestring import mark_safe
8 | from django.utils.encoding import force_text
9 |
10 | try:
11 | # http://code.google.com/p/google-diff-match-patch/
12 | from diff_match_patch import diff_match_patch
13 | except ImportError:
14 | dmp = None
15 | else:
16 | dmp = diff_match_patch()
17 |
18 |
19 | def highlight_diff(diff_text):
20 | """
21 | Simple highlight a diff text in the way pygments do it ;)
22 | """
23 | html = ['']
24 | for line in diff_text.splitlines():
25 | line = escape(line)
26 | if line.startswith("+"):
27 | line = '%s ' % line
28 | elif line.startswith("-"):
29 | line = '%s' % line
30 | html.append(line)
31 | html.append(" ")
32 | html = "\n".join(html)
33 | return html
34 |
35 |
36 | SEMANTIC = 1
37 | EFFICIENCY = 2
38 | LINE_COUNT_4_UNIFIED_DIFF = 4
39 |
40 |
41 | def html_diff_custom(value1, value2, cleanup=SEMANTIC):
42 | """
43 | Generates a diff used google-diff-match-patch is exist or ndiff as fallback
44 |
45 | The cleanup parameter can be SEMANTIC, EFFICIENCY or None to clean up the diff
46 | for greater human readibility.
47 | """
48 | value1 = force_text(value1)
49 | value2 = force_text(value2)
50 | if dmp is not None:
51 | # Generate the diff with google-diff-match-patch
52 | diff = dmp.diff_main(value1, value2)
53 | if cleanup == SEMANTIC:
54 | dmp.diff_cleanupSemantic(diff)
55 | elif cleanup == EFFICIENCY:
56 | dmp.diff_cleanupEfficiency(diff)
57 | elif cleanup is not None:
58 | raise ValueError("cleanup parameter should be one of SEMANTIC, EFFICIENCY or None.")
59 | html = dmp.diff_prettyHtml(diff)
60 | html = html.replace("¶ ", "") # IMHO mark paragraphs are needlessly
61 | else:
62 | # fallback: use built-in difflib
63 | value1 = value1.splitlines()
64 | value2 = value2.splitlines()
65 |
66 | if len(value1) > LINE_COUNT_4_UNIFIED_DIFF or len(value2) > LINE_COUNT_4_UNIFIED_DIFF:
67 | diff = difflib.unified_diff(value1, value2, n=2)
68 | else:
69 | diff = difflib.ndiff(value1, value2)
70 |
71 | diff_text = "\n".join(diff)
72 | html = highlight_diff(diff_text)
73 |
74 | html = mark_safe(html)
75 | return html
76 |
--------------------------------------------------------------------------------
/app_faq/views/tag.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.conf import settings
5 | from django.views.generic import (ListView, DetailView, TemplateView)
6 | from django.db.models.functions import Lower as LowerCase
7 | from django.db.models import (Q, Count)
8 |
9 | from app_faq.utils.json import JSONResponseMixin
10 | from app_faq.utils.paginator import GenericPaginator
11 | from app_faq.models.tag import Tag
12 |
13 |
14 | class TagListView(ListView):
15 | model = Tag
16 | context_object_name = 'tags'
17 | paginate_by = settings.TAGS_PER_PAGE
18 | template_name = 'app_faq/tags.html'
19 |
20 | def get_queryset(self):
21 | order = self.request.GET.get('order', 'popular')
22 | tags = self.model.objects.order_by('-created')
23 | if order == 'popular':
24 | tags = self.model.objects.annotate(
25 | total=Count('question_tags')).order_by('-total')
26 | elif order == 'name':
27 | tags = self.model.objects.order_by(LowerCase('title').asc())
28 | elif order == 'new':
29 | tags = tags
30 | return tags
31 |
32 | def page_range(self):
33 | return GenericPaginator(
34 | self.get_queryset(),
35 | self.paginate_by,
36 | self.request.GET.get('page')
37 | ).get_page_range()
38 |
39 | def get_context_data(self, **kwargs):
40 | context = super(TagListView, self).get_context_data(**kwargs)
41 | context['page_range'] = self.page_range()
42 | return context
43 |
44 |
45 | class TagSearchOffset(ListView):
46 | model = Tag
47 | context_object_name = 'tags'
48 | paginate_by = settings.TAGS_PER_PAGE
49 | template_name = 'app_faq/tags_search_offset.html'
50 |
51 | def get_queryset(self):
52 | query = self.request.GET.get('q')
53 | return self.model.objects.filter(Q(title__startswith=query))
54 |
55 |
56 | class TagSearchJSON(JSONResponseMixin, TemplateView):
57 | model = Tag
58 |
59 | def get_queryset(self, query):
60 | return list(self.model.objects.filter(
61 | Q(title__startswith=query)).values('title', 'slug', 'id'))
62 |
63 | def get(self, request, *args, **kwargs):
64 | context = {'success': False, 'results': []}
65 | query = request.GET.get('q')
66 | if query is not None and query.strip() != '':
67 | context.update({
68 | 'success': True,
69 | 'results': self.get_queryset(query)
70 | })
71 | return self.render_to_json_response(context)
72 |
--------------------------------------------------------------------------------
/templates/reversion-compare/question/action_list_partial.html:
--------------------------------------------------------------------------------
1 | {% load i18n l10n %}
2 | {% load common_tags %}
3 | {% if compare_view %}{% endif %}
61 |
--------------------------------------------------------------------------------
/static/css/github/comment.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Comment
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.comments{margin:1.5em 0;max-width:650px}.ui.comments:first-child{margin-top:0}.ui.comments:last-child{margin-bottom:0}.ui.comments .comment{position:relative;background:0 0;margin:.5em 0 0;padding:.5em 0 0;border:none;border-top:none;line-height:1.2}.ui.comments .comment:first-child{margin-top:0;padding-top:0}.ui.comments .comment .comments{margin:0 0 .5em .5em;padding:1em 0 1em 1em}.ui.comments .comment .comments:before{position:absolute;top:0;left:0}.ui.comments .comment .comments .comment{border:none;border-top:none;background:0 0}.ui.comments .comment .avatar{display:block;width:2.5em;height:auto;float:left;margin:.2em 0 0}.ui.comments .comment .avatar img,.ui.comments .comment img.avatar{display:block;margin:0 auto;width:100%;height:100%;border-radius:.25rem}.ui.comments .comment>.content{display:block}.ui.comments .comment>.avatar~.content{margin-left:3.5em}.ui.comments .comment .author{font-size:1em;color:rgba(0,0,0,.87);font-weight:700}.ui.comments .comment a.author{cursor:pointer}.ui.comments .comment a.author:hover{color:#1e70bf}.ui.comments .comment .metadata{display:inline-block;margin-left:.5em;color:rgba(0,0,0,.4);font-size:.875em}.ui.comments .comment .metadata>*{display:inline-block;margin:0 .5em 0 0}.ui.comments .comment .metadata>:last-child{margin-right:0}.ui.comments .comment .text{margin:.25em 0 .5em;font-size:1em;word-wrap:break-word;color:rgba(0,0,0,.87);line-height:1.3}.ui.comments .comment .actions{font-size:.875em}.ui.comments .comment .actions a{cursor:pointer;display:inline-block;margin:0 .75em 0 0;color:rgba(0,0,0,.4)}.ui.comments .comment .actions a:last-child{margin-right:0}.ui.comments .comment .actions a.active,.ui.comments .comment .actions a:hover{color:rgba(0,0,0,.8)}.ui.comments>.reply.form{margin-top:1em}.ui.comments .comment .reply.form{width:100%;margin-top:1em}.ui.comments .reply.form textarea{font-size:1em;height:12em}.ui.collapsed.comments,.ui.comments .collapsed.comment,.ui.comments .collapsed.comments{display:none}.ui.threaded.comments .comment .comments{margin:-1.5em 0 -1em 1.25em;padding:3em 0 2em 2.25em;box-shadow:-1px 0 0 rgba(34,36,38,.15)}.ui.minimal.comments .comment .actions{opacity:0;position:absolute;top:0;right:0;left:auto;-webkit-transition:opacity .2s ease;transition:opacity .2s ease;-webkit-transition-delay:.1s;transition-delay:.1s}.ui.minimal.comments .comment>.content:hover>.actions{opacity:1}.ui.small.comments{font-size:.9em}.ui.comments{font-size:1em}.ui.large.comments{font-size:1.1em}.ui.huge.comments{font-size:1.2em}
--------------------------------------------------------------------------------
/templates/socialaccount/connections.html:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Account Connections" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 | {% include "includes/profile_menus_top.html" %}
8 |
9 |
10 | {% include "includes/profile_menus_left.html" %}
11 |
12 |
13 |
14 |
15 |
16 | {% if form.accounts %}
17 |
18 | {% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}
19 |
20 |
43 | {% else %}
44 |
45 | {% trans 'You currently have no social network accounts connected to this account.' %}
46 |
47 | {% endif %}
48 |
49 |
50 |
51 |
52 | {% include "socialaccount/snippets/provider_list.html" with process="connect" %}
53 |
54 |
55 | {% include "socialaccount/snippets/login_extra.html" %}
56 |
57 |
58 |
59 | {% endblock %}
60 |
61 | {% block js %}
62 |
63 | {% endblock %}
64 |
--------------------------------------------------------------------------------
/templates/account/password_change.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Change Password" %} :: {{ block.super }}{% endblock %}
4 |
5 | {% block content %}
6 |
7 | {% include "includes/profile_menus_top.html" %}
8 |
9 |
10 | {% include "includes/profile_menus_left.html" %}
11 |
12 |
68 |
69 |
70 | {% endblock %}
71 |
72 | {% block js %}
73 |
74 | {% endblock %}
75 |
--------------------------------------------------------------------------------
/app_faq/views/comment.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.contrib import messages
5 | from django.core.urlresolvers import reverse
6 | from django.shortcuts import get_object_or_404
7 | from django.utils.translation import ugettext_lazy as _
8 | from django.contrib.auth.mixins import LoginRequiredMixin
9 | from django.contrib.contenttypes.models import ContentType
10 | from django.views.generic import (ListView, DetailView, FormView)
11 | from django.http import JsonResponse
12 |
13 | from app_faq.models.answer import Answer
14 | from app_faq.models.question import Question
15 | from app_faq.models.comment import Comment
16 | from app_faq.forms.comment import CommentForm
17 |
18 |
19 | class CommentFormView(LoginRequiredMixin, FormView):
20 | template_name = 'app_faq/comment_create.html'
21 | form_class = CommentForm
22 | model_target = None
23 |
24 | def get_object(self):
25 | return get_object_or_404(self.model_target, pk=self.kwargs['pk'])
26 |
27 | def form_valid(self, form):
28 | if self.model_target is None:
29 | return JsonResponse({'status': False})
30 |
31 | model_name = self.model_target._meta.model_name
32 | content_type = ContentType.objects.get(model=model_name)
33 |
34 | initial = form.save(commit=False)
35 | initial.author = self.request.user
36 | initial.content_type = content_type
37 | initial.object_id = self.get_object().pk
38 | initial.save()
39 | form.save()
40 |
41 | context = {
42 | 'status': True,
43 | 'author': self.request.user.username,
44 | 'comment': initial.comment,
45 | 'created': initial.created,
46 | 'edited': initial.edited,
47 | 'id': initial.id
48 | }
49 | # id="question-comment-{{ question.id }}"
50 | # id="answer-comment-{{ question.id }}"
51 | return JsonResponse(context)
52 |
53 |
54 | class CommentQuestionFormView(CommentFormView):
55 | model_target = Question
56 |
57 |
58 | class CommentAnswerFormView(CommentFormView):
59 | model_target = Answer
60 |
61 |
62 | class CommentsOffsetView(DetailView):
63 | template_name = 'app_faq/comments_offset.html'
64 |
65 | def get_object(self):
66 | model_instance = None
67 | model_name = self.kwargs['model_name']
68 | object_id = self.kwargs['object_id']
69 | if model_name == 'question':
70 | model_instance = get_object_or_404(Question, pk=object_id)
71 | elif model_name == 'answer':
72 | model_instance = get_object_or_404(Answer, pk=object_id)
73 | return model_instance
74 |
75 | def get_comments_offset(self):
76 | if self.get_object():
77 | return self.get_object().get_comments_offset()
78 | return None
79 |
80 | def get_context_data(self, **kwargs):
81 | context = super(CommentsOffsetView, self).get_context_data(**kwargs)
82 | context['comments_offset'] = self.get_comments_offset()
83 | context['object'] = self.get_object()
84 | return context
85 |
--------------------------------------------------------------------------------
/app_user/views.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.conf import settings
5 | from django.contrib import messages
6 | from django.core.urlresolvers import reverse
7 | from django.shortcuts import get_object_or_404
8 | from django.utils.translation import ugettext_lazy as _
9 | from django.contrib.auth.mixins import LoginRequiredMixin
10 | from django.views.generic import (ListView, DetailView, FormView, UpdateView)
11 | from django.views.generic.base import RedirectView
12 | from django.contrib.auth.models import User
13 |
14 | from app_faq.utils.paginator import GenericPaginator
15 | from app_user.models import Profile
16 | from app_user.forms import ProfileForm
17 |
18 |
19 | class UserListView(ListView):
20 | model = User
21 | context_object_name = 'users'
22 | paginate_by = settings.USERS_PER_PAGE
23 | template_name = 'app_user/users.html'
24 |
25 | def get_queryset(self):
26 | return self.model.objects.exclude(
27 | is_active=False).order_by('-date_joined')
28 |
29 | def page_range(self):
30 | return GenericPaginator(
31 | self.get_queryset(),
32 | self.paginate_by,
33 | self.request.GET.get('page')
34 | ).get_page_range()
35 |
36 | def get_context_data(self, **kwargs):
37 | context = super(UserListView, self).get_context_data(**kwargs)
38 | context['page_range'] = self.page_range()
39 | return context
40 |
41 |
42 | class UserProfileRedirectView(RedirectView):
43 |
44 | permanent = False
45 | query_string = True
46 |
47 | def get_redirect_url(self, *args, **kwargs):
48 | user = get_object_or_404(User, pk=kwargs['pk'])
49 | return reverse('user_profile', kwargs={'pk': user.pk,
50 | 'username': user.username})
51 |
52 |
53 | class UserProfile(DetailView):
54 | model = Profile
55 | context_object_name = 'profile'
56 | template_name = 'app_user/user_profile.html'
57 |
58 | def get_object(self):
59 | user = get_object_or_404(User, pk=self.kwargs['pk'],
60 | username=self.kwargs['username'])
61 | profile, truefalse = Profile.objects.get_or_create(user=user)
62 | return profile
63 |
64 |
65 | class UserProfileEdit(LoginRequiredMixin, UpdateView):
66 | form_class = ProfileForm
67 | template_name = 'app_user/user_profile_edit.html'
68 |
69 | def get_success_url(self):
70 | return reverse('user_profile_edit')
71 |
72 | def get_object(self, queryset=None):
73 | profile, truefalse = Profile.objects.get_or_create(user=self.request.user)
74 | return profile
75 |
76 | def form_valid(self, form):
77 | instance = form.save(commit=False)
78 | instance.user = self.request.user
79 | instance.save()
80 | messages.success(self.request, _('Profile updated!'))
81 | return super(UserProfileEdit, self).form_valid(form)
82 |
83 | def get_initial(self):
84 | initial = super(UserProfileEdit, self).get_initial()
85 | for field, _cls in self.form_class.base_fields.items():
86 | value = getattr(self.get_object(), field)
87 | initial.update({field: value})
88 | return initial
89 |
--------------------------------------------------------------------------------
/static/css/github/loader.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Loader
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.loader{display:none;position:absolute;top:50%;left:50%;margin:0;text-align:center;z-index:1000;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%)}.ui.loader:before{position:absolute;content:'';top:0;left:50%;border-radius:500rem;border:.2em solid rgba(0,0,0,.1)}.ui.loader:after{position:absolute;content:'';top:0;left:50%;-webkit-animation:loader .6s linear;animation:loader .6s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;border-radius:500rem;border-color:#767676 transparent transparent;border-style:solid;border-width:.2em;box-shadow:0 0 0 1px transparent}@-webkit-keyframes loader{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loader{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.ui.loader:after,.ui.loader:before{width:2.2585em;height:2.2585em;margin:0 0 0 -1.12925em}.ui.mini.loader:after,.ui.mini.loader:before{width:1.2857em;height:1.2857em;margin:0 0 0 -.64285em}.ui.small.loader:after,.ui.small.loader:before{width:1.7142em;height:1.7142em;margin:0 0 0 -.8571em}.ui.large.loader:after,.ui.large.loader:before{width:4.5714em;height:4.5714em;margin:0 0 0 -2.2857em}.ui.dimmer .loader{display:block}.ui.dimmer .ui.loader{color:rgba(255,255,255,.9)}.ui.dimmer .ui.loader:before{border-color:rgba(255,255,255,.15)}.ui.dimmer .ui.loader:after{border-color:#FFF transparent transparent}.ui.inverted.dimmer .ui.loader{color:rgba(0,0,0,.87)}.ui.inverted.dimmer .ui.loader:before{border-color:rgba(0,0,0,.1)}.ui.inverted.dimmer .ui.loader:after{border-color:#767676 transparent transparent}.ui.text.loader{width:auto!important;height:auto!important;text-align:center;font-style:normal}.ui.indeterminate.loader:after{-webkit-animation-direction:reverse;animation-direction:reverse;-webkit-animation-duration:1.2s;animation-duration:1.2s}.ui.loader.active,.ui.loader.visible{display:block}.ui.loader.disabled,.ui.loader.hidden{display:none}.ui.inverted.dimmer .ui.mini.loader,.ui.mini.loader{width:1.2857em;height:1.2857em;font-size:.71428571em}.ui.inverted.dimmer .ui.small.loader,.ui.small.loader{width:1.7142em;height:1.7142em;font-size:.92857143em}.ui.inverted.dimmer .ui.loader,.ui.loader{width:2.2585em;height:2.2585em;font-size:1em}.ui.inverted.dimmer .ui.loader.large,.ui.loader.large{width:4.5714em;height:4.5714em;font-size:1.14285714em}.ui.mini.text.loader{min-width:1.2857em;padding-top:1.99998571em}.ui.small.text.loader{min-width:1.7142em;padding-top:2.42848571em}.ui.text.loader{min-width:2.2585em;padding-top:2.97278571em}.ui.large.text.loader{min-width:4.5714em;padding-top:5.28568571em}.ui.inverted.loader{color:rgba(255,255,255,.9)}.ui.inverted.loader:before{border-color:rgba(255,255,255,.15)}.ui.inverted.loader:after{border-top-color:#FFF}.ui.inline.loader{position:relative;vertical-align:middle;margin:0;left:0;top:0;-webkit-transform:none;transform:none}.ui.inline.loader.active,.ui.inline.loader.visible{display:inline-block}.ui.centered.inline.loader.active,.ui.centered.inline.loader.visible{display:block;margin-left:auto;margin-right:auto}
--------------------------------------------------------------------------------
/app_faq/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from updown.views import AddRatingFromModel
5 |
6 | from django.conf.urls import url
7 | from app_faq.views.question import *
8 | from app_faq.views.comment import *
9 | from app_faq.views.answer import *
10 | from app_faq.views.tag import *
11 |
12 | urlpatterns = [
13 | # question urls
14 | url(
15 | r'^$',
16 | QuestionHomePage.as_view(),
17 | name='question_homepage'
18 | ),
19 | url(
20 | r'^questions/tagged/(?P[\w-]+)/$',
21 | QuestionsTagged.as_view(),
22 | name='questions_tagged'
23 | ),
24 | url(
25 | r'^question/(?P[\d-]+)/$',
26 | QuestionRedirectView.as_view(),
27 | name='question_redirect'
28 | ),
29 | url(
30 | r'^question/(?P[\d-]+)/(?P[\w\-]+)/$',
31 | QuestionDetail.as_view(),
32 | name='question_detail'
33 | ),
34 | url(
35 | r'^question/create/$',
36 | QuestionCreate.as_view(),
37 | name='question_create'
38 | ),
39 | # url(
40 | # r'^question/edit/(?P[\d-]+)/$',
41 | # QuestionEdit.as_view(),
42 | # name='question_edit'
43 | # ),
44 | url(
45 | r'^question/suggestion/edit/(?P[\d-]+)/$',
46 | QuestionSuggestedEditsCreate.as_view(),
47 | name='question_suggested_edits_create'
48 | ),
49 | # url(
50 | # r'^question/reversions/(?P[\d-]+)/$',
51 | # QuestionReversions.as_view(),
52 | # name='question_reversions'
53 | # ),
54 | url(
55 | r'^question/reversions/(?P[\d-]+)/$',
56 | QuestionSuggestedEditsReversions.as_view(),
57 | name='question_reversions'
58 | ),
59 |
60 | # answer urls
61 | url(
62 | r'^answer/(?P[\d-]+)/create/$',
63 | AnswerFormView.as_view(),
64 | name='answer_create'
65 | ),
66 |
67 | # comment urls
68 | url(
69 | r'^comments/create/question/(?P[\d-]+)/$',
70 | CommentQuestionFormView.as_view(),
71 | name='comment_question_create'
72 | ),
73 | url(
74 | r'^comments/create/answer/(?P[\d-]+)/$',
75 | CommentAnswerFormView.as_view(),
76 | name='comment_answer_create'
77 | ),
78 | url(
79 | r'^comments/offset/(?P[\w\-]+)/(?P[\d-]+)/$',
80 | CommentsOffsetView.as_view(),
81 | name='comments_offset'
82 | ),
83 |
84 | # tag urls
85 | url(
86 | r'^tags/$',
87 | TagListView.as_view(),
88 | name='tags'
89 | ),
90 | url(
91 | r'^tags/search/offset/$',
92 | TagSearchOffset.as_view(),
93 | name='tags_search_offset'
94 | ),
95 | url(
96 | r'^tags/search/json/$',
97 | TagSearchJSON.as_view(),
98 | name='tags_search_json'
99 | ),
100 |
101 | # updown url
102 | url(
103 | r'^question/(?P\d+)/rate/(?P[\d\-]+)$',
104 | AddRatingFromModel(), {'app_label': 'app_faq', 'model': 'Question', 'field_name': 'rating'},
105 | name='question_vote_rating'
106 | ),
107 | url(
108 | r'^answer/(?P\d+)/rate/(?P[\d\-]+)$',
109 | AddRatingFromModel(), {'app_label': 'app_faq', 'model': 'Answer', 'field_name': 'rating'},
110 | name='answer_vote_rating'
111 | ),
112 | ]
113 |
--------------------------------------------------------------------------------
/static/css/github/image.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Image
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.image{position:relative;display:inline-block;vertical-align:middle;max-width:100%;background-color:transparent}img.ui.image{display:block}.ui.image img,.ui.image svg{display:block;max-width:100%;height:auto}.ui.hidden.image,.ui.hidden.images{display:none}.ui.disabled.image,.ui.disabled.images{cursor:default;opacity:.3}.ui.inline.image,.ui.inline.image img,.ui.inline.image svg{display:inline-block}.ui.top.aligned.image,.ui.top.aligned.image img,.ui.top.aligned.image svg,.ui.top.aligned.images .image{display:inline-block;vertical-align:top}.ui.middle.aligned.image,.ui.middle.aligned.image img,.ui.middle.aligned.image svg,.ui.middle.aligned.images .image{display:inline-block;vertical-align:middle}.ui.bottom.aligned.image,.ui.bottom.aligned.image img,.ui.bottom.aligned.image svg,.ui.bottom.aligned.images .image{display:inline-block;vertical-align:bottom}.ui.rounded.image,.ui.rounded.image>*,.ui.rounded.images .image,.ui.rounded.images .image>*{border-radius:.3125em}.ui.bordered.image img,.ui.bordered.image svg,.ui.bordered.images .image,.ui.bordered.images img,.ui.bordered.images svg,img.ui.bordered.image{border:1px solid rgba(0,0,0,.1)}.ui.circular.image,.ui.circular.images{overflow:hidden}.ui.circular.image,.ui.circular.image>*,.ui.circular.images .image,.ui.circular.images .image>*{border-radius:500rem}.ui.fluid.image,.ui.fluid.image img,.ui.fluid.image svg,.ui.fluid.images,.ui.fluid.images img,.ui.fluid.images svg{display:block;width:100%;height:auto}.ui.avatar.image,.ui.avatar.image img,.ui.avatar.image svg,.ui.avatar.images .image,.ui.avatar.images img,.ui.avatar.images svg{margin-right:.25em;display:inline-block;width:2em;height:2em;border-radius:500rem}.ui.spaced.image{display:inline-block!important;margin-left:.5em;margin-right:.5em}.ui[class*="left spaced"].image{margin-left:.5em;margin-right:0}.ui[class*="right spaced"].image{margin-left:0;margin-right:.5em}.ui.floated.image,.ui.floated.images{float:left;margin-right:1em;margin-bottom:1em}.ui.right.floated.image,.ui.right.floated.images{float:right;margin-right:0;margin-bottom:1em;margin-left:1em}.ui.floated.image:last-child,.ui.floated.images:last-child{margin-bottom:0}.ui.centered.image,.ui.centered.images{margin-left:auto;margin-right:auto}.ui.mini.image,.ui.mini.images .image,.ui.mini.images img,.ui.mini.images svg{width:20px;height:auto;font-size:.69230769rem}.ui.tiny.image,.ui.tiny.images .image,.ui.tiny.images img,.ui.tiny.images svg{width:80px;height:auto;font-size:.84615385rem}.ui.small.image,.ui.small.images .image,.ui.small.images img,.ui.small.images svg{width:150px;height:auto;font-size:.92307692rem}.ui.medium.image,.ui.medium.images .image,.ui.medium.images img,.ui.medium.images svg{width:300px;height:auto;font-size:1rem}.ui.large.image,.ui.large.images .image,.ui.large.images img,.ui.large.images svg{width:450px;height:auto;font-size:1.15384615rem}.ui.big.image,.ui.big.images .image,.ui.big.images img,.ui.big.images svg{width:600px;height:auto;font-size:1.38461538rem}.ui.huge.image,.ui.huge.images .image,.ui.huge.images img,.ui.huge.images svg{width:800px;height:auto;font-size:1.46153846rem}.ui.massive.image,.ui.massive.images .image,.ui.massive.images img,.ui.massive.images svg{width:960px;height:auto;font-size:1.69230769rem}.ui.images{font-size:0;margin:0 -.25rem}.ui.images .image,.ui.images img,.ui.images svg{display:inline-block;margin:0 .25rem .5rem}
--------------------------------------------------------------------------------
/static/css/github/feed.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Feed
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.feed{margin:1em 0}.ui.feed:first-child{margin-top:0}.ui.feed:last-child{margin-bottom:0}.ui.feed>.event{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;width:100%;padding:.21428571rem 0;margin:0;background:0 0;border-top:none}.ui.feed>.event:first-child{border-top:0;padding-top:0}.ui.feed>.event:last-child{padding-bottom:0}.ui.feed>.event>.label{display:block;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;width:2.5em;height:auto;-webkit-align-self:stretch;-ms-flex-item-align:stretch;align-self:stretch;text-align:left}.ui.feed>.event>.label .icon{opacity:1;font-size:1.5em;width:100%;padding:.25em;background:0 0;border:none;border-radius:none;color:rgba(0,0,0,.6)}.ui.feed>.event>.label img{width:100%;height:auto;border-radius:500rem}.ui.feed>.event>.label+.content{margin:.5em 0 .35714286em 1.14285714em}.ui.feed>.event>.content{display:block;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-align-self:stretch;-ms-flex-item-align:stretch;align-self:stretch;text-align:left;word-wrap:break-word}.ui.feed>.event:last-child>.content{padding-bottom:0}.ui.feed>.event>.content a{cursor:pointer}.ui.feed>.event>.content .date{margin:-.5rem 0 0;padding:0;font-weight:400;font-size:1em;font-style:normal;color:rgba(0,0,0,.4)}.ui.feed>.event>.content .summary{margin:0;font-size:1em;font-weight:700;color:rgba(0,0,0,.87)}.ui.feed>.event>.content .summary img{display:inline-block;width:auto;height:10em;margin:-.25em .25em 0 0;border-radius:.25em;vertical-align:middle}.ui.feed>.event>.content .user{display:inline-block;font-weight:700;margin-right:0;vertical-align:baseline}.ui.feed>.event>.content .user img{margin:-.25em .25em 0 0;width:auto;height:10em;vertical-align:middle}.ui.feed>.event>.content .summary>.date{display:inline-block;float:none;font-weight:400;font-size:.85714286em;font-style:normal;margin:0 0 0 .5em;padding:0;color:rgba(0,0,0,.4)}.ui.feed>.event>.content .extra{margin:.5em 0 0;background:0 0;padding:0;color:rgba(0,0,0,.87)}.ui.feed>.event>.content .extra.images img{display:inline-block;margin:0 .25em 0 0;width:6em}.ui.feed>.event>.content .extra.text{padding:0;border-left:none;font-size:1em;max-width:500px;line-height:1.4285em}.ui.feed>.event>.content .meta{display:inline-block;font-size:.85714286em;margin:.5em 0 0;background:0 0;border:none;border-radius:0;box-shadow:none;padding:0;color:rgba(0,0,0,.6)}.ui.feed>.event>.content .meta>*{position:relative;margin-left:.75em}.ui.feed>.event>.content .meta>:after{content:'';color:rgba(0,0,0,.2);top:0;left:-1em;opacity:1;position:absolute;vertical-align:top}.ui.feed>.event>.content .meta .like{color:'';-webkit-transition:.2s color ease;transition:.2s color ease}.ui.feed>.event>.content .meta .like:hover .icon{color:#FF2733}.ui.feed>.event>.content .meta .active.like .icon{color:#EF404A}.ui.feed>.event>.content .meta>:first-child{margin-left:0}.ui.feed>.event>.content .meta>:first-child::after{display:none}.ui.feed>.event>.content .meta a,.ui.feed>.event>.content .meta>.icon{cursor:pointer;opacity:1;color:rgba(0,0,0,.5);-webkit-transition:color .1s ease;transition:color .1s ease}.ui.feed>.event>.content .meta a:hover,.ui.feed>.event>.content .meta a:hover .icon,.ui.feed>.event>.content .meta>.icon:hover{color:rgba(0,0,0,.95)}.ui.small.feed{font-size:.92857143rem}.ui.feed{font-size:1rem}.ui.large.feed{font-size:1.14285714rem}
--------------------------------------------------------------------------------
/templates/app_user/users.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load i18n %}
3 | {% load common_tags %}
4 | {% block title %}{% trans "Users" %} :: {{ block.super }}{% endblock %}
5 |
6 | {% block content %}
7 |
8 |
9 |
29 |
30 |
31 |
32 |
48 |
49 |
50 |
51 | {% for user in users %}
52 |
53 |
54 |
{{ user }}
55 |
56 |
57 |
58 |
59 |
60 |
61 | Cambridge, United Kingdom
62 | python, python-3.x, python-2.7
63 |
64 |
78 |
79 | {% endfor %}
80 |
81 |
82 |
83 |
84 |
112 |
113 | {% endblock %}
114 |
--------------------------------------------------------------------------------
/templates/app_faq/tags.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load i18n %}
3 | {% load counter %}
4 | {% block title %}Tags :: {{ block.super }}{% endblock %}
5 |
6 | {% block content %}
7 |
8 |
9 |
30 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
75 |
76 | {% endblock %}
77 |
78 | {% block js %}
79 |
100 | {% endblock %}
101 |
--------------------------------------------------------------------------------
/static/css/github/popup.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Popup
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.popup{display:none;position:absolute;top:0;right:0;min-width:-webkit-min-content;min-width:-moz-min-content;min-width:min-content;z-index:1900;border:1px solid #DDD;line-height:1.4285em;max-width:250px;background:#FFF;padding:.53846154em .84615385em;font-weight:400;font-style:normal;color:rgba(0,0,0,.87);border-radius:.2307em;box-shadow:0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);margin:0}.ui.popup>.header{padding:0;font-family:Arial,'Helvetica Neue',Arial,Helvetica,sans-serif;font-size:1.125em;line-height:1.2;font-weight:700}.ui.popup>.header+.content{padding-top:.5em}.ui.popup:before{position:absolute;content:'';width:.75em;height:.75em;background:#FFF;-webkit-transform:rotate(45deg);transform:rotate(45deg);z-index:2;box-shadow:1px 1px 0 0 #c4c4c4}.ui.top.popup{margin:0 0 .75em}.ui.top.left.popup{-webkit-transform-origin:left bottom;transform-origin:left bottom}.ui.top.center.popup{-webkit-transform-origin:center bottom;transform-origin:center bottom}.ui.top.right.popup{-webkit-transform-origin:right bottom;transform-origin:right bottom}.ui.left.center.popup{margin:0 .75em 0 0;-webkit-transform-origin:right 50%;transform-origin:right 50%}.ui.right.center.popup{margin:0 0 0 .75em;-webkit-transform-origin:left 50%;transform-origin:left 50%}.ui.bottom.popup{margin:.75em 0 0}.ui.bottom.left.popup{-webkit-transform-origin:left top;transform-origin:left top}.ui.bottom.center.popup{-webkit-transform-origin:center top;transform-origin:center top}.ui.bottom.right.popup{-webkit-transform-origin:right top;transform-origin:right top;margin-right:0}.ui.bottom.center.popup:before{margin-left:-.325em;top:-.325em;left:50%;right:auto;bottom:auto;box-shadow:-1px -1px 0 0 #c4c4c4}.ui.bottom.left.popup{margin-left:0}.ui.bottom.left.popup:before{top:-.325em;left:1em;right:auto;bottom:auto;margin-left:0;box-shadow:-1px -1px 0 0 #c4c4c4}.ui.bottom.right.popup:before{top:-.325em;right:1em;bottom:auto;left:auto;margin-left:0;box-shadow:-1px -1px 0 0 #c4c4c4}.ui.top.center.popup:before{top:auto;right:auto;bottom:-.325em;left:50%;margin-left:-.325em}.ui.top.left.popup{margin-left:0}.ui.top.left.popup:before{bottom:-.325em;left:1em;top:auto;right:auto;margin-left:0}.ui.top.right.popup{margin-right:0}.ui.top.right.popup:before{bottom:-.325em;right:1em;top:auto;left:auto;margin-left:0}.ui.left.center.popup:before{top:50%;right:-.325em;bottom:auto;left:auto;margin-top:-.325em;box-shadow:1px -1px 0 0 #c4c4c4}.ui.right.center.popup:before{top:50%;left:-.325em;bottom:auto;right:auto;margin-top:-.325em;box-shadow:-1px 1px 0 0 #c4c4c4}.ui.bottom.popup:before,.ui.left.center.popup:before,.ui.right.center.popup:before,.ui.top.popup:before{background:#FFF}.ui.inverted.bottom.popup:before,.ui.inverted.left.center.popup:before,.ui.inverted.right.center.popup:before,.ui.inverted.top.popup:before{background:#333}.ui.popup>.ui.grid:not(.padded){width:calc(100% + 1.75rem);margin:-.7rem -.875rem}.ui.loading.popup{display:block;visibility:hidden;z-index:-1}.ui.animating.popup,.ui.visible.popup{display:block}.ui.visible.popup{-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden}.ui.basic.popup:before{display:none}.ui.wide.popup{max-width:350px}.ui[class*="very wide"].popup{max-width:550px}@media only screen and (max-width:1048px){.ui.wide.popup,.ui[class*="very wide"].popup{max-width:250px}}.ui.fluid.popup{width:100%;max-width:none}.ui.inverted.popup{background:#333;color:#FFF;border:none;box-shadow:none}.ui.inverted.popup .header{background-color:none;color:#FFF}.ui.inverted.popup:before{background-color:#333;box-shadow:none!important}.ui.flowing.popup{max-width:none}.ui.mini.popup{font-size:.69230769rem}.ui.tiny.popup{font-size:.84615385rem}.ui.small.popup{font-size:.76923077em}.ui.popup{font-size:.84615385em}.ui.large.popup{font-size:1em}.ui.huge.popup{font-size:1.46153846rem}
--------------------------------------------------------------------------------
/static/js/spfjs-main.js:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Google Inc. All rights reserved.
2 | //
3 | // Use of this source code is governed by The MIT License.
4 | // See the LICENSE file for details.
5 | (function () {
6 | 'use strict';
7 |
8 | var html = document.getElementsByTagName('html')[0];
9 | var body = document.body;
10 | var progress = document.getElementById('spfjs-progress-bar');
11 |
12 | var position = -1;
13 | var start = -1;
14 | var timer = -1;
15 |
16 | // Animation states: start time, duration, progress complete, and css class.
17 | var animation = {
18 | // Most progress waiting for response; duration is 3x expected to
19 | // accommodate slow networks and will be short-circuited by next step.
20 | REQUEST: [0, 300, '95%', 'waiting'],
21 | // Finish during short processing time.
22 | PROCESS: [100, 25, '101%', 'waiting'],
23 | // Fade it out slowly.
24 | DONE: [125, 150, '101%', 'done']
25 | };
26 |
27 | html.className = html.className.replace('no-js', '');
28 | if (!('ontouchstart' in window)) {
29 | html.className = html.className + ' no-touch';
30 | }
31 |
32 | function setProgress(anim) {
33 | clearTimeout(timer);
34 | var elapsed = (new Date()).getTime() - start;
35 | var scheduled = anim[0];
36 | var duration = anim[1];
37 | var percentage = anim[2];
38 | var classes = anim[3];
39 | var wait = scheduled - elapsed;
40 | // Since navigation can often be faster than the animation,
41 | // wait for the last scheduled step of the progress bar to complete
42 | // before finishing.
43 | if (classes == 'done' && wait > 0) {
44 | timer = setTimeout(function() {
45 | setProgress(anim);
46 | }, wait);
47 | return;
48 | }
49 | progress.className = '';
50 | var ps = progress.style;
51 | ps.transitionDuration = ps.webkitTransitionDuration = duration + 'ms';
52 | ps.width = percentage;
53 | if (classes == 'done') {
54 | // If done, set the class now to start the fade-out and wait until
55 | // the duration is over (i.e. the fade is complete) to reset the bar
56 | // to the beginning.
57 | progress.className = classes;
58 | timer = setTimeout(function() {
59 | ps.width = '0%';
60 | }, duration);
61 | } else {
62 | // If waiting, set the class after the duration is over (i.e. the
63 | // bar has finished moving) to set the class and start the pulse.
64 | timer = setTimeout(function() {
65 | progress.className = classes;
66 | }, duration);
67 | }
68 | }
69 |
70 | function clearProgress() {
71 | clearTimeout(timer);
72 | progress.className = '';
73 | var ps = progress.style;
74 | ps.transitionDuration = ps.webkitTransitionDuration = '0ms';
75 | ps.width = '0%';
76 | }
77 |
78 | function handleRequest(event) {
79 | start = (new Date()).getTime();
80 | setProgress(animation.REQUEST);
81 | }
82 |
83 | function handleProcess(event) {
84 | setProgress(animation.PROCESS);
85 | window.scroll(0,0);
86 | }
87 |
88 | function handleDone(event) {
89 | setProgress(animation.DONE);
90 | handleScroll();
91 | }
92 |
93 | function handleScriptBeforeUnload(event) {
94 | // If this script is going to be replaced with a new version,
95 | // dispose before the new one is loaded.
96 | if (event.detail.name == 'main') {
97 | dispose();
98 | }
99 | }
100 |
101 | function init() {
102 | spf.init({
103 | 'cache-unified': true
104 | });
105 | document.addEventListener('spfrequest', handleRequest);
106 | document.addEventListener('spfprocess', handleProcess);
107 | document.addEventListener('spfdone', handleDone);
108 | document.addEventListener('spfjsbeforeunload', handleScriptBeforeUnload);
109 | }
110 |
111 | function dispose() {
112 | spf.dispose();
113 | document.removeEventListener('spfprocess', handleRequest);
114 | document.removeEventListener('spfrequest', handleProcess);
115 | document.removeEventListener('spfdone', handleDone);
116 | document.removeEventListener('spfjsbeforeunload', handleScriptBeforeUnload);
117 |
118 | clearProgress();
119 | }
120 |
121 | init();
122 | })();
123 |
--------------------------------------------------------------------------------
/templates/includes/navs.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load common_tags counter %}
3 |
4 |
102 |
--------------------------------------------------------------------------------
/app_faq/templatetags/common_tags.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | import re
5 | import ast
6 | import hashlib
7 | from django import template
8 | from django.utils.module_loading import import_string
9 |
10 | try:
11 | # Python 3
12 | from urllib.parse import urlencode
13 | except ImportError:
14 | # Python 2
15 | from urllib import urlencode
16 |
17 | register = template.Library()
18 |
19 |
20 | @register.filter
21 | def splitter(value, sep='.'):
22 | """
23 | return splited list.
24 | :param `value` is value to split.
25 | :param `sep` is splitter.
26 |
27 | usage:
28 | {{ value|splitter:"/" }}
29 | """
30 | return value.split(sep)
31 |
32 |
33 | @register.filter
34 | def gravatar(email, size="75"):
35 | """
36 | return gravatar url.
37 | :param `email` is email from user.
38 | :param `size` is string size of image.
39 |
40 | usage:
41 | {{ request.user.email|gravatar:"75" }}
42 | """
43 | if email is None:
44 | email = 'fake@email.com'
45 |
46 | gravatar_url = "//www.gravatar.com/avatar/" + \
47 | hashlib.md5(email.encode('utf-8')).hexdigest() + "?"
48 | gravatar_url += urlencode({'d': 'retro', 's': str(size)})
49 | return gravatar_url
50 |
51 |
52 | @register.filter
53 | def wordsonly(value):
54 | """
55 | return string words only.
56 | :param `value` is value from text or words.
57 |
58 | usage:
59 | {{ post.description|striptags|truncatewords:"20"|wordsonly }}
60 | """
61 | return re.sub(r'[^\w\s]', '', value, flags=re.I | re.M)
62 |
63 |
64 | @register.filter
65 | def numberize(number):
66 | """
67 | return convert number to string, an example:
68 | - 1000 to 1k
69 | - 1000000 to 1m, etc.
70 | :param `number` is number to convert.
71 |
72 | usage:
73 | {{ post.get_visitors.count|numberize }}
74 | """
75 | if type(number) == int:
76 | if number > 999 and number <= 999999:
77 | return "{0:.1f}k".format(number / 1000)
78 | elif number > 999999 and number <= 999999999:
79 | return "{0:.1f}m".format(number / 1000000)
80 | elif number > 999999999 and number <= 999999999999:
81 | return "{0:.1f}b".format(number / 1000000000)
82 | elif number > 999999999999 and number <= 999999999999999:
83 | return "{0:.1f}t".format(number / 1000000000000)
84 | else:
85 | return "{}".format(number)
86 | return "{}".format(number)
87 |
88 |
89 | @register.filter
90 | def has_group(user, mode='single'):
91 | """
92 | return group/s object/s from user.
93 | :param `user` is user object.
94 | :param `mode` is single/plural mode.
95 |
96 | single:
97 | {{ request.user|has_group }}
98 |
99 | plural:
100 | {{ request.user|has_group:"plural" }}
101 | """
102 | if mode.lower() == 'plural':
103 | return user.groups.all()
104 | return user.groups.first()
105 |
106 |
107 | @register.filter
108 | def get_tuple_value(tuples, key):
109 | """
110 | an example tuples for:
111 | tuples = (
112 | ("1", "Afghanistan"),
113 | ("2", "Albania"),
114 | ("3", "Algeria")
115 | )
116 | :param `tuples` is tuples inside tuple.
117 | :param `key` is the key from per-single tuple.
118 |
119 | usage:
120 | {{ tuples|get_tuple_value:"1" }}
121 | """
122 | for k, v in tuples:
123 | if k == key:
124 | return v
125 | return key
126 |
127 |
128 | @register.filter
129 | def markdown_find_images(markdown_text):
130 | """
131 | return list of image urls inside `markdown_text`.
132 | :param `markdown_text` is markdown text to find.
133 |
134 | example markdown text:
135 | Hello 
136 |
137 | provides for:
138 | jpeg|jpg|png|gif
139 |
140 | demo:
141 | https://goo.gl/3LEXom
142 |
143 | usage:
144 | {{ field_name|markdown_find_images }}
145 |
146 | example:
147 | {{ post.description|markdown_find_images }}
148 | """
149 | # findgex = r"[^(\s]+\.(?:jpeg|jpg|png|gif)(?=\b[+^\)])"
150 | findgex = r"[^(\s]+\.(?:jpeg|jpg|png|gif)(?=\))"
151 | return re.findall(findgex, markdown_text)
152 |
--------------------------------------------------------------------------------
/app_faq/models/answer.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | from django.db import models
5 | from django.conf import settings
6 | from django.contrib.auth.models import User
7 | from django.utils.encoding import python_2_unicode_compatible
8 | from django.utils.translation import ugettext_lazy as _
9 |
10 | from updown.fields import RatingField
11 |
12 | from app_faq.models.question import Question
13 | from app_faq.models.time import TimeStampedModel
14 | from app_faq.models.comment import Comment
15 |
16 |
17 | class AnswerQuerySet(models.QuerySet):
18 |
19 | def approved(self):
20 | """ whenever the answer is correct according to the author of the question """
21 | return self.filter(status='approved')
22 |
23 | def duplicated(self):
24 | """ mark/flag the answer as duplicated answer """
25 | return self.filter(status='duplicated')
26 |
27 | def pending(self):
28 | return self.filter(status='pending')
29 |
30 | def on_hold(self):
31 | return self.filter(status='on_hold')
32 |
33 | def closed(self):
34 | return self.filter(status='closed')
35 |
36 | def deleted(self):
37 | return self.filter(status='deleted')
38 |
39 |
40 | @python_2_unicode_compatible
41 | class Answer(TimeStampedModel):
42 | author = models.ForeignKey(
43 | User, related_name='answer_author')
44 |
45 | question = models.ForeignKey(
46 | Question, related_name='answer_question')
47 |
48 | STATUS_CHOICES = (
49 | ('approved', _('Approved')),
50 | ('duplicated', _('Duplicated')),
51 | ('pending', _('Pending')),
52 | ('on_hold', _('On Hold')),
53 | ('closed', _('Closed')),
54 | ('deleted', _('Deleted'))
55 | )
56 | status = models.CharField(
57 | _('Status'), max_length=20,
58 | choices=STATUS_CHOICES, default='approved')
59 |
60 | description = models.TextField(_('Description'))
61 |
62 | rating = RatingField(can_change_vote=True)
63 |
64 | edited = models.BooleanField(
65 | _('Edited?'), default=False)
66 |
67 | editor = models.ForeignKey(
68 | User, blank=True, null=True,
69 | on_delete=models.SET_NULL, related_name='answer_editor')
70 |
71 | objects = AnswerQuerySet.as_manager()
72 |
73 | def __str__(self):
74 | _title = _('%(author)s comment on %(question)s')
75 | return _title % {'author': self.author, 'question': self.question}
76 |
77 | def edits_object(self):
78 | answer = self
79 | qs = AnswerSuggestedEdits.objects.filter(answer=answer)
80 | if qs.exists():
81 | return qs.first()
82 | return answer
83 |
84 | def get_comments(self):
85 | """ return all comments contains with this answer """
86 | comments = Comment.objects.filter(object_id=self.pk,
87 | content_type__model=self._meta.model_name)
88 | return comments.order_by('created') # 'rating_likes'
89 |
90 | def get_comments_limit(self):
91 | """ return maximum show the comments """
92 | return self.get_comments()[:settings.COMMENTS_MAX_SHOW]
93 |
94 | def get_comments_offset(self):
95 | """ return all offset comments excluded from `comments_limit` """
96 | comments_limit_ids = [c.id for c in self.get_comments_limit()]
97 | return self.get_comments().exclude(pk__in=comments_limit_ids)
98 |
99 | @property
100 | def has_offset_comments(self):
101 | """ to check the answer has a offset comments or not """
102 | return self.get_comments_offset().exists()
103 |
104 | class Meta:
105 | verbose_name_plural = _('answers')
106 | ordering = ['-created']
107 |
108 |
109 | @python_2_unicode_compatible
110 | class AnswerSuggestedEdits(TimeStampedModel):
111 | editor = models.ForeignKey(
112 | User, related_name='suggested_edits_answer_editor')
113 |
114 | answer = models.ForeignKey(
115 | Question, related_name='suggested_edits_answer')
116 |
117 | STATUS_CHOICES = (
118 | ('approved', _('Approved')),
119 | ('rejected', _('Rejected')),
120 | ('pending', _('Pending'))
121 | )
122 | status = models.CharField(
123 | _('Status'), max_length=20,
124 | choices=STATUS_CHOICES, default='pending')
125 |
126 | description = models.TextField(_('Description'))
127 |
128 | comment = models.TextField(_('Revision Comment'))
129 |
130 | class Meta:
131 | verbose_name_plural = _('answer suggested edits')
132 | ordering = ['-created']
133 |
--------------------------------------------------------------------------------
/templates/account/login.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% load account socialaccount %}
4 | {% block title %}{% trans "Sign In" %} :: {{ block.super }}{% endblock %}
5 | {% block robot %} {% endblock %}
6 | {% block canonical %}{% url 'account_login' %}{% endblock %}
7 |
8 | {% block content %}
9 |
10 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
11 |
12 |
13 |
14 |
15 |
16 |
17 | Please sign in with one of your existing third party accounts, or use login form below:
18 |
19 |
20 |
98 |
101 |
102 |
103 |
104 | {% endblock %}
105 |
106 |
107 | {% block js %}
108 |
109 | {% endblock %}
110 |
--------------------------------------------------------------------------------
/templates/account/signup.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% block title %}Register :: {{ block.super }}{% endblock %}
4 | {% block robot %} {% endblock %}
5 | {% block canonical %}{% url 'account_signup' %}{% endblock %}
6 |
7 | {% block content %}
8 |
9 |
10 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
11 |
12 |
13 |
14 |
15 |
16 |
Fill out the form below to sign-up for a new account
17 |
18 |
19 |
107 |
108 |
Already signed up?
Login here instead.
109 |
110 |
111 |
112 | {% endblock %}
113 |
114 | {% block js %}
115 |
116 | {% endblock %}
117 |
--------------------------------------------------------------------------------
/static/js/djangofaq.detail.js:
--------------------------------------------------------------------------------
1 | // load the answe form after 1 second
2 | setTimeout(function(){
3 | $('.answer-main').show()}, 1000
4 | );
5 | $('.tab-martor-menu').removeClass('secondary pointing');
6 | $('.martor-preview pre').each(function(i, block){hljs.highlightBlock(block)});
7 |
8 | // comment: auth required
9 | $(document).keyup(function(){
10 | var textarea = $('textarea[name=description]');
11 | if(textarea.length > 0) {
12 | if($('textarea[name=description]').val().length >= 10) {
13 | $('.post-answer-button').removeAttr('disabled');
14 | }else {
15 | $('.post-answer-button').attr({'disabled': 'disabled'});
16 | }
17 | }
18 | });
19 |
20 | // to set background color at the selected comment/reply.
21 | var setMarkedBackground = function(selector) {
22 | try {
23 | $('html,body').animate({
24 | scrollTop: selector.offset().top
25 | }, 'slow');
26 | selector.attr({'style':'background:#FDD7AC'});
27 | setTimeout(function(){
28 | selector.removeAttr('style');
29 | }, 2000);
30 | } catch (e) {return false}
31 | };// EOF
32 |
33 | /* requirements
34 | - jQuery
35 | - hljs
36 | -----------------*/
37 | var baseLoadCommentsUrl = '/comments/offset/';
38 | var baseAddCommentUrl = '/comments/create/';
39 |
40 | // load the offset comments
41 | var showMoreComments = function(selector) {
42 | var selector_data = selector.data('target').split(':');
43 | var model_name = selector_data[0];
44 | var object_id = parseInt(selector_data[1]);
45 | var url = baseLoadCommentsUrl+model_name+'/'+object_id+'/';
46 |
47 | $.ajax({
48 | url: url,
49 | type: 'GET',
50 | async: true,
51 | cache: false,
52 | contentType: false,
53 | success: function(response) {
54 | var table_tbody = selector.closest('.table-comments tbody');
55 | table_tbody.append(response);
56 | table_tbody.find('.vertical-line').remove();
57 | selector.remove();
58 |
59 | var tr_actions = 'tr.comment-actions';
60 | var tr_actions_clone = table_tbody.find(tr_actions).clone();
61 | table_tbody.find(tr_actions).remove();
62 | table_tbody.append(tr_actions_clone);
63 |
64 | //hljs.highlightBlock('pre');
65 | }
66 | });
67 | }
68 | $(document).on('click', '.show-more-comments', function() {
69 | showMoreComments($(this));
70 | });
71 |
72 | // load the comment form
73 | var addComment = function(selector) {
74 | var selector_data = selector.data('target').split(':');
75 | var model_name = selector_data[0];
76 | var object_id = parseInt(selector_data[1]);
77 | var url = baseAddCommentUrl+model_name+'/'+object_id+'/';
78 |
79 | $.ajax({
80 | url: url,
81 | type: 'GET',
82 | async: true,
83 | cache: false,
84 | contentType: false,
85 | success: function(response) {
86 | var table_tbody = selector.closest('.table-comments tbody');
87 | table_tbody.find('.show-more-comments').trigger('click');
88 | setTimeout(function(){
89 | var lastTr = table_tbody.find('tr.comment-actions').last();
90 | var formTr = $(response).insertBefore(lastTr);
91 | formTr.find('form').attr({'action': url, 'data-target': selector.data('target')});
92 | formTr.find('textarea').focus();
93 | }, 500);
94 | selector.remove();
95 | }
96 | });
97 | }
98 | $(document).on('click', '.add-a-comment', function() {
99 | addComment($(this));
100 | });
101 |
102 | var sendComment = function(selector) {
103 | var selector_data = selector.data('target').split(':');
104 | var model_name = selector_data[0];
105 | var object_id = parseInt(selector_data[1]);
106 | var url = baseAddCommentUrl+model_name+'/'+object_id+'/';
107 |
108 | $.ajax({
109 | url: url,
110 | type: 'POST',
111 | data: selector.serialize(),
112 | success: function(response) {
113 | var table_tbody = selector.closest('.table-comments tbody');
114 | table_tbody.find('.show-more-comments').trigger('click');
115 | setTimeout(function(){
116 | var lastTr = table_tbody.find('tr.comment-actions').last();
117 | var formTr = $(response).insertBefore(lastTr);
118 | }, 500);
119 | }
120 | });
121 | }
122 | $(document).on('submit', '.comment-form', function() {
123 | sendComment($(this));
124 | });
125 |
126 |
127 | // vote up and vote down the question or answer
128 | $(document).on('click', '.vote-up, .vote-down', function() {
129 | var vote = $(this);
130 | var mode = vote.data('mode');
131 | var id = vote.data('id');
132 | var voteUrl = '/'+mode+'/'+id+'/rate/';
133 |
134 | if(vote.hasClass('vote-up')) {
135 | voteUrl = voteUrl+'1';
136 | }else{
137 | voteUrl = voteUrl+'-1';
138 | }
139 |
140 | $.ajax({
141 | url: voteUrl,
142 | type: 'GET',
143 | success: function(response) {
144 | alert(response);
145 | location.reload();
146 | },
147 | error: function(response) {
148 | alert(response);
149 | location.reload();
150 | }
151 | });
152 | });
153 |
--------------------------------------------------------------------------------
/templates/account/email.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load i18n %}
3 | {% block title %}{% trans "Email Account" %} :: {{ block.super }}{% endblock %}
4 | {% block robot %} {% endblock %}
5 | {% block canonical %}{% url 'account_email' %}{% endblock %}
6 |
7 | {% block content %}
8 |
9 | {% include "includes/profile_menus_top.html" %}
10 |
11 |
12 | {% include "includes/profile_menus_left.html" %}
13 |
14 |
15 |
16 |
17 |
18 | {% if user.emailaddress_set.all %}
19 |
20 | {% trans 'The following e-mail addresses are associated with your account:' %}
21 |
22 |
62 | {% else %}
63 |
64 | {% trans 'Warning:'%} {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
65 |
66 | {% endif %}{# endif user.emailaddress_set.all #}
67 |
68 |
94 |
95 |
96 |
97 | {% endblock %}
98 |
99 | {% block js %}
100 |
113 |
114 | {% endblock %}
115 |
--------------------------------------------------------------------------------
/static/css/github/reveal.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * # Semantic UI 2.1.8 - Reveal
3 | * http://github.com/semantic-org/semantic-ui/
4 | *
5 | *
6 | * Copyright 2015 Contributors
7 | * Released under the MIT license
8 | * http://opensource.org/licenses/MIT
9 | *
10 | */.ui.reveal{display:inherit;position:relative!important;font-size:0!important}.ui.reveal>.visible.content{position:absolute!important;top:0!important;left:0!important;z-index:3!important;-webkit-transition:all .5s ease .1s;transition:all .5s ease .1s}.ui.reveal>.hidden.content{position:relative!important;z-index:2!important}.ui.active.reveal .visible.content,.ui.reveal:hover .visible.content{z-index:4!important}.ui.slide.reveal{position:relative!important;overflow:hidden!important;white-space:nowrap}.ui.slide.reveal>.content{display:block;width:100%;float:left;margin:0;-webkit-transition:-webkit-transform .5s ease .1s;transition:-webkit-transform .5s ease .1s;transition:transform .5s ease .1s;transition:transform .5s ease .1s,-webkit-transform .5s ease .1s}.ui.slide.reveal>.visible.content{position:relative!important}.ui.slide.reveal>.hidden.content{position:absolute!important;left:0!important;width:100%!important;-webkit-transform:translateX(100%)!important;transform:translateX(100%)!important}.ui.slide.active.reveal>.visible.content,.ui.slide.reveal:hover>.visible.content{-webkit-transform:translateX(-100%)!important;transform:translateX(-100%)!important}.ui.slide.active.reveal>.hidden.content,.ui.slide.reveal:hover>.hidden.content,.ui.slide.right.reveal>.visible.content{-webkit-transform:translateX(0)!important;transform:translateX(0)!important}.ui.slide.right.reveal>.hidden.content{-webkit-transform:translateX(-100%)!important;transform:translateX(-100%)!important}.ui.slide.right.active.reveal>.visible.content,.ui.slide.right.reveal:hover>.visible.content{-webkit-transform:translateX(100%)!important;transform:translateX(100%)!important}.ui.slide.right.active.reveal>.hidden.content,.ui.slide.right.reveal:hover>.hidden.content{-webkit-transform:translateX(0)!important;transform:translateX(0)!important}.ui.slide.up.reveal>.hidden.content{-webkit-transform:translateY(100%)!important;transform:translateY(100%)!important}.ui.slide.up.active.reveal>.visible.content,.ui.slide.up.reveal:hover>.visible.content{-webkit-transform:translateY(-100%)!important;transform:translateY(-100%)!important}.ui.slide.up.active.reveal>.hidden.content,.ui.slide.up.reveal:hover>.hidden.content{-webkit-transform:translateY(0)!important;transform:translateY(0)!important}.ui.slide.down.reveal>.hidden.content{-webkit-transform:translateY(-100%)!important;transform:translateY(-100%)!important}.ui.slide.down.active.reveal>.visible.content,.ui.slide.down.reveal:hover>.visible.content{-webkit-transform:translateY(100%)!important;transform:translateY(100%)!important}.ui.slide.down.active.reveal>.hidden.content,.ui.slide.down.reveal:hover>.hidden.content{-webkit-transform:translateY(0)!important;transform:translateY(0)!important}.ui.fade.reveal>.visible.content{opacity:1}.ui.fade.active.reveal>.visible.content,.ui.fade.reveal:hover>.visible.content{opacity:0}.ui.move.reveal{position:relative!important;overflow:hidden!important;white-space:nowrap}.ui.move.reveal>.content{display:block;float:left;margin:0;-webkit-transition:-webkit-transform .5s cubic-bezier(.175,.885,.32,1) .1s;transition:-webkit-transform .5s cubic-bezier(.175,.885,.32,1) .1s;transition:transform .5s cubic-bezier(.175,.885,.32,1) .1s;transition:transform .5s cubic-bezier(.175,.885,.32,1) .1s,-webkit-transform .5s cubic-bezier(.175,.885,.32,1) .1s}.ui.move.reveal>.visible.content{position:relative!important}.ui.move.reveal>.hidden.content{position:absolute!important;left:0!important;width:100%!important}.ui.move.active.reveal>.visible.content,.ui.move.reveal:hover>.visible.content{-webkit-transform:translateX(-100%)!important;transform:translateX(-100%)!important}.ui.move.right.active.reveal>.visible.content,.ui.move.right.reveal:hover>.visible.content{-webkit-transform:translateX(100%)!important;transform:translateX(100%)!important}.ui.move.up.active.reveal>.visible.content,.ui.move.up.reveal:hover>.visible.content{-webkit-transform:translateY(-100%)!important;transform:translateY(-100%)!important}.ui.move.down.active.reveal>.visible.content,.ui.move.down.reveal:hover>.visible.content{-webkit-transform:translateY(100%)!important;transform:translateY(100%)!important}.ui.rotate.reveal>.visible.content{-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transform:rotate(0);transform:rotate(0)}.ui.rotate.reveal>.visible.content,.ui.rotate.right.reveal>.visible.content{-webkit-transform-origin:bottom right;transform-origin:bottom right}.ui.rotate.active.reveal>.visible.conten,.ui.rotate.reveal:hover>.visible.content,.ui.rotate.right.active.reveal>.visible.content,.ui.rotate.right.reveal:hover>.visible.content{-webkit-transform:rotate(110deg);transform:rotate(110deg)}.ui.rotate.left.reveal>.visible.content{-webkit-transform-origin:bottom left;transform-origin:bottom left}.ui.rotate.left.active.reveal>.visible.content,.ui.rotate.left.reveal:hover>.visible.content{-webkit-transform:rotate(-110deg);transform:rotate(-110deg)}.ui.disabled.reveal:hover>.visible.visible.content{position:static!important;display:block!important;opacity:1!important;top:0!important;left:0!important;right:auto!important;bottom:auto!important;-webkit-transform:none!important;transform:none!important}.ui.disabled.reveal:hover>.hidden.hidden.content{display:none!important}.ui.visible.reveal{overflow:visible}.ui.instant.reveal>.content{-webkit-transition-delay:0s!important;transition-delay:0s!important}.ui.reveal>.content{font-size:1rem!important}
--------------------------------------------------------------------------------