add search engine - ringle
This commit is contained in:
96
search-engine/frontend/search.html
Normal file
96
search-engine/frontend/search.html
Normal file
@@ -0,0 +1,96 @@
|
||||
<head>
|
||||
<title>Gurted Search Engine</title>
|
||||
<meta name="description" content="Search across all registered GURT domains">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<icon src="https://cdn-icons-png.flaticon.com/512/295/295128.png">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-sans bg-[#000000] text-[#ffffff] min-h-screen flex flex-col items-center p-8
|
||||
}
|
||||
|
||||
.search-container {
|
||||
max-w-2xl w-full flex flex-col gap-8
|
||||
}
|
||||
|
||||
.logo {
|
||||
text-center text-5xl font-bold text-[#dc2626] mb-8
|
||||
}
|
||||
|
||||
.search-box {
|
||||
flex flex-col gap-4
|
||||
}
|
||||
|
||||
.search-input {
|
||||
w-[600px] p-3 text-base bg-[#1a1a1a] border-2 border-[#333333] rounded-lg text-[#ffffff] outline-none active:border-[#dc2626]
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
bg-[#1a1a1a] text-[#ffffff] px-4 py-2 rounded text-sm border border-[#333333] cursor-pointer hover:border-[#dc2626] hover:shadow-sm
|
||||
}
|
||||
|
||||
.results {
|
||||
w-full flex flex-col gap-4 mt-8
|
||||
}
|
||||
|
||||
.result-item {
|
||||
p-4 cursor-pointer hover:bg-[#0a0a0a] rounded
|
||||
}
|
||||
|
||||
.result-header {
|
||||
inline-flex gap-2 mb-2
|
||||
}
|
||||
|
||||
.result-icon {
|
||||
w-6 h-6 min-w-6 min-h-6 rounded border border-[#333333] bg-[#1a1a1a] object-cover mt-1
|
||||
}
|
||||
|
||||
.result-content {
|
||||
flex-1 min-w-0
|
||||
}
|
||||
|
||||
.result-title {
|
||||
text-xl font-normal text-[#dc2626] mb-1 hover:underline
|
||||
}
|
||||
|
||||
.result-url {
|
||||
text-[#4ade80] text-sm mb-2
|
||||
}
|
||||
|
||||
.result-preview {
|
||||
text-[#cccccc] text-sm leading-relaxed
|
||||
}
|
||||
|
||||
.stats {
|
||||
text-left text-[#999999] text-sm mt-4 ml-1
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-center text-[#999999] mt-8
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="search.lua" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="search-container">
|
||||
<h1 style="logo">Ringle</h1>
|
||||
|
||||
<div style="w-full flex flex-col gap-4 items-center justify-center content-center">
|
||||
<input type="text" id="searchQuery" style="search-input" placeholder="Search across the Gurted..." />
|
||||
<div style="inline-flex gap-2 items-center justify-center">
|
||||
<button id="searchButton" style="search-btn">Search</button>
|
||||
<button id="luckyButton" style="search-btn">I'm feeling lucky</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="loading" style="loading hidden">
|
||||
Searching...
|
||||
</div>
|
||||
|
||||
<div id="results" style="results"></div>
|
||||
|
||||
<div id="stats" style="stats"></div>
|
||||
</div>
|
||||
</body>
|
||||
150
search-engine/frontend/search.lua
Normal file
150
search-engine/frontend/search.lua
Normal file
@@ -0,0 +1,150 @@
|
||||
local searchBtn = gurt.select('#searchButton')
|
||||
local luckyBtn = gurt.select('#luckyButton')
|
||||
local searchQuery = gurt.select('#searchQuery')
|
||||
local loading = gurt.select('#loading')
|
||||
local results = gurt.select('#results')
|
||||
local stats = gurt.select('#stats')
|
||||
|
||||
local function showLoading()
|
||||
loading.classList:remove('hidden')
|
||||
results.text = ''
|
||||
stats.text = ''
|
||||
end
|
||||
|
||||
local function displayResults(data)
|
||||
loading.classList:add('hidden')
|
||||
results.text = ''
|
||||
|
||||
if not data.results or #data.results == 0 then
|
||||
local noResultsItem = gurt.create('div', {
|
||||
text = 'No results found for your query.',
|
||||
style = 'result-item'
|
||||
})
|
||||
results:append(noResultsItem)
|
||||
stats.text = 'No results found'
|
||||
return
|
||||
end
|
||||
|
||||
for i, result in ipairs(data.results) do
|
||||
local resultItem = gurt.create('div', { style = 'result-item' })
|
||||
|
||||
resultItem:on('click', function()
|
||||
gurt.location.goto(result.url)
|
||||
end)
|
||||
|
||||
local headerDiv = gurt.create('div', { style = 'result-header' })
|
||||
|
||||
if result.icon and result.icon ~= '' then
|
||||
local iconImg = gurt.create('img', {
|
||||
src = result.icon,
|
||||
style = 'result-icon',
|
||||
alt = 'Site icon'
|
||||
})
|
||||
headerDiv:append(iconImg)
|
||||
end
|
||||
|
||||
local titleDiv = gurt.create('p', {
|
||||
text = result.title or result.url,
|
||||
style = 'result-title'
|
||||
})
|
||||
|
||||
headerDiv:append(titleDiv)
|
||||
|
||||
local urlDiv = gurt.create('p', {
|
||||
text = result.url,
|
||||
style = 'result-url'
|
||||
})
|
||||
|
||||
local previewText = result.preview or result.description or ''
|
||||
if #previewText > 150 then
|
||||
previewText = previewText:sub(1, 147) .. '...'
|
||||
end
|
||||
|
||||
local previewDiv = gurt.create('p', {
|
||||
text = previewText,
|
||||
style = 'result-preview'
|
||||
})
|
||||
|
||||
resultItem:append(headerDiv)
|
||||
resultItem:append(urlDiv)
|
||||
resultItem:append(previewDiv)
|
||||
|
||||
results:append(resultItem)
|
||||
end
|
||||
|
||||
local resultCount = #data.results
|
||||
local totalResults = data.total_results or resultCount
|
||||
stats.text = 'Found ' .. totalResults .. ' result' .. (totalResults == 1 and '' or 's')
|
||||
end
|
||||
|
||||
local function performSearch(query)
|
||||
if not query or query == '' then
|
||||
return
|
||||
end
|
||||
|
||||
showLoading()
|
||||
|
||||
local url = '/api/search?q=' .. urlEncode(query) .. '&per_page=20'
|
||||
local response = fetch(url, {
|
||||
method = 'GET'
|
||||
})
|
||||
|
||||
if response:ok() then
|
||||
local data = response:json()
|
||||
displayResults(data)
|
||||
else
|
||||
loading.classList:add('hidden')
|
||||
results.text = ''
|
||||
stats.text = 'Search failed: ' .. response.status .. ' ' .. response.statusText
|
||||
end
|
||||
end
|
||||
|
||||
local function performLuckySearch()
|
||||
showLoading()
|
||||
|
||||
local luckyTerms = {'test', 'demo', 'api', 'web', 'site', 'page', 'home', 'index'}
|
||||
local randomTerm = luckyTerms[math.random(#luckyTerms)]
|
||||
|
||||
local url = '/api/search?q=' .. urlEncode(randomTerm) .. '&per_page=50'
|
||||
local response = fetch(url, {
|
||||
method = 'GET'
|
||||
})
|
||||
|
||||
if response:ok() then
|
||||
local data = response:json()
|
||||
if data.results and #data.results > 0 then
|
||||
local randomResult = data.results[math.random(#data.results)]
|
||||
gurt.location.goto(randomResult.url)
|
||||
else
|
||||
loading.classList:add('hidden')
|
||||
results.text = ''
|
||||
stats.text = 'No sites available for lucky search'
|
||||
end
|
||||
else
|
||||
loading.classList:add('hidden')
|
||||
results.text = ''
|
||||
stats.text = 'Lucky search failed'
|
||||
end
|
||||
end
|
||||
|
||||
searchBtn:on('click', function()
|
||||
local query = searchQuery.value
|
||||
if query and query ~= '' then
|
||||
performSearch(query:trim())
|
||||
end
|
||||
end)
|
||||
|
||||
luckyBtn:on('click', function()
|
||||
performLuckySearch()
|
||||
end)
|
||||
|
||||
searchQuery:on('keydown', function(e)
|
||||
if e.key == 'Enter' then
|
||||
local query = searchQuery.value
|
||||
if query and query ~= '' then
|
||||
performSearch(query:trim())
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
searchQuery:focus()
|
||||
Reference in New Issue
Block a user