WikiContent using easy-markdown-editor

This commit is contained in:
José David Guillén 2022-04-27 19:08:42 +00:00
parent 72489186ae
commit 5dc38e2de9
11 changed files with 117 additions and 128 deletions

View File

@ -62,6 +62,8 @@ or:
for integration tests
// Markdown editor: https://simplemde.com/
// https://github.com/Ionaru/easy-markdown-editor
//---
@ -74,10 +76,12 @@ podman run --name=nextcloud --replace=true -p 8080:80 -v /absolute/path/to/apps:
sudo docker run --name=nextcloud -p 8080:80 -v /absolute/path/to/apps:/var/www/html/custom_apps nextcloud
Version000000Date20220302210900
//---
php ./occ migrations:execute <appId> <versionNumber>
Example: sudo -u www-data php ./occ migrations:execute photos 000000Date20201002183800
Example: sudo -u www-data php ./occ migrations:execute mywiki 000000Date20220302210900
https://c.infdj.com/apps/files/?dir=/Documents/Manuals%20-%20Drivers/drivers/MAD&fileid=19227

View File

@ -13,7 +13,7 @@
<category>organization</category>
<bugs>https://git.jd.guillen.io/wiki4nextcloud/issues</bugs>
<dependencies>
<nextcloud min-version="12" max-version="12"/>
<nextcloud min-version="12" max-version="24"/>
</dependencies>
<navigations>
<navigation>

View File

@ -1,23 +1,31 @@
#hello {
color: red;
}
li[data-id="wikis"] select {
width: calc(100% - 50px);
}
.-myWikiControls {
width: 100%;
margin: .25em;
li[class^="wikiPage-lvl-"] a::before {
display: inline-block;
}
.-myWikiControls select {
width: 98%;
.wikiPage-lvl-1 a::before {
content: "•";
width: 1em;
}
.wikiPage-lvl-2 a::before {
content: "• •";
width: 1.5em;
}
.wikiPage-lvl-3 a::before {
content: "• • •";
width: 2em;
}
option.separator {
font-size: 1px;
min-height:1px;
max-height:1px;
padding:0;
background-color: #000000;
#app {
width:100%;
}
#app-content #app-content-wrapper {
display: inline;
}
#app-content-wrapper textarea {
width:100%;
height:100%;
}

View File

@ -4,13 +4,14 @@ class WikiPages {
/*
* The container is the <ul> for the navigation panel
*/
constructor(container) {
constructor(container, onClickLoadPage) {
this.ul = container;
this.wikiId = null;
this._onClickLoadPage = onClickLoadPage;
}
clear() {
this.ul.querySelectorAll('[data-wiki-id]').forEach( x=>x.remove() );
this.wikiId = null;
this.ul.querySelectorAll('[data-page-id]').forEach( x=>x.remove() );
}
getWikiId() {
@ -20,9 +21,8 @@ class WikiPages {
load(wikiId) {
const self = this;
console.info('JDG :: Loading wiki', self.getWikiId() );
this.wikiId = null;
this.clear();
if (wikiId<=0) {
this.clear();
return;
}
@ -43,12 +43,7 @@ class WikiPages {
draw(pages, lvl=0, pid=0) {
let self=this;
if (lvl==0) {
this.clear();
}
// pages = [{"id":880,"pid":0,"title":"WikiTest","sort":1},...]
const self=this;
pages
.filter( x=>x.pid==pid )
.sort( (a,b)=>a.sort - b.sort )
@ -56,43 +51,52 @@ class WikiPages {
self.treeAdd(x.pid, x.id, x.title);
self.draw(pages, lvl+1, x.id);
});
if (lvl==0) {
this.ul.querySelectorAll('button[data-id="add"]').forEach(x => x.addEventListener('click', e=>self.onClickAdd(e)) );
this.ul.querySelectorAll('button[data-id="delete"]').forEach(x => x.addEventListener('click', e=>self.onClickDelete(e)) );
this.ul.querySelectorAll('button[data-id="rename"]').forEach(x => x.addEventListener('click', e=>self.onClickEdit(e)) );
this.ul.querySelectorAll('.icon-close').forEach(x => x.addEventListener('click', e=>self.onClickClose(e)) );
this.ul.querySelectorAll('.icon-checkmark').forEach(x => x.addEventListener('click', e=>self.onClickRename(e)) );
}
}
// -----------------------------------------------------------------------------------------
addListener(root) {
const self = this;
root.querySelectorAll('a[data-id="page"]').forEach(x => x.addEventListener('click', e=>self.onClickLoadPage(e)) );
root.querySelectorAll('button[data-id="add"]').forEach(x => x.addEventListener('click', e=>self.onClickAdd(e)) );
root.querySelectorAll('button[data-id="delete"]').forEach(x => x.addEventListener('click', e=>self.onClickDelete(e)) );
root.querySelectorAll('button[data-id="rename"]').forEach(x => x.addEventListener('click', e=>self.onClickEdit(e)) );
root.querySelectorAll('.icon-close').forEach(x => x.addEventListener('click', e=>self.onClickClose(e)) );
root.querySelectorAll('.icon-checkmark').forEach(x => x.addEventListener('click', e=>self.onClickRename(e)) );
}
onClickLoadPage(e) {
const li = e.target.closest("li[data-page-id]");
let pageId = li.dataset.pageId;
this._onClickLoadPage(this.wikiId, pageId);
}
onClickEdit(e) {
const li = e.target.closest("li[data-wiki-id]");
const li = e.target.closest("li[data-page-id]");
li.querySelector("input").value = li.querySelector("a").innerText;
li.classList.add("editing");
}
onClickClose(e) {
const li = e.target.closest("li[data-wiki-id]");
const li = e.target.closest("li[data-page-id]");
li.classList.remove("editing");
}
onClickRename(e) {
const li = e.target.closest("li[data-wiki-id]");
const li = e.target.closest("li[data-page-id]");
li.classList.remove("editing");
let pageId = li.dataset.wikiId;
let pageId = li.dataset.pageId;
let value = li.querySelector('input').value;
this.rename(pageId, value);
}
onClickAdd(e) {
const li = e.target.closest("li[data-wiki-id]");
this.newPage(li?li.dataset.wikiId:0);
const li = e.target.closest("li[data-page-id]");
this.newPage(li?li.dataset.pageId:0);
}
onClickDelete(e) {
const li = e.target.closest("li[data-wiki-id]");
let pageId = li.dataset.wikiId;
const self = this;
const li = e.target.closest("li[data-page-id]");
let pageId = li.dataset.pageId;
let pageTitle = li.querySelector('a').innerHTML;
OC.dialogs.confirm( t(appName, 'Delete the wiki page "{title}"?', {title:pageTitle}),
@ -129,7 +133,7 @@ class WikiPages {
// -----------------------------------------------------------------------------------------
treeDelete(pageId) {
const x = this.ul.querySelector(`[data-wiki-id="${pageId}"]`);
const x = this.ul.querySelector(`[data-page-id="${pageId}"]`);
const pid = x.dataset.pid;
x.parentNode.remove(x);
this.treeDeleteChildren(pageId);
@ -139,19 +143,19 @@ class WikiPages {
this.ul
.querySelectorAll(`[data-pid="${pageId}"]`)
.forEach(x=>{
self.treeDeleteBranch( x.dataset.wikiId );
self.treeDeleteChildren( x.dataset.pageId );
x.parentNode.remove(x);
}
);
}
treeRename(pageId, title) {
this.ul.querySelector(`[data-wiki-id="${pageId}"] a`).innerHTML = title;
this.ul.querySelector(`[data-page-id="${pageId}"] a`).innerHTML = title;
}
treeAdd(pid, pageId, title) {
let lvl = 0;
let nextNode, lastNode, parent = this.ul.querySelector(`[data-wiki-id="${pid}"]`);
let nextNode, lastNode, parent = this.ul.querySelector(`[data-page-id="${pid}"]`);
if ( parent===null ) {
lastNode = this.ul.lastChild;
} else {
@ -163,14 +167,12 @@ class WikiPages {
} while(nextNode && nextNode.dataset.pid!=parent.dataset.pid);
}
const bullet = ' - ';
let li = document.createElement("li");
// li.classList.add("editing");
li.dataset.wikiId = pageId;
li.classList.add(`wikiPage-lvl-${lvl}`);
li.dataset.pageId = pageId;
li.dataset.pid = pid||this.wikiId;
li.dataset.lvl = lvl;
li.innerHTML = `<a href="#">${bullet.repeat(lvl)} ${title}</a>
li.innerHTML = `<a href="#" data-id="page">${title}</a>
<div class="app-navigation-entry-utils">
<ul>
<li class="app-navigation-entry-utils-menu-button">
@ -202,6 +204,7 @@ class WikiPages {
</ul>
</div>
`;
this.addListener(li);
lastNode.parentNode.insertBefore(li, lastNode.nextSibling)
}

View File

@ -34,38 +34,12 @@ var MyWiki = MyWiki || {};
appNavigationEntryMenuClose();
})
// ------------------------------------------------
let wikiPages = new WikiPages(document.querySelector('li[data-id="pages"]').parentNode, onSelectWikiPage);
let wikiContent = new WikiContent(document.getElementById('app-content-wrapper'));
let wikiPages = new WikiPages(document.querySelector('li[data-id="pages"]').parentNode, (wikiId, pageId)=>wikiContent.load(wikiId, pageId));
let wikiNavigation = new WikiNavigation(document.querySelector('li[data-id="wikis"]'),
wikiId => wikiPages.load(wikiId),
e=>wikiPages.onClickAdd(e)
);
function onSelectWikiPage(wikiPageId) {
console.info(`JDG :: WikiPage selected ${wikiPageId}` );
if ( wikiPageId > 0 ) {
// wikiEditor.load(wikiPage.getWikiId(), wikiPageId );
}
}
// ---------------------------------------------------------------------------------
$(`#${appName}-test`).on('click',test);
function test() {
var baseUrl = OC.generateUrl('/apps/mywiki/wikis');
$.ajax({
url: baseUrl + '/test',
type: 'GET',
contentType: 'application/json'
}).done(function (response) {
// handle success
$('output').html(response);
}).fail(function (response, code) {
// handle failure
$('output').html('<h2>'+response.statusText+'</h2><code>'+response.responseText+'</code>');
});
}
// ---------------------------------------------------------------------------------
})(window, jQuery, MyWiki);

View File

@ -151,9 +151,24 @@ class WikiHelper {
return $wikiTreePage->id;
}
public function getWikiPageContent($id): string {
try {
$pageFolder = $this->getFolderById($id);
$path = $pageFolder->getInternalPath().'/'.self::WIKI_FILE_CONTENT;
if ( $this->wikiFolder->nodeExists($path) ) {
return $this->getFileByName(self::WIKI_FILE_CONTENT)->getContent();
}
$this->wikiFolder->newFile(self::WIKI_FILE_CONTENT, '');
} catch(\Exception $ex) {
return null;
}
return '';
}
public function update(int $id, string $content) {
try {
$path = $this->wikiFolder->getInternalPath().'/'.self::WIKI_FILE_CONTENT;
$pageFolder = $this->getFolderById($id);
$path = $pageFolder->getInternalPath().'/'.self::WIKI_FILE_CONTENT;
if ( $this->wikiFolder->nodeExists($path) ) {
$this->getFileByName(self::WIKI_FILE_CONTENT)->putContent($content);
} else {

View File

@ -43,10 +43,13 @@ class WikiPageService {
}
public function find(int $wikiId, int $id, string $userId) {
echo "\nwikiId: $wikiId";
echo "\nid: $id";
echo "\nuserId: $userId";
die();
try {
$wiki = $this->mapper->find($wikiId, $userId);
$wikiPageContent = $this->wikiHelper->setFolderId($wiki->getFileId())->getWikiPageContent($id);
} catch(Exception $e) {
$this->handleException($e);
}
return ['content'=>$wikiPageContent];
}
public function create(int $wikiId, int $parentFolderId, string $title, ?string $content, string $userId):array {

View File

@ -1,10 +1 @@
<h1>Hello world</h1>
<div id="emptycontent">
<div>
<button id="MyWiki-test">Test</button>
</div>
<div>
<output></output>
</div>
</div>

View File

@ -1,6 +1,13 @@
<?php
// ToDo: Must be a better way to include this
\OCP\Util::addStyle('mywiki', 'fontawesome/css/all.min');
\OCP\Util::addScript('mywiki', 'easy-markdown-editor-master/dist/easymde.min');
\OCP\Util::addStyle('mywiki', '../js/easy-markdown-editor-master/dist/easymde.min');
\OCP\Util::addScript('mywiki', 'WikiDropdownHelper');
\OCP\Util::addScript('mywiki', 'WikiNavigation');
\OCP\Util::addScript('mywiki', 'WikiContent');
\OCP\Util::addScript('mywiki', 'WikiPages');
\OCP\Util::addScript('mywiki', 'script');
\OCP\Util::addStyle('mywiki', 'style');

View File

@ -9,37 +9,22 @@
</ul>
</div>
<div class="app-navigation-entry-menu">
<ul>
<li>
<button data-id="add" class="icon-folder">Add Wiki</button>
</li>
<li>
<button disabled data-id="addPage" class="icon-add">Add Page</button>
</li>
<li>
<button disabled data-id="rename" class="icon-rename">Rename Wiki</button>
</li>
<li>
<button disabled data-id="delete" class="icon-delete">Delete Wiki</button>
</li>
</ul>
<ul>
<li>
<button data-id="add" class="icon-folder">Add Wiki</button>
</li>
<li>
<button disabled data-id="addPage" class="icon-add">Add Page</button>
</li>
<li>
<button disabled data-id="rename" class="icon-rename">Rename Wiki</button>
</li>
<li>
<button disabled data-id="delete" class="icon-delete">Delete Wiki</button>
</li>
</ul>
</div>
</li>
<li data-id="pages">
</li>
</ul>
<div id="myWikiTree">
no data
</div>
</ul>

View File

@ -6,9 +6,8 @@
</div>
<div id="app-settings-content">
<!-- Your settings in here -->
<ul class="with-icon">
<li data-id="deleteWiki">
<a href="#" class="icon-delete svg">Delete Current Wiki</a>
<ul>
<li>
</li>
</ul>
</div>