neon_arch commited on
Commit
0ec8914
1 Parent(s): beb5e60

♻️ refactor(maud): rewrite the frontend code with maud html framework (#302)

Browse files
public/templates/404.html DELETED
@@ -1,10 +0,0 @@
1
- {{>header this}}
2
- <main class="error_container">
3
- <img src="images/robot-404.svg" alt="Image of broken robot." />
4
- <div class="error_content">
5
- <h1>Aw! snap</h1>
6
- <h2>404 Page Not Found!</h2>
7
- <p>Go to <a href="/">search page</a></p>
8
- </div>
9
- </main>
10
- {{>footer}}
 
 
 
 
 
 
 
 
 
 
 
public/templates/about.html DELETED
@@ -1,29 +0,0 @@
1
- {{>header this}}
2
- <main class="about-container">
3
- <article >
4
- <div>
5
- <h1 >Websurfx</h1>
6
- <hr size="4" width="100%" color="#a6e3a1">
7
- </div>
8
- <p>A modern-looking, lightning-fast, privacy-respecting, secure meta search engine written in Rust. It provides a fast and secure search experience while respecting user privacy.<br> It aggregates results from multiple search engines and presents them in an unbiased manner, filtering out trackers and ads.
9
- </p>
10
-
11
- <h2>Some of the Top Features:</h2>
12
-
13
- <ul><strong>Lightning fast </strong>- Results load within milliseconds for an instant search experience.</ul>
14
-
15
- <ul><strong>Secure search</strong> - All searches are performed over an encrypted connection to prevent snooping.</ul>
16
-
17
- <ul><strong>Ad free results</strong> - All search results are ad free and clutter free for a clean search experience.</ul>
18
-
19
- <ul><strong>Privacy focused</strong> - Websurface does not track, store or sell your search data. Your privacy is our priority.</ul>
20
-
21
- <ul><strong>Free and Open source</strong> - The entire project's code is open source and available for free on <a href="https://github.com/neon-mmd/websurfx">GitHub</a> under an GNU Affero General Public License.</ul>
22
-
23
- <ul><strong>Highly customizable</strong> - Websurface comes with 9 built-in color themes and supports creating custom themes effortlessly.</ul>
24
- </article>
25
-
26
- <h3>Devoloped by: <a href="https://github.com/neon-mmd/websurfx">Websurfx team</a></h3>
27
- </main>
28
- {{>footer}}
29
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/bar.html DELETED
@@ -1,3 +0,0 @@
1
- <div class="search_bar">
2
- <input type="search" name="search-box" value="{{this.pageQuery}}" placeholder="Type to search" />
3
- <button type="submit" onclick="searchWeb()">search</button>
 
 
 
 
public/templates/cookies_tab.html DELETED
@@ -1,12 +0,0 @@
1
- <div class="cookies tab">
2
- <h1>Cookies</h1>
3
- <p class="description">
4
- This is the cookies are saved on your system and it contains the preferences
5
- you chose in the settings page
6
- </p>
7
- <input type="text" name="cookie_field" value="" readonly />
8
- <p class="description">
9
- The cookies stored are not used by us for any malicious intend or for
10
- tracking you in any way.
11
- </p>
12
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/engines_tab.html DELETED
@@ -1,32 +0,0 @@
1
- <div class="engines tab">
2
- <h1>Engines</h1>
3
- <h3>select search engines</h3>
4
- <p class="description">
5
- Select the search engines from the list of engines that you want results
6
- from
7
- </p>
8
- <div class="engine_selection">
9
- <div class="toggle_btn">
10
- <label class="switch">
11
- <input type="checkbox" class="select_all" onchange="toggleAllSelection()" />
12
- <span class="slider round"></span>
13
- </label>
14
- Select All
15
- </div>
16
- <hr />
17
- <div class="toggle_btn">
18
- <label class="switch">
19
- <input type="checkbox" class="engine" />
20
- <span class="slider round"></span>
21
- </label>
22
- DuckDuckGo
23
- </div>
24
- <div class="toggle_btn">
25
- <label class="switch">
26
- <input type="checkbox" class="engine" />
27
- <span class="slider round"></span>
28
- </label>
29
- Searx
30
- </div>
31
- </div>
32
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/footer.html DELETED
@@ -1,16 +0,0 @@
1
- <footer>
2
- <div>
3
- <span>Powered By <b>Websurfx</b></span><span>-</span><span>a lightening fast, privacy respecting, secure meta
4
- search engine</span>
5
- </div>
6
- <div>
7
- <ul>
8
- <li><a href="https://github.com/neon-mmd/websurfx">Source Code</a></li>
9
- <li><a href="https://github.com/neon-mmd/websurfx/issues">Issues/Bugs</a></li>
10
- </ul>
11
- </div>
12
- </footer>
13
- <script src="static/settings.js"></script>
14
- </body>
15
-
16
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/general_tab.html DELETED
@@ -1,13 +0,0 @@
1
- <div class="general tab active">
2
- <h1>General</h1>
3
- <h3>Select a safe search level</h3>
4
- <p class="description">
5
- Select a safe search level from the menu below to filter content based on
6
- the level.
7
- </p>
8
- <select name="safe_search_levels">
9
- <option value=0>None</option>
10
- <option value=1>Low</option>
11
- <option value=2>Moderate</option>
12
- </select>
13
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/header.html DELETED
@@ -1,16 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
-
4
- <head>
5
- <title>Websurfx</title>
6
- <meta charset="UTF-8" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1" />
8
- <link href="static/colorschemes/{{colorscheme}}.css" rel="stylesheet" type="text/css" />
9
- <link href="static/themes/{{theme}}.css" rel="stylesheet" type="text/css" />
10
- </head>
11
-
12
- <body onload="getClientSettings()">
13
- <header>
14
- <h1><a href="/">Websurfx</a></h1>
15
- {{>navbar}}
16
- </header>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/index.html DELETED
@@ -1,8 +0,0 @@
1
- {{>header this}}
2
- <main class="search-container">
3
- <img src="../images/websurfx_logo.png" alt="Websurfx meta-search engine logo" />
4
- {{>bar}}
5
- </div>
6
- </main>
7
- <script src="static/index.js"></script>
8
- {{>footer}}
 
 
 
 
 
 
 
 
 
public/templates/navbar.html DELETED
@@ -1,6 +0,0 @@
1
- <nav>
2
- <ul>
3
- <li><a href="about">about</a></li>
4
- <li><a href="settings">settings</a></li>
5
- </ul>
6
- </nav>
 
 
 
 
 
 
 
public/templates/search.html DELETED
@@ -1,86 +0,0 @@
1
- {{>header this.style}}
2
- <main class="results">
3
- {{>search_bar this}}
4
- <div class="results_aggregated">
5
- {{#if results}} {{#each results}}
6
- <div class="result">
7
- <h1><a href="{{{this.url}}}">{{{this.title}}}</a></h1>
8
- <small>{{{this.url}}}</small>
9
- <p>{{{this.description}}}</p>
10
- <div class="upstream_engines">
11
- {{#each engine}}
12
- <span>{{{this}}}</span>
13
- {{/each}}
14
- </div>
15
- </div>
16
- {{/each}} {{else}} {{#if disallowed}}
17
- <div class="result_disallowed">
18
- <div class="description">
19
- <p>
20
- Your search - <span class="user_query">{{{this.pageQuery}}}</span> -
21
- has been disallowed.
22
- </p>
23
- <p class="description_paragraph">Dear user,</p>
24
- <p class="description_paragraph">
25
- The query - <span class="user_query">{{{this.pageQuery}}}</span> - has
26
- been blacklisted via server configuration and hence disallowed by the
27
- server. Henceforth no results could be displayed for your query.
28
- </p>
29
- </div>
30
- <img src="./images/barricade.png" alt="Image of a Barricade" />
31
- </div>
32
- {{else}} {{#if filtered}}
33
- <div class="result_filtered">
34
- <div class="description">
35
- <p>
36
- Your search - <span class="user_query">{{{this.pageQuery}}}</span> -
37
- has been filtered.
38
- </p>
39
- <p class="description_paragraph">Dear user,</p>
40
- <p class="description_paragraph">
41
- All the search results contain results that has been configured to be
42
- filtered out via server configuration and henceforth has been
43
- completely filtered out.
44
- </p>
45
- </div>
46
- <img src="./images/filter.png" alt="Image of a paper inside a funnel" />
47
- </div>
48
- {{else}} {{#if noEnginesSelected}}
49
- <div class="result_engine_not_selected">
50
- <div class="description">
51
- <p>
52
- No results could be fetched for your search "<span class="user_query">{{{this.pageQuery}}}</span>" .
53
- </p>
54
- <p class="description_paragraph">Dear user,</p>
55
- <p class="description_paragraph">
56
- No results could be retrieved from the upstream search engines as no
57
- upstream search engines were selected from the settings page.
58
- </p>
59
- </div>
60
- <img src="./images/no_selection.png" alt="Image of a white cross inside a red circle" />
61
- </div>
62
- {{else}}
63
- <div class="result_not_found">
64
- <p>Your search - {{{this.pageQuery}}} - did not match any documents.</p>
65
- <p class="suggestions">Suggestions:</p>
66
- <ul>
67
- <li>Make sure that all words are spelled correctly.</li>
68
- <li>Try different keywords.</li>
69
- <li>Try more general keywords.</li>
70
- </ul>
71
- <img src="./images/no_results.gif" alt="Man fishing gif" />
72
- </div>
73
- {{/if}} {{/if}} {{/if}} {{/if}}
74
- </div>
75
- <div class="page_navigation">
76
- <button type="button" onclick="navigate_backward()">
77
- &#8592; previous
78
- </button>
79
- <button type="button" onclick="navigate_forward()">next &#8594;</button>
80
- </div>
81
- </main>
82
- <script src="static/index.js"></script>
83
- <script src="static/search_area_options.js"></script>
84
- <script src="static/pagination.js"></script>
85
- <script src="static/error_box.js"></script>
86
- {{>footer}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/search_bar.html DELETED
@@ -1,36 +0,0 @@
1
- <div class="search_area">
2
- {{>bar this}}
3
- <div class="error_box">
4
- {{#if engineErrorsInfo}}
5
- <button onclick="toggleErrorBox()" class="error_box_toggle_button">
6
- <img src="./images/warning.svg" alt="Info icon for error box" />
7
- </button>
8
- <div class="dropdown_error_box">
9
- {{#each engineErrorsInfo}}
10
- <div class="error_item">
11
- <span class="engine_name">{{{this.engine}}}</span>
12
- <span class="engine_name">{{{this.error}}}</span>
13
- <span class="severity_color" style="background: {{{this.severity_color}}};"></span>
14
- </div>
15
- {{/each}}
16
- </div>
17
- {{else}}
18
- <button onclick="toggleErrorBox()" class="error_box_toggle_button">
19
- <img src="./images/info.svg" alt="Warning icon for error box" />
20
- </button>
21
- <div class="dropdown_error_box">
22
- <div class="no_errors">
23
- Everything looks good 🙂!!
24
- </div>
25
- </div>
26
- {{/if}}
27
- </div>
28
- </div>
29
- <div class="search_options">
30
- <select name="safe_search_levels" {{#if (gte safeSearchLevel 3)}} disabled {{/if}}>
31
- <option value=0 {{#if (eq safeSearchLevel 0)}} selected {{/if}}>SafeSearch: None</option>
32
- <option value=1 {{#if (eq safeSearchLevel 1)}} selected {{/if}}>SafeSearch: Low</option>
33
- <option value=2 {{#if (eq safeSearchLevel 2)}} selected {{/if}}>SafeSearch: Moderate</option>
34
- </select>
35
- </div>
36
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/settings.html DELETED
@@ -1,22 +0,0 @@
1
- {{>header this}}
2
- <main class="settings" >
3
- <h1>Settings</h1>
4
- <hr />
5
- <div class="settings_container">
6
- <div class="sidebar">
7
- <div class="btn active" onclick="setActiveTab(this)">general</div>
8
- <div class="btn" onclick="setActiveTab(this)">user interface</div>
9
- <div class="btn" onclick="setActiveTab(this)">engines</div>
10
- <div class="btn" onclick="setActiveTab(this)">cookies</div>
11
- </div>
12
- <div class="main_container">
13
- {{> general_tab}} {{> user_interface_tab}} {{> engines_tab}} {{>
14
- cookies_tab}}
15
- <p class="message"></p>
16
- <button type="submit" onclick="setClientSettings()">Save</button>
17
- </div>
18
- </div>
19
- </main>
20
- <script src="static/settings.js"></script>
21
- <script src="static/cookies.js"></script>
22
- {{>footer}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/templates/user_interface_tab.html DELETED
@@ -1,28 +0,0 @@
1
- <div class="user_interface tab">
2
- <h1>User Interface</h1>
3
- <h3>select theme</h3>
4
- <p class="description">
5
- Select the theme from the available themes to be used in user interface
6
- </p>
7
- <select name="themes">
8
- <option value="simple">simple</option>
9
- </select>
10
- <h3>select color scheme</h3>
11
- <p class="description">
12
- Select the color scheme for your theme to be used in user interface
13
- </p>
14
- <select name="colorschemes">
15
- <option value="catppuccin-mocha">catppuccin mocha</option>
16
- <option value="dark-chocolate">dark chocolate</option>
17
- <option value="dracula">dracula</option>
18
- <option value="gruvbox-dark">gruvbox dark</option>
19
- <option value="monokai">monokai</option>
20
- <option value="nord">nord</option>
21
- <option value="oceanic-next">oceanic next</option>
22
- <option value="one-dark">one dark</option>
23
- <option value="solarized-dark">solarized dark</option>
24
- <option value="solarized-light">solarized light</option>
25
- <option value="tokyo-night">tokyo night</option>
26
- <option value="tomorrow-night">tomorrow night</option>
27
- </select>
28
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/templates/mod.rs ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ //!
2
+
3
+ mod partials;
4
+ pub mod views;
src/templates/partials/bar.rs ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup,PreEscaped};
4
+
5
+ ///
6
+ pub fn bar(query: &str) -> Markup {
7
+ html!(
8
+ (PreEscaped("<div class=\"search_bar\">"))
9
+ input type="search" name="search-box" value=(query) placeholder="Type to search";
10
+ button type="submit" onclick="searchWeb()"{"search"}
11
+ )
12
+ }
src/templates/partials/footer.rs ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup, PreEscaped};
4
+
5
+ ///
6
+ pub fn footer() -> Markup {
7
+ html!(
8
+ footer{
9
+ div{
10
+ span{"Powered By "b{"Websurfx"}}span{"-"}span{"a lightening fast, privacy respecting, secure meta
11
+ search engine"}
12
+ }
13
+ div{
14
+ ul{
15
+ li{a href="https://github.com/neon-mmd/websurfx"{"Source Code"}}
16
+ li{a href="https://github.com/neon-mmd/websurfx/issues"{"Issues/Bugs"}}
17
+ }
18
+ }
19
+ }
20
+ script src="static/settings.js"{}
21
+ (PreEscaped("</body>"))
22
+ (PreEscaped("</html>"))
23
+ )
24
+ }
src/templates/partials/header.rs ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use crate::templates::partials::navbar::navbar;
4
+ use maud::{html, Markup, PreEscaped, DOCTYPE};
5
+
6
+ ///
7
+ pub fn header(colorscheme: &str, theme: &str) -> Markup {
8
+ html!(
9
+ (DOCTYPE)
10
+ html lang="en"
11
+
12
+ head{
13
+ title{"Websurfx"}
14
+ meta charset="UTF-8";
15
+ meta name="viewport" content="width=device-width, initial-scale=1";
16
+ link href=(format!("static/colorschemes/{colorscheme}.css")) rel="stylesheet" type="text/css";
17
+ link href=(format!("static/themes/{theme}.css")) rel="stylesheet" type="text/css";
18
+ }
19
+
20
+ (PreEscaped("<body onload=\"getClientSettings()\">"))
21
+ header{
22
+ h1{a href="/"{"Websurfx"}}
23
+ (navbar())
24
+ }
25
+ )
26
+ }
src/templates/partials/mod.rs ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ pub mod footer;
4
+ pub mod header;
5
+ pub mod navbar;
6
+ pub mod bar;
7
+ pub mod settings_tabs;
8
+ pub mod search_bar;
src/templates/partials/navbar.rs ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup};
4
+
5
+ ///
6
+ pub fn navbar() -> Markup {
7
+ html!(
8
+ nav{
9
+ ul{
10
+ li{a href="about"{"about"}}
11
+ li{a href="settings"{"settings"}}
12
+ }
13
+ }
14
+ )
15
+ }
src/templates/partials/search_bar.rs ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup, PreEscaped};
4
+
5
+ use crate::{models::aggregation_models::EngineErrorInfo, templates::partials::bar::bar};
6
+
7
+ const SAFE_SEARCH_LEVELS_NAME: [&str; 3] = ["None", "Low", "Moderate"];
8
+
9
+ ///
10
+ pub fn search_bar(
11
+ engine_errors_info: &[EngineErrorInfo],
12
+ safe_search_level: u8,
13
+ query: &str,
14
+ ) -> Markup {
15
+ html!(
16
+ .search_area{
17
+ (bar(query))
18
+ .error_box {
19
+ @if !engine_errors_info.is_empty(){
20
+ button onclick="toggleErrorBox()" class="error_box_toggle_button"{
21
+ img src="./images/warning.svg" alt="Info icon for error box";
22
+ }
23
+ .dropdown_error_box{
24
+ @for errors in engine_errors_info{
25
+ .error_item{
26
+ span class="engine_name"{(errors.engine)}
27
+ span class="engine_name"{(errors.error)}
28
+ span class="severity_color" style="background: {{{this.severity_color}}};"{}
29
+ }
30
+ }
31
+ }
32
+ }
33
+ @else {
34
+ button onclick="toggleErrorBox()" class="error_box_toggle_button"{
35
+ img src="./images/info.svg" alt="Warning icon for error box";
36
+ }
37
+ .dropdown_error_box {
38
+ .no_errors{
39
+ "Everything looks good 🙂!!"
40
+ }
41
+ }
42
+ }
43
+ }
44
+ (PreEscaped("</div>"))
45
+ .search_options {
46
+ @if safe_search_level >= 3 {
47
+ (PreEscaped("<select name=\"safe_search_levels\" disabled>"))
48
+ }
49
+ @else{
50
+ (PreEscaped("<select name=\"safe_search_levels\">"))
51
+ }
52
+ @for (idx, name) in SAFE_SEARCH_LEVELS_NAME.iter().enumerate() {
53
+ @if (safe_search_level as usize) == idx {
54
+ option value=(idx) selected {(format!("SafeSearch: {name}"))}
55
+ }
56
+ @else{
57
+ option value=(idx) {(format!("SafeSearch: {name}"))}
58
+ }
59
+ }
60
+ (PreEscaped("</select>"))
61
+ }
62
+ }
63
+ )
64
+ }
src/templates/partials/settings_tabs/cookies.rs ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup};
4
+
5
+ ///
6
+ pub fn cookies() -> Markup {
7
+ html!(
8
+ div class="cookies tab"{
9
+ h1{"Cookies"}
10
+ p class="description"{
11
+ "This is the cookies are saved on your system and it contains the preferences
12
+ you chose in the settings page"
13
+ }
14
+ input type="text" name="cookie_field" value="" readonly;
15
+ p class="description"{
16
+ "The cookies stored are not used by us for any malicious intend or for
17
+ tracking you in any way."
18
+ }
19
+ }
20
+ )
21
+ }
src/templates/partials/settings_tabs/engines.rs ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup};
4
+
5
+ ///
6
+ pub fn engines(engine_names: &[&String]) -> Markup {
7
+ html!(
8
+ div class="engines tab"{
9
+ h1{"Engines"}
10
+ h3{"select search engines"}
11
+ p class="description"{
12
+ "Select the search engines from the list of engines that you want results from"
13
+ }
14
+ .engine_selection{
15
+ .toggle_btn{
16
+ label class="switch"{
17
+ input type="checkbox" class="select_all" onchange="toggleAllSelection()";
18
+ span class="slider round"{}
19
+ }
20
+ "Select All"
21
+ }
22
+ hr;
23
+ @for engine_name in engine_names{
24
+ .toggle_btn{
25
+ label class="switch"{
26
+ input type="checkbox" class="engine";
27
+ span class="slider round"{}
28
+ }
29
+ (format!("{}{}",engine_name[..1].to_uppercase().to_owned(), engine_name[1..].to_owned()))
30
+ }
31
+ }
32
+ }
33
+ }
34
+ )
35
+ }
src/templates/partials/settings_tabs/general.rs ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup};
4
+
5
+ const SAFE_SEARCH_LEVELS: [(u8, &'static str); 3] = [(0, "None"), (1, "Low"), (2, "Moderate")];
6
+
7
+ ///
8
+ pub fn general() -> Markup {
9
+ html!(
10
+ div class="general tab active"{
11
+ h1{"General"}
12
+ h3{"Select a safe search level"}
13
+ p class="description"{
14
+ "Select a safe search level from the menu below to filter content based on the level."
15
+ }
16
+ select name="safe_search_levels"{
17
+ @for (k,v) in SAFE_SEARCH_LEVELS{
18
+ option value=(k){(v)}
19
+ }
20
+ }
21
+ }
22
+ )
23
+ }
src/templates/partials/settings_tabs/mod.rs ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ pub mod general;
4
+ pub mod engines;
5
+ pub mod cookies;
6
+ pub mod user_interface;
src/templates/partials/settings_tabs/user_interface.rs ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use crate::handler::paths::{file_path, FileType};
4
+ use maud::{html, Markup};
5
+ use std::fs::read_dir;
6
+
7
+ fn style_option_list(
8
+ style_type: &str,
9
+ ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error + '_>> {
10
+ let mut style_option_names: Vec<(String, String)> = Vec::new();
11
+ for file in read_dir(format!(
12
+ "{}static/{}/",
13
+ file_path(FileType::Theme)?,
14
+ style_type,
15
+ ))? {
16
+ let style_name = file?.file_name().to_str().unwrap().replace(".css", "");
17
+ style_option_names.push((style_name.clone(), style_name.replace("-", " ")));
18
+ }
19
+
20
+ Ok(style_option_names)
21
+ }
22
+
23
+ ///
24
+ pub fn user_interface() -> Result<Markup, Box<dyn std::error::Error>> {
25
+ Ok(html!(
26
+ div class="user_interface tab"{
27
+ h1{"User Interface"}
28
+ h3{"select theme"}
29
+ p class="description"{
30
+ "Select the theme from the available themes to be used in user interface"
31
+ }
32
+ select name="themes"{
33
+ @for (k,v) in style_option_list("themes")?{
34
+ option value=(k){(v)}
35
+ }
36
+ }
37
+ h3{"select color scheme"}
38
+ p class="description"{
39
+ "Select the color scheme for your theme to be used in user interface"
40
+ }
41
+ select name="colorschemes"{
42
+ @for (k,v) in style_option_list("colorschemes")?{
43
+ option value=(k){(v)}
44
+ }
45
+ }
46
+ }
47
+ ))
48
+ }
src/templates/views/about.rs ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup};
4
+
5
+ use crate::templates::partials::{footer::footer, header::header};
6
+
7
+ ///
8
+ pub fn about(colorscheme: &str, theme: &str) -> Markup {
9
+ html!(
10
+ (header(colorscheme, theme))
11
+ main class="about-container"{
12
+ article {
13
+ div{
14
+ h1{"Websurfx"}
15
+ hr size="4" width="100%" color="#a6e3a1"{}
16
+ }
17
+ p{"A modern-looking, lightning-fast, privacy-respecting, secure meta search engine written in Rust. It provides a fast and secure search experience while respecting user privacy."br{}" It aggregates results from multiple search engines and presents them in an unbiased manner, filtering out trackers and ads."
18
+ }
19
+
20
+ h2{"Some of the Top Features:"}
21
+
22
+ ul{strong{"Lightning fast "}"- Results load within milliseconds for an instant search experience."}
23
+
24
+ ul{strong{"Secure search"}" - All searches are performed over an encrypted connection to prevent snooping."}
25
+
26
+ ul{strong{"Ad free results"}" - All search results are ad free and clutter free for a clean search experience."}
27
+
28
+ ul{strong{"Privacy focused"}" - Websurfx does not track, store or sell your search data. Your privacy is our priority."}
29
+
30
+ ul{strong{"Free and Open source"}" - The entire project's code is open source and available for free on "{a href="https://github.com/neon-mmd/websurfx"{"GitHub"}}" under an GNU Affero General Public License."}
31
+
32
+ ul{strong{"Highly customizable"}" - Websurfx comes with 9 built-in color themes and supports creating custom themes effortlessly."}
33
+ }
34
+
35
+ h3{"Devoloped by: "{a href="https://github.com/neon-mmd/websurfx"{"Websurfx team"}}}
36
+ }
37
+ (footer())
38
+ )
39
+ }
src/templates/views/index.rs ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup, PreEscaped};
4
+
5
+ use crate::templates::partials::{bar::bar, footer::footer, header::header};
6
+
7
+ ///
8
+ pub fn index(colorscheme: &str, theme: &str, query: &str) -> Markup {
9
+ html!(
10
+ (header(colorscheme, theme))
11
+ main class="search-container"{
12
+ img src="../images/websurfx_logo.png" alt="Websurfx meta-search engine logo";
13
+ (bar(query))
14
+ (PreEscaped("</div>"))
15
+ }
16
+ script src="static/index.js"{}
17
+ (footer())
18
+ )
19
+ }
src/templates/views/mod.rs ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ pub mod about;
4
+ pub mod index;
5
+ pub mod not_found;
6
+ pub mod settings;
7
+ pub mod search;
src/templates/views/not_found.rs ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use crate::templates::partials::{footer::footer, header::header};
4
+ use maud::{html, Markup};
5
+
6
+ ///
7
+ pub fn not_found(colorscheme: &str, theme: &str) -> Markup {
8
+ html!(
9
+ (header(colorscheme, theme))
10
+ main class="error_container"{
11
+ img src="images/robot-404.svg" alt="Image of broken robot.";
12
+ div class="error_content"{
13
+ h1{"Aw! snap"}
14
+ h2{"404 Page Not Found!"}
15
+ p{"Go to "{a href="/"{"search page"}}}
16
+ }
17
+ }
18
+ (footer())
19
+ )
20
+ }
src/templates/views/search.rs ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup, PreEscaped};
4
+
5
+ use crate::{
6
+ models::aggregation_models::SearchResults,
7
+ templates::partials::{footer::footer, header::header, search_bar::search_bar},
8
+ };
9
+
10
+ ///
11
+ pub fn search(
12
+ colorscheme: &str,
13
+ theme: &str,
14
+ query: &str,
15
+ search_results: &SearchResults,
16
+ ) -> Markup {
17
+ html!(
18
+ (header(colorscheme, theme))
19
+ main class="results"{
20
+ (search_bar(&search_results.engine_errors_info, search_results.safe_search_level, query))
21
+ .results_aggregated{
22
+ @if !search_results.results.is_empty() {
23
+ @for result in search_results.results.iter(){
24
+ .result {
25
+ h1{a href=(result.url){(PreEscaped(&result.title))}}
26
+ small{(result.url)}
27
+ p{(PreEscaped(&result.description))}
28
+ .upstream_engines{
29
+ @for name in result.clone().engine{
30
+ span{(name)}
31
+ }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ @else if search_results.disallowed{
37
+ .result_disallowed{
38
+ .description{
39
+ p{
40
+ "Your search - "{span class="user_query"{(query)}}" -
41
+ has been disallowed."
42
+ }
43
+ p class="description_paragraph"{"Dear user,"}
44
+ p class="description_paragraph"{
45
+ "The query - "{span class="user_query"{(query)}}" - has
46
+ been blacklisted via server configuration and hence disallowed by the
47
+ server. Henceforth no results could be displayed for your query."
48
+ }
49
+ }
50
+ img src="./images/barricade.png" alt="Image of a Barricade";
51
+ }
52
+ }
53
+ @else if search_results.filtered {
54
+ .result_filtered{
55
+ .description{
56
+ p{
57
+ "Your search - "{span class="user_query"{(query)}}" -
58
+ has been filtered."
59
+ }
60
+ p class="description_paragraph"{"Dear user,"}
61
+ p class="description_paragraph"{
62
+ "All the search results contain results that has been configured to be
63
+ filtered out via server configuration and henceforth has been
64
+ completely filtered out."
65
+ }
66
+ }
67
+ img src="./images/filter.png" alt="Image of a paper inside a funnel";
68
+ }
69
+ }
70
+ @else if search_results.no_engines_selected {
71
+ .result_engine_not_selected{
72
+ .description{
73
+ p{
74
+ "No results could be fetched for your search '{span class="user_query"{(query)}}'."
75
+ }
76
+ p class="description_paragraph"{"Dear user,"}
77
+ p class="description_paragraph"{
78
+ "No results could be retrieved from the upstream search engines as no
79
+ upstream search engines were selected from the settings page."
80
+ }
81
+ }
82
+ img src="./images/no_selection.png" alt="Image of a white cross inside a red circle";
83
+ }
84
+ }
85
+ @else{
86
+ .result_not_found {
87
+ p{"Your search - "{(query)}" - did not match any documents."}
88
+ p class="suggestions"{"Suggestions:"}
89
+ ul{
90
+ li{"Make sure that all words are spelled correctly."}
91
+ li{"Try different keywords."}
92
+ li{"Try more general keywords."}
93
+ }
94
+ img src="./images/no_results.gif" alt="Man fishing gif";
95
+ }
96
+ }
97
+ }
98
+ .page_navigation {
99
+ button type="button" onclick="navigate_backward()"{
100
+ (PreEscaped("&#8592;")) "previous"
101
+ }
102
+ button type="button" onclick="navigate_forward()"{"next" (PreEscaped("&#8594;"))}
103
+ }
104
+ }
105
+ script src="static/index.js"{}
106
+ script src="static/search_area_options.js"{}
107
+ script src="static/pagination.js"{}
108
+ script src="static/error_box.js"{}
109
+ (footer())
110
+ )
111
+ }
src/templates/views/settings.rs ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //!
2
+
3
+ use maud::{html, Markup};
4
+
5
+ use crate::templates::partials::{
6
+ footer::footer,
7
+ header::header,
8
+ settings_tabs::{
9
+ cookies::cookies, engines::engines, general::general, user_interface::user_interface,
10
+ },
11
+ };
12
+
13
+ ///
14
+ pub fn settings(
15
+ colorscheme: &str,
16
+ theme: &str,
17
+ engine_names: &[&String],
18
+ ) -> Result<Markup, Box<dyn std::error::Error>> {
19
+ Ok(html!(
20
+ (header(colorscheme, theme))
21
+ main class="settings"{
22
+ h1{"Settings"}
23
+ hr;
24
+ .settings_container{
25
+ .sidebar{
26
+ div class="btn active" onclick="setActiveTab(this)"{"general"}
27
+ .btn onclick="setActiveTab(this)"{"user interface"}
28
+ .btn onclick="setActiveTab(this)"{"engines"}
29
+ .btn onclick="setActiveTab(this)"{"cookies"}
30
+ }
31
+ .main_container{
32
+ (general())
33
+ (user_interface()?)
34
+ (engines(engine_names))
35
+ (cookies())
36
+ p class="message"{}
37
+ button type="submit" onclick="setClientSettings()"{"Save"}
38
+ }
39
+ }
40
+ }
41
+ script src="static/settings.js"{}
42
+ script src="static/cookies.js"{}
43
+ (footer())
44
+ ))
45
+ }