From b12f1c724d35c575848eafc2c10d67c4b1bf6440 Mon Sep 17 00:00:00 2001
From: Martii <thalamew@q.com>
Date: Mon, 19 Oct 2015 19:14:28 -0600
Subject: [PATCH] Add inverse filter list

* Convert `flagged` to a multi-state QSP instead of **just** `true`/`false` for the inverse filter ... depends on role
* Coerce conditionals to indicate that one is testing `true`/`false` but the value is not necessarily expected to be those
* Modify affected views
* Create a sub view e.g. includes view to reuse some view code for the "Filters"

**NOTES**
* More to go but this is the stepping stone for Option 4a

Applies to #641

Tested on dev and local pro
---
 controllers/group.js                          |  2 +-
 controllers/index.js                          | 10 ++--
 controllers/user.js                           | 12 ++---
 libs/modelQuery.js                            | 50 ++++++++++++++++---
 .../includes/flagAdminToolFlaggedFilters.html |  6 +++
 views/includes/scriptList.html                |  8 +--
 views/includes/userList.html                  |  4 +-
 views/pages/modPage.html                      |  6 +--
 views/pages/scriptListPage.html               |  5 ++
 views/pages/userListPage.html                 |  5 ++
 views/pages/userScriptListPage.html           |  5 ++
 11 files changed, 84 insertions(+), 29 deletions(-)
 create mode 100644 views/includes/flagAdminToolFlaggedFilters.html

diff --git a/controllers/group.js b/controllers/group.js
index 8fcc00029..be48fabcd 100644
--- a/controllers/group.js
+++ b/controllers/group.js
@@ -254,7 +254,7 @@ exports.view = function (aReq, aRes, aNext) {
 
       // Empty list
       options.scriptListIsEmptyMessage = 'No scripts.';
-      if (options.isFlagged) {
+      if (!!options.isFlagged) {
         if (options.librariesOnly) {
           options.scriptListIsEmptyMessage = 'No flagged libraries.';
         } else {
diff --git a/controllers/index.js b/controllers/index.js
index 75253f081..eaba4b7ca 100644
--- a/controllers/index.js
+++ b/controllers/index.js
@@ -116,7 +116,7 @@ exports.home = function (aReq, aRes) {
 
     // Empty list
     options.scriptListIsEmptyMessage = 'No scripts.';
-    if (options.isFlagged) {
+    if (!!options.isFlagged) {
       if (options.librariesOnly) {
         options.scriptListIsEmptyMessage = 'No flagged libraries.';
       } else {
@@ -134,13 +134,13 @@ exports.home = function (aReq, aRes) {
 
     // Heading
     if (options.librariesOnly) {
-      options.pageHeading = options.isFlagged ? 'Flagged Libraries' : 'Libraries';
+      options.pageHeading = !!options.isFlagged ? 'Flagged Libraries' : 'Libraries';
     } else {
-      options.pageHeading = options.isFlagged ? 'Flagged Scripts' : 'Scripts';
+      options.pageHeading = !!options.isFlagged ? 'Flagged Scripts' : 'Scripts';
     }
 
     // Page metadata
-    if (options.isFlagged) {
+    if (!!options.isFlagged) {
       if (options.librariesOnly) {
         pageMetadata(options, ['Flagged Libraries', 'Moderation']);
       } else {
@@ -155,7 +155,7 @@ exports.home = function (aReq, aRes) {
 
     async.parallel([
       function (aCallback) {
-        if (!options.isFlagged || !options.isAdmin) {  // NOTE: Watchpoint
+        if (!!!options.isFlagged || !options.isAdmin) {  // NOTE: Watchpoint
           aCallback();
           return;
         }
diff --git a/controllers/user.js b/controllers/user.js
index 673fa3205..50ed610e3 100644
--- a/controllers/user.js
+++ b/controllers/user.js
@@ -223,17 +223,17 @@ exports.userListPage = function (aReq, aRes, aNext) {
 
     // Empty list
     options.userListIsEmptyMessage = 'No users.';
-    if (options.isFlagged) {
+    if (!!options.isFlagged) {
       options.userListIsEmptyMessage = 'No flagged users.';
     } else if (options.searchBarValue) {
       options.userListIsEmptyMessage = 'We couldn\'t find any users by this name.';
     }
 
     // Heading
-    options.pageHeading = options.isFlagged ? 'Flagged Users' : 'Users';
+    options.pageHeading = !!options.isFlagged ? 'Flagged Users' : 'Users';
 
     // Page metadata
-    if (options.isFlagged) {
+    if (!!options.isFlagged) {
       pageMetadata(options, ['Flagged Users', 'Moderation']);
     }
   }
@@ -248,7 +248,7 @@ exports.userListPage = function (aReq, aRes, aNext) {
 
     async.parallel([
       function (aCallback) {
-        if (!options.isFlagged || !options.isAdmin) {  // NOTE: Watchpoint
+        if (!!!options.isFlagged || !options.isAdmin) {  // NOTE: Watchpoint
           aCallback();
           return;
         }
@@ -524,7 +524,7 @@ exports.userScriptListPage = function (aReq, aRes, aNext) {
 
       // Empty list
       options.scriptListIsEmptyMessage = 'No scripts.';
-      if (options.isFlagged) {
+      if (!!options.isFlagged) {
         if (options.librariesOnly) {
           options.scriptListIsEmptyMessage = 'No flagged libraries.';
         } else {
@@ -547,7 +547,7 @@ exports.userScriptListPage = function (aReq, aRes, aNext) {
 
       async.parallel([
         function (aCallback) {
-          if (!options.isFlagged || !options.isAdmin) {  // NOTE: Watchpoint
+          if (!!!options.isFlagged || !options.isAdmin) {  // NOTE: Watchpoint
             aCallback();
             return;
           }
diff --git a/libs/modelQuery.js b/libs/modelQuery.js
index 906a8f84b..3d5411553 100644
--- a/libs/modelQuery.js
+++ b/libs/modelQuery.js
@@ -182,25 +182,59 @@ var applyModelListQueryFlaggedFilter = function (aModelListQuery, aOptions, aFla
   if (aOptions.isYou || aOptions.isMod) {
     // Mod
     if (aFlaggedQuery) {
-      if (aFlaggedQuery === 'true') {
-        aOptions.isFlagged = true;
-        aOptions.searchBarPlaceholder = aOptions.searchBarPlaceholder.replace(/^Search /, 'Search Flagged ');
-        if (!_.findWhere(aOptions.searchBarFormHiddenVariables, { name: 'flagged' })) {
-          aOptions.searchBarFormHiddenVariables.push({ name: 'flagged', value: 'true' });
-        }
-        aModelListQuery.and({ flags: { $gt: 0 } });
+
+      aOptions.isFlagged = aFlaggedQuery;
+      aOptions.searchBarPlaceholder = aOptions.searchBarPlaceholder.replace(
+        /^Search /, 'Search Flagged '
+      );
+
+      switch (aOptions.isFlagged) {
+        case 'none':
+          if (aOptions.isAdmin) {
+            // Filter nothing but still show Flagged column
+            break;
+          }
+          // fallthrough
+        case 'absolute':
+          if (aOptions.isAdmin) {
+            aOptions.filterAbsolute = true;
+            aModelListQuery.and({ flagsAbsolute: { $gt: 0 } }); // TODO: This does not exist yet
+            break;
+          }
+          // fallthrough
+        default:
+           // Ensure default depending on role
+          if (aOptions.isAdmin) {
+            aOptions.isFlagged = 'critical';
+            aOptions.filterCritical = true;
+
+          } else {
+            aOptions.isFlagged = 'true';
+          }
+
+          aModelListQuery.and({ flags: { $gt: 0 } });
+          break;
+      }
+
+      if (!_.findWhere(aOptions.searchBarFormHiddenVariables, { name: 'flagged' })) {
+        aOptions.searchBarFormHiddenVariables.push({ name: 'flagged', value: aOptions.isFlagged });
       }
+
     } else {
+
       // Remove `flagged` form variable if present
       aOptions.searchBarFormHiddenVariables = _.without(
         aOptions.searchBarFormHiddenVariables,
-        _.findWhere(aOptions.searchBarFormHiddenVariables, { name: 'flagged', value: 'true' })
+        _.findWhere(aOptions.searchBarFormHiddenVariables, { name: 'flagged' })
       );
+
     }
   } else {
+
     // Hide
     // Script.flagged is undefined by default.
     aModelListQuery.and({ flagged: { $ne: true } });
+
   }
 };
 exports.applyModelListQueryFlaggedFilter = applyModelListQueryFlaggedFilter;
diff --git a/views/includes/flagAdminToolFlaggedFilters.html b/views/includes/flagAdminToolFlaggedFilters.html
new file mode 100644
index 000000000..bada85c74
--- /dev/null
+++ b/views/includes/flagAdminToolFlaggedFilters.html
@@ -0,0 +1,6 @@
+<h3>Filters</h3>
+<div class="list-group">
+  <a class="list-group-item list-group-item-info" href="?flagged=none{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}"><i class="fa fa-fw fa-times"></i> Clear Filter</a>
+  <a class="list-group-item{{#filterCritical}} active{{/filterCritical}}" href="?flagged=critical{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}"><i class="fa fa-fw fa-flag-o"></i> Critical Flags</a>
+  <a class="list-group-item{{#filterAbsolute}} active{{/filterAbsolute}}" href="?flagged=absolute{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}"><i class="fa fa-fw fa-flag"></i> Absolute Flags</a>
+</div>
diff --git a/views/includes/scriptList.html b/views/includes/scriptList.html
index eb2498f27..df217873e 100644
--- a/views/includes/scriptList.html
+++ b/views/includes/scriptList.html
@@ -1,10 +1,10 @@
 <table class="table table-hover">
   <thead>
     <tr>
-      <th class="text-center"><a href="?orderBy=name&orderDir={{orderDir.name}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#librariesOnly}}&library=true{{/librariesOnly}}{{#isFlagged}}&flagged=true{{/isFlagged}}">Name</a></th>
-      {{^librariesOnly}}<th class="text-center td-fit"><a href="?orderBy=installs&orderDir={{orderDir.install}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#isFlagged}}&flagged=true{{/isFlagged}}">Installs</a></th>{{/librariesOnly}}
-      <th class="text-center td-fit"><a href="?orderBy=rating&orderDir={{orderDir.rating}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#librariesOnly}}&library=true{{/librariesOnly}}{{#isFlagged}}&flagged=true{{/isFlagged}}">Rating</a></th>
-      <th class="text-center td-fit"><a href="?orderBy=updated&orderDir={{orderDir.updated}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#librariesOnly}}&library=true{{/librariesOnly}}{{#isFlagged}}&flagged=true{{/isFlagged}}">Last Updated</a></th>
+      <th class="text-center"><a href="?orderBy=name&orderDir={{orderDir.name}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#librariesOnly}}&library=true{{/librariesOnly}}{{#isFlagged}}&flagged={{isFlagged}}{{/isFlagged}}">Name</a></th>
+      {{^librariesOnly}}<th class="text-center td-fit"><a href="?orderBy=installs&orderDir={{orderDir.install}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#isFlagged}}&flagged={{isFlagged}}{{/isFlagged}}">Installs</a></th>{{/librariesOnly}}
+      <th class="text-center td-fit"><a href="?orderBy=rating&orderDir={{orderDir.rating}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#librariesOnly}}&library=true{{/librariesOnly}}{{#isFlagged}}&flagged={{isFlagged}}{{/isFlagged}}">Rating</a></th>
+      <th class="text-center td-fit"><a href="?orderBy=updated&orderDir={{orderDir.updated}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#librariesOnly}}&library=true{{/librariesOnly}}{{#isFlagged}}&flagged={{isFlagged}}{{/isFlagged}}">Last Updated</a></th>
       {{#hasFlagged}}
       <th>Flagged</th>
       {{/hasFlagged}}
diff --git a/views/includes/userList.html b/views/includes/userList.html
index d081a92e4..1a43a36ba 100644
--- a/views/includes/userList.html
+++ b/views/includes/userList.html
@@ -1,8 +1,8 @@
 <table class="table table-hover table-condensed">
   <thead>
     <tr>
-      <th><a href="?orderBy=name&orderDir={{orderDir.name}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#isFlagged}}&flagged=true{{/isFlagged}}">Name</a></th>
-      <th class="td-fit"><a href="?orderBy=role&orderDir={{orderDir.role}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#isFlagged}}&flagged=true{{/isFlagged}}">Rank</a></th>
+      <th><a href="?orderBy=name&orderDir={{orderDir.name}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#isFlagged}}&flagged={{isFlagged}}{{/isFlagged}}">Name</a></th>
+      <th class="td-fit"><a href="?orderBy=role&orderDir={{orderDir.role}}{{#searchBarValue}}&q={{searchBarValue}}{{/searchBarValue}}{{#isFlagged}}&flagged={{isFlagged}}{{/isFlagged}}">Rank</a></th>
       {{#hasFlagged}}
       <th>Flagged</th>
       {{/hasFlagged}}
diff --git a/views/pages/modPage.html b/views/pages/modPage.html
index 14906065a..39ec43380 100644
--- a/views/pages/modPage.html
+++ b/views/pages/modPage.html
@@ -12,13 +12,13 @@
         <h3>Flagged Items</h3>
         <p>These are items over their threshold.</p>
         <div class="list-group">
-          <a href="/?flagged=true" class="list-group-item">
+          <a href="/?flagged={{#isAdmin}}critical{{/isAdmin}}{{^isAdmin}}true{{/isAdmin}}" class="list-group-item">
             <i class="fa fa-fw fa-file-code-o"></i> <i class="fa fa-fw fa-flag"></i> Flagged Scripts
           </a>
-          <a href="/?library=true&flagged=true" class="list-group-item">
+          <a href="/?library=true&flagged={{#isAdmin}}critical{{/isAdmin}}{{^isAdmin}}true{{/isAdmin}}" class="list-group-item">
             <i class="fa fa-fw fa-file-excel-o"></i> <i class="fa fa-fw fa-flag"></i> Flagged Libraries
           </a>
-          <a href="/users?flagged=true" class="list-group-item">
+          <a href="/users?flagged={{#isAdmin}}critical{{/isAdmin}}{{^isAdmin}}true{{/isAdmin}}" class="list-group-item">
             <i class="fa fa-fw fa-user"></i> <i class="fa fa-fw fa-flag"></i> Flagged Users
           </a>
         </div>
diff --git a/views/pages/scriptListPage.html b/views/pages/scriptListPage.html
index f4788063f..9c46a5b8a 100644
--- a/views/pages/scriptListPage.html
+++ b/views/pages/scriptListPage.html
@@ -28,6 +28,11 @@ <h2 class="page-heading">
       </div>
       <div class="col-sm-4">
         {{> includes/searchBarPanel.html }}
+        {{#isFlagged}}
+          {{#isAdmin}}
+            {{> includes/flagAdminToolFlaggedFilters.html }}
+          {{/isAdmin}}
+        {{/isFlagged}}
         {{> includes/popularGroupsPanel.html }}
         {{> includes/announcementsPanel.html }}
       </div>
diff --git a/views/pages/userListPage.html b/views/pages/userListPage.html
index 40d9ae1b2..ed039b9f1 100644
--- a/views/pages/userListPage.html
+++ b/views/pages/userListPage.html
@@ -28,6 +28,11 @@ <h2 class="page-heading">
       </div>
       <div class="col-sm-4">
         {{> includes/searchBarPanel.html }}
+        {{#isFlagged}}
+          {{#isAdmin}}
+            {{> includes/flagAdminToolFlaggedFilters.html }}
+          {{/isAdmin}}
+        {{/isFlagged}}
       </div>
     </div>
   </div>
diff --git a/views/pages/userScriptListPage.html b/views/pages/userScriptListPage.html
index 20341cd70..49dc30f02 100644
--- a/views/pages/userScriptListPage.html
+++ b/views/pages/userScriptListPage.html
@@ -30,6 +30,11 @@
       </div>
       <div class="container-fluid col-sm-4">
         {{> includes/searchBarPanel.html }}
+        {{#isFlagged}}
+          {{#isAdmin}}
+            {{> includes/flagAdminToolFlaggedFilters.html }}
+          {{/isAdmin}}
+        {{/isFlagged}}
         {{> includes/userStatsPanel.html }}
       </div>
     </div>