1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-02 07:47:32 +00:00

Show group recent changes

This commit is contained in:
zhengxie 2015-01-29 14:45:26 +08:00 committed by Daniel Pan
parent 7920f11b41
commit e80a1dfbdb
11 changed files with 339 additions and 58 deletions

View File

@ -0,0 +1,19 @@
define([
'underscore',
'backbone',
'app/models/group-change'
], function(_, Backbone, GroupChange) {
'use strict';
var GroupChangeCollection = Backbone.Collection.extend({
model: GroupChange,
url: app.pageOptions.groupChangesUrl,
initialize: function() {
}
});
return new GroupChangeCollection();
});

View File

@ -0,0 +1,10 @@
define([
'underscore',
'backbone'
], function(_, Backbone) {
'use strict';
var GroupChange = Backbone.Model.extend({});
return GroupChange;
});

View File

@ -11,20 +11,30 @@ define([
routes: {
'libs/:id(/*path)': 'showDirents',
'recent-changes': 'showRecentChanges',
// Default
'*actions': 'defaultAction'
},
initialize: function() {
this.groupView = new GroupView();
},
showDirents: function(id, path){
console.log("Repo route has been called.." + "id:" + id + " path:" + path);
// new GroupView().showDirentList(id, path);
},
showRecentChanges: function() {
console.log('recent changes');
this.groupView.showChanges();
},
defaultAction: function(actions){
// We have no matching route, lets just log what the URL was
console.log('No route:', actions);
new GroupView().showRepoList();
this.groupView.showRepoList();
}
});

View File

@ -0,0 +1,81 @@
define([
'jquery',
'underscore',
'backbone',
'common',
'text!' + app.config._tmplRoot + 'group-change-item.html'
], function($, _, Backbone, Common, changeItemTemplate) {
'use strict';
var GroupChangeItemView = Backbone.View.extend({
tagName: 'tr',
template: _.template(changeItemTemplate),
events: {
'click .lsch': 'showDetail'
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
showDetail: function() {
console.log(this.model);
// TODO: if repo is encrypted, and not set password, show decrypt
// form, else show details
var model = this.model;
var url = app.config.siteRoot + 'ajax/repo/' + model.get("repo").id + '/history/changes/' + "?commit_id=" + model.get("id");
var loadingHtml = '<div id="ls-ch"><img src="'+ app.config.mediaUrl + 'img/loading-icon.gif" alt="" style="margin-top:30px;" /></div>';
$.modal(loadingHtml, {autoResize:true});
$('#ls-ch').css('text-align', 'center');
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
$.ajax({
url: url,
dataType: 'json',
cache: false,
success: function(data) {
var heading = '<h3>' + "Modification Details" + '</h3>';
var time = '<p class="commit-time">' + model.get("ctime") + '</p>';
var con = '';
function show(data_, hd) {
if (data_.length > 0) {
con += '<h4>' + hd + '</h4>';
con += '<ul>';
for (var i = 0, len = data_.length; i < len; i++) {
con += '<li>' + data_[i] + '</li>';
}
con += '</ul>';
}
}
show(data['new'], "New files");
show(data['removed'], "Deleted files");
show(data['renamed'], "Renamed or Moved files");
show(data['modified'], "Modified files");
show(data['newdir'], "New directories");
show(data['deldir'], "Deleted directories");
if (!con) {
if (data['cmt_desc']) {
con = '<p>' + Common.HTMLescape(data['cmt_desc']) + '</p>';
}
}
$('#ls-ch').css('text-align','left').html(heading + time + con);
$(window).resize();
},
error: function() {
$('#ls-ch').html("Unknown error.");
setTimeout(function() { $.modal.close(); }, 2500);
}
});
}
});
return GroupChangeItemView;
});

View File

@ -0,0 +1,94 @@
define([
'jquery',
'underscore',
'backbone',
'common',
'app/collections/group-changes',
'app/views/group-change-items'
], function($, _, Backbone, Common, RecentChanges, GroupChangeItemView) {
'use strict';
var GroupRecentChangeView = Backbone.View.extend({
el: '#grp-repos-commits',
initialize: function() {
this.$cont = this.$el;
this.$table = $('table', this.$el);
this.$tableHead = $('thead', this.$table);
this.$tableBody = $('tbody', this.$table);
this.listenTo(RecentChanges, 'add', this.addOne);
this.listenTo(RecentChanges, 'reset', this.addAll);
this.listenTo(RecentChanges, 'error', this.error);
this.listenTo(RecentChanges, 'all', this.render); // XXX: really render table when recieve any event ?
},
error: function(model_or_collection, resp, options) {
Common.feedback(resp.statusText, "error", Common.ERROR_TIMEOUT);
},
all: function(event) {
console.log('event: ' + event);
},
addOne: function(change, collection, options) {
console.log('add one change');
var view = new GroupChangeItemView({model: change});
if (options.prepend) {
this.$tableBody.before(view.render().el);
} else {
this.$tableBody.append(view.render().el);
}
},
addAll: function() {
console.log('add all');
this.resetTable();
RecentChanges.each(this.addOne, this);
},
// Reset table by empty table body.
resetTable: function() {
console.log('reset table');
this.$tableBody.empty();
},
show: function() {
RecentChanges.fetch({reset: true});
},
render: function(event) {
console.log('got event: ' + event + ', render change list...' );
this.$table.parent().show();
this.hideLoading();
if (RecentChanges.length) {
this.showTable();
} else {
this.hideTable();
}
},
hideTable: function() {
this.$table.hide();
},
showTable: function() {
this.$table.show();
},
hideLoading: function() {
this.$cont.find('.loading').hide();
},
showLoading: function() {
this.$cont.find('.loading').show();
},
});
return GroupRecentChangeView;
});

View File

@ -6,9 +6,10 @@ define([
'app/collections/group-repos',
'app/collections/dirents',
'app/views/group-repos',
'app/views/add-group-repo'
'app/views/add-group-repo',
'app/views/group-recent-change'
// 'app/views/dirents'
], function($, _, Backbone, Common, Repos, DirentCollection, GroupRepoView, AddGroupRepoView/*, DirentView*/) {
], function($, _, Backbone, Common, Repos, DirentCollection, GroupRepoView, AddGroupRepoView/*, DirentView*/, GroupRecentChangeView) {
'use strict';
var GroupView = Backbone.View.extend({
@ -24,7 +25,6 @@ define([
this.$cont = this.$('#right-panel');
this.$tab = this.$('#tabs div:first-child');
this.$tabCont = this.$('#grp-repos');
this.$table = this.$('#grp-repos table');
this.$tableHead = $('thead', this.$table);
@ -38,6 +38,7 @@ define([
this.listenTo(Repos, 'reset', this.addAll);
// this.listenTo(Repos, 'sync', this.render);
this.listenTo(Repos, 'all', this.render); // XXX: really render table when recieve any event ?
this.listenTo(Repos, 'all', this.all);
},
all: function(event) {
@ -93,7 +94,9 @@ define([
render: function(event) {
console.log('got event: ' + event + ', render repo list...' );
this.$table.parent().show();
this.hideLoading();
if (Repos.length) {
this.hideEmptyTips();
this.showTable();
@ -110,6 +113,15 @@ define([
createRepo: function() {
new AddGroupRepoView();
},
showChanges: function() {
this.$table.parent().hide(); // XXX: hide or empty ?
if (!this.recentChangeView) {
this.recentChangeView = new GroupRecentChangeView();
}
this.recentChangeView.show();
}
});

View File

@ -207,6 +207,13 @@ define([
});
},
HTMLescape: function(html){
return document.createElement('div')
.appendChild(document.createTextNode(html))
.parentNode
.innerHTML;
},
pathJoin: function(array) {
var result = array[0];
for (var i = 1; i < array.length; i++) {
@ -216,7 +223,7 @@ define([
result += '/' + array[i];
}
return result;
},
}
}
});

View File

@ -70,6 +70,7 @@ urlpatterns = patterns('',
url(r'^groups/$', Groups.as_view()),
url(r'^groups/(?P<group_id>\d+)/$', Groups.as_view()),
url(r'^groups/(?P<group_id>\d+)/members/$', GroupMembers.as_view()),
url(r'^groups/(?P<group_id>\d+)/changes/$', GroupChanges.as_view(), name="api2-group-changes"),
url(r'^groups/(?P<group_id>\d+)/repos/$', GroupRepos.as_view(), name="api2-grouprepos"),
url(r'^groups/(?P<group_id>\d+)/repos/(?P<repo_id>[-0-9a-f]{36})/$', GroupRepo.as_view()),

View File

@ -44,7 +44,8 @@ from seahub.avatar.templatetags.group_avatar_tags import api_grp_avatar_url, \
grp_avatar
from seahub.base.accounts import User
from seahub.base.models import FileDiscuss, UserStarredFiles, DeviceToken
from seahub.base.templatetags.seahub_tags import email2nickname
from seahub.base.templatetags.seahub_tags import email2nickname, \
translate_commit_desc, translate_seahub_time
from seahub.group.models import GroupMessage, MessageReply, MessageAttachment
from seahub.group.signals import grpmsg_added, grpmsg_reply_added
from seahub.group.views import group_check, remove_group_common, \
@ -2856,6 +2857,71 @@ class GroupMembers(APIView):
return HttpResponse(json.dumps({'success': True}), status=200, content_type=json_content_type)
class GroupChanges(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)
throttle_classes = (UserRateThrottle, )
def get(self, request, group_id, format=None):
# TODO: group check
# TODO: perm check
group_id = int(group_id)
username = request.user.username
if is_org_context(request):
org_id = request.user.org.org_id
repos = seaserv.get_org_group_repos(org_id, group_id, username)
else:
repos = seaserv.get_group_repos(group_id, username)
recent_commits = []
cmt_repo_dict = {}
for repo in repos:
repo.user_perm = check_permission(repo.props.id, username)
cmmts = get_commits(repo.props.id, 0, 10)
for c in cmmts:
cmt_repo_dict[c.id] = repo
recent_commits += cmmts
recent_commits.sort(lambda x, y: cmp(y.props.ctime, x.props.ctime))
recent_commits = recent_commits[:15]
for cmt in recent_commits:
cmt.repo = cmt_repo_dict[cmt.id]
cmt.repo.password_set = is_passwd_set(cmt.props.repo_id, username)
cmt.tp = cmt.props.desc.split(' ')[0]
res = []
for c in recent_commits:
cmt_tp = c.tp.lower()
if 'add' in cmt_tp:
change_tp = 'added'
elif ('delete' or 'remove') in cmt_tp:
change_tp = 'deleted'
else:
change_tp = 'modified'
change_repo = {
'id': c.repo.id,
'name': c.repo.name,
'desc': c.repo.desc,
'encrypted': c.repo.encrypted,
}
change = {
"type": change_tp,
"repo": change_repo,
"id": c.id,
"desc": c.desc,
"desc_human": translate_commit_desc(c.desc),
"ctime": c.ctime,
"ctime_human": translate_seahub_time(c.ctime),
"creator": c.creator_name,
"creator_nickname": email2nickname(c.creator_name)
}
res.append(change)
return Response(res)
class GroupRepos(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated,)

View File

@ -65,16 +65,18 @@
<div id="tabs" class="tab-tabs">
<div class="hd ovhd">
<ul class="tab-tabs-nav fleft">
<li class="tab"><a href="#grp-repos" class="a">{% trans "Libraries" %}</a></li>
<li class="tab long-tab"><a href="#grp-repos-commits" class="a">{% trans "Recent Changes" %}</a></li>
<li class="tab"><a href="{% url 'group_info' group.id %}" class="a">{% trans "Libraries" %}</a></li>
<li class="tab long-tab"><a href="#/recent-changes" class="a">{% trans "Recent Changes" %}</a></li>
</ul>
{% if user.permissions.can_add_repo %}
<button id="repo-create" class="fright"><img src="{{ MEDIA_URL }}img/add.png" alt="" class="add vam" /><span class="vam">{% trans "New Library" %}</span></button>
{% endif %}
</div>
<div id="grp-repos">
<p class="loading">{% trans "Loading ..." %}</p>
<table style="display:none">
<thead>
<tr>
@ -97,54 +99,19 @@
</div>
<div id="grp-repos-commits" class="hide">
{% if recent_commits|length > 0 %}
<table>
<tr>
<th width="5%"></th>
<th width="17%">{% trans "Library" %}</th>
<th width="48%">{% trans "Description" %}</th>
<th width="15%">{% trans "Modified at" %}</th>
<th width="15%">{% trans "Modifier" %}</th>
</tr>
{% for cmt in recent_commits %}
<tr>
<td>
{% if cmt.tp == 'Added' or cmt.tp == 'Deleted' or cmt.tp == 'Removed' %}
{% if cmt.tp == 'Added' %}
<span class="icon-plus"></span>
{% else %}
<span class="icon-minus"></span>
{% endif %}
{% else %}
<span class="icon-pencil"></span>
{% endif %}
</td>
<td><a href="{{ SITE_ROOT }}repo/{{ cmt.repo.props.id }}/">{{ cmt.repo.props.name }}</a></td>
<td>
{{cmt.props.desc|translate_commit_desc}}
{% if cmt.repo.encrypted %}
<a class="lsch-encrypted"{% if cmt.repo.password_set %} data-passwordset="true"{% endif %} href="#" data-url="{% url 'repo_history_changes' cmt.repo.id %}?commit_id={{ cmt.id }}" data-repoid="{{cmt.repo.id}}" data-reponame="{{cmt.repo.name}}" data-time="{{ cmt.props.ctime|tsstr_sec }}">{% trans 'Details' %}</a>
{% else %}
<a class="lsch" href="#" data-url="{% url 'repo_history_changes' cmt.repo.id %}?commit_id={{ cmt.id }}" data-time="{{ cmt.props.ctime|tsstr_sec }}">{% trans 'Details' %}</a>
{% endif %}
</td>
<td>{{cmt.props.ctime|translate_seahub_time}}</td>
<td>
{% if cmt.creator_name %}
{% if cmt.second_parent_id %}
{% trans "None" %}
{% else %}
{{cmt.creator_name|email2nickname}}
{% endif %}
{% else %}
{% trans "Unknown"%}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
<p class="loading">{% trans "Loading ..." %}</p>
<table class="hide">
<thead>
<tr>
<th width="5%"></th>
<th width="17%">{% trans "Library" %}</th>
<th width="48%">{% trans "Description" %}</th>
<th width="15%">{% trans "Modified at" %}</th>
<th width="15%">{% trans "Modifier" %}</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
@ -170,6 +137,7 @@
app["pageOptions"] = {
groupId: {{ group.id }},
groupReposUrl: "{% url "api2-grouprepos" group.id %}",
groupChangesUrl: "{% url "api2-group-changes" group.id %}",
isGroupStaff: (function() {
if ("{{ is_staff }}" == "True")
return true;

View File

@ -0,0 +1,13 @@
{% load i18n %}
<td>
<span class="icon-plus"></span>
</td>
<td><a href="#"><%= repo.name %></a></td>
<td>
<%= desc_human %>
<a class="lsch" >{% trans 'Details' %}</a>
</td>
<td><%= ctime_human %></td>
<td>
<%- creator_nickname %>
</td>