mirror of
https://github.com/JanGross/quicknotes.git
synced 2025-12-01 15:47:17 +01:00
Inital backend support to pinned notes
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
<name>Quick notes</name>
|
<name>Quick notes</name>
|
||||||
<summary>Quick notes with a basic rich text</summary>
|
<summary>Quick notes with a basic rich text</summary>
|
||||||
<description>Quick notes with a basic rich text</description>
|
<description>Quick notes with a basic rich text</description>
|
||||||
<version>0.2.4</version>
|
<version>0.2.5</version>
|
||||||
<licence>agpl</licence>
|
<licence>agpl</licence>
|
||||||
<author>Matias De lellis</author>
|
<author>Matias De lellis</author>
|
||||||
<namespace>QuickNotes</namespace>
|
<namespace>QuickNotes</namespace>
|
||||||
|
|||||||
53
js/script.js
53
js/script.js
@@ -137,10 +137,11 @@ Notes.prototype = {
|
|||||||
isLoaded: function () {
|
isLoaded: function () {
|
||||||
return this._loaded;
|
return this._loaded;
|
||||||
},
|
},
|
||||||
updateActive: function (title, content, tags, color) {
|
updateActive: function (title, content, pinned, tags, color) {
|
||||||
var note = this.getActive();
|
var note = this.getActive();
|
||||||
note.title = title;
|
note.title = title;
|
||||||
note.content = content;
|
note.content = content;
|
||||||
|
note.pinned = pinned;
|
||||||
note.tags = tags;
|
note.tags = tags;
|
||||||
note.color = color;
|
note.color = color;
|
||||||
|
|
||||||
@@ -151,9 +152,14 @@ Notes.prototype = {
|
|||||||
data: JSON.stringify(note)
|
data: JSON.stringify(note)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
updateId: function (id, title, content, tags, color) {
|
updateId: function (id, title, content, pinned, tags, color) {
|
||||||
this.load(id);
|
this.load(id);
|
||||||
return this.updateActive(title, content, tags, color);
|
return this.updateActive(title, content, pinned, tags, color);
|
||||||
|
},
|
||||||
|
setPinnedNote: function (id, pinned) {
|
||||||
|
this.load(id);
|
||||||
|
var note = this.getActive();
|
||||||
|
return this.updateActive(note.title, note.content, pinned, note.tags, note.color);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -344,7 +350,7 @@ View.prototype = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this._notes.updateId(id, title, content, tags, color).done(function () {
|
this._notes.updateId(id, title, content, false, tags, color).done(function () {
|
||||||
var modal = $('#modal-note-div');
|
var modal = $('#modal-note-div');
|
||||||
var modalnote = $("#modal-note-div .quicknote");
|
var modalnote = $("#modal-note-div .quicknote");
|
||||||
var modaltitle = $('#modal-note-div #title-editable');
|
var modaltitle = $('#modal-note-div #title-editable');
|
||||||
@@ -581,25 +587,40 @@ View.prototype = {
|
|||||||
|
|
||||||
$('#app-content').on("click", ".icon-pin", function (event) {
|
$('#app-content').on("click", ".icon-pin", function (event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
$(this).removeClass("hide-header-icon");
|
|
||||||
$(this).addClass("fixed-header-icon");
|
|
||||||
$(this).removeClass("icon-pin");
|
|
||||||
$(this).addClass("icon-pinned");
|
|
||||||
$(this).attr('title', t('quicknotes', 'Unpin note'));
|
|
||||||
|
|
||||||
$('.notes-grid').isotope('updateSortData').isotope();
|
var icon = $(this);
|
||||||
|
var note = icon.parent().parent();
|
||||||
|
var id = parseInt(note.data('id'), 10);
|
||||||
|
|
||||||
|
self._notes.setPinnedNote(id, true).done(function () {
|
||||||
|
icon.removeClass("hide-header-icon");
|
||||||
|
icon.addClass("fixed-header-icon");
|
||||||
|
icon.removeClass("icon-pin");
|
||||||
|
icon.addClass("icon-pinned");
|
||||||
|
icon.attr('title', t('quicknotes', 'Unpin note'));
|
||||||
|
$('.notes-grid').isotope('updateSortData').isotope();
|
||||||
|
}).fail(function () {
|
||||||
|
alert('Could not pin note');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#app-content').on("click", ".icon-pinned", function (event) {
|
$('#app-content').on("click", ".icon-pinned", function (event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
$(this).removeClass("fixed-header-icon");
|
|
||||||
$(this).addClass("hide-header-icon");
|
|
||||||
$(this).removeClass("icon-pinned");
|
|
||||||
$(this).addClass("icon-pin");
|
|
||||||
|
|
||||||
$(this).attr('title', t('quicknotes', 'Pin note'));
|
var icon = $(this);
|
||||||
|
var note = icon.parent().parent();
|
||||||
|
var id = parseInt(note.data('id'), 10);
|
||||||
|
|
||||||
$('.notes-grid').isotope('updateSortData').isotope();
|
self._notes.setPinnedNote(id, false).done(function () {
|
||||||
|
icon.removeClass("fixed-header-icon");
|
||||||
|
icon.addClass("hide-header-icon");
|
||||||
|
icon.removeClass("icon-pinned");
|
||||||
|
icon.addClass("icon-pin");
|
||||||
|
icon.attr('title', t('quicknotes', 'Pin note'));
|
||||||
|
$('.notes-grid').isotope('updateSortData').isotope();
|
||||||
|
}).fail(function () {
|
||||||
|
alert('Could not unpin');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -15,7 +15,11 @@
|
|||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div>
|
<div>
|
||||||
<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>
|
<div class="icon-header-note icon-delete hide-header-icon icon-delete-note" title="{{t "quicknotes" "Delete note"}}"></div>
|
||||||
<!--
|
<!--
|
||||||
{{#if sharedwith}}
|
{{#if sharedwith}}
|
||||||
|
|||||||
@@ -88,10 +88,17 @@ class NoteController extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$notes = array_merge($notes, $shares);
|
$notes = array_merge($notes, $shares);
|
||||||
|
|
||||||
// Insert true color to response
|
// Insert true 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
|
||||||
|
foreach ($notes as $note) {
|
||||||
|
$note->setIsPinned($note->getPinned() ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
return new DataResponse($notes);
|
return new DataResponse($notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,10 +152,11 @@ class NoteController extends Controller {
|
|||||||
* @param int $id
|
* @param int $id
|
||||||
* @param string $title
|
* @param string $title
|
||||||
* @param string $content
|
* @param string $content
|
||||||
|
* @param boolean $pinned
|
||||||
* @param array $tags
|
* @param array $tags
|
||||||
* @param string $color
|
* @param string $color
|
||||||
*/
|
*/
|
||||||
public function update($id, $title, $content, $tags, $color = "#F7EB96") {
|
public function update($id, $title, $content, $pinned, $tags, $color = "#F7EB96") {
|
||||||
// Get current Note and Color.
|
// Get current Note and Color.
|
||||||
try {
|
try {
|
||||||
$note = $this->notemapper->find($id, $this->userId);
|
$note = $this->notemapper->find($id, $this->userId);
|
||||||
@@ -206,10 +214,13 @@ class NoteController extends Controller {
|
|||||||
// Set new info on Note
|
// Set new info on Note
|
||||||
$note->setTitle($title);
|
$note->setTitle($title);
|
||||||
$note->setContent($content);
|
$note->setContent($content);
|
||||||
|
$note->setPinned($pinned ? 1 : 0);
|
||||||
$note->setTimestamp(time());
|
$note->setTimestamp(time());
|
||||||
$note->setColorId($hcolor->id);
|
$note->setColorId($hcolor->id);
|
||||||
|
|
||||||
// Insert true color to response
|
// Insert true color to response
|
||||||
$note->setColor($hcolor->getColor());
|
$note->setColor($hcolor->getColor());
|
||||||
|
$note->setIsPinned($note->getPinned() ? true : false);
|
||||||
|
|
||||||
// Update note.
|
// Update note.
|
||||||
$newnote = $this->notemapper->update($note);
|
$newnote = $this->notemapper->update($note);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class Note extends Entity implements JsonSerializable {
|
|||||||
|
|
||||||
protected $title;
|
protected $title;
|
||||||
protected $content;
|
protected $content;
|
||||||
|
protected $pinned;
|
||||||
protected $timestamp;
|
protected $timestamp;
|
||||||
protected $colorId;
|
protected $colorId;
|
||||||
protected $userId;
|
protected $userId;
|
||||||
@@ -17,16 +18,23 @@ class Note extends Entity implements JsonSerializable {
|
|||||||
protected $tags;
|
protected $tags;
|
||||||
|
|
||||||
protected $color;
|
protected $color;
|
||||||
|
protected $isPinned;
|
||||||
|
|
||||||
public function setColor($color) {
|
public function setColor($color) {
|
||||||
$this->color = $color;
|
$this->color = $color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setIsPinned($pinned) {
|
||||||
|
$this->isPinned = $pinned;
|
||||||
|
}
|
||||||
|
|
||||||
public function jsonSerialize() {
|
public function jsonSerialize() {
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'title' => $this->title,
|
'title' => $this->title,
|
||||||
'content' => $this->content,
|
'content' => $this->content,
|
||||||
|
'pinned' => $this->pinned,
|
||||||
|
'ispinned' => $this->isPinned,
|
||||||
'timestamp' => $this->timestamp,
|
'timestamp' => $this->timestamp,
|
||||||
'colorid' => $this->colorId,
|
'colorid' => $this->colorId,
|
||||||
'color' => $this->color,
|
'color' => $this->color,
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
<?php
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\QuickNotes\Db;
|
namespace OCA\QuickNotes\Db;
|
||||||
|
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
use OCP\AppFramework\Db\Mapper;
|
use OCP\AppFramework\Db\QBMapper;
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
|
|
||||||
class NoteMapper extends Mapper {
|
class NoteMapper extends QBMapper {
|
||||||
|
|
||||||
public function __construct(IDBConnection $db) {
|
public function __construct(IDBConnection $db) {
|
||||||
parent::__construct($db, 'quicknotes_notes', '\OCA\QuickNotes\Db\Note');
|
parent::__construct($db, 'quicknotes_notes');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,26 +21,34 @@ class NoteMapper extends Mapper {
|
|||||||
* @return Note
|
* @return Note
|
||||||
*/
|
*/
|
||||||
public function find($id, $userId) {
|
public function find($id, $userId) {
|
||||||
$sql = 'SELECT * FROM *PREFIX*quicknotes_notes WHERE id = ? AND user_id = ?';
|
$qb = $this->db->getQueryBuilder();
|
||||||
return $this->findEntity($sql, [$id, $userId]);
|
$qb->select('*')
|
||||||
}
|
->from($this->tableName)
|
||||||
|
->where(
|
||||||
public function findById($id) {
|
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)),
|
||||||
$sql = 'SELECT * FROM *PREFIX*quicknotes_notes WHERE id = ?';
|
$qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))
|
||||||
return $this->findEntity($sql, [$id]);
|
);
|
||||||
|
return $this->findEntity($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAll($userId) {
|
public function findAll($userId) {
|
||||||
$sql = 'SELECT * FROM *PREFIX*quicknotes_notes WHERE user_id = ?';
|
$qb = $this->db->getQueryBuilder();
|
||||||
return $this->findEntities($sql, [$userId]);
|
$qb->select('*')
|
||||||
|
->from($this->tableName)
|
||||||
|
->where(
|
||||||
|
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
|
||||||
|
);
|
||||||
|
return $this->findEntities($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function colorIdCount($colorid) {
|
public function colorIdCount($colorid) {
|
||||||
$sql = 'SELECT COUNT(*) as `count` FROM *PREFIX*quicknotes_notes WHERE color_id = ?';
|
$qb = $this->db->getQueryBuilder();
|
||||||
$result = $this->execute($sql, [$colorid]);
|
$qb->select('id')
|
||||||
$row = $result->fetch();
|
->from($this->tableName)
|
||||||
$result->closeCursor();
|
->where(
|
||||||
return $row['count'];
|
$qb->expr()->eq('color_id', $qb->createNamedParameter($colorid, IQueryBuilder::PARAM_INT))
|
||||||
|
);
|
||||||
|
return count($this->findEntities($qb));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
35
lib/Migration/Version000205Date20200604122312.php
Normal file
35
lib/Migration/Version000205Date20200604122312.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace OCA\QuickNotes\Migration;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use OCP\DB\ISchemaWrapper;
|
||||||
|
use OCP\Migration\IOutput;
|
||||||
|
use OCP\Migration\SimpleMigrationStep;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated migration step: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
class Version000205Date20200604122312 extends SimpleMigrationStep {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param IOutput $output
|
||||||
|
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||||
|
* @param array $options
|
||||||
|
* @return null|ISchemaWrapper
|
||||||
|
*/
|
||||||
|
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
|
||||||
|
/** @var ISchemaWrapper $schema */
|
||||||
|
$schema = $schemaClosure();
|
||||||
|
|
||||||
|
$table = $schema->getTable('quicknotes_notes');
|
||||||
|
$table->addColumn('pinned', 'boolean', [
|
||||||
|
'notnull' => true,
|
||||||
|
'default' => false,
|
||||||
|
]);
|
||||||
|
return $schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace OCA\QuickNotes\Service;
|
|
||||||
|
|
||||||
class NotFoundException extends ServiceException {}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace OCA\QuickNotes\Service;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
|
||||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
|
||||||
|
|
||||||
use OCA\OwnNotes\Db\Note;
|
|
||||||
use OCA\OwnNotes\Db\NoteMapper;
|
|
||||||
|
|
||||||
|
|
||||||
class NoteService {
|
|
||||||
|
|
||||||
private $mapper;
|
|
||||||
|
|
||||||
public function __construct(NoteMapper $mapper){
|
|
||||||
$this->mapper = $mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findAll($userId) {
|
|
||||||
return $this->mapper->findAll($userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function handleException ($e) {
|
|
||||||
if ($e instanceof DoesNotExistException ||
|
|
||||||
$e instanceof MultipleObjectsReturnedException) {
|
|
||||||
throw new NotFoundException($e->getMessage());
|
|
||||||
} else {
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id, $userId) {
|
|
||||||
try {
|
|
||||||
return $this->mapper->find($id, $userId);
|
|
||||||
|
|
||||||
// in order to be able to plug in different storage backends like files
|
|
||||||
// for instance it is a good idea to turn storage related exceptions
|
|
||||||
// into service related exceptions so controllers and service users
|
|
||||||
// have to deal with only one type of exception
|
|
||||||
} catch(Exception $e) {
|
|
||||||
$this->handleException($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create($title, $content, $color = "#F7EB96", $userId) {
|
|
||||||
$note = new Note();
|
|
||||||
$note->setTitle($title);
|
|
||||||
$note->setContent($content);
|
|
||||||
$note->setColor($color);
|
|
||||||
$note->setUserId($userId);
|
|
||||||
return $this->mapper->insert($note);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($id, $title, $content, $color = "#F7EB96", $userId) {
|
|
||||||
try {
|
|
||||||
$note = $this->mapper->find($id, $userId);
|
|
||||||
$note->setTitle($title);
|
|
||||||
$note->setContent($content);
|
|
||||||
$note->setColor($color);
|
|
||||||
return $this->mapper->update($note);
|
|
||||||
} catch(Exception $e) {
|
|
||||||
$this->handleException($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete($id, $userId) {
|
|
||||||
try {
|
|
||||||
$note = $this->mapper->find($id, $userId);
|
|
||||||
$this->mapper->delete($note);
|
|
||||||
return $note;
|
|
||||||
} catch(Exception $e) {
|
|
||||||
$this->handleException($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace OCA\QuickNotes\Service;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
class ServiceException extends Exception {}
|
|
||||||
Reference in New Issue
Block a user