1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-20 21:59:42 +02:00

Support for document versioning

This commit is contained in:
sauls8t 2018-03-19 12:24:58 +00:00
parent bc2cab5721
commit a7a82d9fe3
9 changed files with 158 additions and 110 deletions

View file

@ -65,7 +65,6 @@ func FilterCategoryProtected(docs []doc.Document, cats []category.Category, memb
// CopyDocument clones an existing document // CopyDocument clones an existing document
func CopyDocument(ctx domain.RequestContext, s domain.Store, documentID string) (newDocumentID string, err error) { func CopyDocument(ctx domain.RequestContext, s domain.Store, documentID string) (newDocumentID string, err error) {
doc, err := s.Document.Get(ctx, documentID) doc, err := s.Document.Get(ctx, documentID)
if err != nil { if err != nil {
err = errors.Wrap(err, "unable to fetch existing document") err = errors.Wrap(err, "unable to fetch existing document")
@ -145,3 +144,32 @@ func CopyDocument(ctx domain.RequestContext, s domain.Store, documentID string)
return return
} }
// FilterLastVersion returns the latest version of each document
// by removing all previous versions.
// If a document is not versioned, it is returned as-is.
func FilterLastVersion(docs []doc.Document) (filtered []doc.Document) {
filtered = []doc.Document{}
prev := make(map[string]bool)
for _, doc := range docs {
add := false
if doc.GroupID == "" {
add = true
} else {
if _, isExisting := prev[doc.GroupID]; !isExisting {
add = true
prev[doc.GroupID] = true
} else {
add = false
}
}
if add {
filtered = append(filtered, doc)
}
}
return
}

View file

@ -44,9 +44,10 @@ type Handler struct {
Indexer indexer.Indexer Indexer indexer.Indexer
} }
// Get is an endpoint that returns the document-level information for a given documentID. // Get is an endpoint that returns the document-level information for a
// given documentID.
func (h *Handler) Get(w http.ResponseWriter, r *http.Request) { func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
method := "document.get" method := "document.Get"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
id := request.Param(r, "documentID") id := request.Param(r, "documentID")
@ -101,7 +102,7 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
// DocumentLinks is an endpoint returning the links for a document. // DocumentLinks is an endpoint returning the links for a document.
func (h *Handler) DocumentLinks(w http.ResponseWriter, r *http.Request) { func (h *Handler) DocumentLinks(w http.ResponseWriter, r *http.Request) {
method := "document.links" method := "document.DocumentLinks"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
id := request.Param(r, "documentID") id := request.Param(r, "documentID")
@ -142,7 +143,8 @@ func (h *Handler) BySpace(w http.ResponseWriter, r *http.Request) {
// get user permissions // get user permissions
viewDrafts := permission.CanViewDrafts(ctx, *h.Store, spaceID) viewDrafts := permission.CanViewDrafts(ctx, *h.Store, spaceID)
// get complete list of documents // Get complete list of documents regardless of category permission
// and versioning.
documents, err := h.Store.Document.GetBySpace(ctx, spaceID) documents, err := h.Store.Document.GetBySpace(ctx, spaceID)
if err != nil { if err != nil {
response.WriteServerError(w, method, err) response.WriteServerError(w, method, err)
@ -150,21 +152,25 @@ func (h *Handler) BySpace(w http.ResponseWriter, r *http.Request) {
return return
} }
// sort by title // Sort by title.
sort.Sort(doc.ByTitle(documents)) sort.Sort(doc.ByTitle(documents))
// remove documents that cannot be seen due to lack of category view/access permission // Remove documents that cannot be seen due to lack of
// category view/access permission.
cats, err := h.Store.Category.GetBySpace(ctx, spaceID) cats, err := h.Store.Category.GetBySpace(ctx, spaceID)
members, err := h.Store.Category.GetSpaceCategoryMembership(ctx, spaceID) members, err := h.Store.Category.GetSpaceCategoryMembership(ctx, spaceID)
filtered := FilterCategoryProtected(documents, cats, members, viewDrafts) filtered := FilterCategoryProtected(documents, cats, members, viewDrafts)
// Keep the latest version when faced with multiple versions.
filtered = FilterLastVersion(filtered)
response.WriteJSON(w, filtered) response.WriteJSON(w, filtered)
} }
// Update updates an existing document using the // Update updates an existing document using the format described
// format described in NewDocumentModel() encoded as JSON in the request. // in NewDocumentModel() encoded as JSON in the request.
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) { func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
method := "document.space" method := "document.Update"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
documentID := request.Param(r, "documentID") documentID := request.Param(r, "documentID")
@ -203,7 +209,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
return return
} }
// if space changed for document, remove document categories // If space changed for document, remove document categories.
oldDoc, err := h.Store.Document.Get(ctx, documentID) oldDoc, err := h.Store.Document.Get(ctx, documentID)
if err != nil { if err != nil {
ctx.Transaction.Rollback() ctx.Transaction.Rollback()
@ -224,7 +230,20 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
return return
} }
// Record document being marked as archived // If document part of versioned document group
// then document name must be applied to all documents
// in the group.
if len(d.GroupID) > 0 {
err = h.Store.Document.UpdateGroup(ctx, d)
if err != nil {
ctx.Transaction.Rollback()
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
}
// Record document being marked as archived.
if d.Lifecycle != oldDoc.Lifecycle && d.Lifecycle == workflow.LifecycleArchived { if d.Lifecycle != oldDoc.Lifecycle && d.Lifecycle == workflow.LifecycleArchived {
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{ h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
LabelID: d.LabelID, LabelID: d.LabelID,
@ -233,7 +252,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
ActivityType: activity.TypeArchived}) ActivityType: activity.TypeArchived})
} }
// Record document being marked as draft // Record document being marked as draft.
if d.Lifecycle != oldDoc.Lifecycle && d.Lifecycle == workflow.LifecycleDraft { if d.Lifecycle != oldDoc.Lifecycle && d.Lifecycle == workflow.LifecycleDraft {
h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{ h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{
LabelID: d.LabelID, LabelID: d.LabelID,
@ -246,7 +265,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
h.Store.Audit.Record(ctx, audit.EventTypeDocumentUpdate) h.Store.Audit.Record(ctx, audit.EventTypeDocumentUpdate)
// Live document indexed for search // Live document indexed for search.
if d.Lifecycle == workflow.LifecycleLive { if d.Lifecycle == workflow.LifecycleLive {
a, _ := h.Store.Attachment.GetAttachments(ctx, documentID) a, _ := h.Store.Attachment.GetAttachments(ctx, documentID)
go h.Indexer.IndexDocument(ctx, d, a) go h.Indexer.IndexDocument(ctx, d, a)
@ -259,7 +278,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
// Delete is an endpoint that deletes a document specified by documentID. // Delete is an endpoint that deletes a document specified by documentID.
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) { func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
method := "document.delete" method := "document.Delete"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
documentID := request.Param(r, "documentID") documentID := request.Param(r, "documentID")
@ -348,9 +367,10 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
response.WriteEmpty(w) response.WriteEmpty(w)
} }
// SearchDocuments endpoint takes a list of keywords and returns a list of document references matching those keywords. // SearchDocuments endpoint takes a list of keywords and returns a list of
// document references matching those keywords.
func (h *Handler) SearchDocuments(w http.ResponseWriter, r *http.Request) { func (h *Handler) SearchDocuments(w http.ResponseWriter, r *http.Request) {
method := "document.search" method := "document.SearchDocuments"
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
defer streamutil.Close(r.Body) defer streamutil.Close(r.Body)
@ -467,12 +487,22 @@ func (h *Handler) FetchDocumentData(w http.ResponseWriter, r *http.Request) {
sp = []space.Space{} sp = []space.Space{}
} }
// Get version information for this document.
v, err := h.Store.Document.GetVersions(ctx, document.GroupID)
if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err)
return
}
// Prepare response.
data := BulkDocumentData{} data := BulkDocumentData{}
data.Document = document data.Document = document
data.Permissions = record data.Permissions = record
data.Roles = rolesRecord data.Roles = rolesRecord
data.Links = l data.Links = l
data.Spaces = sp data.Spaces = sp
data.Versions = v
ctx.Transaction, err = h.Runtime.Db.Beginx() ctx.Transaction, err = h.Runtime.Db.Beginx()
if err != nil { if err != nil {
@ -509,4 +539,5 @@ type BulkDocumentData struct {
Roles pm.DocumentRecord `json:"roles"` Roles pm.DocumentRecord `json:"roles"`
Spaces []space.Space `json:"folders"` Spaces []space.Space `json:"folders"`
Links []link.Link `json:"links"` Links []link.Link `json:"links"`
Versions []doc.Version `json:"versions"`
} }

View file

@ -97,20 +97,13 @@ func (s Scope) DocumentMeta(ctx domain.RequestContext, id string) (meta doc.Docu
return return
} }
// GetAll returns a slice containg all of the the documents for the client's organisation.
func (s Scope) GetAll() (ctx domain.RequestContext, documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents, "SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, protection, approval, created, revised FROM document WHERE orgid=? AND template=0 ORDER BY title", ctx.OrgID)
if err != nil {
err = errors.Wrap(err, "select documents")
}
return
}
// GetBySpace returns a slice containing the documents for a given space. // GetBySpace returns a slice containing the documents for a given space.
// No attempt is made to hide documents that are protected //
// by category permissions -- caller must filter as required. // No attempt is made to hide documents that are protected by category
// permissions hence caller must filter as required.
//
// All versions of a document are returned, hence caller must
// decide what to do with them.
func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) { func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents, ` err = s.Runtime.Db.Select(&documents, `
SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template, SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
@ -125,7 +118,7 @@ func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents
AND p.who='role' AND p.location='space' AND p.refid=? AND p.action='view' AND (r.userid=? OR r.userid='0') AND p.who='role' AND p.location='space' AND p.refid=? AND p.action='view' AND (r.userid=? OR r.userid='0')
)) ))
) )
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, spaceID, ctx.OrgID, ctx.UserID, ctx.OrgID, spaceID, ctx.UserID) ORDER BY title, versionorder`, ctx.OrgID, ctx.OrgID, ctx.OrgID, spaceID, ctx.OrgID, ctx.UserID, ctx.OrgID, spaceID, ctx.UserID)
if err == sql.ErrNoRows || len(documents) == 0 { if err == sql.ErrNoRows || len(documents) == 0 {
err = nil err = nil
@ -138,35 +131,6 @@ func (s Scope) GetBySpace(ctx domain.RequestContext, spaceID string) (documents
return return
} }
// Templates returns a slice containing the documents available as templates to the client's organisation, in title order.
func (s Scope) Templates(ctx domain.RequestContext) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents,
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
FROM document
WHERE orgid=? AND template=1 AND lifecycle=1
AND labelid IN
(
SELECT refid FROM label WHERE orgid=?
AND refid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN (
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view'
UNION ALL
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' AND p.location='space' AND p.action='view' AND (r.userid=? OR r.userid='0')
))
)
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.UserID, ctx.OrgID, ctx.UserID)
if err == sql.ErrNoRows || len(documents) == 0 {
err = nil
documents = []doc.Document{}
}
if err != nil {
err = errors.Wrap(err, "select document templates")
}
return
}
// TemplatesBySpace returns a slice containing the documents available as templates for given space. // TemplatesBySpace returns a slice containing the documents available as templates for given space.
func (s Scope) TemplatesBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) { func (s Scope) TemplatesBySpace(ctx domain.RequestContext, spaceID string) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents, err = s.Runtime.Db.Select(&documents,
@ -196,7 +160,9 @@ func (s Scope) TemplatesBySpace(ctx domain.RequestContext, spaceID string) (docu
return return
} }
// PublicDocuments returns a slice of SitemapDocument records, holding documents in folders of type 1 (entity.TemplateTypePublic). // PublicDocuments returns a slice of SitemapDocument records
// linking to documents in public spaces.
// These documents can then be seen by search crawlers.
func (s Scope) PublicDocuments(ctx domain.RequestContext, orgID string) (documents []doc.SitemapDocument, err error) { func (s Scope) PublicDocuments(ctx domain.RequestContext, orgID string) (documents []doc.SitemapDocument, err error) {
err = s.Runtime.Db.Select(&documents, err = s.Runtime.Db.Select(&documents,
`SELECT d.refid as documentid, d.title as document, d.revised as revised, l.refid as folderid, l.label as folder `SELECT d.refid as documentid, d.title as document, d.revised as revised, l.refid as folderid, l.label as folder
@ -217,35 +183,6 @@ func (s Scope) PublicDocuments(ctx domain.RequestContext, orgID string) (documen
return return
} }
// DocumentList returns a slice containing the documents available as templates to the client's organisation, in title order.
func (s Scope) DocumentList(ctx domain.RequestContext) (documents []doc.Document, err error) {
err = s.Runtime.Db.Select(&documents,
`SELECT id, refid, orgid, labelid, userid, job, location, title, excerpt, slug, tags, template,
protection, approval, lifecycle, versioned, versionid, versionorder, groupid, created, revised
FROM document
WHERE orgid=? AND template=0 AND lifecycle=1
AND labelid IN
(
SELECT refid FROM label WHERE orgid=?
AND refid IN (SELECT refid FROM permission WHERE orgid=? AND location='space' AND refid IN (
SELECT refid from permission WHERE orgid=? AND who='user' AND (whoid=? OR whoid='0') AND location='space' AND action='view'
UNION ALL
SELECT p.refid from permission p LEFT JOIN rolemember r ON p.whoid=r.roleid WHERE p.orgid=? AND p.who='role' AND p.location='space' AND p.action='view' AND (r.userid=? OR r.userid='0')
))
)
ORDER BY title`, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.OrgID, ctx.UserID, ctx.OrgID, ctx.UserID)
if err == sql.ErrNoRows {
err = nil
documents = []doc.Document{}
}
if err != nil {
err = errors.Wrap(err, "select documents list")
}
return
}
// Update changes the given document record to the new values, updates search information and audits the action. // Update changes the given document record to the new values, updates search information and audits the action.
func (s Scope) Update(ctx domain.RequestContext, document doc.Document) (err error) { func (s Scope) Update(ctx domain.RequestContext, document doc.Document) (err error) {
document.Revised = time.Now().UTC() document.Revised = time.Now().UTC()
@ -255,11 +192,27 @@ func (s Scope) Update(ctx domain.RequestContext, document doc.Document) (err err
SET SET
labelid=:labelid, userid=:userid, job=:job, location=:location, title=:title, excerpt=:excerpt, slug=:slug, tags=:tags, template=:template, labelid=:labelid, userid=:userid, job=:job, location=:location, title=:title, excerpt=:excerpt, slug=:slug, tags=:tags, template=:template,
protection=:protection, approval=:approval, lifecycle=:lifecycle, versioned=:versioned, versionid=:versionid, versionorder=:versionorder, groupid=:groupid, revised=:revised protection=:protection, approval=:approval, lifecycle=:lifecycle, versioned=:versioned, versionid=:versionid, versionorder=:versionorder, groupid=:groupid, revised=:revised
WHERE orgid=:orgid AND refid=:refid`, WHERE orgid=:orgid AND refid=:refid`,
&document) &document)
if err != nil { if err != nil {
err = errors.Wrap(err, "execute update document") err = errors.Wrap(err, "document.store.Update")
}
return
}
// UpdateGroup applies same values to all documents
// with the same group ID.
func (s Scope) UpdateGroup(ctx domain.RequestContext, d doc.Document) (err error) {
_, err = ctx.Transaction.Exec(`UPDATE document SET title=?, excerpt=? WHERE orgid=? AND groupid=?`,
d.Title, d.Excerpt, ctx.OrgID, d.GroupID)
if err == sql.ErrNoRows {
err = nil
}
if err != nil {
err = errors.Wrap(err, "document.store.UpdateTitle")
} }
return return
@ -341,3 +294,28 @@ func (s Scope) DeleteBySpace(ctx domain.RequestContext, spaceID string) (rows in
return b.DeleteConstrained(ctx.Transaction, "document", ctx.OrgID, spaceID) return b.DeleteConstrained(ctx.Transaction, "document", ctx.OrgID, spaceID)
} }
// GetVersions returns a slice containing the documents for a given space.
//
// No attempt is made to hide documents that are protected by category
// permissions hence caller must filter as required.
//
// All versions of a document are returned, hence caller must
// decide what to do with them.
func (s Scope) GetVersions(ctx domain.RequestContext, groupID string) (v []doc.Version, err error) {
err = s.Runtime.Db.Select(&v, `
SELECT versionid, refid as documentid
FROM document
WHERE orgid=? AND groupid=?
ORDER BY versionorder`, ctx.OrgID, groupID)
if err == sql.ErrNoRows || len(v) == 0 {
err = nil
v = []doc.Version{}
}
if err != nil {
err = errors.Wrap(err, "document.store.GetVersions")
}
return
}

View file

@ -168,18 +168,17 @@ type AuditStorer interface {
type DocumentStorer interface { type DocumentStorer interface {
Add(ctx RequestContext, document doc.Document) (err error) Add(ctx RequestContext, document doc.Document) (err error)
Get(ctx RequestContext, id string) (document doc.Document, err error) Get(ctx RequestContext, id string) (document doc.Document, err error)
GetAll() (ctx RequestContext, documents []doc.Document, err error)
GetBySpace(ctx RequestContext, spaceID string) (documents []doc.Document, err error) GetBySpace(ctx RequestContext, spaceID string) (documents []doc.Document, err error)
DocumentList(ctx RequestContext) (documents []doc.Document, err error)
Templates(ctx RequestContext) (documents []doc.Document, err error)
TemplatesBySpace(ctx RequestContext, spaceID string) (documents []doc.Document, err error) TemplatesBySpace(ctx RequestContext, spaceID string) (documents []doc.Document, err error)
DocumentMeta(ctx RequestContext, id string) (meta doc.DocumentMeta, err error) DocumentMeta(ctx RequestContext, id string) (meta doc.DocumentMeta, err error)
PublicDocuments(ctx RequestContext, orgID string) (documents []doc.SitemapDocument, err error) PublicDocuments(ctx RequestContext, orgID string) (documents []doc.SitemapDocument, err error)
Update(ctx RequestContext, document doc.Document) (err error) Update(ctx RequestContext, document doc.Document) (err error)
UpdateGroup(ctx RequestContext, document doc.Document) (err error)
ChangeDocumentSpace(ctx RequestContext, document, space string) (err error) ChangeDocumentSpace(ctx RequestContext, document, space string) (err error)
MoveDocumentSpace(ctx RequestContext, id, move string) (err error) MoveDocumentSpace(ctx RequestContext, id, move string) (err error)
Delete(ctx RequestContext, documentID string) (rows int64, err error) Delete(ctx RequestContext, documentID string) (rows int64, err error)
DeleteBySpace(ctx RequestContext, spaceID string) (rows int64, err error) DeleteBySpace(ctx RequestContext, spaceID string) (rows int64, err error)
GetVersions(ctx RequestContext, groupID string) (v []doc.Version, err error)
} }
// SettingStorer defines required methods for persisting global and user level settings // SettingStorer defines required methods for persisting global and user level settings

View file

@ -43,7 +43,8 @@ export default Route.extend(AuthenticatedRouteMixin, {
sections: this.modelFor('document').sections, sections: this.modelFor('document').sections,
permissions: this.modelFor('document').permissions, permissions: this.modelFor('document').permissions,
roles: this.modelFor('document').roles, roles: this.modelFor('document').roles,
blocks: this.modelFor('document').blocks blocks: this.modelFor('document').blocks,
versions: this.modelFor('document').versions
}); });
}, },
@ -57,10 +58,11 @@ export default Route.extend(AuthenticatedRouteMixin, {
controller.set('permissions', model.permissions); controller.set('permissions', model.permissions);
controller.set('roles', model.roles); controller.set('roles', model.roles);
controller.set('blocks', model.blocks); controller.set('blocks', model.blocks);
controller.set('versions', model.versions);
}, },
activate: function() { activate: function () {
this._super(...arguments); this._super(...arguments);
window.scrollTo(0,0); window.scrollTo(0, 0);
} }
}); });

View file

@ -1,6 +1,5 @@
{{toolbar/nav-bar}} {{toolbar/nav-bar}} {{toolbar/for-document document=document spaces=folders space=folder
permissions=permissions roles=roles tab=tab versions=versions
{{toolbar/for-document document=document spaces=folders space=folder permissions=permissions roles=roles tab=tab
onDocumentDelete=(action 'onDocumentDelete') onDocumentDelete=(action 'onDocumentDelete')
onSaveTemplate=(action 'onSaveTemplate') onSaveTemplate=(action 'onSaveTemplate')
onSaveDocument=(action 'onSaveDocument') onSaveDocument=(action 'onSaveDocument')
@ -10,9 +9,10 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
{{document/document-heading document=document permissions=permissions {{document/document-heading document=document permissions=permissions
versions=versions
onSaveDocument=(action 'onSaveDocument')}} onSaveDocument=(action 'onSaveDocument')}}
{{document/document-meta document=document folder=folder folders=folders
{{document/document-meta document=document folder=folder folders=folders permissions=permissions pages=pages permissions=permissions pages=pages versions=versions
onSaveDocument=(action 'onSaveDocument')}} onSaveDocument=(action 'onSaveDocument')}}
</div> </div>
</div> </div>

View file

@ -32,6 +32,7 @@ export default Route.extend(AuthenticatedRouteMixin, {
this.set('permissions', data.permissions); this.set('permissions', data.permissions);
this.set('roles', data.roles); this.set('roles', data.roles);
this.set('links', data.links); this.set('links', data.links);
this.set('versions', data.versions);
resolve(); resolve();
}); });
}); });
@ -45,13 +46,14 @@ export default Route.extend(AuthenticatedRouteMixin, {
permissions: this.get('permissions'), permissions: this.get('permissions'),
roles: this.get('roles'), roles: this.get('roles'),
links: this.get('links'), links: this.get('links'),
versions: this.get('versions'),
sections: this.get('sectionService').getAll(), sections: this.get('sectionService').getAll(),
blocks: this.get('sectionService').getSpaceBlocks(this.get('folder.id')) blocks: this.get('sectionService').getSpaceBlocks(this.get('folder.id'))
}); });
}, },
actions: { actions: {
error(error /*, transition*/ ) { error(error /*, transition*/) {
if (error) { if (error) {
this.transitionTo('/not-found'); this.transitionTo('/not-found');
return false; return false;

View file

@ -334,6 +334,7 @@ export default Service.extend({
folders: [], folders: [],
folder: {}, folder: {},
links: [], links: [],
versions: [],
}; };
let doc = this.get('store').normalize('document', response.document); let doc = this.get('store').normalize('document', response.document);
@ -357,6 +358,7 @@ export default Service.extend({
data.folders = folders; data.folders = folders;
data.folder = folders.findBy('id', doc.get('folderId')); data.folder = folders.findBy('id', doc.get('folderId'));
data.links = response.links; data.links = response.links;
data.versions = response.versions;
return data; return data;
}).catch((error) => { }).catch((error) => {

View file

@ -94,3 +94,9 @@ type SitemapDocument struct {
Folder string Folder string
Revised time.Time Revised time.Time
} }
// Version points to a version of a document.
type Version struct {
VersionID string `json:"versionId"`
DocumentID string `json:"documentId"`
}