From fc9127e1653d0ac81eabedcb2d281a58955e99b5 Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Sat, 21 Jan 2017 18:14:31 -0800 Subject: [PATCH] implemented delete reusable content block --- .../components/document/document-sidebar.js | 5 ++ app/app/components/document/page-wizard.js | 16 +++++- app/app/components/section/base-editor.js | 4 -- app/app/pods/document/controller.js | 9 ++++ app/app/pods/document/template.hbs | 2 +- app/app/services/section.js | 12 +++++ app/app/styles/view/document/wizard.scss | 8 +-- .../components/document/document-sidebar.hbs | 2 +- .../components/document/page-wizard.hbs | 8 ++- core/api/endpoint/router.go | 1 + core/api/endpoint/sections_endpoint.go | 54 ++++++++++++++++++- core/api/request/block.go | 25 +++++++++ 12 files changed, 130 insertions(+), 16 deletions(-) diff --git a/app/app/components/document/document-sidebar.js b/app/app/components/document/document-sidebar.js index c2ce79ee..52f5dd32 100644 --- a/app/app/components/document/document-sidebar.js +++ b/app/app/components/document/document-sidebar.js @@ -106,6 +106,11 @@ export default Ember.Component.extend(TooltipMixin, NotifierMixin, { this.attrs.onInsertBlock(block); }, + onDeleteBlock(id) { + this.set('blocks', this.get('blocks').filter((item) => item.get('id') !== id)); + this.attrs.onDeleteBlock(id); + }, + scrollTop() { this.set('showScrollTool', false); diff --git a/app/app/components/document/page-wizard.js b/app/app/components/document/page-wizard.js index 619a9e67..87536103 100644 --- a/app/app/components/document/page-wizard.js +++ b/app/app/components/document/page-wizard.js @@ -12,12 +12,22 @@ import Ember from 'ember'; import NotifierMixin from '../../mixins/notifier'; +const { + computed, +} = Ember; + export default Ember.Component.extend(NotifierMixin, { display: 'section', // which CSS to use hasTemplates: false, didReceiveAttrs() { - this.set('hasBlocks', this.get('blocks.length') > 0); + let blocks = this.get('blocks'); + + this.set('hasBlocks', blocks.get('length') > 0); + + blocks.forEach((b) => { + b.set('deleteId', `delete-block-button-${b.id}`); + }); }, didRender() { @@ -42,6 +52,10 @@ export default Ember.Component.extend(NotifierMixin, { this.attrs.onAddSection(section); }, + onDeleteBlock(id) { + this.attrs.onDeleteBlock(id); + }, + onInsertBlock(block) { this.attrs.onInsertBlock(block); } diff --git a/app/app/components/section/base-editor.js b/app/app/components/section/base-editor.js index b9d0c0bb..b30be215 100644 --- a/app/app/components/section/base-editor.js +++ b/app/app/components/section/base-editor.js @@ -21,10 +21,6 @@ export default Ember.Component.extend({ return is.not.undefined(this.get('page.excerpt')); }), - didReceiveAttrs() { - this._super(...arguments); - }, - didRender() { let self = this; Mousetrap.bind('esc', function () { diff --git a/app/app/pods/document/controller.js b/app/app/pods/document/controller.js index 0e7a6283..7e08039d 100644 --- a/app/app/pods/document/controller.js +++ b/app/app/pods/document/controller.js @@ -15,6 +15,7 @@ import NotifierMixin from '../../mixins/notifier'; export default Ember.Controller.extend(NotifierMixin, { documentService: Ember.inject.service('document'), templateService: Ember.inject.service('template'), + sectionService: Ember.inject.service('section'), page: null, folder: {}, pages: [], @@ -188,6 +189,14 @@ export default Ember.Controller.extend(NotifierMixin, { }); }, + onDeleteBlock(blockId) { + this.get('sectionService').deleteBlock(blockId).then(() => { + this.audit.record("deleted-block"); + this.send("showNotification", "Deleted"); + this.transitionToRoute('document.index'); + }); + }, + onDocumentDelete() { this.get('documentService').deleteDocument(this.get('model.document.id')).then(() => { this.audit.record("deleted-page"); diff --git a/app/app/pods/document/template.hbs b/app/app/pods/document/template.hbs index 3db1ca10..cff52928 100644 --- a/app/app/pods/document/template.hbs +++ b/app/app/pods/document/template.hbs @@ -2,7 +2,7 @@ {{#layout/zone-sidebar}} {{document/document-sidebar document=model.document folder=model.folder pages=model.pages page=model.page isEditor=model.isEditor sections=model.sections - onAddSection=(action 'onAddSection') onInsertBlock=(action 'onInsertBlock') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action 'gotoPage')}} + onAddSection=(action 'onAddSection') onInsertBlock=(action 'onInsertBlock') onDeleteBlock=(action 'onDeleteBlock') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action 'gotoPage')}} {{/layout/zone-sidebar}} {{#layout/zone-content}} diff --git a/app/app/services/section.js b/app/app/services/section.js index e0018a30..3f7d36d0 100644 --- a/app/app/services/section.js +++ b/app/app/services/section.js @@ -81,6 +81,9 @@ export default BaseService.extend({ return this.get('ajax').post(url, { data: JSON.stringify(payload), contentType: 'json' + }).then((response) => { + let data = this.get('store').normalize('block', response); + return this.get('store').push(data); }); }, @@ -116,5 +119,14 @@ export default BaseService.extend({ method: 'PUT', data: JSON.stringify(block) }); + }, + + // Removes specified reusable content block. + deleteBlock: function (blockId) { + let url = `sections/blocks/${blockId}`; + + return this.get('ajax').request(url, { + method: 'DELETE' + }); } }); diff --git a/app/app/styles/view/document/wizard.scss b/app/app/styles/view/document/wizard.scss index 8eaa0860..e9996962 100644 --- a/app/app/styles/view/document/wizard.scss +++ b/app/app/styles/view/document/wizard.scss @@ -83,17 +83,11 @@ text-align: center; width: 20px; margin-top: 5px; - opacity: 0.3; + opacity: 0.4; > .material-icons, a { color: $color-gray; - - &:hover { - opacity: 1; - color: $color-primary; - } } - } } } diff --git a/app/app/templates/components/document/document-sidebar.hbs b/app/app/templates/components/document/document-sidebar.hbs index 19728baf..9f5529a6 100644 --- a/app/app/templates/components/document/document-sidebar.hbs +++ b/app/app/templates/components/document/document-sidebar.hbs @@ -26,6 +26,6 @@ {{/if}} {{#if showSections}} {{document/page-wizard display='section' document=document folder=folder sections=sections blocks=blocks - onCancel=(action 'onCancel') onAddSection=(action 'onAddSection') onInsertBlock=(action 'onInsertBlock')}} + onCancel=(action 'onCancel') onAddSection=(action 'onAddSection') onInsertBlock=(action 'onInsertBlock') onDeleteBlock=(action 'onDeleteBlock')}} {{/if}} diff --git a/app/app/templates/components/document/page-wizard.hbs b/app/app/templates/components/document/page-wizard.hbs index 4dcb5970..e59d6fa8 100644 --- a/app/app/templates/components/document/page-wizard.hbs +++ b/app/app/templates/components/document/page-wizard.hbs @@ -40,9 +40,15 @@ mode_edit {{/link-to}}
- delete + delete
+ {{#dropdown-dialog target=block.deleteId position="top right" button="Delete" color="flat-red" onAction=(action 'onDeleteBlock' block.id)}} +

+ Are you sure you want to delete block
+ {{block.title}}? +

+ {{/dropdown-dialog}} {{/each}} diff --git a/core/api/endpoint/router.go b/core/api/endpoint/router.go index 1f8ace18..2fa20d16 100644 --- a/core/api/endpoint/router.go +++ b/core/api/endpoint/router.go @@ -219,6 +219,7 @@ func init() { log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/space/{folderID}", []string{"GET", "OPTIONS"}, nil, GetBlocksForSpace)) log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/{blockID}", []string{"GET", "OPTIONS"}, nil, GetBlock)) log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/{blockID}", []string{"PUT", "OPTIONS"}, nil, UpdateBlock)) + log.IfErr(Add(RoutePrefixPrivate, "sections/blocks/{blockID}", []string{"DELETE", "OPTIONS"}, nil, DeleteBlock)) log.IfErr(Add(RoutePrefixPrivate, "sections/blocks", []string{"POST", "OPTIONS"}, nil, AddBlock)) // Links diff --git a/core/api/endpoint/sections_endpoint.go b/core/api/endpoint/sections_endpoint.go index 3f94f435..f297d815 100644 --- a/core/api/endpoint/sections_endpoint.go +++ b/core/api/endpoint/sections_endpoint.go @@ -226,7 +226,19 @@ func AddBlock(w http.ResponseWriter, r *http.Request) { log.IfErr(tx.Commit()) - writeSuccessEmptyJSON(w) + b, err = p.GetBlock(b.RefID) + if err != nil { + writeGeneralSQLError(w, method, err) + return + } + + json, err := json.Marshal(b) + if err != nil { + writeJSONMarshalError(w, method, "block", err) + return + } + + writeSuccessBytes(w, json) } // GetBlock returns requested reusable content block. @@ -337,3 +349,43 @@ func UpdateBlock(w http.ResponseWriter, r *http.Request) { writeSuccessEmptyJSON(w) } + +// DeleteBlock removes requested reusable content block. +func DeleteBlock(w http.ResponseWriter, r *http.Request) { + method := "DeleteBlock" + p := request.GetPersister(r) + + params := mux.Vars(r) + blockID := params["blockID"] + + if len(blockID) == 0 { + writeMissingDataError(w, method, "blockID") + return + } + + tx, err := request.Db.Beginx() + if err != nil { + writeTransactionError(w, method, err) + return + } + + p.Context.Transaction = tx + + _, err = p.DeleteBlock(blockID) + if err != nil { + log.IfErr(tx.Rollback()) + writeGeneralSQLError(w, method, err) + return + } + + err = p.RemoveBlockReference(blockID) + if err != nil { + log.IfErr(tx.Rollback()) + writeGeneralSQLError(w, method, err) + return + } + + log.IfErr(tx.Commit()) + + writeSuccessEmptyJSON(w) +} diff --git a/core/api/request/block.go b/core/api/request/block.go index 2f42a415..97e8ce9f 100644 --- a/core/api/request/block.go +++ b/core/api/request/block.go @@ -12,6 +12,7 @@ package request import ( + "database/sql" "fmt" "time" @@ -113,6 +114,30 @@ func (p *Persister) DecrementBlockUsage(id string) (err error) { return } +// RemoveBlockReference clears page.blockid for given blockID. +func (p *Persister) RemoveBlockReference(id string) (err error) { + stmt, err := p.Context.Transaction.Preparex("UPDATE page SET blockid='', revised=? WHERE orgid=? AND blockid=?") + defer utility.Close(stmt) + if err != nil { + log.Error(fmt.Sprintf("Unable to prepare update RemoveBlockReference id %s", id), err) + return + } + + _, err = stmt.Exec(time.Now().UTC(), p.Context.OrgID, id) + + // skip no rows affected + if err == sql.ErrNoRows { + return + } + + if err != nil { + log.Error(fmt.Sprintf("Unable to execute RemoveBlockReference id %s", id), err) + return + } + + return +} + // UpdateBlock updates existing reusable content block item. func (p *Persister) UpdateBlock(b entity.Block) (err error) { b.Revised = time.Now().UTC()