diff --git a/gui/app/components/document/document-toc.js b/gui/app/components/document/document-toc.js index 28debf23..ad7b9425 100644 --- a/gui/app/components/document/document-toc.js +++ b/gui/app/components/document/document-toc.js @@ -35,7 +35,6 @@ export default Component.extend({ didReceiveAttrs() { this._super(...arguments); - this.setState(this.get('currentPageId')); }, @@ -43,10 +42,8 @@ export default Component.extend({ this._super(...arguments); this.setSize(); - this.eventBus.subscribe('documentPageAdded', this, 'onDocumentPageAdded'); this.eventBus.subscribe('resized', this, 'onResize'); - this.attachResizer(); }, diff --git a/gui/app/components/folder/start-document.js b/gui/app/components/folder/start-document.js index d3a6969c..45290ad5 100644 --- a/gui/app/components/folder/start-document.js +++ b/gui/app/components/folder/start-document.js @@ -10,7 +10,6 @@ // https://documize.com import { empty } from '@ember/object/computed'; - import { schedule } from '@ember/runloop'; import Component from '@ember/component'; import { inject as service } from '@ember/service'; diff --git a/gui/app/components/toolbar/for-document.js b/gui/app/components/toolbar/for-document.js index 5eb981df..c170acdf 100644 --- a/gui/app/components/toolbar/for-document.js +++ b/gui/app/components/toolbar/for-document.js @@ -61,6 +61,8 @@ export default Component.extend(ModalMixin, TooltipMixin, AuthMixin, { actions: { onDocumentDelete() { + this.modalClose('#document-delete-modal'); + this.attrs.onDocumentDelete(); }, diff --git a/gui/app/components/toolbar/for-space.js b/gui/app/components/toolbar/for-space.js index 96b9eb5c..0e5b07d0 100644 --- a/gui/app/components/toolbar/for-space.js +++ b/gui/app/components/toolbar/for-space.js @@ -11,14 +11,16 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; +import { schedule } from '@ember/runloop'; import { inject as service } from '@ember/service'; -import NotifierMixin from '../../mixins/notifier'; import TooltipMixin from '../../mixins/tooltip'; import ModalMixin from '../../mixins/modal'; import AuthMixin from '../../mixins/auth'; -export default Component.extend(NotifierMixin, ModalMixin, TooltipMixin, AuthMixin, { +export default Component.extend(ModalMixin, TooltipMixin, AuthMixin, { spaceService: service('folder'), + localStorage: service(), + templateService: service('template'), session: service(), appMeta: service(), pinned: service(), @@ -38,12 +40,24 @@ export default Component.extend(NotifierMixin, ModalMixin, TooltipMixin, AuthMix deleteSpaceName: '', inviteEmail: '', inviteMessage: '', + hasTemplates: computed('templates', function() { + return this.get('templates.length') > 0; + }), + emptyDocName: '', + emptyDocNameError: false, + templateDocName: '', + templateDocNameError: false, + selectedTemplate: '', + importedDocuments: [], + importStatus: [], + dropzone: null, didReceiveAttrs() { this._super(...arguments); let folder = this.get('space'); let targets = _.reject(this.get('spaces'), {id: folder.get('id')}); + this.set('movedFolderOptions', targets); this.get('pinned').isSpacePinned(folder.get('id')).then((pinId) => { this.set('pinState.pinId', pinId); @@ -52,8 +66,6 @@ export default Component.extend(NotifierMixin, ModalMixin, TooltipMixin, AuthMix this.renderTooltips(); }); - this.set('movedFolderOptions', targets); - if (this.get('inviteMessage').length === 0) { this.set('inviteMessage', this.getDefaultInvitationMessage()); } @@ -61,7 +73,6 @@ export default Component.extend(NotifierMixin, ModalMixin, TooltipMixin, AuthMix didInsertElement() { this._super(...arguments); - this.modalInputFocus('#space-delete-modal', '#delete-space-name'); this.modalInputFocus('#space-invite-modal', '#space-invite-email'); }, @@ -69,12 +80,66 @@ export default Component.extend(NotifierMixin, ModalMixin, TooltipMixin, AuthMix willDestroyElement() { this._super(...arguments); this.removeTooltips(); + + if (is.not.null(this.get('dropzone'))) { + this.get('dropzone').destroy(); + this.set('dropzone', null); + } }, getDefaultInvitationMessage() { return "Hey there, I am sharing the " + this.get('space.name') + " space (in " + this.get("appMeta.title") + ") with you so we can both collaborate on documents."; }, + setupImport() { + // already done init? + if (is.not.null(this.get('dropzone'))) { + this.get('dropzone').destroy(); + this.set('dropzone', null); + } + + let self = this; + let folderId = this.get('space.id'); + let url = this.get('appMeta.endpoint'); + let importUrl = `${url}/import/folder/${folderId}`; + + let dzone = new Dropzone("#import-document-button", { + headers: { 'Authorization': 'Bearer ' + self.get('session.session.content.authenticated.token') }, + url: importUrl, + method: "post", + paramName: 'attachment', + acceptedFiles: ".doc,.docx,.md,.markdown,.htm,.html", + clickable: true, + maxFilesize: 10, + parallelUploads: 3, + uploadMultiple: false, + addRemoveLinks: false, + autoProcessQueue: true, + + init: function () { + this.on("success", function (document) { + self.send('onDocumentImported', document.name, document); + }); + + this.on("error", function (x) { + console.log("Conversion failed for", x.name, x); // eslint-disable-line no-console + }); + + // this.on("queuecomplete", function () {}); + + this.on("addedfile", function (file) { + self.send('onDocumentImporting', file.name); + }); + } + }); + + dzone.on("complete", function (file) { + dzone.removeFile(file); + }); + + this.set('dropzone', dzone); + }, + actions: { onUnpin() { this.get('pinned').unpinItem(this.get('pinState.pinId')).then(() => { @@ -166,16 +231,107 @@ export default Component.extend(NotifierMixin, ModalMixin, TooltipMixin, AuthMix this.modalClose('#space-delete-modal'); }, - onAddSpace(e) { + onShowEmptyDocModal() { + this.modalOpen("#empty-doc-modal", {"show": true}, '#empty-doc-name'); + }, + + onAddEmptyDoc(e) { e.preventDefault(); + let docName = this.get('emptyDocName'); + + if (is.empty(docName)) { + this.set('emptyDocNameError', true); + $('#empty-doc-name').focus(); + return; + } else { + this.set('emptyDocNameError', false); + this.set('emptyDocName', ''); + } + + this.modalClose("#empty-doc-modal"); + + this.get('templateService').importSavedTemplate(this.get('space.id'), '0', docName).then((document) => { + this.get('router').transitionTo('document', this.get('space.id'), this.get('space.slug'), document.get('id'), document.get('slug')); + }); }, - onImport() { - this.attrs.onRefresh(); + onShowTemplateDocModal() { + let t = this.get('templates'); + if (t.length > 0) { + t[0].set('selected', true); + this.modalOpen("#template-doc-modal", {"show": true}, '#template-doc-name'); + } }, - onHideStartDocument() { - // this.set('showStartDocument', false); + onSelectTemplate(i) { + let t = this.get('templates'); + t.forEach((t) => { + t.set('selected', false); + }) + i.set('selected', true); + this.set('selectedTemplate', i.id); + }, + + onAddTemplateDoc(e) { + e.preventDefault(); + let docName = this.get('templateDocName'); + + if (is.empty(docName)) { + this.set('templateDocNameError', true); + $('#template-doc-name').focus(); + return; + } else { + this.set('templateDocNameError', false); + this.set('templateDocName', ''); + } + + let id = this.get('selectedTemplate'); + if (is.empty(id)) { + return; + } + + this.modalClose("#template-doc-modal"); + + this.get('templateService').importSavedTemplate(this.get('space.id'), id, docName).then((document) => { + this.get('router').transitionTo('document', this.get('space.id'), this.get('space.slug'), document.get('id'), document.get('slug')); + }); + }, + + onShowImportDocModal() { + this.modalOpen("#import-doc-modal", {"show": true}); + + this.setupImport(); + this.modalOnShown('#import-doc-modal', function() { + schedule('afterRender', ()=> { + }); + }); + }, + + onDocumentImporting(filename) { + let status = this.get('importStatus'); + let documents = this.get('importedDocuments'); + + status.pushObject(`Converting ${filename}...`); + documents.push(filename); + + this.set('importStatus', status); + this.set('importedDocuments', documents); + }, + + onDocumentImported(filename /*, document*/ ) { + let status = this.get('importStatus'); + let documents = this.get('importedDocuments'); + + status.pushObject(`Successfully converted ${filename}`); + documents.pop(filename); + + this.set('importStatus', status); + this.set('importedDocuments', documents); + + if (documents.length === 0) { + this.modalClose("#import-doc-modal"); + this.attrs.onRefresh(); + } } } }); diff --git a/gui/app/mixins/modal.js b/gui/app/mixins/modal.js index 3fbef5ba..315375fc 100644 --- a/gui/app/mixins/modal.js +++ b/gui/app/mixins/modal.js @@ -17,16 +17,18 @@ import { schedule } from '@ember/runloop'; // element: #new-template-name // See https://getbootstrap.com/docs/4.0/components/modal/#via-javascript export default Mixin.create({ - modalOpen(modalId, options) { + modalOpen(modalId, options, focusId) { $(modalId).modal('dispose'); $(modalId).modal(options); + + if (is.not.undefined(focusId)) { + $(focusId).trigger('focus'); + } }, modalInputFocus(modalId, inputId) { - $(modalId).on('show.bs.modal', function(event) { // eslint-disable-line no-unused-vars - schedule('afterRender', () => { - $(inputId).focus(); - }); + $(modalId).on('shown.bs.modal', function(event) { // eslint-disable-line no-unused-vars + $(inputId).trigger('focus'); }); }, diff --git a/gui/app/pods/customize/template.hbs b/gui/app/pods/customize/template.hbs index edf0bbf6..c9143e6e 100644 --- a/gui/app/pods/customize/template.hbs +++ b/gui/app/pods/customize/template.hbs @@ -1,14 +1,14 @@ {{toolbar/nav-bar}} -
Sub-divide spaces into categories which can contain documents with restricted access.
- +Sub-divide spaces into categories which can contain documents with restricted access.
+ +diff --git a/gui/app/templates/components/folder/space-heading.hbs b/gui/app/templates/components/folder/space-heading.hbs index f084d7a8..9e9c3101 100644 --- a/gui/app/templates/components/folder/space-heading.hbs +++ b/gui/app/templates/components/folder/space-heading.hbs @@ -1,28 +1,30 @@ - |
---|