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

add/edit smart sections

This commit is contained in:
Harvey Kandola 2017-03-03 20:17:49 +00:00
parent be4a95df96
commit a7ac034d2c
33 changed files with 1209 additions and 603 deletions

View file

@ -19,18 +19,14 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
editMode: false,
didReceiveAttrs(){
if (this.get('mode') === 'edit') {
this.send('onEdit');
}
this.audit.record("viewed-document-section-" + this.get('model.page.contentType'));
},
didInsertElement() {
let self = this;
this.get('sectionService').refresh(this.get('model.document.id')).then(function (changes) {
this.get('sectionService').refresh(this.get('document.id')).then(function (changes) {
changes.forEach(function (newPage) {
let oldPage = self.get('model.page');
let oldPage = self.get('page');
if (!_.isUndefined(oldPage) && oldPage.get('id') === newPage.get('id')) {
oldPage.set('body', newPage.get('body'));
oldPage.set('revised', newPage.get('revised'));
@ -41,30 +37,37 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
},
actions: {
onEdit() {
this.set('viewMode', false);
this.set('editMode', true);
this.set('mode', 'edit');
onExpand() {
this.set('expanded', !this.get('expanded'));
},
onView() {
this.set('viewMode', true);
this.set('editMode', false);
this.set('mode', 'view');
onSavePageAsBlock(block) {
this.attrs.onSavePageAsBlock(block);
},
onCancel() {
this.send('onView');
onCopyPage(documentId) {
this.attrs.onCopyPage(this.get('page.id'), documentId);
},
onAction(page, meta) {
this.get('onAction')(page, meta);
this.send('onView');
onMovePage(documentId) {
this.attrs.onMovePage(this.get('page.id'), documentId);
},
onDelete() {
this.get('onDelete')(this.get('model.document'), this.get('model.page'));
return true;
onDeletePage(deleteChildren) {
let page = this.get('page');
if (is.undefined(page)) {
return;
}
let params = {
id: page.get('id'),
title: page.get('title'),
children: deleteChildren
};
this.attrs.onDeletePage(params);
},
}
});

View file

@ -30,6 +30,10 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
toEdit: '',
didReceiveAttrs() {
if (this.get('isDestroyed') || this.get('isDestroying')) {
return;
}
this.get('sectionService').getSpaceBlocks(this.get('folder.id')).then((blocks) => {
this.set('blocks', blocks);
this.set('hasBlocks', blocks.get('length') > 0);
@ -73,7 +77,7 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
// local link? exists?
if ((link.linkType === "section" || link.linkType === "tab") && link.documentId === doc.get('id')) {
let exists = self.get('allPages').findBy('id', link.targetId);
let exists = self.get('pages').findBy('id', link.targetId);
if (_.isUndefined(exists)) {
link.orphan = true;
@ -120,7 +124,11 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
const promise = this.get('onInsertSection')(model);
promise.then((id) => {
if (model.page.contentType === 'section') {
this.set('toEdit', id);
} else {
this.get('onEditSection')(id);
}
});
},

View file

@ -0,0 +1,200 @@
// 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 Ember from 'ember';
import TooltipMixin from '../../mixins/tooltip';
const {
computed,
inject: { service }
} = Ember;
export default Ember.Component.extend(TooltipMixin, {
documentService: service('document'),
expanded: false,
deleteChildren: false,
menuOpen: false,
blockTitle: "",
blockExcerpt: "",
documentList: [], //includes the current document
documentListOthers: [], //excludes the current document
selectedDocument: null,
checkId: computed('page', function () {
let id = this.get('page.id');
return `delete-check-button-${id}`;
}),
menuTarget: computed('page', function () {
let id = this.get('page.id');
return `page-menu-${id}`;
}),
deleteButtonId: computed('page', function () {
let id = this.get('page.id');
return `delete-page-button-${id}`;
}),
publishButtonId: computed('page', function () {
let id = this.get('page.id');
return `publish-button-${id}`;
}),
publishDialogId: computed('page', function () {
let id = this.get('page.id');
return `publish-dialog-${id}`;
}),
blockTitleId: computed('page', function () {
let id = this.get('page.id');
return `block-title-${id}`;
}),
blockExcerptId: computed('page', function () {
let id = this.get('page.id');
return `block-excerpt-${id}`;
}),
copyButtonId: computed('page', function () {
let id = this.get('page.id');
return `copy-page-button-${id}`;
}),
copyDialogId: computed('page', function () {
let id = this.get('page.id');
return `copy-dialog-${id}`;
}),
moveButtonId: computed('page', function () {
let id = this.get('page.id');
return `move-page-button-${id}`;
}),
moveDialogId: computed('page', function () {
let id = this.get('page.id');
return `move-dialog-${id}`;
}),
didRender() {
$("#" + this.get('blockTitleId')).removeClass('error');
$("#" + this.get('blockExcerptId')).removeClass('error');
},
actions: {
toggleExpand() {
this.set('expanded', !this.get('expanded'));
this.get('onExpand')();
},
onMenuOpen() {
if ($('#' + this.get('publishDialogId')).is( ":visible" )) {
return;
}
if ($('#' + this.get('copyDialogId')).is( ":visible" )) {
return;
}
if ($('#' + this.get('moveDialogId')).is( ":visible" )) {
return;
}
this.set('menuOpen', !this.get('menuOpen'));
},
onEdit() {
this.attrs.onEdit();
},
deletePage() {
this.attrs.onDeletePage(this.get('deleteChildren'));
},
onSavePageAsBlock() {
let page = this.get('page');
let titleElem = '#' + this.get('blockTitleId');
let blockTitle = this.get('blockTitle');
if (is.empty(blockTitle)) {
$(titleElem).addClass('error');
return;
}
let excerptElem = '#' + this.get('blockExcerptId');
let blockExcerpt = this.get('blockExcerpt');
blockExcerpt = blockExcerpt.replace(/\n/g, "");
if (is.empty(blockExcerpt)) {
$(excerptElem).addClass('error');
return;
}
this.get('documentService').getPageMeta(this.get('document.id'), page.get('id')).then((pm) => {
let block = {
folderId: this.get('folder.id'),
contentType: page.get('contentType'),
pageType: page.get('pageType'),
title: blockTitle,
body: page.get('body'),
excerpt: blockExcerpt,
rawBody: pm.get('rawBody'),
config: pm.get('config'),
externalSource: pm.get('externalSource')
};
this.attrs.onSavePageAsBlock(block);
this.set('menuOpen', false);
this.set('blockTitle', '');
this.set('blockExcerpt', '');
$(titleElem).removeClass('error');
$(excerptElem).removeClass('error');
return true;
});
},
// Copy/move actions
onCopyDialogOpen() {
// Fetch document targets once.
if (this.get('documentList').length > 0) {
return;
}
this.get('documentService').getPageMoveCopyTargets().then((d) => {
let me = this.get('document');
this.set('documentList', d);
this.set('documentListOthers', d.filter((item) => item.get('id') !== me.get('id')));
});
},
onTargetChange(d) {
this.set('selectedDocument', d);
},
onCopyPage() {
// can't proceed if no data
if (this.get('documentList.length') === 0) {
return;
}
let targetDocumentId = this.get('document.id');
if (is.not.null(this.get('selectedDocument'))) {
targetDocumentId = this.get('selectedDocument.id');
}
this.attrs.onCopyPage(targetDocumentId);
return true;
},
onMovePage() {
// can't proceed if no data
if (this.get('documentListOthers.length') === 0) {
return;
}
if (is.null(this.get('selectedDocument'))) {
this.set('selectedDocument', this.get('documentListOthers')[0]);
}
let targetDocumentId = this.get('selectedDocument.id');
this.attrs.onMovePage(targetDocumentId);
return true;
}
}
});

View file

@ -1,6 +1,5 @@
<!DOCTYPE html>
<html>
<head>
{{content-for 'head'}}
<meta charset="utf-8">
@ -17,7 +16,6 @@
<link rel="stylesheet" href="/assets/documize.css">
{{content-for 'head-footer'}}
</head>
<body>
{{content-for 'body'}}
<script src="/assets/vendor.js"></script>
@ -29,5 +27,4 @@
<script src="/codemirror/addon/runmode/colorize.js"></script>
{{content-for 'body-footer'}}
</body>
</html>

View file

@ -13,233 +13,233 @@ import Ember from 'ember';
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: [],
toggled: false,
// to test
// to test
// Jump to the right part of the document.
scrollToPage(pageId) {
Ember.run.schedule('afterRender', function () {
let dest;
let target = "#page-title-" + pageId;
let targetOffset = $(target).offset();
if (is.undefined(targetOffset)) {
return;
}
dest = targetOffset.top > $(document).height() - $(window).height() ? $(document).height() - $(window).height() : targetOffset.top;
// small correction to ensure we also show page title
dest = dest > 50 ? dest - 74 : dest;
$("html,body").animate({
scrollTop: dest
}, 500, "linear");
$(".toc-index-item").removeClass("selected");
$("#index-" + pageId).addClass("selected");
});
},
actions: {
toggleSidebar() {
this.set('toggled', !this.get('toggled'));
},
onTagChange(tags) {
let doc = this.get('model.document');
doc.set('tags', tags);
this.get('documentService').save(doc);
},
onSaveDocument(doc) {
this.get('documentService').save(doc);
this.showNotification('Saved');
},
onCopyPage(pageId, targetDocumentId) {
let documentId = this.get('model.document.id');
this.get('documentService').copyPage(documentId, pageId, targetDocumentId).then(() => {
this.showNotification("Copied");
// refresh data if copied to same document
if (documentId === targetDocumentId) {
this.get('target.router').refresh();
}
});
},
onMovePage(pageId, targetDocumentId) {
let documentId = this.get('model.document.id');
this.get('documentService').copyPage(documentId, pageId, targetDocumentId).then(() => {
this.showNotification("Moved");
this.send('onPageDeleted', { id: pageId, children: false });
});
},
onSavePage(page, meta) {
let self = this;
let documentId = this.get('model.document.id');
let model = {
page: page.toJSON({ includeId: true }),
meta: meta.toJSON({ includeId: true })
};
this.get('documentService').updatePage(documentId, page.get('id'), model).then(function () {
self.audit.record("edited-page");
self.get('documentService').getPages(documentId).then((pages) => {
self.set('model.allPages', pages);
self.set('model.pages', pages.filterBy('pageType', 'section'));
self.set('model.tabs', pages.filterBy('pageType', 'tab'));
});
});
},
onPageDeleted(deletePage) {
let documentId = this.get('model.document.id');
let pages = this.get('model.pages');
let deleteId = deletePage.id;
let deleteChildren = deletePage.children;
let page = _.findWhere(pages, {
id: deleteId
});
let pageIndex = _.indexOf(pages, page, false);
let pendingChanges = [];
this.audit.record("deleted-page");
// select affected pages
for (var i = pageIndex + 1; i < pages.get('length'); i++) {
if (pages[i].get('level') <= page.get('level')) {
break;
}
pendingChanges.push({
pageId: pages[i].get('id'),
level: pages[i].get('level') - 1
});
}
if (deleteChildren) {
// nuke of page tree
pendingChanges.push({
pageId: deleteId
});
this.get('documentService').deletePages(documentId, deleteId, pendingChanges).then(() => {
// update our models so we don't have to reload from db
for (var i = 0; i < pendingChanges.length; i++) {
let pageId = pendingChanges[i].pageId;
this.set('model.pages', _.reject(pages, function (p) { //jshint ignore: line
return p.get('id') === pageId;
}));
}
this.set('model.pages', _.sortBy(pages, "sequence"));
this.get('target.router').refresh();
});
} else {
// page delete followed by re-leveling child pages
this.get('documentService').deletePage(documentId, deleteId).then(() => {
this.set('model.pages', _.reject(pages, function (p) {
return p.get('id') === deleteId;
}));
this.send('onPageLevelChange', pendingChanges);
});
}
},
onInsertSection(data) {
return new Ember.RSVP.Promise((resolve) => {
this.get('documentService').addPage(this.get('model.document.id'), data).then((newPage) => {
let data = this.get('store').normalize('page', newPage);
this.get('store').push(data);
this.get('documentService').getPages(this.get('model.document.id')).then((pages) => {
this.set('model.allPages', pages);
this.set('model.pages', pages.filterBy('pageType', 'section'));
this.set('model.tabs', pages.filterBy('pageType', 'tab'));
resolve(newPage.id);
// this.get('documentService').getPageMeta(this.get('model.document.id'), newPage.id).then(() => {
// console.log("ready to edit");
// // this.transitionToRoute('document.edit',
// // this.get('model.folder.id'),
// // this.get('model.folder.slug'),
// // this.get('model.document.id'),
// // this.get('model.document.slug'),
// // newPage.id);
// documentService: Ember.inject.service('document'),
// templateService: Ember.inject.service('template'),
// sectionService: Ember.inject.service('section'),
// page: null,
// folder: {},
// pages: [],
// toggled: false,
//
// // to test
// // to test
// // Jump to the right part of the document.
// scrollToPage(pageId) {
// Ember.run.schedule('afterRender', function () {
// let dest;
// let target = "#page-title-" + pageId;
// let targetOffset = $(target).offset();
//
// if (is.undefined(targetOffset)) {
// return;
// }
//
// dest = targetOffset.top > $(document).height() - $(window).height() ? $(document).height() - $(window).height() : targetOffset.top;
// // small correction to ensure we also show page title
// dest = dest > 50 ? dest - 74 : dest;
//
// $("html,body").animate({
// scrollTop: dest
// }, 500, "linear");
// $(".toc-index-item").removeClass("selected");
// $("#index-" + pageId).addClass("selected");
// });
});
});
});
},
// to test
onPageSequenceChange(changes) {
this.get('documentService').changePageSequence(this.get('model.document.id'), changes).then(() => {
_.each(changes, (change) => {
let pageContent = _.findWhere(this.get('model.pages'), {
id: change.pageId
});
if (is.not.undefined(pageContent)) {
pageContent.set('sequence', change.sequence);
}
});
this.set('model.pages', this.get('model.pages').sortBy('sequence'));
this.get('target.router').refresh();
});
},
// to test
onPageLevelChange(changes) {
this.get('documentService').changePageLevel(this.get('model.document.id'), changes).then(() => {
_.each(changes, (change) => {
let pageContent = _.findWhere(this.get('model.pages'), {
id: change.pageId
});
if (is.not.undefined(pageContent)) {
pageContent.set('level', change.level);
}
});
let pages = this.get('model.pages');
pages = pages.sortBy('sequence');
this.set('model.pages', []);
this.set('model.pages', pages);
this.get('target.router').refresh();
});
},
// to test
gotoPage(pageId) {
if (is.null(pageId)) {
return;
}
this.scrollToPage(pageId);
},
// to test
onSavePageAsBlock(block) {
this.get('sectionService').addBlock(block).then(() => {
this.showNotification("Published");
});
}
}
// },
//
// actions: {
// toggleSidebar() {
// this.set('toggled', !this.get('toggled'));
// },
//
// onTagChange(tags) {
// let doc = this.get('model.document');
// doc.set('tags', tags);
// this.get('documentService').save(doc);
// },
//
// onSaveDocument(doc) {
// this.get('documentService').save(doc);
// this.showNotification('Saved');
// },
//
// onCopyPage(pageId, targetDocumentId) {
// let documentId = this.get('model.document.id');
// this.get('documentService').copyPage(documentId, pageId, targetDocumentId).then(() => {
// this.showNotification("Copied");
//
// // refresh data if copied to same document
// if (documentId === targetDocumentId) {
// this.get('target.router').refresh();
// }
// });
// },
//
// onMovePage(pageId, targetDocumentId) {
// let documentId = this.get('model.document.id');
//
// this.get('documentService').copyPage(documentId, pageId, targetDocumentId).then(() => {
// this.showNotification("Moved");
//
// this.send('onPageDeleted', { id: pageId, children: false });
// });
// },
//
// onSavePage(page, meta) {
// let self = this;
// let documentId = this.get('model.document.id');
// let model = {
// page: page.toJSON({ includeId: true }),
// meta: meta.toJSON({ includeId: true })
// };
//
// this.get('documentService').updatePage(documentId, page.get('id'), model).then(function () {
// self.audit.record("edited-page");
// self.get('documentService').getPages(documentId).then((pages) => {
// self.set('model.allPages', pages);
// self.set('model.pages', pages.filterBy('pageType', 'section'));
// self.set('model.tabs', pages.filterBy('pageType', 'tab'));
// });
//
// });
// },
//
// onPageDeleted(deletePage) {
// let documentId = this.get('model.document.id');
// let pages = this.get('model.pages');
// let deleteId = deletePage.id;
// let deleteChildren = deletePage.children;
// let page = _.findWhere(pages, {
// id: deleteId
// });
// let pageIndex = _.indexOf(pages, page, false);
// let pendingChanges = [];
//
// this.audit.record("deleted-page");
//
// // select affected pages
// for (var i = pageIndex + 1; i < pages.get('length'); i++) {
// if (pages[i].get('level') <= page.get('level')) {
// break;
// }
//
// pendingChanges.push({
// pageId: pages[i].get('id'),
// level: pages[i].get('level') - 1
// });
// }
//
// if (deleteChildren) {
// // nuke of page tree
// pendingChanges.push({
// pageId: deleteId
// });
//
// this.get('documentService').deletePages(documentId, deleteId, pendingChanges).then(() => {
// // update our models so we don't have to reload from db
// for (var i = 0; i < pendingChanges.length; i++) {
// let pageId = pendingChanges[i].pageId;
// this.set('model.pages', _.reject(pages, function (p) { //jshint ignore: line
// return p.get('id') === pageId;
// }));
// }
//
// this.set('model.pages', _.sortBy(pages, "sequence"));
// this.get('target.router').refresh();
// });
// } else {
// // page delete followed by re-leveling child pages
// this.get('documentService').deletePage(documentId, deleteId).then(() => {
// this.set('model.pages', _.reject(pages, function (p) {
// return p.get('id') === deleteId;
// }));
//
// this.send('onPageLevelChange', pendingChanges);
// });
// }
// },
//
// onInsertSection(data) {
// return new Ember.RSVP.Promise((resolve) => {
// this.get('documentService').addPage(this.get('model.document.id'), data).then((newPage) => {
// let data = this.get('store').normalize('page', newPage);
// this.get('store').push(data);
//
// this.get('documentService').getPages(this.get('model.document.id')).then((pages) => {
// this.set('model.allPages', pages);
// this.set('model.pages', pages.filterBy('pageType', 'section'));
// this.set('model.tabs', pages.filterBy('pageType', 'tab'));
//
// resolve(newPage.id);
//
// // this.get('documentService').getPageMeta(this.get('model.document.id'), newPage.id).then(() => {
// // console.log("ready to edit");
// // // this.transitionToRoute('document.edit',
// // // this.get('model.folder.id'),
// // // this.get('model.folder.slug'),
// // // this.get('model.document.id'),
// // // this.get('model.document.slug'),
// // // newPage.id);
// // });
// });
// });
// });
// },
//
// // to test
// onPageSequenceChange(changes) {
// this.get('documentService').changePageSequence(this.get('model.document.id'), changes).then(() => {
// _.each(changes, (change) => {
// let pageContent = _.findWhere(this.get('model.pages'), {
// id: change.pageId
// });
//
// if (is.not.undefined(pageContent)) {
// pageContent.set('sequence', change.sequence);
// }
// });
//
// this.set('model.pages', this.get('model.pages').sortBy('sequence'));
// this.get('target.router').refresh();
// });
// },
//
// // to test
// onPageLevelChange(changes) {
// this.get('documentService').changePageLevel(this.get('model.document.id'), changes).then(() => {
// _.each(changes, (change) => {
// let pageContent = _.findWhere(this.get('model.pages'), {
// id: change.pageId
// });
//
// if (is.not.undefined(pageContent)) {
// pageContent.set('level', change.level);
// }
// });
//
// let pages = this.get('model.pages');
// pages = pages.sortBy('sequence');
// this.set('model.pages', []);
// this.set('model.pages', pages);
// this.get('target.router').refresh();
// });
// },
//
// // to test
// gotoPage(pageId) {
// if (is.null(pageId)) {
// return;
// }
//
// this.scrollToPage(pageId);
// },
//
// // to test
// onSavePageAsBlock(block) {
// this.get('sectionService').addBlock(block).then(() => {
// this.showNotification("Published");
// });
// }
// }
});
/*

View file

@ -0,0 +1,321 @@
// 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 Ember from 'ember';
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: [],
toggled: false,
// to test
// to test
// Jump to the right part of the document.
scrollToPage(pageId) {
Ember.run.schedule('afterRender', function () {
let dest;
let target = "#page-title-" + pageId;
let targetOffset = $(target).offset();
if (is.undefined(targetOffset)) {
return;
}
dest = targetOffset.top > $(document).height() - $(window).height() ? $(document).height() - $(window).height() : targetOffset.top;
// small correction to ensure we also show page title
dest = dest > 50 ? dest - 74 : dest;
$("html,body").animate({
scrollTop: dest
}, 500, "linear");
$(".toc-index-item").removeClass("selected");
$("#index-" + pageId).addClass("selected");
});
},
actions: {
toggleSidebar() {
this.set('toggled', !this.get('toggled'));
},
onTagChange(tags) {
let doc = this.get('model.document');
doc.set('tags', tags);
this.get('documentService').save(doc);
},
onSaveDocument(doc) {
this.get('documentService').save(doc);
this.showNotification('Saved');
},
onCopyPage(pageId, targetDocumentId) {
let documentId = this.get('model.document.id');
this.get('documentService').copyPage(documentId, pageId, targetDocumentId).then(() => {
this.showNotification("Copied");
// refresh data if copied to same document
if (documentId === targetDocumentId) {
this.get('target.router').refresh();
}
});
},
onMovePage(pageId, targetDocumentId) {
let documentId = this.get('model.document.id');
this.get('documentService').copyPage(documentId, pageId, targetDocumentId).then(() => {
this.showNotification("Moved");
this.send('onPageDeleted', { id: pageId, children: false });
});
},
onSavePage(page, meta) {
let self = this;
let documentId = this.get('model.document.id');
let model = {
page: page.toJSON({ includeId: true }),
meta: meta.toJSON({ includeId: true })
};
this.get('documentService').updatePage(documentId, page.get('id'), model).then(function () {
self.audit.record("edited-page");
self.get('documentService').getPages(documentId).then((pages) => {
self.set('model.pages', pages);
});
});
},
onPageDeleted(deletePage) {
let documentId = this.get('model.document.id');
let pages = this.get('model.pages');
let deleteId = deletePage.id;
let deleteChildren = deletePage.children;
let page = _.findWhere(pages, {
id: deleteId
});
let pageIndex = _.indexOf(pages, page, false);
let pendingChanges = [];
this.audit.record("deleted-page");
// select affected pages
for (var i = pageIndex + 1; i < pages.get('length'); i++) {
if (pages[i].get('level') <= page.get('level')) {
break;
}
pendingChanges.push({
pageId: pages[i].get('id'),
level: pages[i].get('level') - 1
});
}
if (deleteChildren) {
// nuke of page tree
pendingChanges.push({
pageId: deleteId
});
this.get('documentService').deletePages(documentId, deleteId, pendingChanges).then(() => {
// update our models so we don't have to reload from db
for (var i = 0; i < pendingChanges.length; i++) {
let pageId = pendingChanges[i].pageId;
this.set('model.pages', _.reject(pages, function (p) { //jshint ignore: line
return p.get('id') === pageId;
}));
}
this.set('model.pages', _.sortBy(pages, "sequence"));
this.get('target.router').refresh();
});
} else {
// page delete followed by re-leveling child pages
this.get('documentService').deletePage(documentId, deleteId).then(() => {
this.set('model.pages', _.reject(pages, function (p) {
return p.get('id') === deleteId;
}));
this.send('onPageLevelChange', pendingChanges);
});
}
},
onInsertSection(data) {
return new Ember.RSVP.Promise((resolve) => {
this.get('documentService').addPage(this.get('model.document.id'), data).then((newPage) => {
let data = this.get('store').normalize('page', newPage);
this.get('store').push(data);
this.get('documentService').getPages(this.get('model.document.id')).then((pages) => {
this.set('model.pages', pages);
resolve(newPage.id);
});
});
});
},
onEditSection(pageId) {
this.transitionToRoute('document.section',
this.get('model.folder.id'),
this.get('model.folder.slug'),
this.get('model.document.id'),
this.get('model.document.slug'),
pageId);
},
// to test
onPageSequenceChange(changes) {
this.get('documentService').changePageSequence(this.get('model.document.id'), changes).then(() => {
_.each(changes, (change) => {
let pageContent = _.findWhere(this.get('model.pages'), {
id: change.pageId
});
if (is.not.undefined(pageContent)) {
pageContent.set('sequence', change.sequence);
}
});
this.set('model.pages', this.get('model.pages').sortBy('sequence'));
this.get('target.router').refresh();
});
},
// to test
onPageLevelChange(changes) {
this.get('documentService').changePageLevel(this.get('model.document.id'), changes).then(() => {
_.each(changes, (change) => {
let pageContent = _.findWhere(this.get('model.pages'), {
id: change.pageId
});
if (is.not.undefined(pageContent)) {
pageContent.set('level', change.level);
}
});
let pages = this.get('model.pages');
pages = pages.sortBy('sequence');
this.set('model.pages', []);
this.set('model.pages', pages);
this.get('target.router').refresh();
});
},
// to test
gotoPage(pageId) {
if (is.null(pageId)) {
return;
}
this.scrollToPage(pageId);
},
// to test
onSavePageAsBlock(block) {
this.get('sectionService').addBlock(block).then(() => {
this.showNotification("Published");
});
}
}
});
/*
gotoPage(pageId) {
if (is.null(pageId)) {
return;
}
this.scrollToPage(pageId);
},
onSaveTemplate(name, desc) {
this.get('templateService').saveAsTemplate(this.get('model.document.id'), name, desc).then(function () {});
},
onSaveMeta(doc) {
this.get('documentService').save(doc).then(() => {
this.transitionToRoute('document.index');
});
},
onInsertBlock(block) {
this.audit.record("added-content-block-" + block.get('contentType'));
let page = {
documentId: this.get('model.document.id'),
title: `${block.get('title')}`,
level: 1,
sequence: 0,
body: block.get('body'),
contentType: block.get('contentType'),
pageType: block.get('pageType'),
blockId: block.get('id')
};
let meta = {
documentId: this.get('model.document.id'),
rawBody: block.get('rawBody'),
config: block.get('config'),
externalSource: block.get('externalSource')
};
let model = {
page: page,
meta: meta
};
this.get('documentService').addPage(this.get('model.document.id'), model).then((newPage) => {
let data = this.get('store').normalize('page', newPage);
this.get('store').push(data);
this.get('documentService').getPages(this.get('model.document.id')).then((pages) => {
this.set('model.pages', pages.filterBy('pageType', 'section'));
this.set('model.tabs', pages.filterBy('pageType', 'tab'));
this.get('documentService').getPageMeta(this.get('model.document.id'), newPage.id).then(() => {
this.transitionToRoute('document.edit',
this.get('model.folder.id'),
this.get('model.folder.slug'),
this.get('model.document.id'),
this.get('model.document.slug'),
newPage.id);
});
});
});
},
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");
this.send("showNotification", "Deleted");
this.transitionToRoute('folder', this.get('model.folder.id'), this.get('model.folder.slug'));
});
}
*/

View file

@ -0,0 +1,46 @@
// 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 Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
documentService: Ember.inject.service('document'),
linkService: Ember.inject.service('link'),
folderService: Ember.inject.service('folder'),
userService: Ember.inject.service('user'),
queryParams: {
page: {
refreshModel: false
}
},
beforeModel(transition) {
this.set('pageId', is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : "");
},
model() {
let document = this.modelFor('document').document;
this.browser.setTitle(document.get('name'));
this.browser.setMetaDescription(document.get('excerpt'));
return Ember.RSVP.hash({
folders: this.modelFor('document').folders,
folder: this.modelFor('document').folder,
document: this.modelFor('document').document,
page: this.get('pageId'),
isEditor: this.get('folderService').get('canEditCurrentFolder'),
pages: this.modelFor('document').pages,
links: this.modelFor('document').links,
sections: this.modelFor('document').sections
});
}
});

View file

@ -0,0 +1,73 @@
<div id="wrapper" class={{if toggled 'toggled'}}>
<div id="sidebar-wrapper">
<div class="document-sidebar-content">
{{#if model.document.template}}
<div class="is-template">TEMPLATE</div>
{{/if}}
{{document/tag-editor documentTags=model.document.tags isEditor=model.isEditor onChange=(action 'onTagChange')}}
{{#layout/zone-document-sidebar}}
{{/layout/zone-document-sidebar}}
</div>
<div class="document-sidebar-toolbar">
<div class="round-button-mono">
<i class="material-icons color-gray">more_horiz</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">view_headline</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">attach_file</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">timeline</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">person</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">chat_bubble</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">share</i>
</div>
</div>
</div>
<div id="page-content-wrapper">
<div class="container">
<div class="row">
<div class="col-lg-12">
{{#if toggled}}
<div id="sidebar-toggle" class="pull-right" {{action 'toggleSidebar'}}>
<div class="round-button button-black">
<i class="material-icons">keyboard_arrow_left</i>
</div>
</div>
{{else}}
<div id="sidebar-toggle" class="pull-right" {{action 'toggleSidebar'}}>
<div class="round-button button-black">
<i class="material-icons">keyboard_arrow_right</i>
</div>
</div>
{{/if}}
<div id="zone-document-content" class="zone-document-content">
<div class="back-to-space">
{{#link-to 'folder' model.folder.id model.folder.slug}}
<i class="material-icons">arrow_back</i>&nbsp;{{model.folder.name}}
{{/link-to}}
</div>
{{document/document-heading document=model.document isEditor=model.isEditor onSaveDocument=(action 'onSaveDocument')}}
{{document/document-view document=model.document links=model.links pages=model.pages
folder=model.folder folders=model.folders sections=model.sections isEditor=model.isEditor onSavePage=(action 'onSavePage') gotoPage=(action 'gotoPage') onInsertSection=(action 'onInsertSection') onSavePageAsBlock=(action 'onSavePageAsBlock') onCopyPage=(action 'onCopyPage') onMovePage=(action 'onMovePage') onDeletePage=(action 'onPageDeleted') onEditSection=(action 'onEditSection')}}
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -16,6 +16,7 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
sectionService: Ember.inject.service('section'),
documentService: Ember.inject.service('document'),
folderService: Ember.inject.service('folder'),
linkService: Ember.inject.service('link'),
beforeModel(transition) {
this.set('pageId', is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : "");
@ -36,9 +37,7 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
this.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
this.get('documentService').getPages(this.get('documentId')).then((pages) => {
this.set('allPages', pages);
this.set('pages', pages.filterBy('pageType', 'section'));
this.set('tabs', pages.filterBy('pageType', 'tab'));
this.set('pages', pages);
resolve();
});
});
@ -55,17 +54,20 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
document: this.get('document'),
page: this.get('pageId'),
isEditor: this.get('isEditor'),
allPages: this.get('allPages'),
pages: this.get('pages'),
tabs: this.get('tabs'),
sections: this.get('sectionService').getAll().then((sections) => {
return sections;
// return sections.filterBy('pageType', 'section');
// return sections.filterBy('pageType', 'tab');
}),
links: this.get('linkService').getDocumentLinks(this.get('documentId')),
sections: this.get('sectionService').getAll()
});
},
activate() {
$('body').addClass('background-color-off-white');
},
deactivate() {
$('body').removeClass('background-color-off-white');
},
actions: {
error(error /*, transition*/ ) {
console.log(error);

View file

@ -18,6 +18,14 @@ export default Ember.Controller.extend(NotifierMixin, {
mode: null,
actions: {
onCancel() {
this.transitionToRoute('document.index',
this.get('model.folder.id'),
this.get('model.folder.slug'),
this.get('model.document.id'),
this.get('model.document.slug'));
},
onAction(page, meta) {
this.showNotification("Saving");
@ -30,17 +38,13 @@ export default Ember.Controller.extend(NotifierMixin, {
this.audit.record("edited-page");
let data = this.get('store').normalize('page', page);
this.get('store').push(data);
this.get('target.router').refresh();
this.transitionToRoute('document.index',
this.get('model.folder.id'),
this.get('model.folder.slug'),
this.get('model.document.id'),
this.get('model.document.slug'));
});
},
onDelete(document, page) {
this.get('documentService').deletePage(document.get('id'), page.get('id')).then(() => {
this.audit.record("deleted-page");
this.showNotification('Deleted');
this.transitionToRoute('document');
this.get('target.router').refresh();
});
}
}
});

View file

@ -32,12 +32,21 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
folders: this.modelFor('document').folders,
folder: this.modelFor('document').folder,
document: this.modelFor('document').document,
pageId: this.modelFor('document').page,
isEditor: this.get('folderService').get('canEditCurrentFolder'),
pages: this.modelFor('document').pages,
tabs: this.get('documentService').getPages(this.modelFor('document').document.get('id')).then((pages) => {
return pages.filterBy('pageType', 'tab');
}),
links: this.modelFor('document').links,
sections: this.modelFor('document').sections,
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)
});
},
activate() {
$('body').addClass('background-color-off-white');
},
deactivate() {
$('body').removeClass('background-color-off-white');
}
});

View file

@ -1 +1,17 @@
{{document/document-tab mode=mode model=model onAction=(action 'onAction') onDelete=(action 'onDelete')}}
<div class="zone-section-editor">
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div id="zone-document-content" class="zone-document-content">
<div class="back-to-space">
{{#link-to 'document.index' model.folder.id model.folder.slug model.document.id model.document.slug}}
<i class="material-icons">arrow_back</i>&nbsp;{{model.document.name}}
{{/link-to}}
</div>
{{document/document-heading document=model.document isEditor=false}}
{{document/document-editor document=model.document folder=model.folder page=model.page meta=model.meta onCancel=(action 'onCancel') onAction=(action 'onAction')}}
</div>
</div>
</div>
</div>
</div>

View file

@ -1,75 +1,2 @@
{{layout/zone-navigation}}
<div id="wrapper" class={{if toggled 'toggled'}}>
<div id="sidebar-wrapper">
<div class="document-sidebar-content">
{{#if model.document.template}}
<div class="is-template">TEMPLATE</div>
{{/if}}
{{document/tag-editor documentTags=model.document.tags isEditor=model.isEditor onChange=(action 'onTagChange')}}
{{#layout/zone-document-sidebar}}
{{/layout/zone-document-sidebar}}
</div>
<div class="document-sidebar-toolbar">
<div class="round-button-mono">
<i class="material-icons color-gray">more_horiz</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">view_headline</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">attach_file</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">timeline</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">person</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">chat_bubble</i>
</div>
<div class="margin-top-20"></div>
<div class="round-button-mono">
<i class="material-icons color-gray">share</i>
</div>
</div>
</div>
<div id="page-content-wrapper">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
{{#if toggled}}
<div id="sidebar-toggle" class="pull-right" {{action 'toggleSidebar'}}>
<div class="round-button button-black">
<i class="material-icons">keyboard_arrow_left</i>
</div>
</div>
{{else}}
<div id="sidebar-toggle" class="pull-right" {{action 'toggleSidebar'}}>
<div class="round-button button-black">
<i class="material-icons">keyboard_arrow_right</i>
</div>
</div>
{{/if}}
<div id="zone-document-content" class="zone-document-content">
<div class="back-to-space">
{{#link-to 'folder' model.folder.id model.folder.slug}}
<i class="material-icons">arrow_back</i>&nbsp;{{model.folder.name}}
{{/link-to}}
</div>
{{document/document-heading document=model.document isEditor=model.isEditor onSaveDocument=(action 'onSaveDocument')}}
{{document/document-view document=model.document links=model.links allPages=model.allPages tabs=model.tabs pages=model.pages
folder=model.folder folders=model.folders sections=model.sections isEditor=model.isEditor onSavePage=(action 'onSavePage') gotoPage=(action 'gotoPage') onInsertSection=(action 'onInsertSection') onSavePageAsBlock=(action 'onSavePageAsBlock') onCopyPage=(action 'onCopyPage') onMovePage=(action 'onMovePage') onDeletePage=(action 'onPageDeleted')}}
</div>
</div>
</div>
</div>
</div>
</div>
{{outlet}}

View file

@ -1,91 +0,0 @@
// 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 Ember from 'ember';
import NotifierMixin from '../../../mixins/notifier';
export default Ember.Controller.extend(NotifierMixin, {
documentService: Ember.inject.service('document'),
sectionService: Ember.inject.service('section'),
queryParams: ['page'],
// Jump to the right part of the document.
scrollToPage(pageId) {
Ember.run.schedule('afterRender', function () {
let dest;
let target = "#page-title-" + pageId;
let targetOffset = $(target).offset();
if (is.undefined(targetOffset)) {
return;
}
dest = targetOffset.top > $(document).height() - $(window).height() ? $(document).height() - $(window).height() : targetOffset.top;
// small correction to ensure we also show page title
dest = dest > 50 ? dest - 74 : dest;
$("html,body").animate({
scrollTop: dest
}, 500, "linear");
$(".toc-index-item").removeClass("selected");
$("#index-" + pageId).addClass("selected");
});
},
actions: {
gotoPage(pageId) {
if (is.null(pageId)) {
return;
}
this.scrollToPage(pageId);
},
onPageSequenceChange(changes) {
this.get('documentService').changePageSequence(this.get('model.document.id'), changes).then(() => {
_.each(changes, (change) => {
let pageContent = _.findWhere(this.get('model.pages'), {
id: change.pageId
});
if (is.not.undefined(pageContent)) {
pageContent.set('sequence', change.sequence);
}
});
this.set('model.pages', this.get('model.pages').sortBy('sequence'));
this.get('target.router').refresh();
});
},
onPageLevelChange(changes) {
this.get('documentService').changePageLevel(this.get('model.document.id'), changes).then(() => {
_.each(changes, (change) => {
let pageContent = _.findWhere(this.get('model.pages'), {
id: change.pageId
});
if (is.not.undefined(pageContent)) {
pageContent.set('level', change.level);
}
});
let pages = this.get('model.pages');
pages = pages.sortBy('sequence');
this.set('model.pages', pages);
this.get('target.router').refresh();
});
},
}
});

View file

@ -1,66 +0,0 @@
// 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 Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
documentService: Ember.inject.service('document'),
linkService: Ember.inject.service('link'),
folderService: Ember.inject.service('folder'),
userService: Ember.inject.service('user'),
queryParams: {
page: {
refreshModel: false
}
},
beforeModel(transition) {
this.set('pageId', is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : "");
this.set('folderId', this.paramsFor('document').folder_id);
this.set('documentId', this.paramsFor('document').document_id);
let folders = this.get('store').peekAll('folder');
let folder = this.get('store').peekRecord('folder', this.get('folderId'));
let document = this.get('store').peekRecord('document', this.get('documentId'));
this.set('document', document);
this.set('folders', folders);
this.set('folder', folder);
return new Ember.RSVP.Promise((resolve) => {
this.get('documentService').getPages(this.get('documentId')).then((pages) => {
this.set('allPages', pages);
this.set('pages', pages.filterBy('pageType', 'section'));
this.set('tabs', pages.filterBy('pageType', 'tab'));
resolve();
});
});
},
model() {
this.browser.setTitle(this.get('document.name'));
this.browser.setMetaDescription(this.get('document.excerpt'));
return Ember.RSVP.hash({
folders: this.get('folders'),
folder: this.get('folder'),
document: this.get('document'),
page: this.get('pageId'),
isEditor: this.get('folderService').get('canEditCurrentFolder'),
allPages: this.get('allPages'),
pages: this.get('pages'),
tabs: this.get('tabs'),
links: this.get('linkService').getDocumentLinks(this.get('documentId'))
});
}
});

View file

@ -44,9 +44,9 @@ export default Router.map(function () {
// this.route('edit', {
// path: 'edit/:page_id'
// });
this.route('wizard', {
path: 'add'
});
// this.route('wizard', {
// path: 'add'
// });
this.route('history', {
path: 'history'
});

View file

@ -78,6 +78,9 @@ $color-wysiwyg: #3c3c3c;
.background-color-white {
background-color: $color-white !important;
}
.background-color-off-white {
background-color: $color-off-white !important;
}
.background-color-primary {
background-color: $color-primary !important;
}

View file

@ -1,9 +1,10 @@
@import "activity.scss";
@import "edit-tools.scss";
@import "editor.scss";
@import "files.scss";
@import "history.scss";
@import "inline-editor.scss";
@import "layout.scss";
@import "section-editor.scss";
@import "sidebar.scss";
@import "toolbar.scss";
@import "view.scss";

View file

@ -0,0 +1,33 @@
.zone-section-editor {
// min-height: 500px; //ensure dropdowns render in viewport
// height: 100%;
margin-left: 60px;
padding: 20px 60px;
z-index: 777;
position: relative;
.section-editor {
@extend .transition-all;
@include border-radius(2px);
@include ease-in();
position: relative;
padding: 25px 50px;
box-shadow: 0 0 0 0.75pt $color-stroke,0 0 3pt 0.75pt $color-stroke;
background-color: $color-white;
> .buttons {
margin-top: 17px;
float: right;
}
> .canvas {
padding: 0;
}
.cancel-edits-dialog {
display: none;
}
}
}

View file

@ -1,9 +0,0 @@
.document-section {
> .toolbar {
margin-bottom: 10px;
> .buttons {
margin: 10px 0;
}
}
}

View file

@ -4,7 +4,6 @@
margin-left: 60px;
padding: 30px 70px;
z-index: 777;
background-color: $color-off-white;
}
.zone-document-content {
@ -56,13 +55,12 @@
.document-view {
margin: 0 0 50px 0;
max-width: 1200px;
.is-a-page {
@extend .transition-all;
@include border-radius(2px);
@include ease-in();
padding: 50px;
padding: 25px 50px;
box-shadow: 0 0 0 0.75pt $color-stroke,0 0 3pt 0.75pt $color-stroke;
background-color: $color-white;
@ -81,6 +79,72 @@
}
}
.is-a-tab {
// @extend .transition-all;
@include border-radius(2px);
@include ease-in();
padding: 25px 50px;
box-shadow: 0 0 0 0.75pt $color-stroke,0 0 3pt 0.75pt $color-stroke;
background-color: $color-white;
.icon {
text-align: center;
display: inline-block;
width: 40px;
vertical-align: bottom;
margin-right: 5px;
> .img {
text-align: center;
display: inline-block;
height: 30px;
width: 30px;
}
}
> .title {
font-size: 1.3rem;
font-weight: normal;
color: $color-off-black;
letter-spacing: 0.5px;
margin-top: 8px;
}
&:hover {
.page-title {
> .page-toolbar {
opacity: 1;
}
}
}
.page-title {
> .page-toolbar {
opacity: 0;
}
}
}
.tab-min {
padding: 0px 50px;
height: 65px;
overflow: hidden;
cursor: normal;
.page-title {
> .page-toolbar {
opacity: 1;
}
}
}
.tab-max {
padding: 25px 50px;
height: auto;
overflow: auto;
cursor: normal;
}
.section-divider {
height: 60px;
background-color: transparent;

View file

@ -1,6 +1,6 @@
<div id="page-{{ page.id }}" class="is-a-page" data-id="{{ page.id }}" data-type="{{ page.contentType }}">
{{#unless editMode}}
{{document/page-heading tagName=page.tagName document=document folder=folder page=page isEditor=isEditor
{{document/page-heading tagName=page.tagName document=document folder=folder page=page isEditor=isEditor tabMode=tabMode
onEdit=(action 'onEdit')
onSavePageAsBlock=(action 'onSavePageAsBlock') onCopyPage=(action 'onCopyPage') onMovePage=(action 'onMovePage') onDeletePage=(action 'onDeletePage')}}
{{section/base-renderer page=page}}

View file

@ -1,31 +1,7 @@
<div class="document-section">
{{#if viewMode}}
<div class="wysiwyg">
<div>
<h1 class="pull-left">{{model.page.title}}</h1>
<div class="toolbar pull-right">
<div class="buttons">
<div class="round-button-mono" {{action 'onEdit'}}>
<i class="material-icons color-gray">edit</i>
</div>
<div class="button-gap"></div>
<div class="round-button-mono" id="delete-section-button">
<i class="material-icons color-gray">delete</i>
</div>
</div>
</div>
</div>
<div class="clearfix" />
{{#dropdown-dialog target="delete-section-button" position="bottom right" button="Delete" color="flat-red" onAction=(action 'onDelete')}}
<p>Are you sure you want to delete this section?</p>
<p>There is no undo!</p>
{{/dropdown-dialog}}
{{section/base-renderer page=model.page}}
</div>
{{/if}}
{{#if editMode}}
{{document/document-editor document=model.document folder=model.folder page=model.page meta=model.meta onCancel=(action 'onCancel') onAction=(action 'onAction')}}
<div id="page-{{ page.id }}" class="is-a-tab {{if expanded 'tab-max' 'tab-min'}}" data-id="{{ page.id }}" data-type="{{ page.contentType }}">
{{document/tab-heading tagName=page.tagName document=document folder=folder page=page isEditor=isEditor
onExpand=(action 'onExpand') onSavePageAsBlock=(action 'onSavePageAsBlock') onCopyPage=(action 'onCopyPage') onMovePage=(action 'onMovePage') onDeletePage=(action 'onDeletePage')}}
{{#if expanded}}
{{section/base-renderer page=page}}
{{/if}}
</div>

View file

@ -12,10 +12,18 @@
{{else}}
<div class="section-divider" />
{{/if}}
{{#if (is-equal page.pageType 'section')}}
{{#document/document-page document=document folder=folder page=page isEditor=isEditor toEdit=toEdit
onSavePage=(action 'onSavePage') onSavePageAsBlock=(action 'onSavePageAsBlock')
onCopyPage=(action 'onCopyPage') onMovePage=(action 'onMovePage') onDeletePage=(action 'onDeletePage')}}
{{/document/document-page}}
{{/if}}
{{#if (is-equal page.pageType 'tab')}}
{{#document/document-tab document=document folder=folder page=page isEditor=isEditor
onSavePage=(action 'onSavePage') onSavePageAsBlock=(action 'onSavePageAsBlock')
onCopyPage=(action 'onCopyPage') onMovePage=(action 'onMovePage') onDeletePage=(action 'onDeletePage')}}
{{/document/document-tab}}
{{/if}}
{{else}}
no sections!
<div class="empty-state-document">

View file

@ -0,0 +1,92 @@
<div class="page-title">
<div class="icon">
<img class="img" src="/sections/{{page.contentType}}.png" srcset="/sections/{{page.contentType}}@2x.png" />
</div>
<span id="page-title-{{ page.id }}">{{ page.title }}</span>
<div id="page-toolbar-{{ page.id }}" class="pull-right page-toolbar hidden-xs hidden-sm">
{{#unless expanded}}
<div class="round-button-mono" {{action 'toggleExpand'}}>
<i class="material-icons color-gray">expand_more</i>
</div>
{{else}}
{{#if isEditor}}
{{#link-to 'document.section' page.id}}
<div class="round-button-mono">
<i class="material-icons color-gray">mode_edit</i>
</div>
{{/link-to}}
<div class="round-button-mono" id="page-menu-{{page.id}}">
<i class="material-icons color-gray">more_vert</i>
</div>
<div class="round-button-mono" {{action 'toggleExpand'}}>
<i class="material-icons color-gray">expand_less</i>
</div>
{{#dropdown-menu target=menuTarget position="top right" open="click" onOpenCallback=(action 'onMenuOpen') onCloseCallback=(action 'onMenuOpen')}}
<ul class="menu">
<li class="item" id={{copyButtonId}}>Copy</li>
<li class="item" id={{moveButtonId}}>Move</li>
<li class="item" id={{publishButtonId}}>Publish</li>
<li class="divider"></li>
<li class="item danger" id={{deleteButtonId}}>Delete</li>
</ul>
{{/dropdown-menu}}
{{#if menuOpen}}
{{#dropdown-dialog target=deleteButtonId position="bottom right" button="Delete" color="flat-red" onAction=(action 'deletePage')}}
<p>Are you sure you want to delete <span class="bold">{{page.title}}?</span></p>
<p>
{{input type="checkbox" id=checkId class="margin-left-20" checked=deleteChildren}}
<label for="{{checkId}}">&nbsp;Delete child pages</label>
</p>
{{/dropdown-dialog}}
{{#dropdown-dialog id=publishDialogId target=publishButtonId position="bottom right" button="Publish" color="flat-green" focusOn=blockTitleId onAction=(action 'onSavePageAsBlock')}}
<div class="form-header">
<div class="tip">
<span class="bold">{{folder.name}}:</span> Content Block
</div>
</div>
<div class="input-control">
<label>Name</label>
<div class="tip">Short title for reusable content block</div>
{{input type="text" value=blockTitle id=blockTitleId}}
</div>
<div class="input-control">
<label>Name</label>
<div class="tip">Short description to help others understand<br/>the reusable content block</div>
{{textarea rows="3" value=blockExcerpt id=blockExcerptId}}
</div>
{{/dropdown-dialog}}
{{#dropdown-dialog id=copyDialogId target=copyButtonId position="bottom right" button="Copy" color="flat-green" onOpenCallback=(action 'onCopyDialogOpen') onAction=(action 'onCopyPage')}}
<div class="form-header">
<div class="tip">
<span class="bold">Copy:</span> {{page.title}}
</div>
</div>
<div class="input-control">
<label>Target</label>
<div class="tip">Select where the content should be copied to</div>
{{ui-select cssClass="dropdown-page-toolbar" content=documentList action=(action 'onTargetChange') optionValuePath="id" optionLabelPath="name" selection=document}}
</div>
{{/dropdown-dialog}}
{{#dropdown-dialog id=moveDialogId target=moveButtonId position="bottom right" button="Move" color="flat-green" onOpenCallback=(action 'onCopyDialogOpen') onAction=(action 'onMovePage')}}
<div class="form-header">
<div class="tip">
<span class="bold">move:</span> {{page.title}}
</div>
</div>
<div class="input-control">
<label>Target</label>
<div class="tip">Select where the content should be moved to</div>
{{ui-select cssClass="dropdown-page-toolbar" content=documentListOthers action=(action 'onTargetChange') optionValuePath="id" optionLabelPath="name"}}
</div>
{{/dropdown-dialog}}
{{/if}}
{{else}}
<div class="round-button-mono" {{action 'toggleExpand'}}>
<i class="material-icons color-gray">expand_less</i>
</div>
{{/if}}
{{/unless}}
</div>
</div>

View file

@ -1,22 +1,5 @@
<div class="document-editor form-bordered">
<div class="toolbar">
<div class="title pull-left">
<div class="input-control">
<label>Title</label>
<div class="tip">{{tip}}</div>
{{focus-input type='text' id="page-title" value=page.title class="mousetrap"}}
</div>
{{#if hasExcerpt}}
<div class="margin-top-30">
<div class="input-control">
<label>Excerpt</label>
<div class="tip">Short description</div>
{{textarea rows="3" id="page-excerpt" value=page.excerpt class="mousetrap"}}
</div>
</div>
{{/if}}
</div>
<div class="buttons pull-right">
<div class="section-editor">
<div class="buttons">
{{#if busy}}
<img src="/assets/img/busy-gray.gif" class="busy-indicator" />
{{/if}}
@ -25,6 +8,13 @@
<div class="regular-button button-green" {{action 'onAction'}}>{{actionLabel}}</div>
</div>
<div class="clearfix"></div>
<div class="title">
<div class="input-control">
<label>Title</label>
<div class="tip">{{tip}}</div>
{{focus-input type='text' id="page-title" value=page.title class="mousetrap"}}
</div>
</div>
<div class="dropdown-dialog cancel-edits-dialog">
<div class="content">
<p>Do you want to cancel editing and lose unsaved changes?</p>
@ -39,7 +29,6 @@
</div>
<div class="clearfix"></div>
</div>
</div>
<div class="canvas">
{{yield}}
</div>

View file

@ -21,7 +21,7 @@ import (
// the HTML that is rendered by this section.
const renderTemplate = `
{{if .Authenticated}}
<p class="margin-left-20">The Gemini workspace <a href="{{.Config.URL}}/workspace/{{.Config.WorkspaceID}}/items">{{.Config.WorkspaceName}}</a> contains {{.Config.ItemCount}} items.</p>
<p>The Gemini workspace <a href="{{.Config.URL}}/workspace/{{.Config.WorkspaceID}}/items">{{.Config.WorkspaceName}}</a> contains {{.Config.ItemCount}} items.</p>
<table class="basic-table section-gemini-table">
<thead>
<tr>

View file

@ -16,7 +16,7 @@ import "strings"
// the HTML that is rendered by this section.
const renderTemplate = `
{{if .HasData}}
<p class="margin-left-20">The <a href="https://papertrailapp.com">Papertrail log</a> for query <em>{{.Config.Query}}</em> contains {{.Count}} entries.</p>
<p >The <a href="https://papertrailapp.com">Papertrail log</a> for query <em>{{.Config.Query}}</em> contains {{.Count}} entries.</p>
<table class="basic-table section-papertrail-table">
<thead>
<tr>