0
0
mirror of https://github.com/neon-mmd/websurfx.git synced 2024-11-21 21:48:21 -05:00

Merge branch 'rolling' into FIX/468_pagination-for-the-upstream-search-engines-not-working

This commit is contained in:
neon_arch 2023-12-30 13:17:44 +03:00 committed by GitHub
commit 61393ba7c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 177 additions and 39 deletions

View File

@ -1,3 +1,62 @@
/**
* This functions gets the saved cookies if it is present on the user's machine If it
* is available then it is parsed and converted to an object which is then used to
* retrieve the preferences that the user had selected previously and is then loaded
* and used for displaying the user provided settings by setting them as the selected
* options in the settings page.
*
* @function
* @param {string} cookie - It takes the client settings cookie as a string.
* @returns {void}
*/
function setClientSettingsOnPage(cookie) {
let cookie_value = cookie
.split(';')
.map((item) => item.split('='))
.reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {})
// Loop through all select tags and add their values to the cookie dictionary
document.querySelectorAll('select').forEach((select_tag) => {
switch (select_tag.name) {
case 'themes':
select_tag.value = cookie_value['theme']
break
case 'colorschemes':
select_tag.value = cookie_value['colorscheme']
break
case 'animations':
select_tag.value = cookie_value['animation']
break
case 'safe_search_levels':
select_tag.value = cookie_value['safe_search_level']
break
}
})
let engines = document.querySelectorAll('.engine')
let engines_cookie = cookie_value['engines']
if (engines_cookie.length === engines.length) {
document.querySelector('.select_all').checked = true
engines.forEach((engine_checkbox) => {
engine_checkbox.checked = true
})
} else {
engines.forEach((engines_checkbox) => {
engines_checkbox.checked = false
})
engines_cookie.forEach((engine_name) => {
engines.forEach((engine_checkbox) => {
if (
engine_checkbox.parentNode.parentNode.innerText.trim() ===
engine_name.trim()
) {
engine_checkbox.checked = true
}
})
})
}
}
/** /**
* This function is executed when any page on the website finishes loading and * This function is executed when any page on the website finishes loading and
* this function retrieves the cookies if it is present on the user's machine. * this function retrieves the cookies if it is present on the user's machine.
@ -16,9 +75,14 @@ document.addEventListener(
let cookie = decodeURIComponent(document.cookie) let cookie = decodeURIComponent(document.cookie)
// Set the value of the input field to the decoded cookie value if it is not empty // Set the value of the input field to the decoded cookie value if it is not empty
// Otherwise, display a message indicating that no cookies have been saved on the user's system // Otherwise, display a message indicating that no cookies have been saved on the user's system
document.querySelector('.cookies input').value = cookie.length if (cookie.length) {
? cookie document.querySelector('.cookies input').value = cookie
: 'No cookies have been saved on your system' // This function displays the user provided settings on the settings page.
setClientSettingsOnPage(cookie)
} else {
document.querySelector('.cookies input').value =
'No cookies have been saved on your system'
}
} catch (error) { } catch (error) {
// If there is an error decoding the cookie, log the error to the console // If there is an error decoding the cookie, log the error to the console
// and display an error message in the input field // and display an error message in the input field

View File

@ -600,12 +600,20 @@ footer div {
text-transform: capitalize; text-transform: capitalize;
} }
.settings_container .tab .description { .settings_container .tab .description,
.settings_container .tab .admin_warning {
font-size: 1.5rem; font-size: 1.5rem;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
}
.settings_container .tab .description {
color: var(--foreground-color); color: var(--foreground-color);
} }
.settings_container .tab .admin_warning {
color: var(--color-two);
}
.settings_container .user_interface select, .settings_container .user_interface select,
.settings_container .general select { .settings_container .general select {
margin: 0.7rem 0; margin: 0.7rem 0;

View File

@ -75,13 +75,11 @@ pub async fn settings(
.content_type("text/html; charset=utf-8") .content_type("text/html; charset=utf-8")
.body( .body(
crate::templates::views::settings::settings( crate::templates::views::settings::settings(
config.safe_search,
&config.style.colorscheme, &config.style.colorscheme,
&config.style.theme, &config.style.theme,
&config.style.animation, &config.style.animation,
&config &config.upstream_search_engines,
.upstream_search_engines
.keys()
.collect::<Vec<&String>>(),
)? )?
.0, .0,
)) ))

View File

@ -1,17 +1,20 @@
//! A module that handles the engines tab for setting page view in the `websurfx` frontend. //! A module that handles the engines tab for setting page view in the `websurfx` frontend.
use std::collections::HashMap;
use maud::{html, Markup}; use maud::{html, Markup};
/// A functions that handles the html code for the engines tab for the settings page for the search page. /// A functions that handles the html code for the engines tab for the settings page for the search page.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `engine_names` - It takes the list of all available engine names as an argument. /// * `engine_names` - It takes the key value pair list of all available engine names and there corresponding
/// selected (enabled/disabled) value as an argument.
/// ///
/// # Returns /// # Returns
/// ///
/// It returns the compiled html markup code for the engines tab. /// It returns the compiled html markup code for the engines tab.
pub fn engines(engine_names: &[&String]) -> Markup { pub fn engines(engine_names: &HashMap<String, bool>) -> Markup {
html!( html!(
div class="engines tab"{ div class="engines tab"{
h1{"Engines"} h1{"Engines"}
@ -20,16 +23,43 @@ pub fn engines(engine_names: &[&String]) -> Markup {
"Select the search engines from the list of engines that you want results from" "Select the search engines from the list of engines that you want results from"
} }
.engine_selection{ .engine_selection{
// Checks whether all the engines are selected or not if they are then the
// checked `select_all` button is rendered otherwise the unchecked version
// is rendered.
@if engine_names.values().all(|selected| *selected){
.toggle_btn{ .toggle_btn{
label class="switch"{
input type="checkbox" class="select_all" onchange="toggleAllSelection()" checked;
span class="slider round"{}
}
"Select All"
}
}
@else{
.toggle_btn {
label class="switch"{ label class="switch"{
input type="checkbox" class="select_all" onchange="toggleAllSelection()"; input type="checkbox" class="select_all" onchange="toggleAllSelection()";
span class="slider round"{} span class="slider round"{}
} }
"Select All" "Select All"
} }
}
hr; hr;
@for engine_name in engine_names{ @for (engine_name, selected) in engine_names{
// Checks whether the `engine_name` is selected or not if they are then the
// checked `engine` button is rendered otherwise the unchecked version is
// rendered.
@if *selected {
.toggle_btn{ .toggle_btn{
label class="switch"{
input type="checkbox" class="engine" checked;
span class="slider round"{}
}
(format!("{}{}",engine_name[..1].to_uppercase().to_owned(), engine_name[1..].to_owned()))
}
}
@else {
.toggle_btn {
label class="switch"{ label class="switch"{
input type="checkbox" class="engine"; input type="checkbox" class="engine";
span class="slider round"{} span class="slider round"{}
@ -39,5 +69,6 @@ pub fn engines(engine_names: &[&String]) -> Markup {
} }
} }
} }
}
) )
} }

View File

@ -7,10 +7,14 @@ const SAFE_SEARCH_LEVELS: [(u8, &str); 3] = [(0, "None"), (1, "Low"), (2, "Moder
/// A functions that handles the html code for the general tab for the settings page for the search page. /// A functions that handles the html code for the general tab for the settings page for the search page.
/// ///
/// # Arguments
///
/// * `safe_search_level` - It takes the safe search level as an argument.
///
/// # Returns /// # Returns
/// ///
/// It returns the compiled html markup code for the general tab. /// It returns the compiled html markup code for the general tab.
pub fn general() -> Markup { pub fn general(safe_search_level: u8) -> Markup {
html!( html!(
div class="general tab active"{ div class="general tab active"{
h1{"General"} h1{"General"}
@ -18,11 +22,21 @@ pub fn general() -> Markup {
p class="description"{ p class="description"{
"Select a safe search level from the menu below to filter content based on the level." "Select a safe search level from the menu below to filter content based on the level."
} }
select name="safe_search_levels"{ @if safe_search_level < 3 {
@for (k,v) in SAFE_SEARCH_LEVELS{ select name="safe_search_levels" {
// Sets the user selected safe_search_level name from the config file as the first option in the selection list.
option value=(safe_search_level){(SAFE_SEARCH_LEVELS.iter().find(|level| level.0 == safe_search_level).unwrap().1)}
@for (k,v) in SAFE_SEARCH_LEVELS.iter().filter(|level| level.0 != safe_search_level){
option value=(k){(v)} option value=(k){(v)}
} }
} }
} }
@else {
p class="admin_warning" {"⚠️ This setting is being managed by the server administrator."}
select name="safe_search_levels" disabled {
option value=(SAFE_SEARCH_LEVELS[2].0){(SAFE_SEARCH_LEVELS[2].1)}
}
}
}
) )
} }

View File

@ -4,13 +4,16 @@ use crate::handler::{file_path, FileType};
use maud::{html, Markup}; use maud::{html, Markup};
use std::fs::read_dir; use std::fs::read_dir;
/// A helper function that helps in building the list of all available colorscheme/theme names /// A helper function that helps in building the list of all available colorscheme/theme/animation
/// present in the colorschemes and themes folder respectively. /// names present in the colorschemes, animations and themes folder respectively by excluding the
/// ones that have already been selected via the config file.
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `style_type` - It takes the style type of the values `theme` and `colorscheme` as an /// * `style_type` - It takes the style type of the values `theme` and `colorscheme` as an
/// argument. /// argument.
/// * `selected_style` - It takes the currently selected style value provided via the config file
/// as an argument.
/// ///
/// # Error /// # Error
/// ///
@ -18,7 +21,8 @@ use std::fs::read_dir;
/// returns a standard error message. /// returns a standard error message.
fn style_option_list( fn style_option_list(
style_type: &str, style_type: &str,
) -> Result<Vec<(String, String)>, Box<dyn std::error::Error + '_>> { selected_style: &str,
) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> {
let mut style_option_names: Vec<(String, String)> = Vec::new(); let mut style_option_names: Vec<(String, String)> = Vec::new();
for file in read_dir(format!( for file in read_dir(format!(
"{}static/{}/", "{}static/{}/",
@ -26,8 +30,14 @@ fn style_option_list(
style_type, style_type,
))? { ))? {
let style_name = file?.file_name().to_str().unwrap().replace(".css", ""); let style_name = file?.file_name().to_str().unwrap().replace(".css", "");
if selected_style != style_name {
style_option_names.push((style_name.clone(), style_name.replace('-', " "))); style_option_names.push((style_name.clone(), style_name.replace('-', " ")));
} }
}
if style_type == "animations" {
style_option_names.push(("".to_owned(), "none".to_owned()))
}
Ok(style_option_names) Ok(style_option_names)
} }
@ -38,7 +48,11 @@ fn style_option_list(
/// ///
/// It returns the compiled html markup code for the user interface tab on success otherwise /// It returns the compiled html markup code for the user interface tab on success otherwise
/// returns a standard error message. /// returns a standard error message.
pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> { pub fn user_interface(
theme: &str,
colorscheme: &str,
animation: &Option<String>,
) -> Result<Markup, Box<dyn std::error::Error>> {
Ok(html!( Ok(html!(
div class="user_interface tab"{ div class="user_interface tab"{
h1{"User Interface"} h1{"User Interface"}
@ -47,7 +61,9 @@ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
"Select the theme from the available themes to be used in user interface" "Select the theme from the available themes to be used in user interface"
} }
select name="themes"{ select name="themes"{
@for (k,v) in style_option_list("themes")?{ // Sets the user selected theme name from the config file as the first option in the selection list.
option value=(theme){(theme.replace('-', " "))}
@for (k,v) in style_option_list("themes", theme)?{
option value=(k){(v)} option value=(k){(v)}
} }
} }
@ -56,7 +72,9 @@ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
"Select the color scheme for your theme to be used in user interface" "Select the color scheme for your theme to be used in user interface"
} }
select name="colorschemes"{ select name="colorschemes"{
@for (k,v) in style_option_list("colorschemes")?{ // Sets the user selected colorscheme name from the config file as the first option in the selection list.
option value=(colorscheme){(colorscheme.replace('-', " "))}
@for (k,v) in style_option_list("colorschemes", colorscheme)?{
option value=(k){(v)} option value=(k){(v)}
} }
} }
@ -65,12 +83,12 @@ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
"Select the animation for your theme to be used in user interface" "Select the animation for your theme to be used in user interface"
} }
select name="animations"{ select name="animations"{
option value=""{"none"} // Sets the user selected animation name from the config file as the first option in the selection list.
@for (k,v) in style_option_list("animations")?{ option value=(animation.as_ref().unwrap_or(&"".to_owned())){(animation.as_ref().unwrap_or(&"".to_owned()).replace('-'," "))}
@for (k,v) in style_option_list("animations", animation.as_ref().unwrap_or(&"".to_owned()))?{
option value=(k){(v)} option value=(k){(v)}
} }
} }
} }
)) ))
} }

View File

@ -1,5 +1,7 @@
//! A module that handles the view for the settings page in the `websurfx` frontend. //! A module that handles the view for the settings page in the `websurfx` frontend.
use std::collections::HashMap;
use maud::{html, Markup}; use maud::{html, Markup};
use crate::templates::partials::{ use crate::templates::partials::{
@ -14,8 +16,10 @@ use crate::templates::partials::{
/// ///
/// # Arguments /// # Arguments
/// ///
/// * `safe_search_level` - It takes the safe search level as an argument.
/// * `colorscheme` - It takes the colorscheme name as an argument. /// * `colorscheme` - It takes the colorscheme name as an argument.
/// * `theme` - It takes the theme name as an argument. /// * `theme` - It takes the theme name as an argument.
/// * `animation` - It takes the animation name as an argument.
/// * `engine_names` - It takes a list of engine names as an argument. /// * `engine_names` - It takes a list of engine names as an argument.
/// ///
/// # Error /// # Error
@ -23,10 +27,11 @@ use crate::templates::partials::{
/// This function returns a compiled html markup code on success otherwise returns a standard error /// This function returns a compiled html markup code on success otherwise returns a standard error
/// message. /// message.
pub fn settings( pub fn settings(
safe_search_level: u8,
colorscheme: &str, colorscheme: &str,
theme: &str, theme: &str,
animation: &Option<String>, animation: &Option<String>,
engine_names: &[&String], engine_names: &HashMap<String, bool>,
) -> Result<Markup, Box<dyn std::error::Error>> { ) -> Result<Markup, Box<dyn std::error::Error>> {
Ok(html!( Ok(html!(
(header(colorscheme, theme, animation)) (header(colorscheme, theme, animation))
@ -41,8 +46,8 @@ pub fn settings(
.btn onclick="setActiveTab(this)"{"cookies"} .btn onclick="setActiveTab(this)"{"cookies"}
} }
.main_container{ .main_container{
(general()) (general(safe_search_level))
(user_interface()?) (user_interface(theme, colorscheme, animation)?)
(engines(engine_names)) (engines(engine_names))
(cookies()) (cookies())
p class="message"{} p class="message"{}