Guest User

Untitled

a guest
Feb 4th, 2019
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.12 KB | None | 0 0
  1. /********** Like.vue **********/
  2. <template>
  3. <div class="like mt-3" v-cloak>
  4. <span class="badge badge-primary">{{ like.length }} Like</span>
  5. <span class="badge badge-danger">{{ unlike.length }} Unlike</span>
  6. <span class="float-right" v-if="user">
  7. <button class="btn btn-primary" @click="likePost" v-if="canLike"><i class="fa fa-fw fa-thumbs-up" title="Like This Tutorial"></i></button>
  8. <button class="btn btn-danger" @click="unlikePost" v-if="canUnlike"><i class="fa fa-fw fa-thumbs-down" title="Ublike This Tutorial"></i></button>
  9. </span>
  10. </div>
  11. </div>
  12. </template>
  13.  
  14. <script>
  15. export default {
  16. props: {
  17. id: {
  18. type: String,
  19. required: true
  20. },
  21. user: {
  22. type: Object
  23. },
  24. developer_id: {
  25. type: String
  26. },
  27. url: {
  28. type: String,
  29. required: true
  30. }
  31. },
  32. data(){
  33. return {
  34. like: [],
  35. unlike: [],
  36. canLike: true,
  37. canUnlike: true
  38. }
  39. },
  40. methods: {
  41. likePost(){
  42. var app = this;
  43. axios.post(app.url+'/tutorial/like', {
  44. tutorial_id: app.id,
  45. user_id: app.user.id,
  46. developer_id: app.developer_id
  47. })
  48. .then((response) => {
  49. app.like.push(response.data);
  50. app.canLike = false;
  51. app.canUnlike = true;
  52.  
  53. app.unlike.forEach(function(u) {
  54. if(u.developer_id == response.data.developer_id){
  55. var index = app.unlike.indexOf(u);
  56. app.unlike.splice(index, 1);
  57. }
  58. });
  59. })
  60. .catch((e) => {
  61. console.log(e);
  62. })
  63. },
  64. unlikePost(){
  65. var app = this;
  66. axios.post(app.url+'/tutorial/unlike', {
  67. tutorial_id: app.id,
  68. user_id: app.user.id,
  69. developer_id: app.developer_id
  70. })
  71. .then((response) => {
  72. app.unlike.push(response.data);
  73. app.canUnlike = false;
  74. app.canLike = true;
  75.  
  76. app.like.forEach(function(l) {
  77. if(l.developer_id == response.data.developer_id){
  78. var index = app.unlike.indexOf(l);
  79. app.like.splice(index, 1);
  80. }
  81. });
  82. })
  83. .catch((e) => {
  84. console.log(e);
  85. })
  86. }
  87. },
  88. mounted() {
  89. var app = this;
  90. axios.get(app.url+'/tutorial/likes/'+this.id)
  91. .then((response) => {
  92. app.like = response.data;
  93.  
  94. app.like.forEach(function(l) {
  95. if(l.developer_id == app.user.id){
  96. app.canUnlike = true;
  97. app.canLike = false;
  98. }
  99. });
  100. })
  101. .catch((e) => {
  102. console.log(e);
  103. })
  104.  
  105. axios.get(this.url+'/tutorial/unlikes/'+this.id)
  106. .then((response) => {
  107. app.unlike = response.data;
  108.  
  109. app.unlike.forEach(function(u) {
  110. if(u.developer_id == app.user.id){
  111. app.canUnlike = false;
  112. app.canLike = true;
  113. }
  114. });
  115. })
  116. .catch((e) => {
  117. console.log(e);
  118. })
  119. },
  120. computed: {
  121.  
  122. }
  123. }
  124. </script>
  125.  
  126. /********** Registration.vue **********/
  127. <style scoped>
  128. .required-icon{
  129. font-size: 18px;
  130. font-weight: bolder;
  131. color: #f30a0a;
  132. }
  133. .form-signin{
  134. max-width: 700px;
  135. }
  136. </style>
  137.  
  138. <template>
  139. <div class="profile-picture-change-widget mt-2">
  140. <!-- <div class="alert alert-danger" v-if="errors"> </div> -->
  141. <div class="form-signin">
  142. <center>
  143. <h2 class="mb-3 pricing-title">Sign Up Now</h2>
  144. </center>
  145. <form @submit.prevent="submitForm">
  146.  
  147. <div class="alert alert-success" v-if="submitStatus == 'OK'">
  148. <i class="fa fa-check"></i>
  149. An email has sent to you. Please verify your account.
  150. </div>
  151.  
  152. <div class="alert alert-danger" v-if="submitStatus === 'ERROR'">
  153. <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
  154. <p>Please correct the error</p>
  155. <ul>
  156. <li v-for="sError in serverErrors">
  157. <i class="fa fa-warning"></i> {{ sError[0] }}
  158. </li>
  159. </ul>
  160. </div>
  161. <div class="form-group row">
  162. <label for="first_name" class="col-sm-3 col-form-label">Your First Name
  163. <span class="required-icon">*</span>
  164. </label>
  165. <div class="col-sm-6">
  166. <input type="text"
  167. v-model.trim="$v.first_name.$model"
  168. class="form-control"
  169. :class="{' is-invalid': $v.first_name.$error}"
  170. id="first_name"
  171. name="first_name"
  172. placeholder="Write Your First Name">
  173. </div>
  174. <div class="col-sm-3">
  175. <div v-if="$v.first_name.$error" class="text-danger">
  176. <span><i class="fa fa-warning"></i></span>
  177. <span v-if="!$v.first_name.required"> Please give your first name
  178. <span class="required-icon">*</span>
  179. </span>
  180. <span v-if="!$v.first_name.minLength">
  181. First name will be greater than or equal 3 characters
  182. </span>
  183. <span v-if="!$v.first_name.maxLength">
  184. First name will be less than or equal 20 characters
  185. </span>
  186. </div>
  187. <div v-else-if="first_name == ''"></div>
  188. <div v-else>
  189. <i class="fa fa-check text-success"></i>
  190. </div>
  191. </div>
  192. </div>
  193.  
  194. <div class="form-group row">
  195. <label for="last_name" class="col-sm-3 col-form-label">Your Last Name</label>
  196. <div class="col-sm-6">
  197. <input type="text"
  198. v-model.trim="$v.last_name.$model"
  199. class="form-control"
  200. :class="{' is-invalid': $v.last_name.$error}"
  201. id="last_name"
  202. name="last_name"
  203. placeholder="Write Your Last Name">
  204. </div>
  205. <div class="col-sm-3">
  206. <div v-if="$v.last_name.$error" class="text-danger">
  207. <span><i class="fa fa-warning"></i></span>
  208. <span v-if="!$v.last_name.minLength">
  209. Last name will be greater than or equal 3 characters
  210. </span>
  211. <span v-if="!$v.last_name.maxLength">
  212. Last name will be less than or equal 15 characters
  213. </span>
  214. </div>
  215. <div v-else-if="last_name == ''"></div>
  216. <div v-else>
  217. <i class="fa fa-check text-success"></i>
  218. </div>
  219. </div>
  220. </div>
  221.  
  222. <div class="form-group row">
  223. <label for="username" class="col-sm-3 col-form-label">Your Username
  224. <span class="required-icon">*</span>
  225. </label>
  226. <div class="col-sm-6">
  227. <input type="text"
  228. v-model.trim="$v.username.$model"
  229. class="form-control"
  230. :class="{' is-invalid': $v.username.$error || usernameStatus === 'error'}"
  231. id="username"
  232. name="username"
  233. placeholder="Write Your Username">
  234. </div>
  235. <div class="col-sm-3">
  236. <div v-if="$v.username.$error" class="text-danger">
  237. <span><i class="fa fa-warning"></i></span>
  238. <span v-if="!$v.username.required"> Please give your username</span>
  239. <span v-if="!$v.username.minLength">
  240. User name will be greater than or equal 3 characters
  241. </span>
  242. <span v-if="!$v.username.maxLength">
  243. User name will be less than or equal 20 characters
  244. </span>
  245. <span v-if="!$v.username.alphaNum">
  246. Only alphabatic and number is allowed
  247. </span>
  248. </div>
  249. <div v-else>
  250. <div v-if="usernameStatus === 'checking'" class="text-info"> checking <i class="fa fa-spinner fa-spin"></i></div>
  251. <div v-else-if="usernameStatus === 'error'" class="text-danger">
  252. <span><i class="fa fa-warning"></i></span>
  253. Username already exists</div>
  254.  
  255. <div v-else-if="username == ''"></div>
  256. <div v-else><i class="fa fa-check text-success"></i></div>
  257.  
  258. </div>
  259. </div>
  260. </div>
  261.  
  262. <div class="form-group row">
  263. <label for="email" class="col-sm-3 col-form-label">Your Email address
  264. <span class="required-icon">*</span>
  265. </label>
  266. <div class="col-sm-6">
  267. <input type="text"
  268. v-model.trim="$v.email.$model"
  269. class="form-control"
  270. :class="{' is-invalid': $v.email.$error || emailStatus === 'error'}"
  271. id="email"
  272. name="email"
  273. placeholder="Write Your Email address">
  274. </div>
  275. <div class="col-sm-3">
  276. <div v-if="$v.email.$error" class="text-danger">
  277. <span><i class="fa fa-warning"></i></span>
  278. <span v-if="!$v.email.required"> Please give your email address</span>
  279.  
  280. <span v-if="!$v.email.email">
  281. Please give a valid email address
  282. </span>
  283. </div>
  284. <div v-else>
  285. <div v-if="emailStatus === 'checking'" class="text-info"> checking <i class="fa fa-spinner fa-spin"></i></div>
  286. <div v-else-if="emailStatus === 'error'" class="text-danger">
  287. <span><i class="fa fa-warning"></i></span>
  288. email already exists</div>
  289. <div v-else-if="email == ''"></div>
  290. <div v-else><i class="fa fa-check text-success"></i></div>
  291. </div>
  292. </div>
  293. </div>
  294.  
  295. <div class="form-group row">
  296. <label for="phone_no" class="col-sm-3 col-form-label">Your Phone No
  297. <span class="required-icon">*</span>
  298. </label>
  299. <div class="col-sm-6">
  300. <input type="text"
  301. v-model.trim="$v.phone_no.$model"
  302. class="form-control"
  303. :class="{' is-invalid': $v.phone_no.$error || phoneStatus === 'error'}"
  304. id="phone_no"
  305. name="phone_no"
  306. placeholder="Write Your phone no">
  307. </div>
  308. <div class="col-sm-3">
  309. <div v-if="$v.phone_no.$error" class="text-danger">
  310. <span><i class="fa fa-warning"></i></span>
  311. <span v-if="!$v.phone_no.required"> Please give your phone no</span>
  312.  
  313. <span v-if="!$v.phone_no.maxLength">
  314. Please give a phone number between 14 characters
  315. </span>
  316. </div>
  317. <div v-else>
  318. <div v-if="phoneStatus === 'checking'" class="text-info"> checking <i class="fa fa-spinner fa-spin"></i></div>
  319. <div v-else-if="phoneStatus === 'error'" class="text-danger">
  320. <span><i class="fa fa-warning"></i></span>
  321. Phone no already exists</div>
  322. <div v-else-if="phone_no == ''"></div>
  323. <div v-else><i class="fa fa-check text-success"></i></div>
  324. </div>
  325. </div>
  326. </div>
  327.  
  328. <div class="form-group row">
  329. <label for="address" class="col-sm-3 col-form-label">Your Address
  330. </label>
  331. <div class="col-sm-6">
  332. <input type="text"
  333. v-model.trim="$v.address.$model"
  334. class="form-control"
  335. :class="{' is-invalid': $v.address.$error}"
  336. id="address"
  337. name="address"
  338. placeholder="Write Your Address">
  339. </div>
  340. <div class="col-sm-3">
  341. <div v-if="$v.address.$error" class="text-danger">
  342. <span><i class="fa fa-warning"></i></span>
  343.  
  344. <span v-if="!$v.address.maxLength">
  345. Please give your address between 100 characters
  346. </span>
  347. </div>
  348. <div v-else-if="address == ''"></div>
  349. <div v-else>
  350. <i class="fa fa-check text-success"></i>
  351. </div>
  352. </div>
  353. </div>
  354.  
  355.  
  356. <div class="form-group row">
  357. <label for="address" class="col-sm-3 col-form-label">Register as
  358. </label>
  359. <div class="col-sm-6">
  360. <select type="text"
  361. v-model.trim="$v.role.$model"
  362. class="form-control"
  363. :class="{' is-invalid': $v.role.$error}"
  364. id="role"
  365. name="role"
  366. placeholder="Choose your account type">
  367. <option value="">Choose your account type</option>
  368. <option value="0">User</option>
  369. <option value="1">Developer</option>
  370. <option value="2">Trainer</option>
  371. <option value="3">Trainee</option>
  372. <option value="4">Client</option>
  373. </select>
  374. </div>
  375. <div class="col-sm-3">
  376.  
  377. <div v-if="$v.role.$error" class="text-danger">
  378. <span><i class="fa fa-warning"></i></span>
  379.  
  380. <span v-if="!$v.role.required">
  381. Please choose your role
  382. </span>
  383. </div>
  384.  
  385. <div v-else-if="role == ''"></div>
  386. <div v-else>
  387. <i class="fa fa-check text-success"></i>
  388. </div>
  389. </div>
  390. </div>
  391.  
  392.  
  393. <hr>
  394.  
  395. <div class="form-group row">
  396. <label for="password" class="col-sm-3 col-form-label">Password
  397. <span class="text-info">(optional)</span>
  398. </label>
  399. <div class="col-sm-6">
  400. <input type="password"
  401. v-model.trim="$v.password.$model"
  402. class="form-control"
  403. :class="{' is-invalid': $v.password.$error}"
  404. id="password"
  405. name="password"
  406. placeholder="Write Your password">
  407. </div>
  408. <div class="col-sm-3">
  409. <div v-if="$v.password.$error" class="text-danger">
  410. <span><i class="fa fa-warning"></i></span>
  411.  
  412. <span v-if="!$v.password.minLength">
  413. Please give a password more than 6 characters characters
  414. </span>
  415. </div>
  416. <div v-else-if="password == ''"></div>
  417. <div v-else>
  418. <i class="fa fa-check text-success"></i>
  419. </div>
  420. </div>
  421. </div>
  422. <div class="form-group row">
  423. <label for="confirm_password" class="col-sm-3 col-form-label">Confirm password
  424. <span class="text-info">(optional)</span>
  425. </label>
  426. <div class="col-sm-6">
  427. <input type="password"
  428. v-model.trim="$v.confirm_password.$model"
  429. class="form-control"
  430. :class="{' is-invalid': $v.confirm_password.$error}"
  431. id="confirm_password"
  432. name="confirm_password"
  433. placeholder="Confirm password">
  434. </div>
  435. <div class="col-sm-3">
  436. <div v-if="$v.confirm_password.$error" class="text-danger">
  437. <span><i class="fa fa-warning"></i></span>
  438.  
  439. <span v-if="!$v.confirm_password.minLength">
  440. Please confirm password will be more than 6 characters characters
  441. </span>
  442. <span v-if="!$v.confirm_password.sameAs">
  443. Password combination doesn't match
  444. </span>
  445. </div>
  446. <div v-else-if="confirm_password == ''"></div>
  447. <div v-else>
  448. <i class="fa fa-check text-success"></i>
  449. </div>
  450. </div>
  451. </div>
  452.  
  453.  
  454.  
  455. <div class="form-group row">
  456. <div class="col-sm-10">
  457. <button v-if="submitStatus == 'PENDING'" class="btn btn-info"> Signing Up... <i class="fa fa-spinner fa-spin"></i></button>
  458. <button v-else type="submit" class="btn btn-primary"> <i class="fa fa-check"></i> Sign Up</button>
  459. </div>
  460.  
  461. </div>
  462. </form>
  463. </div>
  464.  
  465. </div>
  466. </template>
  467.  
  468. <script>
  469.  
  470. import { required, minLength, maxLength, alphaNum, email, url, numeric, sameAs } from 'vuelidate/lib/validators';
  471. export default {
  472. props: {
  473. url: {
  474. type: String,
  475. required: true
  476. },
  477.  
  478. },
  479. mounted(){
  480.  
  481. },
  482.  
  483. data: function() {
  484. return {
  485.  
  486. first_name : '',
  487. last_name : '',
  488. email : '',
  489. username : '',
  490. phone_no : '',
  491. address : '',
  492. role: '',
  493. password : '',
  494. confirm_password : '',
  495.  
  496. submitStatus: null,
  497. usernameStatus: '',
  498. emailStatus: '',
  499. phoneStatus: '',
  500. serverErrors: []
  501. }
  502. },
  503.  
  504. validations:
  505. {
  506. first_name: {
  507. required,
  508. minLength: minLength(3),
  509. maxLength: maxLength(20),
  510. },
  511. last_name: {
  512. minLength: minLength(3),
  513. maxLength: maxLength(15),
  514. },
  515. username: {
  516. required,
  517. minLength: minLength(3),
  518. maxLength: maxLength(30),
  519. alphaNum
  520. },
  521. email: {
  522. required,
  523. email
  524. },
  525. phone_no: {
  526. required,
  527. maxLength: maxLength(14)
  528. },
  529. address: {
  530. maxLength: maxLength(100)
  531. },
  532. role: {
  533. required
  534. },
  535. password: {
  536. minLength: minLength(6)
  537. },
  538. confirm_password: {
  539. minLength: minLength(6),
  540. sameAsPassword: sameAs('password')
  541. },
  542.  
  543.  
  544. },
  545.  
  546. methods: {
  547.  
  548. submitForm() {
  549. let vm = this;
  550. vm.$v.$touch()
  551. if (vm.$v.$invalid) {
  552. vm.submitStatus = 'ERROR';
  553. } else {
  554. // do your submit logic here
  555. vm.submitStatus = 'PENDING';
  556.  
  557. // Now submit data to server
  558.  
  559. axios.post(vm.url + '/api/developers/register', {
  560. developer: vm.developer,
  561.  
  562. // Pass developer data's
  563. first_name: vm.first_name,
  564. last_name: vm.last_name,
  565. email: vm.email,
  566. phone_no: vm.phone_no,
  567. username: vm.username,
  568. address: vm.address,
  569. role: vm.role,
  570. password: vm.password,
  571. confirm_password: vm.confirm_password
  572.  
  573. }).then(function (response){
  574. console.log(response)
  575.  
  576. if (response.data.status) {
  577.  
  578. vm.submitStatus = 'OK';
  579. console.log(response.data);
  580.  
  581. }else {
  582. vm.submitStatus = 'ERROR';
  583. vm.serverErrors = error.response.data.errors;
  584. console.log(vm.serverErrors);
  585.  
  586. }
  587. }).catch(function (error){
  588. // vm.serverErrors = response.data.errors;
  589. vm.submitStatus = 'ERROR';
  590. vm.serverErrors = error.response.data.errors;
  591. console.log(vm.serverErrors);
  592.  
  593.  
  594. });
  595.  
  596. }
  597.  
  598. },
  599.  
  600. },
  601.  
  602. watch: {
  603.  
  604. email: _.debounce(function() {
  605.  
  606. let vm = this;
  607. vm.emailStatus = 'checking';
  608. // Send it to server and check
  609. if (vm.email) {
  610. axios.get(vm.url + '/api/developers/email-check', {
  611. params: {
  612. email: vm.email
  613. }
  614. }).then(function (response){
  615. // If unique, set the slug else refactor it and make unique
  616. if (response.data) {
  617. // It's unique
  618. vm.emailStatus = 'ok';
  619. }else {
  620. // It's not unique
  621. vm.emailStatus = 'error';
  622. }
  623. }).catch(function (error){
  624. console.log(error);
  625. });
  626. }
  627. }, 100),
  628.  
  629.  
  630. username: _.debounce(function() {
  631.  
  632. let vm = this;
  633. vm.usernameStatus = 'checking';
  634. // Send it to server and check
  635. axios.get(vm.url + '/api/developers/username-check', {
  636. params: {
  637. username: vm.username
  638. }
  639. }).then(function (response){
  640. // If unique, set the slug else refactor it and make unique
  641. if (response.data) {
  642. // It's unique
  643. vm.usernameStatus = 'ok';
  644. }else {
  645. // It's not unique
  646. vm.usernameStatus = 'error';
  647. }
  648. }).catch(function (error){
  649. console.log(error);
  650. });
  651. }, 100),
  652.  
  653.  
  654. phone_no: _.debounce(function() {
  655.  
  656. let vm = this;
  657. vm.phoneStatus = 'checking';
  658. // Send it to server and check
  659. if (vm.phone_no) {
  660. axios.get(vm.url + '/api/developers/phone-check', {
  661. params: {
  662. phone_no: vm.phone_no
  663. }
  664. }).then(function (response){
  665. // If unique, set the slug else refactor it and make unique
  666. if (response.data) {
  667. // It's unique
  668. vm.phoneStatus = 'ok';
  669. }else {
  670. // It's not unique
  671. vm.phoneStatus = 'error';
  672. }
  673. }).catch(function (error){
  674. console.log(error);
  675. });
  676. }
  677. }, 100),
  678.  
  679. submit_status: _.debounce(function() {
  680.  
  681. if (submit_status == "OK") {
  682. this.first_name = '',
  683. this.last_name = '',
  684. this.email = '',
  685. this.username = '',
  686. this.phone_no = '',
  687. this.address = '',
  688. this.role = '',
  689. this.password = '',
  690. this.confirm_password = '',
  691. this.usernameStatus = '',
  692. this.emailStatus = '',
  693. this.phoneStatus = '',
  694. this.serverErrors = []
  695. }
  696. }, 100),
  697.  
  698. }
  699.  
  700. }
  701.  
  702. </script>
  703.  
  704.  
  705. /*********** ProfilePictureChange.vue **********/
  706. <style scoped>
  707. img{
  708. max-width: 150px;
  709. border: 1px solid;
  710. margin: 5px;
  711. }
  712. input.form-control {
  713. background: #b8c3c9;
  714. padding: 3px;
  715. border: 0px;
  716. }
  717. </style>
  718.  
  719. <template>
  720. <div class="profile-picture-change-widget mt-2">
  721. <div>
  722.  
  723. <input type="file" @change="onImageChange" class="form-control" size="60">
  724. <br>
  725. <div v-if="image_loaded">
  726. <img :src="image">
  727. </div>
  728. <br>
  729.  
  730. <button class="btn btn-success mt-2" @click.prevent="updateProfilePicture" v-if="image_loaded && !is_uploading && !is_uploaded">
  731. <i class="fa fa-check"></i> Update Profile Picture
  732. </button>
  733. <button class="btn btn-success mt-2" v-if="is_uploading">
  734. <i class="fa fa-check"></i> Uploading ...
  735. </button>
  736. <button class="btn btn-info mt-2" v-if="is_uploaded">
  737. <i class="fa fa-check"></i> Uploaded Successfully
  738. </button>
  739. </div>
  740. </div>
  741. </template>
  742.  
  743. <script>
  744. export default {
  745. props: {
  746. url: {
  747. type: String,
  748. required: true
  749. },
  750. api_token: {
  751. type: String
  752. }
  753. },
  754. mounted(){
  755.  
  756. },
  757.  
  758. data: function() {
  759. return {
  760. image: '',
  761. image_loaded: false,
  762. is_uploading: false,
  763. is_uploaded: false
  764. }
  765. },
  766. methods: {
  767. onImageChange(e) {
  768. var files = e.target.files || e.dataTransfer.files;
  769. this.createImage(files[0]); // Files the image / file value
  770. },
  771. createImage(file) {
  772. // Preview Image before upload
  773. var image = new Image;
  774. var reader = new FileReader();
  775. reader.onload = (e) => {
  776. this.image = e.target.result;
  777. };
  778. reader.readAsDataURL(file);
  779. this.image_loaded = true;
  780. },
  781. updateProfilePicture() {
  782. let vm = this;
  783. // Upload image to database
  784. vm.is_uploading = true;
  785.  
  786. if (vm.api_token && vm.image) {
  787. axios.post(vm.url + '/api/developers/profile-picture-change', {
  788. api_token: vm.api_token,
  789. image: vm.image
  790. }).then(function (response){
  791. if (response.data) {
  792. console.log(response.data);
  793. vm.is_uploading = false;
  794. vm.is_uploaded = true;
  795. }else {
  796. console.log(response.data);
  797. }
  798. }).catch(function (error){
  799. console.log(error);
  800. });
  801. }
  802. },
  803. cancelImage() {
  804. this.image = ""
  805. }
  806. },
  807.  
  808. watch: {
  809. is_uploaded: _.debounce(function() {
  810.  
  811. if (this.is_uploaded === true) {
  812. window.location.href = this.url + '/developer';
  813. }
  814.  
  815. }, 500),
  816. }
  817.  
  818. }
  819. </script>
  820.  
  821.  
  822. /************ Comment Box ************/
  823. <template>
  824. <div class="mt-5 wow fadeInUp">
  825. <h4 class="mb-3">Leave a Comment</h4>
  826. <div class="row">
  827. <div class="col-md-10">
  828. <div class="form-group">
  829. <textarea class="form-control mb-10" rows="1" id="message" v-model="message" placeholder="Comment" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Comment'" required></textarea>
  830. </div>
  831. </div>
  832. <div class="col-md-2">
  833. <button @click="saveComment" class="btn btn-primary text-uppercase">Post</button>
  834. </div>
  835. </div>
  836. </div>
  837. </template>
  838.  
  839. <script>
  840. export default {
  841. props: {
  842. id: {
  843. type: String,
  844. required: true
  845. },
  846. user_id: {
  847. type: Number
  848. },
  849. developer_id: {
  850. type: String
  851. },
  852. url: {
  853. type: String,
  854. required: true
  855. }
  856. },
  857. data() {
  858. return {
  859. message: ''
  860. }
  861. },
  862. methods: {
  863. saveComment(){
  864. axios.post(this.url+'/tutorial/comment/add', {
  865. message: this.message,
  866. tutorial_id: this.id,
  867. developer_id: this.developer_id
  868. })
  869. .then((response) => {
  870. this.message = '';
  871. this.$emit('newComment', response.data);
  872. })
  873. .catch((e) => {
  874. console.log(e);
  875. })
  876. }
  877. },
  878. mounted() {
  879. var vm = this;
  880. tinymce.init({
  881. selector:'#message' ,
  882. plugins: 'codesample code print preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern',
  883. toolbar: 'codesample bold italic | autolink | link | preview code',
  884. image_advtab: true,
  885. menubar:false,
  886. setup: function(editor){
  887. editor.on('keyup', function(e){
  888. console.log('enter');
  889. vm.model = editor.getContent();
  890. vm.message = editor.getContent();
  891. })
  892. }
  893. });
  894. }
  895. }
  896. </script>
  897.  
  898.  
  899. /********* Comment.js ***********/
  900. <template>
  901. <div class="comment">
  902. <div class="comments-area">
  903. <h4 class="wow fadeIn">{{ length }} Comments</h4>
  904. <div class="comment-list" v-for="comment in comments" v-if="!comment.replier_comment_id">
  905. <div class="single-comment justify-content-between d-flex">
  906. <div class="user justify-content-between d-flex wow slideInLeft">
  907. <div class="thumb">
  908. <img :src="url+'/public/website-images/developers/'+comment.developer.image" alt="" width="30" height="30">
  909. </div>
  910. <div class="desc">
  911. <h5><a href="#">{{ comment.developer.first_name }} {{ comment.developer.last_name }}</a></h5>
  912. <p class="date">{{ comment.created_at }}</p>
  913. <div class="comment" v-html="comment.comment"></div>
  914. </div>
  915. </div>
  916. <CommentReply :comment="comment" :comments="comments" @replies="tutorialReplies"></CommentReply>
  917. </div>
  918. <div class="replies">
  919. <div class="comment-list left-padding">
  920. <div class="single-comment justify-content-between d-flex" v-for="thisReply in thisReplies" v-if="thisReply.replier_comment_id == comment.id">
  921. <div class="user justify-content-between d-flex">
  922. <div class="thumb">
  923. <img src="img/blog/c2.jpg" alt="">
  924. </div>
  925. <div class="desc">
  926. <h5><a href="#">{{ thisReply.developer.first_name }} {{ thisReply.developer.last_name }}</a></h5>
  927. <p class="date">{{ thisReply.created_at }} </p>
  928. <p class="comment">
  929. {{ thisReply.comment }}
  930. </p>
  931. </div>
  932. </div>
  933. </div>
  934. <div v-if="replyBox">
  935. <div v-if="comment.id == comment_id_for_reply">
  936. <div v-if="user">
  937. <ReplyBox :tutorial_id="id" :comment="comment" :developer_id="developer_id" :url="url" @newReply="pushNewReply"></ReplyBox>
  938. </div>
  939. <div v-else>
  940. <div class="alert alert-danger" role="alert">
  941. Please Sign in for comment
  942. </div>
  943. </div>
  944. </div>
  945. </div>
  946. </div>
  947. </div>
  948. </div>
  949. </div>
  950. <div v-if="user">
  951. <CommentBox :id="id" :user_id="user.id" :developer_id="developer_id" :url="url" @newComment="pushNewComment"></CommentBox>
  952. </div>
  953. <div v-else>
  954. <div class="alert">
  955. <div class="alert alert-danger" role="alert">
  956. Please Sign in for comment
  957. </div>
  958. </div>
  959. </div>
  960. </div>
  961. </template>
  962.  
  963. <script>
  964. import CommentBox from "./CommentBox.vue";
  965. import CommentReply from "./CommentReply.vue";
  966. import ReplyBox from "./ReplyBox.vue";
  967.  
  968. export default {
  969. props: {
  970. id: {
  971. type: String,
  972. required: true
  973. },
  974. user: {
  975. type: Object
  976. },
  977. developer_id: {
  978. type: String
  979. },
  980. url: {
  981. type: String,
  982. required: true
  983. }
  984. },
  985. data(){
  986. return {
  987. comments: [],
  988. thisReplies: [],
  989. replyBox: false,
  990. comment_id_for_reply: '',
  991. length: ''
  992. }
  993. },
  994. methods: {
  995. pushNewComment(newComment){
  996. this.comments.push(newComment);
  997. this.length++;
  998. },
  999. tutorialReplies(replies, comment_id){
  1000. this.comment_id_for_reply = comment_id;
  1001. this.replyBox = true;
  1002. this.thisReplies = [];
  1003. if(replies.length > 0){
  1004. this.thisReplies = replies;
  1005. }
  1006. },
  1007. pushNewReply(reply){
  1008. this.thisReplies.push(reply);
  1009. this.length++;
  1010. }
  1011. },
  1012. mounted() {
  1013. axios.get(this.url+'/tutorial/comments/'+this.id)
  1014. .then((response) => {
  1015. this.comments = response.data;
  1016. this.length = this.comments.length;
  1017. })
  1018. .catch((e) => {
  1019. console.log(e);
  1020. })
  1021. },
  1022. computed: {
  1023.  
  1024. },
  1025. components: {
  1026. CommentBox,
  1027. CommentReply,
  1028. ReplyBox
  1029. }
  1030. }
  1031. </script>
  1032.  
  1033.  
  1034. /*********** Comment Reply *********/
  1035. <template>
  1036. <div class="reply-btn wow slideInRight">
  1037. <button class="btn btn-primary btn-sm" @click="allReply">{{ commentReply(comment.id) }} Reply</button>
  1038. </div>
  1039. </template>
  1040.  
  1041. <script>
  1042. export default {
  1043. props: {
  1044. comment: {
  1045. type: Object,
  1046. required: true
  1047. },
  1048. comments: {
  1049. type: Array,
  1050. required: true
  1051. }
  1052. },
  1053. data(){
  1054. return {
  1055. replies: [],
  1056. totalReply: 0
  1057. }
  1058. },
  1059. methods: {
  1060. allReply(){
  1061. var app = this;
  1062. app.replies = [];
  1063. app.comments.forEach(function(c) {
  1064. if(c.replier_comment_id === app.comment.id){
  1065. app.replies.push(c);
  1066. }
  1067. });
  1068. app.$emit('replies', app.replies, app.comment.id);
  1069. },
  1070. commentReply(id){
  1071. var app = this;
  1072. var total = 0;
  1073. app.comments.forEach(function(c) {
  1074. if(c.replier_comment_id === id){
  1075. total++;
  1076. }
  1077. });
  1078.  
  1079. return app.totalReply = total;
  1080. }
  1081. },
  1082. mounted() {
  1083.  
  1084. }
  1085. }
  1086. </script>
  1087.  
  1088.  
  1089. /********* Reply Box *********/
  1090. <template>
  1091. <div class="row">
  1092. <div class="col-md-10">
  1093. <div class="form-group">
  1094. <textarea class="form-control mb-10" rows="1" id="reply_comment" @keydown.enter="saveReply" v-model="reply_comment" placeholder="Reply" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Comment'" required></textarea>
  1095. </div>
  1096. </div>
  1097. <div class="col-md-2">
  1098. <button class="btn btn-primary" @click="saveReply">Post</button>
  1099. </div>
  1100. </div>
  1101. </template>
  1102.  
  1103. <script>
  1104. export default {
  1105. props: {
  1106. comment: {
  1107. type: Object,
  1108. required: true
  1109. },
  1110. tutorial_id: {
  1111. type: String,
  1112. required: true
  1113. },
  1114. developer_id: {
  1115. type: String
  1116. },
  1117. url: {
  1118. type: String,
  1119. required: true
  1120. }
  1121. },
  1122. data() {
  1123. return {
  1124. reply_comment: ''
  1125. }
  1126. },
  1127. methods: {
  1128. saveReply(){
  1129. axios.post(this.url+'/tutorial/comment/reply', {
  1130. reply_comment: this.reply_comment,
  1131. replier_comment_id: this.comment.id,
  1132. tutorial_id: this.tutorial_id,
  1133. developer_id: this.developer_id
  1134. })
  1135. .then((response) => {
  1136. this.reply_comment = '';
  1137. this.$emit('newReply', response.data);
  1138. })
  1139. .catch((e) => {
  1140. console.log(e);
  1141. })
  1142. }
  1143. },
  1144. mounted() {
  1145.  
  1146. }
  1147. }
  1148. </script>
  1149.  
  1150.  
  1151. /***** Draggable Tutorial ******/
  1152. <style scoped>
  1153. .playlist-tutorials{
  1154. cursor: pointer;
  1155. }
  1156. .handleDrag{
  1157. cursor: move;
  1158. }
  1159. #order-change-message{
  1160. color: #e04006!important;
  1161. letter-spacing: 1px;
  1162. padding: 5px;
  1163. padding-left: 10px;
  1164. background: aquamarine;
  1165. }
  1166. </style>
  1167.  
  1168. <template>
  1169. <div class="playlist-tutorials-widget mt-2">
  1170. <div v-if="!is_loaded" class="text-center">
  1171. <p class="">Loading Tutorials ...</p>
  1172. <p class=""><i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
  1173. <span class="sr-only">Loading...</span> </p>
  1174. </div>
  1175. <div v-else>
  1176. <p v-if="is_order_changed" id="order-change-message"><i class="fa fa-check"></i> Tutorials Order has changed</p>
  1177. <draggable :list="posts" :options="{animation:200, handle: '.handleDrag'}" element="div" class="playlist-tutorials" @change="updateOrder">
  1178.  
  1179. <div class="card card-body p-2 m-2" v-for="(post, index) in posts">
  1180. <div class="row">
  1181. <div class="col-sm-2">
  1182.  
  1183. <div v-if="post.featured_image">
  1184. {{ index+1 }}) <img :src="url+'/public/website-images/posts/'+post.featured_image" width="25px">
  1185. </div>
  1186. <div v-else>
  1187. {{ index+1 }}) <i class="fa fa-check bold"></i>
  1188. </div>
  1189.  
  1190. </div>
  1191. <div class="col-sm-6">
  1192. {{ post.title }}
  1193. </div>
  1194. <!-- <div class="col-sm-2">
  1195. {{ post.priority }}
  1196. </div> -->
  1197. <div class="col-sm-2 handleDrag">
  1198. <i class="fa fa-arrows"></i>
  1199. </div>
  1200. </div>
  1201. </div> <!-- Single Post -->
  1202.  
  1203.  
  1204. </draggable :list="posts">
  1205. </div>
  1206. </div>
  1207. </template>
  1208.  
  1209. <script>
  1210. import draggable from 'vuedraggable';
  1211. export default {
  1212. components: {
  1213. draggable
  1214. },
  1215. props: {
  1216. url: {
  1217. type: String,
  1218. required: true
  1219. },
  1220. playlist_slug: {
  1221. type: String,
  1222. required: true
  1223. },
  1224. api_token: {
  1225. type: String,
  1226. required: true
  1227. }
  1228. },
  1229.  
  1230. data: function() {
  1231. return {
  1232. is_loaded: false,
  1233. posts: [],
  1234. is_order_changed: false
  1235. }
  1236. },
  1237.  
  1238. mounted(){
  1239. let vm = this;
  1240. vm.is_loaded = false;
  1241. if (vm.api_token && vm.playlist_slug) {
  1242. axios.get(vm.url + '/api/playlists/get-tutorials/', {
  1243. params: {
  1244. api_token: vm.api_token,
  1245. slug: vm.playlist_slug
  1246. }
  1247. }).then(function (response){
  1248. if (response.data) {
  1249. vm.posts = response.data.posts;
  1250. vm.is_loaded = true;
  1251. }else {
  1252. // vm.is_loaded = true;
  1253. }
  1254. }).catch(function (error){
  1255. console.log(error);
  1256. });
  1257.  
  1258.  
  1259. }
  1260. },
  1261.  
  1262. methods: {
  1263. updateOrder(){
  1264. console.log('Updating order...');
  1265.  
  1266. let vm = this;
  1267. vm.posts.map((post, index) => {
  1268. post.priority = index + 1;
  1269. });
  1270.  
  1271. // Send it to server and update it as a permanent
  1272.  
  1273. if (vm.api_token && vm.playlist_slug) {
  1274. axios.post(vm.url + '/api/playlists/update-tutorials-order', {
  1275. api_token: vm.api_token,
  1276. slug: vm.playlist_slug,
  1277. posts: this.posts
  1278. }).then(function (response){
  1279. if (response.data) {
  1280. // console.log(response.data.status);
  1281. vm.is_order_changed = true;
  1282. }else {
  1283. // vm.is_loaded = true;
  1284. }
  1285. }).catch(function (error){
  1286. console.log(error);
  1287. });
  1288. }
  1289.  
  1290. }
  1291. },
  1292. watch: {
  1293. is_order_changed: _.debounce(function() {
  1294. if (this.is_order_changed) this.is_order_changed = false;
  1295. }, 3000)
  1296. }
  1297. }
  1298. </script>
  1299.  
  1300.  
  1301. /****** PlaylistSlugChecker ****/
  1302. <style scoped>
  1303.  
  1304. </style>
  1305.  
  1306. <template>
  1307. <div class="slug-widget mt-2">
  1308. <i class="fa fa-link"></i>
  1309. {{ url }}/{{ username }}/playlists/
  1310. <input type="text" name="slug" v-model="slug" @keyup="checkPlaylistSlug">
  1311.  
  1312. <span class="slugStatus text-success" v-if="slug_status">
  1313. <i class="fa fa-check"></i> Available
  1314. </span>
  1315. <span class="slugStatus text-center text-danger" v-else>
  1316. <i class="fa fa-close"></i> Not Available
  1317. <br />
  1318. <span v-if="slug_message" v-html="slug_message"></span>
  1319. </span>
  1320. </div>
  1321. </template>
  1322.  
  1323. <script>
  1324. export default {
  1325. props: {
  1326. url: {
  1327. type: String,
  1328. required: true
  1329. },
  1330. username: {
  1331. type: String,
  1332. required: true
  1333. },
  1334. old_slug: {
  1335. type: String,
  1336. required: true
  1337. },
  1338. api_token: {
  1339. type: String,
  1340. required: true
  1341. }
  1342. },
  1343. mounted(){
  1344.  
  1345. },
  1346.  
  1347. data: function() {
  1348. return {
  1349. slug: this.old_slug,
  1350. slug_status: true,
  1351. slug_message: ''
  1352. }
  1353. },
  1354. methods: {
  1355. checkPlaylistSlug(){
  1356. // Get the slug
  1357. let slug = this.slug;
  1358.  
  1359. // Send the slug to the server and get response
  1360. let vm = this;
  1361.  
  1362. if (vm.api_token && slug) {
  1363. // Test to see if the URL is unique or not
  1364. axios.get(vm.url+'/api/playlists/check-unique/', {
  1365. params: {
  1366. api_token: vm.api_token,
  1367. slug: slug
  1368. }
  1369. }).then(function (response){
  1370. // If unique, set the slug else refactor it and make unique
  1371. console.log(response.data)
  1372. if (response.data.slug_available == 1) {
  1373. // It's unique
  1374. vm.slug_status = true;
  1375. vm.slug_message = response.data.message;
  1376. }else {
  1377. // It's not unique and customize the slug
  1378. if (vm.slug == vm.old_slug) {
  1379. vm.slug_status = true;
  1380. vm.slug_message = '';
  1381. }else {
  1382. vm.slug_status = false;
  1383. vm.slug_message = response.data.message;
  1384. }
  1385.  
  1386.  
  1387. }
  1388. }).catch(function (error){
  1389. console.log(error);
  1390. });
  1391. }
  1392.  
  1393. }
  1394.  
  1395. },
  1396. watch: {
  1397.  
  1398. }
  1399. }
  1400. </script>
  1401.  
  1402.  
  1403. /****** Search Tutorial **********/
  1404. <style scoped>
  1405. .tutorial-search-bar{
  1406. max-height: 250px;
  1407. position: absolute;
  1408. overflow-y: auto;
  1409. margin-top: 42px;
  1410. width: 272px;
  1411. background: #f9f1f3;
  1412. padding-bottom: 10px;
  1413. margin-bottom: 10px;
  1414. margin-left: 0px;
  1415. box-shadow: 2px 5px 34px -5px #34354a;
  1416. }
  1417. </style>
  1418.  
  1419. <template>
  1420. <div class="search-tutorial-widget mt-2">
  1421. <input placeholder="Search Tutorials" name="search" type="text" @focus="searchTutorial" v-model="searchText" id="searchTutorialInput" v-on:keyup="searchTutorial()">
  1422. <button type="submit"><i class="fa fa-search"></i></button>
  1423.  
  1424. <div class="tutorial-search-bar" v-if="searchStarted">
  1425. <div v-if="loading" class="text-center">
  1426. <i class="fa fa-circle-o-notch fa-spin fa-2x fa-fw""></i>
  1427. </div>
  1428. <p class="dropdown-item pointer" v-for="tutorial in tutorials" @click="goTutorial(tutorial.slug)" >
  1429. {{ tutorial.title }}
  1430. </p>
  1431. <div v-if="tutorials.length == 0">
  1432. <p class="text-danger m-2"> No tutorials found by your search...</p>
  1433. </div>
  1434. </div>
  1435.  
  1436. </div>
  1437. </template>
  1438.  
  1439. <script>
  1440. export default {
  1441. props: {
  1442. url: {
  1443. type: String,
  1444. required: true
  1445. }
  1446. },
  1447. data: function() {
  1448. return {
  1449. searchText: '',
  1450. searchStarted: false,
  1451. loading: true,
  1452. tutorials: []
  1453. }
  1454. },
  1455. methods: {
  1456. searchTutorial: function(){
  1457. if (this.searchText.length > 0) {
  1458. this.loading = true;
  1459. this.searchStarted = true;
  1460. $('.tutorial-search-bar').show('slow');
  1461. }else{
  1462. this.searchStarted = false
  1463. $('.tutorial-search-bar').hide('slow');
  1464. }
  1465.  
  1466. // Send it to the server and get the related tutorials
  1467. var vm = this;
  1468. if (vm.searchStarted) {
  1469. axios.get(vm.url+ '/api/tutorials/search/'+vm.searchText)
  1470. .then(response => {
  1471. vm.tutorials = response.data;
  1472. vm.loading = false;
  1473. }).catch(function (error){
  1474. })
  1475. }
  1476. },
  1477. focusOut: function(){
  1478. this.searchStarted = false;
  1479. },
  1480. goTutorial: function(val){
  1481. window.location.href = this.url + "/tutorials/search/" + val;
  1482. }
  1483. },
  1484.  
  1485. }
  1486.  
  1487. </script>
  1488.  
  1489.  
  1490. /******* SlugWidget.vue *************/
  1491. <style scoped>
  1492. .slug-widget{
  1493. display: flex;
  1494. justify-content: flex-start;
  1495. align-items: center;
  1496. }
  1497.  
  1498. .wrapper{
  1499. margin-left: 8px;
  1500. }
  1501. .url-wrapper{
  1502. height: 30px;
  1503. display: flex;
  1504. align-items: center;
  1505. }
  1506.  
  1507. .slug{
  1508. background-color: #fcffcd;
  1509. /*padding: 3px;*/
  1510. }
  1511. .input{
  1512. width: auto;
  1513. }
  1514.  
  1515. </style>
  1516.  
  1517. <template>
  1518. <div class="slug-widget mt-2">
  1519. <div class="icon-wrapper wrapper">
  1520. <i class="fa fa-link"></i>
  1521. </div>
  1522. <div class="url-wrapper wrapper">
  1523. <span class="root-url">{{ url }}</span>
  1524. <span class="subdirectory-url">/{{ subdirectory }}/</span>
  1525. <span class="slug" v-show="slug && !isEditing">{{ slug }}</span>
  1526. <input type="text" name="slug-edit" class="input small" @existing-slug="existingSlug" v-show="isEditing" v-model="customSlug">
  1527. </div>
  1528. <div class="slug-checker">
  1529. <p></p>
  1530. </div>
  1531. <div class="button-wrapper wrapper">
  1532. <button type="button" class="btn btn-sm btn-default" v-show="!isEditing" @click.prevent="editSlug">Edit</button>
  1533. <button type="button" class="btn btn-sm btn-default" v-show="isEditing" @click.prevent="saveSlug">Save</button>
  1534. <button type="button" class="btn btn-sm btn-default" v-show="isEditing" @click.prevent="resetSlug">Reset</button>
  1535. </div>
  1536. </div>
  1537. </template>
  1538.  
  1539. <script>
  1540. export default {
  1541. props: {
  1542. url: {
  1543. type: String,
  1544. required: true
  1545. },
  1546. subdirectory: {
  1547. type: String,
  1548. required: true
  1549. },
  1550. title: {
  1551. type: String,
  1552. required: true
  1553. },
  1554. prevSlug: {
  1555. type: String,
  1556. default: ''
  1557. }
  1558. },
  1559. mounted(){
  1560. // if(this.prevSlug != NULL)
  1561. // {
  1562. // this.slug = this.prevSlug;
  1563. // }
  1564. console.log(this.prevSlug)
  1565. if(this.prevSlug){
  1566. this.customSlug = this.prevSlug;
  1567. }else {
  1568. this.customSlug = this.slug;
  1569. this.setSlug(this.title)
  1570. }
  1571.  
  1572. },
  1573.  
  1574. data: function() {
  1575. return {
  1576. slug: this.setSlug(this.title),
  1577. customSlug: '',
  1578. isEditing: false,
  1579. wasEdited: false,
  1580. api_token: this.$root.api_token
  1581. }
  1582. },
  1583. methods: {
  1584. editSlug: function() {
  1585. this.customSlug = this.slug;
  1586. this.$emit('edit', this.slug);
  1587. this.isEditing = true;
  1588. },
  1589. saveSlug: function() {
  1590.  
  1591. if (this.customSlug !== this.slug) {
  1592. this.wasEdited = true;
  1593. }
  1594. this.setSlug(this.customSlug)
  1595.  
  1596. this.$emit('save', this.slug);
  1597. this.isEditing = false;
  1598. },
  1599.  
  1600. resetSlug: function() {
  1601. this.setSlug(this.title)
  1602. this.$emit('reset', this.slug);
  1603. this.wasEdited = false;
  1604. this.isEditing = false;
  1605. },
  1606.  
  1607. setSlug: function (newVal, count = 0) {
  1608. // Slugify the URL
  1609. let slug = Slug(newVal + (count > 0 ? `-${count}` : ''));
  1610. let vm = this;
  1611.  
  1612. if (vm.api_token && slug) {
  1613. // Test to see if the URL is unique or not
  1614. axios.get(this.url + '/api/posts/unique', {
  1615. params: {
  1616. api_token: vm.api_token,
  1617. slug: slug
  1618. }
  1619. }).then(function (response){
  1620. // If unique, set the slug else refactor it and make unique
  1621. if (response.data) {
  1622. // It's unique
  1623. vm.slug = slug;
  1624. vm.$emit('slug-changed', slug);
  1625. }else {
  1626. // It's not unique and customize the slug
  1627. vm.setSlug(newVal, count+1)
  1628.  
  1629. }
  1630. }).catch(function (error){
  1631. console.log(error);
  1632. });
  1633. }
  1634.  
  1635. },
  1636.  
  1637. existingSlug: function(val) {
  1638. this.setSlug(val)
  1639. }
  1640. },
  1641. watch: {
  1642. title: _.debounce(function() {
  1643.  
  1644. if (this.wasEdited === false) {
  1645. this.setSlug(this.title)
  1646. }
  1647.  
  1648. // this.slug = this.convertTitle();
  1649. }, 500),
  1650. // slug: function(val) {
  1651. // this.$emit('slug-changed', val);
  1652. // }
  1653. }
  1654. }
  1655. </script>
Add Comment
Please, Sign In to add comment