mirror of
https://github.com/JanGross/quicknotes.git
synced 2025-11-30 23:37:16 +01:00
Fix backend to shared notes, and initial fronted code.
This commit is contained in:
@@ -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,6 +262,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
43
js/script.js
43
js/script.js
@@ -164,11 +164,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_by, note.shared_with);
|
||||||
this._editableTags(note.tags);
|
this._editableTags(note.tags);
|
||||||
this._editableAttachts(note.attachts);
|
this._editableAttachts(note.attachts);
|
||||||
|
|
||||||
// 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);
|
||||||
@@ -490,6 +491,12 @@ View.prototype = {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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();
|
||||||
@@ -655,6 +662,24 @@ 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) {
|
||||||
|
$('#title-editable').prop('contenteditable', true);
|
||||||
|
$('#modal-note-div .icon-header-note').show();
|
||||||
|
$('#modal-note-div .note-options').show();
|
||||||
|
$('#modal-note-div .note-disable-options').hide();
|
||||||
|
this._initEditor();
|
||||||
|
} else {
|
||||||
|
$('#modal-note-div .note-options').hide();
|
||||||
|
$('#modal-note-div .icon-header-note').hide();
|
||||||
|
$('#title-editable').removeAttr("contentEditable");
|
||||||
|
$('#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 +731,19 @@ View.prototype = {
|
|||||||
$("#modal-note-div .quicknote").css("background-color", color);
|
$("#modal-note-div .quicknote").css("background-color", color);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_editableShares: function(shared_by, shared_with) {
|
||||||
|
if (shared_with === undefined) {
|
||||||
|
return $("#modal-note-div .slim-share").toArray().map(function (value) {
|
||||||
|
return {
|
||||||
|
id: value.getAttribute('tag-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) {
|
||||||
@@ -797,8 +835,10 @@ View.prototype = {
|
|||||||
this._editor = editor;
|
this._editor = editor;
|
||||||
},
|
},
|
||||||
_destroyEditor: function() {
|
_destroyEditor: function() {
|
||||||
|
if (this._editor != undefined) {
|
||||||
this._editor.destroy();
|
this._editor.destroy();
|
||||||
this._editor = undefined;
|
this._editor = undefined;
|
||||||
|
}
|
||||||
this._changed = false;
|
this._changed = false;
|
||||||
|
|
||||||
this._editableId(-1);
|
this._editableId(-1);
|
||||||
@@ -821,7 +861,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"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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" 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,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class='note-body'>
|
<div class='note-body'>
|
||||||
<div>
|
<div>
|
||||||
|
{{#unless is_shared}}
|
||||||
{{#if ispinned}}
|
{{#if ispinned}}
|
||||||
<div class="icon-header-note icon-pinned fixed-header-icon" title="{{t "quicknotes" "Unpin note"}}"></div>
|
<div class="icon-header-note icon-pinned fixed-header-icon" title="{{t "quicknotes" "Unpin note"}}"></div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<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}}
|
||||||
|
{{/unless}}
|
||||||
<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>
|
||||||
@@ -43,6 +29,14 @@
|
|||||||
<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="{{ id }}" title="Shared with {{ shared_user }}">{{{ shared_user }}}</div>
|
||||||
|
{{/each}}
|
||||||
|
{{#each shared_by}}
|
||||||
|
<div class="icon-user slim-share" share-id="{{ id }}" title="Shared by {{ user_id }}">{{{ user_id }}}</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>
|
||||||
@@ -105,7 +99,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="clear: both;"></div>
|
<div style="clear: both;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="note-disable-options">
|
||||||
|
<div class="buttons-toolbar">
|
||||||
|
<button id='close-button'>{{t "quicknotes" "Close"}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
8
js/templates/shares.handlebars
Normal file
8
js/templates/shares.handlebars
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<div class='note-shares'>
|
||||||
|
{{#each shared_with}}
|
||||||
|
<div class="icon-user slim-share" share-id="{{ id }}" title="Shared with {{ shared_user }}">{{{ shared_user }}}</div>
|
||||||
|
{{/each}}
|
||||||
|
{{#each shared_by}}
|
||||||
|
<div class="icon-user slim-share" share-id="{{ id }}" title="Shared from {{ user_id }}">{{{ user_id }}}</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
@@ -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
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -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('*')
|
||||||
|
|||||||
@@ -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
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,50 +75,44 @@ 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();
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
$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());
|
$attachts = $this->attachMapper->findFromNote($userId, $note->getId());
|
||||||
foreach ($attachts as $attach) {
|
foreach ($attachts as $attach) {
|
||||||
|
|||||||
Reference in New Issue
Block a user