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:
parent
7920f11b41
commit
e80a1dfbdb
19
media/scripts/app/collections/group-changes.js
Normal file
19
media/scripts/app/collections/group-changes.js
Normal 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();
|
||||
});
|
10
media/scripts/app/models/group-change.js
Normal file
10
media/scripts/app/models/group-change.js
Normal file
@ -0,0 +1,10 @@
|
||||
define([
|
||||
'underscore',
|
||||
'backbone'
|
||||
], function(_, Backbone) {
|
||||
'use strict';
|
||||
|
||||
var GroupChange = Backbone.Model.extend({});
|
||||
|
||||
return GroupChange;
|
||||
});
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
|
81
media/scripts/app/views/group-change-items.js
Normal file
81
media/scripts/app/views/group-change-items.js
Normal 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;
|
||||
});
|
94
media/scripts/app/views/group-recent-change.js
Normal file
94
media/scripts/app/views/group-recent-change.js
Normal 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;
|
||||
});
|
@ -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();
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -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;
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -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()),
|
||||
|
||||
|
@ -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,)
|
||||
|
@ -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;
|
||||
|
13
seahub/templates/js/group-change-item.html
Normal file
13
seahub/templates/js/group-change-item.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user