Merge pull request #36 from matiasdelellis/shared-notes

Fix backend to shared notes, and initial fronted code.
This commit is contained in:
matiasdelellis
2020-06-17 10:44:23 -03:00
committed by GitHub
23 changed files with 839 additions and 175 deletions

View File

@@ -5,6 +5,28 @@ return ['resources' =>
'noteApi' => ['url' => '/api/v1/notes'] 'noteApi' => ['url' => '/api/v1/notes']
], ],
'routes' => [ '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'
]
] ]
]; ];

View File

@@ -226,7 +226,8 @@ div[contenteditable="true"] {
border: none; border: none;
} }
.note-options { .note-options,
.note-disable-options {
padding: 8px; padding: 8px;
padding-top: 0px; padding-top: 0px;
} }
@@ -249,6 +250,7 @@ div[contenteditable="true"] {
opacity: 0.5; opacity: 0.5;
} }
.slim-share,
.slim-tag { .slim-tag {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
@@ -260,14 +262,17 @@ div[contenteditable="true"] {
font-size: 90%; font-size: 90%;
} }
.slim-share:hover,
.slim-tag:hover { .slim-tag:hover {
background-color: rgba(0,0,0,0.12); background-color: rgba(0,0,0,0.12);
} }
.note-tags { .note-shares > .slim-share,
margin-top: 8px; .note-tags > .slim-tag {
margin-top: 5px;
} }
/* Restore defaults select2 rules */ /* Restore defaults select2 rules */
.select2-container-multi .select2-container-multi
@@ -294,6 +299,10 @@ div[contenteditable="true"] {
z-index: 10000; z-index: 10000;
} }
div.select2-container {
width: 100%;
}
/* Modal Content */ /* Modal Content */
.modal-content { .modal-content {

View File

@@ -56,6 +56,9 @@ const QnDialogs = {
data.push({id: item.id, text: item.name}); data.push({id: item.id, text: item.name});
}); });
return data; return data;
},
formatNoMatches: function() {
return t('quicknotes', 'No tags found');
} }
}); });
@@ -125,6 +128,113 @@ const QnDialogs = {
$('.select2-input').focus(); $('.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 () { _getMessageTemplate: function () {
var defer = $.Deferred(); var defer = $.Deferred();
if (!this.$messageTemplate) { if (!this.$messageTemplate) {

View File

@@ -29,6 +29,9 @@ var Notes = function (baseUrl) {
this._baseUrl = baseUrl; this._baseUrl = baseUrl;
this._notes = []; this._notes = [];
this._loaded = false; this._loaded = false;
this._usersSharing = [];
this._loadUsersSharing();
}; };
Notes.prototype = { Notes.prototype = {
@@ -71,6 +74,9 @@ Notes.prototype = {
}); });
return Ccolors; return Ccolors;
}, },
getUsersSharing: function () {
return this._usersSharing;
},
// Get the tags used in the notes // Get the tags used in the notes
getTags: function () { getTags: function () {
var tags = []; var tags = [];
@@ -136,6 +142,42 @@ Notes.prototype = {
deferred.reject(); deferred.reject();
}); });
return deferred.promise(); 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._editableContent(note.content);
this._editablePinned(note.ispinned); this._editablePinned(note.ispinned);
this._editableColor(note.color); this._editableColor(note.color);
this._editableShares(note.shared_with, note.shared_by);
this._editableTags(note.tags); this._editableTags(note.tags);
this._editableAttachts(note.attachts); this._editableAttachts(note.attachts, !note.is_shared);
// Create medium div editor. // Create medium div editor.
this._initEditor(); this._isEditable(!note.is_shared);
// Show modal editor // Show modal editor
this._showEditor(id); this._showEditor(id);
@@ -182,7 +225,8 @@ View.prototype = {
attachts: this._editableAttachts(), attachts: this._editableAttachts(),
color: this._editableColor(), color: this._editableColor(),
pinned: this._editablePinned(), pinned: this._editablePinned(),
tags: this._editableTags() tags: this._editableTags(),
shares: this._editableShares()
}; };
var self = this; var self = this;
this._notes.update(fakeNote).done(function (note) { this._notes.update(fakeNote).done(function (note) {
@@ -304,18 +348,33 @@ View.prototype = {
t('quicknotes', 'Delete note'), t('quicknotes', 'Delete note'),
function(result) { function(result) {
if (result) { if (result) {
self._notes.remove(note).done(function () { if (!note.is_shared) {
if (self._notes.length() > 0) { self._notes.remove(note).done(function () {
$(".notes-grid").isotope('remove', gridnote.parent()) if (self._notes.length() > 0) {
.isotope('layout'); $(".notes-grid").isotope('remove', gridnote.parent())
self.showAll(); .isotope('layout');
self.renderNavigation(); self.showAll();
} else { self.renderNavigation();
self.render(); } else {
} self.render();
}).fail(function () { }
alert('Could not delete note, not found'); }).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 true
@@ -454,6 +513,20 @@ View.prototype = {
$('#modal-note-div #tag-button').trigger( "click"); $('#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. // handle attach button.
$('#modal-note-div #attach-button').click(function (event) { $('#modal-note-div #attach-button').click(function (event) {
event.stopPropagation(); event.stopPropagation();
@@ -465,7 +538,7 @@ View.prototype = {
preview_url: OC.generateUrl('core') + '/preview.png?file=' + encodeURI(datapath) + '&x=512&y=512', 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}) redirect_url: OC.generateUrl('/apps/files/?dir={dir}&scrollto={scrollto}', {dir: fileInfo.path, scrollto: fileInfo.name})
}); });
self._editableAttachts(attachts); self._editableAttachts(attachts, true);
}).fail(() => { }).fail(() => {
console.log("ERRORRR"); console.log("ERRORRR");
}); });
@@ -483,13 +556,16 @@ View.prototype = {
if (result === true) { if (result === true) {
self._editableTags(newTags); 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. // handle cancel editing notes.
$('#modal-note-div #cancel-button').click(function (event) { $('#modal-note-div #cancel-button').click(function (event) {
event.stopPropagation(); event.stopPropagation();
@@ -516,36 +592,13 @@ View.prototype = {
$('#app-navigation ul').html(html); $('#app-navigation ul').html(html);
// show all notes /* Create a new note */
$('#all-notes').click(function () {
$('.notes-grid').isotope({ filter: '*'});
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; var self = this;
$('#new-note').click(function () { $('#new-note').click(function () {
var fakenote = { var fakenote = {
title: t('quicknotes', 'New note'), title: t('quicknotes', 'New note'),
content: '', content: ''
color: '#F7EB96'
}; };
self._notes.create(fakenote).done(function(note) { self._notes.create(fakenote).done(function(note) {
if (self._notes.length() > 1) { 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 Navigation */
$('#colors-folder').click(function () { $('#colors-folder').click(function () {
@@ -574,9 +659,9 @@ View.prototype = {
event.stopPropagation(); event.stopPropagation();
}); });
$('#app-navigation .circle-toolbar').click(function (event) { $('#colors-folder .circle-toolbar').click(function (event) {
event.stopPropagation(); event.stopPropagation();
var oldColorTool = $('#app-navigation .circle-toolbar.icon-checkmark'); var oldColorTool = $('#colors-folder .circle-toolbar.icon-checkmark');
$.each(oldColorTool, function(i, oct) { $.each(oldColorTool, function(i, oct) {
$(oct).removeClass('icon-checkmark'); $(oct).removeClass('icon-checkmark');
}); });
@@ -636,8 +721,48 @@ View.prototype = {
$(oct).removeClass('icon-checkmark'); $(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. * Some 'private' functions as helpers.
*/ */
@@ -655,6 +780,25 @@ View.prototype = {
return digits[1] + '#' + rgb.toString(16).toUpperCase(); 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) { _editableId: function(id) {
if (id === undefined) if (id === undefined)
return $("#modal-note-div .quicknote").data('id'); return $("#modal-note-div .quicknote").data('id');
@@ -706,6 +850,19 @@ View.prototype = {
$("#modal-note-div .quicknote").css("background-color", color); $("#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) { _editableTags: function(tags) {
if (tags === undefined) { if (tags === undefined) {
return $("#modal-note-div .slim-tag").toArray().map(function (value) { return $("#modal-note-div .slim-tag").toArray().map(function (value) {
@@ -719,7 +876,7 @@ View.prototype = {
$("#modal-note-div .note-tags").replaceWith(html); $("#modal-note-div .note-tags").replaceWith(html);
} }
}, },
_editableAttachts: function(attachts) { _editableAttachts: function(attachts, can_delete) {
if (attachts === undefined) { if (attachts === undefined) {
return $("#modal-note-div .note-attach").toArray().map(function (value) { return $("#modal-note-div .note-attach").toArray().map(function (value) {
return { return {
@@ -729,7 +886,7 @@ View.prototype = {
}; };
}); });
} else { } 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); $("#modal-note-div .note-attachts").replaceWith(html);
lozad('.attach-preview').observe(); lozad('.attach-preview').observe();
@@ -797,8 +954,10 @@ View.prototype = {
this._editor = editor; this._editor = editor;
}, },
_destroyEditor: function() { _destroyEditor: function() {
this._editor.destroy(); if (this._editor != undefined) {
this._editor = undefined; this._editor.destroy();
this._editor = undefined;
}
this._changed = false; this._changed = false;
this._editableId(-1); this._editableId(-1);
@@ -821,7 +980,6 @@ View.prototype = {
"left" : note.offset().left, "left" : note.offset().left,
"top" : note.offset().top, "top" : note.offset().top,
"width" : note.width(), "width" : note.width(),
"min-height": note.height(),
"height:" : "auto" "height:" : "auto"
}); });
@@ -893,6 +1051,7 @@ View.prototype = {
render: function () { render: function () {
this.renderNavigation(); this.renderNavigation();
this.renderContent(); 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 * Create modules
*/ */
@@ -941,8 +1113,7 @@ view.renderContent();
* Loading notes and render final view. * Loading notes and render final view.
*/ */
notes.load().done(function () { notes.load().done(function () {
view.renderNavigation(); view.render();
view.renderContent();
}).fail(function () { }).fail(function () {
alert('Could not load notes'); alert('Could not load notes');
}); });

View File

@@ -4,7 +4,9 @@
<a target="_blank" href="{{redirect_url}}"> <a target="_blank" href="{{redirect_url}}">
<div class="attach-preview note-attach" attach-file-id="{{file_id}}" data-background-image="{{preview_url}}"/> <div class="attach-preview note-attach" attach-file-id="{{file_id}}" data-background-image="{{preview_url}}"/>
</a> </a>
<div class="attach-remove icon-delete" title="{{t "quicknotes" "Delete attachment"}}"/> {{#if ../can_delete}}
<div class="attach-remove icon-delete" title="{{t "quicknotes" "Delete attachment"}}"/>
{{/if}}
</div> </div>
{{/each}} {{/each}}
</div> </div>

View File

@@ -8,6 +8,18 @@
{{allNotesTxt}} {{allNotesTxt}}
</a> </a>
</li> </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"> <li id="colors-folder" class="collapsible open">
<button class="collapse"></button> <button class="collapse"></button>
<a href="#" class="icon-search svg">{{colorsTxt}}</a> <a href="#" class="icon-search svg">{{colorsTxt}}</a>

View File

@@ -1,16 +1,5 @@
<div class="note-grid-item"> <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 }}" > <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 }}" >
{{#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='note-header'> <div class='note-header'>
<div class='note-attachts'> <div class='note-attachts'>
{{#each attachts}} {{#each attachts}}
@@ -28,11 +17,6 @@
<div class="icon-header-note icon-pin hide-header-icon" title="{{t "quicknotes" "Pin note"}}"></div> <div class="icon-header-note icon-pin hide-header-icon" title="{{t "quicknotes" "Pin note"}}"></div>
{{/if}} {{/if}}
<div class="icon-header-note icon-delete hide-header-icon icon-delete-note" title="{{t "quicknotes" "Delete note"}}"></div> <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'> <div class='note-title'>
{{{ title }}} {{{ title }}}
</div> </div>
@@ -40,12 +24,16 @@
<div class='note-content'> <div class='note-content'>
{{{ content }}} {{{ content }}}
</div> </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'> <div class='note-tags'>
{{#each tags}} {{#each tags}}
<div class="icon-tag slim-tag" tag-id="{{ id }}">{{{ name }}}</div> <div class="icon-tag slim-tag" tag-id="{{ id }}">{{{ name }}}</div>
{{/each}} {{/each}}
</div> </div>
<div> <div>
{{/if}}
</div> </div>
</div> </div>

View File

@@ -2,18 +2,7 @@
<div id="notes-grid-div" class="notes-grid"> <div id="notes-grid-div" class="notes-grid">
{{#each notes}} {{#each notes}}
<div class="note-grid-item"> <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 }}" > <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 }}" >
{{#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='note-header'> <div class='note-header'>
<div class='note-attachts'> <div class='note-attachts'>
{{#each attachts}} {{#each attachts}}
@@ -25,17 +14,17 @@
</div> </div>
<div class='note-body'> <div class='note-body'>
<div> <div>
{{#if ispinned}} {{#if is_shared}}
<div class="icon-header-note icon-pinned fixed-header-icon" title="{{t "quicknotes" "Unpin note"}}"></div> <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}} {{else}}
<div class="icon-header-note icon-pin hide-header-icon" title="{{t "quicknotes" "Pin note"}}"></div> {{#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}} {{/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'> <div class='note-title'>
{{{ title }}} {{{ title }}}
</div> </div>
@@ -43,6 +32,11 @@
<div class='note-content'> <div class='note-content'>
{{{ content }}} {{{ content }}}
</div> </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'> <div class='note-tags'>
{{#each tags}} {{#each tags}}
<div class='icon-tag slim-tag' tag-id="{{ id }}"> <div class='icon-tag slim-tag' tag-id="{{ id }}">
@@ -51,7 +45,6 @@
{{/each}} {{/each}}
</div> </div>
</div> </div>
{{/if}}
</div> </div>
</div> </div>
{{/each}} {{/each}}
@@ -68,6 +61,7 @@
<div contenteditable="true" id='title-editable' class='note-title'></div> <div contenteditable="true" id='title-editable' class='note-title'></div>
</div> </div>
<div contenteditable="true" id='content-editable' class='note-content'></div> <div contenteditable="true" id='content-editable' class='note-content'></div>
<div class='note-shares'></div>
<div class='note-tags'></div> <div class='note-tags'></div>
</div> </div>
<div class="note-options"> <div class="note-options">
@@ -87,9 +81,9 @@
<a href="#" class="circle-toolbar" style="background-color: #CECECE"></a> <a href="#" class="circle-toolbar" style="background-color: #CECECE"></a>
</div> </div>
<div class="buttons-toolbar"> <div class="buttons-toolbar">
<!-- <button id='share-button' class='round-tool-button'>
<button id='share-button'><?php p($l->t('Share'));?></button> <div class="icon-shared" title="{{t "quicknotes" "Share note"}}"></div>
--> </button>
<button id='attach-button' class='round-tool-button'> <button id='attach-button' class='round-tool-button'>
<div class="icon-picture" title="{{t "quicknotes" "Attach file"}}"></div> <div class="icon-picture" title="{{t "quicknotes" "Attach file"}}"></div>
</button> </button>
@@ -102,10 +96,14 @@
<button id='save-button'> <button id='save-button'>
{{ saveTxt }} {{ saveTxt }}
</button> </button>
</div>
<div style="clear: both;"></div>
</div>
</div> </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> </div>
</div> </div>

View 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>

View 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>

View File

@@ -91,7 +91,7 @@ class NoteController extends Controller {
* @param string $content * @param string $content
* @param string $color * @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); $note = $this->noteService->create($this->userId, $title, $content, $color);
$etag = md5(json_encode($note)); $etag = md5(json_encode($note));
@@ -111,10 +111,11 @@ class NoteController extends Controller {
* @param array $attachts * @param array $attachts
* @param bool $pinned * @param bool $pinned
* @param array $tags * @param array $tags
* @param array $shares
* @param string $color * @param string $color
*/ */
public function update(int $id, string $title, string $content, array $attachts, bool $pinned, array $tags, string $color = "#F7EB96"): JSONResponse { 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, $color); $note = $this->noteService->update($this->userId, $id, $title, $content, $attachts, $pinned, $tags, $shares, $color);
if (is_null($note)) { if (is_null($note)) {
return new JSONResponse([], Http::STATUS_NOT_FOUND); return new JSONResponse([], Http::STATUS_NOT_FOUND);
} }

View 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);
}
}

View 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([]);
}
}

View File

@@ -73,8 +73,7 @@ class AttachMapper extends QBMapper {
* @param string $userId * @param string $userId
* @param int $noteId * @param int $noteId
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found * @throws \OCP\AppFramework\Db\DoesNotExistException if not found
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException if more than one result * @return Attach[]
* @return Note[]
*/ */
public function findFromNote($userId, $noteId) { public function findFromNote($userId, $noteId) {
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
@@ -86,4 +85,5 @@ class AttachMapper extends QBMapper {
); );
return $this->findEntities($qb); return $this->findEntities($qb);
} }
} }

View File

@@ -13,7 +13,8 @@ class Note extends Entity implements JsonSerializable {
protected $timestamp; protected $timestamp;
protected $colorId; protected $colorId;
protected $userId; protected $userId;
protected $sharedWith; protected $sharedWith = [];
protected $sharedBy = [];
protected $isShared; protected $isShared;
protected $tags; protected $tags;
protected $attachts; protected $attachts;
@@ -40,8 +41,9 @@ class Note extends Entity implements JsonSerializable {
'colorid' => $this->colorId, 'colorid' => $this->colorId,
'color' => $this->color, 'color' => $this->color,
'userid' => $this->userId, 'userid' => $this->userId,
'sharedwith' => $this->sharedWith, 'shared_with' => $this->sharedWith,
'isshared' => $this->isShared, 'shared_by' => $this->sharedBy,
'is_shared' => $this->isShared,
'tags' => $this->tags, 'tags' => $this->tags,
'attachts' => $this->attachts 'attachts' => $this->attachts
]; ];

View File

@@ -31,6 +31,22 @@ class NoteMapper extends QBMapper {
return $this->findEntity($qb); 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) { public function findAll($userId) {
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->select('*') $qb->select('*')

View File

@@ -8,15 +8,18 @@ use OCP\AppFramework\Db\Entity;
class NoteShare extends Entity implements JsonSerializable { class NoteShare extends Entity implements JsonSerializable {
protected $noteId; protected $noteId;
protected $userId;
protected $sharedUser; protected $sharedUser;
protected $sharedGroup; protected $sharedGroup;
public function jsonSerialize() { public function jsonSerialize() {
return [ return [
'id' => $this->id, 'id' => $this->id,
'noteid' => $this->noteId, 'user_id' => $this->userId,
'shareduser' => $this->sharedUser, 'note_id' => $this->noteId,
'sharedgroup' => $this->sharedGroup 'shared_user' => $this->sharedUser,
'shared_group' => $this->sharedGroup
]; ];
} }
} }

View File

@@ -45,4 +45,14 @@ class NoteShareMapper extends Mapper {
$sql = 'DELETE FROM *PREFIX*quicknotes_shares WHERE note_id = ?'; $sql = 'DELETE FROM *PREFIX*quicknotes_shares WHERE note_id = ?';
$this->execute($sql, [$noteId]); $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;
}
} }

View File

@@ -57,13 +57,16 @@ class FileService {
* @param int $fileId file id to show * @param int $fileId file id to show
* @param int $sideSize side lenght 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); $userFolder = $this->rootFolder->getUserFolder($this->userId);
$node = current($userFolder->getById($fileId)); $file = current($userFolder->getById($fileId));
$path = $userFolder->getRelativePath($node->getPath());
if (!($file instanceof File)) {
return null;
}
return $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreview', [ return $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreview', [
'file' => $path, 'file' => $userFolder->getRelativePath($file->getPath()),
'x' => $sideSize, 'x' => $sideSize,
'y' => $sideSize 'y' => $sideSize
]); ]);
@@ -78,7 +81,7 @@ class FileService {
$userFolder = $this->rootFolder->getUserFolder($this->userId); $userFolder = $this->rootFolder->getUserFolder($this->userId);
$file = current($userFolder->getById($fileId)); $file = current($userFolder->getById($fileId));
if(!($file instanceof File)) { if (!($file instanceof File)) {
return null; return null;
} }

View File

@@ -48,26 +48,29 @@ class NoteService {
private $notemapper; private $notemapper;
private $notetagmapper; private $notetagmapper;
private $colormapper; private $colormapper;
private $notesharemapper; private $noteShareMapper;
private $attachMapper; private $attachMapper;
private $tagmapper; private $tagmapper;
private $fileService; private $fileService;
private $settingsService;
public function __construct(NoteMapper $notemapper, public function __construct(NoteMapper $notemapper,
NoteTagMapper $notetagmapper, NoteTagMapper $notetagmapper,
NoteShareMapper $notesharemapper, NoteShareMapper $noteShareMapper,
ColorMapper $colormapper, ColorMapper $colormapper,
AttachMapper $attachMapper, AttachMapper $attachMapper,
TagMapper $tagmapper, TagMapper $tagmapper,
FileService $fileService) FileService $fileService,
SettingsService $settingsService)
{ {
$this->notemapper = $notemapper; $this->notemapper = $notemapper;
$this->notetagmapper = $notetagmapper; $this->notetagmapper = $notetagmapper;
$this->colormapper = $colormapper; $this->colormapper = $colormapper;
$this->notesharemapper = $notesharemapper; $this->noteShareMapper = $noteShareMapper;
$this->attachMapper = $attachMapper; $this->attachMapper = $attachMapper;
$this->tagmapper = $tagmapper; $this->tagmapper = $tagmapper;
$this->fileService = $fileService; $this->fileService = $fileService;
$this->settingsService = $settingsService;
} }
/** /**
@@ -75,57 +78,62 @@ class NoteService {
*/ */
public function getAll(string $userId): array { public function getAll(string $userId): array {
$notes = $this->notemapper->findAll($userId); $notes = $this->notemapper->findAll($userId);
// Set shares with others.
foreach($notes as $note) { foreach($notes as $note) {
$note->setIsShared(false); $note->setIsShared(false);
$sharedWith = $this->notesharemapper->getSharesForNote($note->getId()); $note->setSharedWith($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(); // Get shares from others.
foreach($shareEntries as $entry) { $shares = [];
try { $sharedEntries = $this->noteShareMapper->findForUser($userId);
//find is only to check if current user is owner foreach($sharedEntries as $sharedEntry) {
$this->notemapper->find($entry->getNoteId(), $userId); $sharedNote = $this->notemapper->findShared($sharedEntry->getNoteId());
//user is owner, nothing to do $sharedNote->setIsShared(true);
} catch(\OCP\AppFramework\Db\DoesNotExistException $e) {
$share = $this->notemapper->findById($entry->getNoteId()); $sharedEntry->setUserId($sharedNote->getUserId());
$share->setIsShared(true); $sharedNote->setSharedBy([$sharedEntry]);
$shares[] = $share; $shares[] = $sharedNote;
}
} }
// Attahch shared notes from others to same response
$notes = array_merge($notes, $shares); $notes = array_merge($notes, $shares);
foreach ($notes as $note) { // Set tags to response.
$note->setTitle(strip_tags($note->getTitle())); 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) { foreach ($notes as $note) {
$note->setColor($this->colormapper->find($note->getColorId())->getColor()); $note->setColor($this->colormapper->find($note->getColorId())->getColor());
} }
// Insert true color to response // Insert pin to response
foreach ($notes as $note) { foreach ($notes as $note) {
$note->setIsPinned($note->getPinned() ? true : false); $note->setIsPinned($note->getPinned() ? true : false);
} }
// Insert true attachts to response // Insert attachts to response.
foreach ($notes as $note) { foreach ($notes as $note) {
$attachts = $this->attachMapper->findFromNote($userId, $note->getId()); $rAttachts = [];
$attachts = $this->attachMapper->findFromNote($note->getUserId(), $note->getId());
foreach ($attachts as $attach) { foreach ($attachts as $attach) {
$attach->setPreviewUrl($this->fileService->getPreviewUrl($attach->getFileId(), 512)); $previewUrl = $this->fileService->getPreviewUrl($attach->getFileId(), 512);
$attach->setRedirectUrl($this->fileService->getRedirectToFileUrl($attach->getFileId())); 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; return $notes;
@@ -149,7 +157,11 @@ class NoteService {
* @param string $content * @param string $content
* @param string $color * @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 // Get color or append it
if ($this->colormapper->colorExists($color)) { if ($this->colormapper->colorExists($color)) {
$hcolor = $this->colormapper->findByColor($color); $hcolor = $this->colormapper->findByColor($color);
@@ -187,6 +199,7 @@ class NoteService {
* @param array $attachts * @param array $attachts
* @param bool $pinned * @param bool $pinned
* @param array $tags * @param array $tags
* @param array $shares
* @param string $color * @param string $color
*/ */
public function update(string $userId, public function update(string $userId,
@@ -196,14 +209,14 @@ class NoteService {
array $attachts, array $attachts,
bool $pinned, bool $pinned,
array $tags, array $tags,
string $color): Note array $shares,
string $color): ?Note
{ {
// Get current Note and Color. // Get current Note and Color.
try { $note = $this->get($userId, $id);
$note = $this->notemapper->find($id, $userId); if (is_null($note))
} catch(Exception $e) {
return null; return null;
}
$oldcolorid = $note->getColorId(); $oldcolorid = $note->getColorId();
// Get new Color or append it. // 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 // Delete old tag relations
$dbTags = $this->tagmapper->getTagsForNote($userId, $id); $dbTags = $this->tagmapper->getTagsForNote($userId, $id);
foreach ($dbTags as $dbTag) { foreach ($dbTags as $dbTag) {
@@ -304,6 +342,10 @@ class NoteService {
} }
$newnote->setAttachts($attachts); $newnote->setAttachts($attachts);
// Fill shared with with others
$newnote->setIsShared(false);
$newnote->setSharedWith($this->noteShareMapper->getSharesForNote($newnote->getId()));
// Remove old color if necessary // Remove old color if necessary
if (($oldcolorid !== $hcolor->getId()) && if (($oldcolorid !== $hcolor->getId()) &&
(!$this->notemapper->colorIdCount($oldcolorid))) { (!$this->notemapper->colorIdCount($oldcolorid))) {
@@ -330,7 +372,7 @@ class NoteService {
} }
$oldcolorid = $note->getColorId(); $oldcolorid = $note->getColorId();
$this->notesharemapper->deleteByNoteId($note->getId()); $this->noteShareMapper->deleteByNoteId($note->getId());
// Delete note. // Delete note.
$this->notemapper->delete($note); $this->notemapper->delete($note);
@@ -381,7 +423,7 @@ class NoteService {
} }
$pos_users = array(); $pos_users = array();
$pos_groups = array(); $pos_groups = array();
$shares = $this->notesharemapper->getSharesForNote($noteId); $shares = $this->noteShareMapper->getSharesForNote($noteId);
foreach($shares as $s) { foreach($shares as $s) {
$shareType = $s->getSharedUser(); $shareType = $s->getSharedUser();
if(strlen($shareType) !== 0) { if(strlen($shareType) !== 0) {
@@ -406,14 +448,14 @@ class NoteService {
$share = new NoteShare(); $share = new NoteShare();
$share->setSharedGroup($groupId); $share->setSharedGroup($groupId);
$share->setNoteId($noteId); $share->setNoteId($noteId);
$this->notesharemapper->insert($share); $this->noteShareMapper->insert($share);
} }
/** /**
*/ */
public function removeGroupShare($groupId, $noteId) { public function removeGroupShare($groupId, $noteId) {
$share = $this->notesharemapper->findByNoteAndGroup($noteId, $groupId); $share = $this->noteShareMapper->findByNoteAndGroup($noteId, $groupId);
$this->notesharemapper->delete($share); $this->noteShareMapper->delete($share);
} }
/** /**
@@ -422,13 +464,13 @@ class NoteService {
$share = new NoteShare(); $share = new NoteShare();
$share->setSharedUser($userId); $share->setSharedUser($userId);
$share->setNoteId($noteId); $share->setNoteId($noteId);
$this->notesharemapper->insert($share); $this->noteShareMapper->insert($share);
} }
/** /**
*/ */
public function removeUserShare($userId, $noteId) { public function removeUserShare($userId, $noteId) {
$share = $this->notesharemapper->findByNoteAndUser($noteId, $userId); $share = $this->noteShareMapper->findByNoteAndUser($noteId, $userId);
$this->notesharemapper->delete($share); $this->noteShareMapper->delete($share);
} }
} }

View 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);
}
}

View File

@@ -4,3 +4,9 @@
*/ */
p($l->t('Delete attachment')); p($l->t('Delete attachment'));
p($l->t('Attach file')); 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'));

View File

@@ -1,8 +1,8 @@
<div id="app-settings"> <div id="app-settings">
<div id="app-settings-header"> <div id="app-settings-header">
<button class="settings-button" <button class="settings-button" data-apps-slide-toggle="#app-settings-content">
data-apps-slide-toggle="#app-settings-content" <?php p($l->t('Settings'));?>
></button> </button>
</div> </div>
<div id="app-settings-content"> <div id="app-settings-content">
</div> </div>