From 296ad3a2cea0e05511ad9b508767c128362fa290 Mon Sep 17 00:00:00 2001 From: jdg Date: Sun, 27 Mar 2022 22:01:46 +0000 Subject: [PATCH] Wiki navigation bar --- js/WikiDropdownHelper.js | 37 +++++++ js/WikiNavigation.js | 123 +++++++++++++++++++++++ lib/Helper/WikiTree.php | 83 +++++++++++++++ lib/Helper/WikiTreePage.php | 9 ++ tests/Unit/Helper/WikiTreeHelperTest.php | 50 +++++++++ 5 files changed, 302 insertions(+) create mode 100644 js/WikiDropdownHelper.js create mode 100644 js/WikiNavigation.js create mode 100644 lib/Helper/WikiTree.php create mode 100644 lib/Helper/WikiTreePage.php create mode 100644 tests/Unit/Helper/WikiTreeHelperTest.php diff --git a/js/WikiDropdownHelper.js b/js/WikiDropdownHelper.js new file mode 100644 index 0000000..fc19fc4 --- /dev/null +++ b/js/WikiDropdownHelper.js @@ -0,0 +1,37 @@ +'use strict'; + +class WikiDropdownHelper { + constructor(element) { + this.dd = element; + } + clear() { + while (this.dd.hasChildNodes()) { + this.dd.removeChild(this.dd.firstChild); + } + return this; + } + add(text, value, set=false) { + var option = document.createElement("option"); + option.text = text; + option.value = value; + this.dd.appendChild(option); + if ( set ) { + this.set(value); + } + return this; + } + rename(value, text) { + this.dd.querySelector(`option[value="${value}"]`).innerHTML=text; + return this; + } + get() { + return { + text:this.dd.parentElement.value, + value:this.dd.parentElement.text + }; + } + set(value) { + this.dd.parentElement.value=value; + // this.onSelectWiki(value); + } +} \ No newline at end of file diff --git a/js/WikiNavigation.js b/js/WikiNavigation.js new file mode 100644 index 0000000..028d94f --- /dev/null +++ b/js/WikiNavigation.js @@ -0,0 +1,123 @@ +'use strict'; + +class WikiNavigation { + dd = null; + onSelectWiki = null; + + constructor(container, onSelectWiki){ + let self = this; + this.container = container; + this.onSelectWiki = onSelectWiki; + + let wikiSelector = container.getElementsByTagName('select')[0]; + this.dd = new WikiDropdownHelper(wikiSelector); + wikiSelector.addEventListener('change', e=>{ + if(self.onSelectWiki) { + self.onSelectWiki(+e.target.value||0); + } + }); + this.loadWikis(); + + // Popup menu + let appNavigationMenu = container.getElementsByClassName('app-navigation-entry-menu')[0]; + let button = container.querySelector('.app-navigation-entry-utils-menu-button button'); + button.addEventListener('click', ()=>appNavigationMenu.classList.toggle("open") ); + document.addEventListener('click', e=>{if(e.target!==button)appNavigationMenu.classList.remove("open");}) + + appNavigationMenu.querySelector('[data-id="add"]').addEventListener('click', ()=>self.wikiChooseFolder() ); + appNavigationMenu.querySelector('[data-id="rename"]').addEventListener('click', ()=>self.wikiRename() ); + appNavigationMenu.querySelector('[data-id="delete"]').addEventListener('click', ()=>self.wikiDelete() ); + } + + wikiRename() { + let self=this; + OC.dialogs.prompt( + t(appName, 'This allow you to rename the displayed name for the selected wiki. (The folder will remain unchanged)'), + t(appName, 'Rename Wiki'), + (ok,value)=>{ + if(ok) { + value = value.trim(); + if(value!='') { + let wiki = self.dd.get(); + var baseUrl = OC.generateUrl('/apps/mywiki/wikis'); + $.ajax({ + url: baseUrl, + type: 'PUT', + contentType: 'application/json', + data: JSON.stringify({id:wiki.value, title:value}) + }).done(function (response) { + console.info('JDG :: Wiki renamed', response); + // ToDo :: Rename in the dropdown + }).fail(function (response, code) { + OC.dialogs.alert('Error', t(appName,'Error renaming wiki')); + console.error('JDG :: Error renaming wiki', response); + }); + } + } + }, + false, + t(appName, 'New name:'), + false + ); + } + + loadWikis() { + let self = this; + + this.dd.clear().add(t(appName, 'Loading...'), '', true); + + var baseUrl = OC.generateUrl('/apps/mywiki/wikis'); + $.ajax({ + url: baseUrl, + type: 'GET', + contentType: 'application/json' + }).done(function (response) { + console.info('JDG :: Wikis loaded', response); + self.dd.clear().add('',''); + response.forEach( x=>self.dd.add(x.title, x.id) ); + }).fail(function (response, code) { + OC.dialogs.alert('Error', t(appName,'Error getting the list of wikis')); + console.error('JDG :: Error getting the wikis', response); + self.dd.clear(); + }); + } + + wikiChooseFolder() { + let self = this; + this.dd.set(''); + window.OC.dialogs.filepicker( + t(appName, 'Select Wiki folder'), + (path, type) => { + if (type === OC.dialogs.FILEPICKER_TYPE_CHOOSE) { + self.wikiAdd(path, path.split('/').pop()); + } + }, + false, + ['httpd/unix-directory'], + true, + OC.dialogs.FILEPICKER_TYPE_CHOOSE, + '', // Path + { allowDirectoryChooser: true } + ); + } + + wikiAdd(folderPath, title) { + let self = this; + + var baseUrl = OC.generateUrl('/apps/mywiki/wikis'); + $.ajax({ + url: baseUrl, + type: 'POST', + data: JSON.stringify({title:title, folderPath:folderPath}), + contentType: 'application/json' + }).done(function (response) { + console.info('JDG :: wikiAdd :: Wiki added', response); + if ( response.id>0 ) { + self.dd.add(response.title, response.id, true); + } + }).fail(function (response, code) { + OC.dialogs.alert('Error', t(appName,'It has not been possible to add the new wiki')); + console.error('JDG :: wikiAdd :: Error adding the wiki', response); + }); + } +} \ No newline at end of file diff --git a/lib/Helper/WikiTree.php b/lib/Helper/WikiTree.php new file mode 100644 index 0000000..692bbc8 --- /dev/null +++ b/lib/Helper/WikiTree.php @@ -0,0 +1,83 @@ +wikiPages = $wikiPages??[]; + } + + public function getWikiPages(): array { + return $this->wikiPages; + } + + public function get($id): ?WikiTreePage { + $wikiTreePage = null; + foreach($this->wikiPages as $page) { + if ( $page['id']==$id) { + $wikiTreePage = new WikiTreePage(); + $wikiTreePage->id = $page['id']; + $wikiTreePage->pid = $page['pid']; + $wikiTreePage->title = $page['title']; + $wikiTreePage->sort = $page['sort']; + break; + } + } + return $wikiTreePage; + } + + private function countChilds($id): int { + $n = 0; + foreach($this->wikiPages as $page) { + if ($page['pid']==$id) { + $n++; + } + } + return $n; + } + + public function set(WikiTreePage $wikiTreePage): WikiTree { + if ( $this->get($wikiTreePage->id) === null ) { + $this->add($wikiTreePage); + } else { + $this->modify($wikiTreePage); + } + return $this; + } + + private function add(WikiTreePage $wikiTreePage): WikiTree { + if ($wikiTreePage->sort<=0) { + $wikiTreePage->sort = $this->countChilds($wikiTreePage->pid) + 1; + } + $this->wikiPages[] = [ + "id"=>$wikiTreePage->id, + "pid"=>$wikiTreePage->pid, + "title"=>$wikiTreePage->title, + "sort"=>$wikiTreePage->sort + ]; + return $this; + } + + private function modify(WikiTreePage $wikiTreePage): WikiTree { + foreach($this->wikiPages as &$page) { + if ( $page['id']==$wikiTreePage->id) { + $page['pid'] = $wikiTreePage->pid; + $page['title'] = $wikiTreePage->title; + $page['sort'] = $wikiTreePage->sort; + } + } + return $this; + } + + public function del($id): ?WikiTree { + $pages = []; + foreach($this->wikiPages as $k => $page) { + if ($page['id']!=$id && $page['pid']!=$id) { + $pages[] = $page; + } + } + $this->wikiPages = $pages; + return $this; + } +} \ No newline at end of file diff --git a/lib/Helper/WikiTreePage.php b/lib/Helper/WikiTreePage.php new file mode 100644 index 0000000..cc7056c --- /dev/null +++ b/lib/Helper/WikiTreePage.php @@ -0,0 +1,9 @@ +id = 1; + $wikiPage->pid = 0; + $wikiPage->title = 'Page1'; + $wikiPage->sort = 0; + $wikiTree->set($wikiPage); + + $wikiPage->id = 2; + $wikiPage->pid = 0; + $wikiPage->title = 'Page3'; + $wikiPage->sort = 0; + $wikiTree->set($wikiPage); + + $wikiPage->title = 'Page2'; + $wikiTree->set($wikiPage); + + $wikiPage->id = 11; + $wikiPage->pid = 1; + $wikiPage->title = 'Page1.1'; + $wikiPage->sort = 0; + $wikiTree->set($wikiPage); + + $pages = $wikiTree->getWikiPages(); + $this->assertEquals(3, count($pages)); + $this->assertEquals('Page2', $pages[1]['title']); + + $wikiTree->del(1); + $pages = $wikiTree->getWikiPages(); + $this->assertEquals(1, count($pages)); + + $page = $wikiTree->get(2); + $this->assertEquals(2, $page->id); + $this->assertEquals(0, $page->pid); + $this->assertEquals('Page2', $page->title); + $this->assertEquals(2, $page->sort); + } +}