AdminCategories.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. <template>
  2. <div class='admin_categories'>
  3. <modal-window v-model='showAddModal'>
  4. <div
  5. class='admin_categories__modal__overlay'
  6. :class='{
  7. "admin_categories__modal__overlay--show": loading
  8. }'
  9. >
  10. <loading-icon></loading-icon>
  11. </div>
  12. <div class='admin_categories__modal'>
  13. <p class='admin_categories__modal__text'>Add a category</p>
  14. <fancy-input v-model='add.name' placeholder='Category name'></fancy-input>
  15. <input type='color' class='button button--color_input' v-model='add.color' />
  16. <div class='admin_categories__modal__buttons'>
  17. <button class='button button--modal' @click='toggleAddModal'>Cancel</button>
  18. <button class='button button--modal button--green' @click='addCategory'>Add category</button>
  19. </div>
  20. </div>
  21. </modal-window>
  22. <modal-window v-model='showEditModal'>
  23. <div
  24. class='admin_categories__modal__overlay'
  25. :class='{
  26. "admin_categories__modal__overlay--show": loading
  27. }'
  28. >
  29. <loading-icon></loading-icon>
  30. </div>
  31. <div class='admin_categories__modal'>
  32. <p class='admin_categories__modal__text'>Edit this category</p>
  33. <fancy-input v-model='edit.name' placeholder='Category name'></fancy-input>
  34. <input type='color' class='button button--color_input' v-model='edit.color' />
  35. <div class='admin_categories__modal__buttons'>
  36. <button class='button button--modal' @click='toggleEditModal(null)'>Cancel</button>
  37. <button class='button button--modal button--green' @click='editCategory'>Update category</button>
  38. </div>
  39. </div>
  40. </modal-window>
  41. <div class='category_widget__box'>
  42. <div class='category_widget__text'>
  43. <div class='category_widget__text__title'>Categories</div>
  44. Hover to remove or edit a category. <br/>
  45. Removing a category will place any threads in that category into 'Other'
  46. </div>
  47. <transition-group name='slide'>
  48. <div
  49. class='admin_categories__category'
  50. v-for='(category, $index) in categories'
  51. :key='category'
  52. >
  53. <div class='admin_categories__category__actions_holder'>
  54. <div class='admin_categories__category__actions'>
  55. <div
  56. class='admin_categories__category__action'
  57. @click='removeCateogry(category.id, $index)'
  58. >Remove</div>
  59. <div
  60. class='admin_categories__category__action'
  61. @click='toggleEditModal(category, $index)'
  62. >Edit</div>
  63. </div>
  64. </div>
  65. <div
  66. class='admin_categories__category__color'
  67. :style='{ "background-color": category.color }'
  68. ></div>
  69. <div class='admin_categories__category__name'>{{category.name}}</div>
  70. </div>
  71. </transition-group>
  72. <div style="margin-top: 0.5rem;">
  73. <div class='admin_categories__category admin_categories__category--add' @click='toggleAddModal'>
  74. <div
  75. class='admin_categories__category__color fa fa-plus'
  76. >
  77. </div>
  78. <div class='admin_categories__category__name'>Add new category</div>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. </template>
  84. <script>
  85. import ModalWindow from './ModalWindow'
  86. import FancyInput from './FancyInput'
  87. import LoadingIcon from './LoadingIcon'
  88. import AjaxErrorHandler from '../assets/js/errorHandler'
  89. export default {
  90. name: 'AdminCategories',
  91. components: {
  92. ModalWindow,
  93. FancyInput,
  94. LoadingIcon
  95. },
  96. data () {
  97. return {
  98. loading: false,
  99. showAddModal: false,
  100. showEditModal: false,
  101. add: {
  102. name: '',
  103. color: '#ffffff'
  104. },
  105. edit: {
  106. name: '',
  107. color: '#ffffff',
  108. id: null,
  109. index: null
  110. },
  111. categories: []
  112. }
  113. },
  114. methods: {
  115. toggleAddModal () {
  116. this.add.name = ''
  117. this.add.color = '#ffffff'
  118. this.showAddModal = !this.showAddModal
  119. },
  120. toggleEditModal (category, index) {
  121. if(category) {
  122. this.edit.name = category.name
  123. this.edit.color = category.color
  124. this.edit.id = category.id
  125. this.edit.index = index
  126. } else {
  127. this.edit.name = ''
  128. this.edit.color = '#ffffff'
  129. this.edit.id = null
  130. this.edit.index = null
  131. }
  132. this.showEditModal = !this.showEditModal
  133. },
  134. addCategory () {
  135. this.loading = true
  136. this.axios
  137. .post('/api/v1/category', { name: this.add.name, color: this.add.color })
  138. .then(res => {
  139. this.toggleAddModal()
  140. this.loading = false
  141. this.categories.push(res.data)
  142. this.$store.commit('addCategories', res.data)
  143. })
  144. .catch(AjaxErrorHandler(this.$store))
  145. },
  146. removeCateogry (id, index) {
  147. this.axios
  148. .delete('/api/v1/category/' + id)
  149. .then(res => {
  150. this.categories.splice(index, 1)
  151. this.$store.commit('removeCategory', id)
  152. if(res.data.otherCategoryCreated) {
  153. this.$store.commit('addCategories', res.data.otherCategoryCreated)
  154. }
  155. })
  156. .catch(AjaxErrorHandler(this.$store))
  157. },
  158. editCategory () {
  159. this.loading = true
  160. this.axios
  161. .put('/api/v1/category/' + this.edit.id ,{
  162. name: this.edit.name,
  163. color: this.edit.color
  164. })
  165. .then(res => {
  166. this.loading = false
  167. this.categories.splice(this.edit.index, 1, res.data)
  168. this.$store.commit('updateCategory', res.data)
  169. this.toggleEditModal()
  170. })
  171. .catch(AjaxErrorHandler(this.$store))
  172. }
  173. },
  174. mounted () {
  175. this.axios
  176. .get('/api/v1/category')
  177. .then(res => {
  178. this.categories = res.data.filter(c => c.name !== 'Other')
  179. })
  180. .catch(AjaxErrorHandler(this.$store))
  181. }
  182. }
  183. </script>
  184. <style lang='scss' scoped>
  185. @import '../assets/scss/variables.scss';
  186. .slide-enter-active, .slide-leave-active, .slice-move {
  187. transition: all 1s;
  188. }
  189. .slide-enter, .slide-leave-to {
  190. opacity: 0;
  191. }
  192. .admin_categories {
  193. @at-root #{&}__modal {
  194. padding: 1rem;
  195. @at-root #{&}__text {
  196. margin-top: -0.5rem;
  197. margin-bottom: 1rem;
  198. }
  199. @at-root #{&}__buttons {
  200. margin-top: 0.5rem;
  201. }
  202. }
  203. @at-root #{&}__category {
  204. display: inline-flex;
  205. position: relative;
  206. align-items: center;
  207. background-color: rgba($color__lightgray--primary, 0.5);
  208. justify-content: center;
  209. border-radius: 5rem;
  210. padding: 0.25rem 0.5rem 0.25rem 0.5rem;
  211. border: thin solid $color__gray--darker;
  212. margin-right: 0.5rem;
  213. margin-bottom: 0.5rem;
  214. transition: all 0.2s;
  215. cursor: default;
  216. &:hover {
  217. background-color: $color__lightgray--primary;
  218. & .admin_categories__category__actions_holder {
  219. opacity: 1;
  220. margin-top: 0;
  221. pointer-events: all;
  222. }
  223. }
  224. @at-root #{&}--add {
  225. top: -0.25rem;
  226. cursor: pointer;
  227. }
  228. @at-root #{&}__actions_holder {
  229. position: absolute;
  230. top: -2.25rem;
  231. opacity: 0;
  232. pointer-events: none;
  233. margin-top: 1rem;
  234. padding-bottom: 1rem;
  235. transition: all 0.2s;
  236. }
  237. @at-root #{&}__actions {
  238. border-radius: 3rem;
  239. border: thin solid $color__gray--darker;
  240. overflow: hidden;
  241. display: flex;
  242. background-color: #fff;
  243. box-shadow: 0 0.2rem 3px 0px rgba(224, 224, 224, 0.4);
  244. }
  245. @at-root #{&}__action {
  246. padding: 0.25rem 0.5rem;
  247. cursor: pointer;
  248. transition: all 0.2s;
  249. &:first-of-type {
  250. border-right: 0.1rem solid $color__gray--primary;
  251. }
  252. &:hover {
  253. background-color: $color__lightgray--primary;
  254. }
  255. }
  256. @at-root #{&}__color {
  257. height: 1.25rem;
  258. width: 1.25rem;
  259. border-radius: 100%;
  260. margin-left: 0rem;
  261. margin-right: 0.25rem;
  262. display: flex;
  263. align-items: center;
  264. justify-content: center;
  265. }
  266. @at-root #{&}__name {
  267. position: relative;
  268. bottom: 0.1rem;
  269. }
  270. }
  271. }
  272. </style>