More work on results editor, a=chris

Chris Pollett [2022-08-01 02:Aug:st]
More work on results editor, a=chris
Filename
src/controllers/SearchController.php
src/controllers/components/CrawlComponent.php
src/css/search.css
src/locale/ar/configure.ini
src/locale/bn/configure.ini
src/locale/de/configure.ini
src/locale/el_GR/configure.ini
src/locale/en_US/configure.ini
src/locale/es/configure.ini
src/locale/fa/configure.ini
src/locale/fr_FR/configure.ini
src/locale/he/configure.ini
src/locale/hi/configure.ini
src/locale/id/configure.ini
src/locale/it/configure.ini
src/locale/ja/configure.ini
src/locale/kn/configure.ini
src/locale/ko/configure.ini
src/locale/nl/configure.ini
src/locale/pl/configure.ini
src/locale/pt/configure.ini
src/locale/ru/configure.ini
src/locale/te/configure.ini
src/locale/th/configure.ini
src/locale/tl/configure.ini
src/locale/tr/configure.ini
src/locale/vi_VN/configure.ini
src/locale/vi_VN/statistics.txt
src/locale/zh_CN/configure.ini
src/models/SearchverticalsModel.php
src/views/elements/ResultseditorElement.php
src/views/elements/SearchElement.php
src/views/elements/SearchcalloutElement.php
diff --git a/src/controllers/SearchController.php b/src/controllers/SearchController.php
index 15ef4e0de..f7dedf975 100755
--- a/src/controllers/SearchController.php
+++ b/src/controllers/SearchController.php
@@ -465,8 +465,9 @@ class SearchController extends Controller implements CrawlConstants
                 $changed_settings_flag = true;
             }
         }
-        $data["SEARCH_GROUP_MEMBER"] = $this->model("group")->checkUserGroup(
-            $user, C\SEARCH_GROUP_ID, C\ACTIVE_STATUS);
+        $data["CAN_EDIT_RESULTS"] =
+            $this->model("user")->isAllowedUserActivity(
+            $_SESSION['USER_ID'] ?? C\PUBLIC_USER_ID, "resultsEditor");
         $data['LOCALE_TAG'] = L\getLocaleTag();
         $data['LANGUAGES_TO_SHOW'] = 1;
         $n = C\NUM_RESULTS_PER_PAGE;
diff --git a/src/controllers/components/CrawlComponent.php b/src/controllers/components/CrawlComponent.php
index 7c771f84c..110308406 100644
--- a/src/controllers/components/CrawlComponent.php
+++ b/src/controllers/components/CrawlComponent.php
@@ -2317,7 +2317,7 @@ class CrawlComponent extends Component implements CrawlConstants
                         $_REQUEST["KWIKI_PAGE"] = "";
                         return $parent->redirectWithMessage(
                             tl('crawl_component_results_editor_kwiki_new'),
-                            ["QUERY", "KWIKI_PAGE", "MODE"]);
+                            ["QUERY", "KWIKI_PAGE", "MODE", "SEARCH"]);
                     } else {
                         $_REQUEST["ID"] = $kwiki["ID"];
                         $_REQUEST["QUERY"] = $query;
@@ -2327,7 +2327,7 @@ class CrawlComponent extends Component implements CrawlConstants
                         $_REQUEST["KWIKI_PAGE"] = $kwiki['PAGE'];
                         return $parent->redirectWithMessage(
                             tl('crawl_component_results_editor_page_loaded'),
-                            ["ID", "QUERY", "KWIKI_PAGE", "MODE"]);
+                            ["ID", "QUERY", "KWIKI_PAGE", "MODE", "SEARCH"]);
                     }
                     break;
                 case "loadquerymap":
@@ -2345,12 +2345,12 @@ class CrawlComponent extends Component implements CrawlConstants
                         $_REQUEST['MAP_URLS'] = [];
                         return $parent->redirectWithMessage(
                             tl('crawl_component_results_editor_map_created'),
-                            ["MAP_QUERY", "MAP_URLS", "MODE"]);
+                            ["MAP_QUERY", "MAP_URLS", "MODE", "URL"]);
                     } else {
                         $_REQUEST['MAP_URLS'] = implode("\n", $map_urls);
                         return $parent->redirectWithMessage(
                             tl('crawl_component_results_editor_map_loaded'),
-                            ["MAP_QUERY", "MAP_URLS", "MODE"]);
+                            ["MAP_QUERY", "MAP_URLS", "MODE", "URL"]);
                     }
                     break;
                 case "loadurl":
@@ -2379,7 +2379,7 @@ class CrawlComponent extends Component implements CrawlConstants
                         return $parent->redirectWithMessage(
                             tl('crawl_component_results_editor_page_loaded'),
                             ["ID", "URL", "URL_ACTION", "TITLE",
-                            "DESCRIPTION", "MODE"]);
+                            "DESCRIPTION", "MODE", "MAP_QUERY"]);
                     }
                     break;
                 case "savekwiki":
@@ -2388,7 +2388,7 @@ class CrawlComponent extends Component implements CrawlConstants
                         $_REQUEST["QUERY"] = "";
                         return $parent->redirectWithMessage(
                             tl('crawl_component_results_editor_no_query'),
-                            ["ID", "QUERY", "KWIKI_PAGE", "MODE"]);
+                            ["ID", "QUERY", "KWIKI_PAGE", "MODE", "SEARCH"]);
                     }
                     $query = mb_strtolower(str_replace("-", " ", $query));
                     $_REQUEST["QUERY"] = $query;
@@ -2426,7 +2426,7 @@ class CrawlComponent extends Component implements CrawlConstants
                         $query), "");
                     return $parent->redirectWithMessage(
                         tl('crawl_component_results_editor_page_saved'),
-                        ["ID", "QUERY", "KWIKI_PAGE", "MODE"]);
+                        ["ID", "QUERY", "KWIKI_PAGE", "MODE", "SEARCH"]);
                     break;
                 case "savequerymap":
                     if (empty($map_query)) {
@@ -2441,7 +2441,7 @@ class CrawlComponent extends Component implements CrawlConstants
                     $_REQUEST['MAP_URLS'] = $data['MAP_URLS'];
                     return $parent->redirectWithMessage(
                         tl('crawl_component_results_editor_query_map_saved'),
-                        ["MAP_QUERY", "MAP_URLS", "MODE"]);
+                        ["MAP_QUERY", "MAP_URLS", "MODE", "URL"]);
                     break;
                 case "saveurl":
                     $missing_page_field = ($data["URL"] == "") ? true: false;
@@ -2458,7 +2458,7 @@ class CrawlComponent extends Component implements CrawlConstants
                     return $parent->redirectWithMessage(
                         tl('crawl_component_results_editor_page_updated'),
                         ["ID", "URL_ACTION", "URL", "TITLE",
-                        "DESCRIPTION", "MODE"]);
+                        "DESCRIPTION", "MODE", 'MAP_QUERY']);
                     break;
             }
         }
@@ -2469,6 +2469,8 @@ class CrawlComponent extends Component implements CrawlConstants
             if ($data['MODE'] == 'editkwiki') {
                 $this->initializeWikiEditor($data, "kwiki-page");
             }
+            $data["SEARCH"] = (!empty($_REQUEST["SEARCH"]) &&
+                $_REQUEST["SEARCH"] == "true") ? true : false;
             $data['QUERY'] = $query;
             $data['KWIKI_PAGE'] = html_entity_decode($kwiki_page);
             $data['knowledge_wiki_active'] = "active";
@@ -2482,12 +2484,21 @@ class CrawlComponent extends Component implements CrawlConstants
             $data['query_map_active'] = "active";
             $data['MODE'] = $_REQUEST['MODE'];
             $data['MAP_QUERY'] = $map_query;
+            if (!empty($data['URL'])) {
+                $data['BACK_QUERY'] = $map_query;
+                if (!stristr($data['MAP_URLS'], $data['URL'])) {
+                    $data['MAP_URLS'] .= $data['URL'];
+                }
+            }
             $data['edit_result_active'] = "";
             $data['SCRIPT'] .= "switchTab('querymaptab', ['editresulttab',".
                 "'knowledgetab']);";
         } else {
             $data['MODE'] = (!empty($_REQUEST['MODE']) &&
                 $_REQUEST['MODE'] == 'editurl') ? 'editurl' : 'loadurl';
+            if (!empty($map_query)) {
+                $data['BACK_QUERY'] = $map_query;
+            }
             $data['knowledge_wiki_active'] = "";
             $data['edit_result_active'] = "active";
             $data['query_map_active'] = "";
diff --git a/src/css/search.css b/src/css/search.css
index 108681eca..66ce64bde 100755
--- a/src/css/search.css
+++ b/src/css/search.css
@@ -2096,6 +2096,18 @@ span[aria-label]:hover:after
 {
     width:inherit;
 }
+.edit-search-result
+{
+    position: relative;
+    top: 7px;
+}
+.edit-search-result ul > li:first-child
+{
+    border-color: lightgray !important;
+    color: gray !important;
+    height: 20px;
+    padding: 0 5px 4px 5px;
+}
 .html-ltr .search-stats
 {
     color: #666;
diff --git a/src/locale/ar/configure.ini b/src/locale/ar/configure.ini
index 57d12c52a..273e0fb56 100755
--- a/src/locale/ar/configure.ini
+++ b/src/locale/ar/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s ثانية."
 search_element_results = "عرض %s - %s %s"
 search_element_num_results = "(%s النتائج)"
 search_element_no_results = "لا توجد نتائج. الرجاء محاولة البحث المختلفة."
+search_element_edit_result = "تحرير النتيجة"
+search_element_edit_rank = "تحرير الرتبة"
 search_element_possible_answer = "إجابة ممكنة:"
 search_element_word_cloud = "الكلمات:"
 search_element_cache = "مؤقتا"
diff --git a/src/locale/bn/configure.ini b/src/locale/bn/configure.ini
index e026924d5..3827d15bf 100755
--- a/src/locale/bn/configure.ini
+++ b/src/locale/bn/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s seconds."
 search_element_results = "দেখানো %s - %s এর %s"
 search_element_num_results = "(%s ফলাফল)"
 search_element_no_results = "কোন ফলাফল পাওয়া যায় নি. চেষ্টা করুন, একটি ভিন্ন অনুসন্ধান."
+search_element_edit_result = "ফলাফল সম্পাদন করুন"
+search_element_edit_rank = "র্যাঙ্ক সম্পাদনা করুন"
 search_element_possible_answer = "সম্ভাব্য উত্তর:"
 search_element_word_cloud = "শব্দ:"
 search_element_cache = "ক্যাশে"
diff --git a/src/locale/de/configure.ini b/src/locale/de/configure.ini
index 3e799fee6..dd2ae4c19 100755
--- a/src/locale/de/configure.ini
+++ b/src/locale/de/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s Sekunden."
 search_element_results = "Zeigt %s - %s von %s"
 search_element_num_results = "(%s Suchergebnissen)"
 search_element_no_results = "Keine Ergebnisse gefunden. Bitte versuchen Sie eine andere Suche."
+search_element_edit_result = "Ergebnis bearbeiten"
+search_element_edit_rank = "Rang bearbeiten"
 search_element_possible_answer = "Mögliche Antwort:"
 search_element_word_cloud = "Worte:"
 search_element_cache = "Cache"
diff --git a/src/locale/el_GR/configure.ini b/src/locale/el_GR/configure.ini
index a78fb155e..67b09f6b2 100644
--- a/src/locale/el_GR/configure.ini
+++ b/src/locale/el_GR/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s δευτερόλεπτα."
 search_element_results = "Εμφανίζονται %s - %s από %s"
 search_element_num_results = "(%s Results)"
 search_element_no_results = "Δεν βρέθηκαν αποτελέσματα. Δοκιμάστε διαφορετική αναζήτηση."
+search_element_edit_result = "Επεξεργασία Αποτελέσματος"
+search_element_edit_rank = "Επεξεργασία Κατάταξης"
 search_element_possible_answer = "Δυνατή απάντηση:"
 search_element_word_cloud = "Λέξεις:"
 search_element_cache = "Προσωρινά αποθηκευμένο"
diff --git a/src/locale/en_US/configure.ini b/src/locale/en_US/configure.ini
index d6aa946e1..5d5c664db 100644
--- a/src/locale/en_US/configure.ini
+++ b/src/locale/en_US/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s seconds."
 search_element_results = "Showing %s - %s of %s"
 search_element_num_results = "(%s Results)"
 search_element_no_results = "No results found. Please try a different search."
+search_element_edit_result = "Edit Result"
+search_element_edit_rank = "Edit Rank"
 search_element_possible_answer = "Possible Answer:"
 search_element_word_cloud = "Words:"
 search_element_cache = "Cached"
diff --git a/src/locale/es/configure.ini b/src/locale/es/configure.ini
index 412c4270f..4bf303feb 100755
--- a/src/locale/es/configure.ini
+++ b/src/locale/es/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s segundos."
 search_element_results = "Muestra de %s %s %s"
 search_element_num_results = "(%s Resultados)"
 search_element_no_results = "No se encontraron resultados. Por favor, intente una búsqueda diferente."
+search_element_edit_result = "Editar Resultado"
+search_element_edit_rank = "Editar Rango"
 search_element_possible_answer = "Posible Respuesta:"
 search_element_word_cloud = "Palabras:"
 search_element_cache = "En caché"
diff --git a/src/locale/fa/configure.ini b/src/locale/fa/configure.ini
index 3b14fc731..35ae26570 100755
--- a/src/locale/fa/configure.ini
+++ b/src/locale/fa/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s ثانیه است."
 search_element_results = "نشان %s - %s %s"
 search_element_num_results = "(%s نتایج)"
 search_element_no_results = "هیچ نتیجه ای یافت می شود. لطفا سعی کنید یک جستجوی مختلف."
+search_element_edit_result = "ویرایش نتیجه"
+search_element_edit_rank = "ویرایش رتبه"
 search_element_possible_answer = "ممکن است پاسخ:"
 search_element_word_cloud = "کلمات:"
 search_element_cache = "کش"
diff --git a/src/locale/fr_FR/configure.ini b/src/locale/fr_FR/configure.ini
index 7ba8cabf2..4cf1131ab 100755
--- a/src/locale/fr_FR/configure.ini
+++ b/src/locale/fr_FR/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s secondes."
 search_element_results = "Montrant à %s %s %s"
 search_element_num_results = "(%s résultats)"
 search_element_no_results = "Aucun résultat trouvé. S'il vous plaît essayer une autre recherche."
+search_element_edit_result = "Modifier le Résultat"
+search_element_edit_rank = "Modifier le Rang"
 search_element_possible_answer = "Réponse possible:"
 search_element_word_cloud = "Mots:"
 search_element_cache = "Mis en cache"
diff --git a/src/locale/he/configure.ini b/src/locale/he/configure.ini
index 009a7f617..c85cdd4da 100755
--- a/src/locale/he/configure.ini
+++ b/src/locale/he/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s שניות."
 search_element_results = "מראה %s - %s %s"
 search_element_num_results = "(%s תוצאות)"
 search_element_no_results = "לא נמצאו תוצאות. אנא נסו חיפוש אחר."
+search_element_edit_result = "ערוך תוצאה"
+search_element_edit_rank = "ערוך דרגה"
 search_element_possible_answer = "תשובה אפשרית:"
 search_element_word_cloud = "מילים:"
 search_element_cache = "במטמון"
diff --git a/src/locale/hi/configure.ini b/src/locale/hi/configure.ini
index 9fd3a1072..9c53e9e4b 100755
--- a/src/locale/hi/configure.ini
+++ b/src/locale/hi/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s सेकंड."
 search_element_results = "दिखा %s - %s के %s"
 search_element_num_results = "(%s परिणाम)"
 search_element_no_results = "कोई परिणाम नहीं मिला. कृपया एक अलग खोज की कोशिश."
+search_element_edit_result = "परिणाम संपादित करें"
+search_element_edit_rank = "रैंक संपादित करें"
 search_element_possible_answer = "संभव जवाब:"
 search_element_word_cloud = "शब्द:"
 search_element_cache = "कैश्ड"
diff --git a/src/locale/id/configure.ini b/src/locale/id/configure.ini
index 2d1fb24db..d549c368b 100755
--- a/src/locale/id/configure.ini
+++ b/src/locale/id/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s detik."
 search_element_results = "Menampilkan %s - %s %s"
 search_element_num_results = "(%s Hasil)"
 search_element_no_results = "Tidak ada hasil ditemukan. Silakan coba pencarian yang berbeda."
+search_element_edit_result = "Edit Hasil"
+search_element_edit_rank = "Edit Peringkat"
 search_element_possible_answer = "Jawaban Yang Mungkin:"
 search_element_word_cloud = "Kata-kata:"
 search_element_cache = "Cache"
diff --git a/src/locale/it/configure.ini b/src/locale/it/configure.ini
index 72f9244c7..35e9a99f7 100755
--- a/src/locale/it/configure.ini
+++ b/src/locale/it/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s secondi."
 search_element_results = "Mostra %s - %s di %s"
 search_element_num_results = "(%s Risultati)"
 search_element_no_results = "Nessun risultato trovato. Si prega di provare una ricerca diversa."
+search_element_edit_result = "Modifica risultato"
+search_element_edit_rank = "Modifica Rango"
 search_element_possible_answer = "Possibile Risposta:"
 search_element_word_cloud = "Parole:"
 search_element_cache = "Cache"
diff --git a/src/locale/ja/configure.ini b/src/locale/ja/configure.ini
index b65b0bf19..629b2e964 100755
--- a/src/locale/ja/configure.ini
+++ b/src/locale/ja/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s秒です。"
 search_element_results = "図%s-%s %s"
 search_element_num_results = "(%s結果)"
 search_element_no_results = "な結果に見られる。 てみてください別の検索します。"
+search_element_edit_result = "結果の編集"
+search_element_edit_rank = "編集ランク"
 search_element_possible_answer = "を可能に答え:"
 search_element_word_cloud = "言葉"
 search_element_cache = "キャッシュ"
diff --git a/src/locale/kn/configure.ini b/src/locale/kn/configure.ini
index 15ad19564..0116bd56e 100755
--- a/src/locale/kn/configure.ini
+++ b/src/locale/kn/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s ಸೆಕೆಂಡುಗಳ."
 search_element_results = "ತೋರಿಸಲಾಗುತ್ತಿದೆ %s - %s %s"
 search_element_num_results = "(%s ಫಲಿತಾಂಶಗಳು)"
 search_element_no_results = "ಯಾವುದೇ ಫಲಿತಾಂಶಗಳು ಕಂಡುಬಂದಿಲ್ಲ. Please try a different ಹುಡುಕಾಟ."
+search_element_edit_result = "ಫಲಿತಾಂಶವನ್ನು ಸಂಪಾದಿಸು"
+search_element_edit_rank = "ಸಂಪಾದಿಸು ಶ್ರೇಣಿ"
 search_element_possible_answer = "ಸಾಧ್ಯವಾದಷ್ಟು ಉತ್ತರ:"
 search_element_word_cloud = "ಪದಗಳನ್ನು:"
 search_element_cache = "ಸಂಗ್ರಹ"
diff --git a/src/locale/ko/configure.ini b/src/locale/ko/configure.ini
index fa025a708..884307d50 100755
--- a/src/locale/ko/configure.ini
+++ b/src/locale/ko/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s 초입니다."
 search_element_results = "주의 %s %s %s"
 search_element_num_results = "(%s 결과)"
 search_element_no_results = "결과를 찾을 수 없습니다. 보십시오른 검색합니다."
+search_element_edit_result = "결과 편집"
+search_element_edit_rank = "순위 편집"
 search_element_possible_answer = "가능한 응답:"
 search_element_word_cloud = "어:"
 search_element_cache = "캐시"
diff --git a/src/locale/nl/configure.ini b/src/locale/nl/configure.ini
index a9b04e247..03a0215da 100644
--- a/src/locale/nl/configure.ini
+++ b/src/locale/nl/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s seconden."
 search_element_results = "Het tonen van %s %s %s"
 search_element_num_results = "(%s Resultaten)"
 search_element_no_results = "Geen resultaten gevonden. Probeer een andere zoekopdracht."
+search_element_edit_result = "Resultaat Bewerken"
+search_element_edit_rank = "Rang Bewerken"
 search_element_possible_answer = "Mogelijk Antwoord:"
 search_element_word_cloud = "Woorden:"
 search_element_cache = "Cache"
diff --git a/src/locale/pl/configure.ini b/src/locale/pl/configure.ini
index 85c2123cd..52bc40539 100755
--- a/src/locale/pl/configure.ini
+++ b/src/locale/pl/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s sekund."
 search_element_results = "Wyświetlono %s - %s z %s"
 search_element_num_results = "(%s wyników)"
 search_element_no_results = "Nie znaleziono wyników. Spróbuj na innym wyszukiwanie."
+search_element_edit_result = "Edytuj Wynik"
+search_element_edit_rank = "Edytuj Rangę"
 search_element_possible_answer = "Możliwe Odpowiedzi:"
 search_element_word_cloud = "Słowa:"
 search_element_cache = "Buforowane"
diff --git a/src/locale/pt/configure.ini b/src/locale/pt/configure.ini
index 7a6f1dee1..091cd22b0 100755
--- a/src/locale/pt/configure.ini
+++ b/src/locale/pt/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s segundos."
 search_element_results = "Mostrando de %s %s %s"
 search_element_num_results = "(%s Resultados)"
 search_element_no_results = "Nenhum resultado encontrado. Por favor, tente uma pesquisa diferente."
+search_element_edit_result = "Editar Resultado"
+search_element_edit_rank = "Editar Classificação"
 search_element_possible_answer = "Possível Resposta:"
 search_element_word_cloud = "Palavras:"
 search_element_cache = "Em cache"
diff --git a/src/locale/ru/configure.ini b/src/locale/ru/configure.ini
index 0da9ab8bc..7bbfd2ab2 100755
--- a/src/locale/ru/configure.ini
+++ b/src/locale/ru/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s секунд."
 search_element_results = "Показаны %s - %s из %s"
 search_element_num_results = "(%s результатов)"
 search_element_no_results = "Результатов не найдено. Пожалуйста, попробуйте другой поиск."
+search_element_edit_result = "Редактировать результат"
+search_element_edit_rank = "Редактировать Ранг"
 search_element_possible_answer = "Возможный Ответ:"
 search_element_word_cloud = "Слова:"
 search_element_cache = "Кэшированные"
diff --git a/src/locale/te/configure.ini b/src/locale/te/configure.ini
index 06c85054b..5d3bdcaf1 100644
--- a/src/locale/te/configure.ini
+++ b/src/locale/te/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s సెకన్లు."
 search_element_results = "Showing %s - %s %s"
 search_element_num_results = "(%s ఫలితాలు)"
 search_element_no_results = "ఏ ఫలితాలు దొరకలేదు. Please try a different search."
+search_element_edit_result = "ఫలితం సవరించండి"
+search_element_edit_rank = "రంక్ సవరించు"
 search_element_possible_answer = "సాధ్యం సమాధానం:"
 search_element_word_cloud = "పదాలు:"
 search_element_cache = "కాష్"
diff --git a/src/locale/th/configure.ini b/src/locale/th/configure.ini
index f0f407df1..ce2e0b006 100755
--- a/src/locale/th/configure.ini
+++ b/src/locale/th/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " ทั้งหมด %s วินาที"
 search_element_results = "แสดงทั้งหมด %s-ทั้งหมด %s ของทั้งหมด %s"
 search_element_num_results = "(ทั้งหมด %s ผล)"
 search_element_no_results = "ไม่พบผลลัพธ์ใดๆ ได้โปรดลองต่างออกค้นหา"
+search_element_edit_result = "แก้ไขผลลัพธ์"
+search_element_edit_rank = "แก้ไขลำดับ"
 search_element_possible_answer = "เป็นไปได้คำตอบ:"
 search_element_word_cloud = "จำนวนคำ:"
 search_element_cache = "แคชข้อมูล"
diff --git a/src/locale/tl/configure.ini b/src/locale/tl/configure.ini
index 1849e4565..967767c05 100644
--- a/src/locale/tl/configure.ini
+++ b/src/locale/tl/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s segundo."
 search_element_results = "Ipinapakita ang %s - %s ng %s"
 search_element_num_results = "(%s mga Resulta)"
 search_element_no_results = "Walang natagpuang mga resulta. Mangyaring subukan ang isang iba ' t ibang mga paghahanap."
+search_element_edit_result = "I-Edit Ang Resulta"
+search_element_edit_rank = "I-Edit Ang Ranggo"
 search_element_possible_answer = "Posibleng Sagot:"
 search_element_word_cloud = "Mga salita:"
 search_element_cache = "Naka-cache na"
diff --git a/src/locale/tr/configure.ini b/src/locale/tr/configure.ini
index 19839537b..b917a5b8b 100755
--- a/src/locale/tr/configure.ini
+++ b/src/locale/tr/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s saniye."
 search_element_results = "%s %s gösterme - %s "
 search_element_num_results = "(%s Sonuç)"
 search_element_no_results = "Hiç Sonuç bulunamadı. Farklı bir arama deneyin lütfen."
+search_element_edit_result = "Sonucu Düzenle"
+search_element_edit_rank = "Sıralamayı Düzenle"
 search_element_possible_answer = "Olası Cevap:"
 search_element_word_cloud = "Sözleri:"
 search_element_cache = "Önbelleğe"
diff --git a/src/locale/vi_VN/configure.ini b/src/locale/vi_VN/configure.ini
index 4ce08aa5b..3dcecdca6 100755
--- a/src/locale/vi_VN/configure.ini
+++ b/src/locale/vi_VN/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s giây."
 search_element_results = "Hiển thị %s - %s của %s"
 search_element_num_results = "(%s kết Quả)"
 search_element_no_results = "Không tìm thấy kết quả. Hãy cố gắng một tìm kiếm khác nhau."
+search_element_edit_result = "Chỉnh Sửa Kết Quả"
+search_element_edit_rank = "Chỉnh Sửa Bậc"
 search_element_possible_answer = "Có Thể Có Câu Trả Lời:"
 search_element_word_cloud = "Lời:"
 search_element_cache = "Lưu trữ"
diff --git a/src/locale/vi_VN/statistics.txt b/src/locale/vi_VN/statistics.txt
index b6bef56f0..5a165df53 100755
--- a/src/locale/vi_VN/statistics.txt
+++ b/src/locale/vi_VN/statistics.txt
@@ -1 +1 @@
-d:99;
\ No newline at end of file
+d:100;
\ No newline at end of file
diff --git a/src/locale/zh_CN/configure.ini b/src/locale/zh_CN/configure.ini
index 10382a527..6b7bc7a11 100755
--- a/src/locale/zh_CN/configure.ini
+++ b/src/locale/zh_CN/configure.ini
@@ -1620,6 +1620,8 @@ search_element_calculated = " %s秒钟。"
 search_element_results = "表示%s-%s %s"
 search_element_num_results = "(%s结果)"
 search_element_no_results = "没有找到结果。 请尝试不同的搜索。"
+search_element_edit_result = "编辑结果"
+search_element_edit_rank = "编辑等级"
 search_element_possible_answer = "可能的答案:"
 search_element_word_cloud = "话说:"
 search_element_cache = "缓存"
diff --git a/src/models/SearchverticalsModel.php b/src/models/SearchverticalsModel.php
index 99bb5c617..6f15b21e2 100644
--- a/src/models/SearchverticalsModel.php
+++ b/src/models/SearchverticalsModel.php
@@ -155,6 +155,7 @@ class SearchverticalsModel extends GroupModel
     public function hashIntPair($input, $compute_hash = true)
     {
         if ($compute_hash) {
+            $input = rtrim($input, "/");
             $hash = substr(L\crawlHash($input . "/", true), 1);
         } else {
             $hash = $input;
diff --git a/src/views/elements/ResultseditorElement.php b/src/views/elements/ResultseditorElement.php
index a51cbb380..eff89c2da 100644
--- a/src/views/elements/ResultseditorElement.php
+++ b/src/views/elements/ResultseditorElement.php
@@ -141,13 +141,18 @@ class ResultsEditorElement extends Element
                 for="descriptionfield"><b><?=
                 tl('resultseditor_element_description') ?></b></label></div>
             <textarea class="tall-text-area" id="descriptionfield"
-                name="DESCRIPTION" ><?=$data['DESCRIPTION'] ?></textarea>
-            <div class="center slight-pad"><button class="button-box"
-                formaction="<?=$admin_url ?>a=resultsEditor&amp;<?=
-                    C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
-                    ?>" ><?=
+                name="DESCRIPTION" ><?=$data['DESCRIPTION'] ?></textarea><?php
+            if (empty($data['BACK_QUERY'])) {
+                $back_url = $admin_url . "a=resultsEditor&amp;" . C\CSRF_TOKEN .
+                    "=" .  $data[C\CSRF_TOKEN];
+            } else {
+                $back_url = C\BASE_URL . "?q=" . $data['BACK_QUERY'] . "&amp;" .
+                    C\CSRF_TOKEN . "=" .  $data[C\CSRF_TOKEN];
+            }
+            ?><div class="center slight-pad"><a class="source-anchor-button"
+                href="<?= $back_url ?>" ><?=
                     tl('resultseditor_element_back')
-                ?></button> &nbsp;&nbsp; <button class="button-box"
+                ?></a> &nbsp;&nbsp; <button class="button-box"
                 type="submit" name='arg' value='saveurl'><?=
                 tl('resultseditor_element_save') ?></button></div><?php
         }?>
@@ -184,13 +189,18 @@ class ResultsEditorElement extends Element
                 ?></b></label></div>
             <textarea class="tall-text-area" id="querymap-urls"
                 name="MAP_URLS"  ><?= $data['MAP_URLS']
-            ?></textarea>
-            <div class="center slight-pad"><button class="button-box"
-                formaction="<?=$admin_url ?>a=resultsEditor&amp;<?=
-                    C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
-                    ?>&amp;MODE=loadquerymap" ><?=
+            ?></textarea><?php
+            if (empty($data['BACK_QUERY'])) {
+                $back_url = $admin_url . "a=resultsEditor&amp;" . C\CSRF_TOKEN .
+                    "=" .  $data[C\CSRF_TOKEN] . "&amp;MODE=loadquerymap";
+            } else {
+                $back_url = C\BASE_URL . "?q=" . $data['BACK_QUERY'] . "&amp;" .
+                    C\CSRF_TOKEN . "=" .  $data[C\CSRF_TOKEN];
+            } ?>
+            <div class="center slight-pad"><a class="source-anchor-button"
+                href="<?=$back_url ?>" ><?=
                     tl('resultseditor_element_back')
-                ?></button> &nbsp;&nbsp; <button class="button-box"
+                ?></a> &nbsp;&nbsp; <button class="button-box"
                 name='arg' value='savequerymap'
                 type="submit"><?= tl('resultseditor_element_save')
                 ?></button></div><?php
@@ -230,15 +240,20 @@ class ResultsEditorElement extends Element
                 !wikibtn-search' ><?=
                 $data['KWIKI_PAGE']
             ?></textarea>
-            <div class="center slight-pad"><button class="button-box"
-                formaction="<?=$admin_url ?>a=resultsEditor&amp;<?=
-                    C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
-                    ?>&amp;MODE=loadkwiki" ><?=
-                    tl('resultseditor_element_back')
-                ?></button> &nbsp;&nbsp; <button class="button-box"
-                name='arg' value='savekwiki'
-                type="submit"><?= tl('resultseditor_element_save')
-                ?></button></div><?php
+            <div class="center slight-pad"><?php
+            if (empty($data['SEARCH'])) {
+                $back_url = $admin_url . "a=resultsEditor&amp;" . C\CSRF_TOKEN .
+                    "=" .  $data[C\CSRF_TOKEN] . "&amp;MODE=loadkwiki";
+            } else {
+                $back_url = C\BASE_URL . "?q=" . $data['QUERY'] . "&amp;" .
+                    C\CSRF_TOKEN . "=" .  $data[C\CSRF_TOKEN];
+            } ?>
+            <a class="source-anchor-button" href="<?=$back_url ?>" ><?=
+                tl('resultseditor_element_back')
+            ?></a> &nbsp;&nbsp; <button class="button-box"
+            name='arg' value='savekwiki'
+            type="submit"><?= tl('resultseditor_element_save')
+            ?></button></div><?php
         }?>
         </form>
         </div>
diff --git a/src/views/elements/SearchElement.php b/src/views/elements/SearchElement.php
index 21743e387..1cbe32553 100644
--- a/src/views/elements/SearchElement.php
+++ b/src/views/elements/SearchElement.php
@@ -112,6 +112,7 @@ class SearchElement extends Element implements CrawlConstants
             C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN]."&amp;" : "";
         $is_search_view = (get_class($this->view) == C\NS_VIEWS .
             "SearchView");
+        $can_edit_results = !empty($data['CAN_EDIT_RESULTS']);
         if ($is_search_view) {
             if (!empty($data['PAGES']) && !$_SERVER["MOBILE"]) {
                 ?><h2 class="search-stats"><?php
@@ -237,8 +238,25 @@ class SearchElement extends Element implements CrawlConstants
             if (C\nsdefined('MORE_RESULT') && C\MORE_RESULT) { ?>
                 <span class="result-more"
                     onclick="toggleDisplay('result-extras-<?=$item_cnt ?>')"
-                    tabindex="0">&bull;&bull;&bull;</span>
-                <div id="result-extras-<?=$item_cnt?>" class="result-extras"><?php
+                    tabindex="0">&bull;&bull;&bull;</span><?php
+            }
+            if ($can_edit_results) {
+                $admin_prefix = B\controllerUrl("admin", true) .
+                    $token_string . "a=resultsEditor&amp;URL=" .
+                    urlencode($url) . "&amp;MAP_QUERY=" . $data['QUERY'] .
+                    "&amp;";
+                $edit_result_suffix = "MODE=editurl&amp;arg=loadurl";
+                $edit_rank_suffix = "MODE=editquerymap&amp;arg=loadquerymap";
+                $this->view->helper("options")->renderLinkDropDown(
+                    "edit-result-$item_cnt",
+                    [$edit_result_suffix => tl('search_element_edit_result'),
+                     $edit_rank_suffix => tl('search_element_edit_rank')],
+                    "", "$admin_prefix", false,
+                    "edit-search-result", "⚙");
+            }
+            if (C\nsdefined('MORE_RESULT') && C\MORE_RESULT) { ?>
+                <div id="result-extras-<?=$item_cnt
+                ?>" class="result-extras"><?php
                 if (!$_SERVER["MOBILE"] && isset($page[self::WORD_CLOUD]) &&
                     is_array($page[self::WORD_CLOUD])) { ?>
                     <p>
diff --git a/src/views/elements/SearchcalloutElement.php b/src/views/elements/SearchcalloutElement.php
index 0ef897d9c..574c4c731 100644
--- a/src/views/elements/SearchcalloutElement.php
+++ b/src/views/elements/SearchcalloutElement.php
@@ -46,20 +46,20 @@ class SearchcalloutElement extends Element
     public function render($data)
     {
         $logged_in = isset($data["ADMIN"]) && $data["ADMIN"];
-        $belongs_search_group = !empty($data["SEARCH_GROUP_MEMBER"]);
+        $can_edit_results = !empty($data["CAN_EDIT_RESULTS"]);
         $token_string = ($logged_in) ? C\CSRF_TOKEN ."=". $data[C\CSRF_TOKEN] :
             "";
         if (!empty($data['SEARCH_CALLOUT']) ||
-            ($belongs_search_group && $logged_in &&
+            ($can_edit_results && $logged_in &&
             empty($data["IS_LANDING"]))) { ?>
             <div class="search-callout"><?php
-            if ($logged_in && $belongs_search_group) {
-                $edit_url = B\wikiUrl(preg_replace("/-|\s/u", "_",
-                    mb_strtolower($data['QUERY'])), true, "group",
-                    C\SEARCH_GROUP_ID) .
-                    $token_string . "&amp;noredirect=true&amp;arg=edit";
-                $this->view->helper("iconlink")->renderButton($edit_url, "edit",
-                    false, "float-opposite", "", false, "_blank");
+            $load_kwiki = B\controllerUrl("admin", true) .
+                $token_string . "&amp;a=resultsEditor&amp;QUERY=" .
+                ($data['QUERY'] ?? "") . "&amp;arg=loadkwiki" .
+                "&amp;MODE=loadkwiki&amp;SEARCH=true";
+            if ($logged_in && $can_edit_results) {
+                $this->view->helper("iconlink")->renderButton($load_kwiki,
+                    "edit", false, "float-opposite", "", false);
             }
             ?><?=$data['SEARCH_CALLOUT'] ?>
             </div>
ViewGit