Patch multiday thoughts

This commit is contained in:
2020-03-22 17:29:50 +01:00
parent 80b9a54607
commit 1c88ce7dfa
17 changed files with 2372 additions and 2285 deletions

View File

@@ -212,5 +212,3 @@ class Auth extends PhpObject
return password_verify($sPass, $sHash); return password_verify($sPass, $sHash);
} }
} }
?>

View File

@@ -220,7 +220,10 @@ class MyThoughts extends Main
public function getThoughtDates() public function getThoughtDates()
{ {
$asThoughts = Thought::getThoughtDates($this->oDb, $this->oAuth->getUserId()); $asThoughts = Thought::getThoughtDates($this->oDb, $this->oAuth->getUserId());
foreach($asThoughts as &$asThought) $asThought['created_f'] = self::formatDate($asThought['created'], 'j M'); foreach($asThoughts as &$asThought) {
$asThought['created_d'] = self::formatDate($asThought['created'], 'j M');
$asThought['created_h'] = self::formatDate($asThought['created'], 'h:i');
}
return self::getJsonResult(true, '', $asThoughts); return self::getJsonResult(true, '', $asThoughts);
} }

View File

@@ -5,6 +5,8 @@ class Thought extends PhpObject
const THOUGHT_TABLE = 'thoughts'; const THOUGHT_TABLE = 'thoughts';
private $iId; private $iId;
private $iPrevId;
private $iNextId;
private $iUserId; private $iUserId;
private $asOps; private $asOps;
private $iCreateTimestamp; private $iCreateTimestamp;
@@ -32,6 +34,7 @@ class Thought extends PhpObject
public function setId($iId, $bOpen=true) public function setId($iId, $bOpen=true)
{ {
$this->iId = $iId; $this->iId = $iId;
$this->iNextId = 0;
if($this->iId > 0 && $bOpen) $this->open($this->iId); if($this->iId > 0 && $bOpen) $this->open($this->iId);
} }
@@ -66,6 +69,8 @@ class Thought extends PhpObject
$asWhere = array(Db::getId(self::THOUGHT_TABLE)=>$iId, Db::getId(MyThoughts::USER_TABLE) => $this->iUserId); $asWhere = array(Db::getId(self::THOUGHT_TABLE)=>$iId, Db::getId(MyThoughts::USER_TABLE) => $this->iUserId);
$asInfo = $this->oDb->selectRow(self::THOUGHT_TABLE, $asWhere); $asInfo = $this->oDb->selectRow(self::THOUGHT_TABLE, $asWhere);
$this->iPrevId = $this->getRelativeThoughtId($iId, -1);
$this->iNextId = $this->getRelativeThoughtId($iId, 1);
$this->iId = $asInfo[Db::getId(self::THOUGHT_TABLE)]; $this->iId = $asInfo[Db::getId(self::THOUGHT_TABLE)];
$this->iUserId = $asInfo[Db::getId(MyThoughts::USER_TABLE)]; $this->iUserId = $asInfo[Db::getId(MyThoughts::USER_TABLE)];
$this->asOps = self::decodeThought($asInfo[Db::getText(self::THOUGHT_TABLE)]); $this->asOps = self::decodeThought($asInfo[Db::getText(self::THOUGHT_TABLE)]);
@@ -77,6 +82,23 @@ class Thought extends PhpObject
else $this->addError('getting thought info with no thought id'); else $this->addError('getting thought info with no thought id');
} }
private function getRelativeThoughtId($iId, $iOffset) {
$iThoughtId = 0;
$asThoughtIds = $this->oDb->selectRows(array(
'select' => Db::getId(self::THOUGHT_TABLE),
'from' => self::THOUGHT_TABLE,
'constraint'=> array('id_thought'=> $iId, Db::getId(MyThoughts::USER_TABLE) => $this->iUserId),
'constOpe' => array('id_thought'=> $iOffset>0?'>':'<', Db::getId(MyThoughts::USER_TABLE) => '='),
'orderBy' => array(Db::getId(self::THOUGHT_TABLE) => $iOffset>0?'ASC':'DESC'),
'limit' => abs($iOffset)
));
$iIndex = abs($iOffset) - 1;
if(array_key_exists($iIndex, $asThoughtIds)) $iThoughtId = $asThoughtIds[$iIndex];
return $iThoughtId;
}
public function save() public function save()
{ {
$asThought = array( $asThought = array(
@@ -94,10 +116,13 @@ class Thought extends PhpObject
{ {
return array( return array(
'id' => $this->iId, 'id' => $this->iId,
'prev_id' => $this->iPrevId,
'next_id' => $this->iNextId,
'id_user' => $this->iUserId, 'id_user' => $this->iUserId,
'ops' => $this->asOps, 'ops' => $this->asOps,
'created' => $this->iCreateTimestamp, 'created' => $this->iCreateTimestamp,
'created_f' => date('l, j F', $this->iCreateTimestamp), 'created_d' => date('l, j F', $this->iCreateTimestamp),
'created_h' => date('H:i', $this->iCreateTimestamp),
'led' => $this->sLed 'led' => $this->sLed
); );
} }

View File

@@ -2,7 +2,7 @@
/* /*
MyThoughts Project MyThoughts Project
http://git.lutran.fr/main.git https://git.lutran.fr/franzz/mythoughts
Copyright (C) 2015 François Lutran Copyright (C) 2015 François Lutran
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify

View File

@@ -10,4 +10,9 @@ oMyThoughts.onSamePageMove = function(asHash) {
self.pageInit(self.getHash()); self.pageInit(self.getHash());
return false; return false;
}; };
oMyThoughts.onKeydown = function(oEvent) {
if(oEvent.which == 37 || oEvent.which == 38) oEditor.prevPage();
else if(oEvent.which == 39 || oEvent.which == 40) oEditor.nextPage();
}
</script> </script>

View File

@@ -27,6 +27,8 @@ function MyThoughts(asGlobals)
$(window) $(window)
.bind('hashchange', self.onHashChange) .bind('hashchange', self.onHashChange)
.trigger('hashchange'); .trigger('hashchange');
$('html').on('keydown', self.onKeydown);
}; };
this.updateVars = function(asVars) this.updateVars = function(asVars)
@@ -68,7 +70,9 @@ function MyThoughts(asGlobals)
self.elem.$Side.find('.tag:not(.write)').remove(); self.elem.$Side.find('.tag:not(.write)').remove();
$.each(asData, function(iKey, asThought) { $.each(asData, function(iKey, asThought) {
$Tile = $('<div>', {'class': 'tag'}).appendTo(self.elem.$Side); $Tile = $('<div>', {'class': 'tag'}).appendTo(self.elem.$Side);
var $Link = $('<a>', {'href': '#read-'+asThought.id_thought}).html(asThought.created_f.replace(' ', '<br />')).appendTo($Tile); var $Link = $('<a>', {'href': '#read-'+asThought.id_thought, title:asThought.created_d+', '+asThought.created_h})
.html(asThought.created_d.replace(' ', '<br />'))
.appendTo($Tile);
}); });
self.elem.$Side.slideDown('fast', self.setSideElemVisibility); self.elem.$Side.slideDown('fast', self.setSideElemVisibility);
} }
@@ -107,6 +111,7 @@ function MyThoughts(asGlobals)
self.onSamePageMove = function(asHash){return false}; self.onSamePageMove = function(asHash){return false};
self.onQuitPage = function(){return true}; self.onQuitPage = function(){return true};
self.onFeedback = function(sType, sMsg){Tools.feedback(sType, sMsg);}; self.onFeedback = function(sType, sMsg){Tools.feedback(sType, sMsg);};
self.onKeydown = function(oEvent){};
}; };
this.feedback = function(sType, sMsg) { this.feedback = function(sType, sMsg) {
@@ -295,17 +300,32 @@ const Inline = Quill.import('blots/inline');
class ThoughtDate extends Inline { class ThoughtDate extends Inline {
static create(value) { static create(value) {
let node = super.create(); let node = super.create();
node.setAttribute('class', 'edi_header'); node.setAttribute('class', 'edi_thought_date');
return node; return node;
} }
} }
ThoughtDate.blotName = 'thought_date'; ThoughtDate.blotName = 'thought_date';
ThoughtDate.tagName = 'div'; ThoughtDate.tagName = 'div';
Quill.register(ThoughtDate);
//Time format
class ThoughtTime extends Inline {
static create(value) {
let node = super.create();
node.setAttribute('class', 'edi_thought_time');
return node;
}
}
ThoughtTime.blotName = 'thought_time';
ThoughtTime.tagName = 'div';
Quill.register({'blots/thought_date':ThoughtDate, 'blots/thought_time':ThoughtTime});
class Editor { class Editor {
constructor(sContainerId, bReadOnly) { constructor(sContainerId, bReadOnly) {
this.id = 0; this.id = 0;
this.prevId = 0;
this.nextId = 0;
this.thoughts = [];
this.page = 0; this.page = 0;
this.keystrokes = 0; this.keystrokes = 0;
this.line = false; this.line = false;
@@ -315,7 +335,6 @@ class Editor {
//DOM Elements //DOM Elements
var sEditorId = 'edi'+Math.floor(Math.random() * 1000); var sEditorId = 'edi'+Math.floor(Math.random() * 1000);
this.$Container = $(sContainerId).addClass('editor').append(self.consts.pages['editor']); this.$Container = $(sContainerId).addClass('editor').append(self.consts.pages['editor']);
this.$Header = this.$Container.find('.edi_header');
this.$EditorBox = this.$Container.find('.edi_container'); this.$EditorBox = this.$Container.find('.edi_container');
this.$Editor = this.$Container.find('.edi_table').attr('id', sEditorId); this.$Editor = this.$Container.find('.edi_table').attr('id', sEditorId);
this.$PrevBtn = $('.prev'); this.$PrevBtn = $('.prev');
@@ -340,8 +359,8 @@ class Editor {
//Key strokes //Key strokes
this.$Editor.keydown((e) => { this.$Editor.keydown((e) => {
if($.inArray(e.which, [13, 37, 38, 39, 40]) != -1) this._onChange('', '', 'user', e); if($.inArray(e.which, [13, 37, 38, 39, 40]) != -1) this._onChange('', '', 'user', e);
else if(e.which==33) this.$PrevBtn.click(); else if(e.which == 33) this.prevPage();
else if(e.which==34) this.$NextBtn.click(); else if(e.which == 34) this.nextPage();
else this.onKeyStroke(e); else this.onKeyStroke(e);
}); });
@@ -367,26 +386,43 @@ class Editor {
if(!this.readOnly) this.oQuill.focus(); if(!this.readOnly) this.oQuill.focus();
} }
setHeader(sHeader) { prevPage() {
this.$Editor.find('.edi_header').remove(); this.$PrevBtn.click();
if(this.readOnly) {
this.oQuill.insertText(0, sHeader+"\n");
this.oQuill.formatText(0, sHeader.length, 'thought_date', true);
} }
nextPage() {
this.$NextBtn.click();
} }
open(iThoughtId) { open(iThoughtId) {
if(!(iThoughtId in this.thoughts)) {
Tools.ajax( Tools.ajax(
'load', 'load',
(asData) => { (asData) => {
this.prevId = this.id;
this.id = asData.id; this.id = asData.id;
this.nextId = asData.next_id;
this.thoughts[asData.id] = asData;
asData.ops.unshift({
'attributes': {'thought_time': true},
'insert': asData.created_h+"\n"
});
if(this.prevId==0 || asData.created_d != this.thoughts[this.prevId].created_d) {
asData.ops.unshift({
'attributes': {'thought_date': true},
'insert': 'Thoughts on '+asData.created_d
});
}
if(!this.isEmpty()) asData.ops = this.getContent().concat(asData.ops);
this.oQuill.setContents(asData.ops); this.oQuill.setContents(asData.ops);
this.setHeader('Thoughts on '+asData.created_f); this._postInit(this.page);
this._postInit();
}, },
{id: iThoughtId} {id: iThoughtId}
); );
} }
}
_setPageHeight() { _setPageHeight() {
var iHeight = this.$EditorBox.height(); var iHeight = this.$EditorBox.height();
@@ -504,6 +540,10 @@ class Editor {
//Detect First/Last Page //Detect First/Last Page
this.$PrevBtn.toggleClass('visible', this.page != 0); this.$PrevBtn.toggleClass('visible', this.page != 0);
this.$NextBtn.toggleClass('visible', this.page != iLastPage); this.$NextBtn.toggleClass('visible', this.page != iLastPage);
if(this.readOnly && this.page == iLastPage && this.nextId > 0) {
this.open(this.nextId);
}
} }
} }
@@ -516,7 +556,7 @@ class Editor {
} }
isEmpty() { isEmpty() {
const rEmpty = /^(<p>(<br>|<br\/>|<br\s\/>|\s+|)<\/p>|)$/gm; const rEmpty = /^(<p>(<br\s?\/?>|\s+|)<\/p>|)$/gm;
return rEmpty.test(this.oQuill.getText().trim()); return rEmpty.test(this.oQuill.getText().trim());
} }

View File

@@ -28,13 +28,36 @@
font-family: $font_para; font-family: $font_para;
font-size: 14px; font-size: 14px;
& > p + p > .edi_thought_date, & > p + p > .edi_thought_time {
padding-top: 1em;
}
div { div {
margin: 0; margin: 0;
&.edi_header { &.edi_thought_date {
width: calc(50% - 1.5em);
}
&.edi_thought_date, &.edi_thought_time {
color: $gray-500; color: $gray-500;
font-style: italic; font-style: italic;
line-height: 3em; line-height: 3em;
display: inline-block;
text-indent: 0;
& + .edi_thought_date {
text-align: right;
margin-right: 2px;
padding-top: 0;
width: calc(50% - 2px);
}
}
&.edi_thought_time {
text-align: right;
margin-right: 2px;
width: 100%;
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
sass --unix-newline -l --style=compressed --watch mythoughts.scss:mythoughts.css sass --style=compressed --watch mythoughts.scss:mythoughts.css --poll