diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..09a492f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +_notes/ +.vscode/ \ No newline at end of file diff --git a/changelog.md b/changelog.md index 7e6cdf2..a2d4a51 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,34 @@ # CHANGE LOG +**7 September 2016 + +* Fix: Issue handling illegal characters in group names +* Fix: Better handling of authorization when attempting to edit a workorder. +* Fix: Corrent some spelling errors. +* Improvement: Current approver can add collaborator to a workorder. * db changes see _update. +* Improvement: Sends update email to workorder creator when something changes. +* Improvement: Move workorder approve/edit into page_content and dbquery routing structure. +* Improvement: Refactor php/html in several places for greater clarity. +* Improvement: Add simple pubsub javascript library for easy frontend ui eventing. +* Improvement: Move appconfig.php to /config/appconfig.php * just makes sense. +* Improvement: Bump minor version + +**6 August 2016** + +* Fix: Pay engineering debt. forms_db_controller.php better follows data adapter pattern used in other classes. +* Fix: classes/login.php now including user fname and lname in query. +* Fix: XDebug with PHP on Windows showing multiple undefined variables. Fixed by initializing vars to null in multiple pages. +* Fix: Form preview on workorder forms list page now working. Added header_forms_admin.php to include JS code. +* Fix: Remove old db conn info in appconfig.php Not needed any longer. +* Fix: UserDataAdapter AdminUpdate function protected against SQL injection. +* Fix: Update .gitignore to ignore Visual Studio Code IDE config files in .vscode folder. +* Improvement: Supports using environment variables for db connection. See config/db.php for details. + +**4 August 2016** + +* Fix: #7 district level approver list can now be left blank if needed. Final will be handled by last group level approver. +* Fix: #10 Special characters in goup name can now include / char. +* Fix: #11 If forms fields have identical label text they will now render correctly in email and when viewing/editing. + **16 July 2016** * Fix: Fixed the query section of the update user page. Now you can update user information diff --git a/readme.md b/readme.md index c197aca..970bca6 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# Workorders v2.0.0 +# Workorders v2.1.0 A simple way for large groups to organize work using custom forms! @@ -14,4 +14,5 @@ A simple way for large groups to organize work using custom forms! * User permission levels. * User registration can be limited based on domain. * Users can view work orders that need their approval. -* Users can view work orders they have submitted. \ No newline at end of file +* Users can view work orders they have submitted. +* Collaboration feature allows including others in the workflow process as needed. \ No newline at end of file diff --git a/src/_page_processor.php b/src/_page_processor.php index 1657742..37df502 100644 --- a/src/_page_processor.php +++ b/src/_page_processor.php @@ -2,7 +2,7 @@ require_once("config/db.php"); require_once("classes/Login.php"); -require_once('./resources/appconfig.php'); +require_once('config/appconfig.php'); require_once "./resources/library/appinfo.php"; $appInfoDbAdapter = new AppInfo($dsn, $user_name, $pass_word); @@ -87,8 +87,8 @@ */ - - if($include_address == ""){ + $folder = null; // set default value or error in navbar. XDebug + if(isset($include_address) == false || $include_address == ""){ $include_address = "page_content/index.php"; } if(isset($_GET['I'])){ @@ -158,12 +158,12 @@
- ALERT Your are on the local server + ALERT You are on the local server
db_connection->query($sql); @@ -88,7 +88,6 @@ private function dologinWithPostData() $_SESSION['user_lname'] = $result_row->user_lname; $_SESSION['user_email'] = $result_row->user_email; $_SESSION['user_group'] = $result_row->user_group; - $_SESSION['form_manager'] = $result_row->form_manager; $_SESSION['user_perms'] = $result_row->user_perms; $_SESSION['user_login_status'] = 1; diff --git a/src/classes/_notes/dwsync.xml b/src/classes/_notes/dwsync.xml deleted file mode 100644 index c41608b..0000000 --- a/src/classes/_notes/dwsync.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/resources/appconfig.php b/src/config/appconfig.php similarity index 83% rename from src/resources/appconfig.php rename to src/config/appconfig.php index 8fbc1a9..b174afc 100644 --- a/src/resources/appconfig.php +++ b/src/config/appconfig.php @@ -10,11 +10,7 @@ abstract class Config { const BaseUrl = "http://www.example.com/"; const SiteTitleShort = "FLOW"; const SiteTitleLong = "Work Flow"; - const DbDsn = "mysql:host=localhost;dbname=formsdb"; - const DbUsername = ""; - const DbPassword = ""; const WorkorderApproverScript = "workorderview.php"; const WorkorderViewOnlyScript = "workorderview.php"; } - ?> \ No newline at end of file diff --git a/src/config/db.php b/src/config/db.php index 5b7c6de..3114aef 100644 --- a/src/config/db.php +++ b/src/config/db.php @@ -3,6 +3,15 @@ /** * Configuration for: Database Connection * + * NOTE: There are two ways to configure the DB connection. + * 1) Environment variables + * WO_ENV_ENABLED=1 + * WO_DB_NAME=yourDBname + * WO_DB_USERNAME=yourDBusername + * WO_DB_PASSWORD=yourDBpassword + * 2) Modify values in this config file below + * Change DB_NAME, DB_USERNAME_HERE, and DB_PASSWORD_HERE + * * For more information about constants please @see http://php.net/manual/en/function.define.php * If you want to know why we use "define" instead of "const" @see http://stackoverflow.com/q/2447791/1114320 * @@ -11,13 +20,24 @@ * DB_USER: user for your database. the user needs to have rights for SELECT, UPDATE, DELETE and INSERT. * DB_PASS: the password of the above user */ - $database_name = "DB_NAME"; - $dsn = 'mysql:host=localhost;dbname='.$database_name; - $user_name = 'DB_USERNAME_HERE'; //DEFUAULT DB_USERNAME_HERE - $pass_word = 'DB_PASSWORD_HERE'; + if(getenv("WO_ENV_ENABLED") == 1) + { + // Set these in your local environment + $database_name = getenv("WO_DB_NAME"); // DO NOT MODIFY HERE + $dsn = 'mysql:host=localhost;dbname='.$database_name; + $user_name = getenv('WO_DB_USERNAME'); // DO NOT MODIFY HERE + $pass_word = getenv('WO_DB_PASSWORD'); // DO NOT MODIFY HERE + } else { + // Modify the values below IF you are NOT using environment variables for config. + $database_name = "DB_NAME"; // SET DB NAME HERE + $dsn = 'mysql:host=localhost;dbname='.$database_name; + $user_name = 'DB_USERNAME_HERE'; // SET DB USERNAME HERE + $pass_word = 'DB_PASSWORD_HERE'; // SET DB PASSWORD HERE - if($user_name == 'DB_USERNAME_HERE'){ - echo "

Woah!!! Hold on there Sparky, you need to update the util/forms_db_info.php befor running this program!

"; + if($user_name == 'DB_USERNAME_HERE'){ + echo "

Woah!!! Hold on there Sparky, you need to update the config/db.php before running this program!

"; + die(); + } } define("DB_HOST", "127.0.0.1"); diff --git a/src/dbquery/_notes/dwsync.xml b/src/dbquery/_notes/dwsync.xml deleted file mode 100644 index d0995bc..0000000 --- a/src/dbquery/_notes/dwsync.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/dbquery/qryADMIN/formbuild_qry.php b/src/dbquery/qryADMIN/formbuild_qry.php index e37ec98..e83fa04 100644 --- a/src/dbquery/qryADMIN/formbuild_qry.php +++ b/src/dbquery/qryADMIN/formbuild_qry.php @@ -10,13 +10,13 @@ $formAvailable = 0; if (isset($_POST["formAvailable"])) { $formAvailable = 1; } if (isset($_POST["updateform"])){ - $fdc = new FormsDataController(); + $fdc = new FormsDataController($dsn, $user_name, $pass_word); $QUERY_PROCESS = $fdc->updateForm($_POST["id"], $_POST["formname"], $_POST["formdesc"], $_POST["xmldata"], $_POST["workflow"], $_POST["notifyOnFinalApproval"], $formAvailable, $_POST["groupWorkflows"]); } elseif (isset($_POST["deleteform"])) { - $fdc = new FormsDataController(); + $fdc = new FormsDataController($dsn, $user_name, $pass_word); $QUERY_PROCESS = $fdc->deleteForm($_POST["id"]); } elseif (isset($_POST["addform"])) { - $fdc = new FormsDataController(); + $fdc = new FormsDataController($dsn, $user_name, $pass_word); $QUERY_PROCESS = $fdc->addForm($_POST["formname"], $_POST["formdesc"], $_POST["xmldata"], $_POST["workflow"], $_POST["notifyOnFinalApproval"], $formAvailable, $_POST["groupWorkflows"]); if (!$QUERY_PROCESS){ echo "
All fields are required. Keep calm and try again...
"; diff --git a/src/dbquery/qryGROUP/_notes/dwsync.xml b/src/dbquery/qryGROUP/_notes/dwsync.xml deleted file mode 100644 index 73bb1e4..0000000 --- a/src/dbquery/qryGROUP/_notes/dwsync.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/dbquery/qryUSER/_notes/dwsync.xml b/src/dbquery/qryUSER/_notes/dwsync.xml deleted file mode 100644 index db1e8f0..0000000 --- a/src/dbquery/qryUSER/_notes/dwsync.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/dbquery/qryUSER/edit_user_qry.php b/src/dbquery/qryUSER/edit_user_qry.php index 6a16cbd..2254b09 100644 --- a/src/dbquery/qryUSER/edit_user_qry.php +++ b/src/dbquery/qryUSER/edit_user_qry.php @@ -2,7 +2,7 @@ require_once "./resources/library/user.php"; -$usrDbAdapter = new UserDataAdapter($dsn, $user_name, $pass_word, $currentUserEmail); +$usrDbAdapter = new UserDataAdapter($dsn, $user_name, $pass_word); $element = "User"; diff --git a/src/dbquery/qryWORKORDER/add_collab_qry.php b/src/dbquery/qryWORKORDER/add_collab_qry.php new file mode 100644 index 0000000..a2f0cfb --- /dev/null +++ b/src/dbquery/qryWORKORDER/add_collab_qry.php @@ -0,0 +1,37 @@ +AddCollaborator($id, $comment, $collabUser); + +$wo = $workorderDataAdapter->Select($id); +$woViewModel = new WorkorderViewModel($wo, $key, $currentUserEmail); +// send emails. +$fromEmailAddress = 'noreply@dumasisd.org'; +$emailAdapter = new WorkorderEmailAdapter($fromEmailAddress); +$emailAdapter->SendAddCollab($wo, $woViewModel); +?> \ No newline at end of file diff --git a/src/dbquery/qryWORKORDER/add_comment_qry.php b/src/dbquery/qryWORKORDER/add_comment_qry.php new file mode 100644 index 0000000..42c7773 --- /dev/null +++ b/src/dbquery/qryWORKORDER/add_comment_qry.php @@ -0,0 +1,24 @@ +AddComment($id, $comment); +?> \ No newline at end of file diff --git a/src/dbquery/qryWORKORDER/end_collab_qry.php b/src/dbquery/qryWORKORDER/end_collab_qry.php new file mode 100644 index 0000000..d9f8d56 --- /dev/null +++ b/src/dbquery/qryWORKORDER/end_collab_qry.php @@ -0,0 +1,36 @@ +Select($id); +$woViewModel = new WorkorderViewModel($wo, $key, $currentUserEmail); + +$QUERY_PROCESS = $workorderDataAdapter->EndCollaboration($id, $comment); + +// send emails. +$fromEmailAddress = 'noreply@dumasisd.org'; +$emailAdapter = new WorkorderEmailAdapter($fromEmailAddress); +$emailAdapter->SendEndCollab($wo, $woViewModel); +?> \ No newline at end of file diff --git a/src/dbquery/qryWORKORDER/update_approve_qry.php b/src/dbquery/qryWORKORDER/update_approve_qry.php new file mode 100644 index 0000000..bbb399d --- /dev/null +++ b/src/dbquery/qryWORKORDER/update_approve_qry.php @@ -0,0 +1,110 @@ +Select($id); + /** + * Updates occur without a user logged in as long as the update key is valid. + * We need to use the current approvers email address. + * NOTE: WorkorderDataAdapter will throw when updating if currentUserEmail is not set. + */ + $userEmailAddress = $wo->currentApprover; + $woDbAdapter->currentUserEmail = $userEmailAddress; + // WorkorderViewModel is used to validate the key. + $woViewModel = new WorkorderViewModel($wo, $key); + if ($woViewModel->valid != true || $woDbAdapter->currentUserEmail == null) + { + die("Invalid request. Required data not provided or you are authorized to make changes."); + } + // Update the comments + $comments = json_decode($wo->comments, true); + if ($comments == null) { + $comments = array(); + } + $woComment = new WorkorderComment(); + $woComment->commentData = $comment; + $woComment->createdAt = date('Y-m-d H:i:s'); + $woComment->createdBy = $userEmailAddress; + array_push($comments, $woComment); + $wo->comments = json_encode($comments); + // Must decode the workflow in order to manipulate approvers. Must encode back before saving to DB + $workflow = json_decode($wo->workflow, true); + $approvers = ApproverHelper::toApproverArray($workflow); + // some default flags + $fromEmailAddress = 'noreply@dumasisd.org'; + $isFinalApprover = false; + $sendFinalApproveNotifications = false; + $newApproverKey = generateApproverKey(); // Change the approver key as needed. + // Check if approver is final + if ($wo->currentApprover == ApproverHelper::getFinal($approvers)->email) { + $isFinalApprover = true; + } + // Update approve status, keys, and current approver. + if ($approve == "true") { + if ($isFinalApprover == true){ + $wo->approveState = ApproveState::ApproveClosed; // Final. Work is now completed + $sendFinalApproveNotifications = true; + $wo->approverKey = ""; // No more access as approver. + $newApproverKey = ""; // viewmodel will need this in order to work. + } else { + $wo->approveState = ApproveState::PendingApproval; // waiting on more approvers + $wo->approverKey = $newApproverKey; + $nextApprover = ApproverHelper::getNext($approvers); + ApproverHelper::setCurrent($approvers, $nextApprover); + $wo->currentApprover = ApproverHelper::getCurrent($approvers)->email; + } + } else { + // rejected by the current approver. + if ($isFinalApprover == true){ + $wo->approveState = ApproveState::RejectClosed; // Final approver. Closed as rejected + $sendFinalApproveNotifications = false; // do not notify final approval contacts + $wo->approverKey = ""; // No more access as approver. + $newApproverKey = ""; // viewmodel will need this in order to work. + } else { + $wo->approveState = ApproveState::RejectClosed; // Closed as rejected + $sendFinalApproveNotifications = false; // do not notify final approval contacts + $wo->approverKey = ""; // No more access as approver. + $newApproverKey = ""; // viewmodel will need this in order to work. + } + } + // Must encode workflow back before saving to DB + $updatedWorkflow = new Workflow($workflow['name'], $approvers); + $wo->workflow = json_encode($updatedWorkflow); + $woDbAdapter->Update($id, $wo); + $woViewModel = new WorkorderViewModel($wo, $newApproverKey); // update the viewmodel since the comments have been updated. + + // send notifications + $emailAdapter = new WorkorderEmailAdapter($fromEmailAddress); + if ($approve == "true") { + if ($isFinalApprover != true) { + $emailAdapter->SendNeedsApprovalToCurrentApprover($wo, $woViewModel); + $emailAdapter->SendUpdatedDetailsToCreator($wo, $woViewModel); + } + if ($sendFinalApproveNotifications == true) { + $emailAdapter->SendViewOnlyFinalApprovalNotifications($wo, $woViewModel); + } + } else { + $emailAdapter->SendViewOnlyRejectedToCreator($wo, $woViewModel); + } + +?> diff --git a/src/includes/navbar.php b/src/includes/navbar.php index ae4b7f8..7572159 100644 --- a/src/includes/navbar.php +++ b/src/includes/navbar.php @@ -1,4 +1,4 @@ - +
"; foreach ($woViewModel->fieldData as $fieldkey => $value) { - $woBody .= "

" . $fieldkey . "

"; - $woBody .= "

" . $value . "

"; + $woBody .= "

" . $value["Label"] . "

"; + $woBody .= "

" . $value["Data"] . "

"; } $woBody .= "

Comments

"; if (count($woViewModel->comments) == 0) { @@ -323,6 +390,91 @@ private function RenderWorkorderDetailsStringAsHtml($wo, $woViewModel = null) return $woBody; } + // Sends detail view of workorder to creator, current approver, and current collaborator + public function SendUpdatedDetailsToAll($workorder, $woViewModel = null){ + $toAddresses = []; + $collabs = json_decode($workorder->collaborators, true); + foreach ($collabs as $key => $value) { + if ($value['user_email'] != null){ + $toAddresses[] = $value['user_email']; + } + } + $toAddresses[] = $workorder->createdBy; + $toAddresses[] = $workorder->currentApprover; + $from = $this->fromaddress; + $to = $toAddresses; + $subject = $workorder->formName . " " . $workorder->id . " updated."; + $body = "

Greetings!

This item has been updated.

"; + $body .= "

I'm just keeping you in the loop. You will receive another email when something changes.

"; + $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; + $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); + $this->SendEmail($to, $from, $subject, $body); + } + + // Sends detail view of workorder to creator, current approver, and current collaborator + public function SendUpdatedDetailsToCreator($workorder, $woViewModel = null){ + $from = $this->fromaddress; + $to = $workorder->createdBy; + $subject = $workorder->formName . " " . $workorder->id . " updated."; + $body = "

Greetings!

This item has been updated.

"; + $body .= "

I'm just keeping you in the loop. You will receive another email when something changes.

"; + $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; + $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); + $this->SendEmail($to, $from, $subject, $body); + } + + // Sends detail view of workorder to collaborators and approver + public function SendAddCollab($workorder, $woViewModel = null){ + $toAddresses = []; + $collabList = []; + $collabs = json_decode($workorder->collaborators, true); + foreach ($collabs as $key => $value) { + if ($value['user_email'] != null){ + $toAddresses[] = $value['user_email']; + $collabList[] = $value['user_email']; + } + } + $toAddresses[] = $workorder->currentApprover; + $from = $this->fromaddress; + $to = implode(",", $toAddresses); + $subject = "Collaboration request for " . $workorder->formName . " " . $workorder->id; + $body = "

Greetings!

The following people have been invited to collaborate on this item.

"; + $body .= "

" . implode(",", $collabList) . "

"; + $body .= "

I'm just keeping you in the loop. You will receive another email when something changes.

"; + $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; + $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); + $this->SendEmail($to, $from, $subject, $body); + } + + // Sends detail view of workorder to collaborators and approver + public function SendEndCollab($workorder, $woViewModel = null){ + $toAddresses = []; + $collabList = []; + if ($workorder->collaborators != null){ + $collabs = json_decode($workorder->collaborators, true); + foreach ($collabs as $key => $value) { + if ($value['user_email'] != null){ + $toAddresses[] = $value['user_email']; + $collabList[] = $value['user_email']; + } + } + } + $toAddresses[] = $workorder->currentApprover; + $from = $this->fromaddress; + $to = implode(",", $toAddresses); + $subject = "Collaboration ended for " . $workorder->formName . " " . $workorder->id; + $body = "

Greetings!

Thanks for the assist! Collaboration has ended for the following people.

"; + $body .= "

" . implode(",", $collabList) . "

"; + $body .= "

I'm just keeping you in the loop. If further assistance is needed you will receive another email.

"; + $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; + $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); + $this->SendEmail($to, $from, $subject, $body); + } + public function SendNeedsApprovalToCurrentApprover($workorder, $woViewModel = null) { require_once "email.php"; // LinkHelper @@ -330,7 +482,7 @@ public function SendNeedsApprovalToCurrentApprover($workorder, $woViewModel = nu $from = $this->fromaddress; $to = $workorder->currentApprover; $subject = $workorder->formName . " " . $workorder->id . " needs your approval."; - $body = "

Hello " . $to . ",

You are the current approver for " . $workorder->formName . " " . $workorder->id . ". "; + $body = "

Greetings " . $to . ",

You are the current approver for " . $workorder->formName . " " . $workorder->id . ".

"; $body .= "

Since you are the current approver you will be able to approve or reject the item. "; $body .= "Approval will send the item to the next listed approver. "; $body .= "If you are the final approver, the submitter will be notified of pending completion status. "; @@ -338,6 +490,7 @@ public function SendNeedsApprovalToCurrentApprover($workorder, $woViewModel = nu $body .= "

Click the link below to view " . $workorder->formName . " " . $workorder->id . "

"; $body .= "

" . $approverLink . "

"; $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); $this->SendEmail($to, $from, $subject, $body); } @@ -349,12 +502,13 @@ public function SendViewOnlyCreatedToCreator($workorder, $woViewModel = null) $from = $this->fromaddress; $to = $workorder->createdBy; $subject = $workorder->formName . " " . $workorder->id . " created."; - $body = "

Hello " . $to . ",

Your request has been submitted.

"; + $body = "

Greetings " . $to . ",

Your request has been submitted.

"; $body .= "

You created this item and will be able to view status and changes anytime. "; $body .= "You will receive another email when something changes. "; $body .= "Click the link below to view " . $workorder->formName . " " . $workorder->id . "

"; $body .= "

" . $viewonlyLink . "

"; $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); $this->SendEmail($to, $from, $subject, $body); } @@ -366,10 +520,11 @@ public function SendViewOnlyRejectedToCreator($workorder, $woViewModel = null) $from = $this->fromaddress; $to = $workorder->createdBy; $subject = $workorder->formName . " " . $workorder->id . " has been rejected."; - $body = "

Hello " . $to . ",

" . $workorder->formName . " " . $workorder->id . " has been rejected.

"; + $body = "

Greetings " . $to . ",

" . $workorder->formName . " " . $workorder->id . " has been rejected.

"; $body .= "

Click the link below to view " . $workorder->formName . " " . $workorder->id . "

"; $body .= "

" . $viewonlyLink . "

"; $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); $this->SendEmail($to, $from, $subject, $body); } @@ -384,10 +539,12 @@ public function SendViewOnlyFinalApprovalNotifications($workorder, $woViewModel $to = $workorder->createdBy . ", " . $workorder->notifyOnFinalApproval; } $subject = $workorder->formName . " " . $workorder->id . " Approved and completed"; + $body = "

Greetings " . $to . ",

"; $body = "

" . $workorder->formName . " " . $workorder->id . " has been completed.

"; $body .= "

Click the link below to view " . $workorder->formName . " " . $workorder->id . "

"; $body .= "

" . $viewonlyLink . "

"; $body .= "Regards,
" . $from; + $body .= "

* This is an automated email. Please do not reply. Our robots are not trained to respond yet!

"; $body .= $this->RenderWorkorderDetailsStringAsHtml($workorder, $woViewModel); $this->SendEmail($to, $from, $subject, $body); } @@ -487,6 +644,19 @@ function SelectAll($limit = 100) $stmt->execute(array(':limit' => $limit)); $workorders = $stmt->fetchAll(PDO::FETCH_CLASS); return $workorders; + } + /***********************/ + function SelectAllWhereCollaborator($limit = 100) + { + if ($this->currentUserEmail == null) { + throw new Exception("Operation requires user.", 1); + } + $sql = "SELECT * FROM Workorders WHERE collaborators like :collabEmail ORDER BY createdAt DESC LIMIT :limit"; + $stmt = $this->conn->prepare($sql); + $stmt->setFetchMode(PDO::FETCH_CLASS, "Workorder"); + $stmt->execute(array(':collabEmail' => '%'.$this->currentUserEmail.'%', ':limit' => $limit)); + $workorders = $stmt->fetchAll(PDO::FETCH_CLASS); + return $workorders; } function Insert($workorder) { @@ -504,9 +674,9 @@ function Update($workorderId, $workorder) if ($this->currentUserEmail == null) { throw new Exception("Operation requires user.", 1); } - $sql = "UPDATE Workorders SET formName = :formName, description = :description, formXml = :formXml, formData = :formData, currentApprover = :currentApprover, workflow = :workflow, approveState = :approveState, approverKey = :approverKey, viewOnlyKey = :viewOnlyKey, updatedAt = now(), updatedBy = :updatedBy, formId = :formId, notifyOnFinalApproval = :notifyOnFinalApproval, comments = :comments WHERE id = :id"; + $sql = "UPDATE Workorders SET formName = :formName, description = :description, formXml = :formXml, formData = :formData, currentApprover = :currentApprover, workflow = :workflow, approveState = :approveState, approverKey = :approverKey, viewOnlyKey = :viewOnlyKey, updatedAt = now(), updatedBy = :updatedBy, formId = :formId, notifyOnFinalApproval = :notifyOnFinalApproval, comments = :comments, collaborators = :collaborators WHERE id = :id"; $result = $this->conn->prepare($sql); - $status = $result->execute(array('formName' => $workorder->formName, 'description' => $workorder->description, 'formXml' => $workorder->formXml, 'formData' => $workorder->formData, 'currentApprover' => $workorder->currentApprover, 'workflow' => $workorder->workflow, 'approveState' => $workorder->approveState, 'approverKey' => $workorder->approverKey, 'viewOnlyKey' => $workorder->viewOnlyKey, 'updatedBy' => $this->currentUserEmail, 'formId' => $workorder->formId, 'notifyOnFinalApproval' => $workorder->notifyOnFinalApproval, 'comments' => $workorder->comments, 'id' => $workorderId )); + $status = $result->execute(array('formName' => $workorder->formName, 'description' => $workorder->description, 'formXml' => $workorder->formXml, 'formData' => $workorder->formData, 'currentApprover' => $workorder->currentApprover, 'workflow' => $workorder->workflow, 'approveState' => $workorder->approveState, 'approverKey' => $workorder->approverKey, 'viewOnlyKey' => $workorder->viewOnlyKey, 'updatedBy' => $this->currentUserEmail, 'formId' => $workorder->formId, 'notifyOnFinalApproval' => $workorder->notifyOnFinalApproval, 'comments' => $workorder->comments, 'collaborators' => $workorder->collaborators, 'id' => $workorderId )); return $status; } function UpdateFormData($workorderId, $formData) @@ -519,6 +689,111 @@ function UpdateFormData($workorderId, $formData) $status = $result->execute(array(':formData' => $formData, ':updatedBy' => $this->currentUserEmail, ':id' => $workorderId )); return $status; } + function AddComment($workorderId, $commentText) + { + // Loads the workorder from db and updates the comment data. + if ($this->currentUserEmail == null || $workorderId == null || $commentText == null){ + throw new Exception("Operation requires user."); + } + $wo = $this->Select($workorderId); + $woViewModel = new WorkorderViewModel($wo, "", $this->currentUserEmail); + if (!$woViewModel->userIsCollaborator && !$woViewModel->userIsCurrentApprover){ + throw new Exception("User cannot add comments at this time."); + } + // Update the comments + $comments = json_decode($wo->comments, true); + if ($comments == null) { + $comments = array(); + } + $woComment = new WorkorderComment(); + $woComment->commentData = $commentText; + $woComment->createdAt = date('Y-m-d H:i:s'); + $woComment->createdBy = $this->currentUserEmail; + array_push($comments, $woComment); + $wo->comments = json_encode($comments); + + return $this->Update($workorderId, $wo); + + } + function AddCollaborator($workorderId, $commentText, $collabId) + { + if ($this->currentUserEmail == null){ + throw new Exception("Operation requires user."); + } + if ($workorderId == null){ + throw new Exception("Operation requires workorder id."); + } + if ($commentText == null){ + throw new Exception("Operation requires comment text."); + } + // Loads the workorder from db. + $wo = $this->Select($workorderId); + + // Load collaborator data and add collab + $sql = "SELECT user_id, user_fname, user_lname, user_email FROM users WHERE user_id = :id AND collaborator > 0"; + $stmt = $this->conn->prepare($sql); + $stmt->setFetchMode(PDO::FETCH_CLASS, "WorkorderCollaborator"); + $stmt->execute(array(':id' => $collabId)); + $woCollab = $stmt->fetch(PDO::FETCH_CLASS); + if($woCollab == null){ + throw new Exception("Collaborator not found."); + } + $collabs = json_decode($wo->collaborators, true); + if ($collabs == null){ + $collabs = array(); + } + $collabExist = array_search($collabId, array_column($collabs, 'user_id')); + if ($collabExist == false){ + array_push($collabs, $woCollab); + $wo->collaborators = json_encode($collabs); + } else { + throw new exception("user already assigned as a collaborator."); + } + // Update the comments + $comments = json_decode($wo->comments, true); + if ($comments == null) { + $comments = array(); + } + $woComment = new WorkorderComment(); + $woComment->commentData = $commentText; + $woComment->createdAt = date('Y-m-d H:i:s'); + $woComment->createdBy = $this->currentUserEmail; + array_push($comments, $woComment); + $wo->comments = json_encode($comments); + + return $this->Update($workorderId, $wo); + + } + function EndCollaboration($workorderId, $commentText) + { + if ($this->currentUserEmail == null){ + throw new Exception("Operation requires user"); + } + if ($workorderId == null){ + throw new Exception("Operation requires workorder Id"); + } + if ($commentText == null){ + throw new Exception("Operation requires comment text."); + } + // Loads the workorder from db. + $wo = $this->Select($workorderId); + // Set collaborators field to null + $wo->collaborators = null; + // Update the comments + $comments = json_decode($wo->comments, true); + if ($comments == null) { + $comments = array(); + } + $woComment = new WorkorderComment(); + $woComment->commentData = $commentText; + $woComment->createdAt = date('Y-m-d H:i:s'); + $woComment->createdBy = $this->currentUserEmail; + array_push($comments, $woComment); + $wo->comments = json_encode($comments); + + return $this->Update($workorderId, $wo); + + } function Delete($workorderId) { $sql = "DELETE FROM Workorders WHERE id = :id"; diff --git a/src/views/createworkorder.php b/src/views/createworkorder.php index 7d3fd2b..f30ab8c 100644 --- a/src/views/createworkorder.php +++ b/src/views/createworkorder.php @@ -1,6 +1,7 @@ Get('System Version'); ?> @@ -40,10 +41,15 @@ ?> getFormById($formId); $formName = $formToRender['FormName']; $formDescription = $formToRender['Description']; @@ -61,19 +67,19 @@ // POST['id'] is not present. Should handle posted form data here $formPostHandler = new Pacman($_POST); // Need to load the form. Form data is stored with new workorder. - $formsDataAdapter = new FormsDataController(); + $formsDataAdapter = new FormsDataController($dsn, $user_name, $pass_word); $form = $formsDataAdapter->getFormById($formPostHandler->formId); // Setup data needed for creating workorder and rendering page $hideFormRenderingClassString = "hidden"; $formName = $formPostHandler->formName; //$_POST['form-name']; $formDescription = $formPostHandler->formDescription; //$_POST['form-description']; // Form Workflow field holds array of approver email addresses. We need to transform this to work with the data. - $approverArray = explode(',', $form['Workflow']); + $approverArray = ApproverHelper::ParseRawWorkflowData($form['Workflow']); $approvers = ApproverHelper::NewApproverArrayFromEmailArray($approverArray); // Get the groupWorkflow for the users group $groupWorkflows = $form['GroupWorkflows']; - $groupWorkflows = json_decode($groupWorkflows); - $userGroupApproverArray = $groupWorkflows->$currentUserGroup; + $groupWorkflows = json_decode($groupWorkflows, true); + $userGroupApproverArray = $groupWorkflows[$currentUserGroup]; $groupApprovers = ApproverHelper::NewApproverArrayFromEmailArray($userGroupApproverArray); // merge the approver arrays with group first and create the workflow for the form $mergedApprovers = ApproverHelper::MergeApproverArrays($groupApprovers, $approvers); diff --git a/src/views/formsbuild.php b/src/views/formsbuild.php index a144ba4..1c85aa7 100644 --- a/src/views/formsbuild.php +++ b/src/views/formsbuild.php @@ -1,3 +1,10 @@ +Get('System Version'); +?> diff --git a/src/views/home.php b/src/views/home.php index 37a50a1..f50a76e 100644 --- a/src/views/home.php +++ b/src/views/home.php @@ -1,4 +1,4 @@ - + diff --git a/src/views/not_logged_in.php b/src/views/not_logged_in.php index d2efeb9..113ce71 100644 --- a/src/views/not_logged_in.php +++ b/src/views/not_logged_in.php @@ -21,7 +21,7 @@ } } ?> - + @@ -100,7 +100,7 @@ } ?> - + diff --git a/src/views/register.php b/src/views/register.php index 3aa5673..ad9fa7b 100644 --- a/src/views/register.php +++ b/src/views/register.php @@ -7,7 +7,7 @@ ***************************************************/ ?> Get('System Version'); @@ -12,10 +13,12 @@ } require_once('./resources/library/workorder.php'); + require_once './resources/library/collaborator.php'; require_once('./config/db.php'); - $woDbAdapter = new WorkorderDataAdapter(DB_DSN, DB_USER, DB_PASS, $_SESSION['user_email']); + $woDbAdapter = new WorkorderDataAdapter($dsn, $user_name, $pass_word, $_SESSION['user_email']); $wo = $woDbAdapter->Select($id); $woViewModel = new WorkorderViewModel($wo, $key); + $collabViewModel = new CollaboratorViewModel($dsn, $user_name, $pass_word, $_SESSION['user_email']); $acceptBtnText = "APPROVE (not final)"; $rejectBtnText = "DENY"; @@ -88,17 +91,20 @@
- valid) { - echo "
"; - echo "
" . $woViewModel->approveState . " (" . $wo->currentApprover . ")" . "
"; - echo "

Submitted By

" . $wo->createdBy . ""; - echo "
"; + valid) { ?> +
approveState . " (" . $wo->currentApprover . ")"?>
+
+

+ createdBy?> +
+ fieldData as $fieldkey => $value) { - echo "

" . $fieldkey . "

"; - echo "

" . $value . "

"; + echo "

" . $value["Label"] . "

"; + echo "

" . $value["Data"] . "

"; } - echo "

Approver Comments

"; + ?> +

Approver Comments

+ comments) == 0) { echo "No comments posted."; } else { @@ -116,7 +122,8 @@ } echo ""; } - } else { + ?> + Unable to view the workorder. You may not be authorized...
'; } ?> @@ -138,12 +145,19 @@
- - - " type="button" class="btn btn-primary">Edit Workorder +
+
+ + + " type="button" class="btn btn-primary">Edit Workorder +
+ +
-
@@ -183,7 +197,13 @@ - + + + + + + + diff --git a/src/views/workorderupdate.php b/src/views/workorderupdate.php index 1883da8..dad9eb6 100644 --- a/src/views/workorderupdate.php +++ b/src/views/workorderupdate.php @@ -4,7 +4,7 @@ * Requires valid approver key before update. */ - require_once('./resources/appconfig.php'); + require_once('config/appconfig.php'); require_once("./resources/library/appinfo.php"); $appInfoDbAdapter = new AppInfo($dsn, $user_name, $pass_word); $system_version =$appInfoDbAdapter->Get('System Version'); @@ -169,8 +169,8 @@ echo "

Submitted By

" . $wo->createdBy . ""; echo ""; foreach ($woViewModel->fieldData as $fieldkey => $value) { - echo "

" . $fieldkey . "

"; - echo "

" . $value . "

"; + echo "

" . $value["Label"] . "

"; + echo "

" . $value["Data"] . "

"; } echo "

Comments

"; if (count($woViewModel->comments) == 0) {