a love letter to tangled (android, iOS, and a search API)
at main 124 lines 5.0 kB view raw
1{{define "title"}}Twister &mdash; Search Tangled{{end}} 2{{define "head"}} 3<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> 4{{end}} 5{{define "content"}} 6<div x-data="searchApp()" x-init="initFromURL()"> 7 <section class="search-hero"> 8 <h1>Search Tangled</h1> 9 <form class="search-form" @submit.prevent="doSearch(true)"> 10 <input type="text" x-model="query" placeholder="Search repos, issues, PRs, profiles&hellip;" class="search-input" autofocus> 11 <button type="submit" class="btn btn-primary">Search</button> 12 </form> 13 <div class="filter-bar"> 14 <select x-model="filters.type" @change="doSearch(true)"> 15 <option value="">All types</option> 16 <option value="repo">Repos</option> 17 <option value="issue">Issues</option> 18 <option value="pull">Pull Requests</option> 19 <option value="profile">Profiles</option> 20 <option value="string">Strings</option> 21 <option value="star">Stars</option> 22 </select> 23 <input type="text" x-model="filters.author" placeholder="Author" @keydown.enter="doSearch(true)" class="filter-input"> 24 <input type="text" x-model="filters.language" placeholder="Language" @keydown.enter="doSearch(true)" class="filter-input"> 25 <select x-model="filters.state" @change="doSearch(true)"> 26 <option value="">Any state</option> 27 <option value="open">Open</option> 28 <option value="closed">Closed</option> 29 <option value="merged">Merged</option> 30 </select> 31 </div> 32 </section> 33 34 <section class="results"> 35 <template x-if="error"> 36 <div class="msg msg-error" x-text="error"></div> 37 </template> 38 <template x-if="!error && !searched && !loading"> 39 <div class="msg msg-empty"> 40 <p>Search indexed Tangled records.</p> 41 <p> 42 If a record is missing, fetch it through the API to index it for search. 43 Try 44 <a href="/actors/desertthunder.dev" target="_blank" rel="noopener"> 45 <code>GET /actors/desertthunder.dev</code> 46 </a>. 47 </p> 48 </div> 49 </template> 50 <template x-if="!error && searched && results.length === 0"> 51 <div class="msg msg-empty"> 52 <p>No results found.</p> 53 <p> 54 Fetching a resource through the API will index it for search. 55 Try 56 <a href="/actors/desertthunder.dev" target="_blank" rel="noopener"> 57 <code>GET /actors/desertthunder.dev</code> 58 </a> 59 and search again. 60 </p> 61 </div> 62 </template> 63 <template x-for="r in results" :key="r.id"> 64 <div class="result-shell"> 65 <article class="card"> 66 <div class="card-head"> 67 <span class="badge" x-text="r.record_type"></span> 68 <span class="card-title" x-text="r.title || r.id"></span> 69 </div> 70 <div class="card-snippet" x-show="r.body_snippet" x-html="r.body_snippet"></div> 71 <div class="card-snippet" x-show="!r.body_snippet && r.summary" x-text="r.summary"></div> 72 <div class="card-meta"> 73 <span x-show="r.author_handle" x-text="r.author_handle"></span> 74 <span x-show="r.repo_name" class="meta-sep" x-text="r.repo_name"></span> 75 <span x-show="r.updated_at" class="meta-sep" x-text="relTime(r.updated_at)"></span> 76 </div> 77 <div class="card-actions"> 78 <a 79 x-show="resultURL(r)" 80 :href="resultURL(r)" 81 target="_blank" 82 rel="noopener" 83 class="btn btn-card" 84 >Open on Tangled</a> 85 <button 86 x-show="r.at_uri" 87 type="button" 88 class="btn btn-card" 89 @click="copyATURI(r)" 90 >Copy AT URI</button> 91 <a 92 x-show="r.at_uri" 93 :href="pdsURL(r)" 94 target="_blank" 95 rel="noopener" 96 class="btn btn-card" 97 >Open in pds.ls</a> 98 <a 99 :href="jsonURL(r)" 100 target="_blank" 101 rel="noopener" 102 class="btn btn-card" 103 >View JSON</a> 104 </div> 105 <div x-show="warningMessage(r)" class="card-warning" role="note"> 106 <strong class="warning-title" x-text="warningMessage(r)"></strong> 107 <code x-show="r.at_uri" class="warning-uri" x-text="r.at_uri"></code> 108 </div> 109 </article> 110 </div> 111 </template> 112 <template x-if="hasMore"> 113 <button class="btn btn-more" @click="loadMore()" x-text="loading ? 'Loading\u2026' : 'Load more'" :disabled="loading"></button> 114 </template> 115 </section> 116 <div class="toast" :class="{ 'toast-visible': toastVisible }" x-show="toastVisible" x-transition.opacity.duration.150ms> 117 <span x-text="toastMessage"></span> 118 </div> 119</div> 120{{end}} 121{{define "scripts"}} 122<script src="/static/search.js"></script> 123{{end}} 124{{template "layout" .}}