Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forum Categories having colors and edit category features #2135

Merged
merged 49 commits into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
58db4e3
Forum allow multiple categories for a thread
scopeInfinity Jun 4, 2018
a076b8f
Using Category selection as checkbox
scopeInfinity Jun 5, 2018
e29767e
Categories as buttons
scopeInfinity Jun 6, 2018
5614d67
Fixed typos and indentations
scopeInfinity Jun 6, 2018
d3ed94e
Forum Allows Categories reordering UI
scopeInfinity Jun 6, 2018
db1d318
Merge branch 'master' of https://github.com/Submitty/Submitty into fo…
scopeInfinity Jun 6, 2018
8f4d770
Merge branch 'forum_multiple_categories' into forum_edit_categories
scopeInfinity Jun 6, 2018
6f9e228
Forum allows categories reordering controllers
scopeInfinity Jun 6, 2018
f7e4d18
Forum category rank in sample data
scopeInfinity Jun 7, 2018
8af1b9c
Better UI for button toggle
scopeInfinity Jun 7, 2018
78d4f93
Bug Fix
scopeInfinity Jun 7, 2018
22f025a
Added E2E tests for multiple categories
scopeInfinity Jun 7, 2018
52cef29
Fixed typos
scopeInfinity Jun 7, 2018
e181087
Filter category name
scopeInfinity Jun 8, 2018
7732e1a
Merge branch 'forum_multiple_categories' into forum_edit_categories
scopeInfinity Jun 8, 2018
a29dfe1
Added refreshCategories feature without making additonal request to s…
scopeInfinity Jun 8, 2018
0f79060
Create Thread category selection on JS disabled and Fixed typo
scopeInfinity Jun 9, 2018
743169a
Better category selection on JS enable/disabled
scopeInfinity Jun 9, 2018
77d562d
Filter threads on multiple categories together
scopeInfinity Jun 10, 2018
8e9fb39
Merge branch 'forum_multiple_categories' into forum_edit_categories
scopeInfinity Jun 10, 2018
668e987
Fixed bug, showing category list if not exists
scopeInfinity Jun 10, 2018
d0d0e33
Removed console log
scopeInfinity Jun 10, 2018
8d66ba3
Forum Edit Categories, colors
scopeInfinity Jun 8, 2018
db24e07
Merge branch 'forum_edit_categories' into forum_edit_categories_color…
scopeInfinity Jun 11, 2018
ff2b109
Added 8 colors with names
scopeInfinity Jun 11, 2018
985fd28
Updated sample data for cat colors
scopeInfinity Jun 11, 2018
d1a0271
Merge branch 'master' into forum_multiple_categories
bmcutler Jun 11, 2018
bc02359
Edit Category Name
scopeInfinity Jun 11, 2018
8008823
Forum, Delete Category
scopeInfinity Jun 11, 2018
b92bba8
Dynamic refresh cat-buttons on new category creation
scopeInfinity Jun 12, 2018
c4cce1c
Edit thread title
scopeInfinity Jun 12, 2018
9670e66
Better notification on create/delete category
scopeInfinity Jun 12, 2018
dbe334a
Fixed Bug
scopeInfinity Jun 12, 2018
0b7af56
Merge branch 'master' into forum_multiple_categories
bmcutler Jun 12, 2018
9dc90c8
Forum Edit Categories (Reordering) (#2126)
scopeInfinity Jun 12, 2018
cbbb372
Revert "Edit thread title"
scopeInfinity Jun 13, 2018
8eb1b4a
Merge branch 'forum_multiple_categories' into forum_edit_categories_c…
scopeInfinity Jun 13, 2018
6fb1492
Bug Fix
scopeInfinity Jun 14, 2018
3c9fd4a
Bug Fix update_database.py
scopeInfinity Jun 14, 2018
57475fa
Inline Add Category field in popup
scopeInfinity Jun 14, 2018
05c076b
Merge branch 'master' of https://github.com/Submitty/Submitty into fo…
scopeInfinity Jun 14, 2018
823ee7f
Bug Fix
scopeInfinity Jun 14, 2018
fdbf069
Merge branch 'master' into forum_edit_categories_colorAndText
bmcutler Jun 15, 2018
fa9c5ad
Bug Fixes
scopeInfinity Jun 16, 2018
b5e3a84
Merge branch 'master' into forum_edit_categories_colorAndText
scopeInfinity Jun 16, 2018
fb379ba
DB color column as NOT NULL
scopeInfinity Jun 17, 2018
90a49af
Merge branch 'master' of https://github.com/Submitty/Submitty into fo…
scopeInfinity Jun 17, 2018
f149c6f
Minor UI Fix + changes in update_database.py
scopeInfinity Jun 17, 2018
1e92a58
Merge branch 'master' into forum_edit_categories_colorAndText
bmcutler Jun 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .setup/bin/setup_sample_courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ def create(self):
forum_thread_cat = Table("thread_categories", metadata, autoload=True)

for catData in f_data[2]:
conn.execute(forum_cat_list.insert(), category_desc=catData[0])
conn.execute(forum_cat_list.insert(), category_desc=catData[0], rank=catData[1], color=catData[2])

for thread_id, threadData in enumerate(f_data[1], start = 1):
conn.execute(forum_threads.insert(),
Expand Down
6 changes: 3 additions & 3 deletions .setup/data/forum/categories.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Comment
Question
Tutorials
Comment | 1 | #008000
Question | 0 | #800000
Tutorials | 2 | #000080
4 changes: 4 additions & 0 deletions .setup/update_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@
os.system("PGPASSWORD='{}' psql --host={} --username={} --dbname={} -c 'ALTER TABLE ONLY threads ADD COLUMN merged_thread_id int DEFAULT '-1''".format(*variables))
os.system("PGPASSWORD='{}' psql --host={} --username={} --dbname={} -c 'ALTER TABLE ONLY threads ADD COLUMN merged_post_id int DEFAULT '-1''".format(*variables))

# categories ordering for discussion forum
os.system("PGPASSWORD='{}' psql --host={} --username={} --dbname={} -c 'ALTER TABLE ONLY categories_list ADD COLUMN rank int'".format(*variables))
os.system("PGPASSWORD='{}' psql --host={} --username={} --dbname={} -c 'ALTER TABLE ONLY categories_list ADD COLUMN color varchar DEFAULT '#000080'".format(*variables))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please test this, there is a single quote missing at the end to close off the one before "ALTER"


# To allow delete gradeable
os.system("""PGPASSWORD='{}' psql --host={} --username={} --dbname={} -c 'ALTER TABLE ONLY peer_assign DROP CONSTRAINT peer_assign_g_id_fkey'""".format(*variables))
os.system("""PGPASSWORD='{}' psql --host={} --username={} --dbname={} -c 'ALTER TABLE ONLY peer_assign ADD CONSTRAINT peer_assign_g_id_fkey FOREIGN KEY (g_id) REFERENCES gradeable(g_id) ON UPDATE CASCADE ON DELETE CASCADE'""".format(*variables))
Expand Down
2 changes: 2 additions & 0 deletions migration/data/course_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@ CREATE TABLE "thread_categories" (
CREATE TABLE "categories_list" (
"category_id" serial NOT NULL,
"category_desc" varchar NOT NULL,
"rank" int,
"color" varchar DEFAULT '#000080',
Copy link
Member

@MasterOdin MasterOdin Jun 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can color be null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it can't be NULL. Thankyou!

CONSTRAINT categories_list_pk PRIMARY KEY ("category_id")
);

Expand Down
201 changes: 183 additions & 18 deletions site/app/controllers/forum/ForumController.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public function run() {
case 'add_category':
$this->addNewCategory();
break;
case 'delete_category':
$this->deleteCategory();
break;
case 'edit_category':
$this->editCategory();
break;
case 'reorder_categories':
$this->reorderCategories();
break;
case 'show_stats':
$this->showStats();
break;
Expand Down Expand Up @@ -109,10 +118,50 @@ private function checkGoodAttachment($isThread, $thread_id, $file_post){
} return $imageCheck;
}

private function isValidCategory($inputCategoryId = -1, $inputCategoryName = ''){
private function isValidCategories($inputCategoriesIds = -1, $inputCategoriesName = -1){
$rows = $this->core->getQueries()->getCategories();
if(is_array($inputCategoriesIds)) {
if(count($inputCategoriesIds) < 1) {
return false;
}
foreach ($inputCategoriesIds as $category_id) {
$match_found = false;
foreach($rows as $index => $values){
if($values["category_id"] === $category_id) {
$match_found = true;
break;
}
}
if(!$match_found) {
return false;
}
}
}
if(is_array($inputCategoriesName)) {
if(count($inputCategoriesName) < 1) {
return false;
}
foreach ($inputCategoriesName as $category_name) {
$match_found = false;
foreach($rows as $index => $values){
if($values["category_desc"] === $category_name) {
$match_found = true;
break;
}
}
if(!$match_found) {
return false;
}
}
}
return true;
}

private function isCategoryDeletionGood($category_id){
// Check if not the last category which exists
$rows = $this->core->getQueries()->getCategories();
foreach($rows as $index => $values){
if($values["category_id"] === $inputCategoryId || $values["category_desc"] === $inputCategoryName) {
if(((int)$values["category_id"]) !== $category_id) {
return true;
}
}
Expand All @@ -124,7 +173,7 @@ public function addNewCategory(){
if($this->core->getUser()->getGroup() <= 2){
if(!empty($_REQUEST["newCategory"])) {
$category = $_REQUEST["newCategory"];
if($this->isValidCategory(-1, $category)) {
if($this->isValidCategories(-1, array($category))) {
$result["error"] = "That category already exists.";
} else {
$newCategoryId = $this->core->getQueries()->addNewCategory($category);
Expand All @@ -140,27 +189,118 @@ public function addNewCategory(){
return $result;
}

public function deleteCategory(){
$result = array();
if($this->core->getUser()->getGroup() <= 2){
if(!empty($_REQUEST["deleteCategory"])) {
$category = (int)$_REQUEST["deleteCategory"];
if(!$this->isValidCategories(array($category))) {
$result["error"] = "That category doesn't exists.";
} else if(!$this->isCategoryDeletionGood($category)) {
$result["error"] = "Last category can't be deleted.";
} else {
if($this->core->getQueries()->deleteCategory($category)) {
$result["success"] = "OK";
} else {
$result["error"] = "Category is in use.";
}
}
} else {
$result["error"] = "No category data submitted. Please try again.";
}
} else {
$result["error"] = "You do not have permissions to do that.";
}
$this->core->getOutput()->renderJson($result);
return $result;
}

public function editCategory(){
$result = array();
if($this->core->getUser()->getGroup() <= 2){
$category_id = $_REQUEST["category_id"];
$category_desc = null;
$category_color = null;
$should_update = true;

if((!empty($_REQUEST["category_desc"])) && isset($_REQUEST["category_desc"])) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I didn't know that.

$category_desc = $_REQUEST["category_desc"];
if($this->isValidCategories(-1, array($category_desc))) {
$result["error"] = "That category already exists.";
$should_update = false;
}
}
if(isset($_REQUEST["category_color"])) {
$category_color = $_REQUEST["category_color"];
if(!in_array(strtoupper($category_color), $this->getAllowedCategoryColor())) {
$result["error"] = "Given category color is not allowed.";
$should_update = false;
}
}
if($should_update) {
$this->core->getQueries()->editCategory($category_id, $category_desc, $category_color);
$result["success"] = "OK";
} else if(!isset($result["error"])) {
$result["error"] = "No category data updated. Please try again.";
}
} else {
$result["error"] = "You do not have permissions to do that.";
}
$this->core->getOutput()->renderJson($result);
return $result;
}

public function reorderCategories(){
$result = array();
if($this->core->getUser()->getGroup() <= 2){
$rows = $this->core->getQueries()->getCategories();

$current_order = array();
foreach ($rows as $row) {
$current_order[] = (int)$row['category_id'];
}
$new_order = array();
foreach ($_POST['categorylistitem'] as $item) {
$new_order[] = (int)$item;
}

if(count(array_diff(array_merge($current_order, $new_order), array_intersect($current_order, $new_order))) === 0) {
$this->core->getQueries()->reorderCategories($new_order);
$results["success"] = "ok";
} else {
$result["error"] = "Different Categories IDs given";
}
} else {
$result["error"] = "You do not have permissions to do that.";
}
$this->core->getOutput()->renderJson($result);
return $result;
}

//CODE WILL BE CONSOLIDATED IN FUTURE

public function publishThread(){
$title = $_POST["title"];
$thread_content = str_replace("\r", "", $_POST["thread_content"]);
$anon = (isset($_POST["Anon"]) && $_POST["Anon"] == "Anon") ? 1 : 0;
$announcment = (isset($_POST["Announcement"]) && $_POST["Announcement"] == "Announcement" && $this->core->getUser()->getGroup() < 3) ? 1 : 0 ;
$category_id = (int)$_POST["cat"];
$categories_ids = array();
foreach ($_POST["cat"] as $category_id) {
$categories_ids[] = (int)$category_id;
}
if(empty($title) || empty($thread_content)){
$this->core->addErrorMessage("One of the fields was empty or bad. Please re-submit your thread.");
$this->core->redirect($this->core->buildUrl(array('component' => 'forum', 'page' => 'create_thread')));
}else if(!$this->isValidCategory($category_id)){
$this->core->addErrorMessage("You must select a valid category. Please re-submit your thread.");
}else if(!$this->isValidCategories($categories_ids)){
$this->core->addErrorMessage("You must select valid categories. Please re-submit your thread.");
$this->core->redirect($this->core->buildUrl(array('component' => 'forum', 'page' => 'create_thread')));
} else {
$hasGoodAttachment = $this->checkGoodAttachment(true, -1, 'file_input');
if($hasGoodAttachment == -1){
return;
}

$result = $this->core->getQueries()->createThread($this->core->getUser()->getId(), $title, $thread_content, $anon, $announcment, $hasGoodAttachment, $category_id);
$result = $this->core->getQueries()->createThread($this->core->getUser()->getId(), $title, $thread_content, $anon, $announcment, $hasGoodAttachment, $categories_ids);
$id = $result["thread_id"];
$post_id = $result["post_id"];

Expand Down Expand Up @@ -277,11 +417,11 @@ public function alterPost($modifyType){
}
}

private function getSortedThreads($category_id){
private function getSortedThreads($categories_ids){
$current_user = $this->core->getUser()->getId();
if($this->isValidCategory($category_id)) {
$announce_threads = $this->core->getQueries()->loadAnnouncements($category_id);
$reg_threads = $this->core->getQueries()->loadThreads($category_id);
if($this->isValidCategories($categories_ids)) {
$announce_threads = $this->core->getQueries()->loadAnnouncements($categories_ids);
$reg_threads = $this->core->getQueries()->loadThreads($categories_ids);
} else {
$announce_threads = $this->core->getQueries()->loadAnnouncementsWithoutCategory();
$reg_threads = $this->core->getQueries()->loadThreadsWithoutCategory();
Expand Down Expand Up @@ -312,22 +452,34 @@ private function getSortedThreads($category_id){
$ordered_threads[] = $thread;
}
}

foreach ($ordered_threads as &$thread) {
$list = array();
foreach(explode("|", $thread['categories_ids']) as $id ) {
$list[] = (int)$id;
}
$thread['categories_ids'] = $list;
$thread['categories_desc'] = explode("|", $thread['categories_desc']);
$thread['categories_color'] = explode("|", $thread['categories_color']);
}
return $ordered_threads;
}

public function getThreads(){

$category_id = array_key_exists('thread_category', $_POST) && !empty($_POST["thread_category"]) ? (int)$_POST['thread_category'] : -1;

$categories_ids = array_key_exists('thread_categories', $_POST) && !empty($_POST["thread_categories"]) ? explode("|", $_POST['thread_categories']) : array();
foreach ($categories_ids as &$id) {
$id = (int)$id;
}
$max_thread = 0;
$threads = $this->getSortedThreads($category_id, $max_thread);
$threads = $this->getSortedThreads($categories_ids, $max_thread);

$currentCategoryId = array_key_exists('currentCategoryId', $_POST) ? (int)$_POST["currentCategoryId"] : -1;
$currentCategoriesIds = array_key_exists('currentCategoriesId', $_POST) ? explode("|", $_POST["currentCategoriesId"]) : array();
$currentThreadId = array_key_exists('currentThreadId', $_POST) && !empty($_POST["currentThreadId"]) && is_numeric($_POST["currentThreadId"]) ? (int)$_POST["currentThreadId"] : -1;
$thread_data = array();
$current_thread_title = "";
$activeThread = false;
$this->core->getOutput()->renderOutput('forum\ForumThread', 'showAlteredDislpayList', $threads, true, $currentThreadId, $currentCategoryId);
$this->core->getOutput()->renderOutput('forum\ForumThread', 'showAlteredDisplayList', $threads, true, $currentThreadId, $currentCategoriesIds);
$this->core->getOutput()->useHeader(false);
$this->core->getOutput()->useFooter(false);
return $this->core->getOutput()->renderJson(array("html" => $this->core->getOutput()->getOutput()));
Expand All @@ -339,7 +491,7 @@ public function showThreads(){
$category_id = in_array('thread_category', $_POST) ? $_POST['thread_category'] : -1;

$max_thread = 0;
$threads = $this->getSortedThreads($category_id, $max_thread);
$threads = $this->getSortedThreads(array($category_id), $max_thread);

$current_user = $this->core->getUser()->getId();

Expand All @@ -365,8 +517,21 @@ public function showThreads(){
$this->core->getOutput()->renderOutput('forum\ForumThread', 'showForumThreads', $user, $posts, $threads, $option, $max_thread);
}

private function getAllowedCategoryColor() {
$colors = array();
$colors["MAROON"] = "#800000";
$colors["OLIVE"] = "#808000";
$colors["GREEN"] = "#008000";
$colors["TEAL"] = "#008080";
$colors["NAVY"] = "#000080";
$colors["PURPLE"] = "#800080";
$colors["GRAY"] = "#808080";
$colors["BLACK"] = "#000000";
return $colors;
}

public function showCreateThread(){
$this->core->getOutput()->renderOutput('forum\ForumThread', 'createThread');
$this->core->getOutput()->renderOutput('forum\ForumThread', 'createThread', $this->getAllowedCategoryColor());
}

public function getEditPostContent(){
Expand Down
Loading