1*f4b18c92SGill B.<?php 2*f4b18c92SGill B.if(!defined('DOKU_INC')) die(); 3*f4b18c92SGill B. 4*f4b18c92SGill B.class syntax_plugin_kanban extends DokuWiki_Syntax_Plugin { 5*f4b18c92SGill B. public function getType() { return 'substition'; } 6*f4b18c92SGill B. public function getSort() { return 150; } 7*f4b18c92SGill B. public function connectTo($mode) { 8*f4b18c92SGill B. $this->Lexer->addSpecialPattern('\{\{kanban>.*?\}\}', $mode, 'plugin_kanban'); 9*f4b18c92SGill B. } 10*f4b18c92SGill B. 11*f4b18c92SGill B. public function handle($match, $state, $pos, Doku_Handler $handler) { 12*f4b18c92SGill B. return [substr($match, 9, -2)]; 13*f4b18c92SGill B. 14*f4b18c92SGill B. } 15*f4b18c92SGill B. 16*f4b18c92SGill B. public function render($mode, Doku_Renderer $renderer, $data) { 17*f4b18c92SGill B. if ($mode != 'xhtml') return false; 18*f4b18c92SGill B. global $conf; 19*f4b18c92SGill B. //$mydata = str_split("||",$data); 20*f4b18c92SGill B. list($boardName) = $data; 21*f4b18c92SGill B. //echo $boardName;//debugging line 22*f4b18c92SGill B. //list($boardName) = $mydata[0]; 23*f4b18c92SGill B. //list($boardList) = $mydata[1]; 24*f4b18c92SGill B. list($var1, $var2) = explode("+", $boardName); //added - 5-8-2026 25*f4b18c92SGill B. //Change the variable back to boardName 26*f4b18c92SGill B. $boardName = $var1;//added - 5-8-2026 27*f4b18c92SGill B. // Path to individual card files: data/kanban/[boardName]/*.json 28*f4b18c92SGill B. // $kanbanDir = $conf['savedir'] . '/kanban/' . $boardName . '/'; //WORKS!! 29*f4b18c92SGill B. $kanbanDir = $conf['savedir'] . '/kanban/' . $boardName . '/'; //added - 5-8-2026 30*f4b18c92SGill B. 31*f4b18c92SGill B. // Dynamically create the directory if it doesn't exist 32*f4b18c92SGill B. if (!is_dir($kanbanDir)) io_makeFileDir($kanbanDir . 'placeholder.txt'); 33*f4b18c92SGill B. 34*f4b18c92SGill B. $renderer->doc .= '<div class="kanban-board" data-board="' . hsc($boardName) . '">'; 35*f4b18c92SGill B. // $columns = ['Projects', 'WIP', 'On Hold', 'Done']; // WORKS!! 36*f4b18c92SGill B. // echo $var2; 37*f4b18c92SGill B. $headers = explode(",",$var2); //added - 5-8-2026 38*f4b18c92SGill B. $outpea = [];//added - 5-8-2026 39*f4b18c92SGill B. $thankee = count($headers);//added - 5-8-2026 40*f4b18c92SGill B. for($x=0;$x<$thankee;$x++){//added - 5-8-2026 41*f4b18c92SGill B. if($headers[$x] && $headers[$x] != "" && !is_null($headers[$x])){//added - 5-8-2026 42*f4b18c92SGill B. $outpea[$x] = $headers[$x];//added - 5-8-2026 43*f4b18c92SGill B. }else{//added - 5-8-2026 44*f4b18c92SGill B. continue;//added - 5-8-2026 45*f4b18c92SGill B. }//added - 5-8-2026 46*f4b18c92SGill B. }//added - 5-8-2026 47*f4b18c92SGill B. $columns = $outpea;//added - 5-8-2026 48*f4b18c92SGill B. $colVal=0;//added - 5-8-2026 49*f4b18c92SGill B. 50*f4b18c92SGill B. // Load all .json files in the board directory 51*f4b18c92SGill B. $savedCards = []; 52*f4b18c92SGill B. foreach (glob($kanbanDir . "*.json") as $file) { 53*f4b18c92SGill B. $card = json_decode(io_readFile($file), true); 54*f4b18c92SGill B. if ($card) $savedCards[] = $card; 55*f4b18c92SGill B. } 56*f4b18c92SGill B. 57*f4b18c92SGill B. foreach ($columns as $col) { 58*f4b18c92SGill B. 59*f4b18c92SGill B. $id = strtolower(str_replace(' ', '-', $col)); 60*f4b18c92SGill B. $renderer->doc .= '<div class="kanban-col" data-id="' . $id . '">'; 61*f4b18c92SGill B. $renderer->doc .= ' <h3>' . hsc($col) . '</h3>'; 62*f4b18c92SGill B. $renderer->doc .= ' <div class="cards-container"><div class="kanban-card-locked" data-id=0"><div class="triple-lines"></div></div>'; 63*f4b18c92SGill B. 64*f4b18c92SGill B. foreach ($savedCards as $card) { 65*f4b18c92SGill B. if ($card['column'] === $id) { 66*f4b18c92SGill B. $renderer->doc .= $this->_renderCardHtml($card); 67*f4b18c92SGill B. } 68*f4b18c92SGill B. } 69*f4b18c92SGill B. if($colVal!==0){//added - 5-8-2026 70*f4b18c92SGill B. $renderer->doc .= ' </div></div>';//added - 5-8-2026 71*f4b18c92SGill B. }else{//added - 5-8-2026 72*f4b18c92SGill B. $renderer->doc .= ' </div><button class="add-card-btn">+ Add Card</button></div>'; 73*f4b18c92SGill B. //$renderer->doc .= ' </div><button class="add-col-btn">+ Add Column</button> <button class="add-card-btn">+ Add Card</button></div>';//added - 5-8-2026 74*f4b18c92SGill B. }//added - 5-8-2026 75*f4b18c92SGill B. $colVal = ($colVal + 1);//added - 5-8-2026 76*f4b18c92SGill B. } 77*f4b18c92SGill B. $renderer->doc .= '<div>My name goes here</div></div>'; 78*f4b18c92SGill B. 79*f4b18c92SGill B. return true; 80*f4b18c92SGill B. } 81*f4b18c92SGill B. 82*f4b18c92SGill B. private function _renderCardHtml($card) { 83*f4b18c92SGill B. $currNote = hsc($card['note']); 84*f4b18c92SGill B. $imp = hsc($card['importance'] ?? 'medium'); 85*f4b18c92SGill B. if(hsc($card['checked']) !== "true"){ 86*f4b18c92SGill B. $dat = ""; 87*f4b18c92SGill B. }else{ 88*f4b18c92SGill B. $dat = "checked"; 89*f4b18c92SGill B. } 90*f4b18c92SGill B. $fullNotes = ''; 91*f4b18c92SGill B. $notes=hsc($card['note']); 92*f4b18c92SGill B. $notif = explode("+",$notes); 93*f4b18c92SGill B. array_map('trim', $notif); 94*f4b18c92SGill B. foreach($notif as $note){ 95*f4b18c92SGill B. if($note == ""){ 96*f4b18c92SGill B. continue; 97*f4b18c92SGill B. }else{ 98*f4b18c92SGill B. $fullNotes = $fullNotes . "+ " . $note . "<br>"; 99*f4b18c92SGill B. } 100*f4b18c92SGill B. } 101*f4b18c92SGill B. 102*f4b18c92SGill B. //return the card data only if the card has not been checked complete 103*f4b18c92SGill B. if($dat != "checked"){ 104*f4b18c92SGill B. return '<div class="kanban-card '.$imp.'" data-id="'.hsc($card['id']).'">' 105*f4b18c92SGill B. . '<input type="checkbox" ' . $dat . '>' 106*f4b18c92SGill B. . '<strong class="card-title">'.hsc($card['name']).'</strong><div id="noteDiv" class="noteDiv">Content</div>' 107*f4b18c92SGill B. . '<div class="card-desc">'.hsc($card['desc'] ?? '').'</div>' 108*f4b18c92SGill B. . '<input class="btn-notes" value="+Add Note">' 109*f4b18c92SGill B. . '<div class="card-note">' . $fullNotes . '</div></div>'; 110*f4b18c92SGill B. } 111*f4b18c92SGill B. } 112*f4b18c92SGill B.} 113