forked from zaclys/searxng
[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
|
@ -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
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;
|
||||
}
|
||||
|
|
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
|
|
@ -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 }}">{{- "" -}}
|
||||
<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 -%}
|
||||
{% 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">{{- '' -}}
|
||||
<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>{{- '' -}}
|
||||
{%- 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 New Issue