Compare commits

...

3 Commits

Author SHA1 Message Date
jdg
72489186ae WikiPages controls 2022-04-13 22:55:25 +00:00
jdg
dc745e91da WikiPages controls 2022-04-13 22:54:23 +00:00
jdg
7365248bf3 WikiNavigation, rename/delete 2022-03-29 22:24:32 +00:00
12 changed files with 624 additions and 113 deletions

View File

@ -9,7 +9,8 @@
*/ */
return [ return [
'resources' => [ 'resources' => [
'wiki' => ['url' => '/wikis'] 'wiki' => ['url' => '/wikis'],
'wikiPage' => ['url' => '/wiki/{wikiId}']
], ],
'routes' => [ 'routes' => [
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],

View File

@ -1,8 +1,10 @@
'use strict'; 'use strict';
class WikiDropdownHelper { class WikiDropdownHelper {
constructor(element) { constructor(element, onChange) {
this.onSelectWiki = onChange;
this.dd = element; this.dd = element;
this.dd.addEventListener('change', e=>onChange(+e.target.value||0));
} }
clear() { clear() {
while (this.dd.hasChildNodes()) { while (this.dd.hasChildNodes()) {
@ -11,27 +13,40 @@ class WikiDropdownHelper {
return this; return this;
} }
add(text, value, set=false) { add(text, value, set=false) {
var option = document.createElement("option"); if (this.find(value)<=0) {
option.text = text; var option = document.createElement("option");
option.value = value; option.text = text;
this.dd.appendChild(option); option.value = value;
this.dd.appendChild(option);
}
if ( set ) { if ( set ) {
this.set(value); this.set(value);
} }
return this; return this;
} }
rename(value, text) { find(value) {
this.dd.querySelector(`option[value="${value}"]`).innerHTML=text; return Array.from(this.dd.options).findIndex(option=>option.value==value);
}
delete(value) {
let index = this.find(value);
if (index>0) {
this.dd.remove(index);
}
return this;
}
rename(value, newText) {
this.dd.querySelector(`option[value="${value}"]`).innerHTML=newText;
return this; return this;
} }
get() { get() {
return { return {
text:this.dd.parentElement.value, text:this.dd.options[this.dd.selectedIndex].innerHTML,
value:this.dd.parentElement.text value:this.dd.value
}; };
} }
set(value) { set(value) {
this.dd.parentElement.value=value; this.dd.value=value;
// this.onSelectWiki(value); this.onSelectWiki(value);
return this;
} }
} }

View File

@ -4,33 +4,63 @@ class WikiNavigation {
dd = null; dd = null;
onSelectWiki = null; onSelectWiki = null;
constructor(container, onSelectWiki){ constructor(container, onSelectWiki, onClickAddPage){
let self = this; let self = this;
this.container = container; this.container = container;
this.onSelectWiki = onSelectWiki; this.onSelectWiki = onSelectWiki;
this.onClickAddPage = onClickAddPage;
let wikiSelector = container.getElementsByTagName('select')[0]; let wikiSelector = container.getElementsByTagName('select')[0];
this.dd = new WikiDropdownHelper(wikiSelector);
wikiSelector.addEventListener('change', e=>{ let appNavigationMenu = container.getElementsByClassName('app-navigation-entry-menu')[0];
if(self.onSelectWiki) { let menuEntry = {
self.onSelectWiki(+e.target.value||0); addPage:appNavigationMenu.querySelector('[data-id="addPage"]'),
} add:appNavigationMenu.querySelector('[data-id="add"]'),
}); rename:appNavigationMenu.querySelector('[data-id="rename"]'),
delete:appNavigationMenu.querySelector('[data-id="delete"]')
};
this.dd = new WikiDropdownHelper(wikiSelector, id=>{
menuEntry.addPage.disabled = (id==0);
menuEntry.rename.disabled = (id==0);
menuEntry.delete.disabled = (id==0);
self.onSelectWiki(id);
} );
this.loadWikis(); this.loadWikis();
// Popup menu menuEntry.addPage.addEventListener('click', e=>self.onClickAddPage(e) );
let appNavigationMenu = container.getElementsByClassName('app-navigation-entry-menu')[0]; menuEntry.add.addEventListener('click', ()=>self.wikiChooseFolder() );
let button = container.querySelector('.app-navigation-entry-utils-menu-button button'); menuEntry.rename.addEventListener('click', ()=>self.wikiRename() );
button.addEventListener('click', ()=>appNavigationMenu.classList.toggle("open") ); menuEntry.delete.addEventListener('click', ()=>self.wikiDelete() );
document.addEventListener('click', e=>{if(e.target!==button)appNavigationMenu.classList.remove("open");}) }
appNavigationMenu.querySelector('[data-id="add"]').addEventListener('click', ()=>self.wikiChooseFolder() ); wikiDelete() {
appNavigationMenu.querySelector('[data-id="rename"]').addEventListener('click', ()=>self.wikiRename() ); let self=this;
appNavigationMenu.querySelector('[data-id="delete"]').addEventListener('click', ()=>self.wikiDelete() ); let wiki = this.dd.get();
OC.dialogs.confirm( t(appName, 'Delete the wiki {text}?', wiki),
t(appName, 'Delete Wiki'),
(ok)=>{
if ( ok ) {
var baseUrl = OC.generateUrl('/apps/mywiki/wikis');
$.ajax({
url: baseUrl+'/'+wiki.value,
type: 'DELETE',
contentType: 'application/json',
data: JSON.stringify({removeFiles:false})
}).done(function (response) {
console.info('JDG :: WikiNavigation.wikiDelete()', response);
self.dd.set('').delete(wiki.value);
}).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,'Error deleting wiki {text}', wiki));
console.error('JDG :: WikiNavigation.wikiDelete()', response);
});
}
},
false
);
} }
wikiRename() { wikiRename() {
let self=this; const self=this;
OC.dialogs.prompt( OC.dialogs.prompt(
t(appName, 'This allow you to rename the displayed name for the selected wiki. (The folder will remain unchanged)'), t(appName, 'This allow you to rename the displayed name for the selected wiki. (The folder will remain unchanged)'),
t(appName, 'Rename Wiki'), t(appName, 'Rename Wiki'),
@ -41,22 +71,22 @@ class WikiNavigation {
let wiki = self.dd.get(); let wiki = self.dd.get();
var baseUrl = OC.generateUrl('/apps/mywiki/wikis'); var baseUrl = OC.generateUrl('/apps/mywiki/wikis');
$.ajax({ $.ajax({
url: baseUrl, url: baseUrl+'/'+wiki.value,
type: 'PUT', type: 'PUT',
contentType: 'application/json', contentType: 'application/json',
data: JSON.stringify({id:wiki.value, title:value}) data: JSON.stringify({title:value})
}).done(function (response) { }).done(function (response) {
console.info('JDG :: Wiki renamed', response); console.info('JDG :: WikiNavigation.wikiRename()', response);
// ToDo :: Rename in the dropdown self.dd.rename(response.id, response.title);
}).fail(function (response, code) { }).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,'Error renaming wiki')); OC.dialogs.alert('Error', t(appName,'Error renaming wiki'));
console.error('JDG :: Error renaming wiki', response); console.error('JDG :: WikiNavigation.wikiRename()', response);
}); });
} }
} }
}, },
false, false,
t(appName, 'New name:'), t(appName, 'New name'),
false false
); );
} }
@ -72,12 +102,12 @@ class WikiNavigation {
type: 'GET', type: 'GET',
contentType: 'application/json' contentType: 'application/json'
}).done(function (response) { }).done(function (response) {
console.info('JDG :: Wikis loaded', response); console.info('JDG :: WikiNavigation.loadWikis()', response);
self.dd.clear().add('',''); self.dd.clear().add('','');
response.forEach( x=>self.dd.add(x.title, x.id) ); response.forEach( x=>self.dd.add(x.title, x.id) );
}).fail(function (response, code) { }).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,'Error getting the list of wikis')); OC.dialogs.alert('Error', t(appName,'Error getting the list of wikis'));
console.error('JDG :: Error getting the wikis', response); console.error('JDG :: WikiNavigation.loadWikis()', response);
self.dd.clear(); self.dd.clear();
}); });
} }
@ -111,13 +141,13 @@ class WikiNavigation {
data: JSON.stringify({title:title, folderPath:folderPath}), data: JSON.stringify({title:title, folderPath:folderPath}),
contentType: 'application/json' contentType: 'application/json'
}).done(function (response) { }).done(function (response) {
console.info('JDG :: wikiAdd :: Wiki added', response); console.info('JDG :: WikiNavigation.wikiAdd("'+folderPath+'","'+title+'")', response);
if ( response.id>0 ) { if ( response.id>0 ) {
self.dd.add(response.title, response.id, true); self.dd.add(response.title, response.id, true);
} }
}).fail(function (response, code) { }).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,'It has not been possible to add the new wiki')); 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); console.error('JDG :: WikiNavigation.wikiAdd("'+folderPath+'","'+title+'")', response);
}); });
} }
} }

264
js/WikiPages.js Normal file
View File

@ -0,0 +1,264 @@
'use strict';
class WikiPages {
/*
* The container is the <ul> for the navigation panel
*/
constructor(container) {
this.ul = container;
this.wikiId = null;
}
clear() {
this.ul.querySelectorAll('[data-wiki-id]').forEach( x=>x.remove() );
}
getWikiId() {
return this.wikiId;
}
load(wikiId) {
const self = this;
console.info('JDG :: Loading wiki', self.getWikiId() );
this.wikiId = null;
if (wikiId<=0) {
this.clear();
return;
}
var baseUrl = OC.generateUrl('/apps/mywiki/wiki/'+wikiId);
$.ajax({
url: baseUrl,
type: 'GET',
contentType: 'application/json'
}).done(function (response) {
console.info('JDG :: WikiPages.load('+wikiId+')', response);
self.wikiId = wikiId;
self.draw(response.pages, 0, response.pages[0].id);
}).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,'Error loading wiki('+wikiId+')'));
console.error('JDG :: WikiPages.load('+wikiId+')', response);
});
}
draw(pages, lvl=0, pid=0) {
let self=this;
if (lvl==0) {
this.clear();
}
// pages = [{"id":880,"pid":0,"title":"WikiTest","sort":1},...]
pages
.filter( x=>x.pid==pid )
.sort( (a,b)=>a.sort - b.sort )
.forEach( x => {
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)) );
}
}
// -----------------------------------------------------------------------------------------
onClickEdit(e) {
const li = e.target.closest("li[data-wiki-id]");
li.querySelector("input").value = li.querySelector("a").innerText;
li.classList.add("editing");
}
onClickClose(e) {
const li = e.target.closest("li[data-wiki-id]");
li.classList.remove("editing");
}
onClickRename(e) {
const li = e.target.closest("li[data-wiki-id]");
li.classList.remove("editing");
let pageId = li.dataset.wikiId;
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);
}
onClickDelete(e) {
const li = e.target.closest("li[data-wiki-id]");
let pageId = li.dataset.wikiId;
let pageTitle = li.querySelector('a').innerHTML;
OC.dialogs.confirm( t(appName, 'Delete the wiki page "{title}"?', {title:pageTitle}),
t(appName, 'Delete Wiki Page'),
(ok)=>{
if ( ok ) {
self.delete(pageId);
}
},
false
);
}
newPage(pid) {
const self = this;
OC.dialogs.prompt(
t(appName, 'Please type a title for the new page'),
t(appName, 'New Page'),
(ok,value)=>{
if(ok) {
value = value.trim();
if(value!='') {
self.add(pid, value);
}
}
},
false,
t(appName, 'Page Title'),
false
);
}
// -----------------------------------------------------------------------------------------
treeDelete(pageId) {
const x = this.ul.querySelector(`[data-wiki-id="${pageId}"]`);
const pid = x.dataset.pid;
x.parentNode.remove(x);
this.treeDeleteChildren(pageId);
}
treeDeleteChildren(pageId) {
const self = this;
this.ul
.querySelectorAll(`[data-pid="${pageId}"]`)
.forEach(x=>{
self.treeDeleteBranch( x.dataset.wikiId );
x.parentNode.remove(x);
}
);
}
treeRename(pageId, title) {
this.ul.querySelector(`[data-wiki-id="${pageId}"] a`).innerHTML = title;
}
treeAdd(pid, pageId, title) {
let lvl = 0;
let nextNode, lastNode, parent = this.ul.querySelector(`[data-wiki-id="${pid}"]`);
if ( parent===null ) {
lastNode = this.ul.lastChild;
} else {
lvl = (+parent.dataset.lvl + 1);
nextNode = parent;
do {
lastNode = nextNode;
nextNode = lastNode.nextSibling;
} while(nextNode && nextNode.dataset.pid!=parent.dataset.pid);
}
const bullet = ' - ';
let li = document.createElement("li");
// li.classList.add("editing");
li.dataset.wikiId = pageId;
li.dataset.pid = pid||this.wikiId;
li.dataset.lvl = lvl;
li.innerHTML = `<a href="#">${bullet.repeat(lvl)} ${title}</a>
<div class="app-navigation-entry-utils">
<ul>
<li class="app-navigation-entry-utils-menu-button">
<button></button>
</li>
</ul>
</div>
<div class="app-navigation-entry-edit">
<div data-form>
<input type="text" value="">
<input type="submit" value="" class="icon-close">
<input type="submit" value="" class="icon-checkmark">
</div>
</div>
<div class="app-navigation-entry-menu">
<ul>
<li>
<button data-id="openFolder" class="icon-folder">Open Folder</button>
</li>
<li>
<button data-id="add" class="icon-add">Add Page</button>
</li>
<li>
<button data-id="rename" class="icon-rename">Rename Page</button>
</li>
<li>
<button data-id="delete" class="icon-delete">Delete Page</button>
</li>
</ul>
</div>
`;
lastNode.parentNode.insertBefore(li, lastNode.nextSibling)
}
// -----------------------------------------------------------------------------------------
delete(pageId) {
const self = this;
console.info(`WikiPages.delete("${this.wikiId}-${pageId}")`);
var baseUrl = OC.generateUrl('/apps/mywiki/wiki/'+this.wikiId);
$.ajax({
url: baseUrl+'/'+pageId,
type: 'DELETE',
contentType: 'application/json'
}).done(function (response) {
console.info(`WikiPages.delete("${this.wikiId}-${pageId}")`, response);
self.treeDelete(pageId);
}).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,'Error deleting wiki {text}', wiki));
console.error(`WikiPages.delete("${this.wikiId}-${pageId}")`, response);
});
}
rename(pageId, title) {
const self = this;
console.info(`WikiPages.rename("${this.wikiId}-${pageId}","${title}")`);
var baseUrl = OC.generateUrl('/apps/mywiki/wiki/'+this.wikiId);
$.ajax({
url: baseUrl+'/'+pageId,
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify({title:title, content:null})
}).done(function (response) {
console.info(`WikiPages.rename("${self.wikiId}-${pageId}","${title}")`, response);
self.treeRename(pageId, title);
}).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,`Error renaming wiki page ${self.wikiId}-${pageId}`));
console.error(`WikiPages.rename("${self.wikiId}-${pageId}","${title}")`, response);
});
}
add(pid, title) {
const self = this;
console.info(`WikiPages.add("${this.wikiId}-${pid}","${title}")`);
var baseUrl = OC.generateUrl('/apps/mywiki/wiki/'+this.wikiId);
$.ajax({
url: baseUrl,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({pid:pid, title:title, content:null})
}).done(function (response) {
console.info(`WikiPages.add("${self.wikiId}-${pid}","${title}")`, response);
if ( response.pageId > 0 ) {
self.treeAdd(pid, response.pageId, title);
}
}).fail(function (response, code) {
OC.dialogs.alert('Error', t(appName,`Error adding wiki page "${self.wikiId}-${pid}": "${title}"`));
console.error(`WikiPages.add("${self.wikiId}-${pid}","${title}")`, response);
});
}
}

View File

@ -1,26 +1,6 @@
const appName = 'MyWiki'; const appName = 'MyWiki';
class WikiPages {
constructor(container){
this.wikiId = null;
}
load(wikiId) {
console.info('JDG :: Loading wiki', wikiId );
this.wikiId = wikiId;
}
getWikiId() {
return this.wikiId;
}
add(parentPageId, title) {
}
delete() {
}
rename() {
}
}
class WikiEditor { class WikiEditor {
load(wikiId, wikiPageId) { load(wikiId, wikiPageId) {
console.info(`JDG :: Loading Wiki ${wikiId}/${wikiPageId}`); console.info(`JDG :: Loading Wiki ${wikiId}/${wikiPageId}`);
@ -33,14 +13,35 @@ var MyWiki = MyWiki || {};
(function(window, $, exports, undefined) { (function(window, $, exports, undefined) {
'use strict'; 'use strict';
let wikiNavigation = new WikiNavigation(document.querySelector('li[data-id="wikis"]'), onSelectWiki); // Navigation menu --------------------------------
let wikiPages = new WikiPages(document.querySelector('li[data-id="pages"]'), onSelectWikiPage); function appNavigationEntryMenuClose() {
function onSelectWiki(wikiId) { document.querySelectorAll('.app-navigation-entry-menu').forEach(e=>e.classList.remove("open"));
console.info(`JDG :: WikiList selected ${wikiId}` );
if ( wikiId > 0 ) {
wikiPages.load(wikiId);
}
} }
document.addEventListener('click', e=>{
if (e.target.tagName === 'BUTTON' ) {
const li = e.target.parentNode?.parentNode?.closest('li');
if (!li) return;
const menu = li.querySelector(".app-navigation-entry-menu");
if (!menu) return;
if ( menu.classList.contains("open") ) {
menu.classList.remove("open");
} else {
appNavigationEntryMenuClose();
menu.classList.add("open");
}
return;
}
appNavigationEntryMenuClose();
})
// ------------------------------------------------
let wikiPages = new WikiPages(document.querySelector('li[data-id="pages"]').parentNode, onSelectWikiPage);
let wikiNavigation = new WikiNavigation(document.querySelector('li[data-id="wikis"]'),
wikiId => wikiPages.load(wikiId),
e=>wikiPages.onClickAdd(e)
);
function onSelectWikiPage(wikiPageId) { function onSelectWikiPage(wikiPageId) {
console.info(`JDG :: WikiPage selected ${wikiPageId}` ); console.info(`JDG :: WikiPage selected ${wikiPageId}` );
if ( wikiPageId > 0 ) { if ( wikiPageId > 0 ) {

View File

@ -0,0 +1,88 @@
<?php
namespace OCA\MyWiki\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCA\MyWiki\Service\WikiPageService;
class WikiPageController extends Controller {
private $service;
private $userId;
use Errors;
public function __construct(string $AppName, IRequest $request, WikiPageService $service, $UserId){
parent::__construct($AppName, $request);
$this->service = $service;
$this->userId = $UserId;
}
/**
* @NoAdminRequired
*
* @param int $wikiId
*/
public function index(int $wikiId) {
return $this->handleNotFound(function () use ($wikiId) {
return $this->service->findAll($wikiId, $this->userId);
});
}
/**
* @NoAdminRequired
*
* @param int $wikiId
* @param int $id
*/
public function show(int $wikiId, int $id) {
return $this->handleNotFound(function () use ($wikiId, $id) {
return $this->service->find($wikiId, $id, $this->userId);
});
}
/**
* @NoAdminRequired
*
* @param int $wikiId
* @param int $parentFolderId
* @param string $title
* @param ?string $content
*/
public function create(int $wikiId, int $pid, string $title, ?string $content) {
return $this->handleReadOnly(function () use ($wikiId, $pid, $title, $content) {
return $this->service->create($wikiId, $pid, $title, $content, $this->userId);
});
}
/**
* @NoAdminRequired
*
* @param int $wikiId
* @param int $id
* @param string $title
* @param string $content
*/
public function update(int $wikiId, int $id, ?string $title, ?string $content) {
return $this->handleNotFound(function () use ($wikiId, $id, $title, $content) {
return $this->service->update($wikiId, $id, $title, $content, $this->userId);
});
}
/**
* @NoAdminRequired
*
* @param int $wikiId
* @param int $id
* @param bool $removeFiles
*/
public function destroy(int $wikiId, int $id) {
return $this->handleNotFound(function () use ($wikiId, $id) {
return $this->service->delete($wikiId, $id, $this->userId);
});
}
}

View File

@ -34,7 +34,7 @@ class WikiMapper extends QBMapper {
return $this->findEntity($qb); return $this->findEntity($qb);
} }
public function findAll(string $userId, mixed $filter=null) { public function findAll(string $userId, ?array $filter=null) {
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->select('*') $qb->select('*')
@ -46,12 +46,12 @@ class WikiMapper extends QBMapper {
if ($filter) { if ($filter) {
if (array_key_exists('title',$filter) ) { if (array_key_exists('title',$filter) ) {
$qb->where( $qb->where(
$qb->expr()->eq('title', $qb->createNamedParameter($id)) $qb->expr()->eq('title', $qb->createNamedParameter($filter['title']))
); );
} }
if (array_key_exists('fileId',$filter) ) { if (array_key_exists('fileId',$filter) ) {
$qb->where( $qb->where(
$qb->expr()->eq('fileId', $qb->createNamedParameter($id)) $qb->expr()->eq('file_id', $qb->createNamedParameter($filter['fileId']))
); );
} }
} }

View File

@ -60,16 +60,10 @@ class WikiHelper {
return $this; return $this;
} }
private function isWiki() :bool { private function isWikiable() :bool {
return $this->wikiFolder && $this->wikiFolder->getType() == \OCP\Files\Node::TYPE_FOLDER; return $this->wikiFolder && $this->wikiFolder->getType() == \OCP\Files\Node::TYPE_FOLDER;
} }
public function reloadWikiTree(): array {
$wiki = $this->getWikiData();
$wiki['pages'] = $this->rebuildWikiTree();
$this->setWikiData($wiki);
return $wiki;
}
public function getWikiData(): ?array { public function getWikiData(): ?array {
try { try {
@ -96,41 +90,65 @@ class WikiHelper {
return true; return true;
} }
public function initWiki(string $folderPath, string $title) :?int { public function createWikiData(): array {
$wiki = [
"title"=>$this->wikiFolder->getName(),
"folderId"=>$this->wikiFolder->getId(),
"pages"=>[]
];
$wiki['pages'] = $this->rebuildWikiTree();
return $wiki;
}
public function rebuildWiki($title): ?array {
$wiki = $this->createWikiData(true);
$wiki['title'] = $title;
return $this->setWikiData($wiki) ? $wiki : null;
}
public function create(string $folderPath, string $title) :?int {
$this->wikiFolder = $this->userFolder->get($folderPath); $this->wikiFolder = $this->userFolder->get($folderPath);
if ( !$this->isWiki() ) { if ( !$this->isWikiable() ) {
return null; return null;
} }
$folderId = $this->wikiFolder->getId();
if ( $this->getWikiData() === null ) { if ( $this->getWikiData() === null ) {
$wiki = [ if ( $this->rebuildWiki($title) === null ) {
"title"=>$title,
"folderId"=>$folderId,
"pages"=>$this->rebuildWikiTree()
];
if ( !$this->setWikiData($wiki) ) {
return null; return null;
} }
} }
return $folderId; return $this->wikiFolder->getId();
} }
public function add(int $parentId, string $title) { public function add(int $parentId, string $title, ?string $content) :int {
// $folder = ...newFolder($path) if ($parentId>0) {
$parentFolder = $this->getFolderById($parentId);
} else {
$parentFolder = $this->wikiFolder;
}
try {
$folder = $parentFolder->newFolder($this->sanitize_file_name($title));
$wikiData = $this->getWikiData(); $wikiTreePage = new WikiTreePage();
if ($wikiData) { $wikiTreePage->id = $folder->getId();
$wikiTree = new WikiTree($wikiData['pages']); $wikiTreePage->pid = $parentId;
$wikiPage = new WikiTreePage(); $wikiTreePage->title = $title;
$wikiPage->id = $id; $wikiTreePage->sort = 0;
$wikiPage->pid = $parentId;
$wikiPage->title = $title;
$wikiTree->set($wikiPage);
$wikiData['pages'] = $wikiTree->getWikiPages();
$this->setWikiData($wikiData);
}
if ( !is_null($content) ) {
$this->update($wikiTreePage->id, $content);
}
$wikiData = $this->getWikiData();
if ($wikiData) {
$wikiTree = new WikiTree($wikiData['pages']);
$wikiTree->set($wikiTreePage);
$wikiData['pages'] = $wikiTree->getWikiPages();
$this->setWikiData($wikiData);
}
} catch(\Exception $ex) {
return -1;
}
return $wikiTreePage->id;
} }
public function update(int $id, string $content) { public function update(int $id, string $content) {

View File

@ -0,0 +1,98 @@
<?php
namespace OCA\MyWiki\Service;
use Exception;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\Files\IRootFolder;
use OCA\MyWiki\Db\Wiki;
use OCA\MyWiki\Db\WikiMapper;
use OCA\MyWiki\Helper\WikiHelper;
class WikiPageService {
private $mapper;
private $userId;
private $wikiHelper;
public function __construct(WikiMapper $mapper, IRootFolder $storage, $UserId) {
$this->mapper = $mapper;
$this->userId = $UserId;
$userFolder = $storage->getUserFolder($this->userId);
$this->wikiHelper = new WikiHelper($userFolder);
}
public function findAll(int $wikiId, string $userId) {
try {
$wiki = $this->mapper->find($wikiId, $userId);
return $this->wikiHelper->setFolderId($wiki->getFileId())->getWikiData();
} catch(Exception $e) {
$this->handleException($e);
}
}
private function handleException ($e) {
if ($e instanceof DoesNotExistException ||
$e instanceof MultipleObjectsReturnedException) {
throw new NotFoundException($e->getMessage());
} else {
throw $e;
}
}
public function find(int $wikiId, int $id, string $userId) {
echo "\nwikiId: $wikiId";
echo "\nid: $id";
echo "\nuserId: $userId";
die();
}
public function create(int $wikiId, int $parentFolderId, string $title, ?string $content, string $userId):array {
try {
$wiki = $this->mapper->find($wikiId, $userId);
$pageId = $this->wikiHelper->setFolderId($wiki->getFileId())->add($parentFolderId,$title,$content);
if ( $pageId <= 0 ) {
throw new ReadOnlyException('Error renaming wiki page');
}
} catch(Exception $e) {
$this->handleException($e);
}
return ["pageId"=>$pageId];
}
public function update(int $wikiId, int $id, ?string $title, ?string $content, string $userId) {
try {
$wiki = $this->mapper->find($wikiId, $userId);
$this->wikiHelper->setFolderId($wiki->getFileId());
if (!is_null($title)) {
if ( !$this->wikiHelper->rename($id, $title) ) {
throw new ReadOnlyException('Error renaming wiki page');
}
}
if (!is_null($content)) {
if ( !$this->wikiHelper->update($id, $content) ) {
throw new ReadOnlyException('Error updating wiki content');
}
}
} catch(Exception $e) {
$this->handleException($e);
}
return true;
}
public function delete(int $wikiId, int $id, string $userId) {
try {
$wiki = $this->mapper->find($wikiId, $userId);
if ( !$this->wikiHelper->setFolderId($wiki->getFileId())->delete($id) ) {
throw new ReadOnlyException('Error deleting wiki page');
}
} catch(Exception $e) {
$this->handleException($e);
}
return true;
}
}

View File

@ -58,7 +58,7 @@ class WikiService {
} }
public function create(string $folderPath, string $title, string $userId) { public function create(string $folderPath, string $title, string $userId) {
$folderId = $this->wikiHelper->initWiki($folderPath, $title); $folderId = $this->wikiHelper->create($folderPath, $title);
if ( $folderId === null ) { if ( $folderId === null ) {
throw new ReadOnlyException('Error creating wiki'); throw new ReadOnlyException('Error creating wiki');
} }
@ -79,7 +79,8 @@ class WikiService {
try { try {
$wiki = $this->mapper->find($id, $userId); $wiki = $this->mapper->find($id, $userId);
$wiki->setTitle($title); $wiki->setTitle($title);
return $this->mapper->update($wiki); $res = $this->mapper->update($wiki);
return $res;
} catch(Exception $e) { } catch(Exception $e) {
$this->handleException($e); $this->handleException($e);
} }

View File

@ -1,6 +1,7 @@
<?php <?php
\OCP\Util::addScript('mywiki', 'WikiDropdownHelper'); \OCP\Util::addScript('mywiki', 'WikiDropdownHelper');
\OCP\Util::addScript('mywiki', 'WikiNavigation'); \OCP\Util::addScript('mywiki', 'WikiNavigation');
\OCP\Util::addScript('mywiki', 'WikiPages');
\OCP\Util::addScript('mywiki', 'script'); \OCP\Util::addScript('mywiki', 'script');
\OCP\Util::addStyle('mywiki', 'style'); \OCP\Util::addStyle('mywiki', 'style');
?> ?>

View File

@ -11,22 +11,16 @@
<div class="app-navigation-entry-menu"> <div class="app-navigation-entry-menu">
<ul> <ul>
<li> <li>
<a href="#" data-id="add"> <button data-id="add" class="icon-folder">Add Wiki</button>
<span class="icon-add"></span>
<span>Add</span>
</a>
</li> </li>
<li> <li>
<a href="#" data-id="rename"> <button disabled data-id="addPage" class="icon-add">Add Page</button>
<span class="icon-rename"></span>
<span>Edit</span>
</a>
</li> </li>
<li> <li>
<a href="#" data-id="delete"> <button disabled data-id="rename" class="icon-rename">Rename Wiki</button>
<span class="icon-delete"></span> </li>
<span>Remove</span> <li>
</a> <button disabled data-id="delete" class="icon-delete">Delete Wiki</button>
</li> </li>
</ul> </ul>
</div> </div>