diff --git a/.jsbeautifyrc b/.jsbeautifyrc index 2bdd9abc..f2c86f94 100644 --- a/.jsbeautifyrc +++ b/.jsbeautifyrc @@ -5,7 +5,17 @@ "indent_with_tabs": true, "preserve_newlines": true, "max_preserve_newlines": 2, - "newline_between_rules": true + "newline_between_rules": true, + "selector_separator_newlines": true + }, + "scss": { + "indent_size": 4, + "indent_level": 0, + "indent_with_tabs": true, + "preserve_newlines": true, + "max_preserve_newlines": 2, + "newline_between_rules": true, + "selector_separator_newlines": true }, "html": { "indent_size": 4, @@ -38,8 +48,10 @@ "brace_style": "collapse-preserve-inline", "keep_function_indentation": false, "space_after_anon_function": false, + "space_before_anon_function": false, "space_before_conditional": true, "space_in_empty_paren": false, + "space_before_func_paren": false, "space_in_paren": false }, "sql": { diff --git a/README.md b/README.md index 57e2fa23..c4b6c3f6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Documize Community Edition -Modern Wiki + Docs integrating data from SaaS tools. +The Document IDE for wikis and documents. ![Alt text](screenshot.png "Documize") @@ -8,7 +8,7 @@ The mission is to bring software dev inspired features (refactoring, testing, li ## Latest version -v0.30.0 +v0.31.0 ## OS Support diff --git a/app/app/components/document/document-activity.js b/app/app/components/document/document-activity.js new file mode 100644 index 00000000..2ecbf998 --- /dev/null +++ b/app/app/components/document/document-activity.js @@ -0,0 +1,68 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// https://documize.com + +import Ember from 'ember'; + +export default Ember.Component.extend({ + sortedItems: [], + + didReceiveAttrs() { + let editors = this.get('activity.editors'); + let viewers = this.get('activity.viewers'); + let pages = this.get('pages'); + let sorted = []; + + if (is.null(editors)) { + editors = []; + } + + if (is.null(viewers)) { + viewers = []; + } + + viewers.forEach((item) => { + Ember.set(item, 'changeLabel', "viewed"); + Ember.set(item, "viewed", true); + sorted.pushObject({ date: item.created, item: item }); + }); + + editors.forEach(function (item) { + Ember.set(item, "added", item.action === "add-page"); + Ember.set(item, "changed", item.action === "update-page"); + Ember.set(item, "deleted", item.action === "remove-page"); + + let page = pages.findBy('id', item.pageId); + let title = ""; + + if (item.deleted || is.undefined(page)) { + title = "removed section"; + } else { + if (item.added) { + title = "added " + page.get('title'); + } + + if (item.changed) { + title = "changed " + page.get('title'); + } + } + + Ember.set(item, 'changeLabel', title); + + let exists = sorted.findBy('item.pageId', item.pageId); + + if (is.undefined(exists)) { + sorted.pushObject({ date: item.created, item: item }); + } + }); + + this.set('sortedItems', _.sortBy(sorted, 'date').reverse()); + } +}); diff --git a/app/app/components/document/document-files.js b/app/app/components/document/document-files.js new file mode 100644 index 00000000..fe5a95eb --- /dev/null +++ b/app/app/components/document/document-files.js @@ -0,0 +1,131 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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; + } + } +}); diff --git a/app/app/components/document/document-meta.js b/app/app/components/document/document-meta.js new file mode 100644 index 00000000..97c8ef74 --- /dev/null +++ b/app/app/components/document/document-meta.js @@ -0,0 +1,47 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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(), + + didReceiveAttrs() { + // setup document owner + let owner = this.get('users').findBy('id', this.get('document.userId')); + + // no document owner? You are the owner! + if (is.undefined(owner)) { + owner = this.session.user; + } + + this.set('owner', owner); + }, + + 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; + }, + } +}); diff --git a/app/app/components/document/document-sidebar-edits.js b/app/app/components/document/document-sidebar-edits.js deleted file mode 100644 index 957fea8a..00000000 --- a/app/app/components/document/document-sidebar-edits.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2016 Documize Inc. . 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 . -// -// https://documize.com - -import Ember from 'ember'; - -export default Ember.Component.extend({ - document: {}, - meta: [], - pages: [], - - didReceiveAttrs() { - let editors = this.get('meta.editors'); - let toc = this.get('pages'); - - if (is.null(editors)) { - return; - } - - editors.forEach(function (item) { - Ember.set(item, "added", item.action === "add-page"); - Ember.set(item, "changed", item.action === "update-page"); - Ember.set(item, "deleted", item.action === "remove-page"); - - let page = _.findWhere(toc, { - id: item.pageId - }); - let title = ""; - - if (is.not.undefined(page)) { - title = page.get('title'); - - if (item.added) { - Ember.set(item, 'changeLabel', "added " + title); - } - - if (item.changed) { - Ember.set(item, 'changeLabel', "changed " + title); - } - } else { - Ember.set(item, "deleted", true); - - if (item.added) { - Ember.set(item, 'changeLabel', "added section (since removed)"); - } - - if (item.changed) { - Ember.set(item, 'changeLabel', "changed section (since removed)"); - } - - if (item.deleted) { - Ember.set(item, 'changeLabel', "removed section"); - } - } - }); - } -}); diff --git a/app/app/components/document/document-sidebar-toc.js b/app/app/components/document/document-sidebar-toc.js index a8380c7b..3d4d6be0 100644 --- a/app/app/components/document/document-sidebar-toc.js +++ b/app/app/components/document/document-sidebar-toc.js @@ -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') > 0); + 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)) { - state.actionablePage = state.upDisabled = state.downDisabled = state.indentDisabled = state.outdentDisabled = false; - } + 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() { + 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); + } + } }); diff --git a/app/app/components/document/document-sidebar-viewers.js b/app/app/components/document/document-sidebar-viewers.js deleted file mode 100644 index 47a2a6c9..00000000 --- a/app/app/components/document/document-sidebar-viewers.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 Documize Inc. . 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 . -// -// https://documize.com - -import Ember from 'ember'; - -export default Ember.Component.extend({ - document: {}, - meta: [], -}); \ No newline at end of file diff --git a/app/app/components/document/document-sidebar.js b/app/app/components/document/document-sidebar.js index 5edf0be8..f34f2d8f 100644 --- a/app/app/components/document/document-sidebar.js +++ b/app/app/components/document/document-sidebar.js @@ -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); }, @@ -111,9 +89,8 @@ export default Ember.Component.extend(TooltipMixin, NotifierMixin, { }, onAddSection(section) { + this.send('showToc'); this.attrs.onAddSection(section); - - this.set('showingSections', false); }, scrollTop() { diff --git a/app/app/components/document/document-tab.js b/app/app/components/document/document-tab.js new file mode 100644 index 00000000..56b28fca --- /dev/null +++ b/app/app/components/document/document-tab.js @@ -0,0 +1,70 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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, + + didReceiveAttrs(){ + if (this.get('mode') === 'edit') { + this.send('onEdit'); + } + + this.audit.record("viewed-document-section-" + this.get('model.page.contentType')); + }, + + didInsertElement() { + let self = this; + this.get('sectionService').refresh(this.get('model.document.id')).then(function (changes) { + changes.forEach(function (newPage) { + let oldPage = self.get('model.page'); + if (!_.isUndefined(oldPage) && oldPage.get('id') === newPage.get('id')) { + oldPage.set('body', newPage.get('body')); + oldPage.set('revised', newPage.get('revised')); + self.showNotification(`Refreshed ${oldPage.get('title')}`); + } + }); + }); + }, + + actions: { + onEdit() { + this.set('viewMode', false); + this.set('editMode', true); + this.set('mode', 'edit'); + }, + + onView() { + this.set('viewMode', true); + this.set('editMode', false); + this.set('mode', 'view'); + }, + + onCancel() { + this.send('onView'); + }, + + onAction(page, meta) { + this.get('onAction')(page, meta); + this.send('onView'); + }, + + onDelete() { + this.get('onDelete')(this.get('model.document'), this.get('model.page')); + return true; + } + } +}); diff --git a/app/app/components/document/document-toolbar.js b/app/app/components/document/document-toolbar.js index 4f19a868..a9a24c86 100644 --- a/app/app/components/document/document-toolbar.js +++ b/app/app/components/document/document-toolbar.js @@ -19,6 +19,7 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, { localStorage: Ember.inject.service(), drop: null, users: [], + menuOpen: false, saveTemplate: { name: "", description: "" @@ -30,70 +31,20 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, { }, 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); + if (this.session.isEditor) { + this.addTooltip(document.getElementById("add-document-tab")); } }, 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 +71,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; - }, + } } -}); +}); \ No newline at end of file diff --git a/app/app/components/document/document-view.js b/app/app/components/document/document-view.js index d18f5079..7ac563ed 100644 --- a/app/app/components/document/document-view.js +++ b/app/app/components/document/document-view.js @@ -18,51 +18,21 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, { sectionService: Ember.inject.service('section'), appMeta: Ember.inject.service(), link: Ember.inject.service(), - /* Parameters */ document: null, - // pages: [], - attachments: [], folder: null, folders: [], isEditor: false, - /* Internal */ - drop: null, - deleteAttachment: { - id: "", - name: "", - }, noSections: Ember.computed('pages', function () { return this.get('pages.length') === 0; }), - 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')}`); - } - }); - }); - }, - didRender() { this.contentLinkHandler(); }, willDestroyElement() { this.destroyTooltips(); - - let drop = this.get('drop'); - - if (is.not.null(drop)) { - drop.destroy(); - } }, contentLinkHandler() { @@ -70,18 +40,19 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, { let doc = this.get('document'); let self = this; - $("a[data-documize='true']").off('click').on('click', function(e) { - let link = links.getLinkObject(self.get('meta.outboundLinks'), 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.documentId === doc.get('id')) { - let exists = self.get('pages').findBy('id', link.targetId); + if ((link.linkType === "section" || link.linkType === "tab") && link.documentId === doc.get('id')) { + let exists = self.get('allPages').findBy('id', link.targetId); if (_.isUndefined(exists)) { link.orphan = true; } else { - self.attrs.gotoPage(link.targetId); - return false; + if (link.linkType === "section") { + self.attrs.gotoPage(link.targetId); + } } } @@ -99,55 +70,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, { }, 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.showNotification(`Deleted ${attachment.name}`); - this.attrs.onAttachmentDeleted(this.get('deleteAttachment').id); - this.set('deleteAttachment', { - id: "", - name: "" - }); - - return true; - }, - onDeletePage(id, deleteChildren) { let page = this.get('pages').findBy("id", id); @@ -164,7 +86,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, { this.attrs.onDeletePage(params); }, - // onTagChange event emitted from document/tag-editor component onTagChange(tags) { let doc = this.get('document'); doc.set('tags', tags); diff --git a/app/app/components/document/index-entry.js b/app/app/components/document/index-entry.js index 3c139660..682cc55e 100644 --- a/app/app/components/document/index-entry.js +++ b/app/app/components/document/index-entry.js @@ -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); diff --git a/app/app/components/document/page-wizard.js b/app/app/components/document/page-wizard.js index 36d6477f..9e1728dc 100644 --- a/app/app/components/document/page-wizard.js +++ b/app/app/components/document/page-wizard.js @@ -13,31 +13,28 @@ import Ember from 'ember'; import NotifierMixin from '../../mixins/notifier'; export default Ember.Component.extend(NotifierMixin, { - sectionService: Ember.inject.service('section'), + display: 'section', // which CSS to use - didReceiveAttrs() { + didRender() { let self = this; - this.get('sectionService').getAll().then(function(sections) { - self.set('sections', sections); + + Mousetrap.bind('esc', function () { + if (self.get('isDestroyed') || self.get('isDestroying')) { + return; + } + + self.send('onCancel'); + return false; }); }, - didRender() { - let self = this; - - Mousetrap.bind('esc', function() { - self.send('onCancel'); - return false; - }); - }, - - actions: { + actions: { onCancel() { this.attrs.onCancel(); }, - addSection(section) { - this.attrs.onAction(section); - } - } + addSection(section) { + this.attrs.onAction(section); + } + } }); diff --git a/app/app/components/document/tag-editor.js b/app/app/components/document/tag-editor.js index dbc7c17c..d6a5bcfa 100644 --- a/app/app/components/document/tag-editor.js +++ b/app/app/components/document/tag-editor.js @@ -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) { diff --git a/app/app/components/dropdown-dialog.js b/app/app/components/dropdown-dialog.js index 12ccd8c0..d4e0190f 100644 --- a/app/app/components/dropdown-dialog.js +++ b/app/app/components/dropdown-dialog.js @@ -85,9 +85,9 @@ export default Ember.Component.extend({ self.attrs.onOpenCallback(drop); } }); + self.set('drop', drop); } - }, willDestroyElement() { diff --git a/app/app/components/dropdown-menu.js b/app/app/components/dropdown-menu.js index 6f82ca24..ad05604f 100644 --- a/app/app/components/dropdown-menu.js +++ b/app/app/components/dropdown-menu.js @@ -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() { diff --git a/app/app/components/section/gemini/type-editor.js b/app/app/components/section/gemini/type-editor.js index dd3babf7..e2175aa7 100644 --- a/app/app/components/section/gemini/type-editor.js +++ b/app/app/components/section/gemini/type-editor.js @@ -1,11 +1,11 @@ // Copyright 2016 Documize Inc. . 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 . +// by contacting . // // https://documize.com @@ -49,9 +49,7 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, self.set('waiting', true); this.get('sectionService').fetch(this.get('page'), "secrets", this.get('config')) .then(function (response) { - console.log(response); self.set('waiting', false); - self.set('config.APIKey', response.apikey); self.set('config.url', response.url); self.set('config.username', response.username); @@ -223,4 +221,4 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, this.attrs.onAction(page, meta); } } -}); \ No newline at end of file +}); diff --git a/app/app/components/section/github/type-editor.js b/app/app/components/section/github/type-editor.js index 1402c23d..0d3ecfb3 100644 --- a/app/app/components/section/github/type-editor.js +++ b/app/app/components/section/github/type-editor.js @@ -28,69 +28,72 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, if (is.undefined(this.get('config.clientId')) || is.undefined(this.get('config.callbackUrl'))) { self.get('sectionService').fetch(page, "config", {}) - .then(function (cfg) { - let config = {}; + .then(function (cfg) { + let config = {}; - config = { - clientId: cfg.clientID, - callbackUrl: cfg.authorizationCallbackURL, - owner: null, - owner_name: "", - lists: [], - branchSince: "", - branchLines: "100", - userId: "", - pageId: page.get('id'), - showMilestones: false, - showIssues: false, - showCommits: false, - }; + config = { + clientId: cfg.clientID, + callbackUrl: cfg.authorizationCallbackURL, + owner: null, + owner_name: "", + lists: [], + branchSince: "", + branchLines: "100", + userId: "", + pageId: page.get('id'), + showMilestones: false, + showIssues: false, + showCommits: true, + }; - try { - let metaConfig = JSON.parse(self.get('meta.config')); - config.owner = metaConfig.owner; - config.lists = metaConfig.lists; - config.branchSince = metaConfig.branchSince; - config.userId = metaConfig.userId; - config.pageId = metaConfig.pageId; - config.showMilestones = metaConfig.showMilestones; - config.showIssues = metaConfig.showIssues; - config.showCommits = metaConfig.showCommits; - } catch (e) {} + try { + let metaConfig = JSON.parse(self.get('meta.config')); + config.owner = metaConfig.owner; + config.lists = metaConfig.lists; + config.branchSince = metaConfig.branchSince; + config.userId = metaConfig.userId; + config.pageId = metaConfig.pageId; + config.showMilestones = metaConfig.showMilestones; + config.showIssues = metaConfig.showIssues; + config.showCommits = metaConfig.showCommits; + } catch (e) {} - self.set('config', config); - self.set('config.pageId', page.get('id')); + if (_.isUndefined(config.showCommits)) { + config.showCommits = true; + } - // On auth callback capture code - let code = window.location.search; + self.set('config', config); + self.set('config.pageId', page.get('id')); - if (is.not.undefined(code) && is.not.null(code) && is.not.empty(code) && code !== "") { - let tok = code.replace("?code=", ""); - self.get('sectionService').fetch(page, "saveSecret", { "token": tok }) - .then(function () { - console.log("github auth code saved to db"); - self.send('authStage2'); - }, function (error) { //jshint ignore: line - console.log(error); - self.send('auth'); - }); - } else { - if (config.userId !== self.get("session.session.authenticated.user.id")) { - console.log("github auth wrong user ID, switching"); - self.set('config.userId', self.get("session.session.authenticated.user.id")); - } - self.get('sectionService').fetch(page, "checkAuth", self.get('config')) - .then(function () { - console.log("github auth code valid"); - self.send('authStage2'); - }, function (error) { //jshint ignore: line - console.log(error); - self.send('auth'); // require auth if the db token is invalid - }); + // On auth callback capture code + let code = window.location.search; + code = code.replace("?mode=edit", ""); + + if (is.not.undefined(code) && is.not.null(code) && is.not.empty(code) && code !== "") { + let tok = code.replace("&code=", ""); + self.get('sectionService').fetch(page, "saveSecret", { "token": tok }) + .then(function () { + self.send('authStage2'); + }, function (error) { //jshint ignore: line + console.log(error); + self.send('auth'); + }); + } else { + if (config.userId !== self.get("session.session.authenticated.user.id")) { + console.log("github auth wrong user ID, switching"); + self.set('config.userId', self.get("session.session.authenticated.user.id")); } - }, function (error) { //jshint ignore: line - console.log(error); - }); + self.get('sectionService').fetch(page, "checkAuth", self.get('config')) + .then(function () { + self.send('authStage2'); + }, function (error) { //jshint ignore: line + console.log(error); + self.send('auth'); // require auth if the db token is invalid + }); + } + }, function (error) { //jshint ignore: line + console.log(error); + }); } }, @@ -122,7 +125,6 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, $('#branch-since').datetimepicker(); this.set('initDateTimePicker', "Done"); } - }, getOrgReposLists() { @@ -132,41 +134,41 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, let page = this.get('page'); this.get('sectionService').fetch(page, "orgrepos", self.get('config')) - .then(function (lists) { - let savedLists = self.get('config.lists'); - if (savedLists === null) { - savedLists = []; - } + .then(function (lists) { + let savedLists = self.get('config.lists'); + if (savedLists === null) { + savedLists = []; + } - if (lists.length > 0) { - let noIncluded = true; + if (lists.length > 0) { + let noIncluded = true; - lists.forEach(function (list) { - let included = false; - var saved; - if (is.not.undefined(savedLists)) { - saved = savedLists.findBy("id", list.id); - } - if (is.not.undefined(saved)) { - included = saved.included; - noIncluded = false; - } - list.included = included; - }); - - if (noIncluded) { - lists[0].included = true; // make the first entry the default + lists.forEach(function (list) { + let included = false; + var saved; + if (is.not.undefined(savedLists)) { + saved = savedLists.findBy("id", list.id); } - } + if (is.not.undefined(saved)) { + included = saved.included; + noIncluded = false; + } + list.included = included; + }); - self.set('config.lists', lists); - self.set('busy', false); - }, function (error) { //jshint ignore: line - self.set('busy', false); - self.set('authenticated', false); - self.showNotification("Unable to fetch repositories"); - console.log(error); - }); + if (noIncluded) { + lists[0].included = true; // make the first entry the default + } + } + + self.set('config.lists', lists); + self.set('busy', false); + }, function (error) { //jshint ignore: line + self.set('busy', false); + self.set('authenticated', false); + self.showNotification("Unable to fetch repositories"); + console.log(error); + }); }, actions: { @@ -212,11 +214,12 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, let self = this; self.set('busy', true); self.set('authenticated', false); + let target = "https://github.com/login/oauth/authorize?client_id=" + self.get('config.clientId') + "&scope=repo&redirect_uri=" + encodeURIComponent(self.get('config.callbackUrl')) + "&state=" + encodeURIComponent(window.location.href); - window.location.href = target; + window.location.href = target; }, onOwnerChange(thisOwner) { @@ -256,4 +259,4 @@ export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, }); } } -}); \ No newline at end of file +}); diff --git a/app/app/components/section/markdown/type-editor.js b/app/app/components/section/markdown/type-editor.js index 927bdc47..35f07d85 100644 --- a/app/app/components/section/markdown/type-editor.js +++ b/app/app/components/section/markdown/type-editor.js @@ -18,24 +18,22 @@ const { export default Ember.Component.extend({ link: service(), - + editMode: true, isDirty: false, pageBody: "", + pagePreview: "", + height: $(document).height() - 450, didReceiveAttrs() { this.set("pageBody", this.get("meta.rawBody")); }, didInsertElement() { - let height = $(document).height() - $(".document-editor > .toolbar").height() - 130; - $("#section-markdown-editor, #section-markdown-preview").css("height", height); + $("#section-markdown-editor").css("height", this.get('height')); + $("#section-markdown-preview").css("height", this.get('height')); - this.renderPreview(); - let self = this; - - $("#section-markdown-editor").off("keyup").on("keyup", function () { - self.renderPreview(); - self.set('isDirty', true); + $("#section-markdown-editor").off("keyup").on("keyup", () => { + this.set('isDirty', true); }); }, @@ -43,15 +41,26 @@ export default Ember.Component.extend({ $("#section-markdown-editor").off("keyup"); }, - renderPreview() { - let md = window.markdownit({ - linkify: true - }); - let result = md.render(this.get("pageBody")); - $("#section-markdown-preview").html(result); - }, - actions: { + toggleMode() { + this.set('editMode', !this.get('editMode')); + + Ember.run.schedule('afterRender', () => { + if (this.get('editMode')) { + $("#section-markdown-editor").off("keyup").on("keyup", () => { + this.set('isDirty', true); + }); + $("#section-markdown-editor").css("height", this.get('height')); + } else { + let md = window.markdownit({ linkify: true }); + let result = md.render(this.get("pageBody")); + + this.set('pagePreview', result); + $("#section-markdown-preview").css("height", this.get('height')); + } + }); + }, + onInsertLink(link) { let linkMarkdown = this.get('link').buildLink(link); diff --git a/app/app/components/section/table/type-editor.js b/app/app/components/section/table/type-editor.js index 0c1141a4..c81341e8 100644 --- a/app/app/components/section/table/type-editor.js +++ b/app/app/components/section/table/type-editor.js @@ -1,11 +1,11 @@ // Copyright 2016 Documize Inc. . 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 . +// by contacting . // // https://documize.com @@ -25,23 +25,23 @@ export default Ember.Component.extend({ }, didInsertElement() { - let self = this; - $('#table-editor').froalaEditor({ toolbarButtons: [], - height: this.get('editorHeight') - 260, + height: $(document).height() - 400, toolbarInline: true, tableResizerOffset: 10 }); - $('#table-editor').on('froalaEditor.contentChanged', function () { - self.set('isDirty', true); + $('#table-editor').on('froalaEditor.contentChanged', () => { + this.set('isDirty', true); }); }, willDestroyElement() { - $('#table-editor').froalaEditor('destroy'); $('#table-editor').off('froalaEditor.contentChanged'); + // if ($('#table-editor').data('froala.editor')) { + // $('#table-editor').froalaEditor('destroy'); + // } }, actions: { @@ -69,4 +69,4 @@ export default Ember.Component.extend({ this.attrs.onAction(page, meta); } } -}); \ No newline at end of file +}); diff --git a/app/app/components/section/wysiwyg/type-editor.js b/app/app/components/section/wysiwyg/type-editor.js index f63c9ecb..a55fb2d7 100644 --- a/app/app/components/section/wysiwyg/type-editor.js +++ b/app/app/components/section/wysiwyg/type-editor.js @@ -25,7 +25,7 @@ export default Ember.Component.extend({ }, didInsertElement() { - let maxHeight = $(document).height() - $(".document-editor > .toolbar").height() - 200; + let maxHeight = $(document).height() - 450; let options = { selector: "#rich-text-editor", @@ -59,7 +59,7 @@ export default Ember.Component.extend({ ], menu: {}, menubar: false, - toolbar1: "bold italic underline strikethrough superscript subscript | outdent indent bullist numlist forecolor backcolor | alignleft aligncenter alignright alignjustify | link unlink | table image media | hr codesample", + toolbar1: "bold italic underline strikethrough superscript subscript | outdent indent bullist numlist forecolor backcolor | alignleft aligncenter alignright alignjustify | link unlink | table image media codesample", toolbar2: "formatselect fontselect fontsizeselect", save_onsavecallback: function () { Mousetrap.trigger('ctrl+s'); diff --git a/app/app/models/page.js b/app/app/models/page.js index 586991b4..a4e88fac 100644 --- a/app/app/models/page.js +++ b/app/app/models/page.js @@ -18,6 +18,7 @@ export default Model.extend({ documentId: attr('string'), orgId: attr('string'), contentType: attr('string'), + pageType: attr('string'), level: attr('number', { defaultValue: 1 }), sequence: attr('number', { defaultValue: 0 }), revisions: attr('number', { defaultValue: 0 }), @@ -25,10 +26,9 @@ export default Model.extend({ body: attr('string'), rawBody: attr('string'), meta: attr(), - // meta: hasMany('page-meta'), tagName: Ember.computed('level', function () { - return "h" + this.get('level'); + return "h" + (this.get('level') + 1); }), tocIndent: Ember.computed('level', function () { diff --git a/app/app/models/section.js b/app/app/models/section.js index 8887648b..1082c772 100644 --- a/app/app/models/section.js +++ b/app/app/models/section.js @@ -16,6 +16,7 @@ import Ember from 'ember'; export default Model.extend({ contentType: attr('string'), + pageType: attr('string'), title: attr('string'), description: attr('string'), iconFont: attr('string'), @@ -24,6 +25,7 @@ export default Model.extend({ hasImage: Ember.computed('iconFont', 'iconFile', function () { return this.get('iconFile').length > 0; }), + created: attr(), revised: attr() -}); +}); \ No newline at end of file diff --git a/app/app/pods/customize/folders/template.hbs b/app/app/pods/customize/folders/template.hbs index f770c84e..9ba8a6f5 100644 --- a/app/app/pods/customize/folders/template.hbs +++ b/app/app/pods/customize/folders/template.hbs @@ -1,45 +1,43 @@
-
-
-
-
{{folders.length}} shared {{label}}
-
View and change shared space ownership
-
-
- - - - - - - - - {{#each folders as |folder|}} - - - + + {{/each}} + +
SpaceParticipants
- {{#link-to 'folder' folder.id folder.slug class="alt"}}{{folder.name}}{{/link-to}} - - {{#each folder.sharedWith as |person|}} - {{#if person.isEveryone}} - Everyone - {{else}} +
+
+
{{folders.length}} shared {{label}}
+
View and change shared space ownership
+
+
+ + + + + + + + + {{#each folders as |folder|}} + + + - - {{/each}} - -
SpaceParticipants
+ {{#link-to 'folder' folder.id folder.slug class="alt"}}{{folder.name}}{{/link-to}} + + {{#each folder.sharedWith as |person|}} + {{#if person.isEveryone}} + Everyone + {{else}} - {{#if person.isOwner}} - {{person.firstname}} {{person.lastname}} (owner) - {{else}} - {{person.firstname}} {{person.lastname}} - make owner - {{/if}} - {{/if}} -
- {{/each}} -
-
- + {{#if person.isOwner}} + {{person.firstname}} {{person.lastname}} (owner) + {{else}} + {{person.firstname}} {{person.lastname}} + make owner + {{/if}} + {{/if}} +
+ {{/each}} +
+
diff --git a/app/app/pods/customize/general/template.hbs b/app/app/pods/customize/general/template.hbs index 60cabfa8..908dc47e 100644 --- a/app/app/pods/customize/general/template.hbs +++ b/app/app/pods/customize/general/template.hbs @@ -1,3 +1 @@ -
- {{general-settings model=model save=(action 'save')}} -
+{{general-settings model=model save=(action 'save')}} diff --git a/app/app/pods/customize/global/template.hbs b/app/app/pods/customize/global/template.hbs index 6a52c097..bdf3d052 100644 --- a/app/app/pods/customize/global/template.hbs +++ b/app/app/pods/customize/global/template.hbs @@ -1,3 +1 @@ -
- {{global-settings model=model save=(action 'save')}} -
+{{global-settings model=model save=(action 'save')}} diff --git a/app/app/pods/customize/users/template.hbs b/app/app/pods/customize/users/template.hbs index b8b79a11..d8b084c5 100644 --- a/app/app/pods/customize/users/template.hbs +++ b/app/app/pods/customize/users/template.hbs @@ -1,6 +1,4 @@ -
- {{user-settings add=(action 'add')}} -
+{{user-settings add=(action 'add')}}
diff --git a/app/app/components/document/document-sidebar-close-action.js b/app/app/pods/document/activity/controller.js similarity index 79% rename from app/app/components/document/document-sidebar-close-action.js rename to app/app/pods/document/activity/controller.js index 172a15f1..27719168 100644 --- a/app/app/components/document/document-sidebar-close-action.js +++ b/app/app/pods/document/activity/controller.js @@ -10,11 +10,7 @@ // https://documize.com import Ember from 'ember'; +import NotifierMixin from '../../../mixins/notifier'; -export default Ember.Component.extend({ - actions: { - close() { - this.attrs.close(); - } - } +export default Ember.Controller.extend(NotifierMixin, { }); diff --git a/app/app/pods/document/activity/route.js b/app/app/pods/document/activity/route.js new file mode 100644 index 00000000..d0515980 --- /dev/null +++ b/app/app/pods/document/activity/route.js @@ -0,0 +1,33 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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'), + + model() { + this.audit.record("viewed-document-activity"); + + return Ember.RSVP.hash({ + folders: this.modelFor('document').folders, + folder: this.modelFor('document').folder, + document: this.modelFor('document').document, + isEditor: this.modelFor('document').isEditor, + pages: this.modelFor('document').allPages, + tabs: this.modelFor('document').tabs, + activity: this.get('documentService').getMeta(this.modelFor('document').document.get('id')).then((activity) => { + return activity; + }) + }); + } +}); diff --git a/app/app/pods/document/activity/template.hbs b/app/app/pods/document/activity/template.hbs new file mode 100644 index 00000000..2c687d18 --- /dev/null +++ b/app/app/pods/document/activity/template.hbs @@ -0,0 +1 @@ +{{document/document-activity document=model.document pages=model.pages activity=model.activity}} diff --git a/app/app/pods/document/controller.js b/app/app/pods/document/controller.js index 17a79e72..5b9cd1c0 100644 --- a/app/app/pods/document/controller.js +++ b/app/app/pods/document/controller.js @@ -1,14 +1,147 @@ // Copyright 2016 Documize Inc. . 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 . +// by contacting . // // https://documize.com import Ember from 'ember'; +import NotifierMixin from '../../mixins/notifier'; -export default Ember.Controller.extend({}); \ No newline at end of file +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) { + this.get('documentService').changePageSequence(this.get('model.document.id'), changes).then(() => { + _.each(changes, (change) => { + let pageContent = _.findWhere(this.get('model.pages'), { + id: change.pageId + }); + + if (is.not.undefined(pageContent)) { + pageContent.set('sequence', change.sequence); + } + }); + + this.set('model.pages', this.get('model.pages').sortBy('sequence')); + this.get('target.router').refresh(); + }); + }, + + onPageLevelChange(changes) { + this.get('documentService').changePageLevel(this.get('model.document.id'), changes).then(() => { + _.each(changes, (change) => { + let pageContent = _.findWhere(this.get('model.pages'), { + id: change.pageId + }); + + if (is.not.undefined(pageContent)) { + pageContent.set('level', change.level); + } + }); + + let pages = this.get('model.pages'); + pages = pages.sortBy('sequence'); + this.set('model.pages', []); + this.set('model.pages', pages); + this.get('target.router').refresh(); + }); + }, + + onSaveTemplate(name, desc) { + this.get('templateService').saveAsTemplate(this.get('model.document.id'), name, desc).then(function () {}); + }, + + onAddSection(section) { + this.audit.record("added-section-" + section.get('contentType')); + + let page = { + documentId: this.get('model.document.id'), + title: `${section.get('title')}`, + level: 1, + sequence: 0, + body: "", + contentType: section.get('contentType'), + pageType: section.get('pageType') + }; + + let meta = { + documentId: this.get('model.document.id'), + rawBody: "", + config: "" + }; + + let model = { + page: page, + meta: meta + }; + + this.get('documentService').addPage(this.get('model.document.id'), model).then((newPage) => { + let data = this.get('store').normalize('page', newPage); + this.get('store').push(data); + + this.get('documentService').getPages(this.get('model.document.id')).then((pages) => { + this.set('model.pages', pages.filterBy('pageType', 'section')); + this.set('model.tabs', pages.filterBy('pageType', 'tab')); + + this.get('documentService').getPageMeta(this.get('model.document.id'), newPage.id).then(() => { + this.transitionToRoute('document.edit', + this.get('model.folder.id'), + this.get('model.folder.slug'), + this.get('model.document.id'), + this.get('model.document.slug'), + newPage.id); + }); + }); + }); + }, + + onDocumentDelete() { + this.get('documentService').deleteDocument(this.get('model.document.id')).then(() => { + this.audit.record("deleted-page"); + this.send("showNotification", "Deleted"); + this.transitionToRoute('folder', this.get('model.folder.id'), this.get('model.folder.slug')); + }); + } + } +}); diff --git a/app/app/pods/document/edit/controller.js b/app/app/pods/document/edit/controller.js index 91a2f2b0..a4712c3b 100644 --- a/app/app/pods/document/edit/controller.js +++ b/app/app/pods/document/edit/controller.js @@ -10,9 +10,8 @@ // https://documize.com import Ember from 'ember'; -import NotifierMixin from '../../../mixins/notifier'; -export default Ember.Controller.extend(NotifierMixin, { +export default Ember.Controller.extend({ documentService: Ember.inject.service('document'), actions: { @@ -26,8 +25,6 @@ export default Ember.Controller.extend(NotifierMixin, { onAction(page, meta) { let self = this; - this.showNotification("Saving"); - let model = { page: page.toJSON({ includeId: true }), meta: meta.toJSON({ includeId: true }) diff --git a/app/app/pods/document/edit/route.js b/app/app/pods/document/edit/route.js index cd92ad2a..2eb31dde 100644 --- a/app/app/pods/document/edit/route.js +++ b/app/app/pods/document/edit/route.js @@ -1,11 +1,11 @@ // Copyright 2016 Documize Inc. . 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 . +// by contacting . // // https://documize.com @@ -22,10 +22,10 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { this.audit.record("edited-page"); return Ember.RSVP.hash({ - folder: self.get('folderService').getFolder(self.paramsFor('document').folder_id), - document: self.modelFor('document'), + folder: self.modelFor('document').folder, + document: self.modelFor('document').document, page: self.get('documentService').getPage(self.paramsFor('document').document_id, params.page_id), meta: self.get('documentService').getPageMeta(self.paramsFor('document').document_id, params.page_id) }); } -}); \ No newline at end of file +}); diff --git a/app/app/pods/document/files/controller.js b/app/app/pods/document/files/controller.js new file mode 100644 index 00000000..45ef40b8 --- /dev/null +++ b/app/app/pods/document/files/controller.js @@ -0,0 +1,40 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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(); + }); + }, + } +}); diff --git a/app/app/pods/document/files/route.js b/app/app/pods/document/files/route.js new file mode 100644 index 00000000..ac4f8979 --- /dev/null +++ b/app/app/pods/document/files/route.js @@ -0,0 +1,31 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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'), + + model() { + this.audit.record("viewed-document-attachments"); + + return Ember.RSVP.hash({ + folders: this.modelFor('document').folders, + folder: this.modelFor('document').folder, + document: this.modelFor('document').document, + isEditor: this.modelFor('document').isEditor, + pages: this.modelFor('document').allPages, + tabs: this.modelFor('document').tabs, + files: this.get('documentService').getAttachments(this.modelFor('document').document.get('id')) + }); + } +}); diff --git a/app/app/pods/document/files/template.hbs b/app/app/pods/document/files/template.hbs new file mode 100644 index 00000000..ef1f4748 --- /dev/null +++ b/app/app/pods/document/files/template.hbs @@ -0,0 +1 @@ +{{document/document-files document=model.document files=model.files isEditor=model.isEditor onUpload=(action 'onUpload') onDelete=(action 'onDelete')}} diff --git a/app/app/pods/document/index/controller.js b/app/app/pods/document/index/controller.js index f4fd8b1a..9046f1b8 100644 --- a/app/app/pods/document/index/controller.js +++ b/app/app/pods/document/index/controller.js @@ -14,24 +14,7 @@ import NotifierMixin from '../../../mixins/notifier'; export default Ember.Controller.extend(NotifierMixin, { documentService: Ember.inject.service('document'), - templateService: Ember.inject.service('template'), - queryParams: ['page'], - 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) { @@ -66,11 +49,9 @@ export default Ember.Controller.extend(NotifierMixin, { }, 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'), { + this.get('documentService').changePageSequence(this.get('model.document.id'), changes).then(() => { + _.each(changes, (change) => { + let pageContent = _.findWhere(this.get('model.pages'), { id: change.pageId }); @@ -79,16 +60,15 @@ export default Ember.Controller.extend(NotifierMixin, { } }); - self.set('pages', self.get('pages').sortBy('sequence')); + this.set('model.pages', this.get('model.pages').sortBy('sequence')); + this.get('target.router').refresh(); }); }, 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'), { + this.get('documentService').changePageLevel(this.get('model.document.id'), changes).then(() => { + _.each(changes, (change) => { + let pageContent = _.findWhere(this.get('model.pages'), { id: change.pageId }); @@ -97,28 +77,17 @@ export default Ember.Controller.extend(NotifierMixin, { } }); - let pages = self.get('pages'); + let pages = this.get('model.pages'); pages = pages.sortBy('sequence'); - self.set('pages', []); - self.set('pages', pages); - }); - }, + this.set('model.pages', pages); - onAttachmentUpload() { - this.getAttachments(); - }, - - onAttachmentDeleted(id) { - let self = this; - this.get('documentService').deleteAttachment(this.model.get('id'), id).then(function () { - self.getAttachments(); + this.get('target.router').refresh(); }); }, onPageDeleted(deletePage) { - let self = this; - let documentId = this.get('model.id'); - let pages = this.get('pages'); + let documentId = this.get('model.document.id'); + let pages = this.get('model.pages'); let deleteId = deletePage.id; let deleteChildren = deletePage.children; let page = _.findWhere(pages, { @@ -127,6 +96,8 @@ export default Ember.Controller.extend(NotifierMixin, { let pageIndex = _.indexOf(pages, page, false); let pendingChanges = []; + this.audit.record("deleted-page"); + // select affected pages for (var i = pageIndex + 1; i < pages.get('length'); i++) { if (pages[i].get('level') <= page.get('level')) { @@ -145,102 +116,28 @@ export default Ember.Controller.extend(NotifierMixin, { pageId: deleteId }); - this.get('documentService').deletePages(documentId, deleteId, pendingChanges).then(function () { + this.get('documentService').deletePages(documentId, deleteId, pendingChanges).then(() => { // update our models so we don't have to reload from db for (var i = 0; i < pendingChanges.length; i++) { let pageId = pendingChanges[i].pageId; - self.set('pages', _.reject(self.get('pages'), function (p) { //jshint ignore: line - return p.id === pageId; + this.set('model.pages', _.reject(pages, function (p) { //jshint ignore: line + return p.get('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); - }); + this.set('model.pages', _.sortBy(pages, "sequence")); + this.get('target.router').refresh(); }); } else { // page delete followed by re-leveling child pages - this.get('documentService').deletePage(documentId, deleteId).then(function () { - self.set('pages', _.reject(self.get('pages'), function (p) { + this.get('documentService').deletePage(documentId, deleteId).then(() => { + this.set('model.pages', _.reject(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); - }); + this.send('onPageLevelChange', pendingChanges); }); - - 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')); - }); } } }); diff --git a/app/app/pods/document/index/route.js b/app/app/pods/document/index/route.js index b0135671..1bb91b2f 100644 --- a/app/app/pods/document/index/route.js +++ b/app/app/pods/document/index/route.js @@ -14,97 +14,53 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout export default Ember.Route.extend(AuthenticatedRouteMixin, { documentService: Ember.inject.service('document'), + linkService: Ember.inject.service('link'), folderService: Ember.inject.service('folder'), userService: Ember.inject.service('user'), - pages: [], - attachments: [], - 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 () { - this.audit.record("viewed-document"); - return this.modelFor('document'); - }, + beforeModel(transition) { + this.set('pageId', is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : ""); + this.set('folderId', this.paramsFor('document').folder_id); + this.set('documentId', this.paramsFor('document').document_id); - afterModel: function (model) { - var self = this; - var documentId = model.get('id'); + let folders = this.get('store').peekAll('folder'); + let folder = this.get('store').peekRecord('folder', this.get('folderId')); + let document = this.get('store').peekRecord('document', this.get('documentId')); - this.browser.setTitle(model.get('name')); + this.set('document', document); + this.set('folders', folders); + this.set('folder', folder); - // 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(); - } - }); + return new Ember.RSVP.Promise((resolve) => { + this.get('documentService').getPages(this.get('documentId')).then((pages) => { + this.set('allPages', pages); + this.set('pages', pages.filterBy('pageType', 'section')); + this.set('tabs', pages.filterBy('pageType', 'tab')); + resolve(); }); }); + }, - 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')); - controller.set('attachments', this.get('attachments')); - controller.set('users', this.get('users')); + model() { + this.browser.setTitle(this.get('document.name')); + this.browser.setMetaDescription(this.get('document.excerpt')); - // 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')); + return Ember.RSVP.hash({ + folders: this.get('folders'), + folder: this.get('folder'), + document: this.get('document'), + page: this.get('pageId'), + isEditor: this.get('folderService').get('canEditCurrentFolder'), + allPages: this.get('allPages'), + pages: this.get('pages'), + tabs: this.get('tabs'), + links: this.get('linkService').getDocumentLinks(this.get('documentId')) + }); } }); diff --git a/app/app/pods/document/index/template.hbs b/app/app/pods/document/index/template.hbs index 2b55d35a..36019b5a 100644 --- a/app/app/pods/document/index/template.hbs +++ b/app/app/pods/document/index/template.hbs @@ -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.document links=model.links allPages=model.allPages tabs=model.tabs pages=model.pages folder=model.folder folders=model.folders isEditor=model.isEditor + gotoPage=(action 'gotoPage') onDeletePage=(action 'onPageDeleted')}} diff --git a/app/app/pods/document/meta/controller.js b/app/app/pods/document/meta/controller.js new file mode 100644 index 00000000..e2bc184f --- /dev/null +++ b/app/app/pods/document/meta/controller.js @@ -0,0 +1,24 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// https://documize.com + +import Ember from 'ember'; + +export default Ember.Controller.extend({ + documentService: Ember.inject.service('document'), + + actions: { + onSave(doc) { + this.get('documentService').save(doc).then(() => { + this.transitionToRoute('document.index'); + }); + } + } +}); diff --git a/app/app/pods/document/meta/route.js b/app/app/pods/document/meta/route.js new file mode 100644 index 00000000..887acd57 --- /dev/null +++ b/app/app/pods/document/meta/route.js @@ -0,0 +1,33 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// https://documize.com + +import Ember from 'ember'; +import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin'; + +export default Ember.Route.extend(AuthenticatedRouteMixin, { + userService: Ember.inject.service('user'), + + model() { + this.audit.record("viewed-document-meta"); + + let folderId = this.modelFor('document').folder.get('id'); + + return Ember.RSVP.hash({ + folders: this.modelFor('document').folders, + folder: this.modelFor('document').folder, + document: this.modelFor('document').document, + isEditor: this.modelFor('document').isEditor, + pages: this.modelFor('document').allPages, + tabs: this.modelFor('document').tabs, + users: this.get('userService').getFolderUsers(folderId) + }); + } +}); diff --git a/app/app/pods/document/meta/template.hbs b/app/app/pods/document/meta/template.hbs new file mode 100644 index 00000000..39185e1a --- /dev/null +++ b/app/app/pods/document/meta/template.hbs @@ -0,0 +1 @@ +{{document/document-meta document=model.document folders=model.folders folder=model.folder users=model.users isEditor=model.isEditor onSave=(action 'onSave')}} diff --git a/app/app/pods/document/route.js b/app/app/pods/document/route.js index 52d03ef4..e6958063 100644 --- a/app/app/pods/document/route.js +++ b/app/app/pods/document/route.js @@ -13,15 +13,59 @@ import Ember from 'ember'; import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin'; export default Ember.Route.extend(AuthenticatedRouteMixin, { + sectionService: Ember.inject.service('section'), documentService: Ember.inject.service('document'), + folderService: Ember.inject.service('folder'), - model: function (params) { - this.audit.record("viewed-document"); - return this.get('documentService').getDocument(params.document_id); + beforeModel(transition) { + this.set('pageId', is.not.undefined(transition.queryParams.page) ? transition.queryParams.page : ""); + this.set('folderId', this.paramsFor('document').folder_id); + this.set('documentId', this.paramsFor('document').document_id); + + return new Ember.RSVP.Promise((resolve) => { + this.get('folderService').getAll().then((folders) => { + this.set('folders', folders); + + this.get('folderService').getFolder(this.get('folderId')).then((folder) => { + this.set('folder', folder); + + this.get('folderService').setCurrentFolder(folder).then(() => { + this.set('isEditor', this.get('folderService').get('canEditCurrentFolder')); + + this.get('documentService').getPages(this.get('documentId')).then((pages) => { + this.set('allPages', pages); + this.set('pages', pages.filterBy('pageType', 'section')); + this.set('tabs', pages.filterBy('pageType', 'tab')); + resolve(); + }); + }); + }); + }); + }); + }, + + model() { + return Ember.RSVP.hash({ + folders: this.get('folders'), + folder: this.get('folder'), + document: this.get('documentService').getDocument(this.get('documentId')).then((document) => { + return document; + }), + page: this.get('pageId'), + isEditor: this.get('isEditor'), + allPages: this.get('allPages'), + pages: this.get('pages'), + tabs: this.get('tabs'), + sections: this.get('sectionService').getAll().then((sections) => { + return sections.filterBy('pageType', 'section'); + }), + }); }, actions: { error(error /*, transition*/ ) { + console.log(error); + console.log(error.stack); if (error) { this.transitionTo('/not-found'); return false; diff --git a/app/app/pods/document/section/controller.js b/app/app/pods/document/section/controller.js new file mode 100644 index 00000000..fac8ed73 --- /dev/null +++ b/app/app/pods/document/section/controller.js @@ -0,0 +1,46 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// https://documize.com + +import Ember from 'ember'; +import NotifierMixin from '../../../mixins/notifier'; + +export default Ember.Controller.extend(NotifierMixin, { + documentService: Ember.inject.service('document'), + queryParams: ['mode'], + mode: null, + + actions: { + onAction(page, meta) { + this.showNotification("Saving"); + + let model = { + page: page.toJSON({ includeId: true }), + meta: meta.toJSON({ includeId: true }) + }; + + this.get('documentService').updatePage(page.get('documentId'), page.get('id'), model).then((page) => { + this.audit.record("edited-page"); + let data = this.get('store').normalize('page', page); + this.get('store').push(data); + this.get('target.router').refresh(); + }); + }, + + onDelete(document, page) { + this.get('documentService').deletePage(document.get('id'), page.get('id')).then(() => { + this.audit.record("deleted-page"); + this.showNotification('Deleted'); + this.transitionToRoute('document'); + this.get('target.router').refresh(); + }); + } + } +}); diff --git a/app/app/pods/document/section/route.js b/app/app/pods/document/section/route.js new file mode 100644 index 00000000..79aab403 --- /dev/null +++ b/app/app/pods/document/section/route.js @@ -0,0 +1,43 @@ +// Copyright 2016 Documize Inc. . 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 . +// +// 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'), + pageId: '', + queryParams: { + mode: { + refreshModel: false + } + }, + + beforeModel(transition) { + this.set('mode', !_.isUndefined(transition.queryParams.mode) ? transition.queryParams.mode : ''); + }, + + model(params) { + return Ember.RSVP.hash({ + folders: this.modelFor('document').folders, + folder: this.modelFor('document').folder, + document: this.modelFor('document').document, + pages: this.modelFor('document').pages, + tabs: this.get('documentService').getPages(this.modelFor('document').document.get('id')).then((pages) => { + return pages.filterBy('pageType', 'tab'); + }), + page: this.get('documentService').getPage(this.modelFor('document').document.get('id'), params.page_id), + meta: this.get('documentService').getPageMeta(this.modelFor('document').document.get('id'), params.page_id) + }); + }, +}); diff --git a/app/app/pods/document/section/template.hbs b/app/app/pods/document/section/template.hbs new file mode 100644 index 00000000..5c381c71 --- /dev/null +++ b/app/app/pods/document/section/template.hbs @@ -0,0 +1 @@ +{{document/document-tab mode=mode model=model onAction=(action 'onAction') onDelete=(action 'onDelete')}} diff --git a/app/app/pods/document/template.hbs b/app/app/pods/document/template.hbs index c24cd689..765707c3 100644 --- a/app/app/pods/document/template.hbs +++ b/app/app/pods/document/template.hbs @@ -1 +1,13 @@ -{{outlet}} +{{layout/zone-navigation}} + +{{#layout/zone-sidebar}} + {{document/document-sidebar document=model.document folder=model.folder pages=model.pages page=model.page isEditor=model.isEditor sections=model.sections + onAddSection=(action 'onAddSection') changePageSequence=(action 'onPageSequenceChange') changePageLevel=(action 'onPageLevelChange') gotoPage=(action 'gotoPage')}} +{{/layout/zone-sidebar}} + +{{#layout/zone-content}} + {{document/document-toolbar document=model.document pages=model.pages tabs=model.tabs folder=model.folder isEditor=model.isEditor + onSaveTemplate=(action 'onSaveTemplate') onDocumentDelete=(action 'onDocumentDelete')}} + + {{outlet}} +{{/layout/zone-content}} diff --git a/app/app/pods/document/wizard/controller.js b/app/app/pods/document/wizard/controller.js index b3e7a973..db12c927 100644 --- a/app/app/pods/document/wizard/controller.js +++ b/app/app/pods/document/wizard/controller.js @@ -10,42 +10,44 @@ export default Ember.Controller.extend(NotifierMixin, { }, onAddSection(section) { - this.audit.record("added-section"); this.audit.record("added-section-" + section.get('contentType')); let page = { documentId: this.get('model.document.id'), - title: `${section.get('title')} Section`, + title: `${section.get('title')}`, level: 1, - sequence: 2048, + sequence: 0, body: "", - contentType: section.get('contentType') + contentType: section.get('contentType'), + pageType: section.get('pageType') }; - let data = this.get('store').normalize('page', page); - let pageData = this.get('store').push(data); - let meta = { documentId: this.get('model.document.id'), rawBody: "", - config: "" + config: "", + externaleSource: true }; - let pageMeta = this.get('store').normalize('page-meta', meta); - let pageMetaData = this.get('store').push(pageMeta); - let model = { - page: pageData, - meta: pageMetaData + page: page, + meta: meta }; this.get('documentService').addPage(this.get('model.document.id'), model).then((newPage) => { - this.transitionToRoute('document.edit', - this.get('model.folder.id'), - this.get('model.folder.slug'), - this.get('model.document.id'), - this.get('model.document.slug'), - newPage.id); + let data = this.get('store').normalize('page', newPage); + this.get('store').push(data); + + this.get('documentService').getPages(this.get('model.document.id')).then((pages) => { + this.set('model.pages', pages.filterBy('pageType', 'section')); + this.set('model.tabs', pages.filterBy('pageType', 'tab')); + + this.get('documentService').getPageMeta(this.get('model.document.id'), newPage.id).then(() => { + let options = {}; + options['mode'] = 'edit'; + this.transitionToRoute('document.section', newPage.id, { queryParams: options }); + }); + }); }); } } diff --git a/app/app/pods/document/wizard/route.js b/app/app/pods/document/wizard/route.js index 9ec0fe68..465717f6 100644 --- a/app/app/pods/document/wizard/route.js +++ b/app/app/pods/document/wizard/route.js @@ -2,17 +2,20 @@ 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'), + documentService: Ember.inject.service('document'), folderService: Ember.inject.service('folder'), sectionService: Ember.inject.service('section'), model() { - let self = this; - return Ember.RSVP.hash({ - folder: self.get('folderService').getFolder(self.paramsFor('document').folder_id), - document: self.get('documentService').getDocument(self.paramsFor('document').document_id), - sections: self.get('sectionService').getAll() + folders: this.modelFor('document').folders, + folder: this.modelFor('document').folder, + document: this.modelFor('document').document, + pages: this.modelFor('document').pages, + tabs: this.modelFor('document').tabs, + sections: this.get('sectionService').getAll().then(function (sections) { + return sections.filterBy('pageType', 'tab'); + }) }); } }); diff --git a/app/app/pods/document/wizard/template.hbs b/app/app/pods/document/wizard/template.hbs index 9692f3bf..a5bc3dfd 100644 --- a/app/app/pods/document/wizard/template.hbs +++ b/app/app/pods/document/wizard/template.hbs @@ -1 +1 @@ -{{document/page-wizard document=model.document folder=model.folder sections=model.sections onCancel=(action 'onCancel') onAction=(action 'onAddSection')}} +{{document/page-wizard display='tab' document=model.document folder=model.folder sections=model.sections onCancel=(action 'onCancel') onAction=(action 'onAddSection')}} diff --git a/app/app/pods/settings/route.js b/app/app/pods/settings/route.js index 68ae83e6..c5360d92 100644 --- a/app/app/pods/settings/route.js +++ b/app/app/pods/settings/route.js @@ -145,7 +145,6 @@ export default Ember.Route.extend(NotifierMixin, { var payload = { Message: message, Roles: data }; this.get('folderService').savePermissions(folder.get('id'), payload).then(() => { - this.showNotification("Saved"); }); var hasEveryone = _.find(data, function (permission) { diff --git a/app/app/router.js b/app/app/router.js index 60cefd37..e40cb45a 100644 --- a/app/app/router.js +++ b/app/app/router.js @@ -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,18 @@ 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('section', { + path: 'section/:page_id' + }); this.route('edit', { path: 'edit/:page_id' }); diff --git a/app/app/services/document.js b/app/app/services/document.js index f2fd4877..8ee4020e 100644 --- a/app/app/services/document.js +++ b/app/app/services/document.js @@ -124,12 +124,16 @@ export default Ember.Service.extend({ updatePage: function (documentId, pageId, payload, skipRevision) { var revision = skipRevision ? "?r=true" : "?r=false"; let url = `documents/${documentId}/pages/${pageId}${revision}`; + Ember.set(payload.meta, 'id', parseInt(payload.meta.id)); return this.get('ajax').request(url, { method: 'PUT', data: JSON.stringify(payload), contentType: 'json' + }).then((response) => { + let data = this.get('store').normalize('page', response); + return this.get('store').push(data); }); }, diff --git a/app/app/services/link.js b/app/app/services/link.js index e12496c7..c2815875 100644 --- a/app/app/services/link.js +++ b/app/app/services/link.js @@ -21,6 +21,13 @@ export default Ember.Service.extend({ appMeta: service(), store: service(), + // Returns links within specified document + getDocumentLinks(documentId) { + return this.get('ajax').request(`documents/${documentId}/links`, { + method: "GET" + }); + }, + // Returns candidate links using provided parameters getCandidates(folderId, documentId, pageId) { return this.get('ajax').request(`links/${folderId}/${documentId}/${pageId}`, { @@ -56,7 +63,7 @@ export default Ember.Service.extend({ let endpoint = this.get('appMeta').get('endpoint'); let orgId = this.get('appMeta').get('orgId'); - if (link.linkType === "section" || link.linkType === "document") { + if (link.linkType === "section" || link.linkType === "tab" || link.linkType === "document") { href = `/link/${link.linkType}/${link.id}`; result = `${link.title}`; } @@ -112,6 +119,14 @@ export default Ember.Service.extend({ return; } + // handle tab link + if (link.linkType === "tab") { + let options = {}; + options['mode'] = 'view'; + router.transitionTo('document.section', link.targetId, { queryParams: options }); + return; + } + // handle document link if (link.linkType === "document") { router.transitionTo('document', link.folderId, folderSlug, link.documentId, documentSlug); @@ -125,7 +140,3 @@ export default Ember.Service.extend({ } } }); - -/* - doc meta to show inbound and outbound links. -*/ diff --git a/app/app/styles/app.scss b/app/app/styles/app.scss index c3eb7d18..00fda878 100644 --- a/app/app/styles/app.scss +++ b/app/app/styles/app.scss @@ -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"; diff --git a/app/app/styles/base.scss b/app/app/styles/base.scss index 49668131..ea1fbd85 100644 --- a/app/app/styles/base.scss +++ b/app/app/styles/base.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%; diff --git a/app/app/styles/color.scss b/app/app/styles/color.scss index 37cf0a98..bef64b5c 100644 --- a/app/app/styles/color.scss +++ b/app/app/styles/color.scss @@ -20,7 +20,7 @@ $color-blue: #2667af; $color-gray: #8b9096; $color-goldy: #cc9933; -$color-header: #f3f5f8; +$color-sidebar: #f3f5f8; $color-link: #0092d3; $color-border: #f3f5f8; @@ -40,36 +40,47 @@ $color-chip-text: #1b88e3; .color-white { color: $color-white !important; } + .color-off-white { color: $color-off-white !important; } + .color-black { color: $color-black !important; } + .color-off-black { color: $color-off-black !important; } + .color-primary { color: $color-primary !important; } + .color-link { color: $color-link !important; } + .color-blue { color: $color-blue !important; } + .color-red { color: $color-red !important; } + .color-green { color: $color-green !important; } + .color-gray { color: $color-gray !important; } + .background-color-white { background-color: $color-white !important; } + .background-color-primary { background-color: $color-primary !important; } diff --git a/app/app/styles/font.scss b/app/app/styles/font.scss index 7c6cce5b..79ba89ac 100644 --- a/app/app/styles/font.scss +++ b/app/app/styles/font.scss @@ -1,61 +1,43 @@ -.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-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-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-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-regular: 'open_sansregular'; +$font-semibold: 'open_sanssemibold'; +$font-light: 'open_sanslight'; @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-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-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-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; -} - -$base-font: 'open_sansregular'; - -@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'); } diff --git a/app/app/styles/functions.scss b/app/app/styles/functions.scss index 1f06bdc3..809a1400 100644 --- a/app/app/styles/functions.scss +++ b/app/app/styles/functions.scss @@ -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; diff --git a/app/app/styles/section/github.scss b/app/app/styles/section/github.scss index f3333a40..669ba50f 100644 --- a/app/app/styles/section/github.scss +++ b/app/app/styles/section/github.scss @@ -7,7 +7,7 @@ width: 100%; padding: 10px; white-space: nowrap; - overflow: auto + overflow: auto; } .github-repo-title { @@ -21,7 +21,6 @@ } .github-list-title { - font-weight: bold; color: #4c4c4c; font-size: 14px; margin: 5px; @@ -34,17 +33,16 @@ .github-issue-label { font-size: 11px; color: white; - padding: 0px 4px; + padding: 0 4px; margin-right: 5px; border-radius: 2px; box-shadow: inset 0 -1px 0 rgba(0,0,0,0.12); display: inline-block; line-height: 22px; - } + } } .section-github-render { - a:hover { text-decoration: underline; } @@ -62,7 +60,7 @@ .heading { font-size: 1.6rem; - margin: 30px 0 0 0; + margin: 30px 0 0; } .github-table thead tr th { @@ -73,36 +71,37 @@ text-align: left; span { - color:#838d94; + color: #838d94; } } .github-table tbody tr td { border: none!important; - padding: 5px 20px 5px 20px !important; + padding: 5px 20px !important; } .github-table .right-column { text-align: right; - color:#838d94; + color: #838d94; } span.data { - color:#838d94; + color: #838d94; } .issue-label { - color:white; - font-size: 11px; - padding: 4px 6px; - border-radius: 4px; - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.12); - margin-left: 10px; + color: white; + font-size: 11px; + padding: 4px 6px; + border-radius: 4px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.12); + margin-left: 10px; } .progress-bar { - display: inline-block; border-radius: 3px; + display: inline-block; + border-radius: 3px; width: 40%; background-color: #f1f1f1; height: 8px; @@ -117,8 +116,8 @@ span.issue-state { float: left; - margin-right: 10px; - margin-top: 3px; + margin-right: 10px; + margin-top: 3px; } img.github-avatar { diff --git a/app/app/styles/view/common.scss b/app/app/styles/view/common.scss index bc352e5b..c87e3c84 100644 --- a/app/app/styles/view/common.scss +++ b/app/app/styles/view/common.scss @@ -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'; diff --git a/app/app/styles/view/document/activity.scss b/app/app/styles/view/document/activity.scss new file mode 100644 index 00000000..a5f3c595 --- /dev/null +++ b/app/app/styles/view/document/activity.scss @@ -0,0 +1,139 @@ +.document-activity { + > .metrics { + list-style-type: none; + margin: 0 0 30px; + padding: 0; + width: 100%; + text-align: center; + + > .metric { + padding: 0 30px; + display: inline-block; + text-align: center; + + .label { + padding: 0 0 10px; + font-family: $font-regular; + font-size: 0.9rem; + color: $color-gray; + } + + .number { + font-family: $font-light; + font-size: 2rem; + color: $color-off-black; + } + } + } + + > .items { + list-style-type: none; + margin: 0; + padding: 0; + white-space: nowrap; + + > .item { + padding: 20px 0; + width: 100%; + border-bottom: 1px solid $color-border; + + &:last-of-type { + border-bottom: none !important; + } + + > .avatar-box { + display: inline-block; + margin: 3px 10px 0 0; + width: 5%; + } + + > .name { + display: inline-block; + font-size: 1rem; + font-family: $font-light; + color: $color-off-black; + width: 25%; + } + + > .detail { + display: inline-block; + font-size: 1rem; + font-family: $font-regular; + color: $color-off-black; + width: 45%; + + .viewed { + color: $color-goldy; + } + + .added { + color: $color-green; + } + + .changed { + color: $color-blue; + } + + .deleted { + color: $color-red; + } + } + + > .date { + display: inline-block; + font-family: $font-light; + font-size: 1rem; + float: right; + width: 15%; + padding-top: 10px; + } + } + } +} + +.meta-editors { + position: relative; + + > .items { + list-style-type: none; + margin: 0; + padding: 0; + white-space: nowrap; + + > .item { + margin: 15px 0; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + width: 90%; + + .avatar-box { + display: inline-block; + margin: 3px 10px 0 0; + vertical-align: top; + } + + .detail { + display: inline-block; + + .name { + font-size: 1rem; + color: $color-off-black; + } + + .changed { + font-size: 0.9rem; + } + + .deleted { + font-size: 0.9rem; + color: $color-red; + } + + .date { + font-size: 0.8rem; + } + } + } + } +} diff --git a/app/app/styles/view/document/all.scss b/app/app/styles/view/document/all.scss new file mode 100644 index 00000000..3274d65d --- /dev/null +++ b/app/app/styles/view/document/all.scss @@ -0,0 +1,9 @@ +@import "activity.scss"; +@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"; diff --git a/app/app/styles/view/document/content.scss b/app/app/styles/view/document/content.scss index f76e0354..1576f2e0 100644 --- a/app/app/styles/view/document/content.scss +++ b/app/app/styles/view/document/content.scss @@ -15,73 +15,13 @@ 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; + color: $color-goldy; font-weight: bold; font-size: 1.5em; margin-bottom: 30px; padding-bottom: 5px; - @include border-bottom(1px); + border-bottom: 1px dotted $color-goldy; } > .pages { diff --git a/app/app/styles/view/document/editor.scss b/app/app/styles/view/document/editor.scss index 4ebded01..601cc3e5 100644 --- a/app/app/styles/view/document/editor.scss +++ b/app/app/styles/view/document/editor.scss @@ -1,9 +1,7 @@ .document-editor { > .toolbar { - @extend .z-depth-tiny; - background-color: $color-white; width: 100%; - padding: 20px 40px; + padding: 0; > .title { width: 50%; @@ -12,7 +10,7 @@ margin: 0; > input { - margin: 0 0 5px 0; + margin: 0 0 5px; } } } @@ -23,7 +21,7 @@ } > .canvas { - padding: 40px 40px; + padding: 40px 0; } .cancel-edits-dialog { diff --git a/app/app/styles/view/document/files.scss b/app/app/styles/view/document/files.scss new file mode 100644 index 00000000..1469e610 --- /dev/null +++ b/app/app/styles/view/document/files.scss @@ -0,0 +1,82 @@ +.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-preview, + .dz-processing { + 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; + + &:last-of-type { + border-bottom: none !important; + } + + > .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; +} diff --git a/app/app/styles/view/document/section.scss b/app/app/styles/view/document/section.scss new file mode 100644 index 00000000..e17965e1 --- /dev/null +++ b/app/app/styles/view/document/section.scss @@ -0,0 +1,9 @@ +.document-section { + > .toolbar { + margin-bottom: 10px; + + > .buttons { + margin: 10px 0; + } + } +} diff --git a/app/app/styles/view/document/sidebar.scss b/app/app/styles/view/document/sidebar.scss index 4edea7da..a34c25b6 100644 --- a/app/app/styles/view/document/sidebar.scss +++ b/app/app/styles/view/document/sidebar.scss @@ -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; @@ -164,86 +113,3 @@ } } } - -.meta-viewers { - > .items { - list-style-type: none; - margin: 0; - padding: 0; - white-space: nowrap; - - > .item { - margin: 15px 0; - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; - width: 90%; - - > .avatar-box { - display: inline-block; - margin: 3px 10px 0 0; - vertical-align: top; - } - - > .detail { - display: inline-block; - - > .name { - font-size: 1rem; - color: $color-off-black; - } - - > .date { - font-size: 0.8rem; - } - } - } - } -} - -.meta-editors { - position: relative; - - > .items { - list-style-type: none; - margin: 0; - padding: 0; - white-space: nowrap; - - > .item { - margin: 15px 0; - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; - width: 90%; - - .avatar-box { - display: inline-block; - margin: 3px 10px 0 0; - vertical-align: top; - } - - .detail { - display: inline-block; - - .name { - font-size: 1rem; - color: $color-off-black; - } - - .changed { - font-size: 0.9rem; - } - - .deleted { - font-size: 0.9rem; - color: $color-red; - } - - .date { - font-size: 0.8rem; - } - } - } - } -} diff --git a/app/app/styles/view/document/toolbar.scss b/app/app/styles/view/document/toolbar.scss new file mode 100644 index 00000000..439519f1 --- /dev/null +++ b/app/app/styles/view/document/toolbar.scss @@ -0,0 +1,88 @@ +.document-toolbar { + position: relative; + margin: -30px 0 40px; + height: 60px; + padding: 5px 30px 0; + background-color: $color-sidebar; + @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; + @include ease-in(); + + &:hover { + color: $color-link; + } + } + + > .active { + color: $color-link; + + > .add-tab { + > i { + color: $color-link; + } + } + } + + .add-tab { + display: inline-block; + vertical-align: text-top; + @include ease-in(); + + > i { + font-size: 1.5rem; + color: $color-gray; + + &:hover { + 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; + @include ease-in(); + + &:hover { + color: $color-link; + } + } + } +} diff --git a/app/app/styles/view/document/wizard.scss b/app/app/styles/view/document/wizard.scss index 531bb1c7..d49aae6a 100644 --- a/app/app/styles/view/document/wizard.scss +++ b/app/app/styles/view/document/wizard.scss @@ -1,5 +1,5 @@ .section-wizard { - margin: 20px 0 30px 0; + margin: 20px 0 30px; > .canvas { padding: 0; @@ -27,7 +27,7 @@ color: $color-primary; } } - } + } .icon { text-align: center; @@ -65,3 +65,72 @@ } } } + +.tab-wizard { + margin: 20px 0 30px; + + > .canvas { + padding: 0; + + > .list { + margin: 0; + padding: 0; + + > .item { + list-style: none; + cursor: pointer; + padding: 20px; + @include ease-in(); + + &:hover { + @include ease-in(); + + > .details { + > .title { + color: $color-primary; + } + + > .desc { + color: $color-primary; + } + } + } + + .icon { + text-align: center; + display: inline-block; + width: 50px; + margin-right: 10px; + float: left; + + > .img { + float: left; + text-align: center; + display: inline-block; + height: 40px; + width: 40px; + } + } + + > .details { + vertical-align: top; + display: inline-block; + float: left; + + > .title { + font-size: 1rem; + font-weight: bold; + color: $color-off-black; + letter-spacing: 0.5px; + } + + > .desc { + color: $color-gray; + font-size: 0.9rem; + margin-top: 5px; + } + } + } + } + } +} diff --git a/app/app/styles/view/document/wysiwyg.scss b/app/app/styles/view/document/wysiwyg.scss index a50ad015..e34b58d3 100644 --- a/app/app/styles/view/document/wysiwyg.scss +++ b/app/app/styles/view/document/wysiwyg.scss @@ -39,48 +39,48 @@ b { - font-family: "open_sanssemibold"; + font-family: $font-semibold; } - h1.doc-name { + h1 { font-size: 2em; - font-family: open_sansregular; + font-family: $font-semibold; } - h1 - { - font-size: 1.6em; - font-family: open_sanslight; - color:$color-off-black; - margin: 30px 0 20px 0; - } + // h1 + // { + // font-size: 1.6em; + // font-family: open_sanslight; + // color:$color-off-black; + // margin: 0 0 20px 0; + // } h2 { - font-size: 1.5em; + font-size: 1.7em; margin: 30px 0 20px 0; - font-family: open_sanslight; + font-family: $font-regular; } h3 { - font-size: 1.4rem; + font-size: 1.5rem; margin: 30px 0 20px 0; - font-family: open_sanslight; + font-family: $font-regular; } h4 { font-size: 1.3rem; margin: 30px 0 20px 0; - font-family: open_sanslight; + font-family: $font-regular; } h5, h6, h7, h8, h9 { - font-size: 1.2rem; + font-size: 1.3rem; margin: 30px 0 20px 0; - font-family: open_sanslight; + font-family: $font-regular; } h2, h3, h4, h5, h6, h7, h8, h9 @@ -88,7 +88,7 @@ .page-title { color:$color-off-black; - font-family: open_sansregular; + font-family: $font-regular; } } diff --git a/app/app/styles/view/layout.scss b/app/app/styles/view/layout.scss index 16cb688f..4b3cbb45 100644 --- a/app/app/styles/view/layout.scss +++ b/app/app/styles/view/layout.scss @@ -9,8 +9,8 @@ z-index: 999; overflow-x: hidden; - > .top-zone, - > .bottom-zone { + > .bottom-zone, + > .top-zone { position: absolute; padding: 0; width: 100%; @@ -101,7 +101,7 @@ } .zone-sidebar { - background-color: $color-header; + background-color: $color-sidebar; height: 100%; min-height: 100%; padding: 30px 40px 0; @@ -116,8 +116,8 @@ font-weight: bold; margin-bottom: 10px; - > a > .material-icons, - > .material-icons { + > .material-icons, + > a > .material-icons { font-size: 1rem; vertical-align: middle; } @@ -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; } diff --git a/app/app/styles/view/page-auth.scss b/app/app/styles/view/page-auth.scss index 0d6d9cfa..d34294ce 100644 --- a/app/app/styles/view/page-auth.scss +++ b/app/app/styles/view/page-auth.scss @@ -1,6 +1,6 @@ .auth-box { - height: 450px; - width: 450px; + height: 500px; + width: 500px; background-color: $color-white; border: 1px solid $color-border; display: inline-block; diff --git a/app/app/styles/view/page-search.scss b/app/app/styles/view/page-search.scss index ec4011ca..d45420d7 100644 --- a/app/app/styles/view/page-search.scss +++ b/app/app/styles/view/page-search.scss @@ -1,55 +1,55 @@ .page-search { .input-control { > input { - background-color: $color-header; + background-color: $color-sidebar; } } .search-results { - .heading { - font-size: 1.2rem; - color: $color-off-black; - } + .heading { + font-size: 1.2rem; + color: $color-off-black; + } - > .list { - margin-top: 20px; + > .list { + margin-top: 20px; list-style: none; - > .item { - cursor: pointer; + > .item { + cursor: pointer; margin: 0 30px 30px 0; padding-bottom: 40px; - border-bottom: 1px solid #e1e1e1; + border-bottom: 1px solid #e1e1e1; - > .link { - text-decoration: none; - color: $color-off-black; + > .link { + text-decoration: none; + color: $color-off-black; &:hover { color: $color-link; } - > .title { - display: inline-block; + > .title { + display: inline-block; font-size: 1.2rem; - } + } > .folder { - display: inline-block; - font-size: 0.8rem; - color: $color-gray; + display: inline-block; + font-size: 0.8rem; + color: $color-gray; margin-left: 15px; - } + } - > .excerpt { + > .excerpt { margin-top: 1rem; - font-size: 0.9rem; - } + font-size: 0.9rem; + } > .chips { margin-top: 1rem; } - } + } > .references { margin-top: 1rem; @@ -69,7 +69,7 @@ } } } - } - } - } + } + } + } } diff --git a/app/app/styles/widget/widget-input.scss b/app/app/styles/widget/widget-input.scss index 120b8b2c..903473b1 100644 --- a/app/app/styles/widget/widget-input.scss +++ b/app/app/styles/widget/widget-input.scss @@ -1,77 +1,81 @@ -* { box-sizing: border-box; } +* { + box-sizing: border-box; +} .input-control { - position: relative; - margin-bottom: 25px; + position: relative; + margin-bottom: 50px; - > 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,78 +112,80 @@ } > 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; - padding: 30px 50px; +.form-bordered { + padding: 30px 40px; + border: 10px solid $color-border; + @include border-radius(15px); +} - > .heading, > form .heading { - >.title { - font-size: 1.1rem; - font-weight: bold; - color: $color-off-black; - } +.form-header { + > .title { + font-size: 1.4rem; + font-weight: normal; + font-family: $font-semibold; + pointer-events: none; + font-weight: bold; + color: $color-off-black; + } - > .tip { - color: $color-input; - font-size: 0.9em; - margin: 5px 0 30px 0; - padding: 0; - text-align: left; - } + > .tip { + color: $color-input; + font-size: 1.2rem; + margin: 5px 0 30px; + padding: 0; + font-family: $font-light; + text-align: left; } } @@ -187,11 +193,6 @@ margin-top: 30px; } -.form-borderless { - padding: 0 !important; - border: none !important; -} - .widget-checkbox { color: $color-link; cursor: pointer; diff --git a/app/app/styles/widget/widget-sidebar-menu.scss b/app/app/styles/widget/widget-sidebar-menu.scss index 2dabf6df..03fd9496 100644 --- a/app/app/styles/widget/widget-sidebar-menu.scss +++ b/app/app/styles/widget/widget-sidebar-menu.scss @@ -10,8 +10,9 @@ font-size: 1.3rem; list-style: none; cursor: pointer; - @extend .no-select; color: $color-off-black; + @extend .no-select; + @include ease-in(); &:hover { color: $color-link; diff --git a/app/app/templates/components/document/document-activity.hbs b/app/app/templates/components/document/document-activity.hbs new file mode 100644 index 00000000..15aae77e --- /dev/null +++ b/app/app/templates/components/document/document-activity.hbs @@ -0,0 +1,41 @@ +
+
    +
  • +
    created
    +
    {{time-ago document.created}}
    +
  • +
  • +
    viewers
    +
    {{activity.viewers.length}}
    +
  • +
  • +
    actions
    +
    {{activity.editors.length}}
    +
  • +
+
    + {{#each sortedItems as |e|}} +
  • +
    +
    {{user-initials e.item.firstname e.item.lastname}}
    +
    +
    {{e.item.firstname}} {{e.item.lastname}}
    +
    + {{#if e.item.deleted}} +
    {{e.item.changeLabel}}
    + {{/if}} + {{#if e.item.changed}} +
    {{e.item.changeLabel}}
    + {{/if}} + {{#if e.item.added}} +
    {{e.item.changeLabel}}
    + {{/if}} + {{#if e.item.viewed}} +
    {{e.item.changeLabel}}
    + {{/if}} +
    +
    {{time-ago e.date}}
    +
  • + {{/each}} +
+
diff --git a/app/app/templates/components/document/document-files.hbs b/app/app/templates/components/document/document-files.hbs new file mode 100644 index 00000000..2a274815 --- /dev/null +++ b/app/app/templates/components/document/document-files.hbs @@ -0,0 +1,44 @@ +
+
    + {{#each files key="id" as |a index|}} +
  • + + + {{ a.filename }} + + {{#if isEditor}} +
    + delete +
    + {{/if}} +
  • + {{/each}} +
+ + {{#if emptyState}} +
+
+ There are no files +
+
+ {{/if}} + +
+ Drag-drop files or click to select files +
+
+ + diff --git a/app/app/templates/components/document/document-meta.hbs b/app/app/templates/components/document/document-meta.hbs new file mode 100644 index 00000000..8dce0284 --- /dev/null +++ b/app/app/templates/components/document/document-meta.hbs @@ -0,0 +1,27 @@ +
+
+
Meta Information
+
Name, owner, excerpt
+
+
+ +
Set the document owner
+ {{ui-select id="document-owner" + content=users + action=(action (mut owner)) + optionValuePath="id" + optionLabelPath="fullname" + selection=owner}} +
+
+ +
Short title for this document
+ {{focus-input type='text' id="document-name" value=document.name}} +
+
+ +
Provide short summary of the document (max. 250)
+ {{textarea value=document.excerpt rows="5" id="meta-excerpt"}} +
+
Save
+
diff --git a/app/app/templates/components/document/document-sidebar-close-action.hbs b/app/app/templates/components/document/document-sidebar-close-action.hbs deleted file mode 100644 index b27ae2a4..00000000 --- a/app/app/templates/components/document/document-sidebar-close-action.hbs +++ /dev/null @@ -1,6 +0,0 @@ -
-
- clear -
-
-
diff --git a/app/app/templates/components/document/document-sidebar-edits.hbs b/app/app/templates/components/document/document-sidebar-edits.hbs deleted file mode 100644 index 115f53d1..00000000 --- a/app/app/templates/components/document/document-sidebar-edits.hbs +++ /dev/null @@ -1,20 +0,0 @@ -
-
    - {{#each meta.editors as |edit|}} -
  • -
    -
    {{user-initials edit.firstname edit.lastname}}
    -
    -
    -
    {{edit.firstname}} {{edit.lastname}}
    - {{#if edit.deleted}} -
    {{edit.changeLabel}}
    - {{else}} - {{edit.changeLabel}} - {{/if}} -
    {{time-ago edit.created}}
    -
    -
  • - {{/each}} -
-
diff --git a/app/app/templates/components/document/document-sidebar-toc.hbs b/app/app/templates/components/document/document-sidebar-toc.hbs index d09d8bce..97aa36cd 100644 --- a/app/app/templates/components/document/document-sidebar-toc.hbs +++ b/app/app/templates/components/document/document-sidebar-toc.hbs @@ -1,22 +1,24 @@
{{#if this.session.authenticated}} -