* can use #NUMBER to make a link to the task by id in markdown note; opens this link as a search (experimental)

This commit is contained in:
Max Pozdeev 2022-01-14 22:13:04 +03:00
parent 70918b453d
commit 33810e79f7
6 changed files with 151 additions and 12 deletions

View file

@ -0,0 +1,70 @@
<?php
// FIXME: experimental, subject to change
class DBCore
{
/** @var Database_Abstract $db */
protected $db;
/** @var DBCore $defaultdb */
protected static $defaultInstance;
/**
*
* @param Database_Abstract $db Value of DBConnection::instance() or similar
* @return void
*/
public function __construct(Database_Abstract $db) {
$this->db = $db;
}
/**
*
* @return Database_Abstract
* @throws Exception
*/
public function connection()
{
if (!isset($this->db)) {
throw new Exception("DBConnection is not set");
}
return $this->db;
}
/**
*
* @return DBCore
* @throws Exception
*/
public static function defaultInstance() : DBCore
{
if (!isset(self::$defaultInstance)) {
throw new Exception("DBCore defaultInstance is not initialized");
}
return self::$defaultInstance;
}
/**
*
* @param DBCore $instance
* @return void
*/
public static function setDefaultInstance(DBCore $instance)
{
self::$defaultInstance = $instance;
}
/**
*
* @param int $id
* @return int
*/
public function getListIdByTaskId(int $id): int
{
$db = $this->db;
$listId = (int)$db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=". (int)$id);
return $listId;
}
}

View file

@ -1,6 +1,7 @@
<?php
require_once(MTTINC. 'parsedown/Parsedown.php');
require_once(MTTINC. 'parsedown/MTTParsedown.php');
function noteMarkup($note)
@ -17,7 +18,7 @@ function noteMarkup($note)
// Markdown converter (Parsedown)
function markdownToHtml($s)
{
$parser = Parsedown::instance();
$parser = MTTParsedown::instance();
$parser->setSafeMode(true);
//$parser->setBreaksEnabled(true);
return $parser->text($s);

View file

@ -655,6 +655,11 @@ var mytinytodo = window.mytinytodo = _mtt = {
if (path.settings) {
showSettings();
}
else if (path.search && path.list) {
filter.search = path.search;
this.pageSet('tasks', '');
this.loadLists();
}
else {
this.pageSet('tasks', '');
this.loadLists();
@ -664,7 +669,7 @@ var mytinytodo = window.mytinytodo = _mtt = {
loadLists: function()
{
if(filter.search != '') {
filter.search = '';
//filter.search = '' will be in tabSelect
$('#searchbarkeyword').text('');
$('#searchbar').hide();
}
@ -879,6 +884,7 @@ var mytinytodo = window.mytinytodo = _mtt = {
case "list": if(a[++i].match(/^-?\d+$/)) { p[s] = a[i]; } break;
case "alltasks": p.list = '-1'; break;
case "settings": p.settings = true; break;
case "search": p.search = decodeURIComponent(a[++i]); break;
}
}
@ -1400,6 +1406,7 @@ function tabSelect(elementOrId)
mytinytodo.doAction('listSelected', tabLists.get(id));
}
var newTitle = curList.name + ' - ' + _mtt.options.title;
var isFirstLoad = flag.firstLoad;
updateHistoryState( { list:id }, _mtt.urlForList(curList), newTitle );
if(curList.hidden) {
@ -1409,7 +1416,16 @@ function tabSelect(elementOrId)
flag.tagsChanged = true;
cancelTagFilter(0, 1);
setTaskview(0);
loadTasks({clearTasklist:1});
if (isFirstLoad && filter.search != '') {
$('#search').val(filter.search);
$('#search_close').show();
searchTasks(true);
}
else {
filter.search = '';
loadTasks({clearTasklist:1});
}
};

View file

@ -0,0 +1,37 @@
<?php
class MTTParsedown extends Parsedown
{
function __construct()
{
$this->InlineTypes['#'][]= 'TaskId';
$this->inlineMarkerList .= '#';
}
protected function inlineTaskId($excerpt)
{
if (preg_match('/^#(\d+)/', $excerpt['text'], $matches))
{
return array(
// How many characters to advance the Parsedown's
// cursor after being done processing this tag.
'extent' => strlen($matches[0]),
'element' => array(
'name' => 'a',
'text' => '#'. $matches[1],
'attributes' => array(
'href' => get_mttinfo('url'). '?task='. $matches[1],
'target' => '_blank',
'class' => 'mtt-link-to-task',
'target-id' => $matches[1],
),
),
);
}
}
}

View file

@ -8,14 +8,8 @@
require_once('./init.php');
//Parse query string
if ( isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '' )
{
parse_str($_SERVER['QUERY_STRING'], $q);
if (isset($q['list'])) {
$hash = ($q['list'] == 'alltasks') ? ['alltasks'] : ['list', (int)$q['list']];
unset($q['list']);
redirectWithHashRoute($q, $hash);
}
if ( isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '' ) {
parseRoute($_SERVER['QUERY_STRING']);
}
@ -35,7 +29,26 @@ require(TEMPLATEPATH. 'index.php');
// end
function redirectWithHashRoute(array $q, array $hash)
function parseRoute($queryString)
{
parse_str($queryString, $q);
if (isset($q['list'])) {
$hash = ($q['list'] == 'alltasks') ? ['alltasks'] : ['list', (int)$q['list']];
unset($q['list']);
redirectWithHashRoute($hash, $q);
}
else if (isset($q['task'])) {
$listId = (int)DBCore::defaultInstance()->getListIdByTaskId((int)$q['task']);
if ($listId > 0) {
$h = [ 'list', $listId, 'search', '#'. (int)$q['task']];
redirectWithHashRoute($h);
}
// TODO: not found
}
}
function redirectWithHashRoute(array $hash, array $q = [])
{
$url = get_unsafe_mttinfo('url');
$query = http_build_query($q);

View file

@ -32,6 +32,7 @@ else {
require_once(MTTINC. 'common.php');
require_once(MTTINC. 'class.dbconnection.php');
require_once(MTTINC. 'class.dbcore.php');
require_once(MTTINC. 'class.config.php');
require_once(MTTPATH. 'db/config.php');
@ -71,6 +72,7 @@ else {
die("Not installed. Run <a href=setup.php>setup.php</a> first.");
}
DBConnection::setPrefix(Config::get('prefix'));
DBCore::setDefaultInstance(new DBCore($db));
Config::load();