Initial commit
This commit is contained in:
62
app/plugins/todo/controllers/api/lists.php
Normal file
62
app/plugins/todo/controllers/api/lists.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/todo/controllers/tasts.php
|
||||
*
|
||||
* This is the task lists' API controller.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers\Api;
|
||||
|
||||
use TheTempusProject\Models\Tasklists as ListModel;
|
||||
use TheTempusProject\Classes\ApiController;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
|
||||
class Lists extends ApiController {
|
||||
protected static $lists;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$lists = new ListModel;
|
||||
}
|
||||
|
||||
public function hide( $id = null ) {
|
||||
$list = self::$lists->get( $id );
|
||||
if ( ! $list ) {
|
||||
$responseType = 'error';
|
||||
$response = 'No list found.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = self::$lists->hide( $id );
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
|
||||
public function delete( $id = null ) {
|
||||
$list = self::$lists->get( $id );
|
||||
if ( ! $list ) {
|
||||
$responseType = 'error';
|
||||
$response = 'No list found.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = self::$lists->delete( $id );
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
|
||||
public function home( $id = null ) {
|
||||
$list = self::$lists->get( $id );
|
||||
if ( ! $list ) {
|
||||
$responseType = 'error';
|
||||
$response = 'No list found.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = $list;
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
}
|
62
app/plugins/todo/controllers/api/tasks.php
Normal file
62
app/plugins/todo/controllers/api/tasks.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/todo/controllers/tasts.php
|
||||
*
|
||||
* This is the tasks' API controller.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers\Api;
|
||||
|
||||
use TheTempusProject\Models\Tasks as TaskModel;
|
||||
use TheTempusProject\Classes\ApiController;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
|
||||
class Tasks extends ApiController {
|
||||
protected static $tasks;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$tasks = new TaskModel;
|
||||
}
|
||||
|
||||
public function complete( $id = null ) {
|
||||
$task = self::$tasks->get( $id );
|
||||
if ( ! $task ) {
|
||||
$responseType = 'error';
|
||||
$response = 'No task found.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = self::$tasks->complete( $id );
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
|
||||
public function delete( $id = null ) {
|
||||
$task = self::$tasks->get( $id );
|
||||
if ( ! $task ) {
|
||||
$responseType = 'error';
|
||||
$response = 'No task found.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = self::$tasks->delete( $id );
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
|
||||
public function home( $id = null ) {
|
||||
$task = self::$tasks->get( $id );
|
||||
if ( ! $task ) {
|
||||
$responseType = 'error';
|
||||
$response = 'No task found.';
|
||||
} else {
|
||||
$responseType = 'data';
|
||||
$response = $task;
|
||||
}
|
||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||
}
|
||||
}
|
371
app/plugins/todo/controllers/todo.php
Normal file
371
app/plugins/todo/controllers/todo.php
Normal file
@ -0,0 +1,371 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/todo/controllers/todo.php
|
||||
*
|
||||
* This is the todo controller.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Controllers;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Classes\Controller;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
use TheTempusProject\Houdini\Classes\Forms as FormBuilder;
|
||||
use TheTempusProject\Models\Tasks;
|
||||
use TheTempusProject\Models\Tasklists;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Classes\Config;
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
|
||||
class Todo extends Controller {
|
||||
protected static $tasks;
|
||||
protected static $lists;
|
||||
protected static $showHidden;
|
||||
protected static $listView;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
if ( !App::$isLoggedIn ) {
|
||||
Session::flash( 'notice', 'You must be logged in to use this feature.' );
|
||||
return Redirect::home();
|
||||
}
|
||||
self::$tasks = new Tasks;
|
||||
self::$lists = new Tasklists;
|
||||
self::$title = 'To-Do - {SITENAME}';
|
||||
self::$pageDescription = 'On this page you can create and manage tasks and lists.';
|
||||
|
||||
|
||||
if ( Input::exists('includeCompleted') && 'true' == Input::get('includeCompleted') ) {
|
||||
self::$showHidden = true;
|
||||
Components::set( 'completedToggleText', 'Hide' );
|
||||
Components::set( 'completedToggle', 'false' );
|
||||
} else {
|
||||
self::$showHidden = false;
|
||||
Components::set( 'completedToggleText', 'Show' );
|
||||
Components::set( 'completedToggle', 'true' );
|
||||
}
|
||||
|
||||
$taskTabs = Views::simpleView( 'todo.nav.listTabs' );
|
||||
if ( stripos( Input::get('url'), 'todo/list' ) !== false ) {
|
||||
$tabsView = Navigation::activePageSelect( $taskTabs, '/todo/list/', false, true );
|
||||
$userListTabs = Views::simpleView('todo.nav.userListTabs', self::$lists->simpleObjectByUser(true) );
|
||||
$userListTabsView = Navigation::activePageSelect( $userListTabs, Input::get( 'url' ), false, true );
|
||||
} else {
|
||||
$tabsView = Navigation::activePageSelect( $taskTabs, Input::get( 'url' ), false, true );
|
||||
$userListTabsView = '';
|
||||
}
|
||||
Components::set( 'userListTabs', $userListTabsView );
|
||||
Views::raw( $tabsView );
|
||||
}
|
||||
public function index() {
|
||||
Components::set( 'listName', 'All' );
|
||||
Components::set( 'listID', '' );
|
||||
|
||||
$recentlyCompleted = Views::simpleView( 'todo.tasks.list', self::$tasks->recentlyCompleted( 10 ) );
|
||||
Components::set( 'recentlyCompleted', $recentlyCompleted );
|
||||
|
||||
$dailyTasks = Views::simpleView( 'todo.tasks.daily', self::$tasks->dailyTasks( 10 ) );
|
||||
Components::set( 'dailyTasks', $dailyTasks );
|
||||
|
||||
$weeklyTasks = Views::simpleView( 'todo.tasks.weekly', self::$tasks->weeklyTasks( 10 ) );
|
||||
Components::set( 'weeklyTasks', $weeklyTasks );
|
||||
|
||||
$monthlyTasks = Views::simpleView( 'todo.tasks.monthly', self::$tasks->monthlyTasks( 10 ) );
|
||||
Components::set( 'monthlyTasks', $monthlyTasks );
|
||||
|
||||
$yearlyTasks = Views::simpleView( 'todo.tasks.yearly', self::$tasks->yearlyTasks( 10 ) );
|
||||
Components::set( 'yearlyTasks', $yearlyTasks );
|
||||
|
||||
$tasks = Views::simpleView( 'todo.tasks.list', self::$tasks->recent( 10 ) );
|
||||
Components::set( 'taskList', $tasks );
|
||||
|
||||
$lists = Views::simpleView( 'todo.lists.list', self::$lists->recent() );
|
||||
Components::set( 'listList', $lists );
|
||||
|
||||
Views::view( 'todo.dashboard' );
|
||||
}
|
||||
public function daily() {
|
||||
Views::view( 'todo.tasks.daily', self::$tasks->dailyTasks( 10, self::$showHidden ) );
|
||||
}
|
||||
public function weekly() {
|
||||
Views::view( 'todo.tasks.weekly', self::$tasks->weeklyTasks( 10, self::$showHidden ) );
|
||||
}
|
||||
public function monthly() {
|
||||
Views::view( 'todo.tasks.monthly', self::$tasks->monthlyTasks( 10, self::$showHidden ) );
|
||||
}
|
||||
public function yearly() {
|
||||
Views::view( 'todo.tasks.yearly', self::$tasks->yearlyTasks( 10, self::$showHidden ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists
|
||||
*/
|
||||
public function list( $id = 0 ) {
|
||||
$list = self::$lists->findById( $id );
|
||||
if ( $list == false ) {
|
||||
$lists = self::$lists->recent();
|
||||
return Views::view( 'todo.lists.list', $lists );
|
||||
}
|
||||
Components::set( 'listID', $id );
|
||||
if ( Input::exists('includeCompleted') && 'true' == Input::get('includeCompleted') ) {
|
||||
$include_completed = true;
|
||||
} else {
|
||||
$include_completed = false;
|
||||
}
|
||||
$tasks = self::$tasks->findByListId( $id, $include_completed );
|
||||
Components::set( 'listName', $list->title );
|
||||
Components::set( 'CONTENT_ID', $id );
|
||||
Components::set( 'COMMENT_TYPE', 'tasklist' );
|
||||
Views::view( 'todo.tasks.list', $tasks );
|
||||
}
|
||||
public function createList() {
|
||||
if ( !Input::exists() ) {
|
||||
return Views::view( 'todo.lists.create' );
|
||||
}
|
||||
if ( !Forms::check( 'createTaskList' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error creating your task list.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.lists.create' );
|
||||
}
|
||||
if ( !self::$lists->create( Input::post( 'listName' )) ) {
|
||||
Issues::add( 'error', [ 'There was an error creating your task list.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.lists.create' );
|
||||
}
|
||||
Session::flash( 'success', 'Your Task List has been created.' );
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
public function editList( $id = null ) {
|
||||
$list = self::$lists->findById( $id );
|
||||
if ( $list == false ) {
|
||||
Issues::add( 'error', 'TaskList not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( !Input::exists() ) {
|
||||
return Views::view( 'todo.lists.edit', $list );
|
||||
}
|
||||
if ( !Forms::check( 'editTaskList' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your todo task.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.lists.edit', $list );
|
||||
}
|
||||
if ( !self::$lists->update( $id, Input::post( 'listName' ) ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your todo task.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.lists.edit', $list );
|
||||
}
|
||||
Session::flash( 'success', 'Your Task List has been saved.' );
|
||||
Redirect::to( 'todo/list/' . $id );
|
||||
}
|
||||
public function deleteList( $id = null ) {
|
||||
$list = self::$lists->findById( $id );
|
||||
if ( $list == false ) {
|
||||
Issues::add( 'error', 'TaskList not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $list->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this calendar.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$lists->delete( $id );
|
||||
if ( !$result ) {
|
||||
Issues::add( 'error', 'There was an error deleting the list(s)' );
|
||||
} else {
|
||||
Issues::add( 'success', 'List deleted' );
|
||||
}
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tasks
|
||||
*/
|
||||
public function task( $id = null ) {
|
||||
$task = self::$tasks->findById( $id );
|
||||
if ( $task == false ) {
|
||||
$tasks = self::$tasks->recent();
|
||||
return Views::view( 'todo.tasks.list', $tasks );
|
||||
}
|
||||
Components::set( 'CONTENT_ID', $id );
|
||||
Components::set( 'COMMENT_TYPE', 'task' );
|
||||
Views::view( 'todo.tasks.view', $task );
|
||||
}
|
||||
public function createTask( $id = null ) {
|
||||
if ( in_array( $id, self::$tasks->repeatOptions ) ) {
|
||||
$repeat = $id;
|
||||
$id = 'non';
|
||||
} else {
|
||||
$repeat = 'none';
|
||||
$id = $id;
|
||||
}
|
||||
|
||||
// @todo need to make this change if it 'id' is actually a repeats value
|
||||
$select = FormBuilder::getFormFieldHtml(
|
||||
'listID',
|
||||
'Task List',
|
||||
'select',
|
||||
$id,
|
||||
self::$lists->getSimpleList(true),
|
||||
);
|
||||
Components::set( 'listSelect', $select );
|
||||
|
||||
$repeatSelect = FormBuilder::getFormFieldHtml( 'repeats', 'Frequency', 'select', $repeat, self::$tasks->repeatOptions );
|
||||
Components::set( 'repeatSelect', $repeatSelect );
|
||||
if ( !Input::exists() ) {
|
||||
return Views::view( 'todo.tasks.create' );
|
||||
}
|
||||
if ( !Forms::check( 'createTask' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.tasks.create' );
|
||||
}
|
||||
if ( !self::$tasks->create( Input::post( 'task' ), 'false', Input::post( 'dueDate' ), Input::post( 'listID' ), Input::post( 'repeats' ) ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your todo task.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.tasks.create' );
|
||||
}
|
||||
Session::flash( 'success', 'Your Task has been created.' );
|
||||
if ( Input::exists( 'listID' ) ) {
|
||||
Redirect::to( 'todo/list/' . Input::post( 'listID' ) );
|
||||
} else {
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
}
|
||||
public function editTask( $id = null ) {
|
||||
$task = self::$tasks->findById( $id );
|
||||
if ( $task == false ) {
|
||||
Issues::add( 'error', 'Task not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $task->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this task.' );
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
$select = FormBuilder::getFormFieldHtml(
|
||||
'listID',
|
||||
'Task List',
|
||||
'select',
|
||||
$task->listID,
|
||||
self::$lists->getSimpleList(true),
|
||||
);
|
||||
Components::set( 'listSelect', $select );
|
||||
|
||||
$repeatSelect = FormBuilder::getFormFieldHtml( 'repeats', 'Frequency', 'select', $task->repeats, self::$tasks->repeatOptions );
|
||||
Components::set( 'repeatSelect', $repeatSelect );
|
||||
|
||||
if ( !Input::exists( 'submit' ) ) {
|
||||
return Views::view( 'todo.tasks.edit', $task );
|
||||
}
|
||||
if ( !Forms::check( 'editTask' ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
|
||||
return Views::view( 'todo.tasks.edit', $task );
|
||||
}
|
||||
if ( self::$tasks->update( $id, Input::post( 'task' ), $task->completed, Input::post( 'dueDate' ), Input::post( 'listID' ), Input::post( 'repeats' ) ) ) {
|
||||
Session::flash( 'success', 'Task updated' );
|
||||
} else {
|
||||
return Views::view( 'todo.tasks.edit', self::$tasks->findById( $data ) );
|
||||
}
|
||||
if ( !empty( $task->listID ) ) {
|
||||
Redirect::to( 'todo/list/' . $task->listID );
|
||||
} else {
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
}
|
||||
public function deleteTask( $id = null ) {
|
||||
$task = self::$tasks->findById( $id );
|
||||
if ( $task == false ) {
|
||||
Issues::add( 'error', 'Task not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $task->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this task.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$tasks->delete( $id );
|
||||
if ( !$result ) {
|
||||
Session::flash( 'error', 'There was an error deleting the task(s)' );
|
||||
} else {
|
||||
Session::flash( 'success', 'Task deleted' );
|
||||
}
|
||||
if ( !empty( $task->listID ) ) {
|
||||
Redirect::to( 'todo/list/' . $task->listID );
|
||||
} else {
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
}
|
||||
public function duplicateTask( $id = null ) {
|
||||
$task = self::$tasks->findById( $id );
|
||||
if ( $task == false ) {
|
||||
Issues::add( 'error', 'Task not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $task->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this task.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $task->repeats != 'none' ) {
|
||||
Issues::add( 'error', 'You cannot duplicate a repeating task.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( ! self::$tasks->duplicate( $id ) ) {
|
||||
Session::flash( 'error', [ 'There was an error duplicating your todo task.'] );
|
||||
} else {
|
||||
Session::flash( 'success', 'Your Task has been duplicated.' );
|
||||
}
|
||||
if ( !empty( $task->listID ) ) {
|
||||
Redirect::to( 'todo/list/' . $task->listID );
|
||||
} else {
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
}
|
||||
public function completeTask( $id = null ) {
|
||||
$task = self::$tasks->findById( $id );
|
||||
if ( $task == false ) {
|
||||
Issues::add( 'error', 'Task not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $task->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this task.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$tasks->complete( $id );
|
||||
if ( !$result ) {
|
||||
Session::flash( 'error', 'There was an error completing the task(s)' );
|
||||
} else {
|
||||
Session::flash( 'success', 'Task completed' );
|
||||
}
|
||||
if ( !empty( $task->listID ) ) {
|
||||
Redirect::to( 'todo/list/' . $task->listID );
|
||||
} else {
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
}
|
||||
public function incompleteTask( $id = null ) {
|
||||
$task = self::$tasks->findById( $id );
|
||||
if ( $task == false ) {
|
||||
Issues::add( 'error', 'Task not found.' );
|
||||
return $this->index();
|
||||
}
|
||||
if ( $task->createdBy != App::$activeUser->ID ) {
|
||||
Issues::add( 'error', 'You do not have permission to modify this task.' );
|
||||
return $this->index();
|
||||
}
|
||||
$result = self::$tasks->incomplete( $id );
|
||||
if ( ! $result ) {
|
||||
Session::flash( 'error', 'There was an error un-completing the task(s)' );
|
||||
} else {
|
||||
Session::flash( 'success', 'Task un-completed' );
|
||||
}
|
||||
if ( !empty( $task->listID ) ) {
|
||||
Redirect::to( 'todo/list/' . $task->listID );
|
||||
} else {
|
||||
Redirect::to( 'todo/index' );
|
||||
}
|
||||
}
|
||||
}
|
96
app/plugins/todo/forms.php
Normal file
96
app/plugins/todo/forms.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/bugtracker/forms.php
|
||||
*
|
||||
* This houses all of the form checking functions for this plugin.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins\Todo;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Classes\Forms;
|
||||
|
||||
class TodoForms extends Forms {
|
||||
/**
|
||||
* Adds these functions to the form list.
|
||||
*/
|
||||
public function __construct() {
|
||||
self::addHandler( 'createTask', __CLASS__, 'createTask' );
|
||||
self::addHandler( 'editTask', __CLASS__, 'editTask' );
|
||||
self::addHandler( 'createTaskList', __CLASS__, 'createTaskList' );
|
||||
self::addHandler( 'editTaskList', __CLASS__, 'editTaskList' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the bug tracker create form.
|
||||
*
|
||||
* @return {bool}
|
||||
*/
|
||||
public static function createTask() {
|
||||
if ( ! empty(Input::post( 'dueDate' )) && !self::date( Input::post( 'dueDate' ) ) ) {
|
||||
self::addUserError( 'Invalid Date.' . Input::post( 'dueDate' ) );
|
||||
return false;
|
||||
}
|
||||
if ( ! empty( Input::post( 'listID' ) ) && !self::id( Input::post( 'listID' ) ) ) {
|
||||
self::addUserError( 'Invalid Date.' . Input::post( 'dueDate' ) );
|
||||
return false;
|
||||
}
|
||||
if ( !Input::exists( 'task' ) ) {
|
||||
self::addUserError( 'You must specify a task' );
|
||||
return false;
|
||||
}
|
||||
// if ( !self::token() ) {
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function createTaskList() {
|
||||
if ( !Input::exists( 'listName' ) ) {
|
||||
self::addUserError( 'You must specify a title' );
|
||||
return false;
|
||||
}
|
||||
// if ( !self::token() ) {
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function editTaskList() {
|
||||
if ( !Input::exists( 'listName' ) ) {
|
||||
self::addUserError( 'You must specify a title' );
|
||||
return false;
|
||||
}
|
||||
// if ( !self::token() ) {
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the bug tracker create form.
|
||||
*
|
||||
* @return {bool}
|
||||
*/
|
||||
public static function editTask() {
|
||||
if ( !empty(Input::post( 'dueDate' )) && !self::date( Input::post( 'dueDate' ) ) ) {
|
||||
self::addUserError( 'Invalid Date.' . Input::post( 'dueDate' ) );
|
||||
return false;
|
||||
}
|
||||
if ( !Input::exists( 'task' ) ) {
|
||||
self::addUserError( 'You must specify a task' );
|
||||
return false;
|
||||
}
|
||||
// if ( !self::token() ) {
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
new TodoForms;
|
199
app/plugins/todo/models/tasklists.php
Normal file
199
app/plugins/todo/models/tasklists.php
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/todo/models/todo.php
|
||||
*
|
||||
* This class is used for the manipulation of the tasks database table.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Classes\Config;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\Plugins\Bugreport as Plugin;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
|
||||
class Tasklists extends DatabaseModel {
|
||||
public $tableName = 'tasklists';
|
||||
public $databaseMatrix = [
|
||||
[ 'title', 'varchar', '128' ],
|
||||
[ 'active', 'varchar', '5' ],
|
||||
[ 'createdAt', 'int', '10' ],
|
||||
[ 'color', 'varchar', '48' ],
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
];
|
||||
public $plugin;
|
||||
|
||||
/**
|
||||
* The model constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->plugin = new Plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function parses the bug reports description and
|
||||
* separates it into separate keys in the array.
|
||||
*
|
||||
* @param array $data - The data being parsed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filter( $data, $params = [] ) {
|
||||
foreach ( $data as $instance ) {
|
||||
if ( !is_object( $instance ) ) {
|
||||
$instance = $data;
|
||||
$end = true;
|
||||
}
|
||||
$instance->submittedBy = self::$user->getUsername( $instance->createdBy );
|
||||
$out[] = $instance;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a Bug Report form.
|
||||
*
|
||||
* @param int $ID the user ID submitting the form
|
||||
* @param string $url the url
|
||||
* @param string $o_url the original url
|
||||
* @param int $repeat is repeatable?
|
||||
* @param string $description_ description of the event.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function create( $title, $active = 'true' ) {
|
||||
if ( !$this->plugin->checkEnabled() ) {
|
||||
Debug::info( 'ToDo Plugin is disabled in the config.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'createdAt' => time(),
|
||||
'title' => $title,
|
||||
'active' => $active,
|
||||
];
|
||||
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
|
||||
public function update( $ID, $title, $active = 'true' ) {
|
||||
if ( !$this->plugin->checkEnabled() ) {
|
||||
Debug::info( 'ToDo Plugin is disabled in the config.' );
|
||||
return false;
|
||||
}
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'ToDo List: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$data = $this->findById( $ID );
|
||||
if ( $data == false ) {
|
||||
Debug::info( 'ToDo List: not found.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'title' => $title,
|
||||
'active' => $active,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "ToDo List: $ID not updated: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function activate( $ID ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'TaskList: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'active' => 'true',
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "TaskList: $ID not activated: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hide( $ID ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'TaskList: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'active' => 'false',
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "TaskList: $ID not Hidden: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function recent( $limit = null ) {
|
||||
$where = ['createdBy', '=', App::$activeUser->ID];
|
||||
$data = self::$db->get( $this->tableName, $where, 'createdAt', 'DESC', [0, $limit] );
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
|
||||
return [];
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
|
||||
public function getSimpleList( $includeDefault = false ) {
|
||||
$out = [];
|
||||
if ( $includeDefault === true ) {
|
||||
$out[ 'No List' ] = 0;
|
||||
}
|
||||
$lists = self::$db->get( $this->tableName, [ 'createdBy', '=', App::$activeUser->ID ] );
|
||||
if ( !$lists->count() ) {
|
||||
Debug::warn( 'Could not find any ' . $this->tableName );
|
||||
return $out;
|
||||
}
|
||||
$taskLists = $lists->results();
|
||||
foreach ( $taskLists as &$list ) {
|
||||
$out[ $list->title ] = $list->ID;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function simpleObjectByUser() {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||
$lists = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( !$lists->count() ) {
|
||||
Debug::warn( 'Could not find any tasklists' );
|
||||
return false;
|
||||
}
|
||||
|
||||
$taskLists = $lists->results();
|
||||
$out = [];
|
||||
foreach ( $taskLists as &$list ) {
|
||||
$obj = new \stdClass();
|
||||
$obj->title = $list->title;
|
||||
$obj->ID = $list->ID;
|
||||
$out[] = $obj;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
392
app/plugins/todo/models/tasks.php
Normal file
392
app/plugins/todo/models/tasks.php
Normal file
@ -0,0 +1,392 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/todo/models/todo.php
|
||||
*
|
||||
* This class is used for the manipulation of the tasks database table.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Models;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Classes\Config;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\Plugins\Bugreport as Plugin;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Bedrock\Functions\Date;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
|
||||
class Tasks extends DatabaseModel {
|
||||
public $tableName = 'tasks';
|
||||
public $databaseMatrix = [
|
||||
[ 'task', 'varchar', '128' ],
|
||||
[ 'completed', 'varchar', '5' ],
|
||||
[ 'completedAt', 'int', '10' ],
|
||||
[ 'completedBy', 'int', '10' ],
|
||||
[ 'dueDate', 'int', '10' ],
|
||||
[ 'createdAt', 'int', '10' ],
|
||||
[ 'createdBy', 'int', '11' ],
|
||||
[ 'listID', 'int', '11' ],
|
||||
[ 'color', 'varchar', '48' ],
|
||||
[ 'parentID', 'int', '11' ],
|
||||
[ 'repeats', 'varchar', '48' ],
|
||||
];
|
||||
public $plugin;
|
||||
public $repeatOptions = [
|
||||
'Does Not Repeat' => 'none',
|
||||
'Every Day' => 'daily',
|
||||
'Every Week' => 'weekly',
|
||||
'Every Month' => 'monthly',
|
||||
'Every Year' => 'yearly',
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->plugin = new Plugin;
|
||||
}
|
||||
|
||||
public function filter( $data, $params = [] ) {
|
||||
foreach ( $data as $instance ) {
|
||||
if ( !is_object( $instance ) ) {
|
||||
$instance = $data;
|
||||
$end = true;
|
||||
}
|
||||
|
||||
if ( 'true' == $instance->completed ) {
|
||||
$url = Template::parse(
|
||||
'<a href="{ROOT_URL}todo/incompleteTask/'.$instance->ID.'" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-remove"></i></a>'
|
||||
);
|
||||
$instance->completedUrl = $url;
|
||||
} else {
|
||||
$url = Template::parse(
|
||||
'<a href="{ROOT_URL}todo/completeTask/'.$instance->ID.'" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-ok"></i></a>'
|
||||
);
|
||||
$instance->completedUrl = $url;
|
||||
}
|
||||
|
||||
$out[] = $instance;
|
||||
if ( !empty( $end ) ) {
|
||||
$out = $out[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function create( $task, $completed = 'false', $dueDate = null, $list = 0, $repeats = 'none') {
|
||||
if ( !$this->plugin->checkEnabled() ) {
|
||||
Debug::info( 'ToDo Plugin is disabled in the config.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'task' => $task,
|
||||
'completed' => $completed,
|
||||
'listID' => intval($list),
|
||||
'repeats' => $repeats,
|
||||
'createdBy' => App::$activeUser->ID,
|
||||
'createdAt' => time(),
|
||||
];
|
||||
if ( !empty( $dueDate ) ) {
|
||||
$fields['dueDate'] = strtotime($dueDate);
|
||||
}
|
||||
if ( 'false' !== $completed ) {
|
||||
$fields['completedBy'] = App::$activeUser->ID;
|
||||
$fields['completedAt'] = time();
|
||||
} else {
|
||||
$fields['completedAt'] = '0';
|
||||
}
|
||||
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
return false;
|
||||
}
|
||||
return self::$db->lastId();
|
||||
}
|
||||
public function update( $ID, $task, $completed = "false", $dueDate = null, $list = 0, $repeats = 'none' ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'ToDo Task: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$data = $this->findById( $ID );
|
||||
if ( $data == false ) {
|
||||
Debug::info( 'ToDo Task: not found.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'task' => $task,
|
||||
'completed' => $completed,
|
||||
'listID' => intval($list),
|
||||
'repeats' => $repeats,
|
||||
];
|
||||
if ( !empty( $dueDate ) ) {
|
||||
$fields['dueDate'] = strtotime($dueDate);
|
||||
}
|
||||
if ( 'false' !== $completed && 'false' === $data->completed ) {
|
||||
$fields['completedBy'] = App::$activeUser->ID;
|
||||
$fields['completedAt'] = time();
|
||||
}
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "ToDo: $ID not updated: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function setActive( $ID ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'ToDo Task: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'completed' => 'false',
|
||||
'completedAt' => '0',
|
||||
'completedBy' => null,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "Task: $ID not Activated: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function recent( $limit = null, $include_completed = false ) {
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'ID', '>', '0'];
|
||||
if ( false == $include_completed ) {
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
'AND', 'completed', '!=', 'true'
|
||||
] );
|
||||
}
|
||||
if ( empty( $limit ) ) {
|
||||
$data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
public function recentlyCompleted( $limit = null ) {
|
||||
$whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND', 'completed', '=', 'true'];
|
||||
if ( empty( $limit ) ) {
|
||||
$data = self::$db->getPaginated( $this->tableName, $whereClause, 'completedAt', 'DESC' );
|
||||
} else {
|
||||
$data = self::$db->get( $this->tableName, $whereClause, 'completedAt', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
public function dailyTasks( $limit = null, $include_completed = false ) {
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'daily' ];
|
||||
if ( false == $include_completed ) {
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
// 'AND', 'completedAt', '<', Date::getDayStartTimestamp( '1735736400000', true ),
|
||||
'AND', 'completedAt', '<', Date::getDayStartTimestamp( time(), true ),
|
||||
] );
|
||||
}
|
||||
if ( empty( $limit ) ) {
|
||||
$data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
public function weeklyTasks( $limit = null, $include_completed = false ) {
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'weekly' ];
|
||||
if ( false == $include_completed ) {
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
'AND', 'completedAt', '<', Date::getWeekStartTimestamp( time(), true ),
|
||||
] );
|
||||
}
|
||||
if ( empty( $limit ) ) {
|
||||
$data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
public function monthlyTasks( $limit = null, $include_completed = false ) {
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'monthly' ];
|
||||
if ( false == $include_completed ) {
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
'AND', 'completedAt', '<', Date::getMonthStartTimestamp( time(), true ),
|
||||
] );
|
||||
}
|
||||
if ( empty( $limit ) ) {
|
||||
$data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] );
|
||||
}
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
public function yearlyTasks( $limit = null, $include_completed = false ) {
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'yearly' ];
|
||||
if ( false == $include_completed ) {
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
'AND', 'completedAt', '<', Date::getYearStartTimestamp( time(), true ),
|
||||
] );
|
||||
}
|
||||
if ( empty( $limit ) ) {
|
||||
$data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' );
|
||||
} else {
|
||||
$data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [ 0, $limit ] );
|
||||
}
|
||||
if ( !$data->count() ) {
|
||||
Debug::info( 'No tasks found.' );
|
||||
|
||||
return false;
|
||||
}
|
||||
return $this->filter( $data->results() );
|
||||
}
|
||||
public function findByListId( $id, $include_completed = false ) {
|
||||
$data = [];
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::warn( "$this->tableName findByListId: illegal ID: $id" );
|
||||
return $data;
|
||||
}
|
||||
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
'listID', '=', $id,
|
||||
] );
|
||||
if ( false == $include_completed ) {
|
||||
$whereClause = array_merge( $whereClause, [
|
||||
'AND', 'completed', '!=', 'true'
|
||||
] );
|
||||
}
|
||||
$tasks = self::$db->get( $this->tableName, $whereClause );
|
||||
if ( ! $tasks->count() ) {
|
||||
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||
return [];
|
||||
}
|
||||
return $this->filter( $tasks->results() );
|
||||
}
|
||||
public function duplicate( $ID, $completed = 'false' ) {
|
||||
if ( ! Check::id( $ID ) ) {
|
||||
Debug::info( 'ToDo Task: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$task = $this->findById( $ID );
|
||||
if ( $task == false ) {
|
||||
Debug::info( 'ToDo Task: not found.' );
|
||||
return false;
|
||||
}
|
||||
return $this->create( $task->task, $completed, $task->dueDate, $task->listID );
|
||||
}
|
||||
public function complete( $ID ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'ToDo Task: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$data = $this->findById( $ID );
|
||||
if ( $data == false ) {
|
||||
Debug::info( 'ToDo Task: not found.' );
|
||||
return false;
|
||||
}
|
||||
if ( 'none' == $data->repeats ) {
|
||||
$completed = 'true';
|
||||
$completedBy = App::$activeUser->ID;
|
||||
} else {
|
||||
$completed = 'false';
|
||||
$completedBy = $data->completedBy;
|
||||
$this->duplicate( $data->ID, 'true' );
|
||||
}
|
||||
$fields = [
|
||||
'completed' => $completed,
|
||||
'completedAt' => time(),
|
||||
'completedBy' => $completedBy,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "Task: $ID not Completed: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function incomplete( $ID ) {
|
||||
if ( !Check::id( $ID ) ) {
|
||||
Debug::info( 'ToDo Task: illegal ID.' );
|
||||
return false;
|
||||
}
|
||||
$data = $this->findById( $ID );
|
||||
if ( $data == false ) {
|
||||
Debug::info( 'ToDo Task: not found.' );
|
||||
return false;
|
||||
}
|
||||
if ( 'none' != $data->repeats ) {
|
||||
// this should not be possible as completing a repeating task duplicates it as a completed normal task
|
||||
Debug::info( 'There was an error with your request' );
|
||||
return false;
|
||||
}
|
||||
$fields = [
|
||||
'completed' => 'false',
|
||||
'completedAt' => '0',
|
||||
'completedBy' => null,
|
||||
];
|
||||
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||
new CustomException( $this->tableName );
|
||||
Debug::error( "Task: $ID not Completed: $fields" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private function isTaskCompleted( $repeats, $completedAt ) {
|
||||
if ( ! intval( $completedAt ) > 0 ) {
|
||||
return false;
|
||||
}
|
||||
switch ($repeats) {
|
||||
case 'none':
|
||||
return true;
|
||||
case 'daily':
|
||||
$start = Date::getDayStartTimestamp( time(), true );
|
||||
if ( $completedAt > $start ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'weekly':
|
||||
$start = Date::getWeekStartTimestamp( time(), true );
|
||||
if ( $completedAt > $start ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'monthly':
|
||||
$start = Date::getMonthStartTimestamp( time(), true );
|
||||
if ( $completedAt > $start ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'yearly':
|
||||
$start = Date::getYearStartTimestamp( time(), true );
|
||||
if ( $completedAt > $start ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
41
app/plugins/todo/plugin.php
Normal file
41
app/plugins/todo/plugin.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* app/plugins/todo/plugin.php
|
||||
*
|
||||
* This houses all of the main plugin info and functionality.
|
||||
*
|
||||
* @package TP ToDo
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Plugins;
|
||||
|
||||
use TheTempusProject\Classes\Plugin;
|
||||
|
||||
class Todo extends Plugin {
|
||||
public $pluginName = 'TP ToDo';
|
||||
public $pluginAuthor = 'JoeyK';
|
||||
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||
public $modelVersion = '1.0';
|
||||
public $pluginVersion = '3.0';
|
||||
public $pluginDescription = 'A simple plugin which adds a site wide to-do list.';
|
||||
public $permissionMatrix = [
|
||||
'createTas' => [
|
||||
'pretty' => 'Can create todo items',
|
||||
'default' => false,
|
||||
],
|
||||
'createList' => [
|
||||
'pretty' => 'Can create todo lists',
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
public $main_links = [
|
||||
[
|
||||
'text' => 'To-Do',
|
||||
'url' => '{ROOT_URL}todo/index/',
|
||||
'filter' => 'loggedin',
|
||||
],
|
||||
];
|
||||
}
|
36
app/plugins/todo/views/dashboard.html
Normal file
36
app/plugins/todo/views/dashboard.html
Normal file
@ -0,0 +1,36 @@
|
||||
<button id="hideLists" class="btn btn-primary">Show/Hide Lists</button>
|
||||
<button id="reorder" class="btn btn-primary">Reorder</button>
|
||||
<div class="row">
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<h3>Recently Completed</h3>
|
||||
{recentlyCompleted}
|
||||
</div>
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<h3>Daily Tasks</h3>
|
||||
{dailyTasks}
|
||||
</div>
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<h3>Weekly Tasks</h3>
|
||||
{weeklyTasks}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<h3>Monthly Tasks</h3>
|
||||
{monthlyTasks}
|
||||
</div>
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
<h3>Yearly Tasks</h3>
|
||||
{yearlyTasks}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Task Lists</h3>
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
{listList}
|
||||
</div>
|
||||
<h3>Recently Created Tasks</h3>
|
||||
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||
{taskList}
|
||||
</div>
|
||||
</div>
|
19
app/plugins/todo/views/lists/create.html
Normal file
19
app/plugins/todo/views/lists/create.html
Normal file
@ -0,0 +1,19 @@
|
||||
<legend>New Task List</legend>
|
||||
{BREADCRUMB}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label for="listName" class="col-lg-3 control-label">List Name:</label>
|
||||
<div class="col-lg-3">
|
||||
<input class="form-control" type="text" name="listName" id="listName">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="submit" class="col-lg-3 control-label"></label>
|
||||
<div class="col-lg-3">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Create</button><br>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
14
app/plugins/todo/views/lists/edit.html
Normal file
14
app/plugins/todo/views/lists/edit.html
Normal file
@ -0,0 +1,14 @@
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<legend>Edit Task List</legend>
|
||||
{BREADCRUMB}
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label for="listName" class="col-lg-6 control-label">List Name:</label>
|
||||
<div class="col-lg-2">
|
||||
<input class="form-control" type="text" name="listName" id="listName" value="{title}">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Save</button><br>
|
||||
</form>
|
32
app/plugins/todo/views/lists/list.html
Normal file
32
app/plugins/todo/views/lists/list.html
Normal file
@ -0,0 +1,32 @@
|
||||
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
|
||||
<form action="" method="post">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 95%">List Name</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td><a href='{ROOT_URL}todo/list/{ID}'>{title}</a></td>
|
||||
<td><a href="{ROOT_URL}todo/list/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/editlist/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/deleteList/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
No Task Lists
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}todo/createlist" class="btn btn-sm btn-primary" role="button">New List</a>
|
||||
</form>
|
||||
</div>
|
9
app/plugins/todo/views/nav/listTabs.html
Normal file
9
app/plugins/todo/views/nav/listTabs.html
Normal file
@ -0,0 +1,9 @@
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="{ROOT_URL}todo/index/">Dashboard</a></li>
|
||||
<li><a href="{ROOT_URL}todo/list/">Lists</a></li>
|
||||
<li><a href="{ROOT_URL}todo/daily/">Daily</a></li>
|
||||
<li><a href="{ROOT_URL}todo/weekly/">Weekly</a></li>
|
||||
<li><a href="{ROOT_URL}todo/monthly/">Monthly</a></li>
|
||||
<li><a href="{ROOT_URL}todo/yearly/">Yearly</a></li>
|
||||
</ul>
|
||||
{userListTabs}
|
9
app/plugins/todo/views/nav/userListTabs.html
Normal file
9
app/plugins/todo/views/nav/userListTabs.html
Normal file
@ -0,0 +1,9 @@
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="{ROOT_URL}todo/list/">All</a></li>
|
||||
{LOOP}
|
||||
<li><a href="{ROOT_URL}todo/list/{ID}">{title}</a></li>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<li></li>
|
||||
{/ALT}
|
||||
</ul>
|
25
app/plugins/todo/views/tasks/create.html
Normal file
25
app/plugins/todo/views/tasks/create.html
Normal file
@ -0,0 +1,25 @@
|
||||
<legend>New Task</legend>
|
||||
{BREADCRUMB}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
{listSelect}
|
||||
<div class="form-group">
|
||||
<label for="task" class="col-lg-3 control-label">Task:</label>
|
||||
<div class="col-lg-3">
|
||||
<input class="form-control" type="text" name="task" id="task">
|
||||
</div>
|
||||
</div>
|
||||
{repeatSelect}
|
||||
<div class="form-group">
|
||||
<label for="dueDate" class="col-lg-3 control-label">Due Date:</label>
|
||||
<div class="col-lg-3">
|
||||
<input class="form-control" type="date" name="dueDate" id="dueDate">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="dueDate" class="col-lg-3 control-label"></label>
|
||||
<div class="col-lg-3">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
35
app/plugins/todo/views/tasks/daily.html
Normal file
35
app/plugins/todo/views/tasks/daily.html
Normal file
@ -0,0 +1,35 @@
|
||||
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
|
||||
<form action="" method="post">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60%">Task</th>
|
||||
<th style="width: 20%">Due</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td>{task}</td>
|
||||
<td>{DTC}{dueDate}{/DTC}</td>
|
||||
<td>{completedUrl}</td>
|
||||
<td><a href="{ROOT_URL}todo/edittask/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/deleteTask/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
No Tasks
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}todo/createtask/daily" class="btn btn-sm btn-primary" role="button">New Task</a>
|
||||
<a href="{ROOT_URL}todo/daily/?includeCompleted={completedToggle}" class="btn btn-sm btn-info" role="button">{completedToggleText} Completed</a>
|
||||
</form>
|
||||
</div>
|
20
app/plugins/todo/views/tasks/edit.html
Normal file
20
app/plugins/todo/views/tasks/edit.html
Normal file
@ -0,0 +1,20 @@
|
||||
<legend>Edit Task</legend>
|
||||
{BREADCRUMB}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{listSelect}
|
||||
<div class="form-group">
|
||||
<label for="task" class="col-lg-3 control-label">Task:</label>
|
||||
<div class="col-lg-2">
|
||||
<input class="form-control" type="text" name="task" id="task" value="{task}">
|
||||
</div>
|
||||
</div>
|
||||
{repeatSelect}
|
||||
<div class="form-group">
|
||||
<label for="dueDate" class="col-lg-3 control-label">Due Date:</label>
|
||||
<div class="col-lg-2">
|
||||
<input class="form-control" type="date" name="dueDate" id="dueDate" value="{task}">
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="token" value="{TOKEN}">
|
||||
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Save</button><br>
|
||||
</form>
|
37
app/plugins/todo/views/tasks/list.html
Normal file
37
app/plugins/todo/views/tasks/list.html
Normal file
@ -0,0 +1,37 @@
|
||||
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
|
||||
<form action="" method="post">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60%">Task</th>
|
||||
<th style="width: 20%">Due</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td>{task}</td>
|
||||
<td>{DTC}{dueDate}{/DTC}</td>
|
||||
<td>{completedUrl}</td>
|
||||
<td><a href="{ROOT_URL}todo/duplicateTask/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-copy"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/edittask/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/deleteTask/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
No Tasks
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}todo/createtask/{listID}" class="btn btn-sm btn-primary" role="button">New Task</a>
|
||||
<a href="{ROOT_URL}todo/list/{listID}?includeCompleted={completedToggle}" class="btn btn-sm btn-info" role="button">{completedToggleText} Completed</a>
|
||||
</form>
|
||||
</div>
|
35
app/plugins/todo/views/tasks/monthly.html
Normal file
35
app/plugins/todo/views/tasks/monthly.html
Normal file
@ -0,0 +1,35 @@
|
||||
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
|
||||
<form action="" method="post">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60%">Task</th>
|
||||
<th style="width: 20%">Due</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td>{task}</td>
|
||||
<td>{DTC}{dueDate}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}todo/completeTask/{ID}" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-ok"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/edittask/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/deleteTask/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
No Tasks
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}todo/createtask/monthly" class="btn btn-sm btn-primary" role="button">New Task</a>
|
||||
<a href="{ROOT_URL}todo/monthly/?includeCompleted={completedToggle}" class="btn btn-sm btn-info" role="button">{completedToggleText} Completed</a>
|
||||
</form>
|
||||
</div>
|
1
app/plugins/todo/views/tasks/view.html
Normal file
1
app/plugins/todo/views/tasks/view.html
Normal file
@ -0,0 +1 @@
|
||||
i don't think this file should ever really be reached normally
|
35
app/plugins/todo/views/tasks/weekly.html
Normal file
35
app/plugins/todo/views/tasks/weekly.html
Normal file
@ -0,0 +1,35 @@
|
||||
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
|
||||
<form action="" method="post">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60%">Task</th>
|
||||
<th style="width: 20%">Due</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td>{task}</td>
|
||||
<td>{DTC}{dueDate}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}todo/completeTask/{ID}" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-ok"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/edittask/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/deleteTask/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
No Tasks
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}todo/createtask/weekly" class="btn btn-sm btn-primary" role="button">New Task</a>
|
||||
<a href="{ROOT_URL}todo/weekly/?includeCompleted={completedToggle}" class="btn btn-sm btn-info" role="button">{completedToggleText} Completed</a>
|
||||
</form>
|
||||
</div>
|
35
app/plugins/todo/views/tasks/yearly.html
Normal file
35
app/plugins/todo/views/tasks/yearly.html
Normal file
@ -0,0 +1,35 @@
|
||||
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
|
||||
<form action="" method="post">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 60%">Task</th>
|
||||
<th style="width: 20%">Due</th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
<th style="width: 5%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{LOOP}
|
||||
<tr>
|
||||
<td>{task}</td>
|
||||
<td>{DTC}{dueDate}{/DTC}</td>
|
||||
<td><a href="{ROOT_URL}todo/completeTask/{ID}" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-ok"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/edittask/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||
<td><a href="{ROOT_URL}todo/deleteTask/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||
</tr>
|
||||
{/LOOP}
|
||||
{ALT}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
No Tasks
|
||||
</td>
|
||||
</tr>
|
||||
{/ALT}
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="{ROOT_URL}todo/createtask/yearly" class="btn btn-sm btn-primary" role="button">New Task</a>
|
||||
<a href="{ROOT_URL}todo/yearly/?includeCompleted={completedToggle}" class="btn btn-sm btn-info" role="button">{completedToggleText} Completed</a>
|
||||
</form>
|
||||
</div>
|
Reference in New Issue
Block a user