diff --git a/domain/attachment/store.go b/domain/attachment/store.go index ef49c6b5..b6ce964a 100644 --- a/domain/attachment/store.go +++ b/domain/attachment/store.go @@ -13,6 +13,7 @@ package attachment import ( "database/sql" + "fmt" "strings" "time" @@ -88,6 +89,31 @@ func (s Store) GetAttachments(ctx domain.RequestContext, docID string) (a []atta return } +// GetSectionAttachments returns a slice containing the attachment records +// with file data for specified document section. +func (s Store) GetSectionAttachments(ctx domain.RequestContext, sectionID string) (a []attachment.Attachment, err error) { + err = s.Runtime.Db.Select(&a, s.Bind(` + SELECT id, c_refid AS refid, + c_orgid AS orgid, c_docid AS documentid, c_sectionid AS sectionid, c_job AS job, c_fileid AS fileid, + c_filename AS filename, c_data AS data, c_extension AS extension, + c_created AS created, c_revised AS revised + FROM dmz_doc_attachment + WHERE c_orgid=? AND c_sectionid=? + ORDER BY c_filename`), + ctx.OrgID, sectionID) + + if err == sql.ErrNoRows { + err = nil + a = []attachment.Attachment{} + } + if err != nil { + err = errors.Wrap(err, "execute select section attachments") + return + } + + return +} + // GetAttachmentsWithData returns a slice containing the attachment records (including their data) for document docID, ordered by filename. func (s Store) GetAttachmentsWithData(ctx domain.RequestContext, docID string) (a []attachment.Attachment, err error) { err = s.Runtime.Db.Select(&a, s.Bind(` @@ -116,3 +142,11 @@ func (s Store) GetAttachmentsWithData(ctx domain.RequestContext, docID string) ( func (s Store) Delete(ctx domain.RequestContext, id string) (rows int64, err error) { return s.DeleteConstrained(ctx.Transaction, "dmz_doc_attachment", ctx.OrgID, id) } + +// DeleteSection removes all attachments agasinst a section. +func (s Store) DeleteSection(ctx domain.RequestContext, sectionID string) (rows int64, err error) { + rows, err = s.DeleteWhere(ctx.Transaction, fmt.Sprintf("DELETE FROM dmz_doc_attachment WHERE c_orgid='%s' AND c_sectionid='%s'", + ctx.OrgID, sectionID)) + + return +} diff --git a/domain/page/endpoint.go b/domain/page/endpoint.go index 3d2afb76..949b782a 100644 --- a/domain/page/endpoint.go +++ b/domain/page/endpoint.go @@ -22,6 +22,7 @@ import ( "github.com/documize/community/core/env" "github.com/documize/community/core/request" "github.com/documize/community/core/response" + "github.com/documize/community/core/secrets" "github.com/documize/community/core/streamutil" "github.com/documize/community/core/uniqueid" "github.com/documize/community/domain" @@ -599,6 +600,8 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) { h.Store.Page.DeletePageRevisions(ctx, pageID) + h.Store.Attachment.DeleteSection(ctx, pageID) + // Update doc revised. h.Store.Document.UpdateRevised(ctx, doc.RefID) @@ -700,6 +703,8 @@ func (h *Handler) DeletePages(w http.ResponseWriter, r *http.Request) { h.Store.Page.DeletePageRevisions(ctx, page.SectionID) + h.Store.Attachment.DeleteSection(ctx, page.SectionID) + // Draft actions are not logged if doc.Lifecycle == workflow.LifecycleLive { h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{ @@ -977,7 +982,27 @@ func (h *Handler) Copy(w http.ResponseWriter, r *http.Request) { h.Store.Block.IncrementUsage(ctx, model.Page.TemplateID) } - // Log t actions are not logged + // Copy section attachments. + at, err := h.Store.Attachment.GetSectionAttachments(ctx, pageID) + if err != nil { + h.Runtime.Log.Error(method, err) + } + for i := range at { + at[i].DocumentID = targetID + at[i].SectionID = newPageID + at[i].RefID = uniqueid.Generate() + random := secrets.GenerateSalt() + at[i].FileID = random[0:9] + + err1 := h.Store.Attachment.Add(ctx, at[i]) + if err1 != nil { + ctx.Transaction.Rollback() + response.WriteServerError(w, method, err1) + h.Runtime.Log.Error(method, err1) + return + } + } + if doc.Lifecycle == workflow.LifecycleLive { h.Store.Activity.RecordUserActivity(ctx, activity.UserActivity{ SpaceID: doc.SpaceID, diff --git a/domain/store/storer.go b/domain/store/storer.go index 4296e235..1084b3ed 100644 --- a/domain/store/storer.go +++ b/domain/store/storer.go @@ -207,8 +207,10 @@ type AttachmentStorer interface { Add(ctx domain.RequestContext, a attachment.Attachment) (err error) GetAttachment(ctx domain.RequestContext, orgID, attachmentID string) (a attachment.Attachment, err error) GetAttachments(ctx domain.RequestContext, docID string) (a []attachment.Attachment, err error) + GetSectionAttachments(ctx domain.RequestContext, sectionID string) (a []attachment.Attachment, err error) GetAttachmentsWithData(ctx domain.RequestContext, docID string) (a []attachment.Attachment, err error) Delete(ctx domain.RequestContext, id string) (rows int64, err error) + DeleteSection(ctx domain.RequestContext, id string) (rows int64, err error) } // LinkStorer defines required methods for persisting content links diff --git a/gui/app/components/section/pdf/type-editor.js b/gui/app/components/section/pdf/type-editor.js index 317da9c0..a89ae1cf 100644 --- a/gui/app/components/section/pdf/type-editor.js +++ b/gui/app/components/section/pdf/type-editor.js @@ -54,6 +54,9 @@ export default Component.extend({ setPDF() { let files = this.get('attachments'); + this.set('pdfName', ''); + this.set('pdfOption.fileId', ''); + if (!_.isArray(files)) return; for (let i=0; i < files.length; i++) { @@ -84,7 +87,7 @@ export default Component.extend({ let config = this.get('pdfOption'); let page = this.get('page'); let meta = this.get('meta'); - + page.set('title', title); page.set('body', JSON.stringify(config)); meta.set('config', JSON.stringify(config)); diff --git a/gui/app/components/section/pdf/type-renderer.js b/gui/app/components/section/pdf/type-renderer.js index 27efee07..f6567541 100644 --- a/gui/app/components/section/pdf/type-renderer.js +++ b/gui/app/components/section/pdf/type-renderer.js @@ -51,6 +51,10 @@ export default Component.extend({ let orgId = this.get('appMeta.orgId'); let fileId = this.get('pdfOption.fileId'); + if (_.isEmpty(fileId)) { + return; + } + // For authenticated users we send server auth token. let qry = ''; if (this.get('session.hasSecureToken')) { diff --git a/gui/app/pods/document/section/controller.js b/gui/app/pods/document/section/controller.js index ea3f5556..b7a39b97 100644 --- a/gui/app/pods/document/section/controller.js +++ b/gui/app/pods/document/section/controller.js @@ -43,5 +43,19 @@ export default Controller.extend({ { queryParams: { currentPageId: page.get('id')}}); }); }, + + onAttachmentUpload() { + this.get('documentService').getAttachments(this.get('model.document.id')).then((files) => { + this.set('model.attachments', files); + }); + }, + + onAttachmentDelete(attachmentId) { + this.get('documentService').deleteAttachment(this.get('model.document.id'), attachmentId).then(() => { + this.get('documentService').getAttachments(this.get('model.document.id')).then((files) => { + this.set('attachments', files); + }); + }); + }, } }); diff --git a/gui/app/pods/document/section/route.js b/gui/app/pods/document/section/route.js index 2ea4351b..65b60a1e 100644 --- a/gui/app/pods/document/section/route.js +++ b/gui/app/pods/document/section/route.js @@ -11,8 +11,8 @@ import { hash } from 'rsvp'; import { inject as service } from '@ember/service'; -import Route from '@ember/routing/route'; import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin'; +import Route from '@ember/routing/route'; export default Route.extend(AuthenticatedRouteMixin, { documentService: service('document'), @@ -27,6 +27,7 @@ export default Route.extend(AuthenticatedRouteMixin, { permissions: this.get('folderService').get('permissions'), links: this.modelFor('document').links, sections: this.modelFor('document').sections, + attachments: this.modelFor('document').attachments, page: this.get('documentService').getPage(this.modelFor('document').document.get('id'), params.page_id), meta: this.get('documentService').getPageMeta(this.modelFor('document').document.get('id'), params.page_id) }); diff --git a/gui/app/pods/document/section/template.hbs b/gui/app/pods/document/section/template.hbs index 1bd42bef..2e18719a 100644 --- a/gui/app/pods/document/section/template.hbs +++ b/gui/app/pods/document/section/template.hbs @@ -9,6 +9,17 @@ {{/layout/master-sidebar}} {{#layout/master-content}} - {{document/document-editor document=model.document folder=model.folder page=model.page meta=model.meta + {{document/document-editor + document=model.document + folder=model.folder + page=model.page + meta=model.meta + attachments=model.attachments onCancel=(action "onCancel") onAction=(action "onAction")}} + + {{document/section-attachment uploadLabel="Upload Attachments" + editMode=true page=model.page document=model.document + files=model.attachments + onAttachmentUpload=(action "onAttachmentUpload") + onAttachmentDelete=(action "onAttachmentDelete")}} {{/layout/master-content}}