EditNews.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <template>
  2. <modal title="Edit News">
  3. <div slot="body" v-if="news && news._id">
  4. <label class="label">Title</label>
  5. <p class="control">
  6. <input
  7. v-model="news.title"
  8. class="input"
  9. type="text"
  10. placeholder="News Title"
  11. autofocus
  12. />
  13. </p>
  14. <label class="label">Description</label>
  15. <p class="control">
  16. <input
  17. v-model="news.description"
  18. class="input"
  19. type="text"
  20. placeholder="News Description"
  21. />
  22. </p>
  23. <div class="columns">
  24. <div class="column">
  25. <label class="label">Bugs</label>
  26. <p class="control has-addons">
  27. <input
  28. id="edit-bugs"
  29. class="input"
  30. type="text"
  31. placeholder="Bug"
  32. @keyup.enter="add('bugs')"
  33. />
  34. <a class="button is-info" href="#" @click="add('bugs')"
  35. >Add</a
  36. >
  37. </p>
  38. <span
  39. v-for="(bug, index) in news.bugs"
  40. class="tag is-info"
  41. :key="index"
  42. >
  43. {{ bug }}
  44. <button
  45. class="delete is-info"
  46. @click="remove('bugs', index)"
  47. />
  48. </span>
  49. </div>
  50. <div class="column">
  51. <label class="label">Features</label>
  52. <p class="control has-addons">
  53. <input
  54. id="edit-features"
  55. class="input"
  56. type="text"
  57. placeholder="Feature"
  58. @keyup.enter="add('features')"
  59. />
  60. <a
  61. class="button is-info"
  62. href="#"
  63. @click="add('features')"
  64. >Add</a
  65. >
  66. </p>
  67. <span
  68. v-for="(feature, index) in news.features"
  69. class="tag is-info"
  70. :key="index"
  71. >
  72. {{ feature }}
  73. <button
  74. class="delete is-info"
  75. @click="remove('features', index)"
  76. />
  77. </span>
  78. </div>
  79. </div>
  80. <div class="columns">
  81. <div class="column">
  82. <label class="label">Improvements</label>
  83. <p class="control has-addons">
  84. <input
  85. id="edit-improvements"
  86. class="input"
  87. type="text"
  88. placeholder="Improvement"
  89. @keyup.enter="add('improvements')"
  90. />
  91. <a
  92. class="button is-info"
  93. href="#"
  94. @click="add('improvements')"
  95. >Add</a
  96. >
  97. </p>
  98. <span
  99. v-for="(improvement, index) in news.improvements"
  100. class="tag is-info"
  101. :key="index"
  102. >
  103. {{ improvement }}
  104. <button
  105. class="delete is-info"
  106. @click="remove('improvements', index)"
  107. />
  108. </span>
  109. </div>
  110. <div class="column">
  111. <label class="label">Upcoming</label>
  112. <p class="control has-addons">
  113. <input
  114. id="edit-upcoming"
  115. class="input"
  116. type="text"
  117. placeholder="Upcoming"
  118. @keyup.enter="add('upcoming')"
  119. />
  120. <a
  121. class="button is-info"
  122. href="#"
  123. @click="add('upcoming')"
  124. >Add</a
  125. >
  126. </p>
  127. <span
  128. v-for="(upcoming, index) in news.upcoming"
  129. class="tag is-info"
  130. :key="index"
  131. >
  132. {{ upcoming }}
  133. <button
  134. class="delete is-info"
  135. @click="remove('upcoming', index)"
  136. />
  137. </span>
  138. </div>
  139. </div>
  140. </div>
  141. <div slot="footer">
  142. <button class="button is-success" @click="updateNews(false)">
  143. <i class="material-icons save-changes">done</i>
  144. <span>&nbsp;Save</span>
  145. </button>
  146. <button class="button is-success" @click="updateNews(true)">
  147. <i class="material-icons save-changes">done</i>
  148. <span>&nbsp;Save and close</span>
  149. </button>
  150. <button
  151. class="button is-danger"
  152. @click="
  153. closeModal({
  154. sector,
  155. modal: 'editNews'
  156. })
  157. "
  158. >
  159. <span>&nbsp;Close</span>
  160. </button>
  161. </div>
  162. </modal>
  163. </template>
  164. <script>
  165. import { mapActions, mapState } from "vuex";
  166. import Toast from "toasters";
  167. import io from "../../io";
  168. import Modal from "../Modal.vue";
  169. export default {
  170. components: { Modal },
  171. props: {
  172. newsId: { type: String, default: "" },
  173. sector: { type: String, default: "admin" }
  174. },
  175. computed: {
  176. ...mapState("modals/editNews", {
  177. news: state => state.news
  178. })
  179. },
  180. mounted() {
  181. io.getSocket(socket => {
  182. this.socket = socket;
  183. this.socket.dispatch(`news.getNewsFromId`, this.newsId, res => {
  184. if (res.status === "success") {
  185. const news = res.data;
  186. this.editNews(news);
  187. } else {
  188. new Toast({
  189. content: "News with that ID not found",
  190. timeout: 3000
  191. });
  192. this.closeModal({
  193. sector: this.sector,
  194. modal: "editNews"
  195. });
  196. }
  197. });
  198. });
  199. },
  200. methods: {
  201. add(type) {
  202. const change = document.getElementById(`edit-${type}`).value.trim();
  203. if (this.news[type].indexOf(change) !== -1)
  204. return new Toast({
  205. content: `Tag already exists`,
  206. timeout: 3000
  207. });
  208. if (change) this.addChange({ type, change });
  209. else
  210. new Toast({
  211. content: `${type} cannot be empty`,
  212. timeout: 3000
  213. });
  214. document.getElementById(`edit-${type}`).value = "";
  215. return true;
  216. },
  217. remove(type, index) {
  218. this.removeChange({ type, index });
  219. },
  220. updateNews(close) {
  221. this.socket.dispatch(
  222. "news.update",
  223. this.news._id,
  224. this.news,
  225. res => {
  226. new Toast({ content: res.message, timeout: 4000 });
  227. if (res.status === "success") {
  228. if (close)
  229. this.closeModal({
  230. sector: this.sector,
  231. modal: "editNews"
  232. });
  233. }
  234. }
  235. );
  236. },
  237. ...mapActions("modalVisibility", ["closeModal"]),
  238. ...mapActions("modals/editNews", [
  239. "editNews",
  240. "addChange",
  241. "removeChange"
  242. ])
  243. }
  244. };
  245. </script>
  246. <style lang="scss" scoped>
  247. input[type="range"] {
  248. -webkit-appearance: none;
  249. width: 100%;
  250. margin: 7.3px 0;
  251. }
  252. input[type="range"]:focus {
  253. outline: none;
  254. }
  255. input[type="range"]::-webkit-slider-runnable-track {
  256. width: 100%;
  257. height: 5.2px;
  258. cursor: pointer;
  259. box-shadow: 0;
  260. background: var(--light-grey-3);
  261. border-radius: 0;
  262. border: 0;
  263. }
  264. input[type="range"]::-webkit-slider-thumb {
  265. box-shadow: 0;
  266. border: 0;
  267. height: 19px;
  268. width: 19px;
  269. border-radius: 15px;
  270. background: var(--primary-color);
  271. cursor: pointer;
  272. -webkit-appearance: none;
  273. margin-top: -6.5px;
  274. }
  275. input[type="range"]::-moz-range-track {
  276. width: 100%;
  277. height: 5.2px;
  278. cursor: pointer;
  279. box-shadow: 0;
  280. background: var(--light-grey-3);
  281. border-radius: 0;
  282. border: 0;
  283. }
  284. input[type="range"]::-moz-range-thumb {
  285. box-shadow: 0;
  286. border: 0;
  287. height: 19px;
  288. width: 19px;
  289. border-radius: 15px;
  290. background: var(--primary-color);
  291. cursor: pointer;
  292. -webkit-appearance: none;
  293. margin-top: -6.5px;
  294. }
  295. input[type="range"]::-ms-track {
  296. width: 100%;
  297. height: 5.2px;
  298. cursor: pointer;
  299. box-shadow: 0;
  300. background: var(--light-grey-3);
  301. border-radius: 1.3px;
  302. }
  303. input[type="range"]::-ms-fill-lower {
  304. background: var(--light-grey-3);
  305. border: 0;
  306. border-radius: 0;
  307. box-shadow: 0;
  308. }
  309. input[type="range"]::-ms-fill-upper {
  310. background: var(--light-grey-3);
  311. border: 0;
  312. border-radius: 0;
  313. box-shadow: 0;
  314. }
  315. input[type="range"]::-ms-thumb {
  316. box-shadow: 0;
  317. border: 0;
  318. height: 15px;
  319. width: 15px;
  320. border-radius: 15px;
  321. background: var(--primary-color);
  322. cursor: pointer;
  323. -webkit-appearance: none;
  324. margin-top: 1.5px;
  325. }
  326. .controls {
  327. display: flex;
  328. flex-direction: column;
  329. align-items: center;
  330. }
  331. .artist-genres {
  332. display: flex;
  333. justify-content: space-between;
  334. }
  335. #volumeSlider {
  336. margin-bottom: 15px;
  337. }
  338. .has-text-centered {
  339. padding: 10px;
  340. }
  341. .thumbnail-preview {
  342. display: flex;
  343. margin: 0 auto 25px auto;
  344. max-width: 200px;
  345. width: 100%;
  346. }
  347. .modal-card-body,
  348. .modal-card-foot {
  349. border-top: 0;
  350. }
  351. .label,
  352. .checkbox,
  353. h5 {
  354. font-weight: normal;
  355. }
  356. .video-container {
  357. display: flex;
  358. flex-direction: column;
  359. align-items: center;
  360. padding: 10px;
  361. iframe {
  362. pointer-events: none;
  363. }
  364. }
  365. .save-changes {
  366. color: var(--white);
  367. }
  368. .tag:not(:last-child) {
  369. margin-right: 5px;
  370. }
  371. </style>