mirror of
https://github.com/documize/community.git
synced 2025-07-25 08:09:43 +02:00
moved emberjs to gui folder
This commit is contained in:
parent
6a18d18f91
commit
dc49dbbeff
999 changed files with 677 additions and 651 deletions
53
gui/app/components/document/block-editor.js
Normal file
53
gui/app/components/document/block-editor.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
store: Ember.inject.service(),
|
||||
|
||||
didReceiveAttrs() {
|
||||
let p = this.get('store').createRecord('page');
|
||||
let m = this.get('store').createRecord('pageMeta');
|
||||
|
||||
p.set('id', this.get('block.id'));
|
||||
p.set('orgId', this.get('block.orgId'));
|
||||
p.set('documentId', this.get('document.id'));
|
||||
p.set('contentType', this.get('block.contentType'));
|
||||
p.set('pageType', this.get('block.pageType'));
|
||||
p.set('title', this.get('block.title'));
|
||||
p.set('body', this.get('block.body'));
|
||||
p.set('rawBody', this.get('block.rawBody'));
|
||||
p.set('excerpt', this.get('block.excerpt'));
|
||||
|
||||
m.set('pageId', this.get('block.id'));
|
||||
m.set('orgId', this.get('block.orgId'));
|
||||
m.set('documentId', this.get('document.id'));
|
||||
m.set('rawBody', this.get('block.rawBody'));
|
||||
m.set('config', this.get('block.config'));
|
||||
m.set('externalSource', this.get('block.externalSource'));
|
||||
|
||||
this.set('page', p);
|
||||
this.set('meta', m);
|
||||
|
||||
this.set('editorType', 'section/' + this.get('block.contentType') + '/type-editor');
|
||||
},
|
||||
|
||||
actions: {
|
||||
onCancel() {
|
||||
this.attrs.onCancel();
|
||||
},
|
||||
|
||||
onAction(page, meta) {
|
||||
this.attrs.onAction(page, meta);
|
||||
}
|
||||
}
|
||||
});
|
137
gui/app/components/document/content-linker.js
Normal file
137
gui/app/components/document/content-linker.js
Normal file
|
@ -0,0 +1,137 @@
|
|||
// 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 {
|
||||
inject: { service }
|
||||
} = Ember;
|
||||
|
||||
export default Ember.Component.extend(TooltipMixin, {
|
||||
link: service(),
|
||||
linkName: '',
|
||||
keywords: '',
|
||||
selection: null,
|
||||
matches: {
|
||||
documents: [],
|
||||
pages: [],
|
||||
attachments: []
|
||||
},
|
||||
tabs: [
|
||||
{ label: 'Section', selected: true },
|
||||
{ label: 'Attachment', selected: false },
|
||||
{ label: 'Search', selected: false }
|
||||
],
|
||||
contentLinkerButtonId: Ember.computed('page', function () {
|
||||
let page = this.get('page');
|
||||
return `content-linker-button-${page.id}`;
|
||||
}),
|
||||
|
||||
showSections: Ember.computed('tabs.@each.selected', function () {
|
||||
return this.get('tabs').findBy('label', 'Section').selected;
|
||||
}),
|
||||
showAttachments: Ember.computed('tabs.@each.selected', function () {
|
||||
return this.get('tabs').findBy('label', 'Attachment').selected;
|
||||
}),
|
||||
showSearch: Ember.computed('tabs.@each.selected', function () {
|
||||
return this.get('tabs').findBy('label', 'Search').selected;
|
||||
}),
|
||||
hasMatches: Ember.computed('matches', function () {
|
||||
let m = this.get('matches');
|
||||
return m.documents.length || m.pages.length || m.attachments.length;
|
||||
}),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
let self = this;
|
||||
|
||||
let folderId = this.get('folder.id');
|
||||
let documentId = this.get('document.id');
|
||||
let pageId = this.get('page.id');
|
||||
|
||||
this.get('link').getCandidates(folderId, documentId, pageId).then(function (candidates) {
|
||||
self.set('candidates', candidates);
|
||||
self.set('hasSections', is.not.null(candidates.pages) && candidates.pages.length);
|
||||
self.set('hasAttachments', is.not.null(candidates.attachments) && candidates.attachments.length);
|
||||
});
|
||||
},
|
||||
|
||||
didRender() {
|
||||
this.addTooltip(document.getElementById("content-linker-button"));
|
||||
this.addTooltip(document.getElementById("content-counter-button"));
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
onKeywordChange: function () {
|
||||
Ember.run.debounce(this, this.fetch, 750);
|
||||
}.observes('keywords'),
|
||||
|
||||
fetch() {
|
||||
let keywords = this.get('keywords');
|
||||
let self = this;
|
||||
|
||||
if (_.isEmpty(keywords)) {
|
||||
this.set('matches', { documents: [], pages: [], attachments: [] });
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('link').searchCandidates(keywords).then(function (matches) {
|
||||
self.set('matches', matches);
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
setSelection(i) {
|
||||
let candidates = this.get('candidates');
|
||||
let matches = this.get('matches');
|
||||
|
||||
this.set('selection', i);
|
||||
|
||||
candidates.pages.forEach(c => {
|
||||
Ember.set(c, 'selected', c.id === i.id);
|
||||
});
|
||||
|
||||
candidates.attachments.forEach(c => {
|
||||
Ember.set(c, 'selected', c.id === i.id);
|
||||
});
|
||||
|
||||
matches.documents.forEach(c => {
|
||||
Ember.set(c, 'selected', c.id === i.id);
|
||||
});
|
||||
|
||||
matches.pages.forEach(c => {
|
||||
Ember.set(c, 'selected', c.id === i.id);
|
||||
});
|
||||
|
||||
matches.attachments.forEach(c => {
|
||||
Ember.set(c, 'selected', c.id === i.id);
|
||||
});
|
||||
},
|
||||
|
||||
onInsertLink() {
|
||||
let selection = this.get('selection');
|
||||
|
||||
if (is.null(selection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.get('onInsertLink')(selection);
|
||||
},
|
||||
|
||||
onTabSelect(tabs) {
|
||||
this.set('tabs', tabs);
|
||||
}
|
||||
}
|
||||
});
|
28
gui/app/components/document/document-editor.js
Normal file
28
gui/app/components/document/document-editor.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
// 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
didReceiveAttrs() {
|
||||
this.set('editorType', 'section/' + this.get('page.contentType') + '/type-editor');
|
||||
},
|
||||
|
||||
actions: {
|
||||
onCancel() {
|
||||
this.attrs.onCancel();
|
||||
},
|
||||
|
||||
onAction(page, meta) {
|
||||
this.attrs.onAction(page, meta);
|
||||
}
|
||||
}
|
||||
});
|
66
gui/app/components/document/document-heading.js
Normal file
66
gui/app/components/document/document-heading.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
// 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';
|
||||
|
||||
const {
|
||||
computed,
|
||||
} = Ember;
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
editMode: false,
|
||||
docName: '',
|
||||
docExcerpt: '',
|
||||
hasNameError: computed.empty('docName'),
|
||||
hasExcerptError: computed.empty('docExcerpt'),
|
||||
|
||||
keyUp(e) {
|
||||
if (e.keyCode === 27) { // escape key
|
||||
this.send('onCancel');
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
toggleEdit() {
|
||||
this.set('docName', this.get('document.name'));
|
||||
this.set('docExcerpt', this.get('document.excerpt'));
|
||||
this.set('editMode', true);
|
||||
|
||||
Ember.run.schedule('afterRender', () => {
|
||||
$('#document-name').select();
|
||||
});
|
||||
},
|
||||
|
||||
onSave() {
|
||||
if (this.get('hasNameError') || this.get('hasExcerptError')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set('document.name', this.get('docName'));
|
||||
this.set('document.excerpt', this.get('docExcerpt'));
|
||||
|
||||
this.showNotification('Saved');
|
||||
this.get('browser').setTitle(this.get('document.name'));
|
||||
this.get('browser').setMetaDescription(this.get('document.excerpt'));
|
||||
|
||||
this.get('documentService').save(this.get('document'));
|
||||
|
||||
this.set('editMode', false);
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
this.set('editMode', false);
|
||||
}
|
||||
}
|
||||
});
|
49
gui/app/components/document/document-history.js
Normal file
49
gui/app/components/document/document-history.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
// 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
revision: null,
|
||||
hasDiff: Ember.computed('diff', function () {
|
||||
return this.get('diff').length > 0;
|
||||
}),
|
||||
|
||||
didReceiveAttrs() {
|
||||
let revisions = this.get('revisions');
|
||||
|
||||
revisions.forEach((r) => {
|
||||
Ember.set(r, 'deleted', r.revisions === 0);
|
||||
Ember.set(r, 'label', `${r.created} - ${r.firstname} ${r.lastname} - ${r.title}`);
|
||||
});
|
||||
|
||||
if (revisions.length > 0 && is.null(this.get('revision'))) {
|
||||
this.send('onSelectRevision', revisions[0]);
|
||||
}
|
||||
|
||||
this.set('revisions', revisions);
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelectRevision(revision) {
|
||||
this.set('revision', revision);
|
||||
|
||||
if (!revision.deleted) {
|
||||
this.attrs.onFetchDiff(revision.pageId, revision.id);
|
||||
}
|
||||
},
|
||||
|
||||
onRollback() {
|
||||
let revision = this.get('revision');
|
||||
this.attrs.onRollback(revision.pageId, revision.id);
|
||||
}
|
||||
}
|
||||
});
|
92
gui/app/components/document/document-page.js
Normal file
92
gui/app/components/document/document-page.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
// 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, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
sectionService: Ember.inject.service('section'),
|
||||
editMode: false,
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
if (this.get('isDestroyed') || this.get('isDestroying')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let page = this.get('page');
|
||||
|
||||
this.get('documentService').getPageMeta(page.get('documentId'), page.get('id')).then((meta) => {
|
||||
if (this.get('isDestroyed') || this.get('isDestroying')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set('meta', meta);
|
||||
if (this.get('toEdit') === this.get('page.id') && this.get('isEditor')) {
|
||||
this.send('onEdit');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSavePage(page, meta) {
|
||||
this.set('page', page);
|
||||
this.set('meta', meta);
|
||||
this.set('editMode', false);
|
||||
this.get('onSavePage')(page, meta);
|
||||
},
|
||||
|
||||
onSavePageAsBlock(block) {
|
||||
this.attrs.onSavePageAsBlock(block);
|
||||
},
|
||||
|
||||
onCopyPage(documentId) {
|
||||
this.attrs.onCopyPage(this.get('page.id'), documentId);
|
||||
},
|
||||
|
||||
onMovePage(documentId) {
|
||||
this.attrs.onMovePage(this.get('page.id'), documentId);
|
||||
},
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
onEdit() {
|
||||
if (this.get('editMode')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('toEdit', '');
|
||||
// this.set('pageId', this.get('page.id'));
|
||||
this.set('editMode', true);
|
||||
},
|
||||
|
||||
onCancelEdit() {
|
||||
this.set('editMode', false);
|
||||
}
|
||||
}
|
||||
});
|
77
gui/app/components/document/document-tab.js
Normal file
77
gui/app/components/document/document-tab.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
// 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, {
|
||||
sectionService: Ember.inject.service('section'),
|
||||
viewMode: true,
|
||||
editMode: false,
|
||||
|
||||
didInsertElement() {
|
||||
this.get('sectionService').refresh(this.get('document.id')).then((changes) => {
|
||||
if (this.get('isDestroyed') || this.get('isDestroying')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let oldPage = this.get('page');
|
||||
|
||||
if (is.undefined(changes) || is.undefined(oldPage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
changes.forEach((newPage) => {
|
||||
if (oldPage.get('id') === newPage.get('id')) {
|
||||
oldPage.set('body', newPage.get('body'));
|
||||
oldPage.set('revised', newPage.get('revised'));
|
||||
this.showNotification(`Refreshed ${oldPage.get('title')}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onExpand() {
|
||||
this.set('pageId', this.get('page.id'));
|
||||
this.set('expanded', !this.get('expanded'));
|
||||
},
|
||||
|
||||
onSavePageAsBlock(block) {
|
||||
this.attrs.onSavePageAsBlock(block);
|
||||
},
|
||||
|
||||
onCopyPage(documentId) {
|
||||
this.attrs.onCopyPage(this.get('page.id'), documentId);
|
||||
},
|
||||
|
||||
onMovePage(documentId) {
|
||||
this.attrs.onMovePage(this.get('page.id'), documentId);
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
316
gui/app/components/document/document-view.js
Normal file
316
gui/app/components/document/document-view.js
Normal file
|
@ -0,0 +1,316 @@
|
|||
// 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';
|
||||
|
||||
const {
|
||||
computed,
|
||||
} = Ember;
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
sectionService: Ember.inject.service('section'),
|
||||
appMeta: Ember.inject.service(),
|
||||
link: Ember.inject.service(),
|
||||
hasPages: computed.notEmpty('pages'),
|
||||
newSectionName: 'Section',
|
||||
newSectionNameMissing: computed.empty('newSectionName'),
|
||||
newSectionLocation: '',
|
||||
beforePage: '',
|
||||
toEdit: '',
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.loadBlocks();
|
||||
|
||||
Ember.run.schedule('afterRender', () => {
|
||||
let jumpTo = "#page-" + this.get('pageId');
|
||||
if (!$(jumpTo).inView()) {
|
||||
$(jumpTo).velocity("scroll", { duration: 250, offset: -100 });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
didRender() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.contentLinkHandler();
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.setupAddWizard();
|
||||
|
||||
let self = this;
|
||||
$(".tooltipped").each(function(i, el) {
|
||||
self.addTooltip(el);
|
||||
});
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
$('.start-section:not(.start-section-empty-state)').off('.hoverIntent');
|
||||
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
contentLinkHandler() {
|
||||
let links = this.get('link');
|
||||
let doc = this.get('document');
|
||||
let self = this;
|
||||
|
||||
$("a[data-documize='true']").off('click').on('click', function (e) {
|
||||
let link = links.getLinkObject(self.get('links'), this);
|
||||
|
||||
// local link? exists?
|
||||
if ((link.linkType === "section" || link.linkType === "tab") && link.documentId === doc.get('id')) {
|
||||
let exists = self.get('pages').findBy('id', link.targetId);
|
||||
|
||||
if (_.isUndefined(exists)) {
|
||||
link.orphan = true;
|
||||
} else {
|
||||
if (link.linkType === "section") {
|
||||
self.attrs.onGotoPage(link.targetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (link.orphan) {
|
||||
$(this).addClass('broken-link');
|
||||
self.showNotification('Broken link!');
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
links.linkClick(doc, link);
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
setupAddWizard() {
|
||||
Ember.run.schedule('afterRender', () => {
|
||||
$('.start-section:not(.start-section-empty-state)').off('.hoverIntent');
|
||||
|
||||
$('.start-section:not(.start-section-empty-state)').hoverIntent({interval: 100, over: function() {
|
||||
// in
|
||||
$(this).find('.start-button').velocity("transition.slideDownIn", {duration: 300});
|
||||
}, out: function() {
|
||||
// out
|
||||
$(this).find('.start-button').velocity("transition.slideUpOut", {duration: 300});
|
||||
} });
|
||||
});
|
||||
},
|
||||
|
||||
addSection(model) {
|
||||
// calculate sequence of page (position in document)
|
||||
let sequence = 0;
|
||||
let level = 1;
|
||||
let beforePage = this.get('beforePage');
|
||||
|
||||
if (is.not.null(beforePage)) {
|
||||
level = beforePage.get('level');
|
||||
|
||||
// get any page before the beforePage so we can insert this new section between them
|
||||
let index = _.findIndex(this.get('pages'), function(p) { return p.get('id') === beforePage.get('id'); });
|
||||
|
||||
if (index !== -1) {
|
||||
let beforeBeforePage = this.get('pages')[index-1];
|
||||
|
||||
if (is.not.undefined(beforeBeforePage)) {
|
||||
sequence = (beforePage.get('sequence') + beforeBeforePage.get('sequence')) / 2;
|
||||
} else {
|
||||
sequence = beforePage.get('sequence') / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.page.sequence = sequence;
|
||||
model.page.level = level;
|
||||
|
||||
this.send('onHideSectionWizard');
|
||||
|
||||
return this.get('onInsertSection')(model);
|
||||
},
|
||||
|
||||
loadBlocks() {
|
||||
this.get('sectionService').getSpaceBlocks(this.get('folder.id')).then((blocks) => {
|
||||
if (this.get('isDestroyed') || this.get('isDestroying')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set('blocks', blocks);
|
||||
this.set('hasBlocks', blocks.get('length') > 0);
|
||||
|
||||
blocks.forEach((b) => {
|
||||
b.set('deleteId', `delete-block-button-${b.id}`);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSavePageAsBlock(block) {
|
||||
const promise = this.attrs.onSavePageAsBlock(block);
|
||||
promise.then(() => {
|
||||
this.loadBlocks();
|
||||
});
|
||||
},
|
||||
|
||||
onCopyPage(pageId, documentId) {
|
||||
this.attrs.onCopyPage(pageId, documentId);
|
||||
},
|
||||
|
||||
onMovePage(pageId, documentId) {
|
||||
this.attrs.onMovePage(pageId, documentId);
|
||||
},
|
||||
|
||||
onDeletePage(params) {
|
||||
this.attrs.onDeletePage(params);
|
||||
},
|
||||
|
||||
onSavePage(page, meta) {
|
||||
this.set('toEdit', '');
|
||||
this.attrs.onSavePage(page, meta);
|
||||
},
|
||||
|
||||
onShowSectionWizard(page) {
|
||||
if (is.undefined(page)) {
|
||||
page = { id: '0' };
|
||||
}
|
||||
|
||||
this.set('pageId', '');
|
||||
|
||||
let beforePage = this.get('beforePage');
|
||||
if (is.not.null(beforePage) && $("#new-section-wizard").is(':visible') && beforePage.get('id') === page.id) {
|
||||
this.send('onHideSectionWizard');
|
||||
return;
|
||||
}
|
||||
|
||||
this.set('newSectionLocation', page.id);
|
||||
|
||||
if (page.id === '0') {
|
||||
// this handles add section at the end of the document
|
||||
// because we are not before another page
|
||||
this.set('beforePage', null);
|
||||
} else {
|
||||
this.set('beforePage', page);
|
||||
}
|
||||
|
||||
$("#new-section-wizard").insertAfter(`#add-section-button-${page.id}`);
|
||||
$("#new-section-wizard").velocity("transition.slideDownIn", { duration: 300, complete:
|
||||
function() {
|
||||
$("#new-section-name").focus();
|
||||
}});
|
||||
},
|
||||
|
||||
onHideSectionWizard() {
|
||||
this.set('newSectionLocation', '');
|
||||
this.set('beforePage', null);
|
||||
$("#new-section-wizard").insertAfter('#wizard-placeholder');
|
||||
$("#new-section-wizard").velocity("transition.slideUpOut", { duration: 300 });
|
||||
},
|
||||
|
||||
onInsertSection(section) {
|
||||
let sectionName = this.get('newSectionName');
|
||||
if (is.empty(sectionName)) {
|
||||
$("#new-section-name").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
let page = {
|
||||
documentId: this.get('document.id'),
|
||||
title: sectionName,
|
||||
level: 1,
|
||||
sequence: 0, // calculated elsewhere
|
||||
body: "",
|
||||
contentType: section.get('contentType'),
|
||||
pageType: section.get('pageType')
|
||||
};
|
||||
|
||||
let meta = {
|
||||
documentId: this.get('document.id'),
|
||||
rawBody: "",
|
||||
config: ""
|
||||
};
|
||||
|
||||
let model = {
|
||||
page: page,
|
||||
meta: meta
|
||||
};
|
||||
|
||||
const promise = this.addSection(model);
|
||||
promise.then((id) => {
|
||||
this.set('pageId', id);
|
||||
|
||||
if (model.page.pageType === 'section') {
|
||||
this.set('toEdit', id);
|
||||
} else {
|
||||
this.set('toEdit', '');
|
||||
}
|
||||
|
||||
this.setupAddWizard();
|
||||
});
|
||||
},
|
||||
|
||||
onInsertBlock(block) {
|
||||
let sectionName = this.get('newSectionName');
|
||||
if (is.empty(sectionName)) {
|
||||
$("#new-section-name").focus();
|
||||
return;
|
||||
}
|
||||
|
||||
let page = {
|
||||
documentId: this.get('document.id'),
|
||||
title: `${block.get('title')}`,
|
||||
level: 1,
|
||||
sequence: 0, // calculated elsewhere
|
||||
body: block.get('body'),
|
||||
contentType: block.get('contentType'),
|
||||
pageType: block.get('pageType'),
|
||||
blockId: block.get('id')
|
||||
};
|
||||
|
||||
let meta = {
|
||||
documentId: this.get('document.id'),
|
||||
rawBody: block.get('rawBody'),
|
||||
config: block.get('config'),
|
||||
externalSource: block.get('externalSource')
|
||||
};
|
||||
|
||||
let model = {
|
||||
page: page,
|
||||
meta: meta
|
||||
};
|
||||
|
||||
const promise = this.addSection(model);
|
||||
promise.then((id) => {
|
||||
this.set('pageId', id);
|
||||
|
||||
this.setupAddWizard();
|
||||
});
|
||||
},
|
||||
|
||||
onDeleteBlock(id) {
|
||||
const promise = this.attrs.onDeleteBlock(id);
|
||||
|
||||
promise.then(() => {
|
||||
this.loadBlocks();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
194
gui/app/components/document/page-heading.js
Normal file
194
gui/app/components/document/page-heading.js
Normal file
|
@ -0,0 +1,194 @@
|
|||
// 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'),
|
||||
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: {
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
24
gui/app/components/document/sidebar-view-activity.js
Normal file
24
gui/app/components/document/sidebar-view-activity.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
// 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
documentService: Ember.inject.service('document'),
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.get('documentService').getActivity(this.get('document.id')).then((activity) => {
|
||||
this.set('activity', activity);
|
||||
});
|
||||
}
|
||||
});
|
147
gui/app/components/document/sidebar-view-attachments.js
Normal file
147
gui/app/components/document/sidebar-view-attachments.js
Normal file
|
@ -0,0 +1,147 @@
|
|||
// 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, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
appMeta: Ember.inject.service(),
|
||||
drop: null,
|
||||
emptyState: Ember.computed.empty('files'),
|
||||
deleteAttachment: {
|
||||
id: "",
|
||||
name: "",
|
||||
},
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.getAttachments();
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
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.getAttachments();
|
||||
});
|
||||
|
||||
this.on("addedfile", function ( /*file*/ ) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dzone.on("complete", function (file) {
|
||||
dzone.removeFile(file);
|
||||
});
|
||||
|
||||
this.set('drop', dzone);
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
let drop = this.get('drop');
|
||||
if (is.not.null(drop)) {
|
||||
drop.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
getAttachments() {
|
||||
this.get('documentService').getAttachments(this.get('document.id')).then((files) => {
|
||||
this.set('files', files);
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onConfirmDelete(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);
|
||||
},
|
||||
|
||||
onCancel() {
|
||||
let drop = this.get('drop');
|
||||
drop.close();
|
||||
|
||||
this.set('deleteAttachment', {
|
||||
id: "",
|
||||
name: ""
|
||||
});
|
||||
},
|
||||
|
||||
onDelete() {
|
||||
let attachment = this.get('deleteAttachment');
|
||||
let drop = this.get('drop');
|
||||
drop.close();
|
||||
|
||||
this.showNotification(`Deleted ${name}`);
|
||||
|
||||
this.get('documentService').deleteAttachment(this.get('document.id'), attachment.id).then(() => {
|
||||
this.getAttachments();
|
||||
this.set('deleteAttachment', {
|
||||
id: "",
|
||||
name: ""
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
24
gui/app/components/document/sidebar-view-index-entry.js
Normal file
24
gui/app/components/document/sidebar-view-index-entry.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
// 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
page: {},
|
||||
tagName: "li",
|
||||
classNames: ["item"],
|
||||
|
||||
actions: {
|
||||
onClick(id) {
|
||||
this.get('onClick')(id);
|
||||
}
|
||||
}
|
||||
});
|
170
gui/app/components/document/sidebar-view-index.js
Normal file
170
gui/app/components/document/sidebar-view-index.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
// 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';
|
||||
import tocUtil from '../../utils/toc';
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
document: {},
|
||||
folder: {},
|
||||
pages: [],
|
||||
currentPageId: "",
|
||||
state: {
|
||||
actionablePage: false,
|
||||
upDisabled: true,
|
||||
downDisabled: true,
|
||||
indentDisabled: true,
|
||||
outdentDisabled: true
|
||||
},
|
||||
emptyState: Ember.computed('pages', function () {
|
||||
return this.get('pages.length') === 0;
|
||||
}),
|
||||
|
||||
didReceiveAttrs: function () {
|
||||
this._super(...arguments);
|
||||
|
||||
this.set('showToc', is.not.undefined(this.get('pages')) && this.get('pages').get('length') > 0);
|
||||
|
||||
if (is.not.null(this.get('currentPageId'))) {
|
||||
this.send('onEntryClick', this.get('currentPageId'));
|
||||
}
|
||||
},
|
||||
|
||||
didRender: function () {
|
||||
this._super(...arguments);
|
||||
|
||||
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._super(...arguments);
|
||||
|
||||
this.eventBus.subscribe('documentPageAdded', this, 'onDocumentPageAdded');
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.eventBus.unsubscribe('documentPageAdded');
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
onDocumentPageAdded(pageId) {
|
||||
this.send('onEntryClick', pageId);
|
||||
},
|
||||
|
||||
// Controls what user can do with the toc (left sidebar).
|
||||
// Identifies the target pages.
|
||||
setState(pageId) {
|
||||
this.set('currentPageId', 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)) {
|
||||
state.actionablePage = false;
|
||||
state.upDisabled = state.downDisabled = state.indentDisabled = state.outdentDisabled = true;
|
||||
}
|
||||
|
||||
this.set('state', state);
|
||||
},
|
||||
|
||||
actions: {
|
||||
// Page up - above pages shunt down.
|
||||
pageUp() {
|
||||
if (this.get('state.upDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
let pages = this.get('pages');
|
||||
let page = _.findWhere(pages, { id: this.get('currentPageId') });
|
||||
let pendingChanges = tocUtil.moveUp(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.onPageSequenceChange(pendingChanges);
|
||||
|
||||
this.send('onEntryClick', this.get('currentPageId'));
|
||||
this.showNotification("Moved up");
|
||||
}
|
||||
},
|
||||
|
||||
// Move down -- pages below shift up.
|
||||
pageDown() {
|
||||
if (this.get('state.downDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('currentPageId') });
|
||||
let pendingChanges = tocUtil.moveDown(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.onPageSequenceChange(pendingChanges);
|
||||
|
||||
this.send('onEntryClick', this.get('currentPageId'));
|
||||
this.showNotification("Moved down");
|
||||
}
|
||||
},
|
||||
|
||||
// Indent - changes a page from H2 to H3, etc.
|
||||
pageIndent() {
|
||||
if (this.get('state.indentDisabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let state = this.get('state');
|
||||
var pages = this.get('pages');
|
||||
var page = _.findWhere(pages, { id: this.get('currentPageId') });
|
||||
let pendingChanges = tocUtil.indent(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.onPageLevelChange(pendingChanges);
|
||||
|
||||
this.showNotification("Indent");
|
||||
this.send('onEntryClick', this.get('currentPageId'));
|
||||
}
|
||||
},
|
||||
|
||||
// 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('currentPageId') });
|
||||
let pendingChanges = tocUtil.outdent(state, pages, page);
|
||||
|
||||
if (pendingChanges.length > 0) {
|
||||
this.attrs.onPageLevelChange(pendingChanges);
|
||||
|
||||
this.showNotification("Outdent");
|
||||
this.send('onEntryClick', this.get('currentPageId'));
|
||||
}
|
||||
},
|
||||
|
||||
onEntryClick(id) {
|
||||
this.setState(id);
|
||||
this.attrs.onGotoPage(id);
|
||||
}
|
||||
}
|
||||
});
|
148
gui/app/components/document/sidebar-zone.js
Normal file
148
gui/app/components/document/sidebar-zone.js
Normal file
|
@ -0,0 +1,148 @@
|
|||
// 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';
|
||||
import NotifierMixin from '../../mixins/notifier';
|
||||
|
||||
export default Ember.Component.extend(TooltipMixin, NotifierMixin, {
|
||||
documentService: Ember.inject.service('document'),
|
||||
sectionService: Ember.inject.service('section'),
|
||||
sessionService: Ember.inject.service('session'),
|
||||
appMeta: Ember.inject.service(),
|
||||
userService: Ember.inject.service('user'),
|
||||
localStorage: Ember.inject.service(),
|
||||
pinned: Ember.inject.service(),
|
||||
menuOpen: false,
|
||||
pinState : {
|
||||
isPinned: false,
|
||||
pinId: '',
|
||||
newName: '',
|
||||
},
|
||||
saveTemplate: {
|
||||
name: "",
|
||||
description: ""
|
||||
},
|
||||
tab: '',
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
if (is.empty(this.get('tab')) || is.undefined(this.get('tab'))) {
|
||||
this.set('tab', 'index');
|
||||
}
|
||||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.set('saveTemplate.name', this.get('document.name'));
|
||||
this.set('saveTemplate.description', this.get('document.excerpt'));
|
||||
|
||||
this.set('pinState.pinId', this.get('pinned').isDocumentPinned(this.get('document.id')));
|
||||
this.set('pinState.isPinned', this.get('pinState.pinId') !== '');
|
||||
this.set('pinState.newName', this.get('document.name').substring(0,3).toUpperCase());
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChangeTab(tab) {
|
||||
this.set('tab', tab);
|
||||
},
|
||||
|
||||
onTagChange(tags) {
|
||||
let doc = this.get('document');
|
||||
doc.set('tags', tags);
|
||||
this.get('documentService').save(doc);
|
||||
},
|
||||
|
||||
onMenuOpen() {
|
||||
this.set('menuOpen', !this.get('menuOpen'));
|
||||
},
|
||||
|
||||
onDeleteDocument() {
|
||||
this.attrs.onDocumentDelete();
|
||||
},
|
||||
|
||||
onPrintDocument() {
|
||||
$("#sidebar-zone-more-button").click();
|
||||
window.print();
|
||||
},
|
||||
|
||||
onPageSequenceChange(changes) {
|
||||
this.get('onPageSequenceChange')(changes);
|
||||
},
|
||||
|
||||
onPageLevelChange(changes) {
|
||||
this.get('onPageLevelChange')(changes);
|
||||
},
|
||||
|
||||
onGotoPage(id) {
|
||||
this.get('onGotoPage')(id);
|
||||
},
|
||||
|
||||
onUnpin() {
|
||||
this.get('pinned').unpinItem(this.get('pinState.pinId')).then(() => {
|
||||
this.set('pinState.isPinned', false);
|
||||
this.set('pinState.pinId', '');
|
||||
this.eventBus.publish('pinChange');
|
||||
});
|
||||
},
|
||||
|
||||
onPin() {
|
||||
let pin = {
|
||||
pin: this.get('pinState.newName'),
|
||||
documentId: this.get('document.id'),
|
||||
folderId: this.get('folder.id')
|
||||
};
|
||||
|
||||
if (is.empty(pin.pin)) {
|
||||
$("#pin-document-name").addClass("error").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
this.get('pinned').pinItem(pin).then((pin) => {
|
||||
this.set('pinState.isPinned', true);
|
||||
this.set('pinState.pinId', pin.get('id'));
|
||||
this.eventBus.publish('pinChange');
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
onSaveTemplate() {
|
||||
var name = this.get('saveTemplate.name');
|
||||
var excerpt = this.get('saveTemplate.description');
|
||||
|
||||
if (is.empty(name)) {
|
||||
$("#new-template-name").addClass("error").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is.empty(excerpt)) {
|
||||
$("#new-template-desc").addClass("error").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
this.showNotification('Template saved');
|
||||
this.attrs.onSaveTemplate(name, excerpt);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
onLayoutChange(layout) {
|
||||
let doc = this.get('document');
|
||||
doc.set('layout', layout);
|
||||
this.get('documentService').save(doc);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
200
gui/app/components/document/tab-heading.js
Normal file
200
gui/app/components/document/tab-heading.js
Normal 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;
|
||||
}
|
||||
}
|
||||
});
|
109
gui/app/components/document/tag-editor.js
Normal file
109
gui/app/components/document/tag-editor.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
// 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';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
documentTags: [],
|
||||
tagz: [],
|
||||
isEditor: false,
|
||||
newTag: "",
|
||||
maxTags: 3,
|
||||
canAdd: false,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
let tagz = [];
|
||||
|
||||
if (!_.isUndefined(this.get('documentTags')) && this.get('documentTags').length > 1) {
|
||||
let tags = this.get('documentTags').split('#');
|
||||
_.each(tags, function(tag) {
|
||||
if (tag.length > 0) {
|
||||
tagz.pushObject(tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.set('tagz', tagz);
|
||||
this.set('canAdd', this.get('isEditor') && this.get('tagz').get('length') < 3);
|
||||
},
|
||||
|
||||
didUpdateAttrs() {
|
||||
this.set('canAdd', this.get('isEditor') && this.get('tagz').get('length') < 3);
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
$("#add-tag-field").off("keydown");
|
||||
},
|
||||
|
||||
actions: {
|
||||
onTagEditor() {
|
||||
$("#add-tag-field").off("keydown").on("keydown", function(e) {
|
||||
if (e.shiftKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.which === 13 || e.which === 45 || e.which === 189 || e.which === 8 || e.which === 127 || (e.which >= 65 && e.which <= 90) || (e.which >= 97 && e.which <= 122) || (e.which >= 48 && e.which <= 57)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
addTag() {
|
||||
let tags = this.get("tagz");
|
||||
let tag = this.get('newTag');
|
||||
tag = tag.toLowerCase().trim();
|
||||
|
||||
// empty or dupe?
|
||||
if (tag.length === 0 || _.contains(tags, tag) || tags.length >= this.get('maxTags') || tag.startsWith('-')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tags.pushObject(tag);
|
||||
this.set('tagz', tags);
|
||||
this.set('newTag', '');
|
||||
|
||||
let save = "#";
|
||||
_.each(tags, function(tag) {
|
||||
save = save + tag + "#";
|
||||
});
|
||||
|
||||
this.get('onChange')(save);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// removeTag removes specified tag from the list of tags associated with this document.
|
||||
removeTag(tagToRemove) {
|
||||
let tags = this.get("tagz");
|
||||
let save = "";
|
||||
|
||||
tags = _.without(tags, tagToRemove);
|
||||
|
||||
_.each(tags, function(tag) {
|
||||
save = save + tag + "#";
|
||||
});
|
||||
|
||||
if (save.length) {
|
||||
save = "#" + save;
|
||||
}
|
||||
|
||||
this.set('tagz', tags);
|
||||
this.get('onChange')(save);
|
||||
},
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue