diff --git a/app/app/components/folder/documents-list.js b/app/app/components/folder/documents-list.js index ba68de9b..af0c5518 100644 --- a/app/app/components/folder/documents-list.js +++ b/app/app/components/folder/documents-list.js @@ -13,6 +13,7 @@ import Ember from 'ember'; export default Ember.Component.extend({ selectedDocuments: [], + moveTarget: null, emptyState: Ember.computed('documents', function() { return this.get('documents.length') === 0; @@ -21,6 +22,8 @@ export default Ember.Component.extend({ didReceiveAttrs() { this.set('selectedDocuments', []); this.audit.record('viewed-space'); + + this.set('deleteTargets', this.get('folders').rejectBy('id', this.get('folder.id'))); }, actions: { @@ -41,6 +44,10 @@ export default Ember.Component.extend({ this.set('selectedDocuments', list); this.get('onDocumentsChecked')(list); - } + }, + + onDelete() { + this.get("onDeleteSpace")(); + } } }); diff --git a/app/app/components/folder/folder-heading.js b/app/app/components/folder/folder-heading.js new file mode 100644 index 00000000..0d55d398 --- /dev/null +++ b/app/app/components/folder/folder-heading.js @@ -0,0 +1,60 @@ +// 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'; + +const { + computed, +} = Ember; + +export default Ember.Component.extend(NotifierMixin, TooltipMixin, { + folderService: Ember.inject.service('folder'), + folderName: '', + hasNameError: computed.empty('folderName'), + editMode: false, + isEditor: false, + + keyUp(e) { + if (e.keyCode === 27) { // escape key + this.send('onCancel'); + } + }, + + actions: { + toggleEdit() { + this.set('folderName', this.get('folder.name')); + this.set('editMode', true); + + Ember.run.schedule('afterRender', () => { + $('#folder-name').select(); + }); + }, + + onSave() { + if (this.get('hasNameError')) { + return; + } + + this.set('folder.name', this.get('folderName')); + + this.get('folderService').save(this.get('folder')); + this.showNotification('Saved'); + + this.set('editMode', false); + }, + + onCancel() { + this.set('editMode', false); + } + } +}); diff --git a/app/app/components/folder/folder-settings.js b/app/app/components/folder/folder-settings.js index cf7e5868..7f4e9ef1 100644 --- a/app/app/components/folder/folder-settings.js +++ b/app/app/components/folder/folder-settings.js @@ -33,83 +33,11 @@ export default Ember.Component.extend(AuthMixin, { }, willRender() { - if (this.inviteMessage.length === 0) { - this.set('inviteMessage', this.getDefaultInvitationMessage()); - } - if (this.roleMessage.length === 0) { this.set('roleMessage', this.getDefaultInvitationMessage()); } }, actions: { - rename() { - if (is.empty(this.folder.get('name'))) { - $("#folderName").addClass("error").focus(); - return; - } - - this.sendAction("onRename", this.folder); - }, - - remove() { - if (is.null(this.get('moveTarget'))) { - $("#delete-target > select").addClass("error").focus(); - return; - } - - this.sendAction("onRemove", this.get('moveTarget').get('id')); - }, - - share() { - var email = this.get('inviteEmail').trim().replace(/ /g, ''); - var message = this.get('inviteMessage').trim(); - - if (message.length === 0) { - message = this.getDefaultInvitationMessage(); - } - - if (email.length === 0) { - $("#inviteEmail").addClass("error").focus(); - return; - } - - var result = { - Message: message, - Recipients: [] - }; - - // Check for multiple email addresses - if (email.indexOf(",") > -1) { - result.Recipients = email.split(','); - } - if (email.indexOf(";") > -1 && result.Recipients.length === 0) { - result.Recipients = email.split(';'); - } - - // Handle just one email address - if (result.Recipients.length === 0 && email.length > 0) { - result.Recipients.push(email); - } - - this.set('inviteEmail', ""); - - this.sendAction("onShare", result); - }, - - setPermissions() { - var message = this.get('roleMessage').trim(); - - if (message.length === 0) { - message = this.getDefaultInvitationMessage(); - } - - this.get('permissions').forEach((permission, index) => { // eslint-disable-line no-unused-vars - Ember.set(permission, 'canView', $("#canView-" + permission.userId).prop('checked')); - Ember.set(permission, 'canEdit', $("#canEdit-" + permission.userId).prop('checked')); - }); - - this.sendAction("onPermission", this.get('folder'), message, this.get('permissions')); - } } }); diff --git a/app/app/components/folder/folder-toolbar.js b/app/app/components/folder/folder-toolbar.js index 37d805cb..bd086414 100644 --- a/app/app/components/folder/folder-toolbar.js +++ b/app/app/components/folder/folder-toolbar.js @@ -28,12 +28,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, AuthMixin, { isFolderOwner: computed.equal('folder.userId', 'session.user.id'), moveFolderId: "", drop: null, - pinned: Ember.inject.service(), - pinState : { - isPinned: false, - pinId: '', - newName: '', - }, didReceiveAttrs() { this.set('isFolderOwner', this.get('folder.userId') === this.get("session.user.id")); @@ -46,11 +40,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, AuthMixin, { }); this.set('movedFolderOptions', targets); - - let folder = this.get('folder'); - this.set('pinState.pinId', this.get('pinned').isSpacePinned(folder.get('id'))); - this.set('pinState.isPinned', this.get('pinState.pinId') !== ''); - this.set('pinState.newName', folder.get('name').substring(0,3).toUpperCase()); }, didRender() { @@ -97,39 +86,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, AuthMixin, { this.attrs.onMoveDocument(this.get('moveFolderId')); this.set("moveFolderId", ""); - return true; - }, - - unpin() { - this.audit.record('unpinned-space'); - - this.get('pinned').unpinItem(this.get('pinState.pinId')).then(() => { - this.set('pinState.isPinned', false); - this.set('pinState.pinId', ''); - this.eventBus.publish('pinChange'); - }); - }, - - pin() { - let pin = { - pin: this.get('pinState.newName'), - documentId: '', - folderId: this.get('folder.id') - }; - - if (is.empty(pin.pin)) { - $("#pin-space-name").addClass("error").focus(); - return false; - } - - this.audit.record('pinned-space'); - - this.get('pinned').pinItem(pin).then((pin) => { - this.set('pinState.isPinned', true); - this.set('pinState.pinId', pin.get('id')); - this.eventBus.publish('pinChange'); - }); - return true; } } diff --git a/app/app/components/folder/folders-list.js b/app/app/components/folder/folders-list.js deleted file mode 100644 index c63296f0..00000000 --- a/app/app/components/folder/folders-list.js +++ /dev/null @@ -1,193 +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'; -import constants from '../../utils/constants'; -import TooltipMixin from '../../mixins/tooltip'; -import NotifierMixin from '../../mixins/notifier'; - -const { - inject: { service } -} = Ember; - -export default Ember.Component.extend(TooltipMixin, NotifierMixin, { - folderService: Ember.inject.service('folder'), - templateService: Ember.inject.service('template'), - appMeta: service(), - publicFolders: [], - protectedFolders: [], - privateFolders: [], - savedTemplates: [], - hasPublicFolders: false, - hasProtectedFolders: false, - hasPrivateFolders: false, - newFolder: "", - showScrollTool: false, - showingDocument: false, - showingList: true, - - init() { - this._super(...arguments); - - if (this.get('noFolder')) { - return; - } - - let _this = this; - this.get('templateService').getSavedTemplates().then(function(saved) { - let emptyTemplate = { - id: "0", - title: "Empty", - description: "An empty canvas for your words", - img: "insert_drive_file", - layout: "doc", - locked: true - }; - - saved.forEach(function(t) { - Ember.set(t, 'img', 'content_copy'); - }); - - saved.unshiftObject(emptyTemplate); - _this.set('savedTemplates', saved); - }); - }, - - didRender() { - if (this.get('noFolder')) { - return; - } - - if (this.get('folderService').get('canEditCurrentFolder')) { - this.addTooltip(document.getElementById("start-document-button")); - } - }, - - didInsertElement() { - if (this.get('noFolder')) { - return; - } - - this.eventBus.subscribe('resized', this, 'positionTool'); - this.eventBus.subscribe('scrolled', this, 'positionTool'); - }, - - willDestroyElement() { - this.eventBus.unsubscribe('resized'); - this.eventBus.unsubscribe('scrolled'); - this.destroyTooltips(); - }, - - didReceiveAttrs() { - let folders = this.get('folders'); - - // clear out state - this.set('publicFolders', []); - this.set('protectedFolders', []); - this.set('privateFolders', []); - - _.each(folders, folder => { - if (folder.get('folderType') === constants.FolderType.Public) { - let folders = this.get('publicFolders'); - folders.pushObject(folder); - this.set('publicFolders', folders); - } - if (folder.get('folderType') === constants.FolderType.Private) { - let folders = this.get('privateFolders'); - folders.pushObject(folder); - this.set('privateFolders', folders); - } - if (folder.get('folderType') === constants.FolderType.Protected) { - let folders = this.get('protectedFolders'); - folders.pushObject(folder); - this.set('protectedFolders', folders); - } - }); - - this.set('hasPublicFolders', this.get('publicFolders.length') > 0); - this.set('hasPrivateFolders', this.get('privateFolders.length') > 0); - this.set('hasProtectedFolders', this.get('protectedFolders.length') > 0); - }, - - positionTool() { - if (this.get('isDestroyed') || this.get('isDestroying')) { - return; - } - - let s = $(".scroll-space-tool"); - let windowpos = $(window).scrollTop(); - - if (windowpos >= 300) { - this.set('showScrollTool', true); - s.addClass("stuck-space-tool"); - s.css('left', parseInt($(".zone-navigation").css('width')) + parseInt($(".zone-sidebar").css('width')) - 17 + 'px'); - } else { - this.set('showScrollTool', false); - s.removeClass("stuck-space-tool"); - } - }, - - navigateToDocument(document) { - this.attrs.showDocument(this.get('folder'), document); - }, - - actions: { - onImport() { - this.attrs.onImport(); - }, - - scrollTop() { - this.set('showScrollTool', false); - - $("html,body").animate({ - scrollTop: 0 - }, 500, "linear"); - }, - - addFolder() { - var folderName = this.get('newFolder'); - - if (is.empty(folderName)) { - $("#new-folder-name").addClass("error").focus(); - return false; - } - - this.attrs.onFolderAdd(folderName); - - this.set('newFolder', ""); - return true; - }, - - showDocument() { - this.set('showingDocument', true); - this.set('showingList', false); - }, - - showList() { - this.set('showingDocument', false); - this.set('showingList', true); - }, - - onEditTemplate(template) { - this.navigateToDocument(template); - }, - - onDocumentTemplate(id /*, title, type*/ ) { - let self = this; - - this.send("showNotification", "Creating"); - - this.get('templateService').importSavedTemplate(this.folder.get('id'), id).then(function(document) { - self.navigateToDocument(document); - }); - } - } -}); diff --git a/app/app/components/folder/sidebar-folders-list.js b/app/app/components/folder/sidebar-folders-list.js new file mode 100644 index 00000000..b21c16f2 --- /dev/null +++ b/app/app/components/folder/sidebar-folders-list.js @@ -0,0 +1,128 @@ +// 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 constants from '../../utils/constants'; +import TooltipMixin from '../../mixins/tooltip'; +import NotifierMixin from '../../mixins/notifier'; +import AuthMixin from '../../mixins/auth'; + +export default Ember.Component.extend(TooltipMixin, NotifierMixin, AuthMixin, { + publicFolders: [], + protectedFolders: [], + privateFolders: [], + hasPublicFolders: false, + hasProtectedFolders: false, + hasPrivateFolders: false, + newFolder: '', + + // init() { + // this._super(...arguments); + + // if (this.get('noFolder')) { + // return; + // } + + // let _this = this; + // this.get('templateService').getSavedTemplates().then(function(saved) { + // let emptyTemplate = { + // id: "0", + // title: "Empty", + // description: "An empty canvas for your words", + // img: "insert_drive_file", + // layout: "doc", + // locked: true + // }; + + // saved.forEach(function(t) { + // Ember.set(t, 'img', 'content_copy'); + // }); + + // saved.unshiftObject(emptyTemplate); + // _this.set('savedTemplates', saved); + // }); + // }, + + didReceiveAttrs() { + let folders = this.get('folders'); + + // clear out state + this.set('publicFolders', []); + this.set('protectedFolders', []); + this.set('privateFolders', []); + + _.each(folders, folder => { + if (folder.get('folderType') === constants.FolderType.Public) { + let folders = this.get('publicFolders'); + folders.pushObject(folder); + this.set('publicFolders', folders); + } + if (folder.get('folderType') === constants.FolderType.Private) { + let folders = this.get('privateFolders'); + folders.pushObject(folder); + this.set('privateFolders', folders); + } + if (folder.get('folderType') === constants.FolderType.Protected) { + let folders = this.get('protectedFolders'); + folders.pushObject(folder); + this.set('protectedFolders', folders); + } + }); + + this.set('hasPublicFolders', this.get('publicFolders.length') > 0); + this.set('hasPrivateFolders', this.get('privateFolders.length') > 0); + this.set('hasProtectedFolders', this.get('protectedFolders.length') > 0); + }, + + actions: { + // onImport() { + // this.attrs.onImport(); + // }, + + addFolder() { + var folderName = this.get('newFolder'); + + if (is.empty(folderName)) { + $("#new-folder-name").addClass("error").focus(); + return false; + } + + this.attrs.onFolderAdd(folderName); + + this.set('newFolder', ''); + return true; + }, + + // showDocument() { + // this.set('showingDocument', true); + // this.set('showingList', false); + // }, + + // showList() { + // this.set('showingDocument', false); + // this.set('showingList', true); + // }, + + // onEditTemplate(template) { + // this.navigateToDocument(template); + // }, + + // onDocumentTemplate(id /*, title, type*/ ) { + // let self = this; + + // this.send("showNotification", "Creating"); + + // this.get('templateService').importSavedTemplate(this.folder.get('id'), id).then(function(document) { + // self.navigateToDocument(document); + // }); + // }, + } +}); diff --git a/app/app/pods/settings/route.js b/app/app/components/folder/sidebar-permissions.js similarity index 59% rename from app/app/pods/settings/route.js rename to app/app/components/folder/sidebar-permissions.js index 5500cd14..cd7b2cba 100644 --- a/app/app/pods/settings/route.js +++ b/app/app/components/folder/sidebar-permissions.js @@ -16,38 +16,15 @@ const { inject: { service } } = Ember; -export default Ember.Route.extend(NotifierMixin, { +export default Ember.Component.extend(NotifierMixin, { folderService: service('folder'), userService: service('user'), - folder: {}, - tab: "", - localStorage: service(), + appMeta: service(), store: service(), - beforeModel: function (transition) { - this.tab = is.not.undefined(transition.queryParams.tab) ? transition.queryParams.tab : "tabGeneral"; - }, - - model(params) { - return this.get('folderService').getFolder(params.folder_id); - }, - - setupController(controller, model) { - this.folder = model; - controller.set('model', model); - - controller.set('tabGeneral', false); - controller.set('tabShare', false); - controller.set('tabPermissions', false); - controller.set('tabDelete', false); - controller.set(this.get('tab'), true); - - this.get('folderService').getAll().then((folders) => { - controller.set('folders', folders.rejectBy('id', model.get('id'))); - }); - + didReceiveAttrs() { this.get('userService').getAll().then((users) => { - controller.set('users', users); + this.set('users', users); var folderPermissions = []; @@ -57,8 +34,8 @@ export default Ember.Route.extend(NotifierMixin, { let u = { userId: user.get('id'), fullname: user.get('fullname'), - orgId: model.get('orgId'), - folderId: model.get('id'), + orgId: this.get('folder.orgId'), + folderId: this.get('folder.id'), canEdit: false, canView: false, canViewPrevious: false @@ -72,15 +49,15 @@ export default Ember.Route.extend(NotifierMixin, { var u = { userId: "", fullname: " Everyone", - orgId: model.get('orgId'), - folderId: model.get('id'), + orgId: this.get('folder.orgId'), + folderId: this.get('folder.id'), canEdit: false, canView: false }; folderPermissions.pushObject(u); - this.get('folderService').getPermissions(model.id).then((permissions) => { + this.get('folderService').getPermissions(this.get('folder.id')).then((permissions) => { permissions.forEach((permission, index) => { // eslint-disable-line no-unused-vars var folderPermission = folderPermissions.findBy('userId', permission.get('userId')); if (is.not.undefined(folderPermission)) { @@ -99,38 +76,26 @@ export default Ember.Route.extend(NotifierMixin, { return this.get('store').push(data); }); - controller.set('permissions', folderPermissions.sortBy('fullname')); + this.set('permissions', folderPermissions.sortBy('fullname')); }); - }); + }); + }, + + getDefaultInvitationMessage() { + return "Hey there, I am sharing the " + this.get('folder.name') + " (in " + this.get("appMeta.title") + ") with you so we can both access the same documents."; }, actions: { - onRename: function (folder) { - let self = this; - this.get('folderService').save(folder).then(function () { - self.showNotification("Renamed"); + setPermissions() { + let message = this.getDefaultInvitationMessage(); + let folder = this.get('folder'); + let permissions = this.get('permissions'); + + this.get('permissions').forEach((permission, index) => { // eslint-disable-line no-unused-vars + Ember.set(permission, 'canView', $("#canView-" + permission.userId).prop('checked')); + Ember.set(permission, 'canEdit', $("#canEdit-" + permission.userId).prop('checked')); }); - }, - onRemove(moveId) { - this.get('folderService').remove(this.folder.get('id'), moveId).then(() => { /* jshint ignore:line */ - this.showNotification("Deleted"); - this.get('localStorage').clearSessionItem('folder'); - - this.get('folderService').getFolder(moveId).then((folder) => { - this.get('folderService').setCurrentFolder(folder); - this.transitionTo('folder', folder.get('id'), folder.get('slug')); - }); - }); - }, - - onShare: function(invitation) { - this.get('folderService').share(this.folder.get('id'), invitation).then(() => { - this.showNotification("Shared"); - }); - }, - - onPermission: function (folder, message, permissions) { var data = permissions.map((obj) => { let permission = { 'orgId': obj.orgId, @@ -142,6 +107,7 @@ export default Ember.Route.extend(NotifierMixin, { return permission; }); + var payload = { Message: message, Roles: data }; this.get('folderService').savePermissions(folder.get('id'), payload).then(() => { diff --git a/app/app/components/folder/sidebar-share.js b/app/app/components/folder/sidebar-share.js new file mode 100644 index 00000000..7f0cd7dd --- /dev/null +++ b/app/app/components/folder/sidebar-share.js @@ -0,0 +1,74 @@ +// 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'; + +const { + inject: { service } +} = Ember; + +export default Ember.Component.extend(NotifierMixin, { + folderService: service('folder'), + appMeta: service(), + inviteEmail: '', + inviteMessage: '', + + getDefaultInvitationMessage() { + return "Hey there, I am sharing the " + this.folder.get('name') + " (in " + this.get("appMeta.title") + ") with you so we can both access the same documents."; + }, + + willRender() { + if (this.get('inviteMessage').length === 0) { + this.set('inviteMessage', this.getDefaultInvitationMessage()); + } + }, + + actions: { + onShare() { + var email = this.get('inviteEmail').trim().replace(/ /g, ''); + var message = this.get('inviteMessage').trim(); + + if (message.length === 0) { + message = this.getDefaultInvitationMessage(); + } + + if (email.length === 0) { + $('#inviteEmail').addClass('error').focus(); + return; + } + + var result = { + Message: message, + Recipients: [] + }; + + // Check for multiple email addresses + if (email.indexOf(",") > -1) { + result.Recipients = email.split(','); + } + if (email.indexOf(";") > -1 && result.Recipients.length === 0) { + result.Recipients = email.split(';'); + } + + // Handle just one email address + if (result.Recipients.length === 0 && email.length > 0) { + result.Recipients.push(email); + } + + this.set('inviteEmail', ''); + + this.get('folderService').share(this.folder.get('id'), result).then(() => { + this.showNotification('Shared'); + }); + } + } +}); diff --git a/app/app/components/folder/sidebar-zone.js b/app/app/components/folder/sidebar-zone.js new file mode 100644 index 00000000..768afe41 --- /dev/null +++ b/app/app/components/folder/sidebar-zone.js @@ -0,0 +1,154 @@ +// 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 TooltipMixin from '../../mixins/tooltip'; +import NotifierMixin from '../../mixins/notifier'; +import AuthMixin from '../../mixins/auth'; + +const { + inject: { service } +} = Ember; + +export default Ember.Component.extend(TooltipMixin, NotifierMixin, AuthMixin, { + folderService: service('folder'), + templateService: service('template'), + appMeta: service(), + pinned: service(), + publicFolders: [], + protectedFolders: [], + privateFolders: [], + hasPublicFolders: false, + hasProtectedFolders: false, + hasPrivateFolders: false, + newFolder: "", + menuOpen: false, + pinState : { + isPinned: false, + pinId: '', + newName: '', + }, + tab: '', + + init() { + this._super(...arguments); + + if (is.empty(this.get('tab')) || is.undefined(this.get('tab'))) { + this.set('tab', 'index'); + } + }, + + + // this._super(...arguments); + + // if (this.get('noFolder')) { + // return; + // } + + // let _this = this; + // this.get('templateService').getSavedTemplates().then(function(saved) { + // let emptyTemplate = { + // id: "0", + // title: "Empty", + // description: "An empty canvas for your words", + // img: "insert_drive_file", + // layout: "doc", + // locked: true + // }; + + // saved.forEach(function(t) { + // Ember.set(t, 'img', 'content_copy'); + // }); + + // saved.unshiftObject(emptyTemplate); + // _this.set('savedTemplates', saved); + // }); + // }, + + didReceiveAttrs() { + if (!this.get('noFolder')) { + let folder = this.get('folder'); + this.set('pinState.pinId', this.get('pinned').isSpacePinned(folder.get('id'))); + this.set('pinState.isPinned', this.get('pinState.pinId') !== ''); + this.set('pinState.newName', folder.get('name').substring(0,3).toUpperCase()); + } + }, + + // navigateToDocument(document) { + // this.attrs.showDocument(this.get('folder'), document); + // }, + + actions: { + // onImport() { + // this.attrs.onImport(); + // }, + + onFolderAdd(folderName) { + this.attrs.onFolderAdd(folderName); + return true; + }, + + // onEditTemplate(template) { + // this.navigateToDocument(template); + // }, + + // onDocumentTemplate(id /*, title, type*/ ) { + // let self = this; + + // this.send("showNotification", "Creating"); + + // this.get('templateService').importSavedTemplate(this.folder.get('id'), id).then(function(document) { + // self.navigateToDocument(document); + // }); + // }, + + onChangeTab(tab) { + this.set('tab', tab); + }, + + onMenuOpen() { + this.set('menuOpen', !this.get('menuOpen')); + }, + + onUnpin() { + this.audit.record('unpinned-space'); + + this.get('pinned').unpinItem(this.get('pinState.pinId')).then(() => { + this.set('pinState.isPinned', false); + this.set('pinState.pinId', ''); + this.eventBus.publish('pinChange'); + }); + }, + + onPin() { + let pin = { + pin: this.get('pinState.newName'), + documentId: '', + folderId: this.get('folder.id') + }; + + if (is.empty(pin.pin)) { + $('#pin-space-name').addClass('error').focus(); + return false; + } + + this.audit.record('pinned-space'); + + this.get('pinned').pinItem(pin).then((pin) => { + this.set('pinState.isPinned', true); + this.set('pinState.pinId', pin.get('id')); + this.eventBus.publish('pinChange'); + }); + + return true; + }, + } +}); diff --git a/app/app/pods/document/route.js b/app/app/pods/document/route.js index c3127cda..c3ea9513 100644 --- a/app/app/pods/document/route.js +++ b/app/app/pods/document/route.js @@ -54,14 +54,6 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { sections: this.get('sectionService').getAll() }); }, - - activate() { - $('body').addClass('background-color-off-white'); - }, - - deactivate() { - $('body').removeClass('background-color-off-white'); - }, actions: { error(error /*, transition*/ ) { diff --git a/app/app/pods/folder/controller.js b/app/app/pods/folder/controller.js index c3d84974..0c12ba70 100644 --- a/app/app/pods/folder/controller.js +++ b/app/app/pods/folder/controller.js @@ -15,8 +15,11 @@ import NotifierMixin from '../../mixins/notifier'; export default Ember.Controller.extend(NotifierMixin, { documentService: Ember.inject.service('document'), folderService: Ember.inject.service('folder'), + localStorage: Ember.inject.service('localStorage'), hasSelectedDocuments: false, selectedDocuments: [], + queryParams: ['tab'], + tab: 'index', actions: { onImport() { @@ -73,6 +76,14 @@ export default Ember.Controller.extend(NotifierMixin, { self.get('folderService').setCurrentFolder(newFolder); self.transitionToRoute('folder', newFolder.get('id'), newFolder.get('slug')); }); + }, + + onDeleteSpace() { + this.get('folderService').delete(this.get('model.folder.id')).then(() => { /* jshint ignore:line */ + this.showNotification("Deleted"); + this.get('localStorage').clearSessionItem('folder'); + this.transitionToRoute('application'); + }); } } }); diff --git a/app/app/pods/folder/route.js b/app/app/pods/folder/route.js index 329faf8f..c22b2c17 100644 --- a/app/app/pods/folder/route.js +++ b/app/app/pods/folder/route.js @@ -15,7 +15,7 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout export default Ember.Route.extend(AuthenticatedRouteMixin, { documentService: Ember.inject.service('document'), folderService: Ember.inject.service('folder'), - + session: Ember.inject.service(''), folder: {}, model: function (params) { @@ -30,5 +30,16 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { controller.set('model', model); this.browser.setTitle(model.folder.get('name')); this.get('folderService').setCurrentFolder(model.folder); - } + controller.set('isEditor', this.get('folderService').get('canEditCurrentFolder')); + controller.set('isFolderOwner', this.get('session.user.id') === model.folder.get('userId')); + }, + + actions: { + error(error /*, transition*/ ) { + if (error) { + this.transitionTo('/not-found'); + return false; + } + } + } }); diff --git a/app/app/pods/folder/template.hbs b/app/app/pods/folder/template.hbs index f1d758fe..323bcbc7 100644 --- a/app/app/pods/folder/template.hbs +++ b/app/app/pods/folder/template.hbs @@ -1,12 +1,14 @@ {{layout/zone-navigation}} {{#layout/zone-container}} {{#layout/zone-sidebar}} - {{folder/folders-list folders=model.folders folder=model.folder onImport=(action 'onImport') onFolderAdd=(action 'onFolderAdd') - showDocument=(action 'showDocument')}} + {{folder/sidebar-zone folders=model.folders folder=model.folder isFolderOwner=isFolderOwner isEditor=isEditor tab=tab + onFolderAdd=(action 'onFolderAdd')}} {{/layout/zone-sidebar}} {{#layout/zone-content}} - {{folder/folder-toolbar folders=model.folders folder=model.folder hasSelectedDocuments=hasSelectedDocuments onDeleteDocument=(action - 'onDeleteDocument') onMoveDocument=(action 'onMoveDocument')}} - {{folder/documents-list documents=model.documents folder=model.folder isFolderOwner=isFolderOwner onDocumentsChecked=(action 'onDocumentsChecked') }} + {{folder/folder-heading folder=model.folder isFolderOwner=isFolderOwner isEditor=isEditor}} + {{folder/folder-toolbar folders=model.folders folder=model.folder hasSelectedDocuments=hasSelectedDocuments + onDeleteDocument=(action 'onDeleteDocument') onMoveDocument=(action 'onMoveDocument')}} + {{folder/documents-list documents=model.documents folders=model.folders folder=model.folder isFolderOwner=isFolderOwner + onDocumentsChecked=(action 'onDocumentsChecked') onDeleteSpace=(action 'onDeleteSpace')}} {{/layout/zone-content}} {{/layout/zone-container}} \ No newline at end of file diff --git a/app/app/pods/folders/template.hbs b/app/app/pods/folders/template.hbs index 85acf0ed..b9af815e 100644 --- a/app/app/pods/folders/template.hbs +++ b/app/app/pods/folders/template.hbs @@ -1,7 +1,8 @@ {{layout/zone-navigation}} {{#layout/zone-container}} {{#layout/zone-sidebar}} - {{folder/folders-list folders=model noFolder=true onFolderAdd=(action 'onFolderAdd')}} + {{folder/sidebar-zone folders=model noFolder=true isFolderOwner=false isEditor=false + onFolderAdd=(action 'onFolderAdd')}} {{/layout/zone-sidebar}} {{#layout/zone-content}} {{/layout/zone-content}} diff --git a/app/app/pods/settings/controller.js b/app/app/pods/settings/controller.js deleted file mode 100644 index 2a5d1a5a..00000000 --- a/app/app/pods/settings/controller.js +++ /dev/null @@ -1,31 +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'; -import AuthMixin from '../../mixins/auth'; - -export default Ember.Controller.extend(AuthMixin, { - tabGeneral: false, - tabShare: false, - tabPermissions: false, - tabDelete: false, - - actions: { - selectTab(tab) { - this.set('tabGeneral', false); - this.set('tabShare', false); - this.set('tabPermissions', false); - this.set('tabDelete', false); - - this.set(tab, true); - } - } -}); \ No newline at end of file diff --git a/app/app/pods/settings/template.hbs b/app/app/pods/settings/template.hbs deleted file mode 100644 index 64c329af..00000000 --- a/app/app/pods/settings/template.hbs +++ /dev/null @@ -1,34 +0,0 @@ -{{layout/zone-navigation}} - -{{#layout/zone-sidebar}} - {{#layout/sidebar-intro message='Rename, delete, share and manage space permissions'}} - {{back-to-space folder=model}} - {{/layout/sidebar-intro}} - -{{/layout/zone-sidebar}} - -{{#layout/zone-content}} - {{#folder/folder-settings - tabGeneral=tabGeneral - tabShare=tabShare - tabPermissions=tabPermissions - tabDelete=tabDelete - folder=model - folders=folders - permissions=permissions - users=users - onRemove="onRemove" - onRename="onRename" - onShare="onShare" - onPermission="onPermission" }} - {{/folder/folder-settings}} -{{/layout/zone-content}} diff --git a/app/app/router.js b/app/app/router.js index 0f8354c8..5a04cd24 100644 --- a/app/app/router.js +++ b/app/app/router.js @@ -25,10 +25,6 @@ export default Router.map(function () { path: 's/:folder_id/:folder_slug' }); - this.route('settings', { - path: 's/:folder_id/:folder_slug/settings' - }); - this.route('document', { path: 's/:folder_id/:folder_slug/d/:document_id/:document_slug' }, function () { diff --git a/app/app/services/folder.js b/app/app/services/folder.js index 630d3112..08c99238 100644 --- a/app/app/services/folder.js +++ b/app/app/services/folder.js @@ -80,6 +80,12 @@ export default BaseService.extend({ }); }, + delete(folderId) { + return this.get('ajax').request(`folders/${folderId}`, { + method: 'DELETE' + }); + }, + onboard(folderId, payload) { let url = `public/share/${folderId}`; diff --git a/app/app/styles/view/folder/all.scss b/app/app/styles/view/folder/all.scss index a2f2d4d2..c6d7a06c 100644 --- a/app/app/styles/view/folder/all.scss +++ b/app/app/styles/view/folder/all.scss @@ -1,3 +1,4 @@ @import "document.scss"; @import "folder.scss"; @import "wizard.scss"; +@import "sidebar.scss"; diff --git a/app/app/styles/view/folder/document.scss b/app/app/styles/view/folder/document.scss index e95fb470..f0894e5e 100644 --- a/app/app/styles/view/folder/document.scss +++ b/app/app/styles/view/folder/document.scss @@ -1,11 +1,35 @@ +.folder-heading { + margin: 0 0 55px 0; + + .folder-title { + font-size: 2rem; + margin: 0 0 10px 0; + font-weight: normal; + } +} + +.edit-folder-heading { + margin: 0 0 10px 0; + + .edit-folder-title { + > input { + font-size: 2rem; + font-weight: normal; + margin: 0 0 10px; + color: $color-wysiwyg; + } + } +} + .documents-list { > .document { - margin: 0; - padding: 20px 20px 25px; - width: 100%; + @include content-container(); + margin-bottom: 30px; + // padding: 20px 20px 25px; + // width: 100%; position: relative; transition: 0.3s; - border-bottom: 1px solid $color-border; + // border-bottom: 1px solid $color-border; &:hover { > .link { @@ -26,8 +50,8 @@ > .checkbox { position: absolute; display: none; - top: 8px; - right: 15px; + top: 10px; + right: 20px; cursor: pointer; > .material-icons { @@ -72,7 +96,7 @@ .move-document-options, .start-document-options { - height: 150px; + height: 200px; overflow-y: auto; margin: 0; padding: 0; diff --git a/app/app/styles/view/folder/sidebar.scss b/app/app/styles/view/folder/sidebar.scss new file mode 100644 index 00000000..a37cf4e0 --- /dev/null +++ b/app/app/styles/view/folder/sidebar.scss @@ -0,0 +1,40 @@ +.sidebar-folder-share { + > .input-control { + margin-bottom: 30px; + } +} + +.sidebar-permissions { + > .input-control { + margin-bottom: 30px; + } + + > .permissions-table { + border: none; + padding: 0; + margin: 0 0 30px 0; + width: 100%; + + > thead { + > tr { + > th { + font-weight: bold; + text-align: center; + } + } + } + + > tbody { + > tr { + > td { + padding: 8px 0; + } + + > td:nth-child(2), td:nth-child(3) { + text-align: center; + } + } + } + } +} + diff --git a/app/app/styles/view/layout-left-sidebar.scss b/app/app/styles/view/layout-left-sidebar.scss index 8b90cbb8..b796fea1 100644 --- a/app/app/styles/view/layout-left-sidebar.scss +++ b/app/app/styles/view/layout-left-sidebar.scss @@ -35,6 +35,12 @@ $sidebar-width: 400px; position: absolute; margin-top: 30px; padding: 30px; + + .page-content-title { + font-size: 2rem; + margin: 30px 0 10px; + font-weight: normal; + } } #wrapper.toggled #page-content-wrapper { @@ -160,10 +166,11 @@ $sidebar-width: 400px; margin-bottom: 30px; } - .document-sidebar-form-wrapper { + .folder-sidebar-form-wrapper, .document-sidebar-form-wrapper { padding: 20px; border: 1px solid $color-stroke; @include border-radius(3px); + background-color: $color-white; } } } diff --git a/app/app/templates/components/folder/documents-list.hbs b/app/app/templates/components/folder/documents-list.hbs index 8f780f0b..d912702f 100644 --- a/app/app/templates/components/folder/documents-list.hbs +++ b/app/app/templates/components/folder/documents-list.hbs @@ -20,7 +20,5 @@ {{#if emptyState}} -
- -
+
delete
{{/if}} diff --git a/app/app/templates/components/folder/folder-heading.hbs b/app/app/templates/components/folder/folder-heading.hbs new file mode 100644 index 00000000..da8977c0 --- /dev/null +++ b/app/app/templates/components/folder/folder-heading.hbs @@ -0,0 +1,21 @@ +{{#unless editMode}} +
+

{{folder.name}}

+
+{{else}} +
+
+
+ {{focus-input id="folder-name" type="text" value=folderName class=(if hasNameError 'error-inline') placeholder="Name" autocomplete="off"}} +
+
+ +
+ close +
+
+
+
+{{/unless}} diff --git a/app/app/templates/components/folder/folder-settings.hbs b/app/app/templates/components/folder/folder-settings.hbs index 75b830f3..cc3eebf6 100644 --- a/app/app/templates/components/folder/folder-settings.hbs +++ b/app/app/templates/components/folder/folder-settings.hbs @@ -1,49 +1,4 @@
- {{#if tabGeneral}} -
-
- -
Concise name helps everyone understand what this space contains
- {{focus-input id="folderName" type="text" value=folder.name}} -
-
save
-
- {{/if}} - - {{#if tabShare}} -
-
-
Invitations
-
Invite people to this space
-
-
- -
Comma separate multiple email addresses
- {{focus-input id="inviteEmail" type="text" value=inviteEmail}} -
-
- -
Explain why they are being invited
- {{textarea id="explainInvite" value=inviteMessage rows=3}} -
-
Share
-
- {{/if}} - - {{#if tabDelete}} -
-
-
Danger Here
-
Before careful as there is no undo!
-
-
- -
Move existing documents to another space before you delete {{folder.name}}
- {{ui-select id="delete-target" content=folders action=(action (mut moveTarget)) prompt="Select destination"}} -
-
delete
-
- {{/if}} {{#if tabPermissions}}
@@ -57,31 +12,6 @@ {{textarea id="explainRole" value=roleMessage rows=3}}
- - - - - - - - - - {{#each permissions key="@index" as |permission|}} - - - - - - {{/each}} - -
 Can ViewCan Edit
{{permission.fullname}} - - - - - -
-
Apply
{{/if}} diff --git a/app/app/templates/components/folder/folder-toolbar.hbs b/app/app/templates/components/folder/folder-toolbar.hbs index 30b556cf..a4e3cd2c 100644 --- a/app/app/templates/components/folder/folder-toolbar.hbs +++ b/app/app/templates/components/folder/folder-toolbar.hbs @@ -28,52 +28,7 @@ {{/dropdown-dialog}} {{else}} - {{#if session.authenticated}} - {{#if pinState.isPinned}} -
- star -
- {{else}} -
- star_border -
- {{/if}} - {{#if isFolderOwner}} -
- {{/if}} - {{/if}} - {{#if isFolderOwner}} - {{#if isAuthProviderDocumize}} - {{#link-to 'settings' folder.id folder.slug (query-params tab="tabShare")}} -
- share -
- {{/link-to}} - {{else}} - {{#link-to 'settings' folder.id folder.slug (query-params tab="tabPermissions")}} -
- share -
- {{/link-to}} - {{/if}} -
- {{#link-to 'settings' folder.id folder.slug}} -
- settings -
- {{/link-to}} - {{/if}} - {{#if session.authenticated}} - {{#unless pinState.isPinned}} - {{#dropdown-dialog target="pin-space-button" position="bottom right" button="Pin" color="flat-green" onAction=(action 'pin') focusOn="pin-space-name" }} -
- -
A 3 or 4 character name
- {{input type='text' id="pin-space-name" value=pinState.newName}} -
- {{/dropdown-dialog}} - {{/unless}} - {{/if}} +
{{/if}} {{/if}} diff --git a/app/app/templates/components/folder/folders-list.hbs b/app/app/templates/components/folder/folders-list.hbs deleted file mode 100644 index 53de7d93..00000000 --- a/app/app/templates/components/folder/folders-list.hbs +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - diff --git a/app/app/templates/components/folder/sidebar-folders-list.hbs b/app/app/templates/components/folder/sidebar-folders-list.hbs new file mode 100644 index 00000000..fe97b4c5 --- /dev/null +++ b/app/app/templates/components/folder/sidebar-folders-list.hbs @@ -0,0 +1,72 @@ + diff --git a/app/app/templates/components/folder/sidebar-permissions.hbs b/app/app/templates/components/folder/sidebar-permissions.hbs new file mode 100644 index 00000000..c8ced3a8 --- /dev/null +++ b/app/app/templates/components/folder/sidebar-permissions.hbs @@ -0,0 +1,30 @@ + diff --git a/app/app/templates/components/folder/sidebar-share.hbs b/app/app/templates/components/folder/sidebar-share.hbs new file mode 100644 index 00000000..3c0e27b4 --- /dev/null +++ b/app/app/templates/components/folder/sidebar-share.hbs @@ -0,0 +1,16 @@ + diff --git a/app/app/templates/components/folder/sidebar-zone.hbs b/app/app/templates/components/folder/sidebar-zone.hbs new file mode 100644 index 00000000..af88f2d9 --- /dev/null +++ b/app/app/templates/components/folder/sidebar-zone.hbs @@ -0,0 +1,67 @@ + + + + + diff --git a/core/api/endpoint/label_endpoint.go b/core/api/endpoint/label_endpoint.go index 18a7cf69..6cc94b67 100644 --- a/core/api/endpoint/label_endpoint.go +++ b/core/api/endpoint/label_endpoint.go @@ -341,6 +341,64 @@ func RemoveFolder(w http.ResponseWriter, r *http.Request) { writeSuccessString(w, "{}") } +// DeleteFolder deletes empty folder. +func DeleteFolder(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + + method := "DeleteFolder" + p := request.GetPersister(r) + + if !p.Context.Editor { + writeForbiddenError(w) + return + } + + params := mux.Vars(r) + id := params["folderID"] + + if len(id) == 0 { + writeMissingDataError(w, method, "folderID") + return + } + + tx, err := request.Db.Beginx() + + if err != nil { + writeTransactionError(w, method, err) + return + } + + p.Context.Transaction = tx + + _, err = p.DeleteLabel(id) + if err != nil { + log.IfErr(tx.Rollback()) + writeServerError(w, method, err) + return + } + + _, err = p.DeleteLabelRoles(id) + if err != nil { + log.IfErr(tx.Rollback()) + writeServerError(w, method, err) + return + } + + _, err = p.DeletePinnedSpace(id) + if err != nil && err != sql.ErrNoRows { + log.IfErr(tx.Rollback()) + writeServerError(w, method, err) + return + } + + log.IfErr(tx.Commit()) + + writeSuccessString(w, "{}") +} + // SetFolderPermissions persists specified folder permissions func SetFolderPermissions(w http.ResponseWriter, r *http.Request) { method := "SetFolderPermissions" diff --git a/core/api/endpoint/router.go b/core/api/endpoint/router.go index e1ec83be..50d2e668 100644 --- a/core/api/endpoint/router.go +++ b/core/api/endpoint/router.go @@ -183,6 +183,7 @@ func init() { log.IfErr(Add(RoutePrefixPrivate, "organizations/{orgID}", []string{"PUT", "OPTIONS"}, nil, UpdateOrganization)) // Folder + log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}", []string{"DELETE", "OPTIONS"}, nil, DeleteFolder)) log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/move/{moveToId}", []string{"DELETE", "OPTIONS"}, nil, RemoveFolder)) log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"PUT", "OPTIONS"}, nil, SetFolderPermissions)) log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"GET", "OPTIONS"}, nil, GetFolderPermissions))