mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +02:00
[WIP] initial tabs rendering: content, files, meta
This commit is contained in:
parent
db0af750d0
commit
671a76ac55
46 changed files with 1243 additions and 823 deletions
131
app/app/components/document/document-files.js
Normal file
131
app/app/components/document/document-files.js
Normal file
|
@ -0,0 +1,131 @@
|
|||
// 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';
|
||||
import TooltipMixin from '../../mixins/tooltip';
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
appMeta: Ember.inject.service(),
|
||||
drop: null,
|
||||
deleteAttachment: {
|
||||
id: "",
|
||||
name: "",
|
||||
},
|
||||
emptyState: Ember.computed('files', function () {
|
||||
return this.get('files.length') === 0;
|
||||
}),
|
||||
|
||||
didInsertElement() {
|
||||
if (!this.get('isEditor')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
let documentId = this.get('document.id');
|
||||
let url = this.get('appMeta.endpoint');
|
||||
let uploadUrl = `${url}/documents/${documentId}/attachments`;
|
||||
|
||||
let dzone = new Dropzone("#upload-document-files", {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + self.get('session.session.content.authenticated.token')
|
||||
},
|
||||
url: uploadUrl,
|
||||
method: "post",
|
||||
paramName: 'attachment',
|
||||
clickable: true,
|
||||
maxFilesize: 10,
|
||||
parallelUploads: 3,
|
||||
uploadMultiple: false,
|
||||
addRemoveLinks: false,
|
||||
autoProcessQueue: true,
|
||||
|
||||
init: function () {
|
||||
this.on("success", function (file /*, response*/ ) {
|
||||
self.showNotification(`Attached ${file.name}`);
|
||||
});
|
||||
|
||||
this.on("queuecomplete", function () {
|
||||
self.attrs.onUpload();
|
||||
});
|
||||
|
||||
this.on("addedfile", function ( /*file*/ ) {
|
||||
self.audit.record('attached-file');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dzone.on("complete", function (file) {
|
||||
dzone.removeFile(file);
|
||||
});
|
||||
|
||||
this.set('drop', dzone);
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
let drop = this.get('drop');
|
||||
|
||||
if (is.not.null(drop)) {
|
||||
drop.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
confirmDeleteAttachment(id, name) {
|
||||
this.set('deleteAttachment', {
|
||||
id: id,
|
||||
name: name
|
||||
});
|
||||
|
||||
$(".delete-attachment-dialog").css("display", "block");
|
||||
|
||||
let drop = new Drop({
|
||||
target: $(".delete-attachment-" + id)[0],
|
||||
content: $(".delete-attachment-dialog")[0],
|
||||
classes: 'drop-theme-basic',
|
||||
position: "bottom right",
|
||||
openOn: "always",
|
||||
tetherOptions: {
|
||||
offset: "5px 0",
|
||||
targetOffset: "10px 0"
|
||||
},
|
||||
remove: false
|
||||
});
|
||||
|
||||
this.set('drop', drop);
|
||||
},
|
||||
|
||||
cancel() {
|
||||
let drop = this.get('drop');
|
||||
drop.close();
|
||||
|
||||
this.set('deleteAttachment', {
|
||||
id: "",
|
||||
name: ""
|
||||
});
|
||||
},
|
||||
|
||||
deleteAttachment() {
|
||||
let attachment = this.get('deleteAttachment');
|
||||
let drop = this.get('drop');
|
||||
drop.close();
|
||||
|
||||
this.attrs.onDelete(this.get('deleteAttachment').id, attachment.name);
|
||||
|
||||
this.set('deleteAttachment', {
|
||||
id: "",
|
||||
name: ""
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
35
app/app/components/document/document-meta.js
Normal file
35
app/app/components/document/document-meta.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
// 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';
|
||||
import TooltipMixin from '../../mixins/tooltip';
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
appMeta: Ember.inject.service(),
|
||||
|
||||
actions: {
|
||||
onSave() {
|
||||
let doc = this.get('document');
|
||||
|
||||
if (is.empty(doc.get('excerpt'))) {
|
||||
$("meta-excerpt").addClass("error").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
doc.set('excerpt', doc.get('excerpt').substring(0, 250));
|
||||
doc.set('userId', this.get('owner.id'));
|
||||
|
||||
this.attrs.onSave(doc);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
});
|
|
@ -15,70 +15,73 @@ import TooltipMixin from '../../mixins/tooltip';
|
|||
import tocUtil from '../../utils/toc';
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
document: {},
|
||||
folder: {},
|
||||
pages: [],
|
||||
page: "",
|
||||
document: {},
|
||||
folder: {},
|
||||
pages: [],
|
||||
page: "",
|
||||
state: {
|
||||
actionablePage: false,
|
||||
upDisabled: true,
|
||||
downDisabled: true,
|
||||
indentDisabled: true,
|
||||
outdentDisabled: true
|
||||
upDisabled: true,
|
||||
downDisabled: true,
|
||||
indentDisabled: true,
|
||||
outdentDisabled: true
|
||||
},
|
||||
emptyState: Ember.computed('pages', function () {
|
||||
return this.get('pages.length') === 0;
|
||||
}),
|
||||
|
||||
didReceiveAttrs: function () {
|
||||
this.set('showToc', is.not.undefined(this.get('pages')) && this.get('pages').get('length') > 2);
|
||||
if (is.not.null(this.get('page'))) {
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
}
|
||||
},
|
||||
|
||||
didReceiveAttrs: function() {
|
||||
this.set('showToc', is.not.undefined(this.get('pages')) && this.get('pages').get('length') > 2);
|
||||
if (is.not.null(this.get('page'))) {
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
}
|
||||
},
|
||||
|
||||
didRender: function() {
|
||||
if (this.session.authenticated) {
|
||||
this.addTooltip(document.getElementById("toc-up-button"));
|
||||
this.addTooltip(document.getElementById("toc-down-button"));
|
||||
this.addTooltip(document.getElementById("toc-outdent-button"));
|
||||
this.addTooltip(document.getElementById("toc-indent-button"));
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this.eventBus.subscribe('documentPageAdded', this, 'onDocumentPageAdded');
|
||||
didRender: function () {
|
||||
if (this.session.authenticated) {
|
||||
this.addTooltip(document.getElementById("toc-up-button"));
|
||||
this.addTooltip(document.getElementById("toc-down-button"));
|
||||
this.addTooltip(document.getElementById("toc-outdent-button"));
|
||||
this.addTooltip(document.getElementById("toc-indent-button"));
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this.eventBus.unsubscribe('documentPageAdded');
|
||||
didInsertElement() {
|
||||
this.eventBus.subscribe('documentPageAdded', this, 'onDocumentPageAdded');
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this.eventBus.unsubscribe('documentPageAdded');
|
||||
this.destroyTooltips();
|
||||
},
|
||||
},
|
||||
|
||||
onDocumentPageAdded(pageId) {
|
||||
this.send('onEntryClick', pageId);
|
||||
},
|
||||
onDocumentPageAdded(pageId) {
|
||||
this.send('onEntryClick', pageId);
|
||||
},
|
||||
|
||||
// Controls what user can do with the toc (left sidebar).
|
||||
// Identifies the target pages.
|
||||
setState(pageId) {
|
||||
// Controls what user can do with the toc (left sidebar).
|
||||
// Identifies the target pages.
|
||||
setState(pageId) {
|
||||
this.set('page', pageId);
|
||||
|
||||
let toc = this.get('pages');
|
||||
let page = _.findWhere(toc, { id: pageId });
|
||||
let toc = this.get('pages');
|
||||
let page = _.findWhere(toc, { id: pageId });
|
||||
|
||||
let state = tocUtil.getState(toc, page);
|
||||
|
||||
if (!this.get('isEditor') || is.empty(pageId)) {
|
||||
if (!this.get('isEditor') || is.empty(pageId)) {
|
||||
state.actionablePage = state.upDisabled = state.downDisabled = state.indentDisabled = state.outdentDisabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.set('state', state);
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
// Page up - above pages shunt down.
|
||||
pageUp() {
|
||||
actions: {
|
||||
// Page up - above pages shunt down.
|
||||
pageUp() {
|
||||
if (this.get('state.upDisabled')) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
let pages = this.get('pages');
|
||||
|
@ -88,75 +91,75 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
if (pendingChanges.length > 0) {
|
||||
this.attrs.changePageSequence(pendingChanges);
|
||||
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
this.audit.record("moved-page-up");
|
||||
this.showNotification("Moved up");
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
this.audit.record("moved-page-up");
|
||||
this.showNotification("Moved up");
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Move down -- pages below shift up.
|
||||
pageDown() {
|
||||
// Move down -- pages below shift up.
|
||||
pageDown() {
|
||||
if (this.get('state.downDisabled')) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('page') });
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('page') });
|
||||
let pendingChanges = tocUtil.moveDown(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.changePageSequence(pendingChanges);
|
||||
this.attrs.changePageSequence(pendingChanges);
|
||||
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
this.audit.record("moved-page-down");
|
||||
this.showNotification("Moved down");
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
this.audit.record("moved-page-down");
|
||||
this.showNotification("Moved down");
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Indent - changes a page from H2 to H3, etc.
|
||||
pageIndent() {
|
||||
// Indent - changes a page from H2 to H3, etc.
|
||||
pageIndent() {
|
||||
if (this.get('state.indentDisabled')) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('page') });
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('page') });
|
||||
let pendingChanges = tocUtil.indent(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.changePageLevel(pendingChanges);
|
||||
this.attrs.changePageLevel(pendingChanges);
|
||||
|
||||
this.showNotification("Indent");
|
||||
this.audit.record("changed-page-sequence");
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
this.showNotification("Indent");
|
||||
this.audit.record("changed-page-sequence");
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Outdent - changes a page from H3 to H2, etc.
|
||||
pageOutdent() {
|
||||
if (this.get('state.outdentDisabled')) {
|
||||
return;
|
||||
}
|
||||
// Outdent - changes a page from H3 to H2, etc.
|
||||
pageOutdent() {
|
||||
if (this.get('state.outdentDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('page') });
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('page') });
|
||||
let pendingChanges = tocUtil.outdent(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.changePageLevel(pendingChanges);
|
||||
this.attrs.changePageLevel(pendingChanges);
|
||||
|
||||
this.showNotification("Outdent");
|
||||
this.audit.record("changed-page-sequence");
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
this.showNotification("Outdent");
|
||||
this.audit.record("changed-page-sequence");
|
||||
this.send('onEntryClick', this.get('page'));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
onEntryClick(id) {
|
||||
this.setState(id);
|
||||
this.attrs.gotoPage(id);
|
||||
},
|
||||
},
|
||||
onEntryClick(id) {
|
||||
this.setState(id);
|
||||
this.attrs.gotoPage(id);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -18,15 +18,12 @@ export default Ember.Component.extend(TooltipMixin, NotifierMixin, {
|
|||
document: {},
|
||||
folder: {},
|
||||
showToc: true,
|
||||
showViews: false,
|
||||
showContributions: false,
|
||||
showSections: false,
|
||||
showScrollTool: false,
|
||||
showingSections: false,
|
||||
|
||||
didRender() {
|
||||
if (this.session.authenticated) {
|
||||
this.addTooltip(document.getElementById("owner-avatar"));
|
||||
this.addTooltip(document.getElementById("section-tool"));
|
||||
}
|
||||
},
|
||||
|
@ -75,32 +72,13 @@ export default Ember.Component.extend(TooltipMixin, NotifierMixin, {
|
|||
|
||||
showToc() {
|
||||
this.set('showToc', true);
|
||||
this.set('showViews', false);
|
||||
this.set('showContributions', false);
|
||||
this.set('showSections', false);
|
||||
this.set('showingSections', false);
|
||||
},
|
||||
|
||||
showViews() {
|
||||
this.set('showToc', false);
|
||||
this.set('showViews', true);
|
||||
this.set('showContributions', false);
|
||||
this.set('showSections', false);
|
||||
this.set('showingSections', false);
|
||||
},
|
||||
|
||||
showContributions() {
|
||||
this.set('showToc', false);
|
||||
this.set('showViews', false);
|
||||
this.set('showContributions', true);
|
||||
this.set('showSections', false);
|
||||
this.set('showingSections', false);
|
||||
},
|
||||
|
||||
showSections() {
|
||||
this.set('showToc', false);
|
||||
this.set('showViews', false);
|
||||
this.set('showContributions', false);
|
||||
this.set('showSections', true);
|
||||
this.set('showingSections', true);
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
localStorage: Ember.inject.service(),
|
||||
drop: null,
|
||||
users: [],
|
||||
menuOpen: false,
|
||||
saveTemplate: {
|
||||
name: "",
|
||||
description: ""
|
||||
|
@ -29,71 +30,15 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
this.set('saveTemplate.description', this.get('document.excerpt'));
|
||||
},
|
||||
|
||||
didRender() {
|
||||
if (this.get('isEditor')) {
|
||||
this.addTooltip(document.getElementById("attachment-button"));
|
||||
this.addTooltip(document.getElementById("save-template-button"));
|
||||
this.addTooltip(document.getElementById("set-meta-button"));
|
||||
this.addTooltip(document.getElementById("delete-document-button"));
|
||||
}
|
||||
|
||||
this.addTooltip(document.getElementById("print-document-button"));
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
if (this.get('isEditor')) {
|
||||
let self = this;
|
||||
let documentId = this.get('document.id');
|
||||
let url = this.get('appMeta.endpoint');
|
||||
let uploadUrl = `${url}/documents/${documentId}/attachments`;
|
||||
|
||||
let dzone = new Dropzone("#attachment-button > i", {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + self.get('session.session.content.authenticated.token')
|
||||
},
|
||||
url: uploadUrl,
|
||||
method: "post",
|
||||
paramName: 'attachment',
|
||||
clickable: true,
|
||||
maxFilesize: 10,
|
||||
parallelUploads: 3,
|
||||
uploadMultiple: false,
|
||||
addRemoveLinks: false,
|
||||
autoProcessQueue: true,
|
||||
|
||||
init: function () {
|
||||
this.on("success", function (file /*, response*/ ) {
|
||||
self.showNotification(`Attached ${file.name}`);
|
||||
});
|
||||
|
||||
this.on("queuecomplete", function () {
|
||||
self.attrs.onAttachmentUpload();
|
||||
});
|
||||
|
||||
this.on("addedfile", function ( /*file*/ ) {
|
||||
self.audit.record('attached-file');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dzone.on("complete", function (file) {
|
||||
dzone.removeFile(file);
|
||||
});
|
||||
|
||||
this.set('drop', dzone);
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
if (is.not.null(this.get('drop'))) {
|
||||
this.get('drop').destroy();
|
||||
this.set('drop', null);
|
||||
}
|
||||
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
actions: {
|
||||
onMenuOpen() {
|
||||
this.set('menuOpen', !this.get('menuOpen'));
|
||||
},
|
||||
|
||||
deleteDocument() {
|
||||
this.attrs.onDocumentDelete();
|
||||
},
|
||||
|
@ -120,22 +65,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
this.attrs.onSaveTemplate(name, excerpt);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
saveMeta() {
|
||||
let doc = this.get('document');
|
||||
|
||||
if (is.empty(doc.get('excerpt'))) {
|
||||
$("meta-excerpt").addClass("error").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
doc.set('excerpt', doc.get('excerpt').substring(0, 250));
|
||||
doc.set('userId', this.get('owner.id'));
|
||||
this.showNotification("Saved");
|
||||
|
||||
this.attrs.onDocumentChange(doc);
|
||||
return true;
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -39,16 +39,16 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
didInsertElement() {
|
||||
let self = this;
|
||||
|
||||
this.get('sectionService').refresh(this.get('document.id')).then(function (changes) {
|
||||
changes.forEach(function (newPage) {
|
||||
let oldPage = self.get('pages').findBy('id', newPage.get('id'));
|
||||
if (is.not.undefined(oldPage)) {
|
||||
oldPage.set('body', newPage.get('body'));
|
||||
oldPage.set('revised', newPage.get('revised'));
|
||||
self.showNotification(`Refreshed ${oldPage.get('title')}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
// this.get('sectionService').refresh(this.get('document.id')).then(function (changes) {
|
||||
// changes.forEach(function (newPage) {
|
||||
// let oldPage = self.get('pages').findBy('id', newPage.get('id'));
|
||||
// if (is.not.undefined(oldPage)) {
|
||||
// oldPage.set('body', newPage.get('body'));
|
||||
// oldPage.set('revised', newPage.get('revised'));
|
||||
// self.showNotification(`Refreshed ${oldPage.get('title')}`);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
},
|
||||
|
||||
didRender() {
|
||||
|
|
|
@ -16,16 +16,6 @@ export default Ember.Component.extend({
|
|||
tagName: "li",
|
||||
classNames: ["item"],
|
||||
|
||||
// indentLevel: Ember.computed('page', function() {
|
||||
// let nodeLevel = this.get('page.level');
|
||||
// let indent = (nodeLevel - 1) * 20;
|
||||
// return indent;
|
||||
// }),
|
||||
|
||||
didReceiveAttrs() {
|
||||
// this.set('classNames', ["item", "margin-left-" + this.get("page.tocIndent")]);
|
||||
},
|
||||
|
||||
actions: {
|
||||
onClick(id) {
|
||||
this.get('onClick')(id);
|
||||
|
|
|
@ -23,7 +23,7 @@ export default Ember.Component.extend({
|
|||
this._super(...arguments);
|
||||
let tagz = [];
|
||||
|
||||
if (this.get('documentTags').length > 1) {
|
||||
if (!_.isUndefined(this.get('documentTags')) && this.get('documentTags').length > 1) {
|
||||
let tags = this.get('documentTags').split('#');
|
||||
_.each(tags, function(tag) {
|
||||
if (tag.length > 0) {
|
||||
|
|
|
@ -85,9 +85,9 @@ export default Ember.Component.extend({
|
|||
self.attrs.onOpenCallback(drop);
|
||||
}
|
||||
});
|
||||
|
||||
self.set('drop', drop);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
|
|
|
@ -18,6 +18,8 @@ export default Ember.Component.extend({
|
|||
position: 'bottom right',
|
||||
contentId: "",
|
||||
drop: null,
|
||||
onOpenCallback: null, // callback when opened
|
||||
onCloseCallback: null, // callback when closed
|
||||
tether: Ember.inject.service(),
|
||||
|
||||
didReceiveAttrs() {
|
||||
|
@ -44,7 +46,20 @@ export default Ember.Component.extend({
|
|||
}
|
||||
});
|
||||
|
||||
self.set('drop', drop);
|
||||
if (drop) {
|
||||
drop.on('open', function () {
|
||||
if (is.not.null(self.get("onOpenCallback"))) {
|
||||
self.attrs.onOpenCallback(drop);
|
||||
}
|
||||
});
|
||||
drop.on('close', function () {
|
||||
if (is.not.null(self.get("onCloseCallback"))) {
|
||||
self.attrs.onCloseCallback();
|
||||
}
|
||||
});
|
||||
|
||||
self.set('drop', drop);
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
|
|
16
app/app/pods/document/activity/controller.js
Normal file
16
app/app/pods/document/activity/controller.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
// 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, {
|
||||
});
|
32
app/app/pods/document/activity/route.js
Normal file
32
app/app/pods/document/activity/route.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
// 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'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
userService: Ember.inject.service('user'),
|
||||
|
||||
beforeModel(transition) {
|
||||
},
|
||||
|
||||
model() {
|
||||
},
|
||||
|
||||
afterModel(model) {
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('model', model);
|
||||
}
|
||||
});
|
1
app/app/pods/document/activity/template.hbs
Normal file
1
app/app/pods/document/activity/template.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
activity
|
|
@ -1,14 +1,215 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// 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>.
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import Ember from 'ember';
|
||||
import NotifierMixin from '../../mixins/notifier';
|
||||
|
||||
export default Ember.Controller.extend({});
|
||||
export default Ember.Controller.extend(NotifierMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
templateService: Ember.inject.service('template'),
|
||||
|
||||
page: null,
|
||||
folder: {},
|
||||
pages: [],
|
||||
|
||||
// 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) {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').changePageSequence(this.model.get('id'), changes).then(function () {
|
||||
_.each(changes, function (change) {
|
||||
let pageContent = _.findWhere(self.get('pages'), {
|
||||
id: change.pageId
|
||||
});
|
||||
|
||||
if (is.not.undefined(pageContent)) {
|
||||
pageContent.set('sequence', change.sequence);
|
||||
}
|
||||
});
|
||||
|
||||
self.set('pages', self.get('pages').sortBy('sequence'));
|
||||
});
|
||||
},
|
||||
|
||||
onPageLevelChange(changes) {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').changePageLevel(this.model.get('id'), changes).then(function () {
|
||||
_.each(changes, function (change) {
|
||||
let pageContent = _.findWhere(self.get('pages'), {
|
||||
id: change.pageId
|
||||
});
|
||||
|
||||
if (is.not.undefined(pageContent)) {
|
||||
pageContent.set('level', change.level);
|
||||
}
|
||||
});
|
||||
|
||||
let pages = self.get('pages');
|
||||
pages = pages.sortBy('sequence');
|
||||
self.set('pages', []);
|
||||
self.set('pages', pages);
|
||||
});
|
||||
},
|
||||
|
||||
onPageDeleted(deletePage) {
|
||||
let self = this;
|
||||
let documentId = this.get('model.id');
|
||||
let pages = this.get('pages');
|
||||
let deleteId = deletePage.id;
|
||||
let deleteChildren = deletePage.children;
|
||||
let page = _.findWhere(pages, {
|
||||
id: deleteId
|
||||
});
|
||||
let pageIndex = _.indexOf(pages, page, false);
|
||||
let pendingChanges = [];
|
||||
|
||||
// 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(function () {
|
||||
// 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;
|
||||
self.set('pages', _.reject(self.get('pages'), function (p) { //jshint ignore: line
|
||||
return p.id === pageId;
|
||||
}));
|
||||
}
|
||||
|
||||
self.set('pages', _.sortBy(self.get('pages'), "sequence"));
|
||||
|
||||
self.audit.record("deleted-page");
|
||||
|
||||
// fetch document meta
|
||||
self.get('documentService').getMeta(self.model.get('id')).then(function (meta) {
|
||||
self.set('meta', meta);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// page delete followed by re-leveling child pages
|
||||
this.get('documentService').deletePage(documentId, deleteId).then(function () {
|
||||
self.set('pages', _.reject(self.get('pages'), function (p) {
|
||||
return p.get('id') === deleteId;
|
||||
}));
|
||||
|
||||
self.audit.record("deleted-page");
|
||||
|
||||
// fetch document meta
|
||||
self.get('documentService').getMeta(self.model.get('id')).then(function (meta) {
|
||||
self.set('meta', meta);
|
||||
});
|
||||
});
|
||||
|
||||
self.send('onPageLevelChange', pendingChanges);
|
||||
}
|
||||
},
|
||||
|
||||
onSaveTemplate(name, desc) {
|
||||
this.get('templateService').saveAsTemplate(this.model.get('id'), name, desc).then(function () {});
|
||||
},
|
||||
|
||||
onAddSection(section) {
|
||||
this.audit.record("added-section");
|
||||
this.audit.record("added-section-" + section.get('contentType'));
|
||||
|
||||
let page = {
|
||||
documentId: this.get('model.id'),
|
||||
title: `${section.get('title')} Section`,
|
||||
level: 1,
|
||||
sequence: 2048,
|
||||
body: "",
|
||||
contentType: section.get('contentType')
|
||||
};
|
||||
|
||||
let data = this.get('store').normalize('page', page);
|
||||
let pageData = this.get('store').push(data);
|
||||
|
||||
let meta = {
|
||||
documentId: this.get('model.id'),
|
||||
rawBody: "",
|
||||
config: ""
|
||||
};
|
||||
|
||||
let pageMeta = this.get('store').normalize('page-meta', meta);
|
||||
let pageMetaData = this.get('store').push(pageMeta);
|
||||
|
||||
let model = {
|
||||
page: pageData,
|
||||
meta: pageMetaData
|
||||
};
|
||||
|
||||
this.get('documentService').addPage(this.get('model.id'), model).then((newPage) => {
|
||||
this.transitionToRoute('document.edit',
|
||||
this.get('folder.id'),
|
||||
this.get('folder.slug'),
|
||||
this.get('model.id'),
|
||||
this.get('model.slug'),
|
||||
newPage.id);
|
||||
});
|
||||
},
|
||||
|
||||
onDocumentDelete() {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').deleteDocument(this.get('model.id')).then(function () {
|
||||
self.audit.record("deleted-page");
|
||||
self.send("showNotification", "Deleted");
|
||||
self.transitionToRoute('folder', self.get('folder.id'), self.get('folder.slug'));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
40
app/app/pods/document/files/controller.js
Normal file
40
app/app/pods/document/files/controller.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
// 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'),
|
||||
|
||||
getAttachments() {
|
||||
let self = this;
|
||||
this.get('documentService').getAttachments(this.get('model.document.id')).then(function (files) {
|
||||
self.set('model.files', files);
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onUpload() {
|
||||
this.getAttachments();
|
||||
},
|
||||
|
||||
onDelete(id, name) {
|
||||
let self = this;
|
||||
|
||||
this.showNotification(`Deleted ${name}`);
|
||||
|
||||
this.get('documentService').deleteAttachment(this.get('model.document.id'), id).then(function () {
|
||||
self.getAttachments();
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
34
app/app/pods/document/files/route.js
Normal file
34
app/app/pods/document/files/route.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
// 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 RSVP from 'rsvp';
|
||||
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
|
||||
|
||||
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
userService: Ember.inject.service('user'),
|
||||
|
||||
model() {
|
||||
this.audit.record("viewed-document-attachments");
|
||||
|
||||
return RSVP.hash({
|
||||
document: this.modelFor('document'),
|
||||
files: this.get('documentService').getAttachments(this.modelFor('document').get('id'))
|
||||
});
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('model', model);
|
||||
controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
|
||||
}
|
||||
});
|
1
app/app/pods/document/files/template.hbs
Normal file
1
app/app/pods/document/files/template.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
{{document/document-files document=model.document files=model.files isEditor=isEditor onUpload=(action 'onUpload') onDelete=(action 'onDelete')}}
|
|
@ -20,18 +20,6 @@ export default Ember.Controller.extend(NotifierMixin, {
|
|||
page: null,
|
||||
folder: {},
|
||||
pages: [],
|
||||
attachments: null,
|
||||
|
||||
getAttachments() {
|
||||
let self = this;
|
||||
this.get('documentService').getAttachments(this.model.get('id')).then(function (attachments) {
|
||||
if (is.array(attachments)) {
|
||||
self.set('attachments', attachments);
|
||||
} else {
|
||||
self.set('attachments', []);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Jump to the right part of the document.
|
||||
scrollToPage(pageId) {
|
||||
|
@ -65,56 +53,6 @@ export default Ember.Controller.extend(NotifierMixin, {
|
|||
this.scrollToPage(pageId);
|
||||
},
|
||||
|
||||
onPageSequenceChange(changes) {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').changePageSequence(this.model.get('id'), changes).then(function () {
|
||||
_.each(changes, function (change) {
|
||||
let pageContent = _.findWhere(self.get('pages'), {
|
||||
id: change.pageId
|
||||
});
|
||||
|
||||
if (is.not.undefined(pageContent)) {
|
||||
pageContent.set('sequence', change.sequence);
|
||||
}
|
||||
});
|
||||
|
||||
self.set('pages', self.get('pages').sortBy('sequence'));
|
||||
});
|
||||
},
|
||||
|
||||
onPageLevelChange(changes) {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').changePageLevel(this.model.get('id'), changes).then(function () {
|
||||
_.each(changes, function (change) {
|
||||
let pageContent = _.findWhere(self.get('pages'), {
|
||||
id: change.pageId
|
||||
});
|
||||
|
||||
if (is.not.undefined(pageContent)) {
|
||||
pageContent.set('level', change.level);
|
||||
}
|
||||
});
|
||||
|
||||
let pages = self.get('pages');
|
||||
pages = pages.sortBy('sequence');
|
||||
self.set('pages', []);
|
||||
self.set('pages', pages);
|
||||
});
|
||||
},
|
||||
|
||||
onAttachmentUpload() {
|
||||
this.getAttachments();
|
||||
},
|
||||
|
||||
onAttachmentDeleted(id) {
|
||||
let self = this;
|
||||
this.get('documentService').deleteAttachment(this.model.get('id'), id).then(function () {
|
||||
self.getAttachments();
|
||||
});
|
||||
},
|
||||
|
||||
onPageDeleted(deletePage) {
|
||||
let self = this;
|
||||
let documentId = this.get('model.id');
|
||||
|
@ -181,66 +119,5 @@ export default Ember.Controller.extend(NotifierMixin, {
|
|||
self.send('onPageLevelChange', pendingChanges);
|
||||
}
|
||||
},
|
||||
|
||||
onSaveTemplate(name, desc) {
|
||||
this.get('templateService').saveAsTemplate(this.model.get('id'), name, desc).then(function () {});
|
||||
},
|
||||
|
||||
onDocumentChange(doc) {
|
||||
let self = this;
|
||||
this.get('documentService').save(doc).then(function () {
|
||||
self.set('model', doc);
|
||||
});
|
||||
},
|
||||
|
||||
onAddSection(section) {
|
||||
this.audit.record("added-section");
|
||||
this.audit.record("added-section-" + section.get('contentType'));
|
||||
|
||||
let page = {
|
||||
documentId: this.get('model.id'),
|
||||
title: `${section.get('title')} Section`,
|
||||
level: 1,
|
||||
sequence: 2048,
|
||||
body: "",
|
||||
contentType: section.get('contentType')
|
||||
};
|
||||
|
||||
let data = this.get('store').normalize('page', page);
|
||||
let pageData = this.get('store').push(data);
|
||||
|
||||
let meta = {
|
||||
documentId: this.get('model.id'),
|
||||
rawBody: "",
|
||||
config: ""
|
||||
};
|
||||
|
||||
let pageMeta = this.get('store').normalize('page-meta', meta);
|
||||
let pageMetaData = this.get('store').push(pageMeta);
|
||||
|
||||
let model = {
|
||||
page: pageData,
|
||||
meta: pageMetaData
|
||||
};
|
||||
|
||||
this.get('documentService').addPage(this.get('model.id'), model).then((newPage) => {
|
||||
this.transitionToRoute('document.edit',
|
||||
this.get('folder.id'),
|
||||
this.get('folder.slug'),
|
||||
this.get('model.id'),
|
||||
this.get('model.slug'),
|
||||
newPage.id);
|
||||
});
|
||||
},
|
||||
|
||||
onDocumentDelete() {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').deleteDocument(this.get('model.id')).then(function () {
|
||||
self.audit.record("deleted-page");
|
||||
self.send("showNotification", "Deleted");
|
||||
self.transitionToRoute('folder', self.get('folder.id'), self.get('folder.slug'));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -21,50 +21,37 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
|||
users: [],
|
||||
meta: [],
|
||||
folder: null,
|
||||
|
||||
beforeModel: function (transition) {
|
||||
this.pageId = is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : "";
|
||||
var self = this;
|
||||
|
||||
this.get('folderService').getAll().then(function (folders) {
|
||||
self.set('folders', folders);
|
||||
self.set('folder', folders.findBy("id", self.paramsFor('document').folder_id));
|
||||
self.get('folderService').setCurrentFolder(self.get('folder'));
|
||||
});
|
||||
queryParams: {
|
||||
page: {
|
||||
refreshModel: false
|
||||
}
|
||||
},
|
||||
|
||||
model: function () {
|
||||
beforeModel(transition) {
|
||||
this.pageId = is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : "";
|
||||
|
||||
let folders = this.get('store').peekAll('folder');
|
||||
let folder = this.get('store').peekRecord('folder', this.paramsFor('document').folder_id);
|
||||
this.set('folders', folders);
|
||||
this.set('folder', folder);
|
||||
this.get('folderService').setCurrentFolder(folder);
|
||||
},
|
||||
|
||||
model() {
|
||||
this.audit.record("viewed-document");
|
||||
return this.modelFor('document');
|
||||
},
|
||||
|
||||
afterModel: function (model) {
|
||||
afterModel(model) {
|
||||
var self = this;
|
||||
var documentId = model.get('id');
|
||||
|
||||
this.browser.setTitle(model.get('name'));
|
||||
|
||||
// We resolve the promise when all data is ready.
|
||||
return new Ember.RSVP.Promise(function (resolve) {
|
||||
self.get('documentService').getPages(documentId).then(function (pages) {
|
||||
self.set('pages', pages);
|
||||
|
||||
self.get('documentService').getAttachments(documentId).then(function (attachments) {
|
||||
self.set('attachments', is.array(attachments) ? attachments : []);
|
||||
|
||||
if (self.session.authenticated) {
|
||||
self.get('documentService').getMeta(documentId).then(function (meta) {
|
||||
self.set('meta', meta);
|
||||
|
||||
self.get('userService').getFolderUsers(self.get('folder.id')).then(function (users) {
|
||||
self.set('users', users);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -76,35 +63,5 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
|||
controller.set('currentPage', this.pageId);
|
||||
controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
|
||||
controller.set('pages', this.get('pages'));
|
||||
controller.set('attachments', this.get('attachments'));
|
||||
controller.set('users', this.get('users'));
|
||||
|
||||
// setup document owner
|
||||
let owner = this.get('users').findBy('id', model.get('userId'));
|
||||
|
||||
// no document owner? You are the owner!
|
||||
if (is.undefined(owner)) {
|
||||
owner = this.session.user;
|
||||
model.set('userId', this.get('session.session.authenticated.user.id'));
|
||||
this.get('documentService').save(model);
|
||||
}
|
||||
|
||||
controller.set('owner', owner);
|
||||
|
||||
// check for no meta
|
||||
let meta = this.get('meta');
|
||||
|
||||
if (is.not.null(meta)) {
|
||||
if (is.null(meta.editors)) {
|
||||
meta.editors = [];
|
||||
}
|
||||
if (is.null(meta.viewers)) {
|
||||
meta.viewers = [];
|
||||
}
|
||||
}
|
||||
|
||||
controller.set('meta', meta);
|
||||
|
||||
this.browser.setMetaDescription(model.get('excerpt'));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,17 +1,2 @@
|
|||
{{layout/zone-navigation}}
|
||||
|
||||
{{#layout/zone-sidebar}}
|
||||
{{document/document-sidebar document=model meta=meta folder=folder pages=pages page=page owner=owner isEditor=isEditor onAddSection=(action
|
||||
'onAddSection') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action
|
||||
'gotoPage')}}
|
||||
{{/layout/zone-sidebar}}
|
||||
|
||||
{{#layout/zone-content}}
|
||||
{{document/document-toolbar document=model pages=pages folder=folder owner=owner isEditor=isEditor users=users onSaveTemplate=(action
|
||||
'onSaveTemplate') onDocumentChange=(action 'onDocumentChange') onAttachmentUpload=(action 'onAttachmentUpload') onDocumentDelete=(action
|
||||
'onDocumentDelete')}}
|
||||
|
||||
{{document/document-view document=model meta=meta pages=pages attachments=attachments folder=folder
|
||||
folders=folders isEditor=isEditor gotoPage=(action 'gotoPage') onAttachmentDeleted=(action 'onAttachmentDeleted') onDeletePage=(action
|
||||
'onPageDeleted')}}
|
||||
{{/layout/zone-content}}
|
||||
{{document/document-view document=model meta=meta pages=pages attachments=attachments folder=folder
|
||||
folders=folders isEditor=isEditor gotoPage=(action 'gotoPage') onDeletePage=(action 'onPageDeleted')}}
|
||||
|
|
29
app/app/pods/document/meta/controller.js
Normal file
29
app/app/pods/document/meta/controller.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
// 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'),
|
||||
|
||||
actions: {
|
||||
onSave(doc) {
|
||||
let self = this;
|
||||
|
||||
this.get('documentService').save(doc).then(function () {
|
||||
self.showNotification('Saved');
|
||||
self.set('model', doc);
|
||||
self.transitionToRoute('document.index');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
61
app/app/pods/document/meta/route.js
Normal file
61
app/app/pods/document/meta/route.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
// 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'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
userService: Ember.inject.service('user'),
|
||||
|
||||
model() {
|
||||
this.audit.record("viewed-document-meta");
|
||||
|
||||
let folders = this.get('store').peekAll('folder');
|
||||
let folder = this.get('store').peekRecord('folder', this.paramsFor('document').folder_id);
|
||||
this.set('folders', folders);
|
||||
this.set('folder', folder);
|
||||
|
||||
return this.modelFor('document');
|
||||
},
|
||||
|
||||
afterModel() {
|
||||
let self = this;
|
||||
|
||||
return new Ember.RSVP.Promise(function (resolve) {
|
||||
self.get('userService').getFolderUsers(self.get('folder.id')).then(function (users) {
|
||||
self.set('users', users);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('model', model);
|
||||
controller.set('folder', this.get('folder'));
|
||||
controller.set('folders', this.get('folders').rejectBy('id', 0));
|
||||
controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
|
||||
controller.set('users', this.get('users'));
|
||||
|
||||
// setup document owner
|
||||
let owner = this.get('users').findBy('id', model.get('userId'));
|
||||
|
||||
// no document owner? You are the owner!
|
||||
if (is.undefined(owner)) {
|
||||
owner = this.session.user;
|
||||
model.set('userId', this.get('session.session.authenticated.user.id'));
|
||||
this.get('documentService').save(model);
|
||||
}
|
||||
|
||||
controller.set('owner', owner);
|
||||
}
|
||||
});
|
1
app/app/pods/document/meta/template.hbs
Normal file
1
app/app/pods/document/meta/template.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
{{document/document-meta document=model folders=folders folder=folder users=users owner=owner isEditor=isEditor onSave=(action 'onSave')}}
|
|
@ -14,12 +14,66 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout
|
|||
|
||||
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
folderService: Ember.inject.service('folder'),
|
||||
userService: Ember.inject.service('user'),
|
||||
pages: [],
|
||||
users: [],
|
||||
meta: [],
|
||||
folder: null,
|
||||
|
||||
beforeModel(transition) {
|
||||
this.pageId = is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : "";
|
||||
var self = this;
|
||||
|
||||
this.get('folderService').getAll().then(function (folders) {
|
||||
self.set('folders', folders);
|
||||
self.set('folder', folders.findBy("id", self.paramsFor('document').folder_id));
|
||||
self.get('folderService').setCurrentFolder(self.get('folder'));
|
||||
});
|
||||
},
|
||||
|
||||
model: function (params) {
|
||||
this.audit.record("viewed-document");
|
||||
// this.audit.record("viewed-document");
|
||||
return this.get('documentService').getDocument(params.document_id);
|
||||
},
|
||||
|
||||
afterModel(model) {
|
||||
var self = this;
|
||||
var documentId = model.get('id');
|
||||
|
||||
this.browser.setTitle(model.get('name'));
|
||||
|
||||
return new Ember.RSVP.Promise(function (resolve) {
|
||||
self.get('documentService').getPages(documentId).then(function (pages) {
|
||||
self.set('pages', pages);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
controller.set('model', model);
|
||||
controller.set('folder', this.folder);
|
||||
controller.set('folders', this.get('folders').rejectBy('id', 0));
|
||||
controller.set('currentPage', this.pageId);
|
||||
controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder'));
|
||||
controller.set('pages', this.get('pages'));
|
||||
|
||||
// setup document owner
|
||||
let owner = this.get('users').findBy('id', model.get('userId'));
|
||||
|
||||
// no document owner? You are the owner!
|
||||
if (is.undefined(owner)) {
|
||||
owner = this.session.user;
|
||||
model.set('userId', this.get('session.session.authenticated.user.id'));
|
||||
this.get('documentService').save(model);
|
||||
}
|
||||
|
||||
controller.set('owner', owner);
|
||||
|
||||
this.browser.setMetaDescription(model.get('excerpt'));
|
||||
},
|
||||
|
||||
actions: {
|
||||
error(error /*, transition*/ ) {
|
||||
if (error) {
|
||||
|
|
|
@ -1 +1,15 @@
|
|||
{{outlet}}
|
||||
{{layout/zone-navigation}}
|
||||
|
||||
{{#layout/zone-sidebar}}
|
||||
{{document/document-sidebar document=model folder=folder pages=pages page=page isEditor=isEditor onAddSection=(action
|
||||
'onAddSection') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action
|
||||
'gotoPage')}}
|
||||
{{/layout/zone-sidebar}}
|
||||
|
||||
{{#layout/zone-content}}
|
||||
{{document/document-toolbar document=model pages=pages folder=folder isEditor=isEditor onSaveTemplate=(action
|
||||
'onSaveTemplate') onDocumentDelete=(action
|
||||
'onDocumentDelete')}}
|
||||
|
||||
{{outlet}}
|
||||
{{/layout/zone-content}}
|
||||
|
|
|
@ -20,7 +20,7 @@ export default Router.map(function () {
|
|||
this.route('folders', {
|
||||
path: '/'
|
||||
});
|
||||
|
||||
|
||||
this.route('folder', {
|
||||
path: 's/:folder_id/:folder_slug'
|
||||
});
|
||||
|
@ -32,6 +32,15 @@ export default Router.map(function () {
|
|||
this.route('document', {
|
||||
path: 's/:folder_id/:folder_slug/d/:document_id/:document_slug'
|
||||
}, function () {
|
||||
this.route('files', {
|
||||
path: 'files'
|
||||
});
|
||||
this.route('meta', {
|
||||
path: 'meta'
|
||||
});
|
||||
this.route('activity', {
|
||||
path: 'activity'
|
||||
});
|
||||
this.route('edit', {
|
||||
path: 'edit/:page_id'
|
||||
});
|
||||
|
|
|
@ -20,12 +20,7 @@
|
|||
@import "view/page-auth.scss";
|
||||
@import "view/page-onboard.scss";
|
||||
@import "view/page-exceptions.scss";
|
||||
@import "view/document/sidebar.scss";
|
||||
@import "view/document/content.scss";
|
||||
@import "view/document/wysiwyg.scss";
|
||||
@import "view/document/editor.scss";
|
||||
@import "view/document/wizard.scss";
|
||||
@import "view/document/edit-tools.scss";
|
||||
@import "view/document/all.scss";
|
||||
@import "view/common.scss";
|
||||
@import "vendor.scss";
|
||||
@import "responsive.scss";
|
||||
|
|
|
@ -106,7 +106,7 @@ video.responsive-video {
|
|||
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
font-family: $base-font;
|
||||
font-family: $font-regular;
|
||||
background-color: $color-white;
|
||||
font-size: 14px;
|
||||
height: 100%;
|
||||
|
|
|
@ -1,61 +1,42 @@
|
|||
.fixed-width-font {
|
||||
font-family: 'courier new', courier;
|
||||
.font-fixed-width {
|
||||
font-family: 'courier new', courier;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'open_sansbold';
|
||||
src: url('font/opensans/opensans-bold-webfont.eot');
|
||||
src: url('font/opensans/opensans-bold-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('font/opensans/opensans-bold-webfont.woff2') format('woff2'),
|
||||
url('font/opensans/opensans-bold-webfont.woff') format('woff'),
|
||||
url('font/opensans/opensans-bold-webfont.ttf') format('truetype'),
|
||||
url('font/opensans/opensans-bold-webfont.svg#open_sansbold') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-family: 'open_sansbold';
|
||||
src: url('font/opensans/opensans-bold-webfont.eot');
|
||||
src: url('font/opensans/opensans-bold-webfont.eot?#iefix') format('embedded-opentype'), url('font/opensans/opensans-bold-webfont.woff2') format('woff2'), url('font/opensans/opensans-bold-webfont.woff') format('woff'), url('font/opensans/opensans-bold-webfont.ttf') format('truetype'), url('font/opensans/opensans-bold-webfont.svg#open_sansbold') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'open_sanslight';
|
||||
src: url('font/opensans/opensans-light-webfont.eot');
|
||||
src: url('font/opensans/opensans-light-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('font/opensans/opensans-light-webfont.woff2') format('woff2'),
|
||||
url('font/opensans/opensans-light-webfont.woff') format('woff'),
|
||||
url('font/opensans/opensans-light-webfont.ttf') format('truetype'),
|
||||
url('font/opensans/opensans-light-webfont.svg#open_sanslight') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-family: 'open_sanslight';
|
||||
src: url('font/opensans/opensans-light-webfont.eot');
|
||||
src: url('font/opensans/opensans-light-webfont.eot?#iefix') format('embedded-opentype'), url('font/opensans/opensans-light-webfont.woff2') format('woff2'), url('font/opensans/opensans-light-webfont.woff') format('woff'), url('font/opensans/opensans-light-webfont.ttf') format('truetype'), url('font/opensans/opensans-light-webfont.svg#open_sanslight') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'open_sansregular';
|
||||
src: url('font/opensans/opensans-regular-webfont.eot');
|
||||
src: url('font/opensans/opensans-regular-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('font/opensans/opensans-regular-webfont.woff2') format('woff2'),
|
||||
url('font/opensans/opensans-regular-webfont.woff') format('woff'),
|
||||
url('font/opensans/opensans-regular-webfont.ttf') format('truetype'),
|
||||
url('font/opensans/opensans-regular-webfont.svg#open_sansregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-family: 'open_sansregular';
|
||||
src: url('font/opensans/opensans-regular-webfont.eot');
|
||||
src: url('font/opensans/opensans-regular-webfont.eot?#iefix') format('embedded-opentype'), url('font/opensans/opensans-regular-webfont.woff2') format('woff2'), url('font/opensans/opensans-regular-webfont.woff') format('woff'), url('font/opensans/opensans-regular-webfont.ttf') format('truetype'), url('font/opensans/opensans-regular-webfont.svg#open_sansregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'open_sanssemibold';
|
||||
src: url('font/opensans/opensans-semibold-webfont.eot');
|
||||
src: url('font/opensans/opensans-semibold-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('font/opensans/opensans-semibold-webfont.woff2') format('woff2'),
|
||||
url('font/opensans/opensans-semibold-webfont.woff') format('woff'),
|
||||
url('font/opensans/opensans-semibold-webfont.ttf') format('truetype'),
|
||||
url('font/opensans/opensans-semibold-webfont.svg#open_sanssemibold') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-family: 'open_sanssemibold';
|
||||
src: url('font/opensans/opensans-semibold-webfont.eot');
|
||||
src: url('font/opensans/opensans-semibold-webfont.eot?#iefix') format('embedded-opentype'), url('font/opensans/opensans-semibold-webfont.woff2') format('woff2'), url('font/opensans/opensans-semibold-webfont.woff') format('woff'), url('font/opensans/opensans-semibold-webfont.ttf') format('truetype'), url('font/opensans/opensans-semibold-webfont.svg#open_sanssemibold') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
$base-font: 'open_sansregular';
|
||||
|
||||
$font-regular: 'open_sansregular';
|
||||
$font-semibold: 'open_sanssemibold';
|
||||
$font-light: 'open_sanslight';
|
||||
@font-face {
|
||||
font-family: "Material Icons";
|
||||
font-style : normal;
|
||||
font-weight: 400;
|
||||
src : url("font/icons/MaterialIcons-Regular.eot");
|
||||
src : local('Material Icons'), local('MaterialIcons-Regular'), url("font/icons/MaterialIcons-Regular.woff2") format('woff2'), url("font/icons/MaterialIcons-Regular.woff") format('woff'), url("font/icons/MaterialIcons-Regular.ttf") format('truetype');
|
||||
font-family: "Material Icons";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("font/icons/MaterialIcons-Regular.eot");
|
||||
src: local('Material Icons'), local('MaterialIcons-Regular'), url("font/icons/MaterialIcons-Regular.woff2") format('woff2'), url("font/icons/MaterialIcons-Regular.woff") format('woff'), url("font/icons/MaterialIcons-Regular.ttf") format('truetype');
|
||||
}
|
||||
|
|
|
@ -26,6 +26,20 @@
|
|||
border-top-left-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin border-radius-bottom-right($radius)
|
||||
{
|
||||
-webkit-border-bottom-right-radius: $radius;
|
||||
-moz-border-radius-bottomright: $radius;
|
||||
border-bottom-right-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin border-radius-bottom-left($radius)
|
||||
{
|
||||
-webkit-border-bottom-left-radius: $radius;
|
||||
-moz-border-radius-bottomleft: $radius;
|
||||
border-bottom-left-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin border-radius-none()
|
||||
{
|
||||
-webkit-border-radius: none;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
text-align: center;
|
||||
|
||||
> .empty-state {
|
||||
margin: 30px 0 0;
|
||||
margin: 30px 0;
|
||||
font-size: 2rem;
|
||||
color: $color-gray;
|
||||
font-family: 'open_sanslight';
|
||||
|
|
8
app/app/styles/view/document/all.scss
Normal file
8
app/app/styles/view/document/all.scss
Normal file
|
@ -0,0 +1,8 @@
|
|||
@import "content.scss";
|
||||
@import "edit-tools.scss";
|
||||
@import "editor.scss";
|
||||
@import "files.scss";
|
||||
@import "sidebar.scss";
|
||||
@import "toolbar.scss";
|
||||
@import "wizard.scss";
|
||||
@import "wysiwyg.scss";
|
|
@ -15,66 +15,6 @@
|
|||
color: $color-gray;
|
||||
}
|
||||
|
||||
.attachment-zone {
|
||||
margin: 20px 0 30px 0;
|
||||
|
||||
> .list {
|
||||
margin: 0;
|
||||
padding: 7px 0;
|
||||
|
||||
> .item {
|
||||
color: $color-off-black;
|
||||
margin-top: 10px;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
border-bottom: 1px dotted $color-border;
|
||||
padding-bottom: 10px;
|
||||
|
||||
> .icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
> a {
|
||||
color: $color-gray;
|
||||
|
||||
&:hover {
|
||||
color: $color-link;
|
||||
}
|
||||
|
||||
> .file {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
> .action {
|
||||
float: right;
|
||||
margin-top: -2px;
|
||||
margin-right: 5px;
|
||||
@extend .cursor-pointer;
|
||||
opacity: 0.5;
|
||||
@extend .transition-all;
|
||||
display: none;
|
||||
color: $color-stroke;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.action {
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-attachment-dialog,
|
||||
.delete-page-dialog {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.is-template {
|
||||
color: $color-gray;
|
||||
font-weight: bold;
|
||||
|
|
78
app/app/styles/view/document/files.scss
Normal file
78
app/app/styles/view/document/files.scss
Normal file
|
@ -0,0 +1,78 @@
|
|||
.document-files {
|
||||
margin: 0;
|
||||
|
||||
> .upload-document-files {
|
||||
width: 50%;
|
||||
padding: 20px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
color: $color-gray;
|
||||
border: 2px dotted $color-gray;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
line-height: 1.7rem;
|
||||
@include border-radius(10px);
|
||||
@include ease-in();
|
||||
|
||||
&:hover {
|
||||
border-color: $color-link;
|
||||
color: $color-link;
|
||||
}
|
||||
|
||||
.dz-processing,
|
||||
> .dz-preview {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
> .list {
|
||||
margin: 0 0 50px;
|
||||
padding: 7px 0;
|
||||
|
||||
> .item {
|
||||
color: $color-off-black;
|
||||
margin-top: 10px;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
border-bottom: 1px solid $color-border;
|
||||
padding-bottom: 10px;
|
||||
|
||||
> .icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
> a {
|
||||
color: $color-gray;
|
||||
|
||||
&:hover {
|
||||
color: $color-link;
|
||||
}
|
||||
|
||||
> .file {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
> .action {
|
||||
float: right;
|
||||
margin-top: -2px;
|
||||
margin-right: 5px;
|
||||
@extend .cursor-pointer;
|
||||
@extend .transition-all;
|
||||
display: none;
|
||||
color: $color-gray;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.action {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-attachment-dialog,
|
||||
.delete-page-dialog {
|
||||
display: none;
|
||||
}
|
|
@ -2,57 +2,6 @@
|
|||
@extend .no-select;
|
||||
width: 100%;
|
||||
|
||||
> .summary-line {
|
||||
color: $color-gray;
|
||||
margin: 30px 0;
|
||||
|
||||
> .items {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
|
||||
> .divider {
|
||||
margin-right: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
> .item {
|
||||
list-style-type: none;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
|
||||
> .metric {
|
||||
@extend .cursor-pointer;
|
||||
text-align: center;
|
||||
color: $color-gray;
|
||||
|
||||
.number {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.label {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $color-link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .active {
|
||||
> .metric {
|
||||
color: $color-link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stuck-toc {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
|
@ -109,7 +58,6 @@
|
|||
|
||||
.document-structure {
|
||||
> .toc-controls {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
color: $color-gray;
|
||||
|
||||
|
@ -140,6 +88,7 @@
|
|||
overflow-x: hidden;
|
||||
list-style-type: none;
|
||||
margin: 20px 0 0;
|
||||
font-family: $font-semibold;
|
||||
|
||||
.item {
|
||||
padding: 4px 0;
|
||||
|
|
61
app/app/styles/view/document/toolbar.scss
Normal file
61
app/app/styles/view/document/toolbar.scss
Normal file
|
@ -0,0 +1,61 @@
|
|||
.document-toolbar {
|
||||
position: relative;
|
||||
margin: -30px 0 40px;
|
||||
height: 60px;
|
||||
padding: 5px 30px 0;
|
||||
background-color: $color-off-white;
|
||||
@include border-radius-bottom-right(5px);
|
||||
@include border-radius-bottom-left(5px);
|
||||
@extend .no-select;
|
||||
|
||||
> .tabs {
|
||||
width: 80%;
|
||||
height: 50px;
|
||||
margin-top: 15px;
|
||||
display: inline-block;
|
||||
|
||||
> .tab {
|
||||
list-style-type: none;
|
||||
display: inline-block;
|
||||
margin: 0 20px 0 0;
|
||||
padding: 0;
|
||||
color: $color-gray;
|
||||
font-family: $font-semibold;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $color-link;
|
||||
}
|
||||
|
||||
> a {
|
||||
color: $color-gray;
|
||||
}
|
||||
|
||||
> .active {
|
||||
color: $color-link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .options {
|
||||
width: 20%;
|
||||
height: 50px;
|
||||
margin-top: 15px;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
float: right;
|
||||
|
||||
> .option {
|
||||
list-style-type: none;
|
||||
display: inline-block;
|
||||
margin: 0 0 0 20px;
|
||||
padding: 0;
|
||||
color: $color-gray;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $color-link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@
|
|||
font-size: 1.6em;
|
||||
font-family: open_sanslight;
|
||||
color:$color-off-black;
|
||||
margin: 30px 0 20px 0;
|
||||
margin: 0 0 20px 0;
|
||||
}
|
||||
|
||||
h2
|
||||
|
|
|
@ -133,6 +133,6 @@
|
|||
|
||||
.zone-content {
|
||||
min-height: 500px; //ensure dropdowns render in viewport
|
||||
padding: 30px 40px 30px 100px;
|
||||
padding: 30px 40px 30px 110px;
|
||||
z-index: 777;
|
||||
}
|
||||
|
|
|
@ -1,77 +1,81 @@
|
|||
* { box-sizing: border-box; }
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input-control {
|
||||
position: relative;
|
||||
margin-bottom: 25px;
|
||||
position: relative;
|
||||
margin-bottom: 25px;
|
||||
|
||||
> label {
|
||||
color: $color-input;
|
||||
font-size: 1.1em;
|
||||
font-weight: normal;
|
||||
pointer-events: none;
|
||||
}
|
||||
> label {
|
||||
color: $color-input;
|
||||
font-size: 1.1em;
|
||||
font-weight: normal;
|
||||
font-family: $font-semibold;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
> .tip {
|
||||
color: $color-input;
|
||||
font-size: 0.8em;
|
||||
margin: 5px 0 10px 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
> .tip {
|
||||
color: $color-input;
|
||||
font-size: 1em;
|
||||
margin: 5px 0 10px;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
font-family: $font-light;
|
||||
}
|
||||
|
||||
> input,
|
||||
textarea {
|
||||
font-size: 1em;
|
||||
padding: 8px 0 10px 0;
|
||||
margin: 0 0 15px 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-bottom: 1px solid $color-input;
|
||||
height: 2.3rem;
|
||||
outline: none;
|
||||
> input,
|
||||
textarea {
|
||||
font-size: 1em;
|
||||
padding: 8px 0 10px;
|
||||
margin: 0 0 15px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-bottom: 1px solid $color-input;
|
||||
height: 2.3rem;
|
||||
outline: none;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-bottom: 1px solid $color-input !important;
|
||||
box-shadow: 0 1px 0 0 $color-input !important;
|
||||
transition: 0.2s ease all;
|
||||
-moz-transition: 0.2s ease all;
|
||||
-webkit-transition: 0.2s ease all;
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-bottom: 1px solid $color-primary !important;
|
||||
box-shadow: 0 1px 0 0 $color-primary !important;
|
||||
transition: 0.2s ease all;
|
||||
-moz-transition: 0.2s ease all;
|
||||
-webkit-transition: 0.2s ease all;
|
||||
}
|
||||
}
|
||||
|
||||
> textarea {
|
||||
resize: none;
|
||||
height: auto !important;
|
||||
> textarea {
|
||||
resize: none;
|
||||
height: auto !important;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
> select,
|
||||
> select,
|
||||
> div select {
|
||||
background-color: $color-white;
|
||||
padding: 5px;
|
||||
border: 1px solid $color-input;
|
||||
border-radius: 2px;
|
||||
height: 2.3rem;
|
||||
padding: 5px;
|
||||
border: 1px solid $color-input;
|
||||
border-radius: 2px;
|
||||
height: 2.3rem;
|
||||
font-size: 1rem;
|
||||
display: inline-block;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border: 1px solid $color-input !important;
|
||||
box-shadow: none !important;
|
||||
transition: 0.2s ease all;
|
||||
-moz-transition: 0.2s ease all;
|
||||
-webkit-transition: 0.2s ease all;
|
||||
}
|
||||
outline: none;
|
||||
border: 1px solid $color-input !important;
|
||||
box-shadow: none !important;
|
||||
transition: 0.2s ease all;
|
||||
-moz-transition: 0.2s ease all;
|
||||
-webkit-transition: 0.2s ease all;
|
||||
}
|
||||
}
|
||||
|
||||
> .checkbox {
|
||||
width: 100%;
|
||||
font-size: 1em;
|
||||
padding: 8px 0 10px 0;
|
||||
margin: 0 0 15px 0;
|
||||
padding: 8px 0 10px;
|
||||
margin: 0 0 15px;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
border-bottom: 1px solid $color-input;
|
||||
|
@ -89,7 +93,7 @@
|
|||
|
||||
> input[type='checkbox'] {
|
||||
font-size: 1em;
|
||||
padding: 8px 0 10px 0;
|
||||
padding: 8px 0 10px;
|
||||
margin: 0 0 15px 5px;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
|
@ -108,66 +112,67 @@
|
|||
}
|
||||
|
||||
> label {
|
||||
color: $color-off-black;
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
pointer-events: none;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
}
|
||||
color: $color-off-black;
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
pointer-events: none;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
border-color: $color-red;
|
||||
|
||||
&:focus {
|
||||
border-bottom: 1px solid $color-red !important;
|
||||
box-shadow: 0 1px 0 0 $color-red !important;
|
||||
}
|
||||
border-bottom: 1px solid $color-red !important;
|
||||
box-shadow: 0 1px 0 0 $color-red !important;
|
||||
}
|
||||
}
|
||||
|
||||
select.error {
|
||||
border-color: $color-red;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid $color-red !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
border: 1px solid $color-red !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-inline {
|
||||
display: inline-block;
|
||||
cursor: default;
|
||||
width: 97%;
|
||||
display: inline-block;
|
||||
cursor: default;
|
||||
width: 97%;
|
||||
|
||||
> input {
|
||||
font-size: 1em;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
border: none;
|
||||
height: auto;
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
> input {
|
||||
font-size: 1em;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
border: none;
|
||||
height: auto;
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-bottom: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-bottom: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-form {
|
||||
border: 1px solid $color-border;
|
||||
display: block;
|
||||
border-radius : 3px;
|
||||
background-color: $color-white;
|
||||
border: 1px solid $color-border;
|
||||
display: block;
|
||||
border-radius: 3px;
|
||||
background-color: $color-white;
|
||||
padding: 30px 50px;
|
||||
|
||||
> .heading, > form .heading {
|
||||
>.title {
|
||||
> .heading,
|
||||
> form .heading {
|
||||
> .title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: $color-off-black;
|
||||
|
@ -176,15 +181,17 @@
|
|||
> .tip {
|
||||
color: $color-input;
|
||||
font-size: 0.9em;
|
||||
margin: 5px 0 30px 0;
|
||||
margin: 5px 0 30px;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-divider {
|
||||
margin-top: 30px;
|
||||
.form-bordered {
|
||||
padding: 30px 40px;
|
||||
border: 10px solid $color-border;
|
||||
@include border-radius(15px);
|
||||
}
|
||||
|
||||
.form-borderless {
|
||||
|
@ -192,6 +199,10 @@
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
.form-divider {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.widget-checkbox {
|
||||
color: $color-link;
|
||||
cursor: pointer;
|
||||
|
|
44
app/app/templates/components/document/document-files.hbs
Normal file
44
app/app/templates/components/document/document-files.hbs
Normal file
|
@ -0,0 +1,44 @@
|
|||
<div class="document-files">
|
||||
<ul class="list">
|
||||
{{#each files key="id" as |a index|}}
|
||||
<li class="item">
|
||||
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.extension}}" />
|
||||
<a href="{{ appMeta.endpoint }}/public/attachments/{{ appMeta.orgId }}/{{ a.id }}">
|
||||
<span class="file">{{ a.filename }}</span>
|
||||
</a>
|
||||
{{#if isEditor}}
|
||||
<div class="action round-button-mono">
|
||||
<i class="material-icons color-gray delete-attachment-{{a.id}}" title="Delete" {{action 'confirmDeleteAttachment' a.id a.filename}}>delete</i>
|
||||
</div>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
{{#if emptyState}}
|
||||
<div class="explainer">
|
||||
<div class="empty-state">
|
||||
There are no files
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div id="upload-document-files" class="upload-document-files">
|
||||
Drag-drop files or click to select files
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dropdown-dialog delete-attachment-dialog">
|
||||
<div class="content">
|
||||
<p>Are you sure you want to delete <span class="bold">{{deleteAttachment.name}}?</span></p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="flat-button" {{action 'cancel'}}>
|
||||
cancel
|
||||
</div>
|
||||
<div class="flat-button flat-red" {{action 'deleteAttachment'}}>
|
||||
delete
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
23
app/app/templates/components/document/document-meta.hbs
Normal file
23
app/app/templates/components/document/document-meta.hbs
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div class="form-bordered">
|
||||
<div class="input-control">
|
||||
<label>Owner</label>
|
||||
<div class="tip">Set the document owner</div>
|
||||
{{ui-select id="document-owner"
|
||||
content=users
|
||||
action=(action (mut owner))
|
||||
optionValuePath="id"
|
||||
optionLabelPath="fullname"
|
||||
selection=owner}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Name</label>
|
||||
<div class="tip">Short title for this document</div>
|
||||
{{focus-input type='text' id="document-name" value=document.name}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Excerpt</label>
|
||||
<div class="tip">Provide short summary of the document (max. 250)</div>
|
||||
{{textarea value=document.excerpt rows="5" id="meta-excerpt"}}
|
||||
</div>
|
||||
<div class="regular-button button-blue" {{ action 'onSave' }}>Save</div>
|
||||
</div>
|
|
@ -1,22 +1,24 @@
|
|||
<div class="document-structure">
|
||||
{{#if this.session.authenticated}}
|
||||
<div id="tocToolbar" class="hidden-xs hidden-sm toc-controls {{if state.actionablePage 'current-page' ''}}">
|
||||
<div id="toc-up-button" class="round-button-mono {{if state.upDisabled 'disabled'}}" data-tooltip="Move up" data-tooltip-position="top center" {{action 'pageUp'}}>
|
||||
<i class="material-icons">arrow_upward</i>
|
||||
</div>
|
||||
<div class="button-gap" />
|
||||
<div id="toc-down-button" class="round-button-mono {{if state.downDisabled 'disabled'}}" data-tooltip="Move down" data-tooltip-position="top center" {{action 'pageDown'}}>
|
||||
<i class="material-icons">arrow_downward</i>
|
||||
</div>
|
||||
<div class="button-gap" />
|
||||
<div id="toc-outdent-button" class="round-button-mono {{if state.outdentDisabled 'disabled'}}" data-tooltip="Outdent" data-tooltip-position="top center" {{action 'pageOutdent'}}>
|
||||
<i class="material-icons">format_indent_decrease</i>
|
||||
</div>
|
||||
<div class="button-gap" />
|
||||
<div id="toc-indent-button" class="round-button-mono {{if state.indentDisabled 'disabled'}}" data-tooltip="Indent" data-tooltip-position="top center" {{action 'pageIndent'}}>
|
||||
<i class="material-icons">format_indent_increase</i>
|
||||
</div>
|
||||
</div>
|
||||
{{#unless emptyState}}
|
||||
<div id="tocToolbar" class="hidden-xs hidden-sm toc-controls {{if state.actionablePage 'current-page' ''}}">
|
||||
<div id="toc-up-button" class="round-button-mono {{if state.upDisabled 'disabled'}}" data-tooltip="Move up" data-tooltip-position="top center" {{action 'pageUp'}}>
|
||||
<i class="material-icons">arrow_upward</i>
|
||||
</div>
|
||||
<div class="button-gap" />
|
||||
<div id="toc-down-button" class="round-button-mono {{if state.downDisabled 'disabled'}}" data-tooltip="Move down" data-tooltip-position="top center" {{action 'pageDown'}}>
|
||||
<i class="material-icons">arrow_downward</i>
|
||||
</div>
|
||||
<div class="button-gap" />
|
||||
<div id="toc-outdent-button" class="round-button-mono {{if state.outdentDisabled 'disabled'}}" data-tooltip="Outdent" data-tooltip-position="top center" {{action 'pageOutdent'}}>
|
||||
<i class="material-icons">format_indent_decrease</i>
|
||||
</div>
|
||||
<div class="button-gap" />
|
||||
<div id="toc-indent-button" class="round-button-mono {{if state.indentDisabled 'disabled'}}" data-tooltip="Indent" data-tooltip-position="top center" {{action 'pageIndent'}}>
|
||||
<i class="material-icons">format_indent_increase</i>
|
||||
</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
|
||||
<ul id="document-index" class="entries">
|
||||
|
|
|
@ -1,34 +1,6 @@
|
|||
<div class="document-sidebar">
|
||||
{{back-to-space folder=folder}}
|
||||
|
||||
{{#if session.authenticated}}
|
||||
<div class="summary-line hidden-xs hidden-sm">
|
||||
<ul class="items">
|
||||
<li class="item {{if showToc "active"}}" {{action 'showToc'}}>
|
||||
<div class="metric">
|
||||
<div class="number">{{pages.length}}</div>
|
||||
<div class="label">sections</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="divider" />
|
||||
<li class="item {{if showViews "active"}}" {{action 'showViews'}}>
|
||||
<div class="metric">
|
||||
<div class="number">{{meta.viewers.length}}</div>
|
||||
<div class="label">views</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="divider" />
|
||||
<li class="item {{if showContributions "active"}}" {{action 'showContributions'}}>
|
||||
<div class="metric">
|
||||
<div class="number">{{meta.editors.length}}</div>
|
||||
<div class="label">activity</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="margin-top-40" />
|
||||
{{/if}}
|
||||
<div class="margin-top-40" />
|
||||
|
||||
{{#if isEditor}}
|
||||
<div {{action 'showSections'}} id="section-tool" class="round-button round-button-mono button-white section-tool" data-tooltip="Content" data-tooltip-position="top center">
|
||||
|
@ -48,16 +20,10 @@
|
|||
{{/if}}
|
||||
|
||||
{{#if showToc}}
|
||||
{{document/document-sidebar-toc document=model folder=folder pages=pages page=page isEditor=isEditor
|
||||
{{document/document-sidebar-toc document=document folder=folder pages=pages page=page isEditor=isEditor
|
||||
changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange')
|
||||
gotoPage=(action 'gotoPage')}}
|
||||
{{/if}}
|
||||
{{#if showViews}}
|
||||
{{document/document-sidebar-viewers meta=meta}}
|
||||
{{/if}}
|
||||
{{#if showContributions}}
|
||||
{{document/document-sidebar-edits pages=pages meta=meta}}
|
||||
{{/if}}
|
||||
{{#if showSections}}
|
||||
{{document/page-wizard document=document folder=folder onCancel=(action 'onCancel') onAction=(action 'onAddSection')}}
|
||||
{{/if}}
|
||||
|
|
|
@ -1,35 +1,43 @@
|
|||
<div class="pull-right hidden-xs hidden-sm">
|
||||
{{#if isEditor}}
|
||||
<div class="button-gap"></div>
|
||||
<div class="round-button-mono" id="set-meta-button" data-tooltip="Set meta" data-tooltip-position="top center">
|
||||
<i class="material-icons color-gray">settings</i>
|
||||
</div>
|
||||
<div class="button-gap"></div>
|
||||
<div class="round-button-mono" id="attachment-button" data-tooltip="Attach file" data-tooltip-position="top center">
|
||||
<i class="material-icons color-gray">attach_file</i>
|
||||
</div>
|
||||
<div class="button-gap"></div>
|
||||
<div class="round-button-mono" id="save-template-button" data-tooltip="Save as template" data-tooltip-position="top center">
|
||||
<i class="material-icons color-gray">content_copy</i>
|
||||
</div>
|
||||
<div class="button-gap"></div>
|
||||
{{/if}}
|
||||
<div class="document-toolbar hidden-xs hidden-sm">
|
||||
|
||||
<div class="round-button-mono" id="print-document-button" data-tooltip="Print me" data-tooltip-position="top center" {{action 'printDocument'}}>
|
||||
<i class="material-icons color-gray">print</i>
|
||||
</div>
|
||||
<ul class="tabs">
|
||||
<li class="tab">
|
||||
{{#link-to 'document.index'}}Content{{/link-to}}
|
||||
</li>
|
||||
<li class="tab">
|
||||
{{#link-to 'document.files'}}Files{{/link-to}}
|
||||
</li>
|
||||
{{#if isEditor}}
|
||||
<li class="tab">
|
||||
{{#link-to 'document.meta'}}Meta{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if session.authenticated}}
|
||||
<li class="tab">
|
||||
{{#link-to 'document.activity'}}Activity{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
{{#if isEditor}}
|
||||
<div class="button-gap"></div>
|
||||
<div class="round-button-mono button-red-text" id="delete-document-button" data-tooltip="Delete content" data-tooltip-position="top center">
|
||||
<i class="material-icons color-gray">delete</i>
|
||||
</div>
|
||||
{{/if}}
|
||||
<ul class="options">
|
||||
<li class="option" id="document-toolbar-menu"><i class="material-icons">more_horiz</i></li>
|
||||
</ul>
|
||||
|
||||
{{#if isEditor}}
|
||||
{{#dropdown-menu target="document-toolbar-menu" position="bottom right" open="click" onOpenCallback=(action 'onMenuOpen') onCloseCallback=(action 'onMenuOpen')}}
|
||||
<ul class="menu">
|
||||
<li class="item" id="print-document-button" {{action 'printDocument'}}>Print</li>
|
||||
{{#if isEditor}}
|
||||
<li class="item" id="save-template-button">Save as template</li>
|
||||
<li class="divider"></li>
|
||||
<li class="item" id="delete-document-button">Delete</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{/dropdown-menu}}
|
||||
|
||||
{{#if menuOpen}}
|
||||
{{#dropdown-dialog target="delete-document-button" position="bottom right" button="Delete" color="flat-red" onAction=(action 'deleteDocument')}}
|
||||
<p>Are you sure you want to delete this document?</p>
|
||||
<p>There is no undo!</p>
|
||||
<p>Are you sure you want to delete this document?</p>
|
||||
<p>There is no undo!</p>
|
||||
{{/dropdown-dialog}}
|
||||
{{#dropdown-dialog target="save-template-button" position="bottom right" button="Save as Template" color="flat-green" onAction=(action 'saveTemplate') focusOn="new-template-name"}}
|
||||
<div>
|
||||
|
@ -45,30 +53,8 @@
|
|||
</div>
|
||||
</div>
|
||||
{{/dropdown-dialog}}
|
||||
{{#dropdown-dialog target="set-meta-button" position="bottom right" button="Save" color="flat-blue" onAction=(action 'saveMeta') selectOn="document-name"}}
|
||||
<div>
|
||||
<div class="input-control">
|
||||
<label>Owner</label>
|
||||
<div class="tip">Set the document owner</div>
|
||||
{{ui-select id="document-owner"
|
||||
content=users
|
||||
action=(action (mut owner))
|
||||
optionValuePath="id"
|
||||
optionLabelPath="fullname"
|
||||
selection=owner}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Name</label>
|
||||
<div class="tip">Short title for this document</div>
|
||||
{{input type='text' id="document-name" value=document.name}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Excerpt</label>
|
||||
<div class="tip">Provide short summary of the document (max. 250)</div>
|
||||
{{textarea value=document.excerpt rows="5" id="meta-excerpt"}}
|
||||
</div>
|
||||
</div>
|
||||
{{/dropdown-dialog}}
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
<div class="margin-bottom-20 clearfix" />
|
||||
|
||||
<div class="clearfix"/>
|
||||
|
|
|
@ -14,26 +14,6 @@
|
|||
{{document.name}}
|
||||
</div>
|
||||
|
||||
{{#if attachments}}
|
||||
<div class="attachment-zone">
|
||||
<ul class="list">
|
||||
{{#each attachments key="id" as |a index|}}
|
||||
<li class="item">
|
||||
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.extension}}" />
|
||||
<a href="{{ appMeta.endpoint }}/public/attachments/{{ appMeta.orgId }}/{{ a.id }}">
|
||||
<span class="file">{{ a.filename }}</span>
|
||||
</a>
|
||||
{{#if isEditor}}
|
||||
<div class="action round-button-mono">
|
||||
<i class="material-icons delete-attachment-{{a.id}}" title="Delete" {{action 'confirmDeleteAttachment' a.id a.filename}}>delete</i>
|
||||
</div>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="pages">
|
||||
{{#each pages key="id" as |page index|}}
|
||||
<div class="wysiwyg">
|
||||
|
@ -43,21 +23,6 @@
|
|||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="dropdown-dialog delete-attachment-dialog">
|
||||
<div class="content">
|
||||
<p>Are you sure you want to delete <span class="bold">{{deleteAttachment.name}}?</span></p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="flat-button" {{action 'cancel'}}>
|
||||
cancel
|
||||
</div>
|
||||
<div class="flat-button flat-red" {{action 'deleteAttachment'}}>
|
||||
delete
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if noSections}}
|
||||
|
|
|
@ -91,6 +91,10 @@ func GetAttachments(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if len(a) == 0 {
|
||||
a = []entity.Attachment{}
|
||||
}
|
||||
|
||||
json, err := json.Marshal(a)
|
||||
|
||||
if err != nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue