A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

242 lines
8.9 KiB

  1. {{define "upgrade"}}
  2. <p><a href="/me/plan?to=/me/c/{{.Alias}}">Upgrade</a> for <span>$40 / year</span> to edit.</p>
  3. {{end}}
  4. {{define "collection"}}
  5. {{template "header" .}}
  6. <div class="content-container snug">
  7. <div id="overlay"></div>
  8. {{if .Silenced}}
  9. {{template "user-silenced"}}
  10. {{end}}
  11. <h2>Customize {{.DisplayTitle}} <a href="{{if .SingleUser}}/{{else}}/{{.Alias}}/{{end}}">view blog</a></h2>
  12. {{if .Flashes}}<ul class="errors">
  13. {{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
  14. </ul>{{end}}
  15. <form name="customize-form" action="/api/collections/{{.Alias}}" method="post" onsubmit="return disableSubmit()">
  16. <div id="collection-options">
  17. <div style="text-align:center">
  18. <h1><input type="text" name="title" id="title" value="{{.DisplayTitle}}" placeholder="Title" /></h1>
  19. <p><input type="text" name="description" id="description" value="{{.Description}}" placeholder="Description" /></p>
  20. </div>
  21. <div class="option">
  22. <h2><a name="preferred-url"></a>URL</h2>
  23. <div class="section">
  24. {{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}}
  25. <ul style="list-style:none">
  26. <li>
  27. {{.FriendlyHost}}/<strong>{{.Alias}}</strong>/
  28. </li>
  29. <li>
  30. <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>
  31. </li>
  32. </ul>
  33. </div>
  34. </div>
  35. <div class="option">
  36. <h2>Publicity</h2>
  37. <div class="section">
  38. <ul style="list-style:none">
  39. <li>
  40. <label><input type="radio" name="visibility" id="visibility-unlisted" value="0" {{if .IsUnlisted}}checked="checked"{{end}} />
  41. Unlisted
  42. </label>
  43. <p>This blog is visible to {{if .Private}}any registered user on this instance{{else}}anyone with its link{{end}}.</p>
  44. </li>
  45. <li>
  46. <label class="option-text"><input type="radio" name="visibility" id="visibility-private" value="2" {{if .IsPrivate}}checked="checked"{{end}} />
  47. Private
  48. </label>
  49. <p>Only you may read this blog (while you're logged in).</p>
  50. </li>
  51. <li>
  52. <label class="option-text"><input type="radio" name="visibility" id="visibility-protected" value="4" {{if .IsProtected}}checked="checked"{{end}} />
  53. 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}}" />
  54. </label>
  55. <p>A password is required to read this blog.</p>
  56. </li>
  57. {{if not .SingleUser}}
  58. <li>
  59. <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}} />
  60. Public
  61. </label>
  62. {{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>
  63. {{else}}<p>The public reader is currently turned off for this community.</p>{{end}}
  64. </li>
  65. {{end}}
  66. </ul>
  67. </div>
  68. </div>
  69. <div class="option">
  70. <h2>Display Format</h2>
  71. <div class="section">
  72. <p class="explain">Customize how your posts display on your page.
  73. </p>
  74. <ul style="list-style:none">
  75. <li>
  76. <label><input type="radio" name="format" id="format-blog" value="blog" {{if or (not .Format) (eq .Format "blog")}}checked="checked"{{end}} />
  77. Blog
  78. </label>
  79. <p>Dates are shown. Latest posts listed first.</p>
  80. </li>
  81. <li>
  82. <label class="option-text"><input type="radio" name="format" id="format-novel" value="novel" {{if eq .Format "novel"}}checked="checked"{{end}} />
  83. Novel
  84. </label>
  85. <p>No dates shown. Oldest posts first.</p>
  86. </li>
  87. <li>
  88. <label class="option-text"><input type="radio" name="format" id="format-notebook" value="notebook" {{if eq .Format "notebook"}}checked="checked"{{end}} />
  89. Notebook
  90. </label>
  91. <p>No dates shown. Latest posts first.</p>
  92. </li>
  93. </ul>
  94. </div>
  95. </div>
  96. <div class="option">
  97. <h2>Text Rendering</h2>
  98. <div class="section">
  99. <p class="explain">Customize how plain text renders on your blog.</p>
  100. <ul style="list-style:none">
  101. <li>
  102. <label class="option-text disabled"><input type="checkbox" name="markdown" checked="checked" disabled />
  103. Markdown
  104. </label>
  105. </li>
  106. <li>
  107. <label><input type="checkbox" name="mathjax" {{if .RenderMathJax}}checked="checked"{{end}} />
  108. MathJax
  109. </label>
  110. </li>
  111. </ul>
  112. </div>
  113. </div>
  114. <div class="option">
  115. <h2>Custom CSS</h2>
  116. <div class="section">
  117. <textarea id="css-editor" class="section codable" name="style_sheet">{{.StyleSheet}}</textarea>
  118. <p class="explain">See our guide on <a href="https://guides.write.as/customizing/#custom-css">customization</a>.</p>
  119. </div>
  120. </div>
  121. <div class="option" style="text-align: center; margin-top: 4em;">
  122. <input type="submit" id="save-changes" value="Save changes" />
  123. <p><a href="{{if .SingleUser}}/{{else}}/{{.Alias}}/{{end}}">View Blog</a></p>
  124. {{if ne .Alias .Username}}<p><a class="danger" href="#modal-delete" onclick="promptDelete();">Delete Blog...</a></p>{{end}}
  125. </div>
  126. </div>
  127. </form>
  128. </div>
  129. <div id="modal-delete" class="modal">
  130. <h2>Are you sure you want to delete this blog?</h2>
  131. <div class="body short">
  132. <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>
  133. <p>If you're sure you want to delete this blog, enter its name in the box below and press <strong>Delete</strong>.</p>
  134. <ul id="delete-errors" class="errors"></ul>
  135. <input id="confirm-text" placeholder="{{.Alias}}" type="text" class="boxy" style="margin-top: 0.5em;" />
  136. <div style="text-align:right; margin-top: 1em;">
  137. <a id="cancel-delete" style="margin-right:2em" href="#">Cancel</a>
  138. <button id="btn-delete" class="danger" onclick="deleteBlog(); return false;">Delete</button>
  139. </div>
  140. </div>
  141. </div>
  142. <script src="/js/h.js"></script>
  143. <script src="/js/ace.js" type="text/javascript" charset="utf-8"></script>
  144. <script>
  145. // Begin shared modal code
  146. function showModal(id) {
  147. document.getElementById('overlay').style.display = 'block';
  148. document.getElementById('modal-'+id).style.display = 'block';
  149. }
  150. var closeModals = function(e) {
  151. e.preventDefault();
  152. document.getElementById('overlay').style.display = 'none';
  153. var modals = document.querySelectorAll('.modal');
  154. for (var i=0; i<modals.length; i++) {
  155. modals[i].style.display = 'none';
  156. }
  157. };
  158. H.getEl('overlay').on('click', closeModals);
  159. H.getEl('cancel-delete').on('click', closeModals);
  160. // end
  161. var deleteBlog = function(e) {
  162. if (document.getElementById('confirm-text').value != '{{.Alias}}') {
  163. document.getElementById('delete-errors').innerHTML = '<li class="urgent">Enter <strong>{{.Alias}}</strong> in the box below.</li>';
  164. return;
  165. }
  166. // Clear errors
  167. document.getElementById('delete-errors').innerHTML = '';
  168. document.getElementById('btn-delete').innerHTML = 'Deleting...';
  169. var http = new XMLHttpRequest();
  170. var url = "/api/collections/{{.Alias}}?web=1";
  171. http.open("DELETE", url, true);
  172. http.setRequestHeader("Content-type", "application/json");
  173. http.onreadystatechange = function() {
  174. if (http.readyState == 4) {
  175. if (http.status == 204) {
  176. window.location = '/me/c/';
  177. } else {
  178. var data = JSON.parse(http.responseText);
  179. document.getElementById('delete-errors').innerHTML = '<li class="urgent">'+data.error_msg+'</li>';
  180. document.getElementById('btn-delete').innerHTML = 'Delete';
  181. }
  182. }
  183. };
  184. http.send(null);
  185. };
  186. function createHidden(theForm, key, value) {
  187. var input = document.createElement('input');
  188. input.type = 'hidden';
  189. input.name = key;
  190. input.value = value;
  191. theForm.appendChild(input);
  192. }
  193. function disableSubmit() {
  194. var $form = document.forms['customize-form'];
  195. createHidden($form, 'style_sheet', cssEditor.getSession().getValue());
  196. var $btn = document.getElementById("save-changes");
  197. $btn.value = "Saving changes...";
  198. $btn.disabled = true;
  199. return true;
  200. }
  201. function promptDelete() {
  202. showModal("delete");
  203. }
  204. var $fediDomain = document.getElementById('fedi-domain');
  205. var $fediCustomDomain = document.getElementById('fedi-custom-domain');
  206. var $customDomain = document.getElementById('domain-alias');
  207. var $customHandleEnv = document.getElementById('custom-handle-env');
  208. var $normalHandleEnv = document.getElementById('normal-handle-env');
  209. var opt = {
  210. showLineNumbers: false,
  211. showPrintMargin: 0,
  212. };
  213. var theme = "ace/theme/chrome";
  214. var cssEditor = ace.edit("css-editor");
  215. cssEditor.setTheme(theme);
  216. cssEditor.session.setMode("ace/mode/css");
  217. cssEditor.setOptions(opt);
  218. </script>
  219. {{template "footer" .}}
  220. {{end}}