mirror of
https://github.com/JanGross/quicknotes.git
synced 2025-11-30 23:37:16 +01:00
Merge pull request #36 from matiasdelellis/shared-notes
Fix backend to shared notes, and initial fronted code.
This commit is contained in:
@@ -5,6 +5,28 @@ return ['resources' =>
|
||||
'noteApi' => ['url' => '/api/v1/notes']
|
||||
],
|
||||
'routes' => [
|
||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET']
|
||||
// Main page
|
||||
[
|
||||
'name' => 'page#index',
|
||||
'url' => '/',
|
||||
'verb' => 'GET'
|
||||
],
|
||||
// Share
|
||||
[
|
||||
'name' => 'share#destroy',
|
||||
'url' => '/share/{noteId}',
|
||||
'verb' => 'DELETE'
|
||||
],
|
||||
// User Settings
|
||||
[
|
||||
'name' => 'settings#setUserValue',
|
||||
'url' => '/setuservalue',
|
||||
'verb' => 'POST'
|
||||
],
|
||||
[
|
||||
'name' => 'settings#getUserValue',
|
||||
'url' => '/getuservalue',
|
||||
'verb' => 'GET'
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -226,7 +226,8 @@ div[contenteditable="true"] {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.note-options {
|
||||
.note-options,
|
||||
.note-disable-options {
|
||||
padding: 8px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
@@ -249,6 +250,7 @@ div[contenteditable="true"] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.slim-share,
|
||||
.slim-tag {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
@@ -260,14 +262,17 @@ div[contenteditable="true"] {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.slim-share:hover,
|
||||
.slim-tag:hover {
|
||||
background-color: rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.note-tags {
|
||||
margin-top: 8px;
|
||||
.note-shares > .slim-share,
|
||||
.note-tags > .slim-tag {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* Restore defaults select2 rules */
|
||||
|
||||
.select2-container-multi
|
||||
@@ -294,6 +299,10 @@ div[contenteditable="true"] {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
div.select2-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Modal Content */
|
||||
|
||||
.modal-content {
|
||||
|
||||
110
js/qn-dialogs.js
110
js/qn-dialogs.js
@@ -56,6 +56,9 @@ const QnDialogs = {
|
||||
data.push({id: item.id, text: item.name});
|
||||
});
|
||||
return data;
|
||||
},
|
||||
formatNoMatches: function() {
|
||||
return t('quicknotes', 'No tags found');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -125,6 +128,113 @@ const QnDialogs = {
|
||||
$('.select2-input').focus();
|
||||
});
|
||||
},
|
||||
shares: function (availableUsers, selectedUsers, callback) {
|
||||
return $.when(this._getMessageTemplate()).then(function ($tmpl) {
|
||||
var dialogName = 'qn-dialog-content';
|
||||
var dialogId = '#' + dialogName;
|
||||
var $dlg = $tmpl.octemplate({
|
||||
dialog_name: dialogName,
|
||||
title: t('quicknotes', 'Share note'),
|
||||
message: t('quicknotes', 'Select the users to share. By default you only share the note. Attachments should be shared from files so they can view it.'),
|
||||
type: 'none'
|
||||
});
|
||||
|
||||
var input = $('<input/>');
|
||||
input.attr('type', 'text');
|
||||
input.attr('id', dialogName + '-input');
|
||||
input.attr('multiple', 'multiple');
|
||||
|
||||
$dlg.append(input);
|
||||
$('body').append($dlg);
|
||||
|
||||
input.select2({
|
||||
placeholder: t('quicknotes', 'Select the users to share'),
|
||||
multiple: true,
|
||||
allowClear: true,
|
||||
toggleSelect: true,
|
||||
createSearchChoice: function(params) {
|
||||
return undefined;
|
||||
},
|
||||
tags: function () {
|
||||
var data = [];
|
||||
availableUsers.forEach(function (item, index) {
|
||||
// Select2 expect id, text.
|
||||
data.push({id: item, text: item});
|
||||
});
|
||||
return data;
|
||||
},
|
||||
formatNoMatches: function() {
|
||||
return t('quicknotes', 'No user found');
|
||||
}
|
||||
});
|
||||
|
||||
input.val(selectedUsers.map(function (value) { return value.name }));
|
||||
input.trigger("change");
|
||||
|
||||
$('.select2-input').on("keyup", function (event) {
|
||||
if (event.keyCode === 27) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
input.select2('close');
|
||||
if (callback !== undefined) {
|
||||
callback(false, []);
|
||||
}
|
||||
$(dialogId).ocdialog('close');
|
||||
}
|
||||
});
|
||||
|
||||
// wrap callback in _.once():
|
||||
// only call callback once and not twice (button handler and close
|
||||
// event) but call it for the close event, if ESC or the x is hit
|
||||
if (callback !== undefined) {
|
||||
callback = _.once(callback);
|
||||
}
|
||||
|
||||
var buttonlist = [{
|
||||
text: t('quicknotes', 'Cancel'),
|
||||
click: function () {
|
||||
input.select2('close');
|
||||
if (callback !== undefined) {
|
||||
callback(false, []);
|
||||
}
|
||||
$(dialogId).ocdialog('close');
|
||||
}
|
||||
}, {
|
||||
text: t('quicknotes', 'Done'),
|
||||
click: function () {
|
||||
input.select2('close');
|
||||
if (callback !== undefined) {
|
||||
var users = [];
|
||||
// Quicknotes shares expect id, shared_user
|
||||
newUsers = input.select2("data");
|
||||
newUsers.forEach(function (item) {
|
||||
item['shared_user'] = item.text;
|
||||
users.push(item);
|
||||
});
|
||||
callback(true, users);
|
||||
}
|
||||
$(dialogId).ocdialog('close');
|
||||
},
|
||||
defaultButton: true
|
||||
}
|
||||
];
|
||||
|
||||
$(dialogId).ocdialog({
|
||||
closeOnEscape: false,
|
||||
modal: true,
|
||||
buttons: buttonlist,
|
||||
close: function () {
|
||||
input.select2("close");
|
||||
// callback is already fired if Yes/No is clicked directly
|
||||
if (callback !== undefined) {
|
||||
callback(false, input.val());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.select2-input').focus();
|
||||
});
|
||||
},
|
||||
_getMessageTemplate: function () {
|
||||
var defer = $.Deferred();
|
||||
if (!this.$messageTemplate) {
|
||||
|
||||
253
js/script.js
253
js/script.js
@@ -29,6 +29,9 @@ var Notes = function (baseUrl) {
|
||||
this._baseUrl = baseUrl;
|
||||
this._notes = [];
|
||||
this._loaded = false;
|
||||
|
||||
this._usersSharing = [];
|
||||
this._loadUsersSharing();
|
||||
};
|
||||
|
||||
Notes.prototype = {
|
||||
@@ -71,6 +74,9 @@ Notes.prototype = {
|
||||
});
|
||||
return Ccolors;
|
||||
},
|
||||
getUsersSharing: function () {
|
||||
return this._usersSharing;
|
||||
},
|
||||
// Get the tags used in the notes
|
||||
getTags: function () {
|
||||
var tags = [];
|
||||
@@ -136,6 +142,42 @@ Notes.prototype = {
|
||||
deferred.reject();
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
// Delete shared note.
|
||||
forgetShare: function (note) {
|
||||
var self = this;
|
||||
var deferred = $.Deferred();
|
||||
$.ajax({
|
||||
url: OC.generateUrl('/apps/quicknotes/share') + '/' + note.id,
|
||||
method: 'DELETE'
|
||||
}).done(function () {
|
||||
var index = self._notes.findIndex((aNote) => aNote.id === note.id);
|
||||
self._notes.splice(index, 1);
|
||||
deferred.resolve();
|
||||
}).fail(function () {
|
||||
deferred.reject();
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
// Get the users to share in the notes
|
||||
_loadUsersSharing: function () {
|
||||
var self = this;
|
||||
$.get(OC.linkToOCS('apps/files_sharing/api/v1/', 1) + 'sharees', {
|
||||
format: 'json',
|
||||
perPage: 50,
|
||||
itemType: 1
|
||||
}).done(function (shares) {
|
||||
var users = [];
|
||||
$.each(shares.ocs.data.exact.users, function(index, user) {
|
||||
users.push(user.value.shareWith);
|
||||
});
|
||||
$.each(shares.ocs.data.users, function(index, user) {
|
||||
users.push(user.value.shareWith);
|
||||
});
|
||||
self._usersSharing = users;
|
||||
}).fail(function () {
|
||||
console.error("Could not get users to share.");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -164,11 +206,12 @@ View.prototype = {
|
||||
this._editableContent(note.content);
|
||||
this._editablePinned(note.ispinned);
|
||||
this._editableColor(note.color);
|
||||
this._editableShares(note.shared_with, note.shared_by);
|
||||
this._editableTags(note.tags);
|
||||
this._editableAttachts(note.attachts);
|
||||
this._editableAttachts(note.attachts, !note.is_shared);
|
||||
|
||||
// Create medium div editor.
|
||||
this._initEditor();
|
||||
this._isEditable(!note.is_shared);
|
||||
|
||||
// Show modal editor
|
||||
this._showEditor(id);
|
||||
@@ -182,7 +225,8 @@ View.prototype = {
|
||||
attachts: this._editableAttachts(),
|
||||
color: this._editableColor(),
|
||||
pinned: this._editablePinned(),
|
||||
tags: this._editableTags()
|
||||
tags: this._editableTags(),
|
||||
shares: this._editableShares()
|
||||
};
|
||||
var self = this;
|
||||
this._notes.update(fakeNote).done(function (note) {
|
||||
@@ -304,6 +348,7 @@ View.prototype = {
|
||||
t('quicknotes', 'Delete note'),
|
||||
function(result) {
|
||||
if (result) {
|
||||
if (!note.is_shared) {
|
||||
self._notes.remove(note).done(function () {
|
||||
if (self._notes.length() > 0) {
|
||||
$(".notes-grid").isotope('remove', gridnote.parent())
|
||||
@@ -316,6 +361,20 @@ View.prototype = {
|
||||
}).fail(function () {
|
||||
alert('Could not delete note, not found');
|
||||
});
|
||||
} else {
|
||||
self._notes.forgetShare(note).done(function () {
|
||||
if (self._notes.length() > 0) {
|
||||
$(".notes-grid").isotope('remove', gridnote.parent())
|
||||
.isotope('layout');
|
||||
self.showAll();
|
||||
self.renderNavigation();
|
||||
} else {
|
||||
self.render();
|
||||
}
|
||||
}).fail(function () {
|
||||
alert('Could not delete note, not found');
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
true
|
||||
@@ -454,6 +513,20 @@ View.prototype = {
|
||||
$('#modal-note-div #tag-button').trigger( "click");
|
||||
});
|
||||
|
||||
// handle tags button.
|
||||
$('#modal-note-div #share-button').click(function (event) {
|
||||
event.stopPropagation();
|
||||
QnDialogs.shares(
|
||||
self._notes.getUsersSharing(),
|
||||
self._editableShares(),
|
||||
function(result, newShares) {
|
||||
if (result === true) {
|
||||
self._editableShares(newShares, []);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// handle attach button.
|
||||
$('#modal-note-div #attach-button').click(function (event) {
|
||||
event.stopPropagation();
|
||||
@@ -465,7 +538,7 @@ View.prototype = {
|
||||
preview_url: OC.generateUrl('core') + '/preview.png?file=' + encodeURI(datapath) + '&x=512&y=512',
|
||||
redirect_url: OC.generateUrl('/apps/files/?dir={dir}&scrollto={scrollto}', {dir: fileInfo.path, scrollto: fileInfo.name})
|
||||
});
|
||||
self._editableAttachts(attachts);
|
||||
self._editableAttachts(attachts, true);
|
||||
}).fail(() => {
|
||||
console.log("ERRORRR");
|
||||
});
|
||||
@@ -483,13 +556,16 @@ View.prototype = {
|
||||
if (result === true) {
|
||||
self._editableTags(newTags);
|
||||
}
|
||||
},
|
||||
true,
|
||||
t('quicknotes', 'Tags'),
|
||||
false
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// handle cancel editing notes.
|
||||
$('#modal-note-div #close-button').click(function (event) {
|
||||
event.stopPropagation();
|
||||
self.cancelEdit();
|
||||
});
|
||||
|
||||
// handle cancel editing notes.
|
||||
$('#modal-note-div #cancel-button').click(function (event) {
|
||||
event.stopPropagation();
|
||||
@@ -516,36 +592,13 @@ View.prototype = {
|
||||
|
||||
$('#app-navigation ul').html(html);
|
||||
|
||||
// show all notes
|
||||
$('#all-notes').click(function () {
|
||||
$('.notes-grid').isotope({ filter: '*'});
|
||||
/* Create a new note */
|
||||
|
||||
var oldColorTool = $('#app-navigation .circle-toolbar.icon-checkmark');
|
||||
$.each(oldColorTool, function(i, oct) {
|
||||
$(oct).removeClass('icon-checkmark');
|
||||
});
|
||||
$('#app-navigation .any-color').addClass('icon-checkmark');
|
||||
});
|
||||
|
||||
$('#shared-with-you').click(function () {
|
||||
$('.notes-grid').isotope({ filter: function() {
|
||||
return $(this).children().hasClass('shared');
|
||||
} });
|
||||
});
|
||||
|
||||
$('#shared-by-you').click(function () {
|
||||
$('.notes-grid').isotope({ filter: function() {
|
||||
return $(this).children().hasClass('shareowner');
|
||||
} });
|
||||
});
|
||||
|
||||
// create a new note
|
||||
var self = this;
|
||||
$('#new-note').click(function () {
|
||||
var fakenote = {
|
||||
title: t('quicknotes', 'New note'),
|
||||
content: '',
|
||||
color: '#F7EB96'
|
||||
content: ''
|
||||
};
|
||||
self._notes.create(fakenote).done(function(note) {
|
||||
if (self._notes.length() > 1) {
|
||||
@@ -564,6 +617,38 @@ View.prototype = {
|
||||
});
|
||||
});
|
||||
|
||||
/* Show all notes */
|
||||
|
||||
$('#all-notes').click(function () {
|
||||
$('.notes-grid').isotope({ filter: '*'});
|
||||
|
||||
var oldColorTool = $('#colors-folder .circle-toolbar.icon-checkmark');
|
||||
$.each(oldColorTool, function(i, oct) {
|
||||
$(oct).removeClass('icon-checkmark');
|
||||
});
|
||||
$('#app-navigation .any-color').addClass('icon-checkmark');
|
||||
});
|
||||
|
||||
/* Shares Navigation */
|
||||
|
||||
$('#shared-folder').click(function () {
|
||||
$(this).toggleClass("open");
|
||||
});
|
||||
|
||||
$('#shared-with-you').click(function (event) {
|
||||
event.stopPropagation();
|
||||
$('.notes-grid').isotope({ filter: function() {
|
||||
return $(this).children().hasClass('shared');
|
||||
} });
|
||||
});
|
||||
|
||||
$('#shared-by-you').click(function (event) {
|
||||
event.stopPropagation();
|
||||
$('.notes-grid').isotope({ filter: function() {
|
||||
return $(this).children().hasClass('shareowner');
|
||||
} });
|
||||
});
|
||||
|
||||
/* Colors Navigation */
|
||||
|
||||
$('#colors-folder').click(function () {
|
||||
@@ -574,9 +659,9 @@ View.prototype = {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
$('#app-navigation .circle-toolbar').click(function (event) {
|
||||
$('#colors-folder .circle-toolbar').click(function (event) {
|
||||
event.stopPropagation();
|
||||
var oldColorTool = $('#app-navigation .circle-toolbar.icon-checkmark');
|
||||
var oldColorTool = $('#colors-folder .circle-toolbar.icon-checkmark');
|
||||
$.each(oldColorTool, function(i, oct) {
|
||||
$(oct).removeClass('icon-checkmark');
|
||||
});
|
||||
@@ -636,8 +721,48 @@ View.prototype = {
|
||||
$(oct).removeClass('icon-checkmark');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
},
|
||||
renderSettings: function () {
|
||||
/* Render view */
|
||||
var html = Handlebars.templates['settings']({});
|
||||
$('#app-settings-content').html(html);
|
||||
var self = this;
|
||||
$.get(OC.generateUrl('apps/quicknotes/getuservalue'), {'type': 'default_color'})
|
||||
.done(function (response) {
|
||||
var color = response.value;;
|
||||
var colors = $("#setting-defaul-color")[0].getElementsByClassName("circle-toolbar");
|
||||
$.each(colors, function(i, c) {
|
||||
if (color === self._colorToHex(c.style.backgroundColor)) {
|
||||
c.className += " icon-checkmark";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/* Settings */
|
||||
|
||||
$("#app-settings-content").off();
|
||||
|
||||
$('#app-settings-content').on('click', '.circle-toolbar', function (event) {
|
||||
event.stopPropagation();
|
||||
|
||||
var currentColor = $(this);
|
||||
var color = self._colorToHex(currentColor.css("background-color"));
|
||||
|
||||
$.ajax({
|
||||
url: OC.generateUrl('apps/quicknotes/setuservalue'),
|
||||
type: 'POST',
|
||||
data: {
|
||||
'type': 'default_color',
|
||||
'value': color
|
||||
},
|
||||
success: function (response) {
|
||||
$('#setting-defaul-color .circle-toolbar').removeClass('icon-checkmark');
|
||||
currentColor.addClass('icon-checkmark');
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Some 'private' functions as helpers.
|
||||
*/
|
||||
@@ -655,6 +780,25 @@ View.prototype = {
|
||||
|
||||
return digits[1] + '#' + rgb.toString(16).toUpperCase();
|
||||
},
|
||||
_isEditable: function(editable) {
|
||||
if (editable === undefined)
|
||||
return $('#title-editable').prop('contenteditable');
|
||||
else {
|
||||
if (editable) {
|
||||
$('#modal-note-div .icon-header-note').show();
|
||||
$('#title-editable').prop('contenteditable', true);
|
||||
$('#modal-note-div .note-options').show();
|
||||
$('#modal-note-div .note-disable-options').hide();
|
||||
this._initEditor();
|
||||
} else {
|
||||
$('#modal-note-div .icon-header-note').hide();
|
||||
$('#title-editable').removeAttr("contentEditable");
|
||||
$('#content-editable').removeAttr("contentEditable");
|
||||
$('#modal-note-div .note-options').hide();
|
||||
$('#modal-note-div .note-disable-options').show();
|
||||
}
|
||||
}
|
||||
},
|
||||
_editableId: function(id) {
|
||||
if (id === undefined)
|
||||
return $("#modal-note-div .quicknote").data('id');
|
||||
@@ -706,6 +850,19 @@ View.prototype = {
|
||||
$("#modal-note-div .quicknote").css("background-color", color);
|
||||
}
|
||||
},
|
||||
_editableShares: function(shared_with, shared_by) {
|
||||
if (shared_with === undefined) {
|
||||
return $("#modal-note-div .slim-share").toArray().map(function (value) {
|
||||
return {
|
||||
id: value.getAttribute('share-id'),
|
||||
name: value.textContent.trim()
|
||||
};
|
||||
});
|
||||
} else {
|
||||
var html = Handlebars.templates['shares']({ shared_by: shared_by, shared_with: shared_with});
|
||||
$("#modal-note-div .note-shares").replaceWith(html);
|
||||
}
|
||||
},
|
||||
_editableTags: function(tags) {
|
||||
if (tags === undefined) {
|
||||
return $("#modal-note-div .slim-tag").toArray().map(function (value) {
|
||||
@@ -719,7 +876,7 @@ View.prototype = {
|
||||
$("#modal-note-div .note-tags").replaceWith(html);
|
||||
}
|
||||
},
|
||||
_editableAttachts: function(attachts) {
|
||||
_editableAttachts: function(attachts, can_delete) {
|
||||
if (attachts === undefined) {
|
||||
return $("#modal-note-div .note-attach").toArray().map(function (value) {
|
||||
return {
|
||||
@@ -729,7 +886,7 @@ View.prototype = {
|
||||
};
|
||||
});
|
||||
} else {
|
||||
var html = Handlebars.templates['attachts']({ attachts: attachts});
|
||||
var html = Handlebars.templates['attachts']({ attachts: attachts, can_delete: can_delete});
|
||||
$("#modal-note-div .note-attachts").replaceWith(html);
|
||||
|
||||
lozad('.attach-preview').observe();
|
||||
@@ -797,8 +954,10 @@ View.prototype = {
|
||||
this._editor = editor;
|
||||
},
|
||||
_destroyEditor: function() {
|
||||
if (this._editor != undefined) {
|
||||
this._editor.destroy();
|
||||
this._editor = undefined;
|
||||
}
|
||||
this._changed = false;
|
||||
|
||||
this._editableId(-1);
|
||||
@@ -821,7 +980,6 @@ View.prototype = {
|
||||
"left" : note.offset().left,
|
||||
"top" : note.offset().top,
|
||||
"width" : note.width(),
|
||||
"min-height": note.height(),
|
||||
"height:" : "auto"
|
||||
});
|
||||
|
||||
@@ -893,6 +1051,7 @@ View.prototype = {
|
||||
render: function () {
|
||||
this.renderNavigation();
|
||||
this.renderContent();
|
||||
this.renderSettings();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -926,6 +1085,19 @@ new OCA.Search(search, function() {
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Add Helpers to handlebars
|
||||
*/
|
||||
|
||||
Handlebars.registerHelper('tSW', function(user) {
|
||||
return t('quicknotes', 'Shared with {user}', {user: user});
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('tSB', function(user) {
|
||||
return t('quicknotes', 'Shared by {user}', {user: user});
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Create modules
|
||||
*/
|
||||
@@ -941,8 +1113,7 @@ view.renderContent();
|
||||
* Loading notes and render final view.
|
||||
*/
|
||||
notes.load().done(function () {
|
||||
view.renderNavigation();
|
||||
view.renderContent();
|
||||
view.render();
|
||||
}).fail(function () {
|
||||
alert('Could not load notes');
|
||||
});
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
<a target="_blank" href="{{redirect_url}}">
|
||||
<div class="attach-preview note-attach" attach-file-id="{{file_id}}" data-background-image="{{preview_url}}"/>
|
||||
</a>
|
||||
{{#if ../can_delete}}
|
||||
<div class="attach-remove icon-delete" title="{{t "quicknotes" "Delete attachment"}}"/>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@@ -8,6 +8,18 @@
|
||||
{{allNotesTxt}}
|
||||
</a>
|
||||
</li>
|
||||
<li id="shared-folder" class="collapsible open">
|
||||
<button class="collapse"></button>
|
||||
<a href="#" class="icon-share svg">{{t "quicknotes" "Shared" }}</a>
|
||||
<ul>
|
||||
<li id="shared-by-you">
|
||||
<a href="#" class="icon-share svg">{{t "quicknotes" "Shared with others" }}</a>
|
||||
</li>
|
||||
<li id="shared-with-you">
|
||||
<a href="#" class="icon-share svg">{{t "quicknotes" "Shared with you" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="colors-folder" class="collapsible open">
|
||||
<button class="collapse"></button>
|
||||
<a href="#" class="icon-search svg">{{colorsTxt}}</a>
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
<div class="note-grid-item">
|
||||
<div class="quicknote noselect {{#if active}}note-active{{/if}} {{#if isshared}}shared{{/if}} {{#if sharedwith}}shareowner{{/if}}" style="background-color: {{color}}" data-id="{{ id }}" data-timestamp="{{ timestamp }}" >
|
||||
{{#if isshared}}
|
||||
<div>
|
||||
<div class='icon-share shared-title' title="Shared by {{ userid }}"></div>
|
||||
<div class='note-title'>
|
||||
{{{ title }}}
|
||||
</div>
|
||||
</div>
|
||||
<div id='content' class='note-content'>
|
||||
{{{ content }}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="quicknote noselect {{#if is_shared}}shared{{/if}} {{#if shared_with.length}}shareowner{{/if}}" style="background-color: {{color}}" data-id="{{ id }}" data-timestamp="{{ timestamp }}" >
|
||||
<div class='note-header'>
|
||||
<div class='note-attachts'>
|
||||
{{#each attachts}}
|
||||
@@ -28,11 +17,6 @@
|
||||
<div class="icon-header-note icon-pin hide-header-icon" title="{{t "quicknotes" "Pin note"}}"></div>
|
||||
{{/if}}
|
||||
<div class="icon-header-note icon-delete hide-header-icon icon-delete-note" title="{{t "quicknotes" "Delete note"}}"></div>
|
||||
<!--
|
||||
{{#if sharedwith}}
|
||||
<div class='icon-share shared-title-owner' title="Shared with {{ sharedwith }}"></div>
|
||||
{{/if}}
|
||||
-->
|
||||
<div class='note-title'>
|
||||
{{{ title }}}
|
||||
</div>
|
||||
@@ -40,12 +24,16 @@
|
||||
<div class='note-content'>
|
||||
{{{ content }}}
|
||||
</div>
|
||||
<div class='note-shares'>
|
||||
{{#each shared_with}}
|
||||
<div class="icon-user slim-share" share-id="{{ shared_user }}" title="Shared with {{ shared_user }}">{{{ shared_user }}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class='note-tags'>
|
||||
{{#each tags}}
|
||||
<div class="icon-tag slim-tag" tag-id="{{ id }}">{{{ name }}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,18 +2,7 @@
|
||||
<div id="notes-grid-div" class="notes-grid">
|
||||
{{#each notes}}
|
||||
<div class="note-grid-item">
|
||||
<div class="quicknote noselect {{#if isshared}}shared{{/if}} {{#if sharedwith}}shareowner{{/if}}" style="background-color: {{color}}" data-id="{{ id }}" data-timestamp="{{ timestamp }}" >
|
||||
{{#if isshared}}
|
||||
<div>
|
||||
<div class='icon-share shared-title' title="Shared by {{ userid }}"></div>
|
||||
<div class='note-title'>
|
||||
{{{ title }}}
|
||||
</div>
|
||||
</div>
|
||||
<div id='content' class='note-content'>
|
||||
{{{ content }}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="quicknote noselect {{#if is_shared}}shared{{/if}} {{#if shared_with.length}}shareowner{{/if}}" style="background-color: {{color}}" data-id="{{ id }}" data-timestamp="{{ timestamp }}" >
|
||||
<div class='note-header'>
|
||||
<div class='note-attachts'>
|
||||
{{#each attachts}}
|
||||
@@ -25,17 +14,17 @@
|
||||
</div>
|
||||
<div class='note-body'>
|
||||
<div>
|
||||
{{#if is_shared}}
|
||||
<div class="icon-header-note icon-share" title="{{tSB userid }}"></div>
|
||||
<div class="icon-header-note icon-delete hide-header-icon icon-delete-note" title="{{t "quicknotes" "Delete note"}}"></div>
|
||||
{{else}}
|
||||
{{#if ispinned}}
|
||||
<div class="icon-header-note icon-pinned fixed-header-icon" title="{{t "quicknotes" "Unpin note"}}"></div>
|
||||
{{else}}
|
||||
<div class="icon-header-note icon-pin hide-header-icon" title="{{t "quicknotes" "Pin note"}}"></div>
|
||||
{{/if}}
|
||||
<div class="icon-header-note icon-delete hide-header-icon icon-delete-note" title="{{t "quicknotes" "Delete note"}}"></div>
|
||||
<!--
|
||||
{{#if sharedwith}}
|
||||
<div class='icon-share shared-title-owner' title="Shared with {{ sharedwith }}"></div>
|
||||
{{/if}}
|
||||
-->
|
||||
<div class='note-title'>
|
||||
{{{ title }}}
|
||||
</div>
|
||||
@@ -43,6 +32,11 @@
|
||||
<div class='note-content'>
|
||||
{{{ content }}}
|
||||
</div>
|
||||
<div class='note-shares'>
|
||||
{{#each shared_with}}
|
||||
<div class="icon-user slim-share" share-id="{{ shared_user }}" title="{{tSW shared_user}}">{{{ shared_user }}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class='note-tags'>
|
||||
{{#each tags}}
|
||||
<div class='icon-tag slim-tag' tag-id="{{ id }}">
|
||||
@@ -51,7 +45,6 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
@@ -68,6 +61,7 @@
|
||||
<div contenteditable="true" id='title-editable' class='note-title'></div>
|
||||
</div>
|
||||
<div contenteditable="true" id='content-editable' class='note-content'></div>
|
||||
<div class='note-shares'></div>
|
||||
<div class='note-tags'></div>
|
||||
</div>
|
||||
<div class="note-options">
|
||||
@@ -87,9 +81,9 @@
|
||||
<a href="#" class="circle-toolbar" style="background-color: #CECECE"></a>
|
||||
</div>
|
||||
<div class="buttons-toolbar">
|
||||
<!--
|
||||
<button id='share-button'><?php p($l->t('Share'));?></button>
|
||||
-->
|
||||
<button id='share-button' class='round-tool-button'>
|
||||
<div class="icon-shared" title="{{t "quicknotes" "Share note"}}"></div>
|
||||
</button>
|
||||
<button id='attach-button' class='round-tool-button'>
|
||||
<div class="icon-picture" title="{{t "quicknotes" "Attach file"}}"></div>
|
||||
</button>
|
||||
@@ -105,7 +99,11 @@
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
<div class="note-disable-options">
|
||||
<div class="buttons-toolbar">
|
||||
<button id='close-button'>{{t "quicknotes" "Close"}}</button>
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
19
js/templates/settings.handlebars
Normal file
19
js/templates/settings.handlebars
Normal file
@@ -0,0 +1,19 @@
|
||||
<div>
|
||||
<label>{{t "quicknotes" "Default color for new notes"}}</label>
|
||||
</div>
|
||||
<div id="setting-defaul-color">
|
||||
<div id="defaultColor" style="display: flex; justify-content: center;">
|
||||
<div class="colors-toolbar">
|
||||
<a href="#" class="circle-toolbar" style="background-color: #F7EB96"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #88B7E3"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #C1ECB0"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #BFA6E9"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #DAF188"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #FF96AC"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #FCF66F"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #F2F1EF"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #C1D756"></a>
|
||||
<a href="#" class="circle-toolbar" style="background-color: #CECECE"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
5
js/templates/shares.handlebars
Normal file
5
js/templates/shares.handlebars
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class='note-shares'>
|
||||
{{#each shared_with}}
|
||||
<div class="icon-user slim-share" share-id="{{ shared_user }}" title="{{tSW shared_user}}">{{{ shared_user }}}</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
@@ -91,7 +91,7 @@ class NoteController extends Controller {
|
||||
* @param string $content
|
||||
* @param string $color
|
||||
*/
|
||||
public function create($title, $content, $color = "#F7EB96") {
|
||||
public function create($title, $content, $color = NULL) {
|
||||
$note = $this->noteService->create($this->userId, $title, $content, $color);
|
||||
|
||||
$etag = md5(json_encode($note));
|
||||
@@ -111,10 +111,11 @@ class NoteController extends Controller {
|
||||
* @param array $attachts
|
||||
* @param bool $pinned
|
||||
* @param array $tags
|
||||
* @param array $shares
|
||||
* @param string $color
|
||||
*/
|
||||
public function update(int $id, string $title, string $content, array $attachts, bool $pinned, array $tags, string $color = "#F7EB96"): JSONResponse {
|
||||
$note = $this->noteService->update($this->userId, $id, $title, $content, $attachts, $pinned, $tags, $color);
|
||||
public function update(int $id, string $title, string $content, array $attachts, bool $pinned, array $tags, array $shares, string $color = "#F7EB96"): JSONResponse {
|
||||
$note = $this->noteService->update($this->userId, $id, $title, $content, $attachts, $pinned, $tags, $shares, $color);
|
||||
if (is_null($note)) {
|
||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
112
lib/Controller/SettingsController.php
Normal file
112
lib/Controller/SettingsController.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2020 Matias De lellis <mati86dl@gmail.com>
|
||||
*
|
||||
* @author Matias De lellis <mati86dl@gmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\QuickNotes\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
use OCA\QuickNotes\Service\SettingsService;
|
||||
|
||||
|
||||
class SettingsController extends Controller {
|
||||
|
||||
/** @var SettingsService */
|
||||
private $settingsService;
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
const STATE_OK = 0;
|
||||
const STATE_FALSE = 1;
|
||||
const STATE_SUCCESS = 2;
|
||||
const STATE_ERROR = 3;
|
||||
|
||||
public function __construct ($appName,
|
||||
IRequest $request,
|
||||
SettingsService $settingsService,
|
||||
$userId)
|
||||
{
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->appName = $appName;
|
||||
$this->settingsService = $settingsService;
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $type
|
||||
* @param $value
|
||||
* @return JSONResponse
|
||||
*/
|
||||
public function setUserValue($type, $value) {
|
||||
$status = self::STATE_SUCCESS;
|
||||
|
||||
switch ($type) {
|
||||
case SettingsService::COLOR_FOR_NEW_NOTES_KEY:
|
||||
$this->settingsService->setColorForNewNotes($value);
|
||||
break;
|
||||
default:
|
||||
$status = self::STATE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
// Response
|
||||
$result = [
|
||||
'status' => $status,
|
||||
'value' => $value
|
||||
];
|
||||
|
||||
return new JSONResponse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $type
|
||||
* @return JSONResponse
|
||||
*/
|
||||
public function getUserValue($type) {
|
||||
$status = self::STATE_OK;
|
||||
$value ='nodata';
|
||||
|
||||
switch ($type) {
|
||||
case SettingsService::COLOR_FOR_NEW_NOTES_KEY:
|
||||
$value = $this->settingsService->getColorForNewNotes($this->userId);
|
||||
break;
|
||||
default:
|
||||
$status = self::STATE_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
$result = [
|
||||
'status' => $status,
|
||||
'value' => $value
|
||||
];
|
||||
|
||||
return new JSONResponse($result);
|
||||
}
|
||||
|
||||
}
|
||||
68
lib/Controller/ShareController.php
Normal file
68
lib/Controller/ShareController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright 2020 Matias De lellis <mati86dl@gmail.com>
|
||||
*
|
||||
* @author 2020 Matias De lellis <mati86dl@gmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace OCA\QuickNotes\Controller;
|
||||
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\Controller;
|
||||
|
||||
use OCP\IRequest;
|
||||
|
||||
use OCA\QuickNotes\Db\NoteShare;
|
||||
use OCA\QuickNotes\Db\NoteShareMapper;
|
||||
|
||||
|
||||
class ShareController extends Controller {
|
||||
|
||||
private $noteShareMapper;
|
||||
private $userId;
|
||||
|
||||
public function __construct($AppName,
|
||||
IRequest $request,
|
||||
NoteShareMapper $noteShareMapper,
|
||||
$userId)
|
||||
{
|
||||
parent::__construct($AppName, $request);
|
||||
|
||||
$this->noteShareMapper = $noteShareMapper;
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param int $noteId
|
||||
*/
|
||||
public function destroy(int $noteId): JSONResponse {
|
||||
try {
|
||||
$noteShare = $this->noteShareMapper->findByNoteAndUser($noteId, $this->userId);
|
||||
} catch (DoesNotExistException $e) {
|
||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
$this->noteShareMapper->delete($noteShare);
|
||||
|
||||
return new JSONResponse([]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -73,8 +73,7 @@ class AttachMapper extends QBMapper {
|
||||
* @param string $userId
|
||||
* @param int $noteId
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result
|
||||
* @return Note[]
|
||||
* @return Attach[]
|
||||
*/
|
||||
public function findFromNote($userId, $noteId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -86,4 +85,5 @@ class AttachMapper extends QBMapper {
|
||||
);
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ class Note extends Entity implements JsonSerializable {
|
||||
protected $timestamp;
|
||||
protected $colorId;
|
||||
protected $userId;
|
||||
protected $sharedWith;
|
||||
protected $sharedWith = [];
|
||||
protected $sharedBy = [];
|
||||
protected $isShared;
|
||||
protected $tags;
|
||||
protected $attachts;
|
||||
@@ -40,8 +41,9 @@ class Note extends Entity implements JsonSerializable {
|
||||
'colorid' => $this->colorId,
|
||||
'color' => $this->color,
|
||||
'userid' => $this->userId,
|
||||
'sharedwith' => $this->sharedWith,
|
||||
'isshared' => $this->isShared,
|
||||
'shared_with' => $this->sharedWith,
|
||||
'shared_by' => $this->sharedBy,
|
||||
'is_shared' => $this->isShared,
|
||||
'tags' => $this->tags,
|
||||
'attachts' => $this->attachts
|
||||
];
|
||||
|
||||
@@ -31,6 +31,22 @@ class NoteMapper extends QBMapper {
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result
|
||||
* @return Note
|
||||
*/
|
||||
public function findShared($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->tableName)
|
||||
->where(
|
||||
$qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))
|
||||
);
|
||||
return $this->findEntity($qb);
|
||||
}
|
||||
|
||||
public function findAll($userId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
|
||||
@@ -8,15 +8,18 @@ use OCP\AppFramework\Db\Entity;
|
||||
class NoteShare extends Entity implements JsonSerializable {
|
||||
|
||||
protected $noteId;
|
||||
protected $userId;
|
||||
protected $sharedUser;
|
||||
protected $sharedGroup;
|
||||
|
||||
public function jsonSerialize() {
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'noteid' => $this->noteId,
|
||||
'shareduser' => $this->sharedUser,
|
||||
'sharedgroup' => $this->sharedGroup
|
||||
'user_id' => $this->userId,
|
||||
'note_id' => $this->noteId,
|
||||
'shared_user' => $this->sharedUser,
|
||||
'shared_group' => $this->sharedGroup
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,4 +45,14 @@ class NoteShareMapper extends Mapper {
|
||||
$sql = 'DELETE FROM *PREFIX*quicknotes_shares WHERE note_id = ?';
|
||||
$this->execute($sql, [$noteId]);
|
||||
}
|
||||
|
||||
public function existsByNoteAndUser($noteId, $userId) {
|
||||
$sql = 'SELECT * FROM *PREFIX*quicknotes_shares WHERE shared_user = ? AND note_id = ?';
|
||||
try {
|
||||
return $this->findEntities($sql, [$userId, $noteId]);
|
||||
} catch (DoesNotExistException $e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,13 +57,16 @@ class FileService {
|
||||
* @param int $fileId file id to show
|
||||
* @param int $sideSize side lenght to show
|
||||
*/
|
||||
public function getPreviewUrl(int $fileId, int $sideSize): string {
|
||||
public function getPreviewUrl(int $fileId, int $sideSize): ?string {
|
||||
$userFolder = $this->rootFolder->getUserFolder($this->userId);
|
||||
$node = current($userFolder->getById($fileId));
|
||||
$path = $userFolder->getRelativePath($node->getPath());
|
||||
$file = current($userFolder->getById($fileId));
|
||||
|
||||
if (!($file instanceof File)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreview', [
|
||||
'file' => $path,
|
||||
'file' => $userFolder->getRelativePath($file->getPath()),
|
||||
'x' => $sideSize,
|
||||
'y' => $sideSize
|
||||
]);
|
||||
@@ -78,7 +81,7 @@ class FileService {
|
||||
$userFolder = $this->rootFolder->getUserFolder($this->userId);
|
||||
$file = current($userFolder->getById($fileId));
|
||||
|
||||
if(!($file instanceof File)) {
|
||||
if (!($file instanceof File)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,26 +48,29 @@ class NoteService {
|
||||
private $notemapper;
|
||||
private $notetagmapper;
|
||||
private $colormapper;
|
||||
private $notesharemapper;
|
||||
private $noteShareMapper;
|
||||
private $attachMapper;
|
||||
private $tagmapper;
|
||||
private $fileService;
|
||||
private $settingsService;
|
||||
|
||||
public function __construct(NoteMapper $notemapper,
|
||||
NoteTagMapper $notetagmapper,
|
||||
NoteShareMapper $notesharemapper,
|
||||
NoteShareMapper $noteShareMapper,
|
||||
ColorMapper $colormapper,
|
||||
AttachMapper $attachMapper,
|
||||
TagMapper $tagmapper,
|
||||
FileService $fileService)
|
||||
FileService $fileService,
|
||||
SettingsService $settingsService)
|
||||
{
|
||||
$this->notemapper = $notemapper;
|
||||
$this->notetagmapper = $notetagmapper;
|
||||
$this->colormapper = $colormapper;
|
||||
$this->notesharemapper = $notesharemapper;
|
||||
$this->noteShareMapper = $noteShareMapper;
|
||||
$this->attachMapper = $attachMapper;
|
||||
$this->tagmapper = $tagmapper;
|
||||
$this->fileService = $fileService;
|
||||
$this->settingsService = $settingsService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,57 +78,62 @@ class NoteService {
|
||||
*/
|
||||
public function getAll(string $userId): array {
|
||||
$notes = $this->notemapper->findAll($userId);
|
||||
|
||||
// Set shares with others.
|
||||
foreach($notes as $note) {
|
||||
$note->setIsShared(false);
|
||||
$sharedWith = $this->notesharemapper->getSharesForNote($note->getId());
|
||||
if(count($sharedWith) > 0) {
|
||||
$shareList = array();
|
||||
foreach($sharedWith as $share) {
|
||||
$shareList[] = $share->getSharedUser();
|
||||
}
|
||||
$note->setSharedWith(implode(", ", $shareList));
|
||||
} else {
|
||||
$note->setSharedWith(null);
|
||||
}
|
||||
$note->setTags($this->tagmapper->getTagsForNote($userId, $note->getId()));
|
||||
}
|
||||
$shareEntries = $this->notesharemapper->findForUser($userId);
|
||||
$shares = array();
|
||||
foreach($shareEntries as $entry) {
|
||||
try {
|
||||
//find is only to check if current user is owner
|
||||
$this->notemapper->find($entry->getNoteId(), $userId);
|
||||
//user is owner, nothing to do
|
||||
} catch(\OCP\AppFramework\Db\DoesNotExistException $e) {
|
||||
$share = $this->notemapper->findById($entry->getNoteId());
|
||||
$share->setIsShared(true);
|
||||
$shares[] = $share;
|
||||
$note->setSharedWith($this->noteShareMapper->getSharesForNote($note->getId()));
|
||||
}
|
||||
|
||||
// Get shares from others.
|
||||
$shares = [];
|
||||
$sharedEntries = $this->noteShareMapper->findForUser($userId);
|
||||
foreach($sharedEntries as $sharedEntry) {
|
||||
$sharedNote = $this->notemapper->findShared($sharedEntry->getNoteId());
|
||||
$sharedNote->setIsShared(true);
|
||||
|
||||
$sharedEntry->setUserId($sharedNote->getUserId());
|
||||
$sharedNote->setSharedBy([$sharedEntry]);
|
||||
$shares[] = $sharedNote;
|
||||
}
|
||||
|
||||
// Attahch shared notes from others to same response
|
||||
$notes = array_merge($notes, $shares);
|
||||
|
||||
foreach ($notes as $note) {
|
||||
$note->setTitle(strip_tags($note->getTitle()));
|
||||
// Set tags to response.
|
||||
foreach($notes as $note) {
|
||||
$note->setTags($this->tagmapper->getTagsForNote($userId, $note->getId()));
|
||||
}
|
||||
|
||||
// Insert true color to response
|
||||
// Insert color to response
|
||||
foreach ($notes as $note) {
|
||||
$note->setColor($this->colormapper->find($note->getColorId())->getColor());
|
||||
}
|
||||
|
||||
// Insert true color to response
|
||||
// Insert pin to response
|
||||
foreach ($notes as $note) {
|
||||
$note->setIsPinned($note->getPinned() ? true : false);
|
||||
}
|
||||
|
||||
// Insert true attachts to response
|
||||
// Insert attachts to response.
|
||||
foreach ($notes as $note) {
|
||||
$attachts = $this->attachMapper->findFromNote($userId, $note->getId());
|
||||
$rAttachts = [];
|
||||
$attachts = $this->attachMapper->findFromNote($note->getUserId(), $note->getId());
|
||||
foreach ($attachts as $attach) {
|
||||
$attach->setPreviewUrl($this->fileService->getPreviewUrl($attach->getFileId(), 512));
|
||||
$attach->setRedirectUrl($this->fileService->getRedirectToFileUrl($attach->getFileId()));
|
||||
$previewUrl = $this->fileService->getPreviewUrl($attach->getFileId(), 512);
|
||||
if (is_null($previewUrl))
|
||||
continue;
|
||||
|
||||
$redirectUrl = $this->fileService->getRedirectToFileUrl($attach->getFileId());
|
||||
if (is_null($redirectUrl))
|
||||
continue;
|
||||
|
||||
$attach->setPreviewUrl($previewUrl);
|
||||
$attach->setRedirectUrl($redirectUrl);
|
||||
|
||||
$rAttachts[] = $attach;
|
||||
}
|
||||
$note->setAttachts($attachts);
|
||||
$note->setAttachts($rAttachts);
|
||||
}
|
||||
|
||||
return $notes;
|
||||
@@ -149,7 +157,11 @@ class NoteService {
|
||||
* @param string $content
|
||||
* @param string $color
|
||||
*/
|
||||
public function create(string $userId, string $title, string $content, string $color = "#F7EB96"): Note {
|
||||
public function create(string $userId, string $title, string $content, string $color = NULL): Note {
|
||||
if (is_null($color)) {
|
||||
$color = $this->settingsService->getColorForNewNotes();
|
||||
}
|
||||
|
||||
// Get color or append it
|
||||
if ($this->colormapper->colorExists($color)) {
|
||||
$hcolor = $this->colormapper->findByColor($color);
|
||||
@@ -187,6 +199,7 @@ class NoteService {
|
||||
* @param array $attachts
|
||||
* @param bool $pinned
|
||||
* @param array $tags
|
||||
* @param array $shares
|
||||
* @param string $color
|
||||
*/
|
||||
public function update(string $userId,
|
||||
@@ -196,14 +209,14 @@ class NoteService {
|
||||
array $attachts,
|
||||
bool $pinned,
|
||||
array $tags,
|
||||
string $color): Note
|
||||
array $shares,
|
||||
string $color): ?Note
|
||||
{
|
||||
// Get current Note and Color.
|
||||
try {
|
||||
$note = $this->notemapper->find($id, $userId);
|
||||
} catch(Exception $e) {
|
||||
$note = $this->get($userId, $id);
|
||||
if (is_null($note))
|
||||
return null;
|
||||
}
|
||||
|
||||
$oldcolorid = $note->getColorId();
|
||||
|
||||
// Get new Color or append it.
|
||||
@@ -242,6 +255,31 @@ class NoteService {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete old shares
|
||||
$dbShares = $this->noteShareMapper->getSharesForNote($id);
|
||||
foreach ($dbShares as $dbShare) {
|
||||
$delete = true;
|
||||
foreach ($shares as $share) {
|
||||
if ($dbShare->getSharedUser() === $share['name']) {
|
||||
$delete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($delete) {
|
||||
$this->noteShareMapper->delete($dbShare);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new shares
|
||||
foreach ($shares as $share) {
|
||||
if (!$this->noteShareMapper->existsByNoteAndUser($id, $share['name'])) {
|
||||
$hShare = new NoteShare();
|
||||
$hShare->setNoteId($id);
|
||||
$hShare->setSharedUser($share['name']);
|
||||
$this->noteShareMapper->insert($hShare);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete old tag relations
|
||||
$dbTags = $this->tagmapper->getTagsForNote($userId, $id);
|
||||
foreach ($dbTags as $dbTag) {
|
||||
@@ -304,6 +342,10 @@ class NoteService {
|
||||
}
|
||||
$newnote->setAttachts($attachts);
|
||||
|
||||
// Fill shared with with others
|
||||
$newnote->setIsShared(false);
|
||||
$newnote->setSharedWith($this->noteShareMapper->getSharesForNote($newnote->getId()));
|
||||
|
||||
// Remove old color if necessary
|
||||
if (($oldcolorid !== $hcolor->getId()) &&
|
||||
(!$this->notemapper->colorIdCount($oldcolorid))) {
|
||||
@@ -330,7 +372,7 @@ class NoteService {
|
||||
}
|
||||
$oldcolorid = $note->getColorId();
|
||||
|
||||
$this->notesharemapper->deleteByNoteId($note->getId());
|
||||
$this->noteShareMapper->deleteByNoteId($note->getId());
|
||||
|
||||
// Delete note.
|
||||
$this->notemapper->delete($note);
|
||||
@@ -381,7 +423,7 @@ class NoteService {
|
||||
}
|
||||
$pos_users = array();
|
||||
$pos_groups = array();
|
||||
$shares = $this->notesharemapper->getSharesForNote($noteId);
|
||||
$shares = $this->noteShareMapper->getSharesForNote($noteId);
|
||||
foreach($shares as $s) {
|
||||
$shareType = $s->getSharedUser();
|
||||
if(strlen($shareType) !== 0) {
|
||||
@@ -406,14 +448,14 @@ class NoteService {
|
||||
$share = new NoteShare();
|
||||
$share->setSharedGroup($groupId);
|
||||
$share->setNoteId($noteId);
|
||||
$this->notesharemapper->insert($share);
|
||||
$this->noteShareMapper->insert($share);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function removeGroupShare($groupId, $noteId) {
|
||||
$share = $this->notesharemapper->findByNoteAndGroup($noteId, $groupId);
|
||||
$this->notesharemapper->delete($share);
|
||||
$share = $this->noteShareMapper->findByNoteAndGroup($noteId, $groupId);
|
||||
$this->noteShareMapper->delete($share);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -422,13 +464,13 @@ class NoteService {
|
||||
$share = new NoteShare();
|
||||
$share->setSharedUser($userId);
|
||||
$share->setNoteId($noteId);
|
||||
$this->notesharemapper->insert($share);
|
||||
$this->noteShareMapper->insert($share);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function removeUserShare($userId, $noteId) {
|
||||
$share = $this->notesharemapper->findByNoteAndUser($noteId, $userId);
|
||||
$this->notesharemapper->delete($share);
|
||||
$share = $this->noteShareMapper->findByNoteAndUser($noteId, $userId);
|
||||
$this->noteShareMapper->delete($share);
|
||||
}
|
||||
}
|
||||
|
||||
65
lib/Service/SettingsService.php
Normal file
65
lib/Service/SettingsService.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2020 Matias De lellis <mati86dl@gmail.com>
|
||||
*
|
||||
* @author Matias De lellis <mati86dl@gmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\QuickNotes\Service;
|
||||
|
||||
use OCA\QuickNotes\AppInfo\Application;
|
||||
|
||||
use OCP\IConfig;
|
||||
|
||||
class SettingsService {
|
||||
|
||||
/**
|
||||
* Settings keys and default values.
|
||||
*/
|
||||
const COLOR_FOR_NEW_NOTES_KEY = 'default_color';
|
||||
const DEFAULT_COLOR_FOR_NEW_NOTES = '#F7EB96';
|
||||
|
||||
/** @var IConfig Config */
|
||||
private $config;
|
||||
|
||||
/** @var string|null */
|
||||
private $userId;
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param string $userId
|
||||
*/
|
||||
public function __construct(IConfig $config,
|
||||
$userId)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
|
||||
public function getColorForNewNotes(): string {
|
||||
return $this->config->getUserValue($this->userId, Application::APP_NAME, self::COLOR_FOR_NEW_NOTES_KEY, self::DEFAULT_COLOR_FOR_NEW_NOTES);
|
||||
}
|
||||
|
||||
public function setColorForNewNotes(string $color) {
|
||||
$this->config->setUserValue($this->userId, Application::APP_NAME, self::COLOR_FOR_NEW_NOTES_KEY, $color);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,3 +4,9 @@
|
||||
*/
|
||||
p($l->t('Delete attachment'));
|
||||
p($l->t('Attach file'));
|
||||
p($l->t('Shared'));
|
||||
p($l->t('Shared with others'));
|
||||
p($l->t('Shared with you'));
|
||||
p($l->t('Share note'));
|
||||
p($l->t('Close'));
|
||||
p($l->t('Default color for new notes'));
|
||||
@@ -1,8 +1,8 @@
|
||||
<div id="app-settings">
|
||||
<div id="app-settings-header">
|
||||
<button class="settings-button"
|
||||
data-apps-slide-toggle="#app-settings-content"
|
||||
></button>
|
||||
<button class="settings-button" data-apps-slide-toggle="#app-settings-content">
|
||||
<?php p($l->t('Settings'));?>
|
||||
</button>
|
||||
</div>
|
||||
<div id="app-settings-content">
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user