mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +02:00
document activity log
This commit is contained in:
parent
d91811bb3d
commit
96e4b2058c
9 changed files with 182 additions and 96 deletions
|
@ -13,64 +13,12 @@ import Ember from 'ember';
|
|||
|
||||
export default Ember.Component.extend({
|
||||
documentService: Ember.inject.service('document'),
|
||||
appMeta: Ember.inject.service(),
|
||||
sortedItems: [],
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.get('documentService').getMeta(this.get('document.id')).then((activity) => {
|
||||
this.get('documentService').getActivity(this.get('document.id')).then((activity) => {
|
||||
this.set('activity', activity);
|
||||
|
||||
let editors = this.get('activity.editors');
|
||||
let viewers = this.get('activity.viewers');
|
||||
let pages = this.get('pages');
|
||||
let sorted = [];
|
||||
|
||||
if (is.null(editors)) {
|
||||
editors = [];
|
||||
}
|
||||
|
||||
if (is.null(viewers)) {
|
||||
viewers = [];
|
||||
}
|
||||
|
||||
viewers.forEach((item) => {
|
||||
Ember.set(item, 'changeLabel', "viewed");
|
||||
Ember.set(item, "viewed", true);
|
||||
sorted.pushObject({ date: item.created, item: item });
|
||||
});
|
||||
|
||||
editors.forEach(function (item) {
|
||||
Ember.set(item, "added", item.action === "add-page");
|
||||
Ember.set(item, "changed", item.action === "update-page");
|
||||
Ember.set(item, "deleted", item.action === "remove-page");
|
||||
|
||||
let page = pages.findBy('id', item.pageId);
|
||||
let title = "";
|
||||
|
||||
if (item.deleted || is.undefined(page)) {
|
||||
title = "removed section";
|
||||
} else {
|
||||
if (item.added) {
|
||||
title = "added " + page.get('title');
|
||||
}
|
||||
|
||||
if (item.changed) {
|
||||
title = "changed " + page.get('title');
|
||||
}
|
||||
}
|
||||
|
||||
Ember.set(item, 'changeLabel', title);
|
||||
|
||||
let exists = sorted.findBy('item.pageId', item.pageId);
|
||||
|
||||
if (is.undefined(exists)) {
|
||||
sorted.pushObject({ date: item.created, item: item });
|
||||
}
|
||||
});
|
||||
|
||||
this.set('sortedItems', _.sortBy(sorted, 'date').reverse());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
103
app/app/models/document-activity.js
Normal file
103
app/app/models/document-activity.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Model from 'ember-data/model';
|
||||
import attr from 'ember-data/attr';
|
||||
import Ember from 'ember';
|
||||
import constants from '../utils/constants';
|
||||
|
||||
export default Model.extend({
|
||||
orgId: attr('string'),
|
||||
folderId: attr('string'),
|
||||
documentId: attr('string'),
|
||||
userId: attr('string'),
|
||||
firstname: attr('string'),
|
||||
lastname: attr('string'),
|
||||
activityType: attr('number'),
|
||||
created: attr(),
|
||||
|
||||
activityLabel: Ember.computed('activityType', function() {
|
||||
let label = '';
|
||||
|
||||
switch (this.get('activityType')) {
|
||||
case constants.UserActivityType.Created:
|
||||
label = 'Added';
|
||||
break;
|
||||
case constants.UserActivityType.Read:
|
||||
label = 'Viewed';
|
||||
break;
|
||||
case constants.UserActivityType.Edited:
|
||||
label = 'Edited';
|
||||
break;
|
||||
case constants.UserActivityType.Deleted:
|
||||
label = 'Deleted';
|
||||
break;
|
||||
case constants.UserActivityType.Archived:
|
||||
label = 'Archived';
|
||||
break;
|
||||
case constants.UserActivityType.Approved:
|
||||
label = 'Approved';
|
||||
break;
|
||||
case constants.UserActivityType.Reverted:
|
||||
label = 'Reverted';
|
||||
break;
|
||||
case constants.UserActivityType.PublishedTemplate:
|
||||
label = 'Published Template';
|
||||
break;
|
||||
case constants.UserActivityType.PublishedBlock:
|
||||
label = 'Published Block';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return label;
|
||||
}),
|
||||
|
||||
activityColor: Ember.computed('activityType', function() {
|
||||
let color = '';
|
||||
|
||||
switch (this.get('activityType')) {
|
||||
case constants.UserActivityType.Created:
|
||||
color = 'color-blue';
|
||||
break;
|
||||
case constants.UserActivityType.Read:
|
||||
color = 'color-black';
|
||||
break;
|
||||
case constants.UserActivityType.Edited:
|
||||
color = 'color-green';
|
||||
break;
|
||||
case constants.UserActivityType.Deleted:
|
||||
color = 'color-red';
|
||||
break;
|
||||
case constants.UserActivityType.Archived:
|
||||
color = 'color-gray';
|
||||
break;
|
||||
case constants.UserActivityType.Approved:
|
||||
color = 'color-green';
|
||||
break;
|
||||
case constants.UserActivityType.Reverted:
|
||||
color = 'color-red';
|
||||
break;
|
||||
case constants.UserActivityType.PublishedTemplate:
|
||||
color = 'color-blue';
|
||||
break;
|
||||
case constants.UserActivityType.PublishedBlock:
|
||||
color = 'color-blue';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return color;
|
||||
})
|
||||
|
||||
});
|
|
@ -208,12 +208,19 @@ export default Ember.Service.extend({
|
|||
},
|
||||
|
||||
// document meta referes to number of views, edits, approvals, etc.
|
||||
getMeta(documentId) {
|
||||
return this.get('ajax').request(`documents/${documentId}/meta`, {
|
||||
getActivity(documentId) {
|
||||
return this.get('ajax').request(`documents/${documentId}/activity`, {
|
||||
method: "GET"
|
||||
}).then((response) => {
|
||||
return response;
|
||||
let data = [];
|
||||
data = response.map((obj) => {
|
||||
let data = this.get('store').normalize('documentActivity', obj);
|
||||
return this.get('store').push(data);
|
||||
});
|
||||
|
||||
return data;
|
||||
}).catch(() => {
|
||||
return [];
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -2,26 +2,13 @@
|
|||
<div class="title">Activity</div>
|
||||
<div class="document-sidebar-view-activity">
|
||||
<ul class="items">
|
||||
{{#each sortedItems as |e|}}
|
||||
{{#each activity as |a|}}
|
||||
<li class="item">
|
||||
<div class="avatar-box">
|
||||
<div class="avatar">{{user-initials e.item.firstname e.item.lastname}}</div>
|
||||
</div>
|
||||
<div class="name">{{e.item.firstname}} {{e.item.lastname}}, {{time-ago e.date}}</div>
|
||||
<div class="detail">
|
||||
{{#if e.item.deleted}}
|
||||
<div class="deleted">{{e.item.changeLabel}}</div>
|
||||
{{/if}}
|
||||
{{#if e.item.changed}}
|
||||
<div class="changed">{{e.item.changeLabel}}</div>
|
||||
{{/if}}
|
||||
{{#if e.item.added}}
|
||||
<div class="added">{{e.item.changeLabel}}</div>
|
||||
{{/if}}
|
||||
{{#if e.item.viewed}}
|
||||
<div class="viewed">{{e.item.changeLabel}}</div>
|
||||
{{/if}}
|
||||
<div class="avatar">{{user-initials a.firstname a.lastname}}</div>
|
||||
</div>
|
||||
<div class="name">{{a.firstname}} {{a.lastname}}</div>
|
||||
<div class="detail {{a.activityColor}}">{{a.activityLabel}}, {{time-ago a.created}}</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
|
|
@ -26,5 +26,18 @@ export default {
|
|||
Feedback: 2,
|
||||
Contribute: 3,
|
||||
Approve: 4
|
||||
}
|
||||
},
|
||||
|
||||
UserActivityType: {
|
||||
Created: 1,
|
||||
Read: 2,
|
||||
Edited: 3,
|
||||
Deleted: 4,
|
||||
Archived: 5,
|
||||
Approved: 6,
|
||||
Reverted: 7,
|
||||
PublishedTemplate: 8,
|
||||
PublishedBlock: 9,
|
||||
Feedback: 10
|
||||
}
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/documize/community/core/log"
|
||||
"github.com/documize/community/core/utility"
|
||||
|
||||
"github.com/documize/community/core/api/util"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
|
@ -126,39 +127,25 @@ func GetDocument(w http.ResponseWriter, r *http.Request) {
|
|||
writeSuccessBytes(w, json)
|
||||
}
|
||||
|
||||
// GetDocumentMeta is an endpoint returning the metadata for a document.
|
||||
func GetDocumentMeta(w http.ResponseWriter, r *http.Request) {
|
||||
method := "GetDocumentMeta"
|
||||
// GetDocumentActivity is an endpoint returning the activity logs for specified document.
|
||||
func GetDocumentActivity(w http.ResponseWriter, r *http.Request) {
|
||||
method := "GetDocumentActivity"
|
||||
p := request.GetPersister(r)
|
||||
|
||||
params := mux.Vars(r)
|
||||
id := params["documentID"]
|
||||
|
||||
id := params["documentID"]
|
||||
if len(id) == 0 {
|
||||
writeMissingDataError(w, method, "documentID")
|
||||
return
|
||||
}
|
||||
|
||||
meta, err := p.GetDocumentMeta(id)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
writeNotFoundError(w, method, id)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
a, err := p.GetDocumentActivity(id)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
writeGeneralSQLError(w, method, err)
|
||||
return
|
||||
}
|
||||
|
||||
json, err := json.Marshal(meta)
|
||||
|
||||
if err != nil {
|
||||
writeJSONMarshalError(w, method, "document", err)
|
||||
return
|
||||
}
|
||||
|
||||
writeSuccessBytes(w, json)
|
||||
util.WriteJSON(w, a)
|
||||
}
|
||||
|
||||
// GetDocumentLinks is an endpoint returning the links for a document.
|
||||
|
|
|
@ -16,6 +16,7 @@ package models
|
|||
|
||||
import (
|
||||
"github.com/documize/community/core/api/entity"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PageSequenceRequestModel details a page ID and its sequence within the document.
|
||||
|
@ -66,3 +67,16 @@ type PageModel struct {
|
|||
Page entity.Page `json:"page"`
|
||||
Meta entity.PageMeta `json:"meta"`
|
||||
}
|
||||
|
||||
// DocumentActivity represents an activity taken against a document.
|
||||
type DocumentActivity struct {
|
||||
ID int `json:"id"`
|
||||
OrgID string `json:"orgId"`
|
||||
LabelID string `json:"folderId"`
|
||||
DocumentID string `json:"documentId"`
|
||||
UserID string `json:"userId"`
|
||||
Firstname string `json:"firstname"`
|
||||
Lastname string `json:"lastname"`
|
||||
ActivityType int `json:"activityType"`
|
||||
Created time.Time `json:"created"`
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ func init() {
|
|||
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}", []string{"GET", "OPTIONS"}, nil, GetDocument))
|
||||
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}", []string{"PUT", "OPTIONS"}, nil, UpdateDocument))
|
||||
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}", []string{"DELETE", "OPTIONS"}, nil, DeleteDocument))
|
||||
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/meta", []string{"GET", "OPTIONS"}, nil, GetDocumentMeta))
|
||||
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/activity", []string{"GET", "OPTIONS"}, nil, GetDocumentActivity))
|
||||
|
||||
// Document Page
|
||||
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/pages/level", []string{"POST", "OPTIONS"}, nil, ChangeDocumentPageLevel))
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/documize/community/core/api/endpoint/models"
|
||||
"github.com/documize/community/core/api/entity"
|
||||
"github.com/documize/community/core/log"
|
||||
"github.com/documize/community/core/utility"
|
||||
|
@ -42,3 +45,27 @@ func (p *Persister) RecordUserActivity(activity entity.UserActivity) (err error)
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// GetDocumentActivity returns the metadata for a specified document.
|
||||
func (p *Persister) GetDocumentActivity(id string) (a []models.DocumentActivity, err error) {
|
||||
s := `SELECT a.id, a.created, a.orgid, IFNULL(a.userid, '') AS userid, a.labelid, a.sourceid as documentid, a.activitytype,
|
||||
IFNULL(u.firstname, 'Anonymous') AS firstname, IFNULL(u.lastname, 'Viewer') AS lastname
|
||||
FROM useractivity a
|
||||
LEFT JOIN user u ON a.userid=u.refid
|
||||
WHERE a.orgid=? AND a.sourceid=? AND a.sourcetype=2
|
||||
AND a.userid != '0' AND a.userid != ''
|
||||
ORDER BY a.created DESC`
|
||||
|
||||
err = Db.Select(&a, s, p.Context.OrgID, id)
|
||||
|
||||
if len(a) == 0 {
|
||||
a = []models.DocumentActivity{}
|
||||
}
|
||||
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
log.Error(fmt.Sprintf("Unable to execute GetDocumentActivity %s", id), err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue