ThreadNew.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <div class='route_container thread_new'>
  3. <div class='h1'>Post new thread</div>
  4. <div class='thread_meta_info'>
  5. <div class='thread_meta_info__text'>Enter the thread title and the category to post it in</div>
  6. <select-button v-model='selectedCategory' :options='categories'></select-button>
  7. <fancy-input
  8. placeholder='Thread title'
  9. v-model='name'
  10. :error='errors.name'
  11. style='margin-left: 0.5rem; display: inline-block;'
  12. large='true'
  13. width='15rem'
  14. ></fancy-input>
  15. </div>
  16. <div class='editor' :class='{"editor--focus": focusInput}'>
  17. <div class='editor__input'>
  18. <div class='editor__format_bar'>
  19. editor
  20. </div>
  21. <input-editor-core
  22. v-model='editor'
  23. :error='errors.content'
  24. @mentions='setMentions'
  25. @focus='setFocusInput(true)'
  26. @blur='setFocusInput(false)'
  27. ></input-editor-core>
  28. </div>
  29. <div class='editor__preview'>
  30. <div class='editor__format_bar editor__format_bar--preview'>
  31. preview
  32. </div>
  33. <input-editor-preview :value='editor' :mentions='mentions'></input-editor-preview>
  34. </div>
  35. </div>
  36. <loading-button class='button--green submit' :loading='loading' @click='postThread'>Post thread</loading-button>
  37. </div>
  38. </template>
  39. <script>
  40. import InputEditorCore from '../InputEditorCore'
  41. import InputEditorPreview from '../InputEditorPreview'
  42. import FancyInput from '../FancyInput'
  43. import SelectButton from '../SelectButton'
  44. import LoadingButton from '../LoadingButton'
  45. import AjaxErrorHandler from '../../assets/js/errorHandler'
  46. import logger from '../../assets/js/logger'
  47. export default {
  48. name: 'ThreadNew',
  49. components: {
  50. InputEditorCore,
  51. InputEditorPreview,
  52. SelectButton,
  53. FancyInput,
  54. LoadingButton
  55. },
  56. data () {
  57. return {
  58. selectedCategory: this.$store.state.category.selectedCategory,
  59. editor: '',
  60. mentions: [],
  61. name: '',
  62. loading: false,
  63. focusInput: false,
  64. errors: {
  65. content: '',
  66. name: ''
  67. }
  68. }
  69. },
  70. computed: {
  71. categories () {
  72. return this.$store.getters.categoriesWithoutAll
  73. }
  74. },
  75. methods: {
  76. postThread () {
  77. if(!this.editor.trim().length) {
  78. this.errors.content = 'Cannot be blank'
  79. return;
  80. }
  81. this.errors.content = ''
  82. this.errors.name = ''
  83. this.loading = true
  84. this.axios.post('/api/v1/thread', {
  85. name: this.name,
  86. category: this.selectedCategory
  87. }).then(res => {
  88. return this.axios.post('/api/v1/post', {
  89. threadId: res.data.id,
  90. content: this.editor,
  91. mentions: this.mentions
  92. })
  93. }).then(res => {
  94. this.loading = false
  95. this.$router.push(`/thread/${res.data.Thread.slug}/${res.data.Thread.id}/0`)
  96. }).catch(e => {
  97. this.loading = false
  98. AjaxErrorHandler(this.$store)(e, (error, errors) => {
  99. let path = error.path
  100. if(this.errors[path] !== undefined) {
  101. this.errors[path] = error.message
  102. } else {
  103. errors.push(error.message)
  104. }
  105. })
  106. })
  107. },
  108. setFocusInput (val) {
  109. this.focusInput = val
  110. },
  111. setMentions (mentions) {
  112. this.mentions = mentions
  113. }
  114. },
  115. watch: {
  116. '$store.state.username' (username) {
  117. if(!username) {
  118. this.$router.push('/')
  119. }
  120. }
  121. },
  122. mounted () {
  123. this.$store.dispatch('setTitle', 'new thread')
  124. logger('threadNew')
  125. },
  126. beforeRouteEnter (to, from, next) {
  127. next(vm => {
  128. if(!vm.$store.state.username) {
  129. vm.$store.commit('setAccountModalState', true);
  130. next('/')
  131. }
  132. })
  133. }
  134. }
  135. </script>
  136. <style lang='scss'>
  137. @import '../../assets/scss/variables.scss';
  138. .thread_new {
  139. margin-top: 1rem;
  140. }
  141. .thread_meta_info {
  142. background-color: #fff;
  143. @extend .shadow_border;
  144. border-radius: 0.25rem;
  145. padding: 1rem;
  146. margin: 1rem 0;
  147. @at-root #{&}__text {
  148. margin-bottom: 0.5rem;
  149. }
  150. }
  151. .submit {
  152. margin-top: 1rem;
  153. }
  154. .editor {
  155. display: flex;
  156. background-color: #fff;
  157. border-radius: 0.25rem;
  158. box-shadow: 0 0 0.3rem rgba(175, 175, 175, 0.5);
  159. transition: all 0.2s;
  160. @at-root #{&}--focus {
  161. box-shadow: 0 0 0.3rem rgba(175, 175, 175, 1);
  162. }
  163. @at-root #{&}__format_bar {
  164. height: 2.5rem;
  165. background-color: $color__gray--primary;
  166. display: flex;
  167. padding-right: 1rem;
  168. padding-bottom: 0.25rem;
  169. justify-content: flex-end;
  170. align-items: center;
  171. font-variant: small-caps;
  172. }
  173. @at-root #{&}__input {
  174. width: 50%;
  175. position: relative;
  176. .input_editor_core__format_bar {
  177. left: 0rem;
  178. }
  179. .input_editor_core textarea {
  180. height: 14rem;
  181. }
  182. }
  183. @at-root #{&}__preview {
  184. border-left: 1px solid $color__gray--darker;
  185. width: 50%;
  186. .input_editor_preview__markdownHTML {
  187. height: 14.2rem;
  188. }
  189. }
  190. }
  191. </style>