shortener.hbs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <main>
  2. <div id="shorturl">
  3. {{#if link}}
  4. <div class="clipboard">
  5. <button
  6. aria-label="Copy"
  7. hx-on:click="handleShortURLCopyLink(this);"
  8. data-url="{{url}}"
  9. >
  10. {{> icons/copy}}
  11. </button>
  12. {{> icons/check}}
  13. </div>
  14. <h1
  15. class="link"
  16. hx-on:click="handleShortURLCopyLink(this);"
  17. data-url="{{url}}"
  18. >
  19. {{link}}
  20. </h1>
  21. {{/if}}
  22. {{#unless link}}
  23. <h1>Kutt your links <span>shorter</span>.</h1>
  24. {{/unless}}
  25. </div>
  26. <form
  27. id="shortener-form"
  28. hx-post="/api/links"
  29. hx-trigger="submit queue:none"
  30. hx-target="closest main"
  31. hx-swap="outerHTML"
  32. autocomplete="off"
  33. >
  34. <div class="target-wrapper {{#if errors.target}}error{{/if}}">
  35. <input
  36. id="target"
  37. name="target"
  38. type="text"
  39. placeholder="Paste your long URL"
  40. aria-label="target"
  41. autofocus="true"
  42. data-lpignore="true"
  43. hx-preserve="true"
  44. />
  45. <button class="submit">
  46. <svg class="send" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24"><path d="m2 21 21-9L2 3v7l15 2-15 2z"/></svg>
  47. <svg class="spinner" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M12 2v4m0 12v4M5 5l2.8 2.8m8.4 8.4 2.9 2.9M2 12h4m12 0h4M5 19l2.8-2.8m8.4-8.4 2.9-2.9"/></svg>
  48. </button>
  49. {{#if errors.target}}<p class="error">{{errors.target}}</p>{{/if}}
  50. {{#unless errors}}
  51. {{#if error}}
  52. <p class="error">{{error}}</p>
  53. {{/if}}
  54. {{/unless}}
  55. </div>
  56. <label id="advanced" class="checkbox">
  57. <input
  58. name="show_advanced"
  59. type="checkbox"
  60. hx-on:change="htmx.toggleClass('#advanced-options', 'hidden')"
  61. {{#if show_advanced}}checked="true"{{/if}}
  62. />
  63. Show advanced options
  64. </label>
  65. <section id="advanced-options" class="{{#unless show_advanced}}hidden{{/unless}}">
  66. <div class="advanced-input-wrapper">
  67. <label class="{{#if errors.domain}}error{{/if}}">
  68. Domain:
  69. <select
  70. id="domain"
  71. name="domain"
  72. hx-preserve="true"
  73. hx-on:change="
  74. const elm = document.querySelector('#customurl-label span');
  75. if (!elm) return;
  76. elm.textContent = event.target.value + '/';
  77. "
  78. >
  79. <option value={{default_domain}}>{{default_domain}}</option>
  80. {{#each domains}}
  81. <option value={{address}}>{{address}}</option>
  82. {{/each}}
  83. </select>
  84. {{#if errors.domain}}<p class="error">{{errors.domain}}</p>{{/if}}
  85. </label>
  86. <label id="customurl-label" class="{{#if errors.customurl}}error{{/if}}">
  87. <span id="customurl-label-value" hx-preserve="true">{{default_domain}}/</span>
  88. <input
  89. type="text"
  90. id="customurl"
  91. name="customurl"
  92. placeholder="Custom address..."
  93. hx-preserve="true"
  94. autocomplete="off"
  95. />
  96. {{#if errors.customurl}}<p class="error">{{errors.customurl}}</p>{{/if}}
  97. </label>
  98. <label class="{{#if errors.password}}error{{/if}}">
  99. Password:
  100. <input
  101. type="password"
  102. id="password"
  103. name="password"
  104. placeholder="Password..."
  105. hx-preserve="true"
  106. autocomplete="off"
  107. />
  108. {{#if errors.password}}<p class="error">{{errors.password}}</p>{{/if}}
  109. </label>
  110. </div>
  111. <div class="advanced-input-wrapper">
  112. <label class="expire-in {{#if errors.expire_in}}error{{/if}}">
  113. Expire in:
  114. <input
  115. type="text"
  116. id="expire_in"
  117. name="expire_in"
  118. placeholder="2 minutes/hours/days"
  119. hx-preserve="true"
  120. />
  121. {{#if errors.expire_in}}<p class="error">{{errors.expire_in}}</p>{{/if}}
  122. </label>
  123. <label class="description {{#if errors.description}}error{{/if}}">
  124. Description:
  125. <input
  126. type="text"
  127. id="description"
  128. name="description"
  129. placeholder="Description..."
  130. hx-preserve="true"
  131. />
  132. {{#if errors.description}}<p class="error">{{errors.description}}</p>{{/if}}
  133. </label>
  134. </div>
  135. </section>
  136. </form>
  137. </main>