forked from Ponysearch/Ponysearch
[mod] oscar: /preferences , engines tab: report engine times
* display the median time instead of the average. * add a "Reliability" column (sum up the metrics and the checker results). * the "selected language", "SafeSearch", "Time range" values are displayed as "broken" when the checker tests fail.
This commit is contained in:
parent
c27fef1cde
commit
7cfd8d900a
34 changed files with 849 additions and 60 deletions
|
@ -20,7 +20,6 @@ import searx.settings_loader
|
|||
from os import environ
|
||||
from os.path import realpath, dirname, join, abspath, isfile
|
||||
|
||||
|
||||
searx_dir = abspath(dirname(__file__))
|
||||
engine_dir = dirname(realpath(__file__))
|
||||
static_path = abspath(join(dirname(__file__), 'static'))
|
||||
|
|
|
@ -5,6 +5,7 @@ import types
|
|||
import functools
|
||||
import itertools
|
||||
from time import time
|
||||
from timeit import default_timer
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import re
|
||||
|
@ -386,7 +387,7 @@ class Checker:
|
|||
params = self.processor.get_params(search_query, engineref_category)
|
||||
if params is not None:
|
||||
counter_inc('engine', search_query.engineref_list[0].name, 'search', 'count', 'sent')
|
||||
self.processor.search(search_query.query, params, result_container, time(), 5)
|
||||
self.processor.search(search_query.query, params, result_container, default_timer(), 5)
|
||||
return result_container
|
||||
|
||||
def get_result_container_tests(self, test_name: str, search_query: SearchQuery) -> ResultContainerTests:
|
||||
|
|
|
@ -923,12 +923,78 @@ input.cursor-text {
|
|||
padding: 0.5rem 1rem;
|
||||
margin: 0rem 0 0 2rem;
|
||||
border: 1px solid #ddd;
|
||||
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.1);
|
||||
background: white;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
}
|
||||
td:hover .engine-tooltip,
|
||||
th:hover .engine-tooltip,
|
||||
.engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
/* stacked-bar-chart */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 3rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
.stacked-bar-chart-base {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
.stacked-bar-chart-median {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: #000000;
|
||||
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate80 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate95 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, 0.5);
|
||||
padding: 0;
|
||||
}
|
||||
.stacked-bar-chart-rate100 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -896,15 +896,81 @@ input.cursor-text {
|
|||
padding: 0.5rem 1rem;
|
||||
margin: 0rem 0 0 2rem;
|
||||
border: 1px solid #ddd;
|
||||
box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.1);
|
||||
background: white;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
}
|
||||
td:hover .engine-tooltip,
|
||||
th:hover .engine-tooltip,
|
||||
.engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
/* stacked-bar-chart */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 3rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
.stacked-bar-chart-base {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
.stacked-bar-chart-median {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: #d5d8d7;
|
||||
border: 1px solid rgba(213, 216, 215, 0.9);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate80 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(213, 216, 215, 0.3);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate95 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted rgba(213, 216, 215, 0.5);
|
||||
padding: 0;
|
||||
}
|
||||
.stacked-bar-chart-rate100 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-left: 1px solid rgba(213, 216, 215, 0.9);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
/*Global*/
|
||||
body {
|
||||
background: #1d1f21 none !important;
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -688,6 +688,71 @@ input[type=checkbox]:not(:checked) + .label_hide_if_checked + .label_hide_if_not
|
|||
z-index: 1000000;
|
||||
}
|
||||
th:hover .engine-tooltip,
|
||||
td:hover .engine-tooltip,
|
||||
.engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
/* stacked-bar-chart */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 3rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
.stacked-bar-chart-base {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
.stacked-bar-chart-median {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: #000000;
|
||||
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate80 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate95 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, 0.5);
|
||||
padding: 0;
|
||||
}
|
||||
.stacked-bar-chart-rate100 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
searx/static/themes/oscar/js/searx.min.js
vendored
2
searx/static/themes/oscar/js/searx.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,7 @@
|
|||
@import "../logicodev/variables.less";
|
||||
|
||||
@stacked-bar-chart: rgb(213, 216, 215, 1);
|
||||
|
||||
@import "../logicodev/footer.less";
|
||||
@import "../logicodev/checkbox.less";
|
||||
@import "../logicodev/onoff.less";
|
||||
|
|
|
@ -20,12 +20,72 @@ input.cursor-text {
|
|||
padding: 0.5rem 1rem;
|
||||
margin: 0rem 0 0 2rem;
|
||||
border: 1px solid #ddd;
|
||||
box-shadow: 2px 2px 2px 0px rgba(0,0,0,0.1);
|
||||
background: white;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
}
|
||||
|
||||
th:hover .engine-tooltip, .engine-tooltip:hover {
|
||||
td:hover .engine-tooltip, th:hover .engine-tooltip, .engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* stacked-bar-chart */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 3rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-base {
|
||||
display:flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-median {
|
||||
.stacked-bar-chart-base();
|
||||
background: @stacked-bar-chart;
|
||||
border: 1px solid fade(@stacked-bar-chart, 90%);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate80 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border: 1px solid fade(@stacked-bar-chart, 30%);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate95 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted fade(@stacked-bar-chart, 50%);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate100 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border-left: 1px solid fade(@stacked-bar-chart, 90%);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
|
|
@ -14,3 +14,5 @@
|
|||
@light-green: #01D7D4;
|
||||
@orange: #FFA92F;
|
||||
@dark-red: #c9432f;
|
||||
|
||||
@stacked-bar-chart: rgb(0, 0, 0);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import "variables.less";
|
||||
|
||||
@import "footer.less";
|
||||
|
||||
@import "checkbox.less";
|
||||
|
|
|
@ -14,6 +14,66 @@
|
|||
z-index: 1000000;
|
||||
}
|
||||
|
||||
th:hover .engine-tooltip, .engine-tooltip:hover {
|
||||
th:hover .engine-tooltip, td:hover .engine-tooltip, .engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* stacked-bar-chart */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 3rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-base {
|
||||
display:flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-median {
|
||||
.stacked-bar-chart-base();
|
||||
background: @stacked-bar-chart;
|
||||
border: 1px solid fade(@stacked-bar-chart, 90%);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate80 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border: 1px solid fade(@stacked-bar-chart, 30%);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate95 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted fade(@stacked-bar-chart, 50%);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate100 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border-left: 1px solid fade(@stacked-bar-chart, 90%);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@stacked-bar-chart: rgb(0, 0, 0);
|
|
@ -1,4 +1,4 @@
|
|||
/*! searx | 23-03-2021 | */
|
||||
/*! searx | 21-04-2021 | */
|
||||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*
|
||||
|
@ -692,6 +692,12 @@ html.js .show_if_nojs {
|
|||
.danger {
|
||||
background-color: #fae1e1;
|
||||
}
|
||||
.warning {
|
||||
background: #faf5e1;
|
||||
}
|
||||
.success {
|
||||
background: #e3fae1;
|
||||
}
|
||||
.badge {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
|
@ -1147,6 +1153,69 @@ select:focus {
|
|||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* -- stacked bar chart -- */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 4rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
.stacked-bar-chart-base {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
.stacked-bar-chart-median {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: #000000;
|
||||
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate80 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate95 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, 0.5);
|
||||
padding: 0;
|
||||
}
|
||||
.stacked-bar-chart-rate100 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
/*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */
|
||||
.autocomplete {
|
||||
position: absolute;
|
||||
|
@ -1435,8 +1504,10 @@ select:focus {
|
|||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
text-align: left;
|
||||
}
|
||||
#main_preferences th:hover .engine-tooltip,
|
||||
#main_preferences td:hover .engine-tooltip,
|
||||
#main_preferences .engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
/*! searx | 23-03-2021 | */
|
||||
/*! searx | 21-04-2021 | */
|
||||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*
|
||||
|
@ -692,6 +692,12 @@ html.js .show_if_nojs {
|
|||
.danger {
|
||||
background-color: #fae1e1;
|
||||
}
|
||||
.warning {
|
||||
background: #faf5e1;
|
||||
}
|
||||
.success {
|
||||
background: #e3fae1;
|
||||
}
|
||||
.badge {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
|
@ -1147,6 +1153,69 @@ select:focus {
|
|||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* -- stacked bar chart -- */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 4rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
.stacked-bar-chart-base {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
.stacked-bar-chart-median {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: #000000;
|
||||
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate80 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
.stacked-bar-chart-rate95 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, 0.5);
|
||||
padding: 0;
|
||||
}
|
||||
.stacked-bar-chart-rate100 {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
background: transparent;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.9);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
/*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */
|
||||
.autocomplete {
|
||||
position: absolute;
|
||||
|
@ -1435,8 +1504,10 @@ select:focus {
|
|||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
text-align: left;
|
||||
}
|
||||
#main_preferences th:hover .engine-tooltip,
|
||||
#main_preferences td:hover .engine-tooltip,
|
||||
#main_preferences .engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
2
searx/static/themes/simple/css/searx.min.css
vendored
2
searx/static/themes/simple/css/searx.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
/*! simple/searx.min.js | 23-03-2021 | */
|
||||
/*! simple/searx.min.js | 21-04-2021 | */
|
||||
|
||||
(function(t,e){"use strict";var a=e.currentScript||function(){var t=e.getElementsByTagName("script");return t[t.length-1]}();t.searx={touch:"ontouchstart"in t||t.DocumentTouch&&document instanceof DocumentTouch||false,method:a.getAttribute("data-method"),autocompleter:a.getAttribute("data-autocompleter")==="true",search_on_category_select:a.getAttribute("data-search-on-category-select")==="true",infinite_scroll:a.getAttribute("data-infinite-scroll")==="true",static_path:a.getAttribute("data-static-path"),translations:JSON.parse(a.getAttribute("data-translations"))};e.getElementsByTagName("html")[0].className=t.searx.touch?"js touch":"js"})(window,document);
|
||||
//# sourceMappingURL=searx.head.min.js.map
|
2
searx/static/themes/simple/js/searx.min.js
vendored
2
searx/static/themes/simple/js/searx.min.js
vendored
|
@ -1,4 +1,4 @@
|
|||
/*! simple/searx.min.js | 23-03-2021 | */
|
||||
/*! simple/searx.min.js | 21-04-2021 | */
|
||||
|
||||
window.searx=function(t,a){"use strict";if(t.Element){(function(e){e.matches=e.matches||e.matchesSelector||e.webkitMatchesSelector||e.msMatchesSelector||function(e){var t=this,n=(t.parentNode||t.document).querySelectorAll(e),i=-1;while(n[++i]&&n[i]!=t);return!!n[i]}})(Element.prototype)}function o(e,t,n){try{e.call(t,n)}catch(e){console.log(e)}}var s=window.searx||{};s.on=function(i,e,r,t){t=t||false;if(typeof i!=="string"){i.addEventListener(e,r,t)}else{a.addEventListener(e,function(e){var t=e.target||e.srcElement,n=false;while(t&&t.matches&&t!==a&&!(n=t.matches(i)))t=t.parentElement;if(n)o(r,t,e)},t)}};s.ready=function(e){if(document.readyState!="loading"){e.call(t)}else{t.addEventListener("DOMContentLoaded",e.bind(t))}};s.http=function(e,t,n){var i=new XMLHttpRequest,r=function(){},a=function(){},o={then:function(e){r=e;return o},catch:function(e){a=e;return o}};try{i.open(e,t,true);i.onload=function(){if(i.status==200){r(i.response,i.responseType)}else{a(Error(i.statusText))}};i.onerror=function(){a(Error("Network Error"))};i.onabort=function(){a(Error("Transaction is aborted"))};i.send()}catch(e){a(e)}return o};s.loadStyle=function(e){var t=s.static_path+e,n="style_"+e.replace(".","_"),i=a.getElementById(n);if(i===null){i=a.createElement("link");i.setAttribute("id",n);i.setAttribute("rel","stylesheet");i.setAttribute("type","text/css");i.setAttribute("href",t);a.body.appendChild(i)}};s.loadScript=function(e,t){var n=s.static_path+e,i="script_"+e.replace(".","_"),r=a.getElementById(i);if(r===null){r=a.createElement("script");r.setAttribute("id",i);r.setAttribute("src",n);r.onload=t;r.onerror=function(){r.setAttribute("error","1")};a.body.appendChild(r)}else if(!r.hasAttribute("error")){try{t.apply(r,[])}catch(e){console.log(e)}}else{console.log("callback not executed : script '"+n+"' not loaded.")}};s.insertBefore=function(e,t){element.parentNode.insertBefore(e,t)};s.insertAfter=function(e,t){t.parentNode.insertBefore(e,t.nextSibling)};s.on(".close","click",function(e){var t=e.target||e.srcElement;this.parentNode.classList.add("invisible")});return s}(window,document);(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.AutoComplete=e()}})(function(){var e,t,n;return function a(o,s,l){function u(n,e){if(!s[n]){if(!o[n]){var t=typeof require=="function"&&require;if(!e&&t)return t(n,!0);if(c)return c(n,!0);var i=new Error("Cannot find module '"+n+"'");throw i.code="MODULE_NOT_FOUND",i}var r=s[n]={exports:{}};o[n][0].call(r.exports,function(e){var t=o[n][1][e];return u(t?t:e)},r,r.exports,a,o,s,l)}return s[n].exports}var c=typeof require=="function"&&require;for(var e=0;e<l.length;e++)u(l[e]);return u}({1:[function(e,t,n){
|
||||
/*
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
@color-warning: #dbba34;
|
||||
@color-warning-background: lighten(@color-warning, 40%);
|
||||
|
||||
@color-success: #42db34;
|
||||
@color-success-background: lighten(@color-success, 40%);
|
||||
|
||||
/// General
|
||||
|
||||
@color-font: #444;
|
||||
|
|
|
@ -105,9 +105,10 @@
|
|||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th:hover .engine-tooltip, .engine-tooltip:hover {
|
||||
th:hover .engine-tooltip, td:hover .engine-tooltip, .engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* To convert "style.less" to "style.css" run: $make styles
|
||||
*/
|
||||
|
||||
@stacked-bar-chart: rgb(0, 0, 0);
|
||||
|
||||
@import "normalize.less";
|
||||
|
||||
@import "definitions.less";
|
||||
|
|
|
@ -36,6 +36,14 @@ html.js .show_if_nojs {
|
|||
background-color: @color-error-background;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: @color-warning-background;
|
||||
}
|
||||
|
||||
.success {
|
||||
background: @color-success-background;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
|
@ -466,3 +474,61 @@ select {
|
|||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- stacked bar chart -- */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 4rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-base {
|
||||
display:flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-median {
|
||||
.stacked-bar-chart-base();
|
||||
background: @stacked-bar-chart;
|
||||
border: 1px solid fade(@stacked-bar-chart, 90%);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate80 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border: 1px solid fade(@stacked-bar-chart, 30%);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate95 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted fade(@stacked-bar-chart, 50%);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate100 {
|
||||
.stacked-bar-chart-base();
|
||||
background: transparent;
|
||||
border-left: 1px solid fade(@stacked-bar-chart, 90%);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
|
|
@ -134,13 +134,11 @@ custom-select{% if rtl %}-rtl{% endif %}
|
|||
{%- endmacro %}
|
||||
|
||||
{% macro support_toggle(supports) -%}
|
||||
{%- if supports -%}
|
||||
<span class="label label-success">
|
||||
{{- _("supported") -}}
|
||||
</span>
|
||||
{%- if supports == '?' -%}
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true" title="{{- _('broken') -}}"></span>{{- "" -}}
|
||||
{%- elif supports -%}
|
||||
<span class="glyphicon glyphicon-ok" aria-hidden="true" title="{{- _('supported') -}}"></span>{{- "" -}}
|
||||
{%- else -%}
|
||||
<span class="label label-danger">
|
||||
{{- _("not supported") -}}
|
||||
</span>
|
||||
<span aria-hidden="true" title="{{- _('not supported') -}}"></span>{{- "" -}}
|
||||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
|
|
@ -1,16 +1,92 @@
|
|||
{% from 'oscar/macros.html' import preferences_item_header, preferences_item_header_rtl, preferences_item_footer, preferences_item_footer_rtl, checkbox_toggle, support_toggle, custom_select_class %}
|
||||
{% extends "oscar/base.html" %}
|
||||
{% macro engine_about(search_engine, id) -%}
|
||||
{% if search_engine.about is defined %}
|
||||
{%- macro engine_about(search_engine, id) -%}
|
||||
{% if search_engine.about is defined or stats[search_engine.name]['result_count'] > 0 %}
|
||||
{% set about = search_engine.about %}
|
||||
<div class="engine-tooltip" role="tooltip" id="{{ id }}">{{- "" -}}
|
||||
{% if search_engine.about is defined %}
|
||||
<h5><a href="{{about.website}}" rel="noreferrer">{{about.website}}</a></h5>
|
||||
{%- if about.wikidata_id -%}<p><a href="https://www.wikidata.org/wiki/{{about.wikidata_id}}" rel="noreferrer">wikidata.org/wiki/{{about.wikidata_id}}</a></p>{%- endif -%}
|
||||
{% endif %}
|
||||
{%- if search_engine.enable_http %}<p>{{ icon('exclamation-sign', 'No HTTPS') }}{{ _('No HTTPS')}}</p>{% endif -%}
|
||||
{%- if stats[search_engine.name]['result_count'] -%}
|
||||
<p>{{ _('Number of results') }}: {{ stats[search_engine.name]['result_count'] }} ( {{ _('Avg.') }} )</p>{{- "" -}}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
{% block title %}{{ _('preferences') }} - {% endblock %}
|
||||
|
||||
{%- macro engine_time(engine_name, css_align_class) -%}
|
||||
<td class="{{ css_align_class }} {{ 'danger' if stats[engine_name]['warn_time'] else '' }}">
|
||||
{%- if stats[engine_name].time != None -%}
|
||||
<span aria-labelledby="{{engine_name}}_time">
|
||||
{%- if stats[engine_name]['warn_time'] -%}
|
||||
{{icon('exclamation-sign')}}
|
||||
{%- endif -%}
|
||||
{{- stats[engine_name].time -}}
|
||||
</span>{{- "" -}}
|
||||
<div class="engine-tooltip text-left" role="tooltip" id="{{engine_name}}_time">{{- "" -}}
|
||||
<p>{{ _('Median') }}: {{ stats[engine_name].time }}</p>{{- "" -}}
|
||||
<p>{{ _('P80') }}: {{ stats[engine_name].rate80 }}</p>{{- "" -}}
|
||||
<p>{{ _('P95') }}: {{ stats[engine_name].rate95 }}</p>{{- "" -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro engine_time(engine_name, css_align_class) -%}
|
||||
<td class="{{ label }}" style="padding: 2px">{{- "" -}}
|
||||
{%- if stats[engine_name].time != None -%}
|
||||
<span class="stacked-bar-chart-value">{{- stats[engine_name].time -}}</span>{{- "" -}}
|
||||
<span class="stacked-bar-chart" aria-labelledby="{{engine_name}}_chart" aria-hidden="true">{{- "" -}}
|
||||
<span style="width: calc(max(2px, 100%*{{ (stats[engine_name].time / max_rate95)|round(3) }}))" class="stacked-bar-chart-median"></span>{{- "" -}}
|
||||
<span style="width: calc(100%*{{ ((stats[engine_name].rate80 - stats[engine_name].time) / max_rate95)|round(3) }})" class="stacked-bar-chart-rate80"></span>{{- "" -}}
|
||||
<span style="width: calc(100%*{{ ((stats[engine_name].rate95 - stats[engine_name].rate80) / max_rate95)|round(3) }})" class="stacked-bar-chart-rate95"></span>{{- "" -}}
|
||||
<span class="stacked-bar-chart-rate100"></span>{{- "" -}}
|
||||
</span>{{- "" -}}
|
||||
<div class="engine-tooltip text-left" role="tooltip" id="{{engine_name}}_graph">{{- "" -}}
|
||||
<p>{{ _('Median') }}: {{ stats[engine_name].time }}</p>{{- "" -}}
|
||||
<p>{{ _('P80') }}: {{ stats[engine_name].rate80 }}</p>{{- "" -}}
|
||||
<p>{{ _('P95') }}: {{ stats[engine_name].rate95 }}</p>{{- "" -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro engine_reliability(engine_name, css_align_class) -%}
|
||||
{% set r = reliabilities.get(engine_name, {}).get('reliablity', None) %}
|
||||
{% set checker_result = reliabilities.get(engine_name, {}).get('checker', []) %}
|
||||
{% set errors = reliabilities.get(engine_name, {}).get('errors', []) %}
|
||||
{% if r != None %}
|
||||
{% if r <= 50 %}{% set label = 'danger' %}
|
||||
{% elif r < 80 %}{% set label = 'warning' %}
|
||||
{% elif r < 90 %}{% set label = 'default' %}
|
||||
{% else %}{% set label = 'success' %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set r = '' %}
|
||||
{% endif %}
|
||||
{% if checker_result or errors %}
|
||||
<td class="{{ css_align_class }} {{ label }}">{{- "" -}}
|
||||
<span aria-labelledby="{{engine_name}}_reliablity">
|
||||
{%- if reliabilities[engine_name].checker %}{{ icon('exclamation-sign', 'The checker fails on the some tests') }}{% endif %} {{ r -}}
|
||||
</span>{{- "" -}}
|
||||
<div class="engine-tooltip text-left" role="tooltip" id="{{engine_name}}_reliablity">
|
||||
{%- if checker_result -%}
|
||||
<p>{{ _("Failed checker test(s): ") }} {{ ', '.join(checker_result) }}</p>
|
||||
{%- endif -%}
|
||||
{%- for error in errors -%}
|
||||
<p>{{ error }} </p>{{- "" -}}
|
||||
{%- endfor -%}
|
||||
</div>{{- "" -}}
|
||||
</td>
|
||||
{%- else -%}
|
||||
<td class="{{ css_align_class }} {{ label }}"><span>{{ r }}</span></td>
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- block title %}{{ _('preferences') }} - {% endblock -%}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div>
|
||||
|
@ -182,7 +258,6 @@
|
|||
</fieldset>
|
||||
</div>
|
||||
<div class="tab-pane active_if_nojs" id="tab_engine">
|
||||
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs nav-justified hide_if_nojs" role="tablist">
|
||||
{% for categ in all_categories %}
|
||||
|
@ -217,14 +292,16 @@
|
|||
<th scope="col">{{ _("Allow") }}</th>
|
||||
<th scope="col">{{ _("Engine name") }}</th>
|
||||
<th scope="col">{{ _("Shortcut") }}</th>
|
||||
<th scope="col">{{ _("Selected language") }}</th>
|
||||
<th scope="col">{{ _("SafeSearch") }}</th>
|
||||
<th scope="col">{{ _("Time range") }}</th>
|
||||
<th scope="col">{{ _("Avg. time") }}</th>
|
||||
<th scope="col">{{ _("Max time") }}</th>
|
||||
<th scope="col" style="width: 10rem">{{ _("Selected language") }}</th>
|
||||
<th scope="col" style="width: 10rem">{{ _("SafeSearch") }}</th>
|
||||
<th scope="col" style="width: 10rem">{{ _("Time range") }}</th>
|
||||
<th scope="col">{{ _("Response time") }}</th>
|
||||
<th scope="col" class="text-right" style="width: 7rem">{{ _("Max time") }}</th>
|
||||
<th scope="col" class="text-right" style="width: 7rem">{{ _("Reliablity") }}</th>
|
||||
{% else %}
|
||||
<th scope="col" class="text-right">{{ _("Max time") }}</th>
|
||||
<th scope="col" class="text-right">{{ _("Avg. time") }}</th>
|
||||
<th scope="col">{{ _("Reliablity") }}</th>
|
||||
<th scope="col">{{ _("Max time") }}</th>
|
||||
<th scope="col" class="text-right">{{ _("Response time") }}</th>
|
||||
<th scope="col" class="text-right">{{ _("Time range") }}</th>
|
||||
<th scope="col" class="text-right">{{ _("SafeSearch") }}</th>
|
||||
<th scope="col" class="text-right">{{ _("Selected language") }}</th>
|
||||
|
@ -246,17 +323,19 @@
|
|||
{{- engine_about(search_engine, 'tooltip_' + categ + '_' + search_engine.name) -}}
|
||||
</th>
|
||||
<td class="name">{{ shortcuts[search_engine.name] }}</td>
|
||||
<td>{{ support_toggle(stats[search_engine.name].supports_selected_language) }}</td>
|
||||
<td>{{ support_toggle(search_engine.safesearch==True) }}</td>
|
||||
<td>{{ support_toggle(search_engine.time_range_support==True) }}</td>
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{% if stats[search_engine.name]['warn_time'] %}{{ icon('exclamation-sign')}} {% endif %}{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{% if stats[search_engine.name]['warn_timeout'] %}{{ icon('exclamation-sign') }} {% endif %}{{ search_engine.timeout }}</td>
|
||||
<td>{{ support_toggle(supports[search_engine.name]['supports_selected_language']) }}</td>
|
||||
<td>{{ support_toggle(supports[search_engine.name]['safesearch']) }}</td>
|
||||
<td>{{ support_toggle(supports[search_engine.name]['time_range_support']) }}</td>
|
||||
{{ engine_time(search_engine.name, 'text-right') }}
|
||||
<td class="text-right {{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{% if stats[search_engine.name]['warn_timeout'] %}{{ icon('exclamation-sign') }} {% endif %}{{ search_engine.timeout }}</td>
|
||||
{{ engine_reliability(search_engine.name, 'text-right ') }}
|
||||
{% else %}
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}{% if stats[search_engine.name]['warn_time'] %} {{ icon('exclamation-sign')}}{% endif %}</td>
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}{% if stats[search_engine.name]['warn_time'] %} {{ icon('exclamation-sign')}}{% endif %}</td>
|
||||
<td>{{ support_toggle(search_engine.time_range_support==True) }}</td>
|
||||
<td>{{ support_toggle(search_engine.safesearch==True) }}</td>
|
||||
<td>{{ support_toggle(stats[search_engine.name].supports_selected_language) }}</td>
|
||||
{{ engine_reliability(search_engine.name, 'text-left') }}
|
||||
<td class="text-left {{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}{% if stats[search_engine.name]['warn_time'] %} {{ icon('exclamation-sign')}}{% endif %}</td>
|
||||
{{ engine_time(search_engine.name, 'text-left') }}
|
||||
<td>{{ support_toggle(supports[search_engine.name]['time_range_support']) }}</td>
|
||||
<td>{{ support_toggle(supports[search_engine.name]['safesearch']) }}</td>
|
||||
<td>{{ support_toggle(supports[search_engine.name]['supports_selected_language']) }}</td>
|
||||
<td>{{ shortcuts[search_engine.name] }}</td>
|
||||
<th scope="row"><span>{% if search_engine.enable_http %}{{ icon('exclamation-sign', 'No HTTPS') }}{% endif %}{{ search_engine.name }}</span>{{ engine_about(search_engine) }}</th>
|
||||
<td class="onoff-checkbox">
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
{% extends "oscar/base.html" %}
|
||||
{% block styles %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/charts.min.css') }}" type="text/css" />
|
||||
<style>
|
||||
#engine-times {
|
||||
--labels-size: 20rem;
|
||||
}
|
||||
|
||||
#engine-times th {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block title %}{{ _('stats') }} - {% endblock %}
|
||||
{% block content %}
|
||||
<div class="container-fluid">
|
||||
|
|
|
@ -79,7 +79,11 @@
|
|||
|
||||
{%- macro checkbox(name, checked, readonly, disabled) -%}
|
||||
<div class="checkbox">{{- '' -}}
|
||||
{%- if checked == '?' -%}
|
||||
{{ icon_small('warning') }}
|
||||
{%- else -%}
|
||||
<input type="checkbox" value="None" id="{{ name }}" name="{{ name }}" {% if checked %}checked{% endif %}{% if readonly %} readonly="readonly" {% endif %}{% if disabled %} disabled="disabled" {% endif %}/>{{- '' -}}
|
||||
<label for="{{ name }}"></label>{{- '' -}}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
|
|
@ -29,6 +29,58 @@
|
|||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro engine_time(engine_name) -%}
|
||||
<td class="{{ label }}" style="padding: 2px; width: 13rem;">{{- "" -}}
|
||||
{%- if stats[engine_name].time != None -%}
|
||||
<span class="stacked-bar-chart-value">{{- stats[engine_name].time -}}</span>{{- "" -}}
|
||||
<span class="stacked-bar-chart" aria-labelledby="{{engine_name}}_chart" aria-hidden="true">{{- "" -}}
|
||||
<span style="width: calc(max(2px, 100%*{{ (stats[engine_name].time / max_rate95)|round(3) }}))" class="stacked-bar-chart-median"></span>{{- "" -}}
|
||||
<span style="width: calc(100%*{{ ((stats[engine_name].rate80 - stats[engine_name].time) / max_rate95)|round(3) }})" class="stacked-bar-chart-rate80"></span>{{- "" -}}
|
||||
<span style="width: calc(100%*{{ ((stats[engine_name].rate95 - stats[engine_name].rate80) / max_rate95)|round(3) }})" class="stacked-bar-chart-rate95"></span>{{- "" -}}
|
||||
<span class="stacked-bar-chart-rate100"></span>{{- "" -}}
|
||||
</span>{{- "" -}}
|
||||
<div class="engine-tooltip text-left" role="tooltip" id="{{engine_name}}_graph">{{- "" -}}
|
||||
<p>{{ _('Median') }}: {{ stats[engine_name].time }}</p>{{- "" -}}
|
||||
<p>{{ _('P80') }}: {{ stats[engine_name].rate80 }}</p>{{- "" -}}
|
||||
<p>{{ _('P95') }}: {{ stats[engine_name].rate95 }}</p>{{- "" -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro engine_reliability(engine_name) -%}
|
||||
{% set r = reliabilities.get(engine_name, {}).get('reliablity', None) %}
|
||||
{% set checker_result = reliabilities.get(engine_name, {}).get('checker', []) %}
|
||||
{% set errors = reliabilities.get(engine_name, {}).get('errors', []) %}
|
||||
{% if r != None %}
|
||||
{% if r <= 50 %}{% set label = 'danger' %}
|
||||
{% elif r < 80 %}{% set label = 'warning' %}
|
||||
{% elif r < 90 %}{% set label = '' %}
|
||||
{% else %}{% set label = 'success' %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set r = '' %}
|
||||
{% endif %}
|
||||
{% if checker_result or errors %}
|
||||
<td class="{{ label }}">{{- "" -}}
|
||||
<span aria-labelledby="{{engine_name}}_reliablity">
|
||||
{%- if reliabilities[engine_name].checker %}{{ icon('warning', 'The checker fails on the some tests') }}{% endif %} {{ r -}}
|
||||
</span>{{- "" -}}
|
||||
<div class="engine-tooltip" style="right: 12rem;" role="tooltip" id="{{engine_name}}_reliablity">
|
||||
{%- if checker_result -%}
|
||||
<p>{{ _("The checker fails on this tests: ") }} {{ ', '.join(checker_result) }}</p>
|
||||
{%- endif -%}
|
||||
{%- if errors %}<p>{{ _('Errors:') }}</p>{% endif -%}
|
||||
{%- for error in errors -%}
|
||||
<p>{{ error }} </p>{{- "" -}}
|
||||
{%- endfor -%}
|
||||
</div>{{- "" -}}
|
||||
</td>
|
||||
{%- else -%}
|
||||
<td class="{{ css_align_class }} {{ label }}"><span>{{ r }}</span></td>
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% block head %} {% endblock %}
|
||||
{% block content %}
|
||||
|
||||
|
@ -123,8 +175,9 @@
|
|||
<th>{{ _("Supports selected language") }}</th>
|
||||
<th>{{ _("SafeSearch") }}</th>
|
||||
<th>{{ _("Time range") }}</th>
|
||||
<th>{{ _("Avg. time") }}</th>
|
||||
<th>{{ _("Response time") }}</th>
|
||||
<th>{{ _("Max time") }}</th>
|
||||
<th>{{ _("Reliablity") }}</th>
|
||||
</tr>
|
||||
{% for search_engine in engines_by_category[categ] %}
|
||||
|
||||
|
@ -134,11 +187,12 @@
|
|||
<td class="engine_checkbox">{{ checkbox_onoff(engine_id, (search_engine.name, categ) in disabled_engines) }}</td>
|
||||
<th class="name">{% if search_engine.enable_http %}{{ icon('warning', 'No HTTPS') }}{% endif %} {{ search_engine.name }} {{ engine_about(search_engine) }}</th>
|
||||
<td class="shortcut">{{ shortcuts[search_engine.name] }}</td>
|
||||
<td>{{ checkbox(engine_id + '_supported_languages', current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages, true, true) }}</td>
|
||||
<td>{{ checkbox(engine_id + '_safesearch', search_engine.safesearch==True, true, true) }}</td>
|
||||
<td>{{ checkbox(engine_id + '_time_range_support', search_engine.time_range_support==True, true, true) }}</td>
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
|
||||
<td>{{ checkbox(engine_id + '_supported_languages', supports[search_engine.name]['supports_selected_language'], true, true) }}</td>
|
||||
<td>{{ checkbox(engine_id + '_safesearch', supports[search_engine.name]['safesearch'], true, true) }}</td>
|
||||
<td>{{ checkbox(engine_id + '_time_range_support', supports[search_engine.name]['time_range_support'], true, true) }}</td>
|
||||
{{ engine_time(search_engine.name) }}
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>
|
||||
{{ engine_reliability(search_engine.name) }}
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
109
searx/webapp.py
109
searx/webapp.py
|
@ -93,7 +93,7 @@ from searx.preferences import Preferences, ValidationException, LANGUAGE_CODES
|
|||
from searx.answerers import answerers
|
||||
from searx.network import stream as http_stream
|
||||
from searx.answerers import ask
|
||||
from searx.metrics import get_engines_stats, get_engine_errors, histogram
|
||||
from searx.metrics import get_engines_stats, get_engine_errors, histogram, counter
|
||||
|
||||
# serve pages with HTTP/1.1
|
||||
from werkzeug.serving import WSGIRequestHandler
|
||||
|
@ -170,6 +170,31 @@ _category_names = (gettext('files'),
|
|||
gettext('onions'),
|
||||
gettext('science'))
|
||||
|
||||
#
|
||||
exception_classname_to_label = {
|
||||
"searx.exceptions.SearxEngineCaptchaException": gettext("CAPTCHA"),
|
||||
"searx.exceptions.SearxEngineTooManyRequestsException": gettext("too many requests"),
|
||||
"searx.exceptions.SearxEngineAccessDeniedException": gettext("access denied"),
|
||||
"searx.exceptions.SearxEngineAPIException": gettext("server API error"),
|
||||
"httpx.TimeoutException": gettext("HTTP timeout"),
|
||||
"httpx.ConnectTimeout": gettext("HTTP timeout"),
|
||||
"httpx.ReadTimeout": gettext("HTTP timeout"),
|
||||
"httpx.WriteTimeout": gettext("HTTP timeout"),
|
||||
"httpx.HTTPStatusError": gettext("HTTP error"),
|
||||
"httpx.ConnectError": gettext("HTTP connection error"),
|
||||
"httpx.RemoteProtocolError": gettext("HTTP protocol error"),
|
||||
"httpx.LocalProtocolError": gettext("HTTP protocol error"),
|
||||
"httpx.ProtocolError": gettext("HTTP protocol error"),
|
||||
"httpx.ReadError": gettext("network error"),
|
||||
"httpx.WriteError": gettext("network error"),
|
||||
"httpx.ProxyError": gettext("proxy error"),
|
||||
"searx.exceptions.SearxEngineXPathException": gettext("parsing error"),
|
||||
"KeyError": gettext("parsing error"),
|
||||
"json.decoder.JSONDecodeError": gettext("parsing error"),
|
||||
"lxml.etree.ParserError": gettext("parsing error"),
|
||||
None: gettext("unexpected crash"),
|
||||
}
|
||||
|
||||
_flask_babel_get_translations = flask_babel.get_translations
|
||||
|
||||
|
||||
|
@ -855,26 +880,101 @@ def preferences():
|
|||
engines_by_category = {}
|
||||
for c in categories:
|
||||
engines_by_category[c] = [e for e in categories[c] if e.name in filtered_engines]
|
||||
# sort the engines alphabetically since the order in settings.yml is meaningless.
|
||||
list.sort(engines_by_category[c], key=lambda e: e.name)
|
||||
|
||||
# get first element [0], the engine time,
|
||||
# and then the second element [1] : the time (the first one is the label)
|
||||
stats = {}
|
||||
max_rate95 = 0
|
||||
for _, e in filtered_engines.items():
|
||||
h = histogram('engine', e.name, 'time', 'total')
|
||||
median = round(h.percentage(50), 1) if h.count > 0 else None
|
||||
rate80 = round(h.percentage(80), 1) if h.count > 0 else None
|
||||
rate95 = round(h.percentage(95), 1) if h.count > 0 else None
|
||||
|
||||
max_rate95 = max(max_rate95, rate95 or 0)
|
||||
|
||||
result_count_sum = histogram('engine', e.name, 'result', 'count').sum
|
||||
successful_count = counter('engine', e.name, 'search', 'count', 'successful')
|
||||
result_count = int(result_count_sum / float(successful_count)) if successful_count else 0
|
||||
|
||||
stats[e.name] = {
|
||||
'time': median if median else None,
|
||||
'warn_time': median is not None and median > settings['outgoing']['request_timeout'],
|
||||
'rate80': rate80 if rate80 else None,
|
||||
'rate95': rate95 if rate95 else None,
|
||||
'warn_timeout': e.timeout > settings['outgoing']['request_timeout'],
|
||||
'supports_selected_language': _is_selected_language_supported(e, request.preferences)
|
||||
'supports_selected_language': _is_selected_language_supported(e, request.preferences),
|
||||
'result_count': result_count,
|
||||
}
|
||||
# end of stats
|
||||
|
||||
# reliabilities
|
||||
reliabilities = {}
|
||||
engine_errors = get_engine_errors(filtered_engines)
|
||||
checker_results = checker_get_result()
|
||||
checker_results = checker_results['engines'] \
|
||||
if checker_results['status'] == 'ok' and 'engines' in checker_results else {}
|
||||
for _, e in filtered_engines.items():
|
||||
checker_result = checker_results.get(e.name, {})
|
||||
checker_success = checker_result.get('success', True)
|
||||
errors = engine_errors.get(e.name) or []
|
||||
if counter('engine', e.name, 'search', 'count', 'sent') == 0:
|
||||
# no request
|
||||
reliablity = None
|
||||
elif checker_success and not errors:
|
||||
reliablity = 100
|
||||
elif 'simple' in checker_result.get('errors', {}):
|
||||
# the basic (simple) test doesn't work: the engine is broken accoding to the checker
|
||||
# even if there is no exception
|
||||
reliablity = 0
|
||||
else:
|
||||
reliablity = 100 - sum([error['percentage'] for error in errors if not error.get('secondary')])
|
||||
|
||||
reliabilities[e.name] = {
|
||||
'reliablity': reliablity,
|
||||
'errors': [],
|
||||
'checker': checker_results.get(e.name, {}).get('errors', {}).keys(),
|
||||
}
|
||||
# keep the order of the list checker_results[e.name]['errors'] and deduplicate.
|
||||
# the first element has the highest percentage rate.
|
||||
reliabilities_errors = []
|
||||
for error in errors:
|
||||
error_user_message = None
|
||||
if error.get('secondary') or 'exception_classname' not in error:
|
||||
continue
|
||||
error_user_message = exception_classname_to_label.get(error.get('exception_classname'))
|
||||
if not error:
|
||||
error_user_message = exception_classname_to_label[None]
|
||||
if error_user_message not in reliabilities_errors:
|
||||
reliabilities_errors.append(error_user_message)
|
||||
reliabilities[e.name]['errors'] = reliabilities_errors
|
||||
|
||||
# supports
|
||||
supports = {}
|
||||
for _, e in filtered_engines.items():
|
||||
supports_selected_language = _is_selected_language_supported(e, request.preferences)
|
||||
safesearch = e.safesearch
|
||||
time_range_support = e.time_range_support
|
||||
for checker_test_name in checker_results.get(e.name, {}).get('errors', {}):
|
||||
if supports_selected_language and checker_test_name.startswith('lang_'):
|
||||
supports_selected_language = '?'
|
||||
elif safesearch and checker_test_name == 'safesearch':
|
||||
safesearch = '?'
|
||||
elif time_range_support and checker_test_name == 'time_range':
|
||||
time_range_support = '?'
|
||||
supports[e.name] = {
|
||||
'supports_selected_language': supports_selected_language,
|
||||
'safesearch': safesearch,
|
||||
'time_range_support': time_range_support,
|
||||
}
|
||||
|
||||
#
|
||||
locked_preferences = list()
|
||||
if 'preferences' in settings and 'lock' in settings['preferences']:
|
||||
locked_preferences = settings['preferences']['lock']
|
||||
|
||||
#
|
||||
return render('preferences.html',
|
||||
selected_categories=get_selected_categories(request.preferences, request.form),
|
||||
all_categories=_get_ordered_categories(),
|
||||
|
@ -883,6 +983,9 @@ def preferences():
|
|||
image_proxy=image_proxy,
|
||||
engines_by_category=engines_by_category,
|
||||
stats=stats,
|
||||
max_rate95=max_rate95,
|
||||
reliabilities=reliabilities,
|
||||
supports=supports,
|
||||
answerers=[{'info': a.self_info(), 'keywords': a.keywords} for a in answerers],
|
||||
disabled_engines=disabled_engines,
|
||||
autocomplete_backends=autocomplete_backends,
|
||||
|
|
Loading…
Reference in a new issue