Browse Source

Add search box

chand1012 1 year ago
parent
commit
0f01a8eda5

+ 1 - 0
README.md

@@ -18,6 +18,7 @@
 * GitHub releases
 * GitHub releases
 * Repository overview
 * Repository overview
 * Site monitor
 * Site monitor
+* Search box
 
 
 #### Themeable
 #### Themeable
 ![multiple color schemes example](docs/images/themes-example.png)
 ![multiple color schemes example](docs/images/themes-example.png)

+ 33 - 0
docs/configuration.md

@@ -21,6 +21,7 @@
   - [Twitch Channels](#twitch-channels)
   - [Twitch Channels](#twitch-channels)
   - [Twitch Top Games](#twitch-top-games)
   - [Twitch Top Games](#twitch-top-games)
   - [iframe](#iframe)
   - [iframe](#iframe)
+  - [Search](#search)
 
 
 ## Intro
 ## Intro
 Configuration is done via a single YAML file and a server restart is required in order for any changes to take effect. Trying to start the server with an invalid config file will result in an error.
 Configuration is done via a single YAML file and a server restart is required in order for any changes to take effect. Trying to start the server with an invalid config file will result in an error.
@@ -1132,3 +1133,35 @@ The source of the iframe.
 
 
 ##### `height`
 ##### `height`
 The height of the iframe. The minimum allowed height is 50.
 The height of the iframe. The minimum allowed height is 50.
+
+### Search
+Display a search bar that can be used to search for specific terms on various search engines.
+
+Example:
+
+```yaml
+- type: search
+  search-url: https://www.google.com/search?q=
+  query: This is a default search
+```
+
+Preview:
+
+![](images/search-widget-preview.png)
+
+#### Properties
+| Name | Type | Required | Default |
+| ---- | ---- | -------- | ------- |
+| search-url | string | no | https://duckduckgo.com/?q= |
+| query | string | no | |
+
+##### `search-url`
+The URL to use for the search. The query will be appended to the end of the URL. Some common examples:
+- Google: `https://www.google.com/search?q=`
+- DuckDuckGo: `https://duckduckgo.com/?q=`
+- Bing: `https://www.bing.com/search?q=`
+- Perplexity AI: `https://perplexity.ai/search?q=`
+- ChatGPT (requires ChatGPT Plus subscription): `https://chatgpt.com/?model=gpt-4o&oai-dm=1&q=`
+
+##### `query`
+The default query to show in the search bar. If left blank the search bar will be empty.

BIN
docs/images/search-widget-preview.png


+ 56 - 0
internal/assets/static/main.css

@@ -1201,3 +1201,59 @@ body {
 .margin-bottom-10   { margin-bottom: 1rem; }
 .margin-bottom-10   { margin-bottom: 1rem; }
 .margin-bottom-15   { margin-bottom: 1.5rem; }
 .margin-bottom-15   { margin-bottom: 1.5rem; }
 .margin-bottom-auto { margin-bottom: auto; }
 .margin-bottom-auto { margin-bottom: auto; }
+
+.search-form {
+    margin: 0;
+    padding: var(--widget-content-padding);
+    background-color: var(--color-background);
+    border-radius: 20px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    width: 100%;
+    display: flex;
+    align-items: center;
+}
+
+.search-input-container {
+    position: relative;
+    width: 100%;
+}
+
+.search-input {
+    width: 100%;
+    padding: 10px 40px 10px 10px;
+    font-size: var(--font-size-h3);
+    border: 1px solid var(--color-widget-content-border);
+    border-radius: 20px;
+    color: white;
+    background: var(--color-background);
+    transition: border-color 0.15s ease;
+}
+
+.search-input:focus {
+    outline: none;
+    border-color: var(--color-primary);
+}
+
+.search-button {
+    position: absolute;
+    right: 10px;
+    top: 50%;
+    transform: translateY(-50%);
+    background: none;
+    border: none;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0;
+}
+
+.search-button svg {
+    width: 24px;
+    height: 24px;
+    color: white;
+}
+
+.search-button:hover svg {
+    color: var(--color-text-highlight);
+}

+ 1 - 0
internal/assets/templates.go

@@ -32,6 +32,7 @@ var (
 	TwitchGamesListTemplate       = compileTemplate("twitch-games-list.html", "widget-base.html")
 	TwitchGamesListTemplate       = compileTemplate("twitch-games-list.html", "widget-base.html")
 	TwitchChannelsTemplate        = compileTemplate("twitch-channels.html", "widget-base.html")
 	TwitchChannelsTemplate        = compileTemplate("twitch-channels.html", "widget-base.html")
 	RepositoryTemplate            = compileTemplate("repository.html", "widget-base.html")
 	RepositoryTemplate            = compileTemplate("repository.html", "widget-base.html")
+	SearchTemplate                = compileTemplate("search.html", "widget-base.html")
 )
 )
 
 
 var globalTemplateFunctions = template.FuncMap{
 var globalTemplateFunctions = template.FuncMap{

+ 18 - 0
internal/assets/templates/search.html

@@ -0,0 +1,18 @@
+{{ template "widget-base.html" . }}
+<!-- Search box  -->
+{{ define "widget-content" }}
+    <form class="search-form" action="{{ .SearchURL }}" method="get">
+      <div class="search-input-container">
+        <input type="text" class="search-input" value name="q" placeholder="Search...">
+        <button type="submit" class="search-button">
+          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
+            class="icon icon-tabler icons-tabler-outline icon-tabler-search">
+            <path stroke="none" d="M0 0h24v24H0z" fill="none" />
+            <path d="M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" />
+            <path d="M21 21l-6 -6" />
+          </svg>
+        </button>
+      </div>
+    </form>
+{{ end }}

+ 30 - 0
internal/widget/search.go

@@ -0,0 +1,30 @@
+package widget
+
+import (
+	"html/template"
+
+	"github.com/glanceapp/glance/internal/assets"
+)
+
+type Search struct {
+	widgetBase `yaml:",inline"`
+	SearchURL  string `yaml:"search-url"`
+	Query      string `yaml:"query"`
+}
+
+func (widget *Search) Initialize() error {
+	widget.withTitle("Search").withError(nil)
+
+	if widget.SearchURL == "" {
+		// set to the duckduckgo search engine
+		widget.SearchURL = "https://duckduckgo.com/?q="
+	}
+
+	// if no query is provided, leave an empty string
+
+	return nil
+}
+
+func (widget *Search) Render() template.HTML {
+	return widget.render(widget, assets.SearchTemplate)
+}

+ 2 - 0
internal/widget/widget.go

@@ -45,6 +45,8 @@ func New(widgetType string) (Widget, error) {
 		return &TwitchChannels{}, nil
 		return &TwitchChannels{}, nil
 	case "repository":
 	case "repository":
 		return &Repository{}, nil
 		return &Repository{}, nil
+	case "search":
+		return &Search{}, nil
 	default:
 	default:
 		return nil, fmt.Errorf("unknown widget type: %s", widgetType)
 		return nil, fmt.Errorf("unknown widget type: %s", widgetType)
 	}
 	}