user.html (14520B)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>Marky</title> 7 <link rel="stylesheet" href="/styles.css" /> 8 <link rel="icon" href="/favicon.svg" type="image/svg+xml" /> 9 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> 10 <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> 11 <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> 12 <script src="/vendor/vue.global.prod.js"></script> 13 <script>if(!window.Vue){var s=document.createElement('script');s.src='https://unpkg.com/vue@3/dist/vue.global.prod.js';document.head.appendChild(s)}</script> 14 <script src="/vendor/marked.min.js"></script> 15 <script>if(!window.marked){var s=document.createElement('script');s.src='https://cdn.jsdelivr.net/npm/marked/marked.min.js';document.head.appendChild(s)}</script> 16 <script src="/vendor/purify.min.js"></script> 17 <script>if(!window.DOMPurify){var s=document.createElement('script');s.src='https://cdn.jsdelivr.net/npm/[email protected]/dist/purify.min.js';document.head.appendChild(s)}</script> 18 </head> 19 <body> 20 <div id="app"> 21 {{HEADER}} 22 <main class="container grid"> 23 <section v-if="view==='self'"> 24 <h2>Add Bookmark</h2> 25 <form @submit.prevent="createBookmark"> 26 <label>URL <input v-model.trim="form.url" type="url" required placeholder="https://example.com" /></label> 27 <label>Title (optional) <input v-model.trim="form.title" type="text" placeholder="Page title" /></label> 28 <label>Description (optional) <textarea v-model.trim="form.description" rows="2" placeholder="Notes..."></textarea></label> 29 <label>Referrer (optional) <input v-model.trim="form.referrer" type="url" placeholder="https://site-that-linked-here.example" /></label> 30 <label class="inline"><input type="checkbox" v-model="form.public" /> Public</label> 31 <button :disabled="busy">{{ busy ? 'Working…' : 'Save' }}</button> 32 <p v-if="error" class="error">{{ error }}</p> 33 <p v-if="message" class="ok">{{ message }}</p> 34 </form> 35 </section> 36 <section v-if="view==='self'" id="bookmarks"> 37 <h2> 38 Bookmarks 39 <span class="small-links" v-if="me && me.username"> 40 <a :href="`/u:${me.username}.json`" title="Your JSON feed (includes private if logged in)">JSON</a> 41 <span class="sep">|</span> 42 <a :href="`/u:${me.username}.rss`" title="Your RSS feed (includes private if logged in)">RSS</a> 43 </span> 44 </h2> 45 <form method="GET" :action="`/u:${me.username}#bookmarks`"> 46 <input name="q" type="search" placeholder="Search…" :value="pager && pager.query ? pager.query : ''" @search="submitOnClear" /> 47 <input type="hidden" name="vis" :value="pager && pager.vis ? pager.vis : 'all'" /> 48 <button>Search</button> 49 </form> 50 <p v-if="pager" class="muted results-summary"> 51 <span> 52 Displaying {{ (pager.count||0) === 0 ? 0 : ((pager.page-1)*pager.size + 1) }}-{{ (pager.count||0) === 0 ? 0 : ((pager.page-1)*pager.size + results.length) }} of {{ pager.count || 0 }} bookmarks 53 </span> 54 <span class="results-filter" v-if="pager && pager.owner"> 55 <a :class="{ selected: (pager.vis||'all')==='all' }" :href="pager && pager.query ? `/u:${me.username}?page=1&size=${pager.size}&q=${pager.queryEncoded}&vis=all#bookmarks` : `/u:${me.username}?page=1&size=${pager.size}&vis=all#bookmarks`">All</a> 56 <span class="sep">|</span> 57 <a :class="{ selected: (pager.vis||'all')==='public' }" :href="pager && pager.query ? `/u:${me.username}?page=1&size=${pager.size}&q=${pager.queryEncoded}&vis=public#bookmarks` : `/u:${me.username}?page=1&size=${pager.size}&vis=public#bookmarks`">Public</a> 58 <span class="sep">|</span> 59 <a :class="{ selected: (pager.vis||'all')==='private' }" :href="pager && pager.query ? `/u:${me.username}?page=1&size=${pager.size}&q=${pager.queryEncoded}&vis=private#bookmarks` : `/u:${me.username}?page=1&size=${pager.size}&vis=private#bookmarks`">Private</a> 60 </span> 61 </p> 62 <div class="results"> 63 <article v-for="b in results" :key="b.id" :class="['card', { private: !b.public }]"> 64 <h3><a :href="b.url" target="_blank" rel="noopener noreferrer">{{ b.title || b.url }}</a></h3> 65 <p :class="['url', { truncate: b.urlTrunc }]" :title="b.url" @click="toggleURL(b)">{{ b.url }}</p> 66 <p v-if="b.referrer" class="referrer">Referrer: <span class="ref-link"><a :href="b.referrer" target="_blank" rel="noopener noreferrer">{{ b.referrer }}</a></span></p> 67 <div v-if="b.editing" class="edit-form"> 68 <label>URL <input v-model.trim="b.editUrl" type="url" required /></label> 69 <label>Title <input v-model.trim="b.editTitle" type="text" required /></label> 70 <label>Description <textarea v-model.trim="b.editDescription" rows="2"></textarea></label> 71 <label>Referrer <input v-model.trim="b.editReferrer" type="url" placeholder="https://site-that-linked-here.example" /></label> 72 <label class="inline"><input type="checkbox" v-model="b.editPublic" /> Public</label> 73 <div class="actions"> 74 <button @click="saveEdit(b)" :disabled="b.saving">{{ b.saving ? 'Saving…' : 'Save' }}</button> 75 <button @click="cancelEdit(b)">Cancel</button> 76 </div> 77 </div> 78 <p v-else-if="b.excerpt" class="excerpt" v-html="formatExcerpt(b.excerpt)"></p> 79 <div v-if="!b.editing && !b.excerpt && b.description" class="desc" v-html="renderMarkdown(b.description)"></div> 80 <p class="action-links"> 81 <span class="meta">{{ formatDate(b.updated_at) }}</span> 82 <span class="sep">|</span> 83 <template v-if="b.has_archive"> 84 <a :href="`/bookmarks/${b.id}/archive`" target="_blank" title="View archived text">Archive</a> 85 <span class="sep">|</span> 86 </template> 87 <a href="#" @click.prevent="startEdit(b)">Edit</a> 88 <span class="sep">|</span> 89 <a href="#" @click.prevent="confirmDelete(b)">Delete</a> 90 </p> 91 </article> 92 </div> 93 <div class="pager"> 94 <div v-if="pager && pager.total > 1" class="pages"> 95 <template v-if="pager.page > 1"> 96 <a :href="pager && pager.query ? `/u:${me.username}?page=${pager.page-1}&size=${pager.size}&q=${pager.queryEncoded}&vis=${pager.vis||'all'}#bookmarks` : `/u:${me.username}?page=${pager.page-1}&size=${pager.size}&vis=${pager.vis||'all'}#bookmarks`">Prev</a> 97 </template> 98 <template v-else> 99 <span class="muted">Prev</span> 100 </template> 101 <span class="sep">|</span> 102 <template v-for="item in pagerPages" :key="item.key"> 103 <template v-if="item.type === 'page'"> 104 <template v-if="item.n === pager.page"> 105 <span class="muted">{{ item.n }}</span> 106 </template> 107 <template v-else> 108 <a :href="pager && pager.query ? `/u:${me.username}?page=${item.n}&size=${pager.size}&q=${pager.queryEncoded}&vis=${pager.vis||'all'}#bookmarks` : `/u:${me.username}?page=${item.n}&size=${pager.size}&vis=${pager.vis||'all'}#bookmarks`">{{ item.n }}</a> 109 </template> 110 </template> 111 <template v-else> 112 <span class="muted">…</span> 113 </template> 114 </template> 115 <span class="sep">|</span> 116 <template v-if="pager.page < pager.total"> 117 <a :href="pager && pager.query ? `/u:${me.username}?page=${pager.page+1}&size=${pager.size}&q=${pager.queryEncoded}&vis=${pager.vis||'all'}#bookmarks` : `/u:${me.username}?page=${pager.page+1}&size=${pager.size}&vis=${pager.vis||'all'}#bookmarks`">Next</a> 118 </template> 119 <template v-else> 120 <span class="muted">Next</span> 121 </template> 122 </div> 123 <div class="sizes"> 124 <span>Page size:</span> 125 <template v-if="pager && pager.size===20"> 126 <span class="muted">20</span> 127 </template> 128 <template v-else> 129 <a :href="pager && pager.query ? `/u:${me.username}?page=1&size=20&q=${pager.queryEncoded}&vis=${pager.vis||'all'}#bookmarks` : `/u:${me.username}?page=1&size=20&vis=${pager.vis||'all'}#bookmarks`">20</a> 130 </template> 131 <span class="sep">|</span> 132 <template v-if="pager && pager.size===50"> 133 <span class="muted">50</span> 134 </template> 135 <template v-else> 136 <a :href="pager && pager.query ? `/u:${me.username}?page=1&size=50&q=${pager.queryEncoded}&vis=${pager.vis||'all'}#bookmarks` : `/u:${me.username}?page=1&size=50&vis=${pager.vis||'all'}#bookmarks`">50</a> 137 </template> 138 <span class="sep">|</span> 139 <template v-if="pager && pager.size===100"> 140 <span class="muted">100</span> 141 </template> 142 <template v-else> 143 <a :href="pager && pager.query ? `/u:${me.username}?page=1&size=100&q=${pager.queryEncoded}&vis=${pager.vis||'all'}#bookmarks` : `/u:${me.username}?page=1&size=100&vis=${pager.vis||'all'}#bookmarks`">100</a> 144 </template> 145 </div> 146 </div> 147 </section> 148 149 <section v-if="view==='public'" class="span2"> 150 <h2> 151 {{ viewUser }} 152 <span class="small-links"> 153 <a :href="`/u:${viewUser}.json`" title="User JSON feed">JSON</a> 154 <span class="sep">|</span> 155 <a :href="`/u:${viewUser}.rss`" title="User RSS feed">RSS</a> 156 </span> 157 </h2> 158 <p v-if="pager" class="muted results-summary"> 159 Displaying {{ (pager.count||0) === 0 ? 0 : ((pager.page-1)*pager.size + 1) }}-{{ (pager.count||0) === 0 ? 0 : ((pager.page-1)*pager.size + results.length) }} of {{ pager.count || 0 }} bookmarks 160 </p> 161 <div class="results"> 162 <article v-for="b in results" :key="b.id" class="card"> 163 <h3><a :href="b.url" target="_blank" rel="noopener noreferrer">{{ b.title || b.url }}</a></h3> 164 <p :class="['url', { truncate: b.urlTrunc }]" :title="b.url" @click="toggleURL(b)">{{ b.url }}</p> 165 <p v-if="b.referrer" class="referrer">Referrer: <span class="ref-link"><a :href="b.referrer" target="_blank" rel="noopener noreferrer">{{ b.referrer }}</a></span></p> 166 <div v-if="b.description" class="desc" v-html="renderMarkdown(b.description)"></div> 167 <p class="action-links"> 168 <span class="meta">{{ formatDate(b.updated_at) }}</span> 169 <template v-if="b.has_archive"> 170 <span class="sep">|</span> 171 <a :href="`/bookmarks/${b.id}/archive`" target="_blank">Archive</a> 172 </template> 173 </p> 174 </article> 175 </div> 176 <div class="pager"> 177 <div v-if="pager && pager.total > 1" class="pages"> 178 <template v-if="pager.page > 1"> 179 <a :href="pager && pager.query ? `/u:${viewUser}?page=${pager.page-1}&size=${pager.size}&q=${pager.queryEncoded}` : `/u:${viewUser}?page=${pager.page-1}&size=${pager.size}`">Prev</a> 180 </template> 181 <template v-else> 182 <span class="muted">Prev</span> 183 </template> 184 <span class="sep">|</span> 185 <template v-for="item in pagerPages" :key="item.key"> 186 <template v-if="item.type === 'page'"> 187 <template v-if="item.n === pager.page"> 188 <span class="muted">{{ item.n }}</span> 189 </template> 190 <template v-else> 191 <a :href="pager && pager.query ? `/u:${viewUser}?page=${item.n}&size=${pager.size}&q=${pager.queryEncoded}` : `/u:${viewUser}?page=${item.n}&size=${pager.size}`">{{ item.n }}</a> 192 </template> 193 </template> 194 <template v-else> 195 <span class="muted">…</span> 196 </template> 197 </template> 198 <span class="sep">|</span> 199 <template v-if="pager.page < pager.total"> 200 <a :href="pager && pager.query ? `/u:${viewUser}?page=${pager.page+1}&size=${pager.size}&q=${pager.queryEncoded}` : `/u:${viewUser}?page=${pager.page+1}&size=${pager.size}`">Next</a> 201 </template> 202 <template v-else> 203 <span class="muted">Next</span> 204 </template> 205 </div> 206 <div class="sizes"> 207 <span>Page size:</span> 208 <template v-if="pager && pager.size===20"> 209 <span class="muted">20</span> 210 </template> 211 <template v-else> 212 <a :href="pager && pager.query ? `/u:${viewUser}?page=1&size=20&q=${pager.queryEncoded}` : `/u:${viewUser}?page=1&size=20`">20</a> 213 </template> 214 <span class="sep">|</span> 215 <template v-if="pager && pager.size===50"> 216 <span class="muted">50</span> 217 </template> 218 <template v-else> 219 <a :href="pager && pager.query ? `/u:${viewUser}?page=1&size=50&q=${pager.queryEncoded}` : `/u:${viewUser}?page=1&size=50`">50</a> 220 </template> 221 <span class="sep">|</span> 222 <template v-if="pager && pager.size===100"> 223 <span class="muted">100</span> 224 </template> 225 <template v-else> 226 <a :href="pager && pager.query ? `/u:${viewUser}?page=1&size=100&q=${pager.queryEncoded}` : `/u:${viewUser}?page=1&size=100`">100</a> 227 </template> 228 </div> 229 </div> 230 </section> 231 </main> 232 </div> 233 <script src="/app.js"></script> 234 </body> 235 </html>