1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-26 15:26:19 +00:00

Merge pull request #1014 from haiwen/turn-group-wiki

Turn on/off group Wiki
This commit is contained in:
Daniel Pan
2016-02-19 17:29:41 +08:00
12 changed files with 154 additions and 147 deletions

View File

@@ -131,7 +131,7 @@
.sf2-icon-x2:before { content:"\e01f"; }
.sf2-icon-user2:before { content:"\e020"; }
.sf2-icon-msgs2:before { content:"\e021"; }
.sf2-icon-group-settings:before { content:"\e022"; }
/*.sf2-icon-group-settings:before { content:"\e022"; }*/
.sf2-icon-comment:before { content:"\e023"; }
.sf2-icon-wiki2:before { content:"\e024"; }
@@ -656,7 +656,8 @@ textarea:-moz-placeholder {/* for FF */
}
.side-tabnav .grp-name { /*for 'group'*/
display:inline-block;
width:130px;
max-width:130px;
font-weight:normal;
}
.side-tabnav-tabs {
margin-bottom:1em;
@@ -2090,7 +2091,7 @@ textarea:-moz-placeholder {/* for FF */
.fixed-upload-file-dialog .op-icon {
font-size:18px;
color: #b8b8b8;
margin:0;
margin:0;
}
.fixed-upload-file-dialog .close,
.fileupload-buttonbar .cancel {

View File

@@ -27,6 +27,8 @@ from seahub.group.utils import validate_group_name, check_group_name_conflict, \
from seahub.group.views import remove_group_common
from seahub.base.templatetags.seahub_tags import email2nickname, \
translate_seahub_time
from seahub.views.modules import is_wiki_mod_enabled_for_group, \
enable_mod_for_group, disable_mod_for_group, MOD_GROUP_WIKI
from .utils import api_check_group
@@ -58,6 +60,7 @@ def get_group_info(request, group_id, avatar_size=GROUP_AVATAR_DEFAULT_SIZE):
"created_at": val.strftime("%Y-%m-%dT%H:%M:%S") + DateFormat(val).format('O'),
"avatar_url": request.build_absolute_uri(avatar_url),
"admins": get_group_admins(group.id),
"wiki_enabled": is_wiki_mod_enabled_for_group(group_id)
}
return group_info
@@ -266,6 +269,31 @@ class Group(APIView):
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
wiki_enabled = request.data.get('wiki_enabled', None)
# turn on/off group wiki
if wiki_enabled:
try:
# only group owner/admin can turn on a group wiki
if not is_group_admin_or_owner(group_id, username):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# augument check
if wiki_enabled != 'true' and wiki_enabled != 'false':
error_msg = 'wiki_enabled invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# turn on/off group wiki
if wiki_enabled == 'true':
enable_mod_for_group(group_id, MOD_GROUP_WIKI)
else:
disable_mod_for_group(group_id, MOD_GROUP_WIKI)
except SearpcError as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
group_info = get_group_info(request, group_id)
return Response(group_info)

View File

@@ -10,66 +10,12 @@
<div class="side-tabnav">
<div class="hd w100 ovhd">
<h3 class="fleft">
{% grp_avatar group.props.id 32 %} <span title="{{ group.group_name }}" class="grp-name ellipsis vam">{{ group.group_name }}</span>
{% grp_avatar group.props.id 32 %} <a title="{{ group.group_name }}" class="grp-name ellipsis vam" href="{% url 'group_info' group.id %}">{{ group.group_name }}</a>
</h3>
{% if is_staff %}
<span id="enable-mods" class="sf2-icon-cog2 op-icon fright" title="{% trans "Enable Modules" %}" style="margin:6px 0 0 5px;"></span>
{% endif %}
{% if group.is_pub %}<img src="{{MEDIA_URL}}img/grp_public.png" alt="" title="{% trans "This group is public." %}" class="fright" style="margin:8px 0 0 5px;" />{% endif %}
</div>
<ul class="side-tabnav-tabs">
<li class="tab {% block cur_library %}{% endblock%}"><a href="{{ SITE_ROOT }}#group/{{ group.id }}/"><span class="sf2-icon-library"></span>{% trans "Libraries" %}</a></li>
{% if not group.is_pub %}
<li class="tab {% block cur_discuss %}{% endblock%}"><a href="{% url 'group_discuss' group.id %}"><span class="sf2-icon-msgs"></span>{% trans "Discussion" %}</a></li>
{% endif %}
{% for mod in mods_enabled %}
{% if mod == 'group wiki' %}
<li class="tab {% block cur_wiki %}{%endblock%}"><a href="{% url 'group_wiki' group.id %}"><span class="sf2-icon-wiki"></span>{% trans "Wiki" %}</a></li>
{% endif %}
{% endfor %}
{% if enable_pubfile and group.is_pub %}
<li class="tab {% block cur_pubfile %}{%endblock%}"><a href="{% url 'group_pubfiles' group.id %}"><span class="sf2-icon-file"></span>{% trans "Files" %}</a></li>
{% endif %}
{% if group.view_perm != 'pub' %}
<li class="tab {% block cur_members %}{%endblock%}"><a href="{% url 'group_members' group.id %}"><span class="sf2-icon-user"></span>{% trans "Members" %}</a></li>
{% endif %}
{% if is_staff %}
<li class="tab {% block cur_admin %}{%endblock%}"><a href="{% url 'group_manage' group.id %}"><span class="sf2-icon-wrench"></span>{% trans "Admin" %}</a></li>
{% endif %}
</ul>
</div>
{% endblock %}
{% block main_panel %}
<form id="mods-enable-form" method="post" action="{% url 'group_toggle_modules' group.id %}" class="hide">{% csrf_token%}
<h3>{% trans "Enable Modules"%}</h3>
<ul>
{% for mod in mods_available %}
{% if mod == 'group wiki' %}
<li>
<label class="checkbox-label">
<span class="checkbox {% if mod in mods_enabled %}checkbox-checked{% endif %}"><input type="checkbox" name="group_wiki" class="checkbox-orig" {%if mod in mods_enabled%}checked{% endif%} /></span>
<span class="checkbox-option">{% trans "Wiki" %}</span>
</label>
</li>
{% endif %}
{% endfor %}
</ul>
<input type="submit" value="{% trans "Submit"%}" class="submit" />
</form>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
$('#enable-mods').click(function() {
$('#mods-enable-form').modal({appendTo: "#main"});
$('#simplemodal-container').css('height', 'auto');
return false;
});
</script>
{% endblock %}

View File

@@ -22,10 +22,10 @@
<span id="edit-index" class="icon-pencil fright" title="{% trans "Edit" %}"></span>
{% endif %}
</div>
<div id="wiki-index-con"></div>
{% endif %}
<div id="wiki-index-con"></div>
{% endif %}
</div>
{% endif %}
{% endif %}
{% endblock %}
{% block right_panel %}
@@ -68,10 +68,10 @@
<li class="item{% if page == 'home' %} cur-item{% endif %}"><a href="{% url 'group_wiki' group.id %}" class="link">{% trans "Home" %}</a></li>
<li class="item"><a href="{% url 'group_wiki_pages' group.id %}" class="link">{% trans "Pages" %}</a></li>
{% if group.view_perm != "pub" %}
<li class="item"><a href="{% url 'repo_history' repo_id %}" target="_blank" class="link">{% trans "Wiki History" %}</a></li>
<li class="item"><a href="{% url 'repo_history' repo_id %}" class="link">{% trans "Wiki History" %}</a></li>
{% endif %}
</ul>
{% if repo_perm == 'rw' %}
<button id="page-create" class="op-btn">{% trans "New Page" %}</button>
<button id="page-delete" class="op-btn" data-url="{% url 'group_wiki_page_delete' group.id page %}">{% trans "Delete Page" %}</button>
@@ -117,11 +117,11 @@ $('#wiki-content')
.find('h1, h2').hover(
function() {
$('.anchor', $(this)).removeClass('vh');
},
},
function() {
$('.anchor', $(this)).addClass('vh');
}
);
);
$('#page-create').click(function() {
$('#page-create-form').modal({appendTo: '#main', autoResize: true});
@@ -197,7 +197,7 @@ $('#wiki-create-form').submit(function () {
return false;
});
{% if group_repos %}
{% if group_repos %}
var all_repos = [];
{% for a_repo in group_repos %}
all_repos.push({
@@ -232,7 +232,7 @@ $('#wiki-index-con').html(marked('{{ index_content|escapejs }}'));
location.href = "{% url 'group_wiki_page_edit' group.id page_name %}";
{% endwith %}
});
{% endif %}
{% endif %}
{% else %}
{% if repo_perm == 'rw' %}
$('#create-index').click(function() {
@@ -240,7 +240,7 @@ $('#wiki-index-con').html(marked('{{ index_content|escapejs }}'));
$('[name="page_name"]', form).val('index');
form.submit();
});
{% endif %}
{% endif %}
{% endif %}
{% endif %}
</script>

View File

@@ -11,7 +11,7 @@
<li class="item"><a href="{% url 'group_wiki' group.id %}" class="link">{% trans "Home" %}</a></li>
<li class="item cur-item"><a href="{% url 'group_wiki_pages' group.id %}" class="link">{% trans "Pages" %}</a></li>
{% if group.view_perm != "pub" %}
<li class="item"><a href="{% url 'repo_history' repo_id %}" target="_blank" class="link">{% trans "Wiki History" %}</a></li>
<li class="item"><a href="{% url 'repo_history' repo_id %}" class="link">{% trans "Wiki History" %}</a></li>
{% endif %}
</ul>
{% if repo_perm == 'rw' %}

View File

@@ -672,7 +672,10 @@
{% endif %}
<div class="fright">
<span class="sf2-icon-group-settings op-icon" title="{% trans "Settings" %}" id="group-settings-icon"></span>
<% if (wiki_enabled) { %>
<span class="sf2-icon-wiki2 op-icon" title="{% trans "Wiki" %}" id="group-wiki-icon"></span>
<% } %>
<span class="sf2-icon-cog1 op-icon" title="{% trans "Settings" %}" id="group-settings-icon"></span>
<span class="sf2-icon-user2 op-icon" title="{% trans "Members" %}" id="group-members-icon"></span>
<span class="sf2-icon-msgs2 op-icon" title="{% trans "Discussion" %}"></span>
</div>
@@ -732,7 +735,7 @@
</select>
</td>
<td>
<span class="sf2-icon-delete delete-icon op-icon vh" title="{% trans "Delete" %}"></span>
<span class="sf2-icon-delete delete-icon op-icon vh" title="{% trans "Delete" %}"></span>
</td>
</script>
<script type="text/template" id="folder-perm-popup-tmpl">
@@ -802,7 +805,7 @@
<td><%- repo_name %></td>
<td><%= mtime_relative %></td>
<td>
<span class="sf2-icon-delete unstar op-icon vh" title="{% trans "Unstar" %}"></span>
<span class="sf2-icon-delete unstar op-icon vh" title="{% trans "Unstar" %}"></span>
</td>
</script>
<script type="text/template" id="my-repos-hd-tmpl">
@@ -944,6 +947,11 @@
<ul class="group-setting-list">
<li class="group-setting-item" data-op="rename">{% trans "Rename" %}</li>
<li class="group-setting-item" data-op="transfer">{% trans "Transfer" %}</li>
<% if (!wiki_enabled) { %>
<li class="group-setting-item" data-op="add-wiki">{% trans "Add Wiki" %}</li>
<% } else { %>
<li class="group-setting-item" data-op="remove-wiki">{% trans "Remove Wiki" %}</li>
<% } %>
</ul>
<ul class="group-setting-list">
<li class="group-setting-item" data-op="import-members">{% trans "Import Members" %}</li>
@@ -955,6 +963,11 @@
<% } else if (is_admin) { %>
<ul class="group-setting-list">
<li class="group-setting-item" data-op="rename">{% trans "Rename" %}</li>
<% if (!wiki_enabled) { %>
<li class="group-setting-item" data-op="add-wiki">{% trans "Add Wiki" %}</li>
<% } else { %>
<li class="group-setting-item" data-op="remove-wiki">{% trans "Remove Wiki" %}</li>
<% } %>
</ul>
<ul class="last-group-setting-list">
<li class="group-setting-item" data-op="import-members">{% trans "Import Members" %}</li>
@@ -972,7 +985,7 @@
<input type="text" name="new_name" value="" class="input" /><br />
<p class="error hide"></p>
<input type="submit" value="{% trans "Submit" %}" />
</form>
</form>
</script>
<script type="text/template" id="group-transfer-form-tmpl">
<form method="post" action="">
@@ -980,7 +993,7 @@
<input type="hidden" name="email" /><br />
<p class="error hide"></p>
<input type="submit" value="{% trans "Submit" %}" />
</form>
</form>
</script>
<script type="text/template" id="group-import-members-form-tmpl">
<form enctype="multipart/form-data" method="post" action="">

View File

@@ -167,9 +167,7 @@
<h3 class="popover-title">{% trans "Settings" %}</h3>
</div>
<div class="popover-con">
<span class="loading-icon loading-tip"></span>
<div id="group-setting-con" class="hide"></div>
<p class="error hide"></p>
</div>
</div>

View File

@@ -12,7 +12,7 @@ def get_available_mods_by_user(username):
"""
mods_available = [MOD_PERSONAL_WIKI, ]
return mods_available
def get_enabled_mods_by_user(username):
"""Returns a list of enabled modules for user.
"""
@@ -23,7 +23,7 @@ def get_enabled_mods_by_user(username):
if personal_wiki_enabled:
mod_enabled.append(MOD_PERSONAL_WIKI)
return mod_enabled
def enable_mod_for_user(username, mod_name):
@@ -43,7 +43,7 @@ def get_available_mods_by_group(group_id):
"""
mods_available = [MOD_GROUP_WIKI, ]
return mods_available
def get_enabled_mods_by_group(group_id):
"""Returns a list of enabled modules for group.
"""
@@ -56,6 +56,14 @@ def get_enabled_mods_by_group(group_id):
mod_enabled.append(MOD_GROUP_WIKI)
return mod_enabled
def is_wiki_mod_enabled_for_group(group_id):
group_wiki_enabled = GroupEnabledModule.objects.filter(
group_id=group_id, module_name=MOD_GROUP_WIKI).exists()
if group_wiki_enabled:
return True
else:
return False
def enable_mod_for_group(group_id, mod_name):
if mod_name != MOD_GROUP_WIKI:
raise BadModNameError
@@ -78,4 +86,3 @@ def get_wiki_enabled_group_list(in_group_ids=None):
if in_group_ids is not None:
qs = qs.filter(group_id__in=in_group_ids)
return qs

View File

@@ -26,7 +26,6 @@ define([
'group/:group_id/': 'showGroupRepos',
'group/:group_id/lib/:repo_id(/*path)': 'showGroupRepoDir',
'group/:group_id/members/': 'showGroupMembers',
'group/:group_id/settings/': 'showGroupSettings',
'org/': 'showOrgRepos',
'org/lib/:repo_id(/*path)': 'showOrgRepoDir',
'common/lib/:repo_id(/*path)': 'showCommonDir',
@@ -190,11 +189,6 @@ define([
this.groupView.showMembers();
},
showGroupSettings: function(group_id) {
this.showGroupRepos(group_id);
this.groupView.showSettings();
},
showOrgRepos: function() {
this.switchCurrentView(this.orgView);
this.orgView.showRepoList();

View File

@@ -21,9 +21,7 @@ define([
// group basic info
this.group = {};
this.$loadingTip = this.$('.loading-tip');
this.$listContainer = $('#group-setting-con');
this.$error = this.$('.error');
this.$listContainer = $('#group-setting-con');
var _this = this;
$(window).resize(function() {
@@ -39,7 +37,7 @@ define([
!$popup.find('*').is(target) &&
!$popup_switch.is(target)) {
_this.hide();
}
}
});
},
@@ -51,49 +49,22 @@ define([
},
render: function() {
this.$error.hide();
this.$listContainer.hide();
this.$loadingTip.show();
// the user's role in this group
this.is_owner = false,
this.is_admin = false;
var _this = this;
$.ajax({
url: Common.getUrl({
'name': 'group',
'group_id': this.group.id
}),
cache: false,
dataType: 'json',
success: function(data) {
_this.group = data; // {id, name, owner, created_at, avatar_url, admins}
var username = app.pageOptions.username;
if (username == _this.group.owner) {
_this.is_owner = true;
} else if ($.inArray(username, _this.group.admins) != -1) {
_this.is_admin = true;
}
_this.$listContainer.html(_this.template({
'is_owner': _this.is_owner,
'is_admin': _this.is_admin
})).show();
},
error: function(xhr) {
var err_msg;
if (xhr.responseText) {
err_msg = gettext('Error');
} else {
err_msg = gettext("Please check the network.");
}
_this.$error.html(err_msg).show();
},
complete: function() {
_this.$loadingTip.hide();
}
});
if (app.pageOptions.username == this.group.owner) {
this.is_owner = true;
} else if ($.inArray(app.pageOptions.username, this.group.admins) != -1) {
this.is_admin = true;
}
this.$listContainer.html(this.template({
'is_owner': this.is_owner,
'is_admin': this.is_admin,
'wiki_enabled': this.group.wiki_enabled
})).show();
},
// set max-height for '.popover-con'
@@ -102,16 +73,14 @@ define([
},
show: function(options) {
this.group.id = options.group_id;
this.group = options.group;
this.$el.show();
this.setConMaxHeight();
this.render();
app.router.navigate('group/' + this.group.id + '/settings/');
this.setConMaxHeight();
},
hide: function() {
this.$el.hide();
app.router.navigate('group/' + this.group.id + '/');
},
highlightItem: function(e) {
@@ -130,6 +99,12 @@ define([
case 'transfer':
this.transfer();
break;
case 'add-wiki':
this.toggleWiki('on');
break;
case 'remove-wiki':
this.toggleWiki('off');
break;
case 'import-members':
this.importMembers();
break;
@@ -153,7 +128,7 @@ define([
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
$form.submit(function() {
var new_name = $.trim($('[name="new_name"]', $(this)).val());
var new_name = $.trim($('[name="new_name"]', $(this)).val());
if (!new_name || new_name == _this.group.name) {
return false;
}
@@ -161,12 +136,12 @@ define([
Common.disableButton($submitBtn);
$.ajax({
url: Common.getUrl({
'name': 'group',
'name': 'group',
'group_id': _this.group.id
}),
type: 'put',
dataType: 'json',
beforeSend: Common.prepareCSRFToken,
beforeSend: Common.prepareCSRFToken,
data: {
'name': new_name
},
@@ -218,12 +193,12 @@ define([
Common.disableButton($submitBtn);
$.ajax({
url: Common.getUrl({
'name': 'group',
'name': 'group',
'group_id': _this.group.id
}),
type: 'put',
dataType: 'json',
beforeSend: Common.prepareCSRFToken,
beforeSend: Common.prepareCSRFToken,
data: {
'owner': email
},
@@ -246,6 +221,44 @@ define([
});
},
toggleWiki: function(status) {
var _this = this;
var wiki_enabled;
if (status == 'on') {
wiki_enabled = 'true';
} else {
wiki_enabled = 'false';
}
$.ajax({
url: Common.getUrl({
'name': 'group',
'group_id': _this.group.id
}),
type: 'put',
dataType: 'json',
beforeSend: Common.prepareCSRFToken,
data: {
'wiki_enabled': wiki_enabled
},
success: function() {
_this.hide();
_this.groupView.renderGroupTop();
},
error: function(xhr) {
var error_msg;
if (xhr.responseText) {
error_msg = $.parseJSON(xhr.responseText).error_msg;
} else {
error_msg = gettext("Failed. Please check the network.");
}
Common.feedback(error_msg, 'error');
_this.hide();
}
});
},
importMembers: function() {
var _this = this;
var $form = $(this.importMembersTemplate());
@@ -264,12 +277,12 @@ define([
Common.disableButton($submitBtn);
var file = $fileInput.files[0];
var formData = new FormData();
var formData = new FormData();
formData.append('file', file);
$.ajax({
url: Common.getUrl({
'name': 'group_import_members',
'group_id': _this.group.id
'group_id': _this.group.id
}),
type: 'post',
dataType: 'json',
@@ -320,12 +333,12 @@ define([
var yesCallback = function () {
$.ajax({
url: Common.getUrl({
'name': 'group',
'name': 'group',
'group_id': _this.group.id
}),
type: 'delete',
dataType: 'json',
beforeSend: Common.prepareCSRFToken,
beforeSend: Common.prepareCSRFToken,
success: function() {
app.ui.sideNavView.updateGroups();
app.router.navigate('groups/', {trigger: true});

View File

@@ -21,6 +21,7 @@ define([
events: {
'click #group-settings-icon': 'toggleSettingsPanel',
'click #group-members-icon': 'toggleMembersPanel',
'click #group-wiki-icon': 'showGroupWiki',
'click .repo-create': 'createRepo',
'click .by-name': 'sortByName',
'click .by-time': 'sortByTime'
@@ -34,6 +35,8 @@ define([
this.$loadingTip = this.$('#group-repos .loading-tip');
this.$emptyTip = this.$('#group-repos .empty-tips');
this.group = {}; // will be fetched when rendering the top bar
this.repos = new GroupRepos();
this.listenTo(this.repos, 'add', this.addOne);
this.listenTo(this.repos, 'reset', this.reset);
@@ -42,7 +45,6 @@ define([
this.membersView = new GroupMembersView();
this.settingsView = new GroupSettingsView({
sideNavView: options.sideNavView,
groupView: this
});
},
@@ -90,6 +92,7 @@ define([
cache: false,
dataType: 'json',
success: function (data) {
_this.group = data;
$groupTop.html(_this.groupTopTemplate(data));
},
error: function(xhr) {
@@ -120,7 +123,7 @@ define([
reset: true,
data: {from: 'web'},
success: function (collection, response, opts) {
},
},
error: function (collection, response, opts) {
$loadingTip.hide();
var $error = _this.$('.error');
@@ -206,7 +209,7 @@ define([
showSettings: function() {
this.settingsView.show({
'group_id': this.group_id
'group': this.group
});
},
@@ -219,6 +222,10 @@ define([
}
},
showGroupWiki: function() {
location.href = '/group/' + this.group.id + '/wiki/';
},
showMembers: function() {
this.membersView.show({'group_id': this.group_id});
},

View File

@@ -32,7 +32,7 @@ class GroupsTest(BaseTestCase):
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert len(json_resp[0]) == 6
assert len(json_resp[0]) == 7
group_ids = []
for group in json_resp:
@@ -45,7 +45,7 @@ class GroupsTest(BaseTestCase):
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert len(json_resp[0]) == 7
assert len(json_resp[0]) == 8
group_ids = []
group_repos = []
@@ -68,7 +68,7 @@ class GroupsTest(BaseTestCase):
self.assertEqual(201, resp.status_code)
json_resp = json.loads(resp.content)
assert len(json_resp) == 6
assert len(json_resp) == 7
assert json_resp['name'] == new_group_name
assert json_resp['owner'] == self.user.email
@@ -80,7 +80,7 @@ class GroupsTest(BaseTestCase):
self.assertEqual(201, resp.status_code)
json_resp = json.loads(resp.content)
assert len(json_resp) == 6
assert len(json_resp) == 7
assert json_resp['name'] == new_group_name
assert json_resp['owner'] == self.user.email