A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

321 linhas
12 KiB

  1. {{define "collection"}}
  2. {{template "header" .}}
  3. <style>
  4. textarea.section.norm {
  5. font-family: Lora,'Palatino Linotype','Book Antiqua','New York','DejaVu serif',serif !important;
  6. min-height: 10em;
  7. max-height: 20em;
  8. resize: vertical;
  9. }
  10. @media (pointer: coarse) {
  11. .codable {
  12. font-size: 0.75em !important;
  13. height: 17em !important;
  14. }
  15. }
  16. </style>
  17. <div class="content-container snug">
  18. <div id="overlay"></div>
  19. {{if .Silenced}}
  20. {{template "user-silenced"}}
  21. {{end}}
  22. {{template "collection-breadcrumbs" .}}
  23. <h1>Customize</h1>
  24. {{template "collection-nav" (dict "Alias" .Alias "Path" .Path "SingleUser" .SingleUser)}}
  25. {{if .Flashes}}<ul class="errors">
  26. {{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
  27. </ul>{{end}}
  28. <form name="customize-form" action="/api/collections/{{.Alias}}" method="post" onsubmit="return disableSubmit()">
  29. <div id="collection-options">
  30. <div style="text-align:center">
  31. <h1><input type="text" name="title" id="title" value="{{.DisplayTitle}}" placeholder="Title" maxlength="255" /></h1>
  32. <p><input type="text" name="description" id="description" value="{{.Description}}" placeholder="Description" maxlength="160" /></p>
  33. </div>
  34. <div class="option">
  35. <h2><a name="preferred-url"></a>URL</h2>
  36. <div class="section">
  37. {{if eq .Alias .Username}}<p style="font-size: 0.8em">This blog uses your username in its URL{{if .Federation}} and fediverse handle{{end}}. You can change it in your <a href="/me/settings">Account Settings</a>.</p>{{end}}
  38. <ul style="list-style:none">
  39. <li>
  40. {{.FriendlyHost}}/<strong>{{.Alias}}</strong>/
  41. </li>
  42. <li>
  43. <strong id="normal-handle-env" class="fedi-handle" {{if not .Federation}}style="display:none"{{end}}>@<span id="fedi-handle">{{.Alias}}</span>@<span id="fedi-domain">{{.FriendlyHost}}</span></strong>
  44. </li>
  45. </ul>
  46. </div>
  47. </div>
  48. <div class="option">
  49. <h2>Publicity</h2>
  50. <div class="section">
  51. <ul style="list-style:none">
  52. <li>
  53. <label><input type="radio" name="visibility" id="visibility-unlisted" value="0" {{if .IsUnlisted}}checked="checked"{{end}} />
  54. Unlisted
  55. </label>
  56. <p>This blog is visible to {{if .Private}}any registered user on this instance{{else}}anyone with its link{{end}}.</p>
  57. </li>
  58. <li>
  59. <label class="option-text"><input type="radio" name="visibility" id="visibility-private" value="2" {{if .IsPrivate}}checked="checked"{{end}} />
  60. Private
  61. </label>
  62. <p>Only you may read this blog (while you're logged in).</p>
  63. </li>
  64. <li>
  65. <label class="option-text"><input type="radio" name="visibility" id="visibility-protected" value="4" {{if .IsProtected}}checked="checked"{{end}} />
  66. Password-protected: <input type="password" class="low-profile" name="password" id="collection-pass" autocomplete="new-password" placeholder="{{if .IsProtected}}xxxxxxxxxxxxxxxx{{else}}a memorable password{{end}}" />
  67. </label>
  68. <p>A password is required to read this blog.</p>
  69. </li>
  70. {{if not .SingleUser}}
  71. <li>
  72. <label class="option-text{{if not .LocalTimeline}} disabled{{end}}"><input type="radio" name="visibility" id="visibility-public" value="1" {{if .IsPublic}}checked="checked"{{end}} {{if not .LocalTimeline}}disabled="disabled"{{end}} />
  73. Public
  74. </label>
  75. {{if .LocalTimeline}}<p>This blog is displayed on the public <a href="/read">reader</a>, and is visible to {{if .Private}}any registered user on this instance{{else}}anyone with its link{{end}}.</p>
  76. {{else}}<p>The public reader is currently turned off for this community.</p>{{end}}
  77. </li>
  78. {{end}}
  79. </ul>
  80. </div>
  81. </div>
  82. <div class="option">
  83. <h2 id="updates">Updates</h2>
  84. <div class="section">
  85. <p class="explain">Keep readers updated with your latest posts wherever they are.</p>
  86. <ul style="list-style:none">
  87. <li>
  88. <label class="option-text"><input type="checkbox" checked="checked" disabled />
  89. RSS feed
  90. </label>
  91. <p class="describe">Readers can subscribe to your blog's <a href="{{.CanonicalURL}}feed/" target="feed">RSS feed</a> with their favorite RSS reader.</p>
  92. </li>
  93. {{if .EmailCfg.Enabled}}
  94. <li>
  95. <label class="option-text" id="email-sub-label"><input type="checkbox" name="email_subs" id="email_subs" {{if .EmailSubsEnabled}}checked="checked"{{end}} />
  96. Email subscriptions
  97. </label>
  98. <p class="describe">
  99. Let readers subscribe to your blog via email, and optionally accept private replies.
  100. </p>
  101. <div id="custom-letter-reply" style="font-size: .8em; margin-top: -0.5em; margin-left: 1.8em; margin-bottom: 1em;" {{if not .EmailSubsEnabled}}style="display:none"{{end}}>
  102. Allow replies to this address:
  103. <input type="email" name="letter_reply" id="letter_reply" placeholder="me@example.com" value="{{.LetterReplyTo}}" {{if not .EmailSubsEnabled}}disabled{{end}} />
  104. </div>
  105. </li>
  106. {{end}}
  107. {{if .Federation}}
  108. <li>
  109. <label class="option-text" id="federate-label"><input type="checkbox" name="federate" id="federate" {{if .Federation}}checked="checked"{{end}} disabled />
  110. Federation
  111. </label>
  112. <strong id="normal-handle-env" class="fedi-handle">@<span id="fedi-handle">{{.Alias}}</span>@<span id="fedi-domain">{{.FriendlyHost}}</span></strong>
  113. <p class="describe">Allow others to follow your blog and interact with your posts in the fediverse. <a href="https://video.writeas.org/videos/watch/cc55e615-d204-417c-9575-7b57674cc6f3" target="video">See how it works</a>.</p>
  114. </li>
  115. {{end}}
  116. </ul>
  117. </div>
  118. </div>
  119. <div class="option">
  120. <h2>Display Format</h2>
  121. <div class="section">
  122. <p class="explain">Customize how your posts display on your page.
  123. </p>
  124. <ul style="list-style:none">
  125. <li>
  126. <label><input type="radio" name="format" id="format-blog" value="blog" {{if or (not .Format) (eq .Format "blog")}}checked="checked"{{end}} />
  127. Blog
  128. </label>
  129. <p>Dates are shown. Latest posts listed first.</p>
  130. </li>
  131. <li>
  132. <label class="option-text"><input type="radio" name="format" id="format-novel" value="novel" {{if eq .Format "novel"}}checked="checked"{{end}} />
  133. Novel
  134. </label>
  135. <p>No dates shown. Oldest posts first.</p>
  136. </li>
  137. <li>
  138. <label class="option-text"><input type="radio" name="format" id="format-notebook" value="notebook" {{if eq .Format "notebook"}}checked="checked"{{end}} />
  139. Notebook
  140. </label>
  141. <p>No dates shown. Latest posts first.</p>
  142. </li>
  143. </ul>
  144. </div>
  145. </div>
  146. <div class="option">
  147. <h2>Text Rendering</h2>
  148. <div class="section">
  149. <p class="explain">Customize how plain text renders on your blog.</p>
  150. <ul style="list-style:none">
  151. <li>
  152. <label class="option-text disabled"><input type="checkbox" name="markdown" checked="checked" disabled />
  153. Markdown
  154. </label>
  155. </li>
  156. <li>
  157. <label><input type="checkbox" name="mathjax" {{if .RenderMathJax}}checked="checked"{{end}} />
  158. MathJax
  159. </label>
  160. </li>
  161. </ul>
  162. </div>
  163. </div>
  164. <div class="option">
  165. <h2>Custom CSS</h2>
  166. <div class="section">
  167. <textarea id="css-editor" class="section codable" name="style_sheet">{{.StyleSheet}}</textarea>
  168. <p class="explain">See our guide on <a href="https://guides.write.as/customizing/#custom-css">customization</a>.</p>
  169. </div>
  170. </div>
  171. <div class="option">
  172. <h2>Post Signature</h2>
  173. <div class="section">
  174. <p class="explain">This content will be added to the end of every post on this blog, as if it were part of the post itself. Markdown, HTML, and shortcodes are allowed.</p>
  175. <textarea id="signature" class="section norm" name="signature">{{.Signature}}</textarea>
  176. </div>
  177. </div>
  178. <div class="option">
  179. <h2>Verification</h2>
  180. <div class="section">
  181. <p class="explain">Verify that you own another site on the open web, fediverse, etc. For example, enter your Mastodon profile address here, then on Mastodon add a link back to this blog &mdash; it will show up as <a href="https://joinmastodon.org/verification" target="mastoverified">verified</a> there.</p>
  182. <input type="text" name="verification_link" style="width:100%" value="{{.Verification}}" placeholder="https://writing.exchange/@writefreely" />
  183. <p class="explain">This adds a <code>rel="me"</code> code in your blog's <code>&lt;head&gt;</code>.</p>
  184. </div>
  185. </div>
  186. {{if .UserPage.StaticPage.AppCfg.Monetization}}
  187. <div class="option">
  188. <h2>Web Monetization</h2>
  189. <div class="section">
  190. <p class="explain">Web Monetization enables you to receive micropayments from readers via <a href="https://interledger.org">Interledger</a>. Add your payment pointer to enable Web Monetization on your blog.</p>
  191. <input type="text" name="monetization_pointer" style="width:100%" value="{{.Collection.Monetization}}" placeholder="$wallet.example.com/alice" />
  192. </div>
  193. </div>
  194. {{end}}
  195. <div class="option" style="text-align: center; margin-top: 4em;">
  196. <input type="submit" id="save-changes" value="Save changes" />
  197. <p><a href="{{if .SingleUser}}/{{else}}/{{.Alias}}/{{end}}">View Blog</a></p>
  198. {{if ne .Alias .Username}}<p><a class="danger" href="#modal-delete" onclick="promptDelete();">Delete Blog...</a></p>{{end}}
  199. </div>
  200. </div>
  201. </form>
  202. </div>
  203. <div id="modal-delete" class="modal">
  204. <h2>Are you sure you want to delete this blog?</h2>
  205. <div class="body short">
  206. <p style="text-align:left">This will permanently erase <strong>{{.DisplayTitle}}</strong> ({{.FriendlyHost}}/{{.Alias}}) from the internet. Any posts on this blog will be saved and made into drafts (found on your <a href="/me/posts/">Drafts</a> page).</p>
  207. <p>If you're sure you want to delete this blog, enter its name in the box below and press <strong>Delete</strong>.</p>
  208. <ul id="delete-errors" class="errors"></ul>
  209. <input id="confirm-text" placeholder="{{.Alias}}" type="text" class="boxy" style="margin-top: 0.5em;" />
  210. <div style="text-align:right; margin-top: 1em;">
  211. <a id="cancel-delete" style="margin-right:2em" href="#">Cancel</a>
  212. <button id="btn-delete" class="danger" onclick="deleteBlog(); return false;">Delete</button>
  213. </div>
  214. </div>
  215. </div>
  216. <script src="/js/h.js"></script>
  217. <script src="/js/modals.js"></script>
  218. <script src="/js/ace.js" type="text/javascript" charset="utf-8"></script>
  219. <script>
  220. H.getEl('cancel-delete').on('click', closeModals);
  221. var deleteBlog = function(e) {
  222. if (document.getElementById('confirm-text').value != '{{.Alias}}') {
  223. document.getElementById('delete-errors').innerHTML = '<li class="urgent">Enter <strong>{{.Alias}}</strong> in the box below.</li>';
  224. return;
  225. }
  226. // Clear errors
  227. document.getElementById('delete-errors').innerHTML = '';
  228. document.getElementById('btn-delete').innerHTML = 'Deleting...';
  229. var http = new XMLHttpRequest();
  230. var url = "/api/collections/{{.Alias}}?web=1";
  231. http.open("DELETE", url, true);
  232. http.setRequestHeader("Content-type", "application/json");
  233. http.onreadystatechange = function() {
  234. if (http.readyState == 4) {
  235. if (http.status == 204) {
  236. window.location = '/me/c/';
  237. } else {
  238. var data = JSON.parse(http.responseText);
  239. document.getElementById('delete-errors').innerHTML = '<li class="urgent">'+data.error_msg+'</li>';
  240. document.getElementById('btn-delete').innerHTML = 'Delete';
  241. }
  242. }
  243. };
  244. http.send(null);
  245. };
  246. function createHidden(theForm, key, value) {
  247. var input = document.createElement('input');
  248. input.type = 'hidden';
  249. input.name = key;
  250. input.value = value;
  251. theForm.appendChild(input);
  252. }
  253. function disableSubmit() {
  254. var $form = document.forms['customize-form'];
  255. createHidden($form, 'style_sheet', cssEditor.getSession().getValue());
  256. var $btn = document.getElementById("save-changes");
  257. $btn.value = "Saving changes...";
  258. $btn.disabled = true;
  259. return true;
  260. }
  261. function promptDelete() {
  262. showModal("delete");
  263. }
  264. var $fediDomain = document.getElementById('fedi-domain');
  265. var $fediCustomDomain = document.getElementById('fedi-custom-domain');
  266. var $customDomain = document.getElementById('domain-alias');
  267. var $customHandleEnv = document.getElementById('custom-handle-env');
  268. var $normalHandleEnv = document.getElementById('normal-handle-env');
  269. var $emailSubsCheck = document.getElementById('email_subs');
  270. var $letterReply = document.getElementById('letter_reply');
  271. H.getEl('email_subs').on('click', function() {
  272. let show = $emailSubsCheck.checked
  273. $letterReply.disabled = !show
  274. })
  275. if (matchMedia('(pointer:fine)').matches) {
  276. // Only initialize Ace editor on devices with a mouse
  277. var opt = {
  278. showLineNumbers: false,
  279. showPrintMargin: 0,
  280. minLines: 10,
  281. maxLines: 40,
  282. };
  283. var theme = "ace/theme/chrome";
  284. var cssEditor = ace.edit("css-editor");
  285. cssEditor.setTheme(theme);
  286. cssEditor.session.setMode("ace/mode/css");
  287. cssEditor.setOptions(opt);
  288. cssEditor.resize(true);
  289. }
  290. </script>
  291. {{template "footer" .}}
  292. {{end}}