post_wizard.tx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <script type="text/javascript" src="/scripts/post_wizard.js"></script>
  2. <script type="application/json" id="wizard-types"><: $types | mark_raw :></script>
  3. <div id="backoffice">
  4. <p class="title">
  5. Existing Post Types:
  6. </p>
  7. A "post type" is just a template living in <code>templates/html/components/forms/</code>.
  8. Every post picks exactly one of them &mdash; it's what the <em>Content Template</em> dropdown
  9. selects when you edit a Series.
  10. <hr />
  11. <label for="wizard-existing">Start from</label>
  12. <select class="cooltext" id="wizard-existing" name="wizard_existing" onchange="fillFromType(this);">
  13. <option value="">A new post type</option>
  14. : for $forms -> $form {
  15. <option value="<: $form :>"><: $form :></option>
  16. : }
  17. </select>
  18. <p id="wizard-type-description" class="wizard-type-description"></p>
  19. <form class="Submissions" id="postTypeWizard" method="post" action="/admin/wyzzerdd/save">
  20. <details id="wizard-description-editor">
  21. <summary>Description &mdash; what this post type is for</summary>
  22. Shown here when somebody picks this type. It is stored in the sidecar under
  23. x-tcms-post-type, which the validator never sees, so it can say whatever is useful.
  24. <br />
  25. <textarea class="cooltext" name="description" rows="3" form="postTypeWizard"
  26. placeholder="A recipe, with its cook time and servings."><: $description :></textarea>
  27. </details>
  28. <hr />
  29. <p class="title">
  30. Create a new Post Type:
  31. </p>
  32. Picking an existing type above fills this form in with what that type was made from,
  33. so you can change one thing and save it back. Overwrite is ticked for you when you do,
  34. since saving it under the same name is the point &mdash; change the name and you get a
  35. copy instead.
  36. <br />
  37. This writes a new template into the forms directory currently in use
  38. (<code><: $forms_dir :></code>) along with a matching <code>.json</code> sidecar describing
  39. any custom fields, so that the data model knows to keep them when a post is saved.
  40. <hr />
  41. Type Name * &mdash; letters, numbers, dash and underscore only<br />
  42. <input required class="cooltext" type="text" name="name" pattern="[A-Za-z0-9_-]+" placeholder="recipe" value="<: $name :>" />
  43. <p class="title">Canned Fields</p>
  44. Most post types reuse the same handful of blocks. Tick whichever ones this type needs.
  45. The title input, the visibility selector (visibility.tx) and the ACL selector (acls.tx)
  46. are always included &mdash; every post has all three, and a type whose editor cannot set
  47. them produces posts nobody can title, find or restrict.
  48. <br />
  49. <label for="wiz-wrapper">Wrap output in the standard post &lt;div&gt;<input id="wiz-wrapper" class="coolcb" type="checkbox" name="wrapper" value="1" <: $checked.wrapper :> /></label><br />
  50. <label for="wiz-post_title">Post title &amp; permalink (post_title.tx)<input id="wiz-post_title" class="coolcb" type="checkbox" name="inc_post_title" value="1" <: $checked.inc_post_title :> /></label><br />
  51. <label for="wiz-post_tags">Post tag list (post_tags.tx)<input id="wiz-post_tags" class="coolcb" type="checkbox" name="inc_post_tags" value="1" <: $checked.inc_post_tags :> /></label><br />
  52. <label for="wiz-preview">Preview image upload (preview.tx)<input id="wiz-preview" class="coolcb" type="checkbox" name="inc_preview" value="1" <: $checked.inc_preview :> /></label><br />
  53. <label for="wiz-tags">Tag editor (tags.tx)<input id="wiz-tags" class="coolcb" type="checkbox" name="inc_tags" value="1" <: $checked.inc_tags :> /></label><br />
  54. <label for="wiz-aliases">Alias URL editor (aliases.tx)<input id="wiz-aliases" class="coolcb" type="checkbox" name="inc_aliases" value="1" <: $checked.inc_aliases :> /></label><br />
  55. <label for="wiz-attachments">Attachment uploader (attachments.tx)<input id="wiz-attachments" class="coolcb" type="checkbox" name="inc_attachments" value="1" <: $checked.inc_attachments :> /></label><br />
  56. <br />
  57. Title placeholder text<br />
  58. <input class="cooltext" type="text" name="title_placeholder" placeholder="Iowa Man Destroys Moon" value="<: $title_placeholder :>" />
  59. <br />
  60. Where the posts come from<br />
  61. <select class="cooltext" name="datasource">
  62. <option value="" <: $datasource ? '' : 'selected' :> >The datastore &mdash; posts people write</option>
  63. : for $datasources -> $source {
  64. <option value="<: $source :>" <: $datasource == $source ? 'selected' : '' :> ><: $source :></option>
  65. : }
  66. </select>
  67. <br />
  68. A datasource builds this type's posts from somewhere else every time the page is drawn, rather
  69. than from posts anybody wrote &mdash; and if it says its posts cannot be written, no editor is
  70. generated at all, because there would be nothing behind the form to save.
  71. <br />
  72. Content Body &mdash; this is always the last thing in the editor, and is what carries the post body itself.<br />
  73. <select class="cooltext" name="body_form">
  74. <option value="form_common.tx" <: $body_form == 'form_multi.tx' ? '' : 'selected' :> >Single page (form_common.tx)</option>
  75. <option value="form_multi.tx" <: $body_form == 'form_multi.tx' ? 'selected' : '' :> >Multiple pages, like presentations (form_multi.tx)</option>
  76. </select>
  77. <p class="title">Custom Fields</p>
  78. These become extra inputs in the editor, and are available in your display template below
  79. as <code>&lt;: $post.your_field_name :&gt;</code>.
  80. Uploads aren't supported here &mdash; use the Attachment uploader above for those.
  81. <br />
  82. Whatever a canned block already collects isn't listed here &mdash; each one has a sidecar
  83. beside it saying so (preview.tx has preview.json), so a preview image is that box being
  84. ticked rather than a field you have to add.
  85. <br />
  86. A field set to <em>editors only</em> is dropped before the page is rendered for anyone who
  87. cannot edit it, so it is safe to refer to in the display template below without guarding it
  88. yourself &mdash; useful for a connection string or anything else that shouldn't be public.
  89. <br />
  90. An <em>Another Post</em> field depends on a different post type.
  91. <em>Pick one</em> stores a single post's ID, chosen from a dropdown in the editor, and hands you
  92. the whole post as <code>&lt;: $post.your_field_name_post :&gt;</code>.
  93. <em>All of them</em> stores nothing and simply hands you every post of that type as
  94. <code>&lt;: $post.your_field_name :&gt;</code> to loop over.
  95. <div id="wizard-params"></div>
  96. <button type="button" style="float:right;" class="coolbutton" onclick="addParam(); return false;">Add Field</button>
  97. <br style="clear:both;" />
  98. <p class="title">Display Template</p>
  99. <a href="https://metacpan.org/pod/Text::Xslate::Syntax::Kolon" title="GET UR MIND RITE">Kolon</a>
  100. markup for how this post type renders when someone looks at it.
  101. <br />
  102. <code>&lt;: $tiled :&gt;</code> is true when the series asked for its posts to be tiled, so branch on it
  103. if this type wants a compact view &mdash; see <code>forms/file.tx</code> for the shape.
  104. The wrapper gets the <code>tile</code> class either way.
  105. Note that it is only ever true for logged-out visitors: an editor needs the full view.
  106. Use <code>&lt;: $post.yourfield :&gt;</code> for your custom fields, and
  107. <code>&lt;: render_it($post.data) | mark_raw :&gt;</code> for the post body.
  108. <br />
  109. <textarea class="cooltext" name="display" rows="12" placeholder="&lt;div class=&quot;postData responsive-text&quot;&gt;&#10; &lt;: render_it($post.data) | mark_raw :&gt;&#10;&lt;/div&gt;"><: $display :></textarea>
  110. <br />
  111. <label for="wiz-overwrite">Overwrite it if this type already exists?<input id="wiz-overwrite" class="coolcb" type="checkbox" name="overwrite" value="1" <: $checked.overwrite :> /></label>
  112. <br />
  113. <input type="submit" class="coolbutton" value="Create Post Type" />
  114. </form>
  115. <template id="wizard-param-template">
  116. <div class="wizard-param-row">
  117. <hr />
  118. Name <input required class="cooltext" type="text" name="param_name" pattern="[A-Za-z][A-Za-z0-9_]*" placeholder="cook_time" />
  119. Type <select class="cooltext param-type" name="param_type" onchange="syncRelationRow(this);">
  120. <option value="text">Text</option>
  121. <option value="url">URL</option>
  122. <option value="number">Number</option>
  123. <option value="date">Date</option>
  124. <option value="textarea">Long Text</option>
  125. <option value="checkbox">Checkbox</option>
  126. <option value="relation">Another Post</option>
  127. </select>
  128. <span class="wizard-relation" style="display:none;">
  129. of type <select class="cooltext" name="param_relation_form">
  130. : for $forms -> $form {
  131. <option value="<: $form :>"><: $form :></option>
  132. : }
  133. </select>
  134. <select class="cooltext" name="param_relation_mode">
  135. <option value="one">pick one</option>
  136. <option value="all">all of them</option>
  137. </select>
  138. </span>
  139. Label <input class="cooltext" type="text" name="param_label" placeholder="Cook Time" />
  140. Placeholder <input class="cooltext" type="text" name="param_placeholder" placeholder="45 minutes" />
  141. <select class="cooltext" name="param_required">
  142. <option value="0">Optional</option>
  143. <option value="1">Required</option>
  144. </select>
  145. <select class="cooltext" name="param_private">
  146. <option value="0">Shown to everyone</option>
  147. <option value="1">Shown to editors only</option>
  148. </select>
  149. <!--
  150. The checkbox has no name, so it never submits; the hidden input beside
  151. it carries the value and always submits exactly one, ticked or not.
  152. A named checkbox would submit nothing when clear, and the server zips
  153. the param_* arrays together positionally, so one short row shifts
  154. every row after it.
  155. -->
  156. <label class="wizard-index" title="Give this field its own column and index, so queries on it do not have to read every post. Costs a little on save and some disk; only worth it for a field you actually search or filter on.">
  157. Index this field
  158. <input type="hidden" name="param_indexed" value="0" />
  159. <input class="coolcb" type="checkbox" onchange="syncIndexedRow(this);" />
  160. </label>
  161. <button type="button" class="coolbutton" onclick="delParam(this); return false;">Remove</button>
  162. </div>
  163. </template>
  164. </div>