AdminCategories.vue 7.5 KB

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