1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-21 22:29:41 +02:00

space sidebar

This commit is contained in:
Harvey Kandola 2017-03-24 13:10:32 +00:00
parent 27ce8507d5
commit 5bfd3bb247
33 changed files with 834 additions and 664 deletions

View file

@ -13,6 +13,7 @@ import Ember from 'ember';
export default Ember.Component.extend({ export default Ember.Component.extend({
selectedDocuments: [], selectedDocuments: [],
moveTarget: null,
emptyState: Ember.computed('documents', function() { emptyState: Ember.computed('documents', function() {
return this.get('documents.length') === 0; return this.get('documents.length') === 0;
@ -21,6 +22,8 @@ export default Ember.Component.extend({
didReceiveAttrs() { didReceiveAttrs() {
this.set('selectedDocuments', []); this.set('selectedDocuments', []);
this.audit.record('viewed-space'); this.audit.record('viewed-space');
this.set('deleteTargets', this.get('folders').rejectBy('id', this.get('folder.id')));
}, },
actions: { actions: {
@ -41,6 +44,10 @@ export default Ember.Component.extend({
this.set('selectedDocuments', list); this.set('selectedDocuments', list);
this.get('onDocumentsChecked')(list); this.get('onDocumentsChecked')(list);
},
onDelete() {
this.get("onDeleteSpace")();
} }
} }
}); });

View file

@ -0,0 +1,60 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import NotifierMixin from '../../mixins/notifier';
import TooltipMixin from '../../mixins/tooltip';
const {
computed,
} = Ember;
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
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);
}
}
});

View file

@ -33,83 +33,11 @@ export default Ember.Component.extend(AuthMixin, {
}, },
willRender() { willRender() {
if (this.inviteMessage.length === 0) {
this.set('inviteMessage', this.getDefaultInvitationMessage());
}
if (this.roleMessage.length === 0) { if (this.roleMessage.length === 0) {
this.set('roleMessage', this.getDefaultInvitationMessage()); this.set('roleMessage', this.getDefaultInvitationMessage());
} }
}, },
actions: { 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'));
}
} }
}); });

View file

@ -28,12 +28,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
isFolderOwner: computed.equal('folder.userId', 'session.user.id'), isFolderOwner: computed.equal('folder.userId', 'session.user.id'),
moveFolderId: "", moveFolderId: "",
drop: null, drop: null,
pinned: Ember.inject.service(),
pinState : {
isPinned: false,
pinId: '',
newName: '',
},
didReceiveAttrs() { didReceiveAttrs() {
this.set('isFolderOwner', this.get('folder.userId') === this.get("session.user.id")); 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); 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() { didRender() {
@ -97,39 +86,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
this.attrs.onMoveDocument(this.get('moveFolderId')); this.attrs.onMoveDocument(this.get('moveFolderId'));
this.set("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; return true;
} }
} }

View file

@ -1,193 +0,0 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import 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);
});
}
}
});

View file

@ -0,0 +1,128 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import 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);
// });
// },
}
});

View file

@ -16,38 +16,15 @@ const {
inject: { service } inject: { service }
} = Ember; } = Ember;
export default Ember.Route.extend(NotifierMixin, { export default Ember.Component.extend(NotifierMixin, {
folderService: service('folder'), folderService: service('folder'),
userService: service('user'), userService: service('user'),
folder: {}, appMeta: service(),
tab: "",
localStorage: service(),
store: service(), store: service(),
beforeModel: function (transition) { didReceiveAttrs() {
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')));
});
this.get('userService').getAll().then((users) => { this.get('userService').getAll().then((users) => {
controller.set('users', users); this.set('users', users);
var folderPermissions = []; var folderPermissions = [];
@ -57,8 +34,8 @@ export default Ember.Route.extend(NotifierMixin, {
let u = { let u = {
userId: user.get('id'), userId: user.get('id'),
fullname: user.get('fullname'), fullname: user.get('fullname'),
orgId: model.get('orgId'), orgId: this.get('folder.orgId'),
folderId: model.get('id'), folderId: this.get('folder.id'),
canEdit: false, canEdit: false,
canView: false, canView: false,
canViewPrevious: false canViewPrevious: false
@ -72,15 +49,15 @@ export default Ember.Route.extend(NotifierMixin, {
var u = { var u = {
userId: "", userId: "",
fullname: " Everyone", fullname: " Everyone",
orgId: model.get('orgId'), orgId: this.get('folder.orgId'),
folderId: model.get('id'), folderId: this.get('folder.id'),
canEdit: false, canEdit: false,
canView: false canView: false
}; };
folderPermissions.pushObject(u); 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 permissions.forEach((permission, index) => { // eslint-disable-line no-unused-vars
var folderPermission = folderPermissions.findBy('userId', permission.get('userId')); var folderPermission = folderPermissions.findBy('userId', permission.get('userId'));
if (is.not.undefined(folderPermission)) { if (is.not.undefined(folderPermission)) {
@ -99,38 +76,26 @@ export default Ember.Route.extend(NotifierMixin, {
return this.get('store').push(data); 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: { actions: {
onRename: function (folder) { setPermissions() {
let self = this; let message = this.getDefaultInvitationMessage();
this.get('folderService').save(folder).then(function () { let folder = this.get('folder');
self.showNotification("Renamed"); let permissions = this.get('permissions');
});
},
onRemove(moveId) { this.get('permissions').forEach((permission, index) => { // eslint-disable-line no-unused-vars
this.get('folderService').remove(this.folder.get('id'), moveId).then(() => { /* jshint ignore:line */ Ember.set(permission, 'canView', $("#canView-" + permission.userId).prop('checked'));
this.showNotification("Deleted"); Ember.set(permission, 'canEdit', $("#canEdit-" + permission.userId).prop('checked'));
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) => { var data = permissions.map((obj) => {
let permission = { let permission = {
'orgId': obj.orgId, 'orgId': obj.orgId,
@ -142,6 +107,7 @@ export default Ember.Route.extend(NotifierMixin, {
return permission; return permission;
}); });
var payload = { Message: message, Roles: data }; var payload = { Message: message, Roles: data };
this.get('folderService').savePermissions(folder.get('id'), payload).then(() => { this.get('folderService').savePermissions(folder.get('id'), payload).then(() => {

View file

@ -0,0 +1,74 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import NotifierMixin from '../../mixins/notifier';
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');
});
}
}
});

View file

@ -0,0 +1,154 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import TooltipMixin from '../../mixins/tooltip';
import NotifierMixin from '../../mixins/notifier';
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;
},
}
});

View file

@ -55,14 +55,6 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
}); });
}, },
activate() {
$('body').addClass('background-color-off-white');
},
deactivate() {
$('body').removeClass('background-color-off-white');
},
actions: { actions: {
error(error /*, transition*/ ) { error(error /*, transition*/ ) {
if (error) { if (error) {

View file

@ -15,8 +15,11 @@ import NotifierMixin from '../../mixins/notifier';
export default Ember.Controller.extend(NotifierMixin, { export default Ember.Controller.extend(NotifierMixin, {
documentService: Ember.inject.service('document'), documentService: Ember.inject.service('document'),
folderService: Ember.inject.service('folder'), folderService: Ember.inject.service('folder'),
localStorage: Ember.inject.service('localStorage'),
hasSelectedDocuments: false, hasSelectedDocuments: false,
selectedDocuments: [], selectedDocuments: [],
queryParams: ['tab'],
tab: 'index',
actions: { actions: {
onImport() { onImport() {
@ -73,6 +76,14 @@ export default Ember.Controller.extend(NotifierMixin, {
self.get('folderService').setCurrentFolder(newFolder); self.get('folderService').setCurrentFolder(newFolder);
self.transitionToRoute('folder', newFolder.get('id'), newFolder.get('slug')); 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');
});
} }
} }
}); });

View file

@ -15,7 +15,7 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout
export default Ember.Route.extend(AuthenticatedRouteMixin, { export default Ember.Route.extend(AuthenticatedRouteMixin, {
documentService: Ember.inject.service('document'), documentService: Ember.inject.service('document'),
folderService: Ember.inject.service('folder'), folderService: Ember.inject.service('folder'),
session: Ember.inject.service(''),
folder: {}, folder: {},
model: function (params) { model: function (params) {
@ -30,5 +30,16 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
controller.set('model', model); controller.set('model', model);
this.browser.setTitle(model.folder.get('name')); this.browser.setTitle(model.folder.get('name'));
this.get('folderService').setCurrentFolder(model.folder); 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;
}
}
} }
}); });

View file

@ -1,12 +1,14 @@
{{layout/zone-navigation}} {{layout/zone-navigation}}
{{#layout/zone-container}} {{#layout/zone-container}}
{{#layout/zone-sidebar}} {{#layout/zone-sidebar}}
{{folder/folders-list folders=model.folders folder=model.folder onImport=(action 'onImport') onFolderAdd=(action 'onFolderAdd') {{folder/sidebar-zone folders=model.folders folder=model.folder isFolderOwner=isFolderOwner isEditor=isEditor tab=tab
showDocument=(action 'showDocument')}} onFolderAdd=(action 'onFolderAdd')}}
{{/layout/zone-sidebar}} {{/layout/zone-sidebar}}
{{#layout/zone-content}} {{#layout/zone-content}}
{{folder/folder-toolbar folders=model.folders folder=model.folder hasSelectedDocuments=hasSelectedDocuments onDeleteDocument=(action {{folder/folder-heading folder=model.folder isFolderOwner=isFolderOwner isEditor=isEditor}}
'onDeleteDocument') onMoveDocument=(action 'onMoveDocument')}} {{folder/folder-toolbar folders=model.folders folder=model.folder hasSelectedDocuments=hasSelectedDocuments
{{folder/documents-list documents=model.documents folder=model.folder isFolderOwner=isFolderOwner onDocumentsChecked=(action 'onDocumentsChecked') }} 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-content}}
{{/layout/zone-container}} {{/layout/zone-container}}

View file

@ -1,7 +1,8 @@
{{layout/zone-navigation}} {{layout/zone-navigation}}
{{#layout/zone-container}} {{#layout/zone-container}}
{{#layout/zone-sidebar}} {{#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-sidebar}}
{{#layout/zone-content}} {{#layout/zone-content}}
{{/layout/zone-content}} {{/layout/zone-content}}

View file

@ -1,31 +0,0 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import 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);
}
}
});

View file

@ -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}}
<div class="sidebar-menu">
<ul class="options">
<li class="option {{if tabGeneral "selected"}}" {{action 'selectTab' 'tabGeneral'}}>General</li>
{{#if isAuthProviderDocumize}}
<li class="option {{if tabShare "selected"}}" {{action 'selectTab' 'tabShare'}}>Share</li>
{{/if}}
<li class="option {{if tabPermissions "selected"}}" {{action 'selectTab' 'tabPermissions'}}>Permissions</li>
<li class="option {{if tabDelete "selected"}}" {{action 'selectTab' 'tabDelete'}}>Delete</li>
</ul>
</div>
{{/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}}

View file

@ -25,10 +25,6 @@ export default Router.map(function () {
path: 's/:folder_id/:folder_slug' path: 's/:folder_id/:folder_slug'
}); });
this.route('settings', {
path: 's/:folder_id/:folder_slug/settings'
});
this.route('document', { this.route('document', {
path: 's/:folder_id/:folder_slug/d/:document_id/:document_slug' path: 's/:folder_id/:folder_slug/d/:document_id/:document_slug'
}, function () { }, function () {

View file

@ -80,6 +80,12 @@ export default BaseService.extend({
}); });
}, },
delete(folderId) {
return this.get('ajax').request(`folders/${folderId}`, {
method: 'DELETE'
});
},
onboard(folderId, payload) { onboard(folderId, payload) {
let url = `public/share/${folderId}`; let url = `public/share/${folderId}`;

View file

@ -1,3 +1,4 @@
@import "document.scss"; @import "document.scss";
@import "folder.scss"; @import "folder.scss";
@import "wizard.scss"; @import "wizard.scss";
@import "sidebar.scss";

View file

@ -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 { .documents-list {
> .document { > .document {
margin: 0; @include content-container();
padding: 20px 20px 25px; margin-bottom: 30px;
width: 100%; // padding: 20px 20px 25px;
// width: 100%;
position: relative; position: relative;
transition: 0.3s; transition: 0.3s;
border-bottom: 1px solid $color-border; // border-bottom: 1px solid $color-border;
&:hover { &:hover {
> .link { > .link {
@ -26,8 +50,8 @@
> .checkbox { > .checkbox {
position: absolute; position: absolute;
display: none; display: none;
top: 8px; top: 10px;
right: 15px; right: 20px;
cursor: pointer; cursor: pointer;
> .material-icons { > .material-icons {
@ -72,7 +96,7 @@
.move-document-options, .move-document-options,
.start-document-options { .start-document-options {
height: 150px; height: 200px;
overflow-y: auto; overflow-y: auto;
margin: 0; margin: 0;
padding: 0; padding: 0;

View file

@ -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;
}
}
}
}
}

View file

@ -35,6 +35,12 @@ $sidebar-width: 400px;
position: absolute; position: absolute;
margin-top: 30px; margin-top: 30px;
padding: 30px; padding: 30px;
.page-content-title {
font-size: 2rem;
margin: 30px 0 10px;
font-weight: normal;
}
} }
#wrapper.toggled #page-content-wrapper { #wrapper.toggled #page-content-wrapper {
@ -160,10 +166,11 @@ $sidebar-width: 400px;
margin-bottom: 30px; margin-bottom: 30px;
} }
.document-sidebar-form-wrapper { .folder-sidebar-form-wrapper, .document-sidebar-form-wrapper {
padding: 20px; padding: 20px;
border: 1px solid $color-stroke; border: 1px solid $color-stroke;
@include border-radius(3px); @include border-radius(3px);
background-color: $color-white;
} }
} }
} }

View file

@ -20,7 +20,5 @@
</ul> </ul>
{{#if emptyState}} {{#if emptyState}}
<div class="empty-state-space"> <div class="regular-button button-red" {{action 'onDelete'}}>delete</div>
<img src="/assets/img/empty-state-space.gif" />
</div>
{{/if}} {{/if}}

View file

@ -0,0 +1,21 @@
{{#unless editMode}}
<div class="folder-heading {{if isFolderOwner 'cursor-pointer'}}" onclick={{if isFolderOwner (action 'toggleEdit')}}>
<h1 class="folder-title">{{folder.name}}</h1>
</div>
{{else}}
<form {{action "onSave" on="submit"}}>
<div class="edit-folder-heading">
<div class="input-inline input-transparent edit-folder-title">
{{focus-input id="folder-name" type="text" value=folderName class=(if hasNameError 'error-inline') placeholder="Name" autocomplete="off"}}
</div>
<div>
<button type="submit" class="round-button-mono" {{action 'onSave'}}>
<i class="material-icons color-green">check</i>
</button>
<div class="round-button-mono" {{action 'onCancel'}}>
<i class="material-icons color-gray">close</i>
</div>
</div>
</div>
</form>
{{/unless}}

View file

@ -1,49 +1,4 @@
<div class="folder-settings"> <div class="folder-settings">
{{#if tabGeneral}}
<div class="form-bordered">
<div class="input-control">
<label>Name</label>
<div class="tip">Concise name helps everyone understand what this space contains</div>
{{focus-input id="folderName" type="text" value=folder.name}}
</div>
<div class="regular-button button-blue" {{ action 'rename' }}>save</div>
</div>
{{/if}}
{{#if tabShare}}
<div class="form-bordered">
<div class="form-header">
<div class="title">Invitations</div>
<div class="tip">Invite people to this space</div>
</div>
<div class="input-control">
<label>Email</label>
<div class="tip">Comma separate multiple email addresses</div>
{{focus-input id="inviteEmail" type="text" value=inviteEmail}}
</div>
<div class="input-control">
<label>Message</label>
<div class="tip">Explain why they are being invited</div>
{{textarea id="explainInvite" value=inviteMessage rows=3}}
</div>
<div class="regular-button button-blue" {{ action 'share' }}>Share</div>
</div>
{{/if}}
{{#if tabDelete}}
<div class="form-bordered">
<div class="form-header">
<div class="title">Danger Here</div>
<div class="tip">Before careful as there is no undo!</div>
</div>
<div class="input-control">
<label>Move before delete</label>
<div class="tip">Move existing documents to another space before you delete <strong>{{folder.name}}</strong></div>
{{ui-select id="delete-target" content=folders action=(action (mut moveTarget)) prompt="Select destination"}}
</div>
<div class="regular-button button-red" {{ action 'remove' }}>delete</div>
</div>
{{/if}}
{{#if tabPermissions}} {{#if tabPermissions}}
<div class="form-bordered"> <div class="form-bordered">
@ -57,31 +12,6 @@
{{textarea id="explainRole" value=roleMessage rows=3}} {{textarea id="explainRole" value=roleMessage rows=3}}
</div> </div>
<table class="basic-table">
<thead>
<tr>
<th>&nbsp;</th>
<th>Can View</th>
<th>Can Edit</th>
</tr>
</thead>
<tbody>
{{#each permissions key="@index" as |permission|}}
<tr>
<td>{{permission.fullname}}</td>
<td>
<input type="checkbox" id="canView-{{permission.userId}}" checked={{permission.canView}} />
<label for="canView-{{permission.userId}}">&nbsp;</label>
</td>
<td>
<input type="checkbox" id="canEdit-{{permission.userId}}" checked={{permission.canEdit}} />
<label for="canEdit-{{permission.userId}}">&nbsp;</label>
</td>
</tr>
{{/each}}
</tbody>
</table>
<div class="regular-button button-blue" {{ action 'setPermissions' }}>Apply</div>
</div> </div>
{{/if}} {{/if}}
</div> </div>

View file

@ -28,52 +28,7 @@
</ul> </ul>
{{/dropdown-dialog}} {{/dropdown-dialog}}
{{else}} {{else}}
{{#if session.authenticated}} <div class="margin-top-35"></div>
{{#if pinState.isPinned}}
<div class="round-button-mono" {{action 'unpin'}}>
<i class="material-icons color-primary">star</i>
</div>
{{else}}
<div class="round-button-mono" id="pin-space-button">
<i class="material-icons color-gray">star_border</i>
</div>
{{/if}}
{{#if isFolderOwner}}
<div class="button-gap"></div>
{{/if}}
{{/if}}
{{#if isFolderOwner}}
{{#if isAuthProviderDocumize}}
{{#link-to 'settings' folder.id folder.slug (query-params tab="tabShare")}}
<div class="round-button-mono" id="folder-share-button" data-tooltip="Share" data-tooltip-position="top center">
<i class="material-icons color-gray">share</i>
</div>
{{/link-to}}
{{else}}
{{#link-to 'settings' folder.id folder.slug (query-params tab="tabPermissions")}}
<div class="round-button-mono" id="folder-share-button" data-tooltip="Share" data-tooltip-position="top center">
<i class="material-icons color-gray">share</i>
</div>
{{/link-to}}
{{/if}}
<div class="button-gap"></div>
{{#link-to 'settings' folder.id folder.slug}}
<div class="round-button-mono" id="folder-settings-button" data-tooltip="Settings" data-tooltip-position="top center">
<i class="material-icons color-gray">settings</i>
</div>
{{/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" }}
<div class="input-control">
<label>Pin Space</label>
<div class="tip">A 3 or 4 character name</div>
{{input type='text' id="pin-space-name" value=pinState.newName}}
</div>
{{/dropdown-dialog}}
{{/unless}}
{{/if}}
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}

View file

@ -1,84 +0,0 @@
<div class="sidebar-toolbar">
</div>
<div class="sidebar-common">
{{layout/sidebar-intro title=appMeta.title message=appMeta.message}}
</div>
<div class="sidebar-wrapper">
{{#unless noFolder}}
<div class="space-tools">
{{#if showingDocument}}
{{folder/start-document savedTemplates=savedTemplates folder=folder editor=folderService.canEditCurrentFolder
onImport=(action 'onImport')
onEditTemplate=(action 'onEditTemplate')
onDocumentTemplate=(action 'onDocumentTemplate')}}
{{/if}}
</div>
{{/unless}}
<div class="folders-list">
{{#if showingList}}
{{#if session.isEditor}}
<div id="add-space-button" class="regular-button button-white">
<i class="material-icons">add</i>
<div class="name">Space</div>
</div>
{{#dropdown-dialog target="add-space-button" position="bottom left" button="Add" color="flat-green" onAction=(action 'addFolder') focusOn="new-folder-name" }}
<div>
<div class="input-control">
<label>New space</label>
<div class="tip">A repository for related documentation</div>
{{input type='text' id="new-folder-name" class="mousetrap" value=newFolder}}
</div>
</div>
{{/dropdown-dialog}}
{{/if}}
<div class="section">
<div class="heading">EVERYONE</div>
{{#unless hasPublicFolders}}
<div class="message margin-left-15">No global spaces</div>
{{/unless}}
<ul class="list">
{{#each publicFolders as |folder|}}
{{#link-to 'folder' folder.id folder.slug class="link" activeClass='selected' }}
<li class="item">{{ folder.name }}</li>
{{/link-to}}
{{/each}}
</ul>
</div>
{{#if session.authenticated}}
<div class="section">
<div class="heading">TEAM</div>
{{#unless hasProtectedFolders}}
<div class="message margin-left-15">No protected spaces</div>
{{/unless}}
<ul class="list">
{{#each protectedFolders as |folder|}}
{{#link-to 'folder' folder.id folder.slug class="link" activeClass='selected' }}
<li class="item">{{ folder.name }}</li>
{{/link-to}}
{{/each}}
</ul>
</div>
<div class="section">
<div class="heading">PERSONAL</div>
{{#unless hasPrivateFolders}}
<div class="message margin-left-15">No private spaces</div>
{{/unless}}
<ul class="list">
{{#each privateFolders as |folder|}}
{{#link-to 'folder' folder.id folder.slug class="link" activeClass='selected' }}
<li class="item">{{ folder.name }}</li>
{{/link-to}}
{{/each}}
</ul>
</div>
{{/if}}
{{/if}}
</div>
</div>

View file

@ -0,0 +1,72 @@
<div class="sidebar-panel">
<div class="space-tools">
{{#if showingDocument}}
{{folder/start-document savedTemplates=savedTemplates folder=folder editor=folderService.canEditCurrentFolder
onImport=(action 'onImport')
onEditTemplate=(action 'onEditTemplate')
onDocumentTemplate=(action 'onDocumentTemplate')}}
{{/if}}
</div>
<div class="folders-list">
{{#if session.isEditor}}
<div id="add-space-button" class="regular-button button-white">
<i class="material-icons">add</i>
<div class="name">Space</div>
</div>
{{#dropdown-dialog target="add-space-button" position="bottom left" button="Add" color="flat-green" onAction=(action 'addFolder') focusOn="new-folder-name" }}
<div>
<div class="input-control">
<label>New space</label>
<div class="tip">A repository for related documentation</div>
{{input type='text' id="new-folder-name" class="mousetrap" value=newFolder}}
</div>
</div>
{{/dropdown-dialog}}
{{/if}}
<div class="section">
<div class="heading">EVERYONE</div>
{{#unless hasPublicFolders}}
<div class="message margin-left-15">No global spaces</div>
{{/unless}}
<ul class="list">
{{#each publicFolders as |folder|}}
{{#link-to 'folder' folder.id folder.slug class="link" activeClass='selected' }}
<li class="item">{{ folder.name }}</li>
{{/link-to}}
{{/each}}
</ul>
</div>
{{#if session.authenticated}}
<div class="section">
<div class="heading">TEAM</div>
{{#unless hasProtectedFolders}}
<div class="message margin-left-15">No protected spaces</div>
{{/unless}}
<ul class="list">
{{#each protectedFolders as |folder|}}
{{#link-to 'folder' folder.id folder.slug class="link" activeClass='selected' }}
<li class="item">{{ folder.name }}</li>
{{/link-to}}
{{/each}}
</ul>
</div>
<div class="section">
<div class="heading">PERSONAL</div>
{{#unless hasPrivateFolders}}
<div class="message margin-left-15">No private spaces</div>
{{/unless}}
<ul class="list">
{{#each privateFolders as |folder|}}
{{#link-to 'folder' folder.id folder.slug class="link" activeClass='selected' }}
<li class="item">{{ folder.name }}</li>
{{/link-to}}
{{/each}}
</ul>
</div>
{{/if}}
</div>
</div>

View file

@ -0,0 +1,30 @@
<div class="sidebar-panel">
<div class="title">Space Permissions</div>
<div class="sidebar-permissions folder-sidebar-form-wrapper">
<table class="permissions-table">
<thead>
<tr>
<th>&nbsp;</th>
<th>View</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
{{#each permissions key="@index" as |permission|}}
<tr>
<td>{{permission.fullname}}</td>
<td>
<input type="checkbox" id="canView-{{permission.userId}}" checked={{permission.canView}} />
<label for="canView-{{permission.userId}}">&nbsp;</label>
</td>
<td>
<input type="checkbox" id="canEdit-{{permission.userId}}" checked={{permission.canEdit}} />
<label for="canEdit-{{permission.userId}}">&nbsp;</label>
</td>
</tr>
{{/each}}
</tbody>
</table>
<div class="regular-button button-blue" {{action 'setPermissions'}}>Set</div>
</div>
</div>

View file

@ -0,0 +1,16 @@
<div class="sidebar-panel">
<div class="title">Invite Users</div>
<div class="sidebar-folder-share folder-sidebar-form-wrapper">
<div class="input-control">
<label>Email</label>
<div class="tip">Comma separate multiple email addresses</div>
{{focus-input id="inviteEmail" type="text" class="input-transparent" value=inviteEmail}}
</div>
<div class="input-control">
<label>Message</label>
<div class="tip">Explain why they are being invited</div>
{{textarea id="explainInvite" value=inviteMessage class="input-transparent" rows="5"}}
</div>
<div class="regular-button button-blue" {{ action 'onShare' }}>Share</div>
</div>
</div>

View file

@ -0,0 +1,67 @@
<div class="sidebar-toolbar">
{{#unless noFolder}}
<div class="margin-top-20"></div>
<div class="round-button-mono {{if (is-equal tab 'index') 'selected'}}" {{action 'onChangeTab' 'index'}}>
<i class="material-icons">view_headline</i>
</div>
<div class="margin-top-20"></div>
{{#if session.authenticated}}
{{#if isFolderOwner}}
{{#if isAuthProviderDocumize}}
<div class="round-button-mono {{if (is-equal tab 'share') 'selected'}}" {{action 'onChangeTab' 'share'}}>
<i class="material-icons">person_add</i>
</div>
<div class="margin-top-20"></div>
{{/if}}
<div class="round-button-mono {{if (is-equal tab 'permissions') 'selected'}}" {{action 'onChangeTab' 'permissions'}}>
<i class="material-icons">group</i>
</div>
<div class="margin-top-20"></div>
{{/if}}
<div class="round-button-mono" id="space-more-button">
<i class="material-icons">more_horiz</i>
</div>
{{#dropdown-menu target="space-more-button" position="bottom left" open="click" onOpenCallback=(action 'onMenuOpen') onCloseCallback=(action 'onMenuOpen')}}
<ul class="menu">
{{#if pinState.isPinned}}
<li class="item" {{action 'onUnpin'}}>Unpin</li>
{{else}}
<li class="item" id="pin-space-button">Pin</li>
{{/if}}
</ul>
{{/dropdown-menu}}
{{#if menuOpen}}
{{#unless pinState.isPinned}}
{{#dropdown-dialog target="pin-space-button" position="bottom left" button="Pin" color="flat-green" onAction=(action 'onPin') focusOn="pin-space-name" }}
<div class="input-control">
<label>Pin Space</label>
<div class="tip">A 3 or 4 character name</div>
{{input type='text' id="pin-space-name" value=pinState.newName}}
</div>
{{/dropdown-dialog}}
{{/unless}}
{{/if}}
{{/if}}
{{/unless}}
</div>
<div class="sidebar-common">
{{layout/sidebar-intro title=appMeta.title message=appMeta.message}}
</div>
<div class="sidebar-wrapper">
{{#if (is-equal tab 'index')}}
{{folder/sidebar-folders-list folders=folders folder=folder isFolderOwner=isFolderOwner onFolderAdd=(action 'onFolderAdd')}}
{{/if}}
{{#if (is-equal tab 'share')}}
{{folder/sidebar-share folders=folders folder=folder}}
{{/if}}
{{#if (is-equal tab 'permissions')}}
{{folder/sidebar-permissions folders=folders folder=folder}}
{{/if}}
</div>

View file

@ -341,6 +341,64 @@ func RemoveFolder(w http.ResponseWriter, r *http.Request) {
writeSuccessString(w, "{}") 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 // SetFolderPermissions persists specified folder permissions
func SetFolderPermissions(w http.ResponseWriter, r *http.Request) { func SetFolderPermissions(w http.ResponseWriter, r *http.Request) {
method := "SetFolderPermissions" method := "SetFolderPermissions"

View file

@ -183,6 +183,7 @@ func init() {
log.IfErr(Add(RoutePrefixPrivate, "organizations/{orgID}", []string{"PUT", "OPTIONS"}, nil, UpdateOrganization)) log.IfErr(Add(RoutePrefixPrivate, "organizations/{orgID}", []string{"PUT", "OPTIONS"}, nil, UpdateOrganization))
// Folder // 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}/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{"PUT", "OPTIONS"}, nil, SetFolderPermissions))
log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"GET", "OPTIONS"}, nil, GetFolderPermissions)) log.IfErr(Add(RoutePrefixPrivate, "folders/{folderID}/permissions", []string{"GET", "OPTIONS"}, nil, GetFolderPermissions))