All checks were successful
ci/woodpecker/push/build/1 Pipeline was successful
ci/woodpecker/push/build/2 Pipeline was successful
ci/woodpecker/push/manifest Pipeline was successful
ci/woodpecker/tag/build/1 Pipeline was successful
ci/woodpecker/release/build/1 Pipeline was successful
ci/woodpecker/release/build/2 Pipeline was successful
ci/woodpecker/release/manifest Pipeline was successful
ci/woodpecker/tag/build/2 Pipeline was successful
ci/woodpecker/tag/manifest Pipeline was successful
187 lines
8.6 KiB
HTML
187 lines
8.6 KiB
HTML
#macro("head"):
|
|
<script>
|
|
async function getSuggestions(repo, input) {
|
|
input = input.trim();
|
|
if (repo.length == 0 || input.length == 0) return [];
|
|
const res = await fetch("/suggestions?" + new URLSearchParams({
|
|
'input': input,
|
|
'repo': repo,
|
|
}))
|
|
if (!res.ok) {
|
|
let resData = await res.json();
|
|
throw new Error(`[suggestions] ${resData.error} (HTTP ${res.status})`)
|
|
}
|
|
return await res.json();
|
|
}
|
|
|
|
function pushTag(tags, input) {
|
|
const splitTag = input.value.split('=');
|
|
if (splitTag.length != 2) {
|
|
input.classList.add('is-danger');
|
|
} else {
|
|
input.classList.remove('is-danger');
|
|
tags.push(splitTag);
|
|
input.value = "";
|
|
}
|
|
}
|
|
</script>
|
|
#!macro
|
|
|
|
#macro("content"):
|
|
<div class="is-flex is-flex-direction-column is-align-items-center image is-16x9 mb-4">
|
|
<img src="/assets/logo/distrohop.svg" style="max-width: 500px" alt="Distrohop Logo">
|
|
</div>
|
|
|
|
<section
|
|
x-data="{activeTab: new URLSearchParams(location.search).get('tab') || 'pkg', nav: false}"
|
|
x-init="$watch('activeTab', (val) => {
|
|
if (nav) {
|
|
nav = false;
|
|
return;
|
|
}
|
|
const url = new URL(window.location.href);
|
|
url.searchParams.set('tab', val);
|
|
history.pushState(null, document.title, url.toString());
|
|
})"
|
|
@popstate.window="nav = true; activeTab = new URLSearchParams(location.search).get('tab') || 'pkg'"
|
|
>
|
|
<div class="tabs is-centered">
|
|
<ul>
|
|
<li :class="{'is-active': activeTab == 'pkg'}" @click="activeTab = 'pkg'"><a>Search by Package</a></li>
|
|
<li :class="{'is-active': activeTab == 'tags'}" @click="activeTab = 'tags'"><a>Search by Tags</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div x-cloak x-transition:enter x-show="activeTab == 'pkg'" class="columns">
|
|
<form x-data="{'suggestions': []}" class="column is-half is-offset-one-quarter has-text-centered" action="/search/pkg">
|
|
<label class="label mb-0" for="from">Search For:</label>
|
|
<div class="icon-text has-text-grey">
|
|
<span class="icon is-aligned">#icon("material-symbols/info-outline")</span>
|
|
<p class="is-size-7 has-text-grey">
|
|
Try searching for archlinux
|
|
<a href="/search/pkg?from=archlinux&pkg=firefox&in=debian-bookworm"><code>firefox</code></a>
|
|
in debian-bookworm.
|
|
</p>
|
|
</div>
|
|
<div class="field has-addons is-align-self-stretch" id="from">
|
|
<div class="control">
|
|
<span class="select">
|
|
<select name="from" x-ref="from" class="is-clipped" autocomplete="off" required>
|
|
<option selected disabled value="">Select Repo...</option>
|
|
#for(repo in cfg.Repos):
|
|
<option>#(repo.Name)</option>
|
|
#!for
|
|
</select>
|
|
</span>
|
|
</div>
|
|
<div class="control is-expanded">
|
|
<p @click.outside="suggestions = []">
|
|
<input @keyup.debounce="suggestions = await getSuggestions($refs.from.value, $refs.pkg.value)" x-ref="pkg" class="input" name="pkg" type="text" placeholder="Package Name" autocomplete="off">
|
|
</p>
|
|
<div class="dropdown is-active" x-show="suggestions.length > 0" x-anchor.bottom-start="$refs.pkg" style="z-index: 1000; width: 100%">
|
|
<div class="dropdown-content" style="width: 100%">
|
|
<template x-for="suggestion in suggestions">
|
|
<button @click.prevent="$refs.pkg.value = suggestion; suggestions = []" :title="suggestion" x-text="suggestion" class="dropdown-item is-clipped" style="text-overflow: ellipsis"></button>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="field is-align-self-stretch" id="in">
|
|
<p class="control">
|
|
<span class="select is-fullwidth">
|
|
<select name="in" autocomplete="off" required>
|
|
<option selected disabled value="">Search In...</option>
|
|
#for(repo in cfg.Repos):
|
|
<option>#(repo.Name)</option>
|
|
#!for
|
|
</select>
|
|
</span>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="field mt-4 is-align-self-stretch">
|
|
<p class="control">
|
|
<button class="button is-info is-inverted is-rounded is-fullwidth" type="submit">
|
|
<div class="icon-text">
|
|
<span class="icon is-aligned m-0">#icon("map/search")</span>
|
|
<span>Search</span>
|
|
</div>
|
|
</button>
|
|
</p>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div x-cloak x-data="{tags: []}" x-transition:enter x-show="activeTab == 'tags'" class="columns">
|
|
<div class="column is-half is-offset-one-quarter has-text-centered">
|
|
<form action="/search/tags" x-ref="tagsForm">
|
|
<template x-if="tags.length == 0">
|
|
<div class="has-text-centered">
|
|
<p class="is-size-5">Tags you add will appear here...</p>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="field is-grouped is-grouped-multiline">
|
|
<template x-for="(tag, idx) in tags">
|
|
<div>
|
|
<div class="tags has-addons">
|
|
<span class="tag is-dark has-background-info-dark has-text-info-light" x-text="tag[0]"></span><span class="tag is-dark" x-text="tag[1]"></span><a class="tag is-dark is-delete m-0" @click.prevent="tags.splice(idx, 1)"></a>
|
|
</div>
|
|
<input class="is-hidden" name="tag" :value="tag.join('=')">
|
|
</div>
|
|
</template>
|
|
<span></span>
|
|
</div>
|
|
|
|
<div class="icon-text mt-5 has-text-grey">
|
|
<span class="icon is-aligned">#icon("material-symbols/info-outline")</span>
|
|
<p class="is-size-7 has-text-grey">
|
|
Try searching for
|
|
<code class="is-clickable" @click="tags.push(['lib', 'pcre2-8'])">lib=pcre2-8</code>,
|
|
<code class="is-clickable" @click="tags.push(['lib', 'libaudit.so.1'])">lib=libaudit.so.1</code>,
|
|
<code class="is-clickable" @click="tags.push(['bin', 'firefox'])">bin=firefox</code>,
|
|
etc.
|
|
</p>
|
|
</div>
|
|
<div class="mt-0 field has-addons">
|
|
<div class="control is-expanded">
|
|
<input @keydown.comma.prevent="pushTag(tags, $refs.newTagInput)" class="input" x-ref="newTagInput" placeholder="bin=nano">
|
|
</div>
|
|
<div class="control">
|
|
<button class="button" @click.prevent="pushTag(tags, $refs.newTagInput)">
|
|
<div class="icon-text">
|
|
<span class="icon is-aligned m-0">#icon("icons8/plus")</span>
|
|
<span>Add</span>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="field" id="in">
|
|
<p class="control">
|
|
<span class="select is-fullwidth">
|
|
<select name="in" autocomplete="off" required>
|
|
<option selected disabled value="">Select Repo...</option>
|
|
#for(repo in cfg.Repos):
|
|
<option>#(repo.Name)</option>
|
|
#!for
|
|
</select>
|
|
</span>
|
|
</p>
|
|
</div>
|
|
|
|
<button class="button is-info is-inverted is-rounded is-fullwidth" type="submit">
|
|
<div class="icon-text">
|
|
<span class="icon is-aligned m-0">#icon("map/search")</span>
|
|
<span>Search</span>
|
|
</div>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
#!macro
|
|
#include("base.html", page = "Search")
|