diff options
author | Adolfo Fitoria <adolfo.fitoria@gmail.com> | 2012-08-20 09:03:56 -0600 |
---|---|---|
committer | Adolfo Fitoria <adolfo.fitoria@gmail.com> | 2012-08-20 09:03:56 -0600 |
commit | 7a1c9b8f86147ce3fe7facd05e0e431a5b2e0eb1 (patch) | |
tree | c3b7594b17b5637ee8122cbf14a6b4280f7fccdb | |
parent | f30e098e2fb280d28b668d704c846e4378ab9ee7 (diff) | |
parent | b52e72b5c74c4c672cf8e81cf83f8c281bd765c2 (diff) | |
download | askbot-7a1c9b8f86147ce3fe7facd05e0e431a5b2e0eb1.tar.gz askbot-7a1c9b8f86147ce3fe7facd05e0e431a5b2e0eb1.tar.bz2 askbot-7a1c9b8f86147ce3fe7facd05e0e431a5b2e0eb1.zip |
Merge branch 'user-groups' of github.com:ASKBOT/askbot-devel into user-groups
-rw-r--r-- | askbot/management/commands/askbot_add_test_content.py | 2 | ||||
-rw-r--r-- | askbot/skins/common/media/js/post.js | 74 | ||||
-rw-r--r-- | askbot/skins/common/media/js/utils.js | 126 | ||||
-rw-r--r-- | askbot/skins/default/templates/question.html | 1 | ||||
-rw-r--r-- | askbot/skins/default/templates/question/javascript.html | 1 | ||||
-rw-r--r-- | askbot/skins/default/templates/widgets/groups_list.html | 4 | ||||
-rw-r--r-- | askbot/skins/default/templates/widgets/user_list.html | 8 | ||||
-rw-r--r-- | askbot/skins/loaders.py | 12 | ||||
-rw-r--r-- | askbot/views/commands.py | 33 | ||||
-rw-r--r-- | askbot/views/readers.py | 4 |
10 files changed, 250 insertions, 15 deletions
diff --git a/askbot/management/commands/askbot_add_test_content.py b/askbot/management/commands/askbot_add_test_content.py index ace629d0..17d3ffd0 100644 --- a/askbot/management/commands/askbot_add_test_content.py +++ b/askbot/management/commands/askbot_add_test_content.py @@ -14,7 +14,7 @@ NUM_COMMENTS = 20 # karma. This can be calculated dynamically - max of MIN_REP_TO_... settings INITIAL_REPUTATION = 500 -BAD_STUFF = "<script>alert('hohoho')</script>" +BAD_STUFF = ''#"<script>alert('hohoho')</script>" # Defining template inputs. USERNAME_TEMPLATE = BAD_STUFF + "test_user_%s" diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js index 5f2484ee..cafc6840 100644 --- a/askbot/skins/common/media/js/post.js +++ b/askbot/skins/common/media/js/post.js @@ -207,6 +207,65 @@ var CPValidator = function(){ /** * @constructor */ +var ThreadUsersDialog = function() { + SimpleControl.call(this); + this._heading_text = 'Add heading with the setHeadingText()'; +}; +inherits(ThreadUsersDialog, SimpleControl); + +ThreadUsersDialog.prototype.setHeadingText = function(text) { + this._heading_text = text; +}; + +ThreadUsersDialog.prototype.showUsers = function(html) { + this._dialog.setContent(html); + this._dialog.show(); +}; + +ThreadUsersDialog.prototype.startShowingUsers = function() { + var me = this; + var threadId = this._threadId; + var url = this._url; + $.ajax({ + type: 'GET', + data: {'thread_id': threadId}, + dataType: 'json', + url: url, + cache: false, + success: function(data){ + if (data['success'] == true){ + me.showUsers(data['html']); + } else { + showMessage(me.getElement(), data['message'], 'after'); + } + } + }); +}; + +ThreadUsersDialog.prototype.decorate = function(element) { + this._element = element; + ThreadUsersDialog.superClass_.decorate.call(this, element); + this._threadId = element.data('threadId'); + this._url = element.data('url'); + var dialog = new ModalDialog(); + dialog.setRejectButtonText(''); + dialog.setAcceptButtonText(gettext('Back to the question')); + dialog.setHeadingText(this._heading_text); + dialog.setAcceptHandler(function(){ dialog.hide(); }); + var dialog_element = dialog.getElement(); + $(dialog_element).find('.modal-footer').css('text-align', 'center'); + $(document).append(dialog_element); + this._dialog = dialog; + var me = this; + this.setHandler(function(){ + me.startShowingUsers(); + }); +}; + + +/** + * @constructor + */ var DraftPost = function() { WrappedElement.call(this); }; @@ -249,7 +308,7 @@ DraftPost.prototype.getSaveHandler = function() { return function(save_synchronously) { if (me.shouldSave()) { $.ajax({ - type: 'POST', + type: 'GET', cache: false, dataType: 'json', async: save_synchronously ? false : true, @@ -3867,6 +3926,19 @@ $(document).ready(function() { }); usersAc.decorate(usersInput); } + + var showSharedUsers = $('.see-related-users'); + if (showSharedUsers.length) { + var usersPopup = new ThreadUsersDialog(); + usersPopup.setHeadingText(gettext('Shared with the following users:')); + usersPopup.decorate(showSharedUsers); + } + var showSharedGroups = $('.see-related-groups'); + if (showSharedGroups.length) { + var groupsPopup = new ThreadUsersDialog(); + groupsPopup.setHeadingText(gettext('Shared with the following groups:')); + groupsPopup.decorate(showSharedGroups); + } }); diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js index 01239304..b8a716ec 100644 --- a/askbot/skins/common/media/js/utils.js +++ b/askbot/skins/common/media/js/utils.js @@ -569,6 +569,132 @@ DeleteIcon.prototype.setContent = function(content){ } /** + * @contstructor + * Simple modal dialog with Ok/Cancel buttons by default + */ +var ModalDialog = function() { + WrappedElement.call(this); + this._accept_button_text = gettext('Ok'); + this._reject_button_text = gettext('Cancel'); + this._heading_text = 'Add heading by setHeadingText()'; + this._initial_content = undefined; + this._accept_handler = function(){}; + var me = this; + this._reject_handler = function() { me.hide(); }; + this._content_element = undefined; +}; +inherits(ModalDialog, WrappedElement); + +ModalDialog.prototype.show = function() { + this._element.modal('show'); +}; + +ModalDialog.prototype.hide = function() { + this._element.modal('hide'); +}; + +ModalDialog.prototype.setContent = function(content) { + this._initial_content = content; + if (this._content_element) { + this._content_element.html(content); + } +}; + +ModalDialog.prototype.prependContent = function(content) { + this._content_element.prepend(content); +}; + +ModalDialog.prototype.setHeadingText = function(text) { + this._heading_text = text; +}; + +ModalDialog.prototype.setAcceptButtonText = function(text) { + this._accept_button_text = text; +}; + +ModalDialog.prototype.setRejectButtonText = function(text) { + this._reject_button_text = text; +}; + +ModalDialog.prototype.setAcceptHandler = function(handler) { + this._accept_handler = handler; +}; + +ModalDialog.prototype.setRejectHandler = function(handler) { + this._reject_handler = handler; +}; + +ModalDialog.prototype.clearMessages = function() { + this._element.find('.alert').remove(); +}; + +ModalDialog.prototype.setMessage = function(text, message_type) { + var box = new AlertBox(); + box.setText(text); + if (message_type === 'error') { + box.setError(true); + } + this.prependContent(box.getElement()); +}; + +ModalDialog.prototype.createDom = function() { + this._element = this.makeElement('div') + var element = this._element; + + element.addClass('modal'); + + //1) create header + var header = this.makeElement('div') + header.addClass('modal-header'); + element.append(header); + + var close_link = this.makeElement('div'); + close_link.addClass('close'); + close_link.attr('data-dismiss', 'modal'); + close_link.html('x'); + header.append(close_link); + + var title = this.makeElement('h3'); + title.html(this._heading_text); + header.append(title); + + //2) create content + var body = this.makeElement('div') + body.addClass('modal-body'); + element.append(body); + this._content_element = body; + if (this._initial_content) { + this._content_element.append(this._initial_content); + } + + //3) create footer with accept and reject buttons (ok/cancel). + var footer = this.makeElement('div'); + footer.addClass('modal-footer'); + element.append(footer); + + var accept_btn = this.makeElement('button'); + accept_btn.addClass('btn btn-primary'); + accept_btn.html(this._accept_button_text); + footer.append(accept_btn); + + if (this._reject_button_text) { + var reject_btn = this.makeElement('button'); + reject_btn.addClass('btn cancel'); + reject_btn.html(this._reject_button_text); + footer.append(reject_btn); + } + + //4) attach event handlers to the buttons + setupButtonEventHandlers(accept_btn, this._accept_handler); + if (this._reject_button_text) { + setupButtonEventHandlers(reject_btn, this._reject_handler); + } + setupButtonEventHandlers(close_link, this._reject_handler); + + this.hide(); +}; + +/** * attaches a modal menu with a text editor * to a link. The modal menu is from bootstrap.js */ diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index c810aecb..7c3ef372 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -8,6 +8,7 @@ {% block forestyle %} <link rel="canonical" href="{{settings.APP_URL|strip_path}}{{question.get_absolute_url()}}" /> <link rel="stylesheet" type="text/css" href="{{'/js/wmd/wmd.css'|media}}" /> + <link href="{{'/bootstrap/css/bootstrap.css'|media}}" rel="stylesheet" type="text/css" /> {% endblock %} {% block forejs %} <script type="text/javascript"> diff --git a/askbot/skins/default/templates/question/javascript.html b/askbot/skins/default/templates/question/javascript.html index 4399c823..bc640623 100644 --- a/askbot/skins/default/templates/question/javascript.html +++ b/askbot/skins/default/templates/question/javascript.html @@ -27,6 +27,7 @@ {% endif %} askbot['settings']['tagSource'] = '{{ settings.TAG_SOURCE }}'; </script> +<script type="text/javascript" src='{{"/bootstrap/js/bootstrap.js"|media}}'></script> {% if settings.EDITOR_TYPE == 'markdown' %} <script type='text/javascript' src='{{"/js/wmd/showdown.js"|media}}'></script> <script type='text/javascript' src='{{"/js/wmd/wmd.js"|media}}'></script> diff --git a/askbot/skins/default/templates/widgets/groups_list.html b/askbot/skins/default/templates/widgets/groups_list.html new file mode 100644 index 00000000..0669f34f --- /dev/null +++ b/askbot/skins/default/templates/widgets/groups_list.html @@ -0,0 +1,4 @@ +{% import "macros.html" as macros %} +{% for group in groups %} + <p>{{ macros.user_group(group) }}</p> +{% endfor %} diff --git a/askbot/skins/default/templates/widgets/user_list.html b/askbot/skins/default/templates/widgets/user_list.html index e51abc5b..52cf8bd4 100644 --- a/askbot/skins/default/templates/widgets/user_list.html +++ b/askbot/skins/default/templates/widgets/user_list.html @@ -1,4 +1,4 @@ -{%from "macros.html" import gravatar %} +{% import "macros.html" as macros %} <div class="userList"> <table class="list-table"> <tr> @@ -6,10 +6,10 @@ {% for user in users %} <div class="user"> <ul> - <li class="thumb">{{ gravatar(user, 32) }}</li> - <li><a href="{% url user_profile user.id, user.username|slugify %}{% if profile_section %}?sort={{profile_section}}{% endif %}">{{user.username|escape}}</a>{{ user_country_flag(user) }}</li> + <li class="thumb">{{ macros.gravatar(user, 32) }}</li> + <li><a href="{% url user_profile user.id, user.username|slugify %}{% if profile_section %}?sort={{profile_section}}{% endif %}">{{user.username|escape}}</a>{{ macros.user_country_flag(user) }}</li> <li>{{ - user_score_and_badge_summary( + macros.user_score_and_badge_summary( user, karma_mode = karma_mode, badges_mode = badges_mode diff --git a/askbot/skins/loaders.py b/askbot/skins/loaders.py index aa3188e9..c1367fe5 100644 --- a/askbot/skins/loaders.py +++ b/askbot/skins/loaders.py @@ -115,14 +115,20 @@ def get_template(template, request = None): skin.set_language(request.LANGUAGE_CODE) return skin.get_template(template) +def render_into_skin_as_string(template, data, request): + context = RequestContext(request, data) + template = get_template(template, request) + return template.render(context) + def render_into_skin(template, data, request, mimetype = 'text/html'): """in the future this function will be able to switch skin depending on the site administrator/user selection right now only admins can switch """ - context = RequestContext(request, data) - template = get_template(template, request) - return HttpResponse(template.render(context), mimetype = mimetype) + return HttpResponse( + render_into_skin_as_string(template, data, request), + mimetype=mimetype + ) def render_text_into_skin(text, data, request): context = RequestContext(request, data) diff --git a/askbot/views/commands.py b/askbot/views/commands.py index 123fc112..aa602f55 100644 --- a/askbot/views/commands.py +++ b/askbot/views/commands.py @@ -30,6 +30,7 @@ from askbot.utils import decorators from askbot.utils import url_utils from askbot import mail from askbot.skins.loaders import render_into_skin, get_template +from askbot.skins.loaders import render_into_skin_as_string from askbot import const @@ -475,15 +476,39 @@ def get_tags_by_wildcard(request): re_data = simplejson.dumps({'tag_count': count, 'tag_names': list(names)}) return HttpResponse(re_data, mimetype = 'application/json') -@decorators.ajax_only @decorators.get_only def get_thread_shared_users(request): - pass + """returns snippet of html with users""" + thread_id = request.GET['thread_id'] + thread_id = IntegerField().clean(thread_id) + thread = models.Thread.objects.get(id=thread_id) + users = thread.get_users_shared_with() + data = { + 'users': users, + } + html = render_into_skin_as_string('widgets/user_list.html', data, request) + re_data = simplejson.dumps({ + 'html': html, + 'users_count': users.count(), + 'success': True + }) + return HttpResponse(re_data, mimetype='application/json') -@decorators.ajax_only @decorators.get_only def get_thread_shared_groups(request): - pass + """returns snippet of html with groups""" + thread_id = request.GET['thread_id'] + thread_id = IntegerField().clean(thread_id) + thread = models.Thread.objects.get(id=thread_id) + groups = thread.get_groups_shared_with() + data = {'groups': groups} + html = render_into_skin_as_string('widgets/groups_list.html', data, request) + re_data = simplejson.dumps({ + 'html': html, + 'groups_count': groups.count(), + 'success': True + }) + return HttpResponse(re_data, mimetype='application/json') @decorators.ajax_only def get_html_template(request): diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 3d0f131f..c7a4fc26 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -568,12 +568,12 @@ def question(request, id):#refactor - long subroutine. display question body, an #shared with ... users_count, groups_count = thread.get_sharing_info() shared_users = thread.get_users_shared_with( - max_count=2, + max_count=2,#"visitor" is implicit exclude_user=request.user ) sharing_info = { 'users': shared_users, - 'groups': thread.get_groups_shared_with(max_count=2), + 'groups': thread.get_groups_shared_with(max_count=3), 'more_users_count': max(0, users_count - 3), 'more_groups_count': max(0, groups_count - 3) } |