diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 58049dc..16b1da6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,19 +1,5 @@
# Contributing
- * All pull requests must be made against the `dev` branch
- * Complete documentation is available at http://taskboard.matthewross.me/docs/
- * In fact, more information about TaskBoard in general is available at http://taskboard.matthewross.me/
+ Fork the repository and make your changes on the `dev` branch.
- ## Versioning
-
-To clarify for myself and others, here is the versioning scheme used by Taskboard as of version v0.3.0 (for versions prior, it was basically just make it up as I went along):
-
-Versions are defined in three parts; major, minor and revision. For example, v0.3.0 is Major 0, Minor 3, Revision 0.
-
- * Major version numbers change in two cases:'
- * v1.0.0 is when I feel TaskBoard is *Production Ready*
- * When changes are made that add significant new features or break some form of compatibility with previous versions (e.g. requiring a new database)
-
-Minor version numbers change when a chosen set of changes are ready for use. The changes are issues reported by users or added by myself for tracking planned features.
-
-Revision version numbers change when a bug is reported that needs to be fixed before another minor version is released.
+ Create a pull request against the `dev` branch to merge your changes with the main repository.
diff --git a/LICENSE b/LICENSE
index c2e0515..1ccb69f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2014 Matthew Ross
+Copyright (c) 2014-2016 Matthew Ross
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index cbf3059..069a686 100644
--- a/README.md
+++ b/README.md
@@ -4,79 +4,51 @@
A [Kanban](http://en.wikipedia.org/wiki/Kanban_board)-inspired app for keeping track of things that need to get done.
-The goal of TaskBoard is to provide a simple and clean interface to a functional and minimal application for keeping track of tasks. It's not trying to be the next Trello or LeanKit.
+The goal of TaskBoard is to provide a simple and clean interface to a functional and minimal application for keeping track of tasks. **It's not trying to be the next Trello or LeanKit.**
-###How It's Made
+### How It's Made
1. Front end
- * [AngularJS](https://angularjs.org/) single-page app.
-
- * [ng-context-menu](https://github.com/ianwalter/ng-context-menu), [jQueryUI Datepicker](http://jqueryui.com/datepicker/), [Spectrum](http://bgrins.github.io/spectrum/) colorpicker, [(noty)](http://ned.im/noty/) notifications, [marked](https://github.com/chjj/marked) Markdown parser, and [-prefix-free](http://leaverou.github.io/prefixfree/) CSS prefix helper.
-
- * [Bootstrap](http://getbootstrap.com/) for base look and feel.
+ * [Angular](https://angular.io/) single-page app
+ * [Bourbon](http://bourbon.io/) and [Neat](http://neat.bourbon.io/) SCSS library & framework
+ * [marked](https://github.com/chjj/marked) Markdown parser
2. Back end
- * RESTful API written in PHP, using [Slim Framework](http://www.slimframework.com/) for routing and [RedBeanPHP](http://www.redbeanphp.com/) for database ORM. Also uses [PHPMailer](https://github.com/PHPMailer/PHPMailer) for sending emails.
+ * [Slim Framework](http://www.slimframework.com/) and [RedBeanPHP](http://www.redbeanphp.com/) for a RESTful API
+ * [PHPMailer](https://github.com/PHPMailer/PHPMailer) for sending emails.
+ * [JWT](https://jwt.io/) authentication
+ * SQLite database
- * Token-based authentication.
+## Installation
- * SQLite database.
+### Prerequisites
-##Installation
-
-###Requirements
A web server running PHP with sqlite enabled. Developed and tested under Apache2 running PHP 5.5+.
-The server must have `sqlite` and `php5-sqlite` installed, as well as the `rewrite` and `expires` Apache modules.
+The server must have `sqlite` and `php5-sqlite` installed, as well as the `rewrite` Apache module.
-**Note:** For Apache v2.3.9 and later, virtual host for a site should have [`AllowOverride All`](http://httpd.apache.org/docs/2.4/mod/core.html#allowoverride) for TaskBoard root directory. Otherwise, .htaccess files will be completely ignored.
+### Install
-**Optional:** to build minimized JavaScript and CSS (Install step 3) you must have curl and a jre installed, tested with `openjdk-7-jre` and `openjdk-8-jre`.
+Installing TaskBoard is as easy as 1, 2, 3!
-###Install
+ 1. Download the latest release (or whatever version you want)
+ 2. Extract it to your webserver
+ 3. Verify the `api` directory is writable
-Installing TaskBoard is as easy as 1, 2, (3), 4!
+### Development
-**Note:** You can skip step 3 if you don't care about minification of JavaScript and CSS for a production environment!
+Developing on TaskBoard is pretty simple too.
-1. Clone the repository directly where you want it, or clone and copy to it's final location.
+ 1. Clone the repository
+ 2. Run `npm i` to install dependencies
+ 3. Run `git checkout dev` to work on the `dev` branch
- git clone https://github.com/kiswa/TaskBoard.git
+## Features
-2. Install the PHP dependencies via composer. Open `TaskBoard/` in a terminal and run `./build/composer.phar install`
+### Boards
-3. (Optional) Open `TaskBoard/build/` in a terminal and run `./build-all`.
-
-4. Visit the site and log in with the username and password `admin` (and don't forget to change the password once you're in!).
-
-**Note:** Ensure `TaskBoard/api/` is writable so the back end can do its job!
-
-### Development instance
-
-Now you can start a simple development environment with the php internal webserver.
-
-`php -S 127.0.0.1:8080 devrouter.php`
-
-After launching the internal webserver go to http://127.0.0.1:8080/
-
-##Features
-
-###Email
-
-TaskBoard will email you (if you supply it with an email address) about changes in the following cases: Board Created, Board Updated, Item Created, Item Edited, Item Comment Created, and Item Comment Edited.
-
-For now, it emails all users assigned to the related Board. There will be further work done on this to allow more fine-grained control of emails.
-
-###Settings
-The settings page allows normal users to see what boards they have access to and edit their user settings.
-
-Admin users have the same, with the additional abilities of adding/editing users and boards, and viewing a log of all activity in TaskBoard.
-
-
-
-###Boards
Each board may have as many columns as needed. For example, a software project might have columns like:
* Proposed
@@ -96,39 +68,17 @@ It's all up to you! However many columns you have, each column may have tasks ad
Boards may also have categories for additional organization, *e.g.* `Bug`, `Enhancement`, `New Feature`.
-
+### Items
-###Items
-An item (task) only has to have a Title to be added to a board, but there is much more than that available. Items may be assigned to any user on the board (or left Unassigned), and include options for Due Date, Color, Points (an optional difficulty rating), and Category.
+An item (task) only has to have a Title to be added to a board, but there is much more available. Items may be assigned to any user on the board (or left Unassigned), and include options for Due Date, Color, Points (an optional difficulty rating), and Category.
TaskBoard uses a [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#table-of-contents) parser for the Description, allowing for better display of details (like this readme).
Once an item has been entered, it may have Comments or Attachments added to it by viewing the task detail. There is a link to edit the item, which takes you to a modal much like the original add item dialog. For admin users, there is also a link to delete the item. This view also shows the task's activity log on the right side of the screen, displaying the complete history of events related to the item.
-
-
##Feedback
Constructive feedback is appreciated! If you have ideas for improvement, please [add an issue](https://github.com/kiswa/TaskBoard/issues) or submit a pull request.
If you find a bug, please post it on the [Issue Tracker](https://github.com/kiswa/TaskBoard/issues).
-##Lines of Code
-
-It's silly to use [LOC](http://en.wikipedia.org/wiki/Source_lines_of_code) as a metric, but it can be interesting to see what goes into a project.
-This is only for TaskBoard files (library code is excluded), using [CLOC](http://cloc.sourceforge.net/).
-
-Count was done from parent directory of TaskBoard as `cloc TaskBoard --exclude-dir=lib,vendor`.
-
-Language | Files | Blank Lines | Comments | Code
--------------------|-------:|-------------:|---------:|---------:
-Javascript | 23 | 220 | 34 | 2087
-PHP | 9 | 235 | 55 | 1220
-HTML | 24 | 12 | 10 | 1160
-CSS | 1 | 13 | 26 | 703
-Bourne Again Shell | 4 | 12 | 0 | 58
-JSON | 1 | 0 | 0 | 17
-XML | 1 | 0 | 0 | 12
-__SUM:__ | __63__ | __492__ | __125__ | __5257__
-
-Counts Last Updated: Nov 8, 2015
diff --git a/VERSION b/VERSION
index 921febd..b1f1a73 100644
--- a/VERSION
+++ b/VERSION
@@ -1,9 +1,6 @@
-v0.3.1
+v1.0.0
Changelog
- * Fix automatic action color change bug.
- * Fix new user default board bug.
- * Fix boards button bug.
- * Fix modal display bug.
- * Allow email to be reset to nothing.
+ * Complete re-write
+
diff --git a/api/.htaccess b/api/.htaccess
deleted file mode 100644
index c726d97..0000000
--- a/api/.htaccess
+++ /dev/null
@@ -1,10 +0,0 @@
-ExpiresActive Off
-RewriteEngine On
-
-RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
-RewriteRule ^(.*)$ - [E=BASE:%1]
-
-RewriteRule ^taskboard.db$ %{ENV:BASE}api.php [QSA,L]
-
-RewriteCond %{REQUEST_FILENAME} !-f
-RewriteRule ^(.*)$ %{ENV:BASE}api.php [QSA,L]
diff --git a/api/api.php b/api/api.php
deleted file mode 100644
index b885c2e..0000000
--- a/api/api.php
+++ /dev/null
@@ -1,53 +0,0 @@
-response->headers->set('Content-Type', 'application/json');
-
-$jsonResponse = new JsonResponse();
-require_once('helpers.php'); // Must come after $jsonResponse exists.
-
-// Catch Exception if connection to DB failed
-function exceptionHandler($exception) {
- global $jsonResponse;
-
- header('Content-Type: application/json');
- http_response_code(503);
-
- $jsonResponse->message = 'API Error.';
- $jsonResponse->data = $exception->getMessage();
- $jsonResponse->trace = $exception->getTrace();
- echo $jsonResponse->asJson();
-};
-set_exception_handler('exceptionHandler');
-
-R::setup('sqlite:'.__DIR__.'/taskboard.db');
-R::setAutoResolve(TRUE);
-createInitialUser();
-
-$app->notFound(function() use ($app, $jsonResponse) {
- $app->response->setStatus(404);
- $jsonResponse->message = 'Matching API call Not found.';
-
- $app->response->setBody($jsonResponse->asJson());
-});
-
-$app->get('/authenticate', function() use($app, $jsonResponse) {
- if (validateToken()) {
- $jsonResponse->message = 'Token is authenticated.';
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-require_once('mailFactory.php');
-
-require_once('userRoutes.php');
-require_once('boardRoutes.php');
-require_once('itemRoutes.php');
-
-$app->run();
-R::close();
diff --git a/api/boardRoutes.php b/api/boardRoutes.php
deleted file mode 100644
index 9c06ccc..0000000
--- a/api/boardRoutes.php
+++ /dev/null
@@ -1,177 +0,0 @@
-get('/boards', function() use($app, $jsonResponse) {
- if (validateToken()) {
- $jsonResponse->addBeans(getBoards());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Create new board.
-$app->post('/boards', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $board = R::dispense('board');
- loadBoardData($board, $data);
-
- $actor = getUser();
- logAction($actor->username . ' added board ' . $board->name, null, $board->export());
- $jsonResponse->addBeans(getBoards());
- $jsonResponse->addAlert('success', 'New board ' . $board->name . ' created.');
-
- foreach($board->sharedUser as $user) {
- $body = getNewBoardEmailBody($board->id, $user->username, $board->name);
- $subject = 'TaskBoard: New board created!';
- $recipient = $user->username;
- $email = $user->email;
-
- sendEmail($email, $recipient, $subject, $body);
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Update existing board.
-$app->post('/boards/update', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $board = R::load('board', $data->boardId);
- if ($board->id) {
- $before = $board->export();
- loadBoardData($board, $data);
- $jsonResponse->addAlert('success', 'Board ' . $board->name . ' edited.');
- $actor = getUser();
- logAction($actor->username . ' updated board ' . $board->name, $before, $board->export());
- }
- $jsonResponse->addBeans(getBoards());
-
- foreach($board->sharedUser as $user) {
- $body = getEditBoardEmailBody($board->id, $user->username, $board->name);
- $subject = 'TaskBoard: Board updated!';
- $recipient = $user->username;
- $email = $user->email;
-
- sendEmail($email, $recipient, $subject, $body);
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Remove a board.
-$app->post('/boards/remove', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $board = R::load('board', $data->boardId);
- if ($board->id == $data->boardId) {
- $before = $board->export();
- foreach($board->sharedUser as $user) {
- if ($user->defaultBoard == $data->boardId) {
- $user->defaultBoard = null;
- R::store($user);
- }
- }
- R::trashAll($board->xownLane);
- R::trashAll($board->xownCategory);
- R::trash($board);
- R::exec('DELETE from board_user WHERE board_id = ?', [$data->boardId]);
- $jsonResponse->addAlert('success', 'Removed board ' . $board->name . '.');
- $actor = getUser();
- logAction($actor->username . ' removed board ' . $board->name, $before, null);
- }
- $jsonResponse->addBeans(getBoards());
- $jsonResponse->users = R::exportAll(getUsers());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-$app->post('/autoactions', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $board = R::load('board', $data->boardId);
- if ($board->id) {
- $autoAction = R::dispense('autoaction');
- $autoAction->triggerId = $data->triggerId;
- $autoAction->secondaryId = $data->secondaryId;
- $autoAction->actionId = $data->actionId;
- $autoAction->color = $data->color;
- $autoAction->categoryId = $data->categoryId;
- $autoAction->assigneeId = $data->assigneeId;
- }
- $board->ownAutoaction[] = $autoAction;
- R::store($board);
- $jsonResponse->addAlert('success', 'Automatic action created.');
- $actions = R::findAll('autoaction');
- $jsonResponse->addBeans($actions);
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-$app->get('/autoactions', function() use($app, $jsonResponse) {
- if (validateToken()) {
- $actions = R::findAll('autoaction');
- $jsonResponse->addBeans($actions);
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-$app->post('/autoactions/remove', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $autoAction = R::load('autoaction', $data->actionId);
- R::trash($autoAction);
-
- $actions = R::findAll('autoaction');
- $jsonResponse->addBeans($actions);
- $jsonResponse->addAlert('success', 'Automatic action removed.');
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Toggle the expand/collapse state of a lane for the current user.
-$app->post('/lanes/:laneId/toggle', function($laneId) use($app, $jsonResponse) {
- if (validateToken()) {
- $user = getUser();
- $lane = R::load('lane', $laneId);
- $collapsed = R::findOne('collapsed', ' user_id = ? AND lane_id = ? ', [$user->id, $laneId]);
-
- if (null != $collapsed) {
- R::trash($collapsed);
- $jsonResponse->message = 'Expanded lane ' . $lane->name;
- } else {
- $collapsed = R::dispense('collapsed');
- $collapsed->userId = $user->id;
- $collapsed->laneId = $laneId;
- R::store($collapsed);
- $jsonResponse->message = 'Collapsed lane ' . $lane->name;
- }
-
- $jsonResponse->addBeans(getBoards());
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['laneId' => '\d+']); // Numbers only.
-
-$app->post('/boards/:boardId/toggleActive', function($boardId) use($app, $jsonResponse) {
- if (validateToken()) {
- $user = getUser();
- if ($user->isAdmin) {
- $board = R::load('board', $boardId);
- $before = $board->export();
- $board->active = !$board->active;
- R::store($board);
-
- $state = $board->active ? 'active' : 'inactive';
- $jsonResponse->message = 'Set board ' . $board->name . ' ' . $state;
- $jsonResponse->addBeans(getBoards());
-
- logAction($user->username . ' changed active status of board ' . $board->name,
- $before, $board->export());
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['boardId' => '\d+']); // Numbers only.
diff --git a/api/helpers.php b/api/helpers.php
deleted file mode 100644
index 2e7975c..0000000
--- a/api/helpers.php
+++ /dev/null
@@ -1,468 +0,0 @@
- $value) {
- if (substr($name, 0, 5) == 'HTTP_') {
- $headers[str_replace(' ', '-', ucwords(strtolower(
- str_replace('_', ' ', substr($name, 5))
- )))] = $value;
- }
- }
-
- return $headers;
- }
-}
-
-// Log an action. If $itemId is set, it is an item action.
-function logAction($comment, $oldValue, $newValue, $itemId=null) {
- $activity = R::dispense('activity');
- $activity->comment = $comment;
- $activity->oldValue = json_encode($oldValue);
- $activity->newValue = json_encode($newValue);
- $activity->timestamp = time();
- $activity->itemId = $itemId;
-
- R::store($activity);
-}
-
-// Sets the JWT for the current user and stores in DB for lookup.
-function setUserToken($user, $expires) {
- $token = JWT::encode(array(
- 'exp' => time() + $expires,
- 'uid' => $user->id
- ), getJwtKey());
-
- $dbToken = R::dispense('token');
- $dbToken->token = $token;
-
- if (null == $user->ownToken) {
- $user->ownToken = [];
- }
- $user->ownToken[] = $dbToken;
-
- R::store($user);
-}
-
-// Get the user making the current request.
-function getUser() {
- global $jsonResponse;
-
- if (isset(getallheaders()['Authorization'])) {
- $hash = getallheaders()['Authorization'];
- try {
- $payload = JWT::decode($hash, getJwtKey());
- $user = R::load('user', $payload->uid);
-
- if ($user->id) {
- return $user;
- }
- } catch (Exception $e) {}
- }
-
- $jsonResponse->addAlert('error', 'Unable to load user. Please try again.');
- return null;
-}
-
-function getUserByID($id) {
- try {
- $user = R::load('user', $id);
-
- if ($user->id) {
- return $user;
- }
- } catch (Exception $e) {}
-
- return null;
-}
-
-function getLaneByID($id) {
- try {
- $lane = R::load('lane', $id);
-
- if ($lane->id) {
- return $lane;
- }
- } catch (Exception $e) {}
-
- return null;
-}
-
-// Get all users.
-function getUsers($sanitize = true) {
- try {
- $hash = getallheaders()['Authorization'];
- $payload = JWT::decode($hash, getJwtKey());
-
- $users = R::findAll('user');
- if ($sanitize) {
- foreach($users as &$user) {
- sanitize($user);
- }
- }
-
- return $users;
- } catch (Exception $e) {}
-
- $jsonResponse->addAlert('error', 'Unable to load users. Please try again.');
- return null;
-}
-
-// Add a user to a board.
-function addUserToBoard($boardId, $user) {
- if ($user->isAdmin) {
- $boards = R::findAll('board'); // DO NOT use getBoards here - it sanitizes the users which causes problems.
- foreach($boards as $board) {
- $board->sharedUser[] = $user;
- R::store($board);
- }
- } else {
- $board = R::load('board', $boardId);
- if ($board->id) {
- $board->sharedUser[] = $user;
- R::store($board);
- }
- }
-}
-
-// Get all boards.
-function getBoards() {
- $user = getUser();
- $boards = R::find('board');
-
- foreach($boards as $board) {
- foreach($board->sharedUser as $boardUser) {
- sanitize($boardUser);
- }
- }
-
- $collapsedLanes = R::find('collapsed', ' user_id = ' . $user->id);
- foreach($boards as $board) {
- foreach($board->xownLane as $lane) {
- foreach($collapsedLanes as $collapsed) {
- if ($lane->id == $collapsed->lane_id) {
- $lane->collapsed = true;
- }
- }
- }
- }
-
- if ($user->isAdmin) {
- return $boards;
- } else {
- $filteredBoards = [];
- foreach($boards as $board) {
- foreach($board->sharedUser as $boardUser) {
- if ($user->username == $boardUser->username) {
- $filteredBoards[] = $board;
- }
- }
- }
- return $filteredBoards;
- }
-}
-
-// Finds the removed IDs for updating a board.
-function getIdsToRemove($boardList, $dataList) {
- $retVal = [];
- foreach($boardList as $item) {
- $remove = true;
- foreach($dataList as $newItem) {
- if (intval($newItem->id) == $item->id) {
- $remove = false;
- }
- }
- if ($remove) {
- $retVal[] = $item->id;
- }
- }
- return $retVal;
-}
-
-// Load a board bean from provided data.
-function loadBoardData($board, $data) {
- $board->name = $data->name;
- $board->active = true;
-
- $removeIds = getIdsToRemove($board->xownLane, $data->lanes);
- foreach($removeIds as $id) {
- unset($board->xownLane[$id]);
- }
-
- // R::load works like R::dispense if the id is not found.
- foreach($data->lanes as $item) {
- $lane = R::load('lane', $item->id);
- $lane->name = $item->name;
- $lane->position = intval($item->position);
-
- if (null == $lane->ownItems) {
- $lane->ownItems = [];
- }
- // New lane, add it to the board
- if (!$lane->id) {
- $board->xownLane[] = $lane;
- }
- R::store($lane);
- }
-
- $removeIds = getIdsToRemove($board->xownCategory, $data->categories);
- foreach($removeIds as $id) {
- unset($board->xownCategory[$id]);
- }
- foreach($data->categories as $item) {
- $category = R::load('category', $item->id);
- $category->name = $item->name;
-
- // New category, add it to the board.
- if (!$category->id) {
- $board->xownCategory[] = $category;
- }
- R::store($category);
- }
-
- // Add or remove users as selected.
- for($i = 1; $i < count($data->users); $i++) {
- $user = R::load('user', $i);
- if ($data->users[$i] && $user->id && !in_array($user, $board->sharedUser)) {
- $board->sharedUser[] = $user;
- } else {
- unset($board->sharedUser[$i]);
- }
- }
-
- // Add all admin users.
- foreach(getUsers(false) as $user) {
- if ($user->isAdmin && !in_array($user, $board->sharedUser)) {
- $board->sharedUser[] = $user;
- }
- }
-
- R::store($board);
-}
-
-// Clean a user bean for return to front-end.
-function sanitize($user) {
- $user['salt'] = null;
- $user->ownToken = [];
- $user['password'] = null;
-}
-
-// Change username if available.
-function updateUsername($user, $data) {
- global $jsonResponse;
- $nameTaken = R::findOne('user', ' username = ?', [$data->newUsername]);
-
- if (null != $user && null == $nameTaken) {
- $user->username = $data->newUsername;
- $jsonResponse->addAlert('success', 'Username updated.');
- } else {
- $jsonResponse->addAlert('error', 'Username already in use.');
- }
-
- return $user;
-}
-
-// Change email if available.
-function updateEmail($user, $data) {
- global $jsonResponse;
- $emailTaken = R::findOne('user', ' username = ?', [$data->newEmail]);
-
- if (null != $user && null == $emailTaken) {
- $user->email = $data->newEmail;
- $jsonResponse->addAlert('success', 'Email updated.');
- } else {
- $jsonResponse->addAlert('error', 'Email already in use.');
- }
-
- return $user;
-}
-
-// Validate a provided JWT.
-function validateToken($requireAdmin = false) {
- global $jsonResponse, $app;
- $retVal = false;
-
- if (checkDbToken()) {
- $retVal = true;
- } else {
- clearDbToken();
- $jsonResponse->message = 'Invalid token.';
- $app->response->setStatus(401);
- }
-
- if ($retVal && $requireAdmin) {
- $user = getUser();
- if (!$user->isAdmin) {
- clearDbToken();
- $jsonResponse->message = 'Insufficient user privileges.';
- $app->response->setStatus(401);
- }
- }
-
- return $retVal;
-}
-
-// Retrieve user's token from DB and compare to header token.
-function checkDbToken() {
- $user = getUser();
- $isValid = false;
-
- if (null != $user) {
- if (isset(getallheaders()['Authorization'])) {
- $hash = getallheaders()['Authorization'];
-
- foreach ($user->ownToken as $token) {
- if ($hash == $token->token) {
- $isValid = true;
- }
- }
- }
- }
-
- return $isValid;
-}
-
-// Clear a user's token from the DB.
-function clearDbToken() {
- $payload = null;
-
- try {
- $payload = JWT::decode(getallheaders()['Authorization'], getJwtKey());
- } catch (Exception $e) {}
-
- if (null != $payload) {
- $user = R::load('user', $payload->uid);
- if (0 != $user->id) {
- $hash = getallheaders()['Authorization'];
-
- foreach ($user->ownToken as $token) {
- if ($hash == $token->token) {
- R::trash($token);
- }
- }
-
- R::store($user);
- }
- }
-}
-
-// Get the application's JWT key (created on first run).
-function getJwtKey() {
- $key = R::load('jwt', 1);
-
- if (!$key->id) {
- $key->token = password_hash(strval(time()), PASSWORD_BCRYPT);
- R::store($key);
- }
-
- return $key->token;
-}
-
-// If there are no users, create the admin user.
-function createInitialUser() {
- if (!R::count('user')) {
- $admin = R::dispense('user');
-
- $admin->username = 'admin';
- $admin->isAdmin = true;
- $admin->logins = 0;
- $admin->lastLogin = time(); //date('Y-m-d H:i:s');
- $admin->defaultBoard = null;
- $admin->salt = password_hash($admin->username . time(), PASSWORD_BCRYPT);
- $admin->password = password_hash('admin', PASSWORD_BCRYPT, array('salt' => $admin->salt));
- $admin->email = '';
-
- $options = R::dispense('option');
- $options->tasksOrder = 0;
- $options->showAnimations = true;
- $options->showAssignee = true;
-
- $admin->xownOptionList[] = $options;
-
- R::store($admin);
- }
-}
-
-// Gets the position for a new item in a column.
-function getNextItemPosition($columnId) {
- $retVal = 0;
- $column = R::load('lane', $columnId);
-
- if ($column->id) {
- $options = R::exportAll(getUser()->ownOption);
-
- if ($options[0]['tasks_order'] == 1) {
- // Tasks at top of column.
- renumberItems($columnId, 0, false);
- } else {
- try {
- $retVal = $column->countOwn('item');
- } catch (Exception $e) {
- // Ignore, just means there are no items.
- }
- }
- }
-
- return $retVal;
-}
-
-function renumberItems($columnId, $itemPosition, $isRemoved = true) {
- $items = R::find('item', 'lane_id = ' . $columnId);
-
- foreach ($items as $item) {
- if ($item->position >= $itemPosition) {
- $item->position += $isRemoved ? -1 : 1;
- R::store($item);
- }
- }
-}
-
-function runAutoActions(&$item) {
- $lane = R::load('lane', $item->laneId);
- $board = R::load('board', $lane->boardId);
-
- foreach($board->ownAutoaction as $action) {
- switch($action->triggerId) {
- case 0: // Item moves to lane
- if ($item->laneId == $action->secondaryId) {
- updateItemFromAction($item, $action);
- }
- break;
- case 1: // Item assigned to user
- if ($item->assignee == $action->secondaryId ||
- ($action->secondaryId == 0 && $item->assignee == null)) {
- updateItemFromAction($item, $action);
- }
- break;
- case 2: // Item assigned to category
- if ($item->category == $action->secondaryId ||
- ($action->secondaryId == 0 && $item->category == null)) {
- updateItemFromAction($item, $action);
- }
- break;
- }
- }
-}
-
-function updateItemFromAction(&$item, $action) {
- switch($action->actionId) {
- case 0: // Set item color
- $item->color = $action->color;
- break;
- case 1: // Set item category
- $item->category = $action->categoryId;
- break;
- case 2: // Set item assignee
- $item->assignee = $action->assigneeId;
- break;
- case 3: // Clear item due date
- $item->dueDate = null;
- break;
- }
- R::store($item);
-}
-
-
diff --git a/api/itemRoutes.php b/api/itemRoutes.php
deleted file mode 100644
index c6ea23a..0000000
--- a/api/itemRoutes.php
+++ /dev/null
@@ -1,361 +0,0 @@
-post('/boards/:id/items', function($id) use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $board = R::load('board', $id);
- if ($board->id) {
- $item = R::dispense('item');
- $item->title = $data->title;
- $item->description = $data->description;
- $item->assignee = $data->assignee;
- $item->category = $data->category;
- $item->color = $data->color;
- $item->dueDate = $data->dueDate;
- $item->points = $data->points;
- $item->position = getNextItemPosition($data->lane);
-
- $board->xownLane[$data->lane]->xownItem[] = $item;
- R::store($board);
- runAutoActions($item);
-
- if ($item->id) {
- $actor = getUser();
- logAction($actor->username . ' added item ' . $item->title . ' to board ' . $board->name,
- null, $item->export(), $item->id);
- $jsonResponse->addAlert('success', 'New board item created.');
- $jsonResponse->addBeans(getBoards());
- } else {
- $jsonResponse->addAlert('error', 'Failed to create board item.');
- }
-
- foreach($board->sharedUser as $user) {
- $actor = getUser();
- $assignee = 'Unassigned';
- if ($item->assignee > 0) {
- $assignee = getUserByID($item->assignee)->username;
- }
-
- $body = getNewItemEmailBody(
- $board->id,
- $actor->username,
- $board->name,
- $item->title,
- $item->description,
- $assignee,
- $item->category,
- $item->dueDate,
- $item->points,
- $item->position
- );
- $subject = 'TaskBoard: New item created!';
- $recipient = $user->username;
- $email = $user->email;
-
- sendEmail($email, $recipient, $subject, $body);
- }
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['id' => '\d+']); // Numbers only.
-
-//Update existing item
-$app->post('/items/:itemId', function($itemId) use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $item = R::load('item', $itemId);
- $before = $item->export();
- if ($item->id) {
- $item->title = $data->title;
- $item->description = $data->description;
- $item->assignee = $data->assignee;
- $item->category = $data->category;
- $item->color = $data->color;
- $item->dueDate = $data->dueDate;
- $item->points = $data->points;
- if ($data->lane != $item->lane_id) {
- $item->position = getNextItemPosition($data->lane);
- $item->lane = R::load('lane', $data->lane);
- } else {
- $item->position = $data->position;
- }
-
- runAutoActions($item);
- R::store($item);
- logAction($user->username . ' updated item ' . $item->title, $before, $item->export(), $itemId);
- $jsonResponse->addAlert('success', 'Updated item ' . $item->title . '.');
- $jsonResponse->addBeans(getBoards());
-
- $lane = R::load('lane', $item->lane_id);
- $board = R::load('board', $lane->boardId);
-
- foreach($board->sharedUser as $user) {
- $actor = getUser();
- $assignee = 'Unassigned';
- if ($item->assignee > 0) {
- $assignee = getUserByID($item->assignee)->username;
- }
-
- $body = getEditItemEmailBody(
- $board->id,
- $actor->username,
- $board->name,
- $item->title,
- $item->description,
- $assignee,
- $item->category,
- $item->dueDate,
- $item->points,
- $item->position
- );
- $subject = 'TaskBoard: Item edited';
- $recipient = $user->username;
- $email = $user->email;
-
- sendEmail($email, $recipient, $subject, $body);
- }
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['itemId' => '\d+']);
-
-// Update item positions
-$app->post('/items/positions', function() use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $movedItem = null;
- $beforeItem = null;
- $afterItem = null;
- R::begin();
- foreach($data->positions as $posItem) {
- $item = R::load('item', $posItem->item);
- $before = $item->export();
- $oldLane = $item->lane->id;
- $item->lane = R::load('lane', $posItem->lane);
- if ($oldLane != $item->lane->id) {
- $movedItem = $item;
- $beforeItem = $before;
- $afterItem = $item->export();
- }
- $item->position = $posItem->position;
-
- R::store($item);
- runAutoActions($item);
- R::store($item);
- }
- R::commit();
-
- // If an item changed lanes, log the action.
- if (null != $movedItem) {
- logAction($user->username . ' moved item ' . $movedItem->title . ' to lane ' . $movedItem->lane->name,
- $beforeItem, $afterItem, $movedItem->id);
- }
- $jsonResponse->addBeans(getBoards());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Add a comment to an item.
-$app->post('/items/:itemId/comment', function($itemId) use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $item = R::load('item', $itemId);
- if ($item->id) {
- $comment = R::dispense('comment');
- $comment->text = $data->text;
- $comment->userId = $user->id;
- $comment->timestamp = time();
-
- $item->ownComment[] = $comment;
- R::store($item);
-
- logAction($user->username . ' added a comment to item ' . $item->title, null, $comment->export(), $itemId);
- $jsonResponse->addAlert('success', 'Comment added to item ' . $item->title . '.');
- $jsonResponse->addBeans(R::load('item', $itemId));
-
- $lane = R::load('lane', $item->lane_id);
- $board = R::load('board', $lane->boardId);
-
- foreach($board->sharedUser as $user) {
- $body = getNewCommentEmailBody(
- $board->id,
- $user->username,
- $board->name,
- $item->title,
- $comment->text
- );
- $subject = 'TaskBoard: New comment';
- $recipient = $user->username;
- $email = $user->email;
-
- sendEmail($email, $recipient, $subject, $body);
- }
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['itemId' => '\d+']);
-
-// Update an existing comment
-$app->post('/comments/:commentId', function($commentId) use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if(validateToken()) {
- $user = getUser();
- $comment = R::load('comment', $commentId);
- $before = $comment->export();
-
- $comment->text = $data->text;
- $comment->userId = $user->id;
- $comment->timestamp = time();
- $comment->isEdited = true;
- R::store($comment);
-
- logAction($user->username . ' edited comment ' . $comment->id, $before, $comment->export(), $comment->id);
- $jsonResponse->addAlert('success', 'Comment edited.');
- $jsonResponse->addBeans(R::load('item', $comment->item_id));
-
- $item = R::load('item', $comment->item_id);
- $lane = R::load('lane', $item->lane_id);
- $board = R::load('board', $lane->boardId);
-
- foreach($board->sharedUser as $user) {
- $body = getEditCommentEmailBody(
- $board->id,
- $user->username,
- $board->name,
- $item->title,
- $comment->text
- );
- $subject = 'TaskBoard: Comment updated';
- $recipient = $user->username;
- $email = $user->email;
-
- sendEmail($email, $recipient, $subject, $body);
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['commentId' => '\d+']);
-
-// Remove a comment from an item.
-$app->post('/items/:itemId/comment/remove', function($itemId) use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $comment = R::load('comment', $data->id);
- if ($comment->id) {
- $before = $comment->export();
- R::trash($comment);
-
- $item = R::load('item', $itemId);
- logAction($user->username . ' removed comment from item ' . $item->title . '.', $before, null, $item->id);
- $jsonResponse->addAlert('success', 'Comment was deleted.');
- $jsonResponse->addBeans(R::load('item', $itemId));
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['itemId' => '\d+']);
-
-// Add an attachment to an item.
-$app->post('/items/:itemId/upload', function($itemId) use ($app, $jsonResponse) {
- $upload = $_FILES['file'];
- if (!file_exists('uploads/')) {
- mkdir('uploads', 0777, true);
- }
-
- if (validateToken()) {
- $file = R::dispense('attachment');
- $item = R::load('item', $itemId);
- $before = $item->export();
- $user = getUser();
-
- $file->filename = sha1($upload['tmp_name']);
- $file->name = $upload['name'];
- $file->type = $upload['type'];
- $file->userId = $user->id;
- $file->timestamp = time();
-
- $item->ownAttachment[] = $file;
- R::store($item);
-
- move_uploaded_file($upload['tmp_name'], 'uploads/' . $file->filename);
-
- logAction($user->username . ' uploaded attachment ' . $file->name . ' to item ' . $item->name,
- $before, $item, $itemId);
- $jsonResponse->addAlert('success', $file->name . ' was added.');
- $jsonResponse->addBeans($item);
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['itemId' => '\d+']);
-
-// Get an item attachment's information.
-$app->get('/items/:itemId/upload/:attachmentId', function($itemId, $attachmentId) use ($app, $jsonResponse) {
- if (validateToken()) {
- $file = R::load('attachment', $attachmentId);
-
- if ($file->id) {
- $file->username = 'unknown';
- $user = R::load('user', $file->userId);
- if ($user->id) {
- $file->username = $user->username;
- }
- $jsonResponse->addBeans($file);
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['itemId' => '\d+', 'attachmentId' => '\d+']);
-
-// Remove an attachment from an item.
-$app->post('/items/:itemId/upload/remove', function($itemId) use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $item = R::load('item', $itemId);
- $before = $item->export();
- $actor = getUser();
-
- $file = R::load('attachment', $data->fileId);
- if ($file->id) {
- $filename = $file->name;
- $before = $item->export();
- unlink('uploads/' . $file->filename);
- R::trash($file);
- R::store($item);
-
- logAction($actor->username . ' removed attachment ' . $filename . ' from item ' . $item->title,
- $before, $item, $itemId);
- $jsonResponse->addAlert('success', $filename . ' was deleted.');
- $jsonResponse->addBeans($item);
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-})->conditions(['itemId' => '\d+']);
-
-// Remove an item.
-$app->post('/items/remove', function() use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $item = R::load('item', $data->itemId);
- if ($item->id) {
- $before = $item->export();
- R::trash($item);
-
- renumberItems($item->lane_id, $item->position);
-
- $actor = getUser();
- logAction($actor->username . ' removed item ' . $item->title, $before, null, $data->itemId);
- $jsonResponse->addAlert('success', $item->title . ' was deleted.');
- $jsonResponse->addBeans(getBoards());
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-});
diff --git a/api/jsonResponse.php b/api/jsonResponse.php
deleted file mode 100644
index b9b0a31..0000000
--- a/api/jsonResponse.php
+++ /dev/null
@@ -1,22 +0,0 @@
-data = R::exportAll($beans);
- }
-
- function addAlert($type, $text) {
- $this->alerts[] = ['type' => $type, 'text' => $text];
- }
-}
diff --git a/api/mailConfig.php b/api/mailConfig.php
deleted file mode 100644
index 7d74df0..0000000
--- a/api/mailConfig.php
+++ /dev/null
@@ -1,9 +0,0 @@
- $value) {
- if (strtolower($header) == 'host') {
- return $value;
- }
- }
-}
-
-function createMailObject() {
- global $MAIL_HOST, $MAIL_USERNAME, $MAIL_PASSWORD, $MAIL_SMTPSECURE, $MAIL_PORT, $MAIL_FROM, $MAIL_FROMNAME;
-
- $mail = new PHPMailer;
-
- $mail->isSMTP();
- $mail->Host = $MAIL_HOST;
- $mail->SMTPAuth = true;
- $mail->Username = $MAIL_USERNAME;
- $mail->Password = $MAIL_PASSWORD;
- $mail->SMTPSecure = $MAIL_SMTPSECURE;
- $mail->Port = $MAIL_PORT;
-
- $mail->From = $MAIL_FROM;
- $mail->FromName = $MAIL_FROMNAME;
-
- return $mail;
-}
-
-function sendEmail($email, $recipient, $subject, $body) {
- $mail = createMailObject();
- $mail->addAddress($email, $recipient); // Add a recipient
- $mail->isHTML(true);
-
- $mail->Subject = $subject;
- $mail->Body = $body;
-
- $mail->send();
-}
-
-function getNewBoardEmailBody($boardid, $username, $boardname) {
- $message = file_get_contents('mail_templates/newBoard.html');
- $message = str_replace('%hostname%', getServerHost(), $message);
- $message = str_replace('%boardid%', $boardid, $message);
- $message = str_replace('%username%', $username, $message);
- $message = str_replace('%boardname%', $boardname, $message);
-
- return $message;
-}
-
-function getEditBoardEmailBody($boardid, $username, $boardname) {
- $message = file_get_contents('mail_templates/editBoard.html');
- $message = str_replace('%hostname%', getServerHost(), $message);
- $message = str_replace('%boardid%', $boardid, $message);
- $message = str_replace('%username%', $username, $message);
- $message = str_replace('%boardname%', $boardname, $message);
-
- return $message;
-}
-
-function getNewItemEmailBody($boardid, $username, $boardname, $title, $description, $assignee, $category, $dueDate, $points, $position)
-{
- $message = file_get_contents('mail_templates/newItem.html');
- $message = str_replace('%hostname%', getServerHost(), $message);
- $message = str_replace('%boardid%', $boardid, $message);
- $message = str_replace('%username%', $username, $message);
- $message = str_replace('%boardname%', $boardname, $message);
- $message = str_replace('%title%', $title, $message);
- $message = str_replace('%description%', $description, $message);
- $message = str_replace('%assignee%', $assignee, $message);
- $message = str_replace('%category%', $category, $message);
- $message = str_replace('%duedate%', $dueDate, $message);
- $message = str_replace('%points%', $points, $message);
- $message = str_replace('%position%', $position, $message);
-
- return $message;
-}
-
-function getEditItemEmailBody($boardid, $username, $boardname, $title, $description, $assignee, $category, $dueDate, $points, $position)
-{
- $message = file_get_contents('mail_templates/editItem.html');
- $message = str_replace('%hostname%', getServerHost(), $message);
- $message = str_replace('%boardid%', $boardid, $message);
- $message = str_replace('%username%', $username, $message);
- $message = str_replace('%boardname%', $boardname, $message);
- $message = str_replace('%title%', $title, $message);
- $message = str_replace('%description%', $description, $message);
- $message = str_replace('%assignee%', $assignee, $message);
- $message = str_replace('%category%', $category, $message);
- $message = str_replace('%duedate%', $dueDate, $message);
- $message = str_replace('%points%', $points, $message);
- $message = str_replace('%position%', $position, $message);
-
- return $message;
-}
-
-function getNewCommentEmailBody($boardid, $username, $boardname, $title, $comment)
-{
- $message = file_get_contents('mail_templates/newComment.html');
- $message = str_replace('%hostname%', getServerHost(), $message);
- $message = str_replace('%boardid%', $boardid, $message);
- $message = str_replace('%username%', $username, $message);
- $message = str_replace('%boardname%', $boardname, $message);
- $message = str_replace('%title%', $title, $message);
- $message = str_replace('%comment%', $comment, $message);
-
- return $message;
-}
-
-function getEditCommentEmailBody($boardid, $username, $boardname, $title, $comment)
-{
- $message = file_get_contents('mail_templates/editComment.html');
- $message = str_replace('%hostname%', getServerHost(), $message);
- $message = str_replace('%boardid%', $boardid, $message);
- $message = str_replace('%username%', $username, $message);
- $message = str_replace('%boardname%', $boardname, $message);
- $message = str_replace('%title%', $title, $message);
- $message = str_replace('%comment%', $comment, $message);
-
- return $message;
-}
diff --git a/api/mail_templates/editBoard.html b/api/mail_templates/editBoard.html
deleted file mode 100644
index eff5c56..0000000
--- a/api/mail_templates/editBoard.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-%username% updated board %boardname%!
-Navigate to board!
-
-
diff --git a/api/mail_templates/editComment.html b/api/mail_templates/editComment.html
deleted file mode 100644
index 1ba2538..0000000
--- a/api/mail_templates/editComment.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-%username% edited comment at board %boardname%:
-%title%
-%comment%
-
-Navigate to board!
-
-
diff --git a/api/mail_templates/editItem.html b/api/mail_templates/editItem.html
deleted file mode 100644
index 240e766..0000000
--- a/api/mail_templates/editItem.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-%username% edited item at board %boardname%:
-%title%
-%description%
-%duedate%
-%assignee%
-%category%
-%points%
-%position%
-Navigate to board!
-
-
-
diff --git a/api/mail_templates/newBoard.html b/api/mail_templates/newBoard.html
deleted file mode 100644
index 654c02a..0000000
--- a/api/mail_templates/newBoard.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-%username% created new board %boardname%!
-Navigate to board!
-
-
diff --git a/api/mail_templates/newComment.html b/api/mail_templates/newComment.html
deleted file mode 100644
index 429e739..0000000
--- a/api/mail_templates/newComment.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-%username% created new comment at board %boardname%:
-%title%
-%comment%
-
-Navigate to board!
-
-
diff --git a/api/mail_templates/newItem.html b/api/mail_templates/newItem.html
deleted file mode 100644
index 5bafe90..0000000
--- a/api/mail_templates/newItem.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-%username% created new item at board %boardname%:
-%title%
-%description%
-%duedate%
-%assignee%
-%category%
-%points%
-%position%
-Navigate to board!
-
-
-
diff --git a/api/userRoutes.php b/api/userRoutes.php
deleted file mode 100644
index 9e86030..0000000
--- a/api/userRoutes.php
+++ /dev/null
@@ -1,280 +0,0 @@
-post('/login', function() use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- $expires = ($data->rememberme)
- ? (2 * 7 * 24 * 60 * 60) /* Two weeks */
- : (1.5 * 60 * 60) /* One and a half hours */;
-
- $lookup = R::findOne('user', ' username = ? ', [$data->username]);
-
- $jsonResponse->message = 'Invalid username or password.';
- $app->response->setStatus(401);
-
- if (null != $lookup) {
- $hash = password_hash($data->password, PASSWORD_BCRYPT, array('salt' => $lookup->salt));
- if ($lookup->password == $hash) {
- if ($lookup->logins == 0 && $lookup->username == 'admin') {
- $jsonResponse->addAlert('warning', "This is your first login, don't forget to change your password.");
- $jsonResponse->addAlert('success', 'Go to Settings to add your first board.');
- }
- setUserToken($lookup, $expires);
- $lookup->logins = $lookup->logins + 1;
- $lookup->lastLogin = time();
- R::store($lookup);
-
- logAction($lookup->username . ' logged in.', null, null);
- $jsonResponse->message = 'Login successful.';
- $jsonResponse->data = R::findOne('token', ' user_id = ? ORDER BY id DESC ', [$lookup->id])->token;
- $app->response->setStatus(200);
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Log out a user by clearing tokens.
-$app->get('/logout', function() use ($app, $jsonResponse) {
- if (validateToken()) {
- clearDbToken();
- $jsonResponse->message = 'Logout complete.';
- $actor = getUser();
- logAction($actor->username . ' logged out.', null, null);
- }
- $app->response->setStatus(200); // Doesn't matter if the token was no good.
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Update current user's password.
-$app->post('/updatepassword', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- if (null != $user) {
- $checkPass = password_hash($data->currentPass, PASSWORD_BCRYPT, array('salt' => $user->salt));
- if ($user->password == $checkPass) {
- $before = $user->export();
- $user->password = password_hash($data->newPass, PASSWORD_BCRYPT, array('salt' => $user->salt));
- R::store($user);
-
- logAction($user->username . ' changed their password.', $before, $user->export());
- $jsonResponse->addAlert('success', 'Password changed.');
- } else {
- $jsonResponse->addAlert('error', 'Invalid current password. Password not changed.');
- }
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Update current user's username if not taken.
-$app->post('/updateusername', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $before = $user->export();
- $user = updateUsername($user, $data);
- R::store($user);
-
- if ($jsonResponse->alerts[0]['type'] == 'success') {
- logAction($before['username'] . ' changed username to ' . $user->username, $before, $user->export());
- }
- $jsonResponse->addBeans(getUsers());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Update current user's email if not taken.
-$app->post('/updateemail', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $before = $user->export();
- $user = updateEmail($user, $data);
- R::store($user);
-
- if ($jsonResponse->alerts[0]['type'] == 'success') {
- logAction($before['username'] . ' changed email to ' . $user->email, $before, $user->export());
- }
- $jsonResponse->addBeans(getUsers());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Update current user's default board.
-$app->post('/updateboard', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- $before = $user->export();
- $user->defaultBoard = $data->defaultBoard;
-
- R::store($user);
-
- logAction($user->username . ' changed their default board.', $before, $user->export());
- $jsonResponse->addBeans(getUsers());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Get all user actions
-$app->get('/actions', function() use($app, $jsonResponse) {
- if (validateToken(true)) {
- $actions = R::findAll('activity', ' order by timestamp desc ');
- $jsonResponse->addBeans($actions);
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Get current user
-$app->get('/users/current', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
- if (null != $user) {
- $userOptions = R::exportAll($user->xownOptionList);
- $options = [
- 'tasksOrder' => $userOptions[0]['tasks_order'],
- 'showAssignee' => $userOptions[0]['show_assignee'] == 1,
- 'showAnimations' => $userOptions[0]['show_animations'] == 1
- ];
- $jsonResponse->data = [
- 'userId' => $user->id,
- 'username' => $user->username,
- 'isAdmin' => $user->isAdmin,
- 'email' => $user->email,
- 'defaultBoard' => $user->defaultBoard,
- 'options' => $options
- ];
- }
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-$app->post('/users/current/options', function() use ($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken()) {
- $user = getUser();
-
- $user->xownOptionList[0]->tasksOrder = $data->tasksOrder;
- $user->xownOptionList[0]->showAssignee = $data->showAssignee;
- $user->xownOptionList[0]->showAnimations = $data->showAnimations;
- R::store($user);
-
- $jsonResponse->data = $data;
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Get all users
-$app->get('/users', function() use($app, $jsonResponse) {
- if (validateToken()) {
- $jsonResponse->addBeans(getUsers());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Create a new user
-$app->post('/users', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $nameTaken = R::findOne('user', ' username = ?', [$data->username]);
-
- if (null != $nameTaken) {
- $jsonResponse->addAlert('error', 'Username already in use.');
- } else {
- $user = R::dispense('user');
- $user->username = $data->username;
- $user->isAdmin = $data->isAdmin;
- $user->email = $data->email;
- $user->defaultBoard = $data->defaultBoard;
- $user->salt = password_hash($data->username . time(), PASSWORD_BCRYPT);
- $user->password = password_hash($data->password, PASSWORD_BCRYPT, array('salt' => $user->salt));
-
- $options = R::dispense('option');
- $options->tasksOrder = 0; // Bottom of column (1 == top of column)
- $options->showAnimations = true;
- $options->showAssignee = true;
- $user->xownOptionList[] = $options;
-
- R::store($user);
- addUserToBoard($data->defaultBoard, $user);
-
- if (property_exists($data, 'boardAccess') && is_array($data->boardAccess)) {
- foreach($data->boardAccess as $board) {
- addUserToBoard($board, $user);
- }
- }
-
- $actor = getUser();
- logAction($actor->username . ' added user ' . $user->username, null, $user->export());
- $jsonResponse->addAlert('success', 'New user ' . $user->username . ' created.');
- }
- $jsonResponse->addBeans(getUsers());
- $jsonResponse->boards = R::exportAll(getBoards());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Update a user
-$app->post('/users/update', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $user = R::load('user', $data->userId);
- $actor = getUser();
- if ($user->id && $actor->isAdmin) {
- $before = $user->export();
- if ($data->newUsername != $user->username) {
- $user = updateUsername($user, $data);
- }
- if ($data->password != '' && $data->password != null) {
- $user->password = password_hash($data->password, PASSWORD_BCRYPT, array('salt' => $user->salt));
- }
- $user->isAdmin = $data->isAdmin;
- $user->email = $data->email;
- $user->defaultBoard = $data->defaultBoard;
-
- R::store($user);
- addUserToBoard($data->defaultBoard, $user);
- foreach($data->boardAccess as $board) {
- addUserToBoard($board, $user);
- }
-
- logAction($actor->username . ' updated user ' . $user->username, $before, $user->export());
- $jsonResponse->addAlert('success', 'User updated.');
- }
- $jsonResponse->addBeans(getUsers());
- $jsonResponse->boards = R::exportAll(getBoards());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
-
-// Remove a user.
-$app->post('/users/remove', function() use($app, $jsonResponse) {
- $data = json_decode($app->environment['slim.input']);
-
- if (validateToken(true)) {
- $user = R::load('user', $data->userId);
- $actor = getUser();
- if ($user->id == $data->userId && $actor->isAdmin) {
- $before = $user->export();
- R::trash($user);
- R::exec('DELETE from board_user WHERE user_id = ?', [$data->userId]);
-
- logAction($actor->username . ' removed user ' . $before['username'], $before, null);
- $jsonResponse->addAlert('success', 'Removed user ' . $user->username . '.');
- }
- $jsonResponse->addBeans(getUsers());
- $jsonResponse->boards = R::exportAll(getBoards());
- }
- $app->response->setBody($jsonResponse->asJson());
-});
diff --git a/build/Dockerfile b/build/Dockerfile
deleted file mode 100644
index 2e43caf..0000000
--- a/build/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-# Dockerfile for Taskboard with nginx and sqlite.
-
-FROM ubuntu:trusty
-MAINTAINER Alex van den Hoogen
-
-RUN apt-get update && \
- apt-get install -yq --no-install-recommends git wget nginx php5-fpm php5-sqlite sqlite3 ca-certificates pwgen && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/*
-
-RUN echo "cgi.fix_pathinfo = 0;" >> /etc/php5/fpm/php.ini && \
- echo "daemon off;" >> /etc/nginx/nginx.conf && \
- mkdir -p /var/www
-
-RUN git clone https://github.com/kiswa/TaskBoard.git /var/www && \
- chmod 777 $(find /var/www -type d)
-
-ADD nginx.conf /etc/nginx/sites-available/default
-
-EXPOSE 80
-
-CMD service php5-fpm start && nginx
\ No newline at end of file
diff --git a/build/build-all b/build/build-all
deleted file mode 100755
index ba6d1f6..0000000
--- a/build/build-all
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-set -e
-
-echo Building...
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd $DIR
-
-echo ' Installing dependencies'
-cd ..
-./build/composer.phar install
-cd build
-
-echo ' Compiling lib JS files...'
-./minify-libs
-
-echo ' Minifying lib CSS files...'
-cd ../lib/css/
-cat bootstrap.min.css > combined.css
-cat font-awesome.min.css >> combined.css
-cat jquery-ui.min.css >> combined.css
-cat spectrum.css >> combined.css
-curl -X POST -s --data-urlencode 'input@combined.css' http://cssminifier.com/raw > combined.min.css
-rm combined.css
-cd ../../build/
-
-echo ' Compiling app JS files...'
-./minify-app
-
-echo ' Minifying app CSS files...'
-cd ../css/
-curl -X POST -s --data-urlencode 'input@styles.css' http://cssminifier.com/raw > styles.min.css
-cd ../build/
-
-echo ' Updating index.html...'
-cd ../
-if [ -f indexProd.html ]; then
- mv index.html indexDev.html
- mv indexProd.html index.html
-fi
-cd build/
-
-echo Build Complete
diff --git a/build/clean b/build/clean
deleted file mode 100755
index 3e56119..0000000
--- a/build/clean
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-echo Cleaning...
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd $DIR
-
-echo ' Cleaning CSS files...'
-rm -f ../lib/css/combined.min.css
-rm -f ../css/styles.min.css
-
-echo ' Cleaning JS files...'
-rm -f ../js/app.min.js
-rm -f ../lib/libs.min.js
-
-echo ' Restoring index.html...'
-cd ../
-if [ -f indexDev.html ]; then
- mv index.html indexProd.html
- mv indexDev.html index.html
-fi
-cd build/
-
-echo Clean Complete
diff --git a/build/compiler.jar b/build/compiler.jar
deleted file mode 100644
index c7006a8..0000000
Binary files a/build/compiler.jar and /dev/null differ
diff --git a/build/composer.phar b/build/composer.phar
deleted file mode 100755
index 93f06b8..0000000
Binary files a/build/composer.phar and /dev/null differ
diff --git a/build/minify-app b/build/minify-app
deleted file mode 100755
index 2ffbb94..0000000
--- a/build/minify-app
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-cd ../js/
-java -jar ../build/compiler.jar -W QUIET --js app.js controllers/*.js services/*.js directives/*.js --js_output_file app.min.js
diff --git a/build/minify-libs b/build/minify-libs
deleted file mode 100755
index c6f1cfb..0000000
--- a/build/minify-libs
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-cd ../lib/
-java -jar ../build/compiler.jar -W QUIET --js jquery-1.11.3.min.js jquery-ui.min.js jquery.noty.min.js bootstrap.min.js angular.min.js angular-route.min.js angular-sanitize.min.js ng-context-menu.min.js marked.min.js spectrum.js prefixfree.min.js --js_output_file libs.min.js
diff --git a/build/nginx.conf b/build/nginx.conf
deleted file mode 100644
index 6fba378..0000000
--- a/build/nginx.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-server {
- listen 80 default_server;
- listen [::]:80 default_server ipv6only=on;
-
- root /var/www;
- index index.php index.html;
-
- # Make site accessible from http://localhost/
- server_name localhost;
-
- location / {
- try_files $uri $uri/ /index.php?$args;
- }
-
- location /api {
- if (!-e $request_filename) {
- rewrite ^(.*)$ /api/api.php last; break;
- }
- }
-
- location /api/taskboard.db {
- rewrite ^(.*)$ /api/api.php last; break;
- }
-
- location ~ \.php$ {
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
-
- fastcgi_pass unix:/var/run/php5-fpm.sock;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- fastcgi_index index.php;
- include fastcgi_params;
- }
-}
\ No newline at end of file
diff --git a/composer.json b/composer.json
deleted file mode 100644
index 583cecb..0000000
--- a/composer.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "name": "kiswa/taskboard",
- "require": {
- "slim/slim": "=2.6.1",
- "firebase/php-jwt": "=1.0.0",
- "ircmaxell/password-compat": "~1.0.3",
- "gabordemooij/redbean": "=4.2.0",
- "phpmailer/phpmailer": "~5.2.9"
- },
- "license": "MIT",
- "authors": [
- {
- "name": "Matthew Ross"
- }
- ],
- "minimum-stability": "stable"
-}
diff --git a/composer.lock b/composer.lock
deleted file mode 100644
index e462e75..0000000
--- a/composer.lock
+++ /dev/null
@@ -1,253 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
- "This file is @generated automatically"
- ],
- "hash": "bcd0d77c65d6fda9ece3a2600d80347c",
- "content-hash": "99f3562842898771c354cfc411491902",
- "packages": [
- {
- "name": "firebase/php-jwt",
- "version": "1.0.0",
- "target-dir": "Firebase/PHP-JWT",
- "source": {
- "type": "git",
- "url": "https://github.com/firebase/php-jwt.git",
- "reference": "58c1e61d0dff797f2989c54415229f4016d57a6d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/firebase/php-jwt/zipball/58c1e61d0dff797f2989c54415229f4016d57a6d",
- "reference": "58c1e61d0dff797f2989c54415229f4016d57a6d",
- "shasum": ""
- },
- "require": {
- "php": ">=5.2.0"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "Authentication/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Neuman Vong",
- "email": "neuman+pear@twilio.com",
- "role": "Developer"
- },
- {
- "name": "Anant Narayanan",
- "email": "anant@php.net",
- "role": "Developer"
- }
- ],
- "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
- "homepage": "https://github.com/firebase/php-jwt",
- "time": "2014-08-28 17:14:17"
- },
- {
- "name": "gabordemooij/redbean",
- "version": "v4.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/gabordemooij/redbean.git",
- "reference": "840a2e0d856042e75a701453f37896c597c6fbc2"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/gabordemooij/redbean/zipball/840a2e0d856042e75a701453f37896c597c6fbc2",
- "reference": "840a2e0d856042e75a701453f37896c597c6fbc2",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.4"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "RedBeanPHP\\": "RedBeanPHP"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "New BSD and GPLv2"
- ],
- "authors": [
- {
- "name": "Gabor de Mooij",
- "email": "gabor@redbeanphp.com",
- "homepage": "http://redbeanphp.com"
- }
- ],
- "description": "RedBeanPHP ORM",
- "homepage": "http://redbeanphp.com/",
- "keywords": [
- "orm"
- ],
- "time": "2015-04-01 19:03:42"
- },
- {
- "name": "ircmaxell/password-compat",
- "version": "v1.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/ircmaxell/password_compat.git",
- "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c",
- "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c",
- "shasum": ""
- },
- "require-dev": {
- "phpunit/phpunit": "4.*"
- },
- "type": "library",
- "autoload": {
- "files": [
- "lib/password.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Anthony Ferrara",
- "email": "ircmaxell@php.net",
- "homepage": "http://blog.ircmaxell.com"
- }
- ],
- "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
- "homepage": "https://github.com/ircmaxell/password_compat",
- "keywords": [
- "hashing",
- "password"
- ],
- "time": "2014-11-20 16:49:30"
- },
- {
- "name": "phpmailer/phpmailer",
- "version": "v5.2.14",
- "source": {
- "type": "git",
- "url": "https://github.com/PHPMailer/PHPMailer.git",
- "reference": "e774bc9152de85547336e22b8926189e582ece95"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e774bc9152de85547336e22b8926189e582ece95",
- "reference": "e774bc9152de85547336e22b8926189e582ece95",
- "shasum": ""
- },
- "require": {
- "php": ">=5.0.0"
- },
- "require-dev": {
- "phpdocumentor/phpdocumentor": "*",
- "phpunit/phpunit": "4.7.*"
- },
- "suggest": {
- "league/oauth2-client": "Needed for XOAUTH2 authentication",
- "league/oauth2-google": "Needed for Gmail XOAUTH2"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "class.phpmailer.php",
- "class.phpmaileroauth.php",
- "class.phpmaileroauthgoogle.php",
- "class.smtp.php",
- "class.pop3.php",
- "extras/EasyPeasyICS.php",
- "extras/ntlm_sasl_client.php"
- ]
- },
- "notification-url": "http://packagist.org/downloads/",
- "license": [
- "LGPL-2.1"
- ],
- "authors": [
- {
- "name": "Jim Jagielski",
- "email": "jimjag@gmail.com"
- },
- {
- "name": "Marcus Bointon",
- "email": "phpmailer@synchromedia.co.uk"
- },
- {
- "name": "Andy Prevost",
- "email": "codeworxtech@users.sourceforge.net"
- },
- {
- "name": "Brent R. Matzelle"
- }
- ],
- "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
- "time": "2015-11-01 10:15:28"
- },
- {
- "name": "slim/slim",
- "version": "2.6.1",
- "source": {
- "type": "git",
- "url": "https://github.com/slimphp/Slim.git",
- "reference": "365dbfa0c02a31e76888eaec693dacd9dca1c82a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/slimphp/Slim/zipball/365dbfa0c02a31e76888eaec693dacd9dca1c82a",
- "reference": "365dbfa0c02a31e76888eaec693dacd9dca1c82a",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "suggest": {
- "ext-mcrypt": "Required for HTTP cookie encryption"
- },
- "type": "library",
- "autoload": {
- "psr-0": {
- "Slim": "."
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Josh Lockhart",
- "email": "info@joshlockhart.com",
- "homepage": "http://www.joshlockhart.com/"
- }
- ],
- "description": "Slim Framework, a PHP micro framework",
- "homepage": "http://github.com/codeguy/Slim",
- "keywords": [
- "microframework",
- "rest",
- "router"
- ],
- "time": "2015-03-02 19:09:48"
- }
- ],
- "packages-dev": [],
- "aliases": [],
- "minimum-stability": "stable",
- "stability-flags": [],
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": [],
- "platform-dev": []
-}
diff --git a/css/styles.css b/css/styles.css
deleted file mode 100644
index 64c09cd..0000000
--- a/css/styles.css
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- Contents:
-
- #General - Styles that apply throughout.
- #Login - Login page specific styles.
- #PageTop - Styles for the top bar across pages (includes board navigation).
- #SiteNav - Site navigation section styles.
- #BoardLayout - Styles specific to the board layout.
- #ViewItem - Styles for item view modal.
- #SettingsPage - Styles specific to the settings page.
- #FilesPage - Styles for the file viewer page.
- #3rdParty - Styles for 3rd party widgets (noty, calendar, etc.)
-*/
-
-/* #General */
-html, body {
- height: 100%;width: 100%;
-}
-body {
- background: url(../images/bg.png);
- font-family: "Pontano Sans", sans-serif;
- font-size: 12pt;
-}
-th, h1, h2, h3, h4, h5, h6, #board-nav a {
- font-family: "Raleway";
- font-weight: 500;
-}
-th {
- font-size: 91%;
-}
-a, button {
- transition: background-color 0.3s, color 0.3s;
-}
-a:hover.fa {
- text-decoration: none;
-}
-textarea {
- resize: vertical;
-}
-.green {
- color: green;
-}
-.red {
- color: darkred;
-}
-.dateNear {
- text-shadow: 0px 0px 3px rgba(255, 163, 84, 1);
-}
-.datePast {
- text-shadow: 0px 0px 3px rgba(255, 81, 28, 1);
-}
-.unbold {
- font-weight: normal;
-}
-.fa-edit, .fa-trash-o {
- cursor: pointer;
-}
-.pull-up {
- margin-top: -10px;
-}
-#wrapper {
- display: table;
- table-layout: fixed;
- border-spacing: 5px;
- width: 100%;
- height: 100%;
- overflow-x: scroll;
- margin: 0;
- padding: 0;
-}
-
-/* #Login */
-.form-signin {
- max-width: 350px;
- padding: 15px;
- margin: 0 auto;
-}
-.form-signin .form-signin-heading,
-.form-signin .checkbox {
- margin-bottom: 10px;
- font-weight: normal;
- text-align: center;
-}
-.form-signin .form-signin-heading {
- margin-top: .5em;
-}
-.form-signin .form-control {
- position: relative;
- height: auto;
- box-sizing: border-box;
- padding: 10px;
- font-size: 16px;
-}
-.form-signin .form-control:focus {
- z-index: 2;
-}
-.form-signin input[type="text"] {
- margin-bottom: -1px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
- text-align: center;
-}
-.form-signin input[type="password"] {
- margin-bottom: 10px;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- text-align: center;
-}
-.login-container {
- background: #fff;
- border: 1px solid #ccc;
- width: 350px;
- height: 275px;
- margin: 2em auto;
- position: relative;
-}
-.login-error {
- text-align: center;
- font-weight: bold;
- margin-bottom: -2.1em;
-}
-.login-container::before, .login-container::after {
- content: "";
- width: 100%; height: 100%;
- position: absolute;
- top: 0; left: 0;
- background: #ededed;
- border: 1px solid #ccc;
- z-index: -1;
- transform: rotateZ(4deg);
-}
-.login-container::after {
- top: 4px;
- z-index: -2;
- background: #efefef;
- transform: rotateZ(-4deg);
-}
-
-/* #PageTop */
-#header {
- display: table-row;
- margin: 0;
-}
-#header h2 {
- border-bottom: 1px solid rgba(51,51,51,.2);
- margin-top: 5px;
- padding-bottom: 10px;
-}
-#board-nav {
- margin-top: -10px;
- overflow: hidden;
-}
-#board-nav p {
- margin-bottom: 2px;
- margin-left: 3px;
-}
-#board-nav .form-control {
- height: auto;
- padding: 3px 6px;
- margin-right: 7px;
-}
-#board-nav :last-child.form-control {
- margin-right: 0;
-}
-.version {
- margin-top: 5px;
- font-size: small !important;
-}
-/* #SiteNav*/
-.nav {
- margin-top: -.7em;
- padding: 0;
-}
-.nav>li.active>a {
- cursor: default;
-}
-.nav>li>a {
- border: 1px solid #ccc;
- background-color: #eee;
-}
-.nav>li>a:hover,.nav>li>a:focus {
- background-color: #fff;
-}
-.content {
- display: table-row;
- height: 100%;
-}
-
-/* #BoardLayout */
-#board {
- overflow-x: auto;
- width: 100%;
- height: 100%;
-}
-#boardColumns {
- display: table;
- width: 100%;
- height: 100%;
-}
-.boardColumn {
- display: table-cell;
- overflow: auto;
- min-width: 260px;
- max-width: 300px;
- height: 100%;
- margin: 5px;
- border: 1px solid rgba(51,51,51,.3);
- box-shadow: 0px 0px 3px 0px rgba(51,51,51,.2);
- border-radius: 3px;
- background-color: #fff;
-}
-.boardColumn > h3 {
- margin: 0;
- padding: 5px;
- background-color: #e0edf2;
- border-bottom: 1px solid rgba(51,51,51,.05);
-}
-.itemContainer {
- height: 94%;
- overflow: auto;
-}
-.default-cursor {
- cursor: default;
-}
-.pointer-cursor {
- cursor: pointer;
-}
-.filtered {
- opacity: 0.4;
-}
-.boardColumn.collapsed {
- min-width: 0;
- width: 1.9em;
- padding: 0;
- margin: 0;
- background-color: #e0edf2;
-}
-.boardColumn.collapsed > h3 {
- border: none;
- width: 1.5em;
- white-space: nowrap;
- transform: rotate(90deg) translateX(-30px);
- transform-origin: left bottom;
-}
-.shrink {
- float: right;
- margin-top: 5px;
- cursor: pointer;
-}
-.expand {
- display: none;
- cursor: pointer;
- transform: translateY(-3px) translateX(-10px);
-}
-.boardColumn.collapsed .shrink {
- display: none;
-}
-.boardColumn.collapsed .expand {
- display: inline-block;
- margin-left: 1em;
-}
-.boardColumn.collapsed .itemContainer {
- display: none;
-}
-.boardColumn.collapsed .badge {
- transform: rotate(-90deg) translateX(4px);
-}
-.boardItem {
- background: lightyellow;
- padding: 3px;
- margin: 5px;
- border: 1px solid rgba(51,51,51,.1);
- border-radius: 3px;
- box-shadow: 1px 1px 2px -1px rgba(51,51,51,.2);
-}
-.itemHeader {
- position: relative;
-}
-.itemHeader h4 {
- border-bottom: 1px dotted rgba(51,51,51,.3);
- cursor: move;
- padding-bottom: 3px;
- margin: 0;
- padding-right: 25px;
-}
-.itemHeader .badge {
- position: absolute;
- right: 0;
- top: 0;
- margin: 0;
- font-family: "Pontano Sans";
- border-radius: 7px;
- cursor: default;
-}
-.boardItem .category {
- font-weight: 700;
- text-align: right;
- display: inline-block;
- width: 100%;
- padding-right: 3px;
-}
-.boardItem .description {
- margin: 3px;
- max-height: 12em;
- overflow: auto;
-}
-.boardItem .assignee {
- font-size: .8em;
- font-family: Raleway;
-}
-.boardItem p:last-child {
- margin-bottom: 0;
-}
-.addItem {
- margin: 5px;
- text-align: right;
-}
-.draggable-placeholder {
- height: 80px;
- box-shadow: inset 0px 0px 10px 0px rgba(51,51,51,.25);
- border-radius: 5px;
- margin: 5px;
-}
-span.fa {
- margin-right: 5px;
-}
-.lane-placeholder {
- width: 100%;
- height: 1.2em;
- box-shadow: inset 0px 0px 10px 0px rgba(0,0,0,.25);
- list-style: none;
-}
-.dropdown.fixed {
- position: fixed;
-}
-.contextItemWrap {
- margin: -5px 10px 0 19px;
- display: block;
-}
-
-/* #ViewItem */
-.itemViewModal .modal-dialog {
- width: 700px;
-}
-.itemViewModal .modal-content, .view-item-details {
- overflow: hidden;
-}
-.itemViewModal h4 {
- padding-top: 1em;
-}
-.due-date {
- font-weight: bold;
- font-size: 1.1em;
- margin: .9em;
-}
-.view-item-details {
- padding-bottom: .5em;
- font-size: 91%;
- border: 1px solid rgba(51,51,51,.1);
- border-radius: 5px;
-}
-.view-item-details .description {
- margin: 1em;
- max-height: 500px;
- overflow: auto;
-}
-.view-item-actions {
- overflow: hidden;
- padding: .5em 0;
-}
-.view-item-actions a {
- display: block;
-}
-.alternate {
- background-color: rgba(51,51,51,.04);
-}
-.view-item-attachments .list-group {
- margin-bottom: 0;
-}
-.view-item-comment-form {
- overflow: hidden;
-}
-.edit-item-comment-form {
- overflow: hidden;
-}
-.edit-item-comment-form button {
- margin-left: 5px;
- margin-top: 5px;
-}
-.detail {
- display: block;
- font-size: 80%;
- margin-left: 1em;
-}
-p.detail {
- margin-top: -10px;
- margin-bottom: 0;
-}
-.links {
- margin-top: -2em;
-}
-.links a {
- margin-left: 3px;
-}
-.commentText {
- display: inline-block;
- width: 95%;
- overflow: hidden;
-}
-.commentActions {
- position: absolute;
- top: .8em;
- right: .4em;
-}
-.commentActions a {
- margin-left: 3px;
-}
-#add-comment {
- margin-top: 5px;
-}
-.sidebar {
- position: fixed;
- top: 30px;
- left: 0;
- width: 240px;
- height: 85%;
- background: #fff;
- border-radius: 0;
- border-top-right-radius: 6px;
- border-bottom-right-radius: 6px;
- border: 1px solid rgba(0,0,0,0.2);
- box-shadow: 0 5px 15px rgba(0,0,0,0.5);
- transition: all 0.3s ease;
-}
-.sidebar .modal-header {
- position: fixed;
- width: 238px;
-}
-.sidebar .sidebar-content {
- margin-top: 2.55em;
- overflow: auto;
- height: 93.6%;
-}
-.sidebar.toggle {
- left:-240px;
-}
-.sidebar .fa {
- cursor: pointer;
-}
-.sidebar .showtab {
- border-radius: 0;
- border-top-right-radius: 6px;
- border-bottom-right-radius: 6px;
- border: 1px solid rgba(0,0,0,0.2);
- box-shadow: 0 5px 15px rgba(0,0,0,0.5);
- position: fixed;
- top: 30px;
- left: 0;
- width: auto;
-}
-.showtab.toggle {
- display:none;
-}
-.sidebar .action {
- margin: 5px;
-}
-
-/* #SettingsPage */
-.form-control.wide {
- width: 85%;
- margin-bottom: 5px;
-}
-.short-top {
- margin-top: -1em;
-}
-label.wide {
- font-weight: normal;
- width: 100%;
-}
-.fa-arrows-v {
- cursor: move;
- padding: 0 6px 0 5px;
- margin: 0 3px 0 0;
- border-right: 1px solid #ccc;
-}
-#widget-container {
- display: table-cell;
-}
-.min-padding { padding: 5px; }
-.settings-widget {
- border: 1px solid rgba(51,51,51,.2);
- border-radius: 5px;
- background-color: #fff;
- box-shadow: 0px 0px 3px 0px rgba(51,51,51,.2);
-}
-.widget-header, .modal-header {
- margin: 0 0 5px 0;
- padding: 7px;
- border-radius: 5px 5px 0 0;
- background-color: #e0edf2;
- border-bottom: 1px solid rgba(51,51,51,.05);
-}
-.widget-content {
- margin: 5px;
- cursor: auto;
-}
-.widget-content h4 {
- clear: both;
-}
-.widget-content .list-group-item {
- padding: 3px 7px;
- background: transparent;
- min-width: 125px;
-}
-.list-group-item.small {
- padding: 3px;
-}
-.list-group.editable > .list-group-item {
- overflow: hidden;
-}
-td > .list-group {
- margin: 0;
- padding: 0;
-}
-fieldset > .list-group {
- margin-bottom: 10px;
-}
-span.filter {
- margin-left: 5px;
-}
-.board-status {
- font-weight: normal;
- display: inline-block;
- min-width: 70px;
-}
-#change-password, #default-board, #change-username, #change-email {
- width: 48%;
- float: left;
- margin-bottom: 1em;
-}
-#change-username, #change-email {
- margin-left: 4%;
- margin-bottom: .6em;
-}
-.board-options p {
- width: 48%;
- float: left;
- margin-bottom: 1em;
-}
-.board-options label {
- font-weight: normal;
-}
-#changeUserSettings hr, .board-options hr {
- clear: both;
-}
-.badge { margin: 0 3px; }
-.half-width {
- width: 50%;
- float: left;
- padding-right: 10px;
- margin-right: 0;
-}
-.half-width > ul {
- margin-right: 1em;
-}
-.list-group-item > a {
- margin-right: 5px;
- margin-top: 3px;
- vertical-align: top;
-}
-input.custom-inline {
- height: auto;
- padding: 0 6px;
- margin-top: -3px;
-}
-/* Activity Log slide out */
-.slide-menu {
- position: fixed;
- width: 240px;
- height: 100%;
- top: 90px;
- z-index: 10000;
- right: -240px;
- transition: all 0.3s ease;
-}
-.slide-menu .fa-times {
- cursor: pointer;
-}
-.slide-menu-open {
- right: 0;
-}
-.slide-menu > .settings-widget {
- height: 85%;
-}
-.slide-menu .widget-header {
- position: fixed;
- width: 240px;
-}
-.slide-menu .widget-content {
- margin-top: 3em;
- height: 92%;
- overflow: auto;
-}
-.action {
- border: 1px solid rgba(51,51,51,.2);
- border-radius: 5px;
- box-shadow: inset 0px 0px 5px 0px rgba(51,51,51,.2);
- background-color: rgba(51,51,51,.005);
- padding: 5px;
- margin: 0;
- margin-bottom: 5px;
-}
-.action .timestamp {
- margin-bottom: -5px;
- font-size: .8em;
-}
-
-/* #FilesPage */
-.files-wrapper {
- height: 100%;
-}
-
-.files-widget {
- border: 1px solid rgba(51,51,51,.2);
- border-radius: 5px;
- background-color: #fff;
- box-shadow: 0px 0px 3px 0px rgba(51,51,51,.2);
- height: 100%;
-}
-
-.files-widget .widget-content {
- height: 90%;
-}
-
-.files-widget .small.pull-right {
- margin-top: .3em;
-}
-
-#iframe-wrapper {
- width: 100%;
- height: 100%;
-}
-#iframe-wrapper iframe {
- display: block;
- border: 1px solid rgba(51,51,51,.3);
- width: 100%;
- height: 100%;
-}
-
-/* #3rdParty */
-/* Bootstrap fix */
-.table-responsive {
- overflow-x: inherit;
-}
-/* noty notifications */
-.noty_bar {
- color: #fff;
- font-weight: bold;
- text-shadow: 0 0 2px #333;
-}
-.noty_type_error {
- background-color: #d9534f;
- border-color: #d43f3a;
-}
-.noty_type_warning {
- background-color: #f0ad4e;
- border-color: #eea236;
-}
-.noty_type_information {
- background-color: #5bc0de;
- border-color: #46b8da;
-}
-.noty_type_success {
- background-color: #5cb85c;
- border-color: #4cae4c;
-}
-.noty_type_notification {
- background-color: #428bca;
- border-color: #357ebd;
-}
-/* spectrum color picker */
-.sp-replacer {
- display: block;
- height: 34px;
- padding: 6px 12px;
- background-color: #fff;
- border: solid 1px #ccc;
- border-radius: 4px;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-}
-.sp-dd {
- display: none;
-}
-.sp-container {
- width: 202px;
-}
-.sp-disabled {
- background-color: #eee;
-}
-.sp-preview {
- width: 100%;
-}
-.sp-replacer:hover, .sp-replacer.sp-active {
- border-color: rgba(51,51,51,.3);
-}
-.sp-container {
- border: 1px solid #ccc;
- background-color: #fff;
- border-radius: 4px;
-}
-.sp-cf:before, .sp-cf:after {
- display: none !important;
-}
-.sp-palette-container {
- border: none;
- padding-bottom: 290px;
-}
-/* jQueryUI Datepicker */
-.ui-datepicker {
- border: 1px solid rgba(51,51,51,.5);
- background-color: #fff;
- border-radius: 5px;
-}
-.ui-datepicker .ui-datepicker-header {
- border-bottom: 1px dotted rgba(51,51,51,.5);
-}
-.ui-datepicker-week-end {
- background-color: rgba(51,51,51,.05);
-}
-.ui-state-highlight {
- background-color: rgba(51,51,51,.1);
-}
-.ui-state-active {
- background-color: rgba(51,51,51,.2);
-}
-.ui-icon-circle-triangle-e,.ui-icon-circle-triangle-w {
- text-indent: 0 !important;
- cursor: pointer;
-}
-.ui-icon-circle-triangle-e {
- margin-left: -1.2em !important;
-}
-td a.ui-state-hover {
- background-color: rgba(51,51,51,.15);
-}
diff --git a/devrouter.php b/devrouter.php
deleted file mode 100644
index fb68fec..0000000
--- a/devrouter.php
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
- TaskBoard {{ display.smallText }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/indexProd.html b/indexProd.html
deleted file mode 100644
index 67a1539..0000000
--- a/indexProd.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
- TaskBoard {{ display.smallText }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/js/app.js b/js/app.js
deleted file mode 100644
index 7b7b98f..0000000
--- a/js/app.js
+++ /dev/null
@@ -1,82 +0,0 @@
-var taskBoardServices = angular.module('TaskBoardServices', []);
-var taskBoardControllers = angular.module('TaskBoardControllers', []);
-var taskBoardDirectives = angular.module('TaskBoardDirectives', []);
-
-var taskBoard = angular.module('TaskBoard',
- ['ngRoute', 'ngSanitize',
- 'ng-context-menu',
- 'TaskBoardServices',
- 'TaskBoardControllers',
- 'TaskBoardDirectives']);
-
-taskBoard.config(['$routeProvider', '$httpProvider',
-function($routeProvider, $httpProvider) {
- $routeProvider.when('/', {
- controller: 'LoginCtrl',
- templateUrl: 'partials/login.html'
- }).when('/boards', {
- controller: 'BoardCtrl',
- templateUrl: 'partials/boardSelect.html',
- authRequired: true
- }).when('/boards/:boardId', {
- controller: 'BoardCtrl',
- templateUrl: 'partials/board.html',
- authRequired: true,
- resolve: {
- validation: ['$q', '$route', function($q, $route) {
- var deferred = $q.defer(),
- id = parseInt($route.current.params.boardId);
- if (isNaN(id)) {
- deferred.reject('INVALID BOARD ID');
- } else {
- deferred.resolve();
- }
- return deferred.promise;
- }]
- }
- }).when('/settings', {
- controller: 'SettingsCtrl',
- templateUrl: 'partials/settings.html',
- authRequired: true
- }).when('/files/:fileId', {
- controller: 'FilesCtrl',
- templateUrl: 'partials/files.html',
- authRequired: true
- }).otherwise({
- redirectTo: '/'
- });
-
- // Inject the auth token with each API call.
- $httpProvider.interceptors.push('TokenInterceptor');
-}]);
-
-// Custom handlers for route authentication and rejection of invalid board id
-taskBoard.run(['$rootScope', '$location', '$window', 'AuthenticationService',
-function($rootScope, $location, $window, AuthenticationService) {
- $rootScope.version = 'v0.3.1';
-
- $rootScope.$on('$routeChangeStart', function(event, nextRoute, currentRoute) {
- // Redirect to default path if authentication is required but not present.
- if (nextRoute !== null && nextRoute.authRequired !== null &&
- nextRoute.authRequired && !AuthenticationService.isAuthenticated &&
- !$window.localStorage.token) {
- $location.path('/');
- }
- if (nextRoute !== null && nextRoute.controller === 'LoginCtrl' && $window.localStorage.token) {
- $location.path('/boards');
- }
- });
-
- $rootScope.$on('$routeChangeSuccess', function(event, route, previousRoute) {
- if (route.controller === 'LoginCtrl' && previousRoute && previousRoute.originalPath !== '') {
- AuthenticationService.attemptedRoute = previousRoute;
- }
- });
-
- $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {
- // Custom rejection from /boards/:boardId route
- if (rejection === 'INVALID BOARD ID') {
- $location.path('/boards');
- }
- });
-}]);
diff --git a/js/controllers/boards.js b/js/controllers/boards.js
deleted file mode 100644
index 4808653..0000000
--- a/js/controllers/boards.js
+++ /dev/null
@@ -1,280 +0,0 @@
-taskBoardControllers.controller('BoardCtrl',
-['$scope', '$routeParams', '$location', '$interval', '$window',
- 'UserService', 'BoardService', 'AlertService', 'AuthenticationService',
-function ($scope, $routeParams, $location, $interval, $window,
- UserService, BoardService, AlertService, AuthenticationService) {
- // This is here because the BoardCtrl is the default redirect from login.
- // If the user was trying to go somewhere else first, they are redirected now.
- if (AuthenticationService.attemptedRoute) {
- var tmp = AuthenticationService.attemptedRoute,
- path = tmp.originalPath;
-
- tmp.keys.forEach(function(key) {
- path = path.replace(':' + key.name, tmp.params[key.name]);
- });
- AuthenticationService.attemptedRoute = null;
- $location.path(path);
- }
-
- $scope.alerts = AlertService;
- $scope.marked = function(text) {
- if (text) {
- return $window.marked(text);
- } else {
- return '';
- }
- };
-
- $scope.boardId = $routeParams.boardId;
- $scope.filter = {
- user: null,
- category: null,
- hide: false
- };
-
- $scope.filterChanged = function() {
- $scope.currentBoard.ownLane.forEach(function (lane) {
- if (lane.ownItem) {
- lane.ownItem.forEach(function (item) {
- item.filtered = false;
- if ($scope.filter.user !== null) {
- if ($scope.filter.user != item.assignee) {
- item.filtered = true;
- }
- }
- if ($scope.filter.category !== null) {
- if ($scope.filter.category != item.category) {
- item.filtered = true;
- }
- }
- });
- }
- });
- };
-
- $scope.selectBoard = function() {
- $location.path('boards/' + $scope.boardNames.current);
- };
-
- $scope.openEditItem = function() {
- $scope.itemFormData.loadItem($scope.contextItem);
- $('.itemModal textarea').css('height', 'auto');
- $('.itemModal').modal('show');
- };
-
- $scope.openAddItem = function() {
- $scope.itemFormData.reset($scope.contextLaneId);
- $('.itemModal textarea').css('height', 'auto');
- $('.itemModal').modal('show');
- };
-
- $scope.removeItem = function() {
- $scope.openItem($scope.contextItem, false);
- $scope.deleteItem();
- };
-
- $scope.changeItemLane = function() {
- $scope.itemFormData.loadItem($scope.contextItem);
- $scope.itemFormData.isAdd = false;
-
- $scope.submitItem($scope.itemFormData);
- };
-
- $scope.contextItem = {}; // Needs to exist prior to onContextMenu call.
- $scope.onContextMenu = function(laneId, item) {
- $scope.contextItem = item;
- $scope.contextLaneId = laneId;
- };
-
- // This is called every 250ms until the boards are loaded.
- // Once loaded, the repetitive calling is canceled.
- // If a default is found the user is redirected to that board.
- var checkDefaultBoard = function() {
- if ($scope.boardId) {
- $interval.cancel($scope.interval);
- }
- if ($scope.boardsLoaded && !$scope.boardId && $scope.currentUser && parseInt($scope.currentUser.defaultBoard)) {
- $interval.cancel($scope.interval);
- $location.path('boards/' + $scope.currentUser.defaultBoard);
- }
- };
- $scope.interval = $interval(checkDefaultBoard, 250);
- $scope.$on('$destroy', function () { $interval.cancel($scope.interval); });
-
- $scope.boards = [];
- $scope.boardsLoaded = false;
- $scope.boardNames = [];
- $scope.userNames = [];
- $scope.laneNames = [];
- $scope.categories = [];
- $scope.currentBoard = {
- loading: true,
- name: 'Kanban Board App'
- };
-
- var pendingResponse = false,
- updateCounter = 0;
-
- $scope.isActiveFilter = function(element) {
- var retVal = false;
- $scope.boards.forEach(function(board) {
- if (board.id === element.id) {
- retVal = (board.active === '1');
- }
- }, this);
-
- return retVal;
- };
-
- $scope.loadBoards = function() {
- // Don't update the boards if an update is pending.
- if (pendingResponse || updateCounter) {
- return;
- }
-
- pendingResponse = true;
- BoardService.getBoards()
- .success(function(data) {
- pendingResponse = false;
- $scope.updateBoards(data);
- });
- };
- $scope.loadBoards();
- $scope.boardInterval = $interval($scope.loadBoards, 10000);
- $scope.$on('$destroy', function () { $interval.cancel($scope.boardInterval); });
-
- $scope.updateBoards = function(data) {
- // Don't update the boards if a position update is pending.
- if (0 !== updateCounter) {
- return;
- }
- $scope.boards = data.data;
- $scope.boardsLoaded = true;
-
- var boardFound = false;
- if ($scope.boards) {
- $scope.boardNames = [];
- $scope.boards.forEach(function(board) {
- if (parseInt(board.active) === 1) {
- // Add each board's name to the list.
- $scope.boardNames.push({id: board.id, name: board.name});
- }
-
- // If the board is the current board, process and assign it.
- if (board.id == $scope.boardId) {
- board.sharedUser.unshift({ id: 0, username: 'Unassigned' });
- board.sharedUser.forEach(function(user) {
- $scope.userNames[user.id] = user.username;
- });
-
- board.ownLane.forEach(function(lane) {
- $scope.laneNames[lane.id] = lane.name;
- if (lane.ownItem) {
- lane.ownItem.forEach(function(item) {
- var date = new Date(item.due_date),
- diff = date - Date.now();
- if (diff < 0) {
- item.datePast = true;
- } else if (diff < (1000 * 60 * 60 * 24 * 3)) { // Three days
- item.dateNear = true;
- }
-
- item.position = parseInt(item.position);
- });
- }
- });
-
- if (board.ownCategory) {
- board.ownCategory.unshift({ id: 0, name: 'Uncategorized' });
- board.ownCategory.forEach(function(category) {
- $scope.categories[category.id] = category.name;
- });
- }
-
- $scope.currentBoard = board;
- $scope.boardNames.current = board.id;
- boardFound = true;
- }
- });
- }
-
- if (boardFound) {
- $scope.filterChanged(); // Make sure any filters are still applied.
- $scope.currentBoard.loading = false;
- if ($scope.currentBoard.active === '0') {
- $scope.currentBoard = {
- loading: true,
- name: 'Kanban Board App',
- error: true
- };
- }
- } else {
- $scope.currentBoard.error = true;
- }
- };
-
- $scope.toggleLane = function(lane) {
- lane.collapsed = !lane.collapsed;
- updateCounter++;
-
- BoardService.toggleLane(lane.id)
- .success(function(data) {
- updateCounter--;
- $scope.updateBoards(data);
- });
- };
-
- // This is not the Angular way.
- $scope.updateSortables = function() {
- var that = this.$parent;
- $('.itemContainer').sortable({
- connectWith: '.itemContainer',
- placeholder: 'draggable-placeholder',
- items: 'div:not(.addItem, .itemHeader, .description)',
- change: function(event, ui) {
- var parent = $(ui).parent(),
- addItem = parent.find('.addItem');
-
- addItem.detach();
- parent.append(addItem);
- },
- stop: function(event, ui) {
- var lanes = $.find('.boardColumn'),
- positionArray = [];
-
- $(lanes).each(function() {
- var laneId = $(this).attr('data-lane-id');
- $(this).find('.boardItem').each(function(index) {
- var itemId = $(this).attr('data-item-id');
- positionArray.push({
- item: itemId,
- lane: laneId,
- position: index
- });
- });
- });
- that.updatePositions(positionArray);
- }
- });
- };
-
- $scope.updatePositions = function(positionArray) {
- updateCounter++;
- BoardService.updateItemPositions(positionArray)
- .success(function(data) {
- updateCounter--;
- $scope.updateBoards(data);
- });
- };
-
- $scope.currentUser = {};
- $scope.userLoaded = false;
- $scope.updateCurrentUser = function() {
- UserService.currentUser()
- .success(function(data) {
- $scope.userLoaded = true;
- $scope.currentUser = data.data;
- });
- };
- $scope.updateCurrentUser();
-}]);
diff --git a/js/controllers/boardsItemForm.js b/js/controllers/boardsItemForm.js
deleted file mode 100644
index 8a5cc38..0000000
--- a/js/controllers/boardsItemForm.js
+++ /dev/null
@@ -1,132 +0,0 @@
-taskBoardControllers.controller('ItemFormBoardCtrl',
-['$scope', 'BoardService',
-function ($scope, BoardService) {
- var defaultColor = '#ffffe0';
-
- $scope.itemFormData = {
- setFocus: false,
- isSaving: false,
- isAdd: true,
- itemId: 0,
- title: '',
- titleError: false,
- description: '',
- assignee: 0,
- category: 0,
- lane: 0,
- color: defaultColor,
- dueDate: null,
- points: null,
- pointsError: false,
- reset: function(laneId) {
- $('.popover-dismiss').popover({html:true});
- this.setFocus = true;
- this.isSaving = false;
- this.isAdd = true;
- this.itemId = 0;
- this.title = '';
- this.titleError = false;
- this.description = '';
- this.assignee = 0;
- this.category = 0;
- this.lane = laneId || 0;
- this.color = defaultColor;
- this.spectrum(); // Reset the color plugin to default as well.
- this.dueDate = null;
- this.points = null;
- this.pointsError = false;
- var that = this;
- $('.itemModal').on('hidden.bs.modal', function (e) {
- that.reset();
- });
- },
- loadItem: function(item) {
- this.reset(item.lane_id);
- this.isAdd = false;
- this.itemId = item.id;
- this.title = item.title;
- this.description = item.description;
- this.assignee = item.assignee === "0" ? 0 : item.assignee;
- this.category = item.category === "0" ? 0 : item.category;
- this.color = item.color;
- this.spectrum(this.color);
- this.dueDate = item.due_date;
- this.points = parseInt(item.points);
- this.position = item.position;
- },
- // Uses jQuery to close the modal and reset colorpicker.
- cancel: function() {
- $('.itemModal').modal('hide');
- $('#spectrum').spectrum('hide');
- $('#spectrum').spectrum('enable');
- },
- // Uses jQuery to set the colorpicker.
- spectrum: function(color) {
- color = color || defaultColor;
- $('#spectrum').spectrum({
- color: color,
- allowEmpty: false,
- localStorageKey: 'taskboard.colorPalette',
- showPalette: true,
- palette: [ ['#fff', '#ececec', '#ffffe0', '#ffe0fa', '#bee7f4', '#c3f4b5', '#debee8', '#ffdea9', '#ffbaba'] ],
- showSelectionPalette: true,
- showButtons: false,
- showInput: true,
- preferredFormat: 'hex3',
- appendTo: '#addEdit'
- });
- },
- // Uses jQuery to set the datepicker.
- datePicker: function() {
- $('#datepicker').datepicker();
- }
- };
- $scope.$parent.itemFormData = $scope.itemFormData;
-
- $scope.submitItem = function (itemFormData) {
- itemFormData.isSaving = true;
- $('#spectrum').spectrum('disable');
-
- itemFormData.titleError = false;
- if (itemFormData.title === '') {
- $scope.alerts.showAlert({
- type:'error',
- text: 'Title is required to add a new item.'
- });
- itemFormData.isSaving = false;
- itemFormData.titleError = true;
- return;
- }
- itemFormData.pointsError = false;
- if (itemFormData.points === undefined) { // It is undefined if invalid
- $scope.alerts.showAlert({
- type:'error',
- text: 'Points must be greater than or equal to zero (or left empty).'
- });
- itemFormData.isSaving = false;
- itemFormData.pointsError = true;
- return;
- }
-
- if (itemFormData.isAdd) {
- BoardService.addItem(itemFormData, $scope.currentBoard.id)
- .success(function(data) {
- isSuccess(data);
- });
- } else {
- BoardService.updateItem(itemFormData)
- .success(function(data) {
- isSuccess(data);
- });
- }
- };
- $scope.$parent.submitItem = $scope.submitItem;
-
- var isSuccess = function(data) {
- $scope.alerts.showAlerts(data.alerts);
- if (data.alerts[0].type == 'success') {
- $scope.updateBoards(data);
- $scope.itemFormData.cancel();
- }
- };
-}]);
diff --git a/js/controllers/boardsItemView.js b/js/controllers/boardsItemView.js
deleted file mode 100644
index e01cd16..0000000
--- a/js/controllers/boardsItemView.js
+++ /dev/null
@@ -1,244 +0,0 @@
-taskBoardControllers.controller('ItemViewBoardCtrl',
-['$scope', '$window', 'BoardService',
-function ($scope, $window, BoardService) {
- $scope.viewItem = {};
- $scope.comment = {};
- $scope.toggle = {
- sidebar: false
- };
- $scope.fileReset = false;
-
- $scope.comments = {
- options: [
- {id: 0, text: 'Oldest First'},
- {id: 1, text: 'Newest First'}
- ],
- sorting: 0
- };
-
- $scope.markedComment = function(text) {
- if (text) {
- return $window.marked(text);
- } else {
- return "No text
";
- }
- };
-
- // Takes an array of timestamps and converts them to display dates.
- var convertDates = function(timestampArray) {
- if (undefined === timestampArray) {
- return;
- }
-
- var date = new Date();
- timestampArray.forEach(function(item) {
- date.setTime(item.timestamp * 1000);
- item.date = date.toLocaleString();
- });
- },
- updateItem = function(item) {
- $scope.viewItem = item;
- $scope.viewItem.laneName = $scope.laneNames[item.lane_id];
- convertDates($scope.viewItem.ownComment);
- convertDates($scope.viewItem.ownAttachment);
- convertDates($scope.viewItem.ownActivity);
- };
-
- $scope.openItem = function(item, openModal) {
- if (undefined === openModal) {
- openModal = true;
- }
- updateItem(item);
- $scope.viewItem.disabled = false;
-
- if (undefined === $scope.viewItem.ownComment) {
- $scope.viewItem.ownComment = [];
- }
- if (undefined === $scope.viewItem.ownAttachment) {
- $scope.viewItem.ownAttachment = [];
- }
-
- $scope.fileReset = true;
-
- if (openModal) {
- $('.itemViewModal textarea').css('height', 'auto');
- $('.itemViewModal').modal({ show: true, keyboard:false });
- }
- };
- $scope.$parent.openItem = $scope.openItem;
-
- $scope.editItem = function() {
- $scope.itemFormData.loadItem($scope.viewItem);
- $('.itemViewModal').modal('hide');
- $('.itemModal').modal('show');
- }
-
- $scope.deleteItem = function() {
- noty({
- text: 'Deleting an item cannot be undone.
Continue?',
- layout: 'center',
- type: 'information',
- modal: true,
- buttons: [
- {
- addClass: 'btn btn-default',
- text: 'Ok',
- onClick: function($noty) {
- $noty.close();
- $scope.viewItem.disabled = true;
-
- BoardService.removeItem($scope.viewItem.id)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- if (data.alerts[0].type == 'success') {
- $scope.updateBoards(data);
- $('.itemViewModal').modal('hide');
- }
- });
- }
- },
- {
- addClass: 'btn btn-info',
- text: 'Cancel',
- onClick: function($noty) {
- $noty.close();
- }
- }
- ]
- });
- };
- $scope.$parent.deleteItem = $scope.deleteItem;
-
- $scope.deleteComment = function(commentId) {
- noty({
- text: 'Deleting a comment cannot be undone.
Continue?',
- layout: 'center',
- type: 'information',
- modal: true,
- buttons: [
- {
- addClass: 'btn btn-default',
- text: 'Ok',
- onClick: function($noty) {
- $noty.close();
-
- BoardService.removeItemComment($scope.viewItem.id, commentId)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- if (data.alerts[0].type == 'success') {
- updateItem(data.data[0]);
- }
- $scope.loadBoards();
- });
- }
- },
- {
- addClass: 'btn btn-info',
- text: 'Cancel',
- onClick: function($noty) {
- $noty.close();
- }
- }
- ]
- });
- };
-
- $scope.attachmentDeleting = [];
- $scope.deleteAttachment = function(fileId) {
- noty({
- text: 'Deleting an attachment cannot be undone.
Continue?',
- layout: 'center',
- type: 'information',
- modal: true,
- buttons: [
- {
- addClass: 'btn btn-default',
- text: 'Ok',
- onClick: function($noty) {
- $noty.close();
- $scope.attachmentDeleting[fileId] = true;
-
- BoardService.removeItemAttachment($scope.viewItem.id, fileId)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- if (data.alerts[0].type == 'success') {
- updateItem(data.data[0]);
- }
- $scope.loadBoards();
- });
- }
- },
- {
- addClass: 'btn btn-info',
- text: 'Cancel',
- onClick: function($noty) {
- $noty.close();
- }
- }
- ]
- });
- };
-
- $scope.addItemComment = function(comment) {
- if (comment === "" || undefined === comment) {
- $scope.alerts.showAlert({ type: 'error', text: 'Comment cannot be empty.' });
- return;
- }
-
- $scope.viewItem.disabled = true;
- BoardService.addItemComment($scope.viewItem.id, comment)
- .success(function(data) {
- updateItem(data.data[0]);
- $scope.loadBoards();
- $scope.viewItem.disabled = false;
- });
- // Reset input
- $scope.comment.text = "";
- };
-
- $scope.beginEditComment = function(commentId, comment) {
- $scope.comment.isEdit = true;
- $scope.comment.editText = comment;
- $scope.comment.id = commentId;
- };
-
- $scope.editComment = function(commentId, comment) {
- $scope.comment.isEdit = false;
- if (comment === '' || undefined === comment) {
- $scope.alerts.showAlert({ type: 'error', text: 'Comment cannot be empty.' });
- return;
- }
-
- $scope.viewItem.disabled = true;
- BoardService.updateItemComment(commentId, comment)
- .success(function(data) {
- updateItem(data.data[0]);
- $scope.loadBoards();
- $scope.viewItem.disabled = false;
- });
- };
-
- $scope.addItemAttachment = function() {
- if ($scope.itemUpload === undefined || $scope.itemUpload.name === '') {
- $scope.alerts.showAlert({ type: 'error', text: 'Select a file before uploading.' });
- return;
- }
-
- $scope.viewItem.disabled = true;
- BoardService.addItemAttachment($scope.viewItem.id, $scope.itemUpload)
- .success(function(data) {
- updateItem(data.data[0]);
- $scope.loadBoards();
- $scope.viewItem.disabled = false;
- // Reset input
- $scope.fileReset = true;
- })
- .error(function(data) {
- $scope.viewItem.disabled = false;
- $scope.fileReset = true;
- console.log(data);
- $scope.alerts.showAlert({ type: 'error', text: 'There was an error with your attachment. ' +
- 'The file may be too large.' });
- });
- };
-}]);
diff --git a/js/controllers/files.js b/js/controllers/files.js
deleted file mode 100644
index 033768f..0000000
--- a/js/controllers/files.js
+++ /dev/null
@@ -1,27 +0,0 @@
-taskBoardControllers.controller('FilesCtrl',
-['$scope', '$routeParams', '$http', '$window',
- 'BoardService',
-function ($scope, $routeParams, $http, $window, BoardService) {
- $scope.file = {
- id: $routeParams.fileId,
- loading: true
- };
-
- $http.get('api/items/1/upload/' + $scope.file.id)
- .success(function(data) {
- $scope.file.loading = false;
- if (data.data) {
- $scope.file.data = data.data[0];
- var date = new Date();
- date.setTime($scope.file.data.timestamp * 1000);
- $scope.file.data.date = date.toLocaleString();
- $scope.file.data.filename = 'api/uploads/' + $scope.file.data.filename;
- } else {
- $scope.file.error = true;
- }
- })
- .error(function(data) {
- $scope.file.loading = false;
- $scope.file.error = true;
- });
-}]);
diff --git a/js/controllers/header.js b/js/controllers/header.js
deleted file mode 100644
index e01babd..0000000
--- a/js/controllers/header.js
+++ /dev/null
@@ -1,48 +0,0 @@
-taskBoardControllers.controller('HeaderCtrl',
-['$scope', '$window', '$location', 'UserService', 'AuthenticationService', 'AlertService',
-function ($scope, $window, $location, UserService, AuthenticationService, AlertService) {
- UserService.validateToken()
- .error($scope.logout);
-
- $scope.display = {
- username: '',
- smallText: ' - Settings'
- };
- $scope.$parent.display = $scope.display;
- $scope.$watch('currentUser', function(newValue, oldValue) {
- if (undefined !== newValue && undefined !== newValue.username) {
- $scope.display.username = '(' + newValue.username + ')';
- }
- });
-
- $scope.page = {
- boards: false,
- settings: true
- };
-
- if ($location.path().indexOf('boards') > -1) {
- $scope.page.boards = true;
- $scope.page.settings = false;
- $scope.$watch('currentBoard.name', function(newValue, oldValue) {
- $scope.display.smallText = ' - ' + newValue;
- });
- }
- if ($location.path().indexOf('files') > -1) {
- $scope.page.boards = false;
- $scope.page.settings = false;
- $scope.display.smallText = ' - File Viewer';
- }
-
- try {
- $.noty.closeAll(); // Clear any alerts on page load.
- } catch(e) {}
-
- $scope.logout = function() {
- UserService.logOut()
- .then(function(data) {
- AuthenticationService.reset();
- delete $window.localStorage.token;
- $location.path('/');
- });
- };
-}]);
diff --git a/js/controllers/login.js b/js/controllers/login.js
deleted file mode 100644
index 2f2510c..0000000
--- a/js/controllers/login.js
+++ /dev/null
@@ -1,38 +0,0 @@
-taskBoardControllers.controller('LoginCtrl',
-['$rootScope', '$scope', '$location', '$window', 'UserService', 'AuthenticationService', 'AlertService',
-function ($rootScope, $scope, $location, $window, UserService, AuthenticationService, AlertService) {
- $scope.formdata = {
- username: '',
- password: '',
- rememberme: false
- };
- $scope.isSaving = false;
-
- // Uses jQuery to handle clearing of any open modals.
- $scope.clear = function() {
- $('[name~=Modal]').modal('hide');
- $('.modal-backdrop').hide();
- };
-
- $scope.logIn = function (formdata) {
- $scope.errors = [];
- $scope.isSaving = true;
-
- UserService.logIn(formdata.username, formdata.password, formdata.rememberme)
- .success(function(data) {
- if (null !== data.alerts) {
- AlertService.showAlerts(data.alerts);
- }
- AuthenticationService.isAuthenticated = true;
- $window.localStorage.token = data.data;
- $location.path('/boards');
- }).error(function(data, status) {
- $scope.isSaving = false;
- $scope.errors.push(data.message);
- if (status === 503) {
- $scope.errors[0] = $scope.errors[0] + ' Ensure api directory is writable.';
- }
- });
- };
-}
-]);
diff --git a/js/controllers/settings.js b/js/controllers/settings.js
deleted file mode 100644
index 91f4cbf..0000000
--- a/js/controllers/settings.js
+++ /dev/null
@@ -1,99 +0,0 @@
-taskBoardControllers.controller('SettingsCtrl',
-['$scope', 'UserService', 'AlertService',
-function ($scope, UserService, AlertService) {
- $scope.alerts = AlertService;
-
- $scope.users = [];
- $scope.boards = [];
- $scope.boardNames = [];
-
- $scope.boardLookup = {};
- $scope.currentUser = {};
- $scope.slide = {
- open: false
- };
-
- $scope.loadingCurrentUser = true;
- $scope.loadingBoards = true;
- $scope.loadingUsers = true;
-
- $scope.loadCurrentUser = function() {
- UserService.currentUser()
- .success(function(data) {
- $scope.currentUser = data.data;
- loadOptionsData(data.data);
- $scope.loadingCurrentUser = false;
- });
- };
- $scope.loadCurrentUser();
-
- loadOptionsData = function (data) {
- $scope.currentUser.options.tasksOrder = parseInt(data.options.tasksOrder);
- $scope.currentUser.options.showAnimations = data.options.showAnimations;
- $scope.currentUser.options.showAssignee = data.options.showAssignee;
- };
-
- $scope.saveOptions = function() {
- UserService.saveOptions($scope.currentUser.options.tasksOrder,
- $scope.currentUser.options.showAnimations,
- $scope.currentUser.options.showAssignee)
- .success(function(data) {
- loadOptionsData({options: data.data});
- });
- };
-
- $scope.updateBoardsList = function(data) {
- if (undefined === data) {
- return;
- }
-
- $scope.loadingBoards = false;
- if (null === data) {
- $scope.boards = [];
- return;
- }
- $scope.boards = data;
-
- var boardNames = [];
- data.forEach(function(board) {
- boardNames.push({ 'id': board.id, 'name':board.name, 'active':board.active });
- });
- $scope.boardNames = boardNames;
-
- for (var i = 0, len = boardNames.length; i < len; i++) {
- $scope.boardLookup[boardNames[i].id] = boardNames[i].name;
- }
- $scope.updateActions();
- };
-
- $scope.updateUsers = function(data) {
- if (undefined === data || null === data) {
- return;
- }
-
- $scope.users = data;
- $scope.loadingUsers = false;
- $scope.updateActions();
- };
-
- $scope.actions = [];
- $scope.actionsLoading = true;
- $scope.updateActions = function() {
- if ('1' !== $scope.currentUser.isAdmin) {
- return;
- }
- UserService.actions()
- .success(function(data) {
- $scope.actions = data.data;
- if ($scope.actions) {
- var date = new Date();
- $scope.actions.forEach(function(action) {
- date.setTime(action.timestamp * 1000);
- action.date = date.toLocaleString();
- });
- }
- $scope.actionsLoading = false;
- });
- };
- $scope.updateActions();
-}]);
diff --git a/js/controllers/settingsAutoActions.js b/js/controllers/settingsAutoActions.js
deleted file mode 100644
index 39ffdff..0000000
--- a/js/controllers/settingsAutoActions.js
+++ /dev/null
@@ -1,319 +0,0 @@
-taskBoardControllers.controller('AutomaticActionsCtrl',
-['$scope', '$interval', 'BoardService',
-function ($scope, $interval, BoardService) {
- $scope.loadingActions = true;
- $scope.actions = [];
-
- $scope.secondarySelection = [];
- $scope.boardCategories = [{ id: 0, name: 'Uncategorized' }];
- $scope.userList = [{ id: 0, name: 'Unassigned', username: 'Unassigned' }];
-
- $scope.actionData = {
- isSaving: false,
- board: null,
- trigger: 0,
- triggerWord: '',
- secondary: null,
- action: 0,
- color: null,
- category: null,
- assignee: null
- };
- $scope.actionDeleting = [];
-
- $scope.actionTypes = [
- { id: 0, action: 'Set item color' },
- { id: 1, action: 'Set item category'},
- { id: 2, action: 'Set item assignee' },
- { id: 3, action: 'Clear item due date' }
- ];
-
- $scope.actionOptions = {
- triggers: [
- { id: 0, trigger: 'Item moves to column' },
- { id: 1, trigger: 'Item assigned to user' },
- { id: 2, trigger: 'Item set to category' }
- ]
- };
-
- $scope.updateTriggers = function() {
- var foundCategories = false;
- $scope.actionOptions.triggers.forEach(function(trigger) {
- if (trigger.id === 2) {
- foundCategories = true;
- }
- }, this);
-
- if (!foundCategories) {
- $scope.actionOptions.triggers.push({ id: 2, trigger: 'Item set to category' });
- }
-
- if ($scope.boardCategories.length === 1) {
- $scope.actionOptions.triggers.forEach(function(trigger, index) {
- if (trigger.id === 2) {
- $scope.actionOptions.triggers.splice(index, 1);
- }
- });
- $scope.actionTypes.forEach(function(type, index) {
- if (type.id === 1) {
- $scope.actionTypes.splice(index, 1);
- }
- });
- }
- };
-
- var getBoardData = function(boardId) {
- if (null === boardId || undefined === boardId)
- {
- return;
- }
-
- var boardData;
- $scope.boards.forEach(function(board) {
- if (board.id === boardId) {
- boardData = board;
- }
- });
-
- return boardData;
- },
-
- getCategories = function(boardData) {
- var categories = [{ id: '0', name: 'Uncategorized' }];
-
- if (boardData && boardData.ownCategory) {
- boardData.ownCategory.forEach(function(category) {
- categories.push(category);
- });
- }
- return categories;
- },
-
- getUsers = function(boardData) {
- var userList = [{ id: '0', name: 'Unassigned', username: 'Unassigned' }];
-
- if (boardData) {
- boardData.sharedUser.forEach(function(user) {
- userList.push({ id: user.id, name: user.username });
- });
- }
- return userList;
- },
-
- getSecondaryText = function(action) {
- var text = ': ',
- actionBoard = getBoardData(action.board_id),
- boardCategories = getCategories(actionBoard),
- userList = getUsers(actionBoard);
-
- switch(parseInt(action.trigger_id)) {
- case 0: // Lane
- actionBoard.ownLane.forEach(function(lane) {
- if (lane.id === action.secondary_id) {
- text += lane.name;
- }
- });
- break;
- case 1: // User
- userList.forEach(function(user) {
- if (user.id === action.secondary_id) {
- text += user.name;
- }
- });
- break;
- case 2: // Category
- boardCategories.forEach(function(category) {
- if (category.id === action.secondary_id) {
- text += category.name;
- }
- });
- break;
- }
- return text;
- },
-
- getActionText = function(action) {
- var text = '',
- actionBoard = getBoardData(action.board_id),
- boardCategories = getCategories(actionBoard),
- userList = getUsers(actionBoard);
-
- switch(parseInt(action.action_id)) {
- case 0: // Color
- text = ': ' + action.color;
- break;
- case 1: // Category
- boardCategories.forEach(function(category) {
- if (category.id === action.category_id) {
- text = ': ' + category.name;
- }
- });
- break;
- case 2: // Assignee
- userList.forEach(function(user) {
- if (user.id === action.assignee_id) {
- text = ': ' + user.name;
- }
- });
- break;
- }
- return text;
- },
-
- updateAutoActions = function(actions) {
- if (!actions) {
- $scope.actions = [];
- return;
- }
-
- var mappedActions = [];
- actions.forEach(function(action) {
- var actionTrigger, actionType;
- $scope.actionOptions.triggers.forEach(function(trigger) {
- if (trigger.id === parseInt(action.trigger_id)) {
- actionTrigger = trigger.trigger;
- }
- });
- $scope.actionTypes.forEach(function(type) {
- if (type.id === parseInt(action.action_id)) {
- actionType = type.action;
- }
- });
-
- mappedActions.push({
- id: action.id,
- board: $scope.boardLookup[action.board_id],
- trigger: actionTrigger + getSecondaryText(action),
- action: actionType + getActionText(action)
- });
- });
-
- $scope.actions = mappedActions;
- };
-
- $scope.loadActions = function() {
- BoardService.getAutoActions()
- .success(function(data) {
- updateAutoActions(data.data);
- $scope.loadingActions = false;
- });
- };
- $interval($scope.loadActions, 2000);
-
- // Wait until boards are loaded to load the actions.
- $scope.$watch('loadingBoards', function() {
- if (!$scope.loadingBoards) {
- $scope.loadActions();
- }
- });
-
- $scope.addAction = function() {
- if ($scope.actionData.secondary === null ||
- ($scope.actionData.action !== 3 &&
- ($scope.actionData.color === null && $scope.actionData.category === null &&
- $scope.actionData.assignee === null))) {
- $scope.alerts.showAlert({
- type: 'error',
- text: 'One or more required fields are not entered. Automatic Action not added.'
- });
- return;
- }
-
- $scope.actionData.isSaving = true;
- BoardService.addAutoAction($scope.actionData)
- .success(function(data) {
- $scope.actionData.isSaving = false;
- $scope.alerts.showAlerts(data.alerts);
- if (data.alerts[0].type == 'success') {
- updateAutoActions(data.data);
- }
- });
- };
-
- $scope.removeAction = function(actionId) {
- $scope.actionDeleting[actionId] = true;
-
- BoardService.removeAutoAction(actionId)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- updateAutoActions(data.data);
- });
- };
-
- $scope.updateSecondary = function() {
- $scope.secondarySelection = [];
- $scope.actionData.secondary = null;
- $scope.actionData.action = 0;
-
- var boardData = getBoardData($scope.actionData.board);
- $scope.boardCategories = getCategories(boardData);
- $scope.updateTriggers();
- $scope.userList = getUsers(boardData);
-
- if (boardData) {
- switch($scope.actionData.trigger) {
- case 0:
- $scope.secondarySelection = boardData.ownLane;
- break;
- case 1:
- $scope.secondarySelection = $scope.userList;
- break;
- case 2:
- $scope.secondarySelection = $scope.boardCategories;
- break;
- }
- }
- };
-
- $scope.getTriggerWord = function() {
- if ($scope.actionData.trigger !== null) {
- var word = $scope.actionOptions.triggers[$scope.actionData.trigger].trigger.split(" ").pop();
- $scope.actionData.triggerWord = word.charAt(0).toUpperCase() + word.slice(1);
- }
- $scope.updateSecondary();
- };
- $scope.getTriggerWord();
-
- $scope.resetActionSecondary = function() {
- $scope.actionData.color = null;
- $scope.actionData.category = null;
- $scope.actionData.assignee = null;
- };
-
- var defaultColor = '#ffffe0';
- $scope.spectrum = function(color) {
- color = color || defaultColor;
- $('#spectrum').spectrum({
- color: color,
- allowEmpty: false,
- localStorageKey: 'taskboard.colorPalette',
- showPalette: true,
- palette: [ ['#fff', '#ececec', '#ffffe0', '#ffe0fa', '#bee7f4', '#c3f4b5', '#debee8', '#ffdea9', '#ffbaba'] ],
- showSelectionPalette: true,
- showButtons: false,
- showInput: true,
- preferredFormat: 'hex3',
- disabled: $scope.actionData.board === null
- });
- };
- $scope.updateColorpicker = function() {
- if (null !== $scope.actionData.board) {
- $('#spectrum').spectrum('enable');
- $scope.actionData.color = $('#spectrum').spectrum('option', 'color');
- $scope.updateSecondary();
- return;
- }
- $('#spectrum').spectrum('disable');
- $scope.actionData.color = null;
- };
-
- // Check every 500ms to see if a board has been chosen.
- var updateIfBoardChosen = function() {
- if ($scope.actionData.board !== null) {
- $interval.cancel($scope.interval);
- $scope.getTriggerWord();
- }
- };
- $scope.interval = $interval(updateIfBoardChosen, 500);
- $scope.$on('$destroy', function () { $interval.cancel($scope.interval); });
-}]);
diff --git a/js/controllers/settingsBoard.js b/js/controllers/settingsBoard.js
deleted file mode 100644
index 10f051b..0000000
--- a/js/controllers/settingsBoard.js
+++ /dev/null
@@ -1,134 +0,0 @@
-taskBoardControllers.controller('BoardSettingsCtrl',
-['$scope', '$interval', 'BoardService',
-function ($scope, $interval, BoardService) {
- var pendingResponse = false,
- retryCount = 3,
- loadBoards = function() {
- if (pendingResponse) {
- return;
- }
-
- pendingResponse = true;
- BoardService.getBoards()
- .success(function(data) {
- $scope.updateBoardsList(data.data);
- pendingResponse = false;
- retryCount = 3;
- }).error(function(data) {
- if (retryCount--) {
- pendingResponse = false;
- return;
- }
-
- $interval.cancel($scope.interval);
- $scope.$parent.loadingBoards = false;
- });
- };
-
- loadBoards();
- $scope.interval = $interval(loadBoards, 5000);
- $scope.$on('$destroy', function () { $interval.cancel($scope.interval); });
-
- $scope.userOptions = {
- tasksAt: [
- { id: 0, text: 'bottom of column'},
- { id: 1, text: 'top of column'}
- ],
- taskOrder: 0,
- showAnimations: true,
- showAssignee: true
- };
-
- $scope.boardSort = {
- options: [
- { sort: 'id', name: 'Creation Date' },
- { sort: 'name', name: 'Board Name' }
- ],
- sort: 'name'
- };
-
- $scope.boardFilter = {
- options: [
- { filter: 'all', name: 'All Boards' },
- { filter: 'active', name: 'Active' },
- { filter: 'inactive', name: 'Inactive' }
- ],
- filter: 'all',
- userFilter: null
- };
-
- $scope.boardsFilter = function(element) {
- switch ($scope.boardFilter.filter) {
- case 'all':
- return true;
- case 'active':
- return element.active === '1';
- case 'inactive':
- return element.active === '0';
- }
- };
-
- $scope.boardsUserFilter = function(element) {
- if (null === $scope.boardFilter.userFilter) {
- return true;
- }
-
- var retVal = false;
-
- element.sharedUser.forEach(function(user) {
- console.log(user.id === $scope.boardFilter.userFilter);
- if (user.id === $scope.boardFilter.userFilter) {
- retVal = true;
- }
- });
-
- return retVal;
- };
-
- $scope.toggleActiveState = function(boardId) {
- BoardService.toggleActiveState(boardId)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.boards = data.data;
- });
- };
-
- $scope.isDeleting = [];
- $scope.removeBoard = function(boardId) {
- noty({
- text: 'Deleting a board cannot be undone.
Continue?',
- layout: 'center',
- type: 'information',
- modal: true,
- buttons: [
- {
- addClass: 'btn btn-default',
- text: 'Ok',
- onClick: function($noty) {
- $noty.close();
-
- $scope.boards.forEach(function(board) {
- if (board.id === boardId) {
- $scope.isDeleting[boardId] = true;
- }
- });
-
- BoardService.removeBoard(boardId)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.boards = data.data;
- $scope.updateUsers(data.users);
- });
- }
- },
- {
- addClass: 'btn btn-info',
- text: 'Cancel',
- onClick: function($noty) {
- $noty.close();
- }
- }
- ]
- });
- };
-}]);
diff --git a/js/controllers/settingsBoardForm.js b/js/controllers/settingsBoardForm.js
deleted file mode 100644
index b7fe872..0000000
--- a/js/controllers/settingsBoardForm.js
+++ /dev/null
@@ -1,218 +0,0 @@
-taskBoardControllers.controller('BoardFormSettingsCtrl',
-['$scope', 'BoardService',
-function ($scope, BoardService) {
- $scope.boardFormData = {
- setFocus: false,
- boardId: 0,
- isAdd: true,
- name: '',
- lanes: [],
- laneName: '',
- categories: [],
- categoryName: '',
- users: [],
- nameError: false,
- lanesError: false,
- categoriesError: false,
- isSaving: false,
- updateLanesSorting: function() {
- var that = this;
- $('.lanes').sortable({
- placeholder: 'lane-placeholder',
- stop: function(event, ui) {
- that.lanes.length = 0;
- $(ui.item).parent().children().each(function(index) {
- that.lanes.push({
- id: $(this).find('.hidden').text(),
- name: $(this).find('.item-text').text(),
- position: index
- });
- });
- $scope.$apply();
- }
- });
- },
- setBoard: function(board) {
- this.reset();
-
- this.isAdd = false;
- this.boardId = board.id;
- this.name = board.name;
- var that = this;
- if (undefined !== board.ownLane) {
- board.ownLane.forEach(function(lane) {
- that.lanes.push({
- id: lane.id,
- name: lane.name,
- position: lane.position
- });
- });
- }
- if (undefined !== board.ownCategory) {
- board.ownCategory.forEach(function(cat) {
- that.categories.push({
- id: cat.id,
- name: cat.name
- });
- });
- }
- if (undefined !== board.sharedUser) {
- board.sharedUser.forEach(function(user) {
- that.users[user.id] = true;
- });
- }
-
- this.updateLanesSorting();
- },
- addLane: function() {
- this.lanesError = false;
- if (this.laneName === '') {
- this.setAlert(false, true, false, 'Column name cannot be empty.');
- return;
- }
-
- var that = this;
- this.lanes.forEach(function(lane) {
- if (that.laneName == lane.name) {
- that.setAlert(false, true, false, 'That column name has already been added.');
- that.lanesError = true;
- }
- });
-
- // Add the new lane (if no error) and reset the input.
- if (!this.lanesError) {
- this.lanes.push({
- id: 0,
- name: this.laneName,
- position: this.lanes.length
- });
- }
- this.laneName = '';
- this.updateLanesSorting();
- },
- removeLane: function(lane) {
- if (this.isSaving) { return; }
- this.lanes.splice(this.lanes.indexOf(lane), 1);
-
- var pos = 0;
- this.lanes.forEach(function(lane) {
- lane.position = pos;
- pos++;
- });
- },
- addCategory: function() {
- this.categoriesError = false;
- if (this.categoryName === '') {
- this.setAlert(false, false, true, 'Category name cannot be empty.');
- return;
- }
-
- var that = this;
- this.categories.forEach(function(category) {
- if (that.categoryName == category) {
- this.setAlert(false, false, true, 'That category name has already been added.');
- }
- });
-
- // Add the new category (if no error) and reset the input.
- if (!this.categoriesError) {
- this.categories.push({
- id: 0,
- name: this.categoryName
- });
- }
- this.categoryName = '';
- },
- removeCategory: function(category) {
- if (this.isSaving) { return; }
- this.categories.splice(this.categories.indexOf(category), 1);
- },
- setForSaving: function() {
- this.nameError = false;
- this.lanesError = false;
- this.categoriesError = false;
- this.isSaving = true;
- },
- setAlert: function(name, lane, cat, message) {
- this.nameError = name;
- this.lanesError = lane;
- this.categoriesError = cat;
- this.isSaving = false;
- $scope.alerts.showAlert({ 'type': 'error', 'text': message });
- },
- reset: function() {
- this.setFocus = true;
- this.boardId = 0;
- this.isAdd = true;
- this.name = '';
- this.lanes = [];
- this.laneName = '';
- this.categories = [];
- this.categoryName = '';
- this.users = [];
- this.nameError = false;
- this.lanesError = false;
- this.categoriesError = false;
- this.isSaving = false;
- },
- // Uses jQuery to close modal and reset form data.
- cancel: function() {
- $('.boardModal').modal('hide');
- var that = this;
- $('.boardModal').on('hidden.bs.modal', function (e) {
- that.reset();
- });
- }
- };
- $scope.$parent.boardFormData = $scope.boardFormData;
-
- $scope.addBoard = function(boardFormData) {
- boardFormData.setForSaving();
- if (!checkFormInputs(boardFormData)) {
- return;
- }
-
- BoardService.addBoard(boardFormData)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateBoardsList(data.data);
- boardFormData.reset();
-
- if (data.alerts[0].type == 'success') {
- $('.boardModal').modal('hide');
- }
- });
- };
-
- $scope.editBoard = function(boardFormData) {
- boardFormData.setForSaving();
- if (!checkFormInputs(boardFormData)) {
- return;
- }
-
- BoardService.editBoard(boardFormData)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateBoardsList(data.data);
- boardFormData.reset();
-
- if (data.alerts[0].type == 'success') {
- $('.boardModal').modal('hide');
- }
- });
- };
-
- var checkFormInputs = function(boardFormData) {
- if ('' === boardFormData.name) {
- boardFormData.setAlert(true, false, false, 'Board name cannot be empty.');
- return false;
- }
-
- if (0 === boardFormData.lanes.length) {
- boardFormData.setAlert(false, true, false, 'At least one lane is required.');
- return false;
- }
-
- return true;
- };
-}]);
diff --git a/js/controllers/settingsUser.js b/js/controllers/settingsUser.js
deleted file mode 100644
index 0a37373..0000000
--- a/js/controllers/settingsUser.js
+++ /dev/null
@@ -1,194 +0,0 @@
-taskBoardControllers.controller('UserSettingsCtrl',
-['$scope', '$interval', 'UserService',
-function ($scope, $interval, UserService) {
- var pendingResponse = false,
- retryCount = 3,
- loadUsers = function() {
- if (pendingResponse) {
- return;
- }
-
- pendingResponse = true;
- UserService.getUsers()
- .success(function(data) {
- $scope.updateUsers(data.data);
- pendingResponse = false;
- retryCount = 3;
- })
- .error(function() {
- if (retryCount--) {
- pendingResponse = false;
- return;
- }
-
- $interval.cancel($scope.interval);
- $scope.$parent.loadingUsers = false;
- });
- };
-
- loadUsers();
- $scope.interval = $interval(loadUsers, 5000);
- $scope.$on('$destroy', function () { $interval.cancel($scope.interval); });
-
- $scope.passwordFormData = {
- currentPass: '',
- newPass: '',
- verifyPass: '',
- newPassError: false,
- currentPassError: false,
- isSaving: false,
- setForSaving: function() {
- this.newPassError = false;
- this.currentPassError = false;
- this.isSaving = true;
- },
- setAlert: function(newError, oldError, message) {
- this.newPassError = newError;
- this.currentPassError = oldError;
- this.isSaving = false;
- $scope.alerts.showAlert({ 'type': 'error', 'text': message });
- },
- reset: function() {
- this.currentPass = '';
- this.newPass = '';
- this.verifyPass = '';
- this.newPassError = false;
- this.currentPassError = false;
- this.isSaving = false;
- }
- };
- $scope.changePassword = function(passwordFormData) {
- passwordFormData.setForSaving();
-
- if (passwordFormData.currentPass === '') {
- passwordFormData.setAlert(false, true, 'Current password cannot be blank.');
- } else if (passwordFormData.newPass === '' || passwordFormData.verifyPass === '') {
- passwordFormData.setAlert(true, false, 'New password cannot be blank.');
- } else {
- if(passwordFormData.newPass == passwordFormData.verifyPass) {
- UserService.changePassword(passwordFormData.currentPass, passwordFormData.newPass)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- passwordFormData.isSaving = false;
- passwordFormData.currentPass = '';
- if (data.alerts[0].text == "Password changed.") {
- passwordFormData.reset();
- } else {
- passwordFormData.currentPassError = true;
- }
- });
- } else {
- passwordFormData.setAlert(true, false, 'New passwords do not match.');
- }
- }
- };
-
- $scope.usernameFormData = {
- newUsername: '',
- usernameError: false,
- isSaving: false,
- setAlert: function(message) {
- this.isSaving = false;
- this.usernameError = true;
- $scope.alerts.showAlert({ 'type': 'error', 'text': message });
- },
- reset: function() {
- this.newUsername = '';
- this.usernameError = false;
- this.isSaving = false;
- }
- };
- $scope.changeUsername = function(newUsernameFormData) {
- $scope.usernameFormData.isSaving = true;
-
- if (newUsernameFormData.newUsername === '') {
- newUsernameFormData.setAlert('Username cannot be blank.');
- newUsernameFormData.isSaving = false;
- } else {
- UserService.changeUsername(newUsernameFormData.newUsername)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateUsers(data.data);
- $scope.loadCurrentUser();
-
- newUsernameFormData.isSaving = false;
- newUsernameFormData.newUsername = '';
- });
- }
- };
-
- $scope.emailFormData = {
- newEmail: '',
- emailError: false,
- isSaving: false,
- setAlert: function(message) {
- this.isSaving = false;
- this.emailError = true;
- $scope.alerts.showAlert({ 'type': 'error', 'text': message });
- },
- reset: function() {
- this.newEmail = '';
- this.emailError = false;
- this.isSaving = false;
- }
- };
- $scope.changeEmail = function(newEmailFormData) {
- $scope.emailFormData.isSaving = true;
-
- UserService.changeEmail(newEmailFormData.newEmail)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateUsers(data.data);
- $scope.loadCurrentUser();
-
- newEmailFormData.isSaving = false;
- newEmailFormData.newUsername = '';
- });
- };
-
- $scope.updatingDefaultBoard = false;
- $scope.setDefaultBoard = function() {
- $scope.updatingDefaultBoard = true;
-
- UserService.changeDefaultBoard($scope.currentUser.defaultBoard)
- .success(function(data) {
- $scope.updatingDefaultBoard = false;
- $scope.updateUsers(data.data);
- $scope.alerts.showAlert({ 'type': 'success', 'text': 'Default board changed.' });
- });
- };
-
- $scope.isDeleting = [];
- $scope.removeUser = function(userId) {
- noty({
- text: 'Deleting a user cannot be undone.
Continue?',
- layout: 'center',
- type: 'information',
- modal: true,
- buttons: [
- {
- addClass: 'btn btn-default',
- text: 'Ok',
- onClick: function($noty) {
- $noty.close();
- $scope.isDeleting[userId] = true;
-
- UserService.removeUser(userId)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateUsers(data.data);
- $scope.updateBoardsList(data.boards);
- });
- }
- },
- {
- addClass: 'btn btn-info',
- text: 'Cancel',
- onClick: function($noty) {
- $noty.close();
- }
- }
- ]
- });
- };
-}]);
diff --git a/js/controllers/settingsUserForm.js b/js/controllers/settingsUserForm.js
deleted file mode 100644
index 7599b2e..0000000
--- a/js/controllers/settingsUserForm.js
+++ /dev/null
@@ -1,118 +0,0 @@
-taskBoardControllers.controller('UserFormSettingsCtrl',
-['$scope', 'UserService',
-function ($scope, UserService) {
- $scope.userFormData = {
- setFocus: false,
- userId: 0,
- isAdd: true,
- username: '',
- password: '',
- email: '',
- verifyPass: '',
- defaultBoard: null,
- isAdmin: false,
- passError: false,
- usernameError: false,
- emailError: false,
- isSaving: false,
- setUser: function(user) {
- this.reset();
-
- this.isAdd = false;
- this.userId = user.id;
- this.username = user.username;
- this.email = user.email;
- this.defaultBoard = user.default_board;
- this.isAdmin = user.is_admin == '1';
- },
- reset: function() {
- $('.popover-dismiss').popover();
- this.setFocus = true;
- this.userId = 0;
- this.isAdd = true;
- this.username = '';
- this.password = '';
- this.email = '';
- this.verifyPass = '';
- this.defaultBoard = null;
- this.isAdmin = false;
- this.passError = false;
- this.usernameError = false;
- this.isSaving = false;
- },
- cancel: function() {
- $('.userModal').modal('hide');
- var that = this;
- $('.userModal').on('hidden.bs.modal', function (e) {
- that.reset();
- });
- },
- setForSaving: function() {
- this.isSaving = true;
- this.usernameError = false;
- this.passError = false;
- },
- setAlert: function(user, pass, message) {
- this.isSaving = false;
- this.usernameError = user;
- this.passError = pass;
- $scope.alerts.showAlert({ 'type': 'error', 'text': message });
- }
- };
- $scope.$parent.userFormData = $scope.userFormData;
-
- $scope.editUser = function(userFormData) {
- userFormData.setForSaving();
-
- if (userFormData.username === '') {
- userFormData.setAlert(true, false, 'Username cannot be blank.');
- } else {
- userFormData.isSaving = true;
-
- if(userFormData.password == userFormData.verifyPass) {
- UserService.editUser(userFormData)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateUsers(data.data);
- $scope.updateBoardsList(data.boards);
-
- if (data.alerts[0].type == 'success') {
- $('.userModal').modal('hide');
- userFormData.password = '';
- userFormData.verifyPass = '';
- }
- });
- } else {
- userFormData.setAlert(false, true, 'Passwords do not match.');
- }
- }
- };
-
- $scope.addUser = function(userFormData) {
- userFormData.setForSaving();
-
- if (userFormData.username === '') {
- userFormData.setAlert(true, false, 'Username cannot be blank.');
- } else if (userFormData.password === '' || userFormData.verifyPass === '') {
- userFormData.setAlert(false, true, 'Password cannot be blank.');
- } else {
- userFormData.isSaving = true;
-
- if(userFormData.password == userFormData.verifyPass) {
- UserService.addUser(userFormData)
- .success(function(data) {
- $scope.alerts.showAlerts(data.alerts);
- $scope.updateUsers(data.data);
- $scope.updateBoardsList(data.boards);
- userFormData.reset();
-
- if (data.alerts[0].type == 'success') {
- $('.userModal').modal('hide');
- }
- });
- } else {
- userFormData.setAlert(false, true, 'Passwords do not match.');
- }
- }
- };
-}]);
diff --git a/js/directives/clickToEdit.js b/js/directives/clickToEdit.js
deleted file mode 100644
index 2d5c840..0000000
--- a/js/directives/clickToEdit.js
+++ /dev/null
@@ -1,36 +0,0 @@
-taskBoardDirectives.directive('clickToEdit', function() {
- return {
- restrict: 'A',
- replace: true,
- templateUrl: 'partials/clickToEdit.html',
- scope: {
- value: '=clickToEdit'
- },
- controller: ['$scope', function($scope) {
- $scope.view = {
- editableValue: $scope.value,
- editorEnabled: false
- };
-
- $scope.enableEditor = function() {
- $scope.view.editableValue = $scope.value;
- $scope.view.editorEnabled = true;
- };
-
- $scope.save = function() {
- $scope.value = $scope.view.editableValue;
- $scope.view.editorEnabled = false;
- };
-
- $scope.checkKeypress = function(e) {
- if (e.which === 13) { // Enter key
- $scope.save();
- e.preventDefault();
- } else if (e.which === 27) { // Escape key
- $scope.view.editorEnabled = false;
- e.preventDefault();
- }
- };
- }]
- };
-});
diff --git a/js/directives/fileUpload.js b/js/directives/fileUpload.js
deleted file mode 100644
index 0e1c619..0000000
--- a/js/directives/fileUpload.js
+++ /dev/null
@@ -1,24 +0,0 @@
-taskBoardDirectives.directive('fileUpload', ['$parse', function($parse) {
- return {
- restrict: 'A',
- link: function(scope, element, attrs) {
- var fileModel = $parse(attrs.fileUpload),
- resetModel = $parse(attrs.resetFlag);
-
- // When the resetFlag attribute value changes, reset the input.
- scope.$watch(resetModel, function(val) {
- if (val) {
- element[0].value = '';
- resetModel.assign(scope, false);
- }
- });
-
- // Bind the file to the model on change event.
- element.bind('change', function() {
- scope.$apply(function() {
- fileModel.assign(scope, element[0].files[0]);
- });
- });
- }
- };
-}]);
diff --git a/js/directives/focus.js b/js/directives/focus.js
deleted file mode 100644
index 63bf69b..0000000
--- a/js/directives/focus.js
+++ /dev/null
@@ -1,14 +0,0 @@
-taskBoardDirectives.directive('focus', ['$timeout', function($timeout) {
- return {
- link: function(scope, elem, attrs) {
- scope.$watch(attrs.focus, function(val) {
- if (angular.isDefined(val) && val) {
- $timeout(function() {
- elem[0].focus();
- scope.$eval(attrs.focus + ' = false');
- }, 500);
- }
- }, true);
- }
- };
-}]);
diff --git a/js/directives/includeReplace.js b/js/directives/includeReplace.js
deleted file mode 100644
index 60c85e6..0000000
--- a/js/directives/includeReplace.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Simple directive to include a partial and completely replace the element included from.
-taskBoardDirectives.directive('includeReplace', function () {
- return {
- restrict: 'A',
- replace: true,
- templateUrl: function(element, attributes) {
- return attributes.includeReplace;
- }
- };
-});
diff --git a/js/directives/onLoadCallback.js b/js/directives/onLoadCallback.js
deleted file mode 100644
index b1bf0cf..0000000
--- a/js/directives/onLoadCallback.js
+++ /dev/null
@@ -1,14 +0,0 @@
-// Used for loading third-party JS (like jQueryUI sortable) after
-// all elements have been loaded into the DOM.
-taskBoardDirectives.directive('onLoadCallback', function() {
- return {
- restrict: 'A',
- terminal: true,
- scope: {
- callback: '=onLoadCallback'
- },
- link: function(scope, element, attrs) {
- scope.callback();
- }
- };
-});
diff --git a/js/services/alerts.js b/js/services/alerts.js
deleted file mode 100644
index 68d49fc..0000000
--- a/js/services/alerts.js
+++ /dev/null
@@ -1,29 +0,0 @@
-taskBoardServices.factory('AlertService',[
-function() {
- var showNotyAlert = function(alert) {
- // Assumes noty.js is loaded
- noty({
- layout: 'bottom',
- type: alert.type,
- text: alert.text,
- timeout: 5000
- });
- };
-
- return {
- showAlert: function(alert) {
- if (undefined === alert || null === alert) {
- return;
- }
- showNotyAlert(alert);
- },
- showAlerts: function(alerts) {
- if (undefined === alerts || null === alerts || !alerts.length) {
- return;
- }
- alerts.forEach(function(alert) {
- showNotyAlert(alert);
- });
- }
- };
-}]);
diff --git a/js/services/auth.js b/js/services/auth.js
deleted file mode 100644
index ef3023d..0000000
--- a/js/services/auth.js
+++ /dev/null
@@ -1,12 +0,0 @@
-taskBoardServices.factory('AuthenticationService', [
-function() {
- return {
- isAuthenticated: false,
- attemptedRoute: null,
-
- reset: function() {
- this.isAuthenticated = false;
- this.attemptedRoute = null;
- }
- };
-}]);
diff --git a/js/services/board.js b/js/services/board.js
deleted file mode 100644
index d66c651..0000000
--- a/js/services/board.js
+++ /dev/null
@@ -1,139 +0,0 @@
-taskBoardServices.factory('BoardService',
-['$http',
-function($http) {
- return {
- getBoards: function() {
- return $http.get('api/boards');
- },
-
- removeBoard: function(boardId) {
- return $http.post('api/boards/remove', {
- boardId: boardId
- });
- },
-
- addBoard: function(boardData) {
- return $http.post('api/boards', {
- name: boardData.name,
- lanes: boardData.lanes,
- categories: boardData.categories,
- users: boardData.users
- });
- },
-
- editBoard: function(boardData) {
- return $http.post('api/boards/update', {
- boardId: boardData.boardId,
- name: boardData.name,
- lanes: boardData.lanes,
- categories: boardData.categories,
- users: boardData.users
- });
- },
-
- toggleLane: function(laneId) {
- return $http.post('api/lanes/' + laneId + '/toggle');
- },
-
- toggleActiveState: function(boardId) {
- return $http.post('api/boards/' + boardId + '/toggleActive');
- },
-
- getAutoActions: function() {
- return $http.get('api/autoactions');
- },
-
- addAutoAction: function(action) {
- return $http.post('api/autoactions', {
- boardId: action.board,
- triggerId: action.trigger,
- secondaryId: action.secondary,
- actionId: action.action,
- color: action.color,
- categoryId: action.category,
- assigneeId: action.assignee
- });
- },
-
- removeAutoAction: function(actionId) {
- return $http.post('api/autoactions/remove', {
- actionId: actionId
- });
- },
-
- addItem: function(itemData, boardId) {
- return $http.post('api/boards/' + boardId + '/items', {
- title: itemData.title,
- description: itemData.description,
- assignee: itemData.assignee,
- category: itemData.category,
- color: itemData.color,
- dueDate: itemData.dueDate,
- points: itemData.points,
- lane: itemData.lane
- });
- },
-
- updateItem: function(itemData) {
- return $http.post('api/items/' + itemData.itemId, {
- title: itemData.title,
- description: itemData.description,
- assignee: itemData.assignee,
- category: itemData.category,
- color: itemData.color,
- dueDate: itemData.dueDate,
- points: itemData.points,
- lane: itemData.lane,
- position: itemData.position
- });
- },
-
- updateItemPositions: function(positionArray) {
- return $http.post('api/items/positions', {
- positions: positionArray
- });
- },
-
- removeItem: function(itemId) {
- return $http.post('api/items/remove', {
- itemId: itemId
- });
- },
-
- addItemComment: function(itemId, comment) {
- return $http.post('api/items/' + itemId + '/comment', {
- text: comment
- });
- },
-
- updateItemComment: function(commentId, comment) {
- return $http.post('api/comments/' + commentId, {
- text: comment
- });
- },
-
- removeItemComment: function(itemId, commentId) {
- return $http.post('api/items/' + itemId + '/comment/remove', {
- id: commentId
- });
- },
-
- addItemAttachment: function(itemId, file) {
- var fd = new FormData();
- fd.append('file', file);
-
- return $http.post('api/items/' + itemId + '/upload', fd, {
- // Just pass the data, don't serialize.
- transformRequest: angular.identity,
- // Let browser handle Content-Type.
- headers: { 'Content-Type': undefined }
- });
- },
-
- removeItemAttachment: function(itemId, fileId) {
- return $http.post('api/items/' + itemId + '/upload/remove', {
- fileId: fileId
- });
- }
- };
-}]);
diff --git a/js/services/token.js b/js/services/token.js
deleted file mode 100644
index 32fa243..0000000
--- a/js/services/token.js
+++ /dev/null
@@ -1,35 +0,0 @@
-taskBoardServices.factory('TokenInterceptor',
-['$q', '$window', '$location', 'AuthenticationService',
- function ($q, $window, $location, AuthenticationService) {
- return {
- request: function(config) {
- config.headers = config.headers || {};
- if ($window.localStorage.token) {
- config.headers.Authorization = $window.localStorage.token;
- }
- return config;
- },
-
- requestError: function(rejection) {
- return $q.reject(rejection);
- },
-
- response: function(response) {
- if (response !== null && response.status === 200 &&
- $window.localStorage.token && !AuthenticationService.isAuthenticated) {
- AuthenticationService.isAuthenticated = true;
- }
- return response || $q.when(response);
- },
-
- responseError: function(rejection) {
- if (rejection !== null && rejection.status === 401 &&
- ($window.localStorage.token || AuthenticationService.isAuthenticated)) {
- delete $window.localStorage.token;
- AuthenticationService.isAuthenticated = false;
- $location.path('/');
- }
- return $q.reject(rejection);
- }
- };
- }]);
diff --git a/js/services/user.js b/js/services/user.js
deleted file mode 100644
index d0f6461..0000000
--- a/js/services/user.js
+++ /dev/null
@@ -1,95 +0,0 @@
-taskBoardServices.factory('UserService',
-['$http',
-function($http) {
- return {
- currentUser: function() {
- return $http.get('api/users/current');
- },
-
- saveOptions: function(tasksOrder, showAnimations, showAssignee) {
- return $http.post('api/users/current/options', {
- tasksOrder: tasksOrder,
- showAnimations: showAnimations,
- showAssignee: showAssignee
- });
- },
-
- logIn: function(username, password, rememberme) {
- return $http.post('api/login', {
- username: username,
- password: password,
- rememberme: rememberme
- });
- },
-
- logOut: function() {
- return $http.get('api/logout');
- },
-
- validateToken: function() {
- return $http.get('api/authenticate');
- },
-
- changePassword: function(currentPassword, newPassword) {
- return $http.post('api/updatepassword', {
- currentPass: currentPassword,
- newPass: newPassword
- });
- },
-
- changeUsername: function(newUsername) {
- return $http.post('api/updateusername', {
- newUsername: newUsername
- });
- },
-
- changeEmail: function(newEmail) {
- return $http.post('api/updateemail', {
- newEmail: newEmail
- });
- },
-
- changeDefaultBoard: function(newDefaultBoard) {
- return $http.post('api/updateboard', {
- defaultBoard: newDefaultBoard
- });
- },
-
- actions: function() {
- return $http.get('api/actions');
- },
-
- getUsers: function() {
- return $http.get('api/users');
- },
-
- addUser: function(formData) {
- return $http.post('api/users', {
- username: formData.username,
- password: formData.password,
- email: formData.email,
- defaultBoard: formData.defaultBoard,
- boardAccess: formData.boardAccess,
- isAdmin: formData.isAdmin
- });
- },
-
- editUser: function(formData) {
- return $http.post('api/users/update', {
- userId: formData.userId,
- newUsername: formData.username,
- password: formData.password,
- email: formData.email,
- defaultBoard: formData.defaultBoard,
- boardAccess: formData.boardAccess,
- isAdmin: formData.isAdmin
- });
- },
-
- removeUser: function(userId) {
- return $http.post('api/users/remove', {
- userId: userId
- });
- }
- };
-}]);
diff --git a/lib/angular-route.js b/lib/angular-route.js
deleted file mode 100644
index 68150e7..0000000
--- a/lib/angular-route.js
+++ /dev/null
@@ -1,989 +0,0 @@
-/**
- * @license AngularJS v1.3.15
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, angular, undefined) {'use strict';
-
-/**
- * @ngdoc module
- * @name ngRoute
- * @description
- *
- * # ngRoute
- *
- * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- *
- *
- */
- /* global -ngRouteModule */
-var ngRouteModule = angular.module('ngRoute', ['ng']).
- provider('$route', $RouteProvider),
- $routeMinErr = angular.$$minErr('ngRoute');
-
-/**
- * @ngdoc provider
- * @name $routeProvider
- *
- * @description
- *
- * Used for configuring routes.
- *
- * ## Example
- * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
- *
- * ## Dependencies
- * Requires the {@link ngRoute `ngRoute`} module to be installed.
- */
-function $RouteProvider() {
- function inherit(parent, extra) {
- return angular.extend(Object.create(parent), extra);
- }
-
- var routes = {};
-
- /**
- * @ngdoc method
- * @name $routeProvider#when
- *
- * @param {string} path Route path (matched against `$location.path`). If `$location.path`
- * contains redundant trailing slash or is missing one, the route will still match and the
- * `$location.path` will be updated to add or drop the trailing slash to exactly match the
- * route definition.
- *
- * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
- * to the next slash are matched and stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain named groups starting with a colon and ending with a star:
- * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
- * when the route matches.
- * * `path` can contain optional named groups with a question mark: e.g.`:name?`.
- *
- * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
- * `/color/brown/largecode/code/with/slashes/edit` and extract:
- *
- * * `color: brown`
- * * `largecode: code/with/slashes`.
- *
- *
- * @param {Object} route Mapping information to be assigned to `$route.current` on route
- * match.
- *
- * Object properties:
- *
- * - `controller` – `{(string|function()=}` – Controller fn that should be associated with
- * newly created scope or the name of a {@link angular.Module#controller registered
- * controller} if passed as a string.
- * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
- * published to scope under the `controllerAs` name.
- * - `template` – `{string=|function()=}` – html template as a string or a function that
- * returns an html template as a string which should be used by {@link
- * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
- * This property takes precedence over `templateUrl`.
- *
- * If `template` is a function, it will be called with the following parameters:
- *
- * - `{Array.