1import config from "./config.js";
2
3// templates
4const templates = {
5 head: ({ title }) => `
6<!doctype html>
7<html>
8
9<head>
10 <meta charset="utf-8">
11 <meta name="viewport" content="width=device-width, initial-scale=1">
12 <title>${title} | ${config.appName}</title>
13 <link rel="stylesheet" href="/style.css" />
14</head>
15<body>
16`,
17
18 tail: () => `
19</body>
20
21</html>
22`,
23
24 nav: ({ username }) => `
25<nav>
26 <div class="container">
27 <div>
28 <a href="/me">
29 <strong>@${username}</strong>
30 </a>
31 </div>
32 <div>
33 <a href="/logout">⍈ logout</a>
34 </div>
35 </div>
36</nav>
37 `,
38
39 message: ({ query }) => {
40 let html = ``;
41 if (query.message) {
42 html += `
43 <div class="container warning" id="messages">
44 <span>${query.message}</span>
45 <button onclick="this.parentNode.remove();" class="close">×</button>
46 </div>
47 `;
48 }
49 return html;
50 },
51};
52
53export const pageHtml = {
54 home: ({ query }) => {
55 let html = `${templates.head({
56 title: "another URL shortening service",
57 })}`;
58
59 html += templates.message({ query });
60 html += `
61 <div class="container">
62 <h1>hi there!</h1>
63 <p>
64 This is an instance of <a href="https://github.com/aktsbot/lil">lil</a>,
65 a simple URL shortening service. Please login.
66 </p>
67
68 <form action="/login" method="POST">
69 <label for="username">username</label>
70 <input
71 type="text"
72 name="username"
73 id="username"
74 autofocus
75 placeholder="eg: nyanman"
76 required
77 />
78
79 <div class="captcha">
80 <img src="/captcha.svg" alt="captcha" />
81 </div>
82
83 <label for="captcha">captcha</label>
84 <input
85 type="text"
86 class="monospace"
87 name="captcha"
88 id="captcha"
89 placeholder="The content of the image seen above"
90 required
91 />
92
93 <button type="submit">login</button>
94 </form>
95 </div>
96 `;
97
98 html += `${templates.tail()}`;
99 return html;
100 },
101 newUrl: ({ query, user }) => {
102 let html = `${templates.head({ title: "shorten new url" })}`;
103
104 html += `${templates.nav({ username: user.username })}`;
105
106 html += templates.message({ query });
107
108 html += `
109 <div class="container">
110 <a href="/list"><Back</a>
111 <h1>new short url</h1>
112
113 <form action="/" method="POST">
114 <label for="full_url">full url</label>
115 <input
116 type="text"
117 name="full_url"
118 id="full_url"
119 placeholder="eg: https://foo.com/a/long/url?with=query¶ms=1"
120 required
121 />
122
123 <label for="short">short code(optional)</label>
124 <input
125 type="text"
126 name="short"
127 id="short"
128 placeholder="foo1"
129 />
130
131 <button type="submit">shorten</button>
132 </form>
133 </div>
134 `;
135
136 html += `${templates.tail()}`;
137 return html;
138 },
139 listUrls: ({
140 query,
141 user,
142 results,
143 totalPages,
144 offset,
145 nextPageLink,
146 prevPageLink,
147 page,
148 }) => {
149 let html = `${templates.head({ title: "your urls" })}`;
150 // TODO:
151 html += `${templates.nav({ username: user.username })}`;
152
153 html += templates.message({ query });
154
155 html += `
156 <div class="container">
157 <h1>my urls</h1>
158 <div style="margin-bottom: 8px; text-align: right">
159 <a href="/new">+ new url</a>
160 </div>
161 <div style="overflow-x: scroll">
162 <table>
163 <tr>
164 <th>#</th>
165 <th>full url</th>
166 <th>short url</th>
167 </tr>
168 ${
169 results.length
170 ? results
171 .map((r, index) => {
172 return `
173 <tr>
174 <td>${index + 1 + offset}</td>
175 <td>
176 <a href="${r.destination}">${r.destination}</a>
177 </td>
178 <td>
179 <a href="/${r.short}">/${r.short}</a>
180 </td>
181 </tr>
182 `;
183 })
184 .join("")
185 : '<tr><td colspan="3" style="text-align: center;">No urls added yet</td></tr>'
186 }
187 </table>
188 </div>
189
190 ${
191 totalPages
192 ? `
193 <div style="margin-top: 8px; text-align: center">
194 ${prevPageLink ? `<a href="${prevPageLink}">< prev</a>` : ""}
195 <span>page 1 of ${totalPages}</span>
196 ${nextPageLink ? `<a href="${nextPageLink}">next ></a>` : ""}
197 </div>`
198 : ""
199 }
200 </div>
201 `;
202
203 html += `${templates.tail()}`;
204 return html;
205 },
206 me: ({ query, user }) => {
207 let html = `${templates.head({ title: "me" })}`;
208
209 // TODO:
210 html += `${templates.nav({ username: user.username })}`;
211
212 html += `
213 <div class="container">
214 <a href="/list"><Back</a>
215
216 <h1>me</h1>
217
218 <p>username: ${user.username}</p>
219 <p>api token: <code class="token">${user.api_token}</code></p>
220
221 <h2>how to use the api token</h2>
222
223<pre>
224curl -X POST \\
225-H "x-auth-token: ${user.api_token}" \\
226-H "Content-type: application/x-www-form-urlencoded" \\
227-d "full_url=https://www.warp.dev/terminus/curl-post-request" \\
228-d "short=wrp-curl" \\
229${config.hostname}
230</pre>
231
232 <p>The <code>-d "short=wrp-curl"</code> part is optional.</p>
233 </div>
234 `;
235
236 html += `${templates.tail()}`;
237 return html;
238 },
239};