├── djangofaq ├── __init__.py ├── .gitignore ├── wsgi.py └── urls.py ├── app_faq ├── forms │ ├── __init__.py │ ├── answer.py │ ├── comment.py │ └── question.py ├── utils │ ├── __init__.py │ ├── validators.py │ ├── encoder.py │ ├── json.py │ └── revision.py ├── migrations │ ├── __init__.py │ └── .gitignore ├── templatetags │ ├── __init__.py │ ├── counter.py │ └── common_tags.py ├── __init__.py ├── apps.py ├── admin │ ├── flag.py │ ├── help.py │ ├── tag.py │ ├── comment.py │ ├── message.py │ ├── favorite.py │ ├── answer.py │ ├── question.py │ ├── bounty.py │ └── __init__.py ├── models │ ├── time.py │ ├── help.py │ ├── content_type.py │ ├── __init__.py │ ├── favorite.py │ ├── tag.py │ ├── comment.py │ ├── message.py │ ├── flag.py │ ├── bounty.py │ └── answer.py ├── views │ ├── __init__.py │ ├── answer.py │ ├── tag.py │ └── comment.py └── urls.py ├── app_user ├── migrations │ ├── __init__.py │ └── .gitignore ├── __init__.py ├── admin.py ├── apps.py ├── urls.py ├── models.py └── views.py ├── templates ├── account │ ├── base.html │ ├── messages │ │ ├── logged_out.txt │ │ ├── email_confirmed.txt │ │ ├── email_deleted.txt │ │ ├── password_set.txt │ │ ├── primary_email_set.txt │ │ ├── password_changed.txt │ │ ├── email_confirmation_sent.txt │ │ ├── unverified_primary_email.txt │ │ ├── cannot_delete_primary_email.txt │ │ └── logged_in.txt │ ├── snippets │ │ └── already_logged_in.html │ ├── account_inactive.html │ ├── signup_closed.html │ ├── password_reset_from_key_done.html │ ├── verification_sent.html │ ├── email │ │ └── password_reset_key_message.html │ ├── logout.html │ ├── password_reset_done.html │ ├── verified_email_required.html │ ├── password_reset_from_key.html │ ├── email_confirm.html │ ├── password_reset.html │ ├── password_set.html │ ├── password_change.html │ ├── login.html │ ├── signup.html │ └── email.html ├── openid │ ├── base.html │ └── login.html ├── socialaccount │ ├── base.html │ ├── snippets │ │ ├── login_extra.html │ │ └── provider_list.html │ ├── messages │ │ ├── account_connected.txt │ │ ├── account_disconnected.txt │ │ └── account_connected_other.txt │ ├── authentication_error.html │ ├── login_cancelled.html │ ├── signup.html │ └── connections.html ├── app_faq │ ├── question_edit.html │ ├── question_suggested_edits_create.html │ ├── answer_create.html │ ├── comments_offset.html │ ├── tags_search_offset.html │ ├── comment_create.html │ ├── question_revisions_old.html │ ├── question_revisions.html │ └── tags.html ├── reversion-compare │ ├── compare_generic_add.html │ ├── compare_generic_remove.html │ ├── compare_BooleanField.html │ ├── compare_links_partial.html │ ├── compare_DateTimeField.html │ ├── question │ │ ├── compare_links_partial.html │ │ ├── compare_generic_many_to_many.html │ │ ├── compare_partial.html │ │ └── action_list_partial.html │ ├── object_history.html │ ├── compare_generic_many_to_many.html │ ├── compare_partial.html │ ├── compare.html │ └── action_list_partial.html ├── includes │ ├── messages.html │ ├── profile_menus_top.html │ ├── footer.html │ ├── profile_menus_left.html │ └── navs.html ├── nocaptcha_recaptcha │ └── widget.html ├── base.html └── app_user │ └── users.html ├── .gitignore ├── __ext ├── 1. home.png ├── 2. detail.png └── 0.erd-django-faq.png ├── static ├── fonts │ ├── icons.eot │ ├── icons.otf │ ├── icons.ttf │ ├── icons.woff │ ├── icons.woff2 │ ├── octicons.ttf │ ├── octicons.woff │ ├── octicons.woff2 │ └── octicons-local.ttf ├── images │ └── flags.png ├── plugins │ ├── fonts │ │ ├── icons.eot │ │ ├── icons.otf │ │ ├── icons.ttf │ │ ├── icons.woff │ │ └── icons.woff2 │ ├── images │ │ ├── flags.png │ │ ├── heart.png │ │ └── commonmark.png │ ├── css │ │ ├── ace.min.css │ │ └── resizable.min.css │ └── js │ │ ├── snippets │ │ └── markdown.js │ │ ├── theme-github.js │ │ └── resizable.min.js ├── css │ ├── github │ │ ├── sticky.min.css │ │ ├── tab.min.css │ │ ├── rail.min.css │ │ ├── breadcrumb.min.css │ │ ├── nag.min.css │ │ ├── site.min.css │ │ ├── container.min.css │ │ ├── embed.min.css │ │ ├── ad.min.css │ │ ├── reset.min.css │ │ ├── shape.min.css │ │ ├── dimmer.min.css │ │ ├── comment.min.css │ │ ├── loader.min.css │ │ ├── image.min.css │ │ ├── feed.min.css │ │ ├── popup.min.css │ │ └── reveal.min.css │ ├── spfjs.css │ └── semantic-calendar.min.css └── js │ ├── semantic-calendar-widget.js │ ├── djangofaq.js │ ├── spfjs-main.js │ └── djangofaq.detail.js ├── readme.md ├── push.sh ├── requirements.txt └── manage.py /djangofaq/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app_faq/forms/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app_faq/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app_faq/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app_faq/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app_user/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /djangofaq/.gitignore: -------------------------------------------------------------------------------- 1 | settings.py 2 | -------------------------------------------------------------------------------- /app_faq/migrations/.gitignore: -------------------------------------------------------------------------------- 1 | [^.]* 2 | !__init__.py 3 | -------------------------------------------------------------------------------- /app_user/migrations/.gitignore: -------------------------------------------------------------------------------- 1 | [^.]* 2 | !__init__.py 3 | -------------------------------------------------------------------------------- /templates/account/base.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | 4 | -------------------------------------------------------------------------------- /templates/openid/base.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | __pycache__/ 3 | db.sqlite3 4 | *backup* 5 | *.zip 6 | -------------------------------------------------------------------------------- /templates/socialaccount/base.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | -------------------------------------------------------------------------------- /__ext/1. home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/__ext/1. home.png -------------------------------------------------------------------------------- /__ext/2. detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/__ext/2. detail.png -------------------------------------------------------------------------------- /static/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/icons.eot -------------------------------------------------------------------------------- /static/fonts/icons.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/icons.otf -------------------------------------------------------------------------------- /static/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/icons.ttf -------------------------------------------------------------------------------- /static/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/icons.woff -------------------------------------------------------------------------------- /static/fonts/icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/icons.woff2 -------------------------------------------------------------------------------- /static/fonts/octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/octicons.ttf -------------------------------------------------------------------------------- /static/images/flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/images/flags.png -------------------------------------------------------------------------------- /templates/app_faq/question_edit.html: -------------------------------------------------------------------------------- 1 | {% extends "app_faq/question_create.html" %} 2 | {% load i18n %} 3 | -------------------------------------------------------------------------------- /__ext/0.erd-django-faq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/__ext/0.erd-django-faq.png -------------------------------------------------------------------------------- /static/fonts/octicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/octicons.woff -------------------------------------------------------------------------------- /static/fonts/octicons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/octicons.woff2 -------------------------------------------------------------------------------- /static/plugins/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/fonts/icons.eot -------------------------------------------------------------------------------- /static/plugins/fonts/icons.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/fonts/icons.otf -------------------------------------------------------------------------------- /static/plugins/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/fonts/icons.ttf -------------------------------------------------------------------------------- /templates/socialaccount/snippets/login_extra.html: -------------------------------------------------------------------------------- 1 | {% load socialaccount %} 2 | 3 | {% providers_media_js %} 4 | 5 | -------------------------------------------------------------------------------- /static/fonts/octicons-local.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/fonts/octicons-local.ttf -------------------------------------------------------------------------------- /static/plugins/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/fonts/icons.woff -------------------------------------------------------------------------------- /static/plugins/fonts/icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/fonts/icons.woff2 -------------------------------------------------------------------------------- /static/plugins/images/flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/images/flags.png -------------------------------------------------------------------------------- /static/plugins/images/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/images/heart.png -------------------------------------------------------------------------------- /templates/account/messages/logged_out.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You have signed out.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/app_faq/question_suggested_edits_create.html: -------------------------------------------------------------------------------- 1 | {% extends "app_faq/question_create.html" %} 2 | {% load i18n %} 3 | -------------------------------------------------------------------------------- /static/plugins/images/commonmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/djangofaq/HEAD/static/plugins/images/commonmark.png -------------------------------------------------------------------------------- /templates/account/messages/email_confirmed.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You have confirmed {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/account/messages/email_deleted.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Removed e-mail address {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/account/messages/password_set.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Password successfully set.{% endblocktrans %} 3 | 4 | -------------------------------------------------------------------------------- /templates/account/messages/primary_email_set.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Primary e-mail address set.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/account/messages/password_changed.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Password successfully changed.{% endblocktrans %} 3 | 4 | -------------------------------------------------------------------------------- /app_faq/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | default_app_config = 'app_faq.apps.AppFaqConfig' 5 | -------------------------------------------------------------------------------- /app_user/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | default_app_config = 'app_user.apps.AppUserConfig' 5 | -------------------------------------------------------------------------------- /templates/account/messages/email_confirmation_sent.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Confirmation e-mail sent to {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/socialaccount/messages/account_connected.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account has been connected.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/socialaccount/messages/account_disconnected.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account has been disconnected.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/account/messages/unverified_primary_email.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Your primary e-mail address must be verified.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/reversion-compare/compare_generic_add.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |

4 | {% trans "add:" %} {{ value }} 5 |

-------------------------------------------------------------------------------- /templates/reversion-compare/compare_generic_remove.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |

4 | {% trans "remove:" %} {{ value }} 5 |

-------------------------------------------------------------------------------- /templates/account/messages/cannot_delete_primary_email.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You cannot remove your primary e-mail address ({{email}}).{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/socialaccount/messages/account_connected_other.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account is already connected to a different account.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /templates/reversion-compare/compare_BooleanField.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |

4 | {{ bool1 }} {% trans 'changed to:' %} {{ bool2 }} 5 |

6 | -------------------------------------------------------------------------------- /templates/account/messages/logged_in.txt: -------------------------------------------------------------------------------- 1 | {% load account %} 2 | {% load i18n %} 3 | {% user_display user as name %} 4 | {% blocktrans %}Successfully signed in as {{name}}.{% endblocktrans %} 5 | -------------------------------------------------------------------------------- /app_user/admin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | from app_user.models import Profile 6 | 7 | admin.site.register(Profile) 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | > **Under Development** - and we are welcome to contribute the code! 2 | 3 | Homepage 4 | ---------- 5 | 6 | ![home](__ext/1.%20home.png) 7 | 8 | Detail 9 | ---------- 10 | 11 | ![detail](__ext/2.%20detail.png) 12 | -------------------------------------------------------------------------------- /app_faq/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class AppFaqConfig(AppConfig): 8 | name = 'app_faq' 9 | verbose_name = 'F.A.Q' 10 | -------------------------------------------------------------------------------- /app_user/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.apps import AppConfig 5 | 6 | 7 | class AppUserConfig(AppConfig): 8 | name = 'app_user' 9 | verbose_name = 'Users' 10 | -------------------------------------------------------------------------------- /templates/account/snippets/already_logged_in.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% load account %} 3 | 4 | {% user_display user as user_display %} 5 |

{% trans "Note" %}: {% blocktrans %}you are already logged in as {{ user_display }}.{% endblocktrans %}

6 | -------------------------------------------------------------------------------- /templates/reversion-compare/compare_links_partial.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% if prev_url %}
  • ‹ {% trans "previous" %}
  • {% endif %} 3 | {% if next_url %}
  • {% trans "next" %} ›
  • {% endif %} -------------------------------------------------------------------------------- /push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo ''; 4 | echo -n "[+] commit ➜ "; 5 | read commit; 6 | 7 | if [ "$commit" ]; then 8 | git add .; 9 | git commit -m "$commit"; 10 | 11 | # bitbucket 12 | git push -u origin master; 13 | 14 | # github 15 | git push -u github master; 16 | fi 17 | -------------------------------------------------------------------------------- /app_faq/admin/flag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class FlagAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | -------------------------------------------------------------------------------- /app_faq/admin/help.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class HelpAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | -------------------------------------------------------------------------------- /app_faq/admin/tag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class TagAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | -------------------------------------------------------------------------------- /app_faq/admin/comment.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class CommentAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | -------------------------------------------------------------------------------- /app_faq/admin/message.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class MessageAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | -------------------------------------------------------------------------------- /app_faq/admin/favorite.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class FavoriteAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | -------------------------------------------------------------------------------- /templates/reversion-compare/compare_DateTimeField.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |
    4 | - {{ date1|date:_("DATETIME_FORMAT") }} ({% trans 'time since that date:' %} {{ date1|timesince }})
    5 | + {{ date2|date:_("DATETIME_FORMAT") }} ({% trans 'time since that date:' %} {{ date2|timesince }})
    6 | 
    -------------------------------------------------------------------------------- /app_faq/admin/answer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class AnswerAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | 13 | 14 | class AnswerSuggestedEditsAdmin(CompareVersionAdmin): 15 | pass 16 | -------------------------------------------------------------------------------- /app_faq/admin/question.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class QuestionAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | 13 | 14 | class QuestionSuggestedEditsAdmin(CompareVersionAdmin): 15 | pass 16 | -------------------------------------------------------------------------------- /app_faq/models/time.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models 5 | 6 | 7 | class TimeStampedModel(models.Model): 8 | """ 9 | abstract model for timing system. 10 | """ 11 | created = models.DateTimeField(auto_now_add=True) 12 | modified = models.DateTimeField(auto_now=True) 13 | 14 | class Meta: 15 | abstract = True 16 | -------------------------------------------------------------------------------- /app_faq/forms/answer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django import forms 5 | 6 | from martor.widgets import AdminMartorWidget 7 | from app_faq.models.answer import Answer 8 | 9 | 10 | class AnswerForm(forms.ModelForm): 11 | 12 | class Meta: 13 | model = Answer 14 | fields = ['description', ] 15 | widgets = {'description': AdminMartorWidget()} 16 | -------------------------------------------------------------------------------- /app_faq/admin/bounty.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.contrib import admin 5 | 6 | from reversion_compare.admin import CompareVersionAdmin 7 | 8 | 9 | class BountyAdmin(CompareVersionAdmin): 10 | #list_display = ['title', 'creator'] 11 | pass 12 | 13 | 14 | class BountyAwardAdmin(CompareVersionAdmin): 15 | #list_display = ['title', 'creator'] 16 | pass 17 | -------------------------------------------------------------------------------- /templates/app_faq/answer_create.html: -------------------------------------------------------------------------------- 1 | {% load i18n staticfiles %} 2 |
    {% csrf_token %} 3 |
    4 | {{ answer_form.description }} 5 |
    6 |
    7 |
    8 | 11 |
    12 |
    13 |
    14 | -------------------------------------------------------------------------------- /templates/includes/messages.html: -------------------------------------------------------------------------------- 1 | {% if messages %} 2 |
    3 |
    4 | {% for message in messages %} 5 |
    6 | 7 |
    {{ message }}
    8 |
    9 | {% endfor %} 10 |
    11 |
    12 | {% endif %} 13 | -------------------------------------------------------------------------------- /djangofaq/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djangoforum project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoforum.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /templates/account/account_inactive.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Account Inactive" %} :: {{ block.super }}{% endblock %} 4 | 5 | {% block content %} 6 |
    7 |

    {% trans "Account Inactive" %}

    8 |
    9 | {% trans "This account is inactive." %} 10 |
    11 |
    12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /templates/account/signup_closed.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Sign Up Closed" %} :: {{ block.super }}{% endblock %} 4 | 5 | {% block content %} 6 |
    7 |

    {% trans "Sign Up Closed" %}

    8 |
    9 | {% trans "We are sorry, but the sign up is currently closed." %} 10 |
    11 |
    12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /templates/app_faq/comments_offset.html: -------------------------------------------------------------------------------- 1 | {% load martortags %} 2 | 3 | {% for comment in comments_offset %} 4 | 5 | 18 6 | 7 |
    8 | 9 | 10 | 11 | {{ comment.comment|safe_markdown }} {{ comment.author }} {{ comment.created }} 12 | 13 | 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /templates/socialaccount/authentication_error.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Social Network Login Failure" %}{% endblock %} 4 | 5 | {% block content %} 6 |
    7 |

    {% trans "Social Network Login Failure" %}

    8 |
    9 |

    {% trans "An error occurred while attempting to login via your social network account." %}

    10 |
    11 |
    12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /templates/app_faq/tags_search_offset.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% load counter %} 3 | 4 | {% for tag in tags %} 5 |
    6 |

    {{ tag.title }} × {{ tag|get_total_questions_tagged }}

    7 |

    {{ tag.short_description|safe|striptags|truncatewords:"12" }}

    8 |

    532 asked today, 5548 this week

    9 |
    10 | {% endfor %} 11 | -------------------------------------------------------------------------------- /app_faq/utils/validators.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.utils.translation import ugettext_lazy as _ 5 | from django.core.exceptions import ValidationError 6 | from django.core.validators import (RegexValidator, _lazy_re_compile) 7 | 8 | # NOT USED YET 9 | 10 | slug_re = _lazy_re_compile(r'^[-a-zA-Z0-9_]+\Z') 11 | tag_slug_validators = RegexValidator( 12 | slug_re, 13 | # Translators: "letters" means latin letters: a-z and A-Z. 14 | _("Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."), 15 | 'invalid' 16 | ) 17 | -------------------------------------------------------------------------------- /templates/reversion-compare/question/compare_links_partial.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 |
    3 | {% if prev_url %} 4 | 7 | {% endif %} 8 | 9 | {% if next_url %} 10 | 13 | {% endif %} 14 |
    15 | -------------------------------------------------------------------------------- /templates/account/password_reset_from_key_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Change Password" %} :: {{ block.super }}{% endblock %} 4 | {% block robot %}{% endblock %} 5 | {% block canonical %}{% url 'account_reset_password_from_key_done' %}{% endblock %} 6 | 7 | {% block content %} 8 |
    9 |
    10 | {% trans 'Your password is now changed.' %} 11 |
    12 |
    13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /static/plugins/css/ace.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:0.5em;background:white;color:black}.hljs-comment,.hljs-quote,.hljs-variable{color:#008000}.hljs-keyword,.hljs-selector-tag,.hljs-built_in,.hljs-name,.hljs-tag{color:#00f}.hljs-string,.hljs-title,.hljs-section,.hljs-attribute,.hljs-literal,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-addition{color:#a31515}.hljs-deletion,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-meta{color:#2b91af}.hljs-doctag{color:#808080}.hljs-attr{color:#f00}.hljs-symbol,.hljs-bullet,.hljs-link{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} 2 | -------------------------------------------------------------------------------- /app_faq/forms/comment.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 app_faq.models.comment import Comment 8 | 9 | 10 | class CommentForm(forms.ModelForm): 11 | 12 | class Meta: 13 | model = Comment 14 | fields = ['comment', ] 15 | placeholder = _('Use comments to ask for more information ' 16 | 'or suggest improvements. Avoid answering questions in comments.') 17 | widgets = {'comment': forms.Textarea(attrs={'placeholder': placeholder})} 18 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2017.7.27.1 2 | chardet==3.0.4 3 | defusedxml==0.5.0 4 | diff-match-patch 5 | Django==1.11.23 6 | django-allauth==0.33.0 7 | django-badges==0.2.0 8 | django-nocaptcha-recaptcha==0.0.19 9 | django-reversion==2.0.10 10 | django-reversion-compare==0.8.0 11 | django-updown==1.0.2 12 | djipsum==1.1.4 13 | dnspython==1.15.0 14 | email-validator==1.0.2 15 | Faker==0.8.3 16 | idna==2.6 17 | oauthlib==2.0.3 18 | olefile==0.44 19 | Pillow==4.2.1 20 | pkg-resources==0.0.0 21 | python-dateutil==2.6.1 22 | python3-openid==3.1.0 23 | pytz==2017.2 24 | requests==2.18.4 25 | requests-oauthlib==0.8.0 26 | six==1.10.0 27 | urllib3==1.22 28 | -------------------------------------------------------------------------------- /templates/account/verification_sent.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 |

    {% trans "Verify Your E-mail Address" %}

    8 |
    9 | {% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %} 10 |
    11 |
    12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /static/css/github/sticky.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.1.8 - Sticky 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.sticky{position:static;-webkit-transition:none;transition:none;z-index:800}.ui.sticky.bound{position:absolute;left:auto;right:auto}.ui.sticky.fixed{position:fixed;left:auto;right:auto}.ui.sticky.bound.top,.ui.sticky.fixed.top{top:0;bottom:auto}.ui.sticky.bound.bottom,.ui.sticky.fixed.bottom{top:auto;bottom:0}.ui.native.sticky{position:-webkit-sticky;position:-moz-sticky;position:-ms-sticky;position:-o-sticky;position:sticky} -------------------------------------------------------------------------------- /templates/openid/login.html: -------------------------------------------------------------------------------- 1 | {% extends "openid/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans 'OpenID Sign In' %} :: {{ block.super }}{% endblock %} 4 | 5 | {% block content %} 6 |
    7 |

    {% trans 'OpenID Sign In' %}

    8 |
    9 | 14 |
    15 |
    16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /templates/socialaccount/login_cancelled.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Login Cancelled" %} :: {{ block.super }}{% endblock %} 4 | 5 | {% block content %} 6 |
    7 |

    {% trans "Login Cancelled" %}

    8 |
    9 | {% url 'account_login' as login_url %} 10 |

    {% blocktrans %}You decided to cancel logging in to our site using one of your existing accounts. If this was a mistake, please proceed to sign in.{% endblocktrans %}

    11 |
    12 |
    13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /app_user/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.conf.urls import url 5 | from app_user.views import * 6 | 7 | urlpatterns = [ 8 | url( 9 | r'^users/$', 10 | UserListView.as_view(), 11 | name='users' 12 | ), 13 | url( 14 | r'^users/(?P[\d-]+)/$', 15 | UserProfileRedirectView.as_view(), 16 | name='user_profile_redirect' 17 | ), 18 | url( 19 | r'^users/(?P[\d-]+)/(?P[\w\-]+)/$', 20 | UserProfile.as_view(), 21 | name='user_profile' 22 | ), 23 | url( 24 | r'^users/edit/$', 25 | UserProfileEdit.as_view(), 26 | name='user_profile_edit' 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /app_faq/utils/encoder.py: -------------------------------------------------------------------------------- 1 | from django.utils.functional import Promise 2 | from django.utils.encoding import force_text 3 | from django.core.serializers.json import DjangoJSONEncoder 4 | 5 | # This problem because we found error encoding, 6 | # as docs says, django has special `DjangoJSONEncoder` 7 | # https://docs.djangoproject.com/en/1.10/topics/serialization/#serialization-formats-json 8 | # and this answer: http://stackoverflow.com/a/31746279/6396981 9 | 10 | 11 | class LazyEncoder(DjangoJSONEncoder): 12 | """ 13 | used in: app_forum/views/uploader.py 14 | """ 15 | 16 | def default(self, obj): 17 | if isinstance(obj, Promise): 18 | return force_text(obj) 19 | return super(LazyEncoder, self).default(obj) 20 | -------------------------------------------------------------------------------- /templates/reversion-compare/object_history.html: -------------------------------------------------------------------------------- 1 | {% extends "admin/object_history.html" %} 2 | {% load i18n l10n %} 3 | 4 | {% block content %} 5 |
    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 |
  • 9 | {{brand.name}} 13 |
  • 14 | {% endfor %} 15 | {% endif %} 16 |
  • 17 | {{provider.name}} 19 |
  • 20 | {% endfor %} 21 | 22 | -------------------------------------------------------------------------------- /templates/account/email/password_reset_key_message.html: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Hello from {{ site_name }}! 2 |

    Ini versi html

    3 | 4 |

    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 | 20 | {% endif %} 21 | -------------------------------------------------------------------------------- /templates/account/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | {% load i18n %} 3 | {% block title %}{% trans "Sign Out" %} :: {{ block.super }}{% endblock %} 4 | 5 | {% block content %} 6 |
    7 |

    {% trans "Sign Out" %}

    8 |
    9 |
    {% trans 'Are you sure you want to sign out?' %}
    10 |
    {% csrf_token %} 11 | {% if redirect_field_value %} 12 | 13 | {% endif %} 14 | 17 |
    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 %}{% endblock %} 5 | {% block canonical %}{% url 'account_reset_password_done' %}{% endblock %} 6 | 7 | {% block content %} 8 |
    9 |
    10 |
    {% trans "Password Reset" %}
    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 | 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 | 19 | 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 |

    {% trans "Verify Your E-mail Address" %}

    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 |
    9 | 10 |
    11 |
    12 | 13 | 14 |
    15 |
    16 |
    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 |

    {% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}

    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 |
    15 | {% csrf_token %} 16 | {{ form.as_p }} 17 | 18 |
    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 |

    {% trans "Confirm E-mail Address" %}

    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 |
    15 | {% csrf_token %} 16 | 19 |
    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 |
    7 | {% csrf_token %} 8 |
    9 |
    10 | {{ form.comment }} 11 | {% if form.comment.errors %} 12 |
    13 | {% for error in form.comment.errors %} 14 |
  • {{ error }}
  • 15 | {% endfor %} 16 |
    17 | {% endif %} 18 |
    19 |
    20 |
    21 | {% trans "Comment use mini-Markdown formatting:" %} [link](http://example.com) _italic_ **bold** `code`. 22 | {% blocktrans %}The comment author will always be notified of your replied comment. To also notify a previous commenter, mention their user name:{% endblocktrans %} @[username]. 23 | {% trans "Learn more..." %} 24 |
    25 | 28 |
    29 |
    30 |
    31 | 32 | 33 | -------------------------------------------------------------------------------- /templates/reversion-compare/question/compare_partial.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 |

    {% trans "Edit comment:" %}

    4 |
    {{ version2.revision.comment|default:"(no comment exists)" }}
    5 | 6 | {% for field_diff in compare_data %} 7 |

    {% firstof field_diff.field.verbose_name field_diff.field.related_name %}{% if field_diff.is_related and not field_diff.follow %}{% endif %}

    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 | 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 | 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 ![\n ![${1:alttext}](${2:/images/image.jpg} "${3:title}")\nsnippet ![*\n ![${1:alt}](${2:`@*`} "${3:title}")${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 |
      34 | {% block object-tools-items %} 35 | {% include "reversion-compare/compare_links_partial.html" %} 36 | {% endblock %} 37 |
    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 |

    {% trans "Password Reset" %}

    10 |
    11 | {% csrf_token %} 12 |
    13 | 14 |
    15 | {{ form.email }} 16 | 17 |
    18 | {% if form.email.errors %} 19 |
    20 | {% for error in form.email.errors %} 21 |
  • {{ error }}
  • 22 | {% endfor %} 23 |
    24 | {% endif %} 25 |
    26 |
    27 |
    28 | 29 | {{ form.captcha }} 30 | {% if form.captcha.errors %} 31 |
    32 | {% for error in form.captcha.errors %} 33 |
  • {{ error }}
  • 34 | {% endfor %} 35 |
    36 | {% endif %} 37 |
    38 |
    39 |
    40 | 43 |
    44 |
    45 |
    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 |
    13 |

    {% trans "Set Password" %}

    14 |
    15 |
    16 |
    {% csrf_token %} 17 |
    18 | 19 |
    20 | {{ form.password1 }} 21 | 22 |
    23 | {% if form.password1.errors %} 24 |
    25 | {% for error in form.password1.errors %} 26 |
  • {{ error }}
  • 27 | {% endfor %} 28 |
    29 | {% endif %} 30 |
    31 |
    32 | 33 |
    34 | {{ form.password2 }} 35 | 36 |
    37 | {% if form.password2.errors %} 38 |
    39 | {% for error in form.password2.errors %} 40 |
  • {{ error }}
  • 41 | {% endfor %} 42 |
    43 | {% endif %} 44 |
    45 | 46 |
    47 |
    48 |
    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 %} 3 | 4 | 5 | 6 | {% if compare_view %} 7 | 14 | {% endif %} 15 | 16 | 17 | 18 | 19 | 20 | 21 | {% for action in action_list %} 22 | 23 | {% if compare_view %} 24 | 32 | {% endif %} 33 | 40 | 46 | 47 | 48 | {% endfor %} 49 | 50 |
    8 | {% if comparable %} 9 | 10 | {% else %} 11 | {% trans 'compare' %} 12 | {% endif %} 13 | {% trans 'Date/time' %}{% trans 'User' %}{% trans 'Comment' %}
    25 | {% if comparable %} 26 | 27 | 28 | {% else %} 29 | - 30 | {% endif %} 31 | 34 | {% if action.url %} 35 | {{action.revision.date_created|date:_("DATETIME_FORMAT")}} 36 | {% else %} 37 | {{action.revision.date_created|date:_("DATETIME_FORMAT")}} 38 | {% endif %} 39 | 41 | {% if action.revision.user %} 42 | {{action.revision.user.username}} 43 | {% if action.revision.user.first_name %} ({{action.revision.user.first_name}} {{action.revision.user.last_name}}){% endif %} 44 | {% endif %} 45 | {{action.revision.comment|default:""}}
    51 | {% 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 %} 4 | 5 | 6 | 7 | 8 | {% if compare_view %} 9 | 16 | {% endif %} 17 | 18 | 19 | 20 | {% for action in action_list %} 21 | 22 | 34 | 35 | 42 | {% if compare_view %} 43 | 55 | {% endif %} 56 | 57 | {% endfor %} 58 | 59 |
    {% trans "Revisions" %} 10 | {% if comparable %} 11 | 12 | {% else %} 13 | {% trans 'compare' %} 14 | {% endif %} 15 |
    23 | {% if action.revision.user %} 24 |

    25 | 26 |
    27 | {{ action.revision.user.username }} 28 |
    Human Resources 29 |
    30 |
    31 |

    32 | {% endif %} 33 |
    {{ action.revision.comment|default:"" }} 36 | {% if action.url %} 37 | {{action.revision.date_created|date:_("DATETIME_FORMAT")}} 38 | {% else %} 39 | {{action.revision.date_created|date:_("DATETIME_FORMAT")}} 40 | {% endif %} 41 | 44 | {% if comparable %} 45 |
    46 | 47 |
    48 |
    49 | 50 |
    51 | {% else %} 52 | - 53 | {% endif %} 54 |
    60 | {% 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 |

    {% trans "Set Password" %}

    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 |
    {% csrf_token %} 21 |
    22 |

    {% trans "Account Connections" %}

    23 |
    24 | {% if form.non_field_errors %} 25 |
    {{ form.non_field_errors }}
    26 | {% endif %} 27 | {% for base_account in form.accounts %} 28 | {% with base_account.get_provider_account as account %} 29 |
    30 |
    31 | 32 | 33 |
    34 |
    35 | {% endwith %} 36 | {% endfor %} 37 |
    38 |
    39 | 40 |
    41 |
    42 |
    43 | {% else %} 44 |
    45 | {% trans 'You currently have no social network accounts connected to this account.' %} 46 |
    47 | {% endif %} 48 | 49 |
    50 |

    {% trans 'Add a 3rd Party Account' %}

    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 |
    13 |

    {% trans "Change Password" %}

    14 |
    15 |
    16 |
    17 | {% csrf_token %} 18 |
    19 | 20 |
    21 | {{ form.oldpassword }} 22 | 23 |
    24 | {% if form.oldpassword.errors %} 25 |
    26 | {% for error in form.oldpassword.errors %} 27 |
  • {{ error }}
  • 28 | {% endfor %} 29 |
    30 | {% endif %} 31 |
    32 |
    33 | 34 |
    35 | {{ form.password1 }} 36 | 37 |
    38 | {% if form.password1.errors %} 39 |
    40 | {% for error in form.password1.errors %} 41 |
  • {{ error }}
  • 42 | {% endfor %} 43 |
    44 | {% endif %} 45 |
    46 |
    47 | 48 |
    49 | {{ form.password2 }} 50 | 51 |
    52 | {% if form.password2.errors %} 53 |
    54 | {% for error in form.password2.errors %} 55 |
  • {{ error }}
  • 56 | {% endfor %} 57 |
    58 | {% endif %} 59 |
    60 | 63 | {% url 'account_reset_password' as reset_url %} 64 | {% blocktrans with reset_url=reset_url %}or need to reset the password?{% endblocktrans %} 65 |
    66 |
    67 |
    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 | 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 |
    65 | 56K 66 | 67 | 68 | 12 69 | 70 | 71 | 38 72 | 73 | 74 | 93 75 | 76 | 77 |
    78 |
    79 | {% endfor %} 80 |
    81 | 82 |
    83 | 84 |
    85 | 111 |
    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 |
    33 | {% for tag in tags %} 34 |
    35 |

    {{ tag.title }} × {{ tag|get_total_questions_tagged }}

    36 |

    {{ tag.short_description|safe|striptags|truncatewords:"12" }}

    37 |

    532 asked today, 5548 this week

    38 |
    39 | {% endfor %} 40 |
    41 | 42 |
    43 |
    44 | 45 |
    46 |
    47 | 48 | 74 |
    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 |
    5 |
    6 | 77 | 78 | 100 |
    101 |
    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 ![title](/path/to/image.png) 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 | 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 |
    Welcome to Django F.A.Q!
    16 |

    Fill out the form below to sign-up for a new account

    17 |
    18 | 19 |
    {% csrf_token %} 20 |
    21 |
    22 | Github 23 |
    24 | LinkedIn 25 |
    26 |
    27 | 28 |
    29 | 30 |
    31 |
    32 | 33 |
    34 | {{ form.username }} 35 | 36 |
    37 | {% if form.username.errors %} 38 |
    39 | {% for error in form.username.errors %} 40 |
  • {{ error }}
  • 41 | {% endfor %} 42 |
    43 | {% endif %} 44 |
    45 | 59 |
    60 | 61 |
    62 |
    63 | 64 |
    65 | {{ form.password1 }} 66 | 67 |
    68 | {% if form.password1.errors %} 69 |
    70 | {% for error in form.password1.errors %} 71 |
  • {{ error }}
  • 72 | {% endfor %} 73 |
    74 | {% endif %} 75 |
    76 |
    77 | 78 |
    79 | {{ form.password2 }} 80 | 81 |
    82 | {% if form.password2.errors %} 83 |
    84 | {% for error in form.password2.errors %} 85 |
  • {{ error }}
  • 86 | {% endfor %} 87 |
    88 | {% endif %} 89 |
    90 |
    91 | 92 |
    93 | 94 | {{ form.captcha }} 95 | {% if form.captcha.errors %} 96 |
    97 | {% for error in form.captcha.errors %} 98 |
  • {{ error }}
  • 99 | {% endfor %} 100 |
    101 | {% endif %} 102 |
    103 | 106 |
    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 |

    {% trans "Email Account" %}

    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 |
    69 | {% csrf_token %} 70 |

    {% trans "Add E-mail Address" %}

    71 |
    72 |
    73 |
    74 |
    75 | {{ form.email }} 76 | 77 |
    78 | {% if form.email.errors %} 79 |
    80 | {% for error in form.email.errors %} 81 |
  • {{ error }}
  • 82 | {% endfor %} 83 |
    84 | {% endif %} 85 |
    86 |
    87 | 90 |
    91 |
    92 |
    93 |
    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} --------------------------------------------------------------------------------