Purchase access to watch this video.

Unlock course for £159

Already purchased access? Login

Publishing videos

  1. We now want to be able to publish and un-publish videos.
  2. To achieve this, we'll add a new "status" column in the switch component to our
  3. videos listing table.
  4. In our video index view, let's add a new column for "status".
  5. And for each video, we will display a switch toggle to update the status of the video
  6. to publish and un-published.
  7. You can find a link for the mark-up for the component in the video resources.
  8. Pause the video now if you need to grab this.
  9. Copy the switch component mark-up and paste it into the "videos" table.
  10. Now if we take a look at the component, we can see it's just a simple Alpine.js
  11. component with a single "checked" property,
  12. which just toggles its value when the switch is checked.
  13. This isn't very helpful as it's not actually updating the video status.
  14. So let's flesh out this component.
  15. Open up your app.js file.
  16. We're going to create a new component called "updateVideoStatus".
  17. We'll define that "checked" property.
  18. But we're also going to specify some initial arguments the component needs.
  19. The "initialChecked" value.
  20. And the URL we should use to update the video status.
  21. When the switch is toggled, we want to update the video.
  22. If the switch's checked value is "true", that means the video is published and we
  23. want to make a request to un-publish it.
  24. If the checked value is "false", that means the video is not currently published
  25. and we want to publish it.
  26. On the button element, change the click handler.
  27. Instead of just simply toggling the checked property's value, we want to create
  28. a new "toggle" method.
  29. We should also change the component's x-data value to the name of the component
  30. we've just defined, which is "updateVideoStatus".
  31. Back in our app.js file.
  32. Let's create that "toggle" method.
  33. Before we continue, if we look at our Video model and "videos" table in the
  34. database,
  35. we'll see that we don't actually have a way of indicating if the video is
  36. published or not.
  37. We could add a simple "is_published" boolean column, but a better method is to
  38. instead store a timestamp of when the video was published.
  39. This is a approach Laravel uses itself.
  40. For example, specifying a "deleted_at" column instead of just "is_deleted" for
  41. soft deletes.
  42. It would also enable functionality such as a user being able to sort videos by
  43. published time and date, for example.
  44. We'll need to create a migration to modify our "videos" table.
  45. Create a new migration.
  46. Name it "add published at column to videos table".
  47. Let's set the "--table" argument to "videos".
  48. This just automatically sets the table argument to "videos" in the migration
  49. itself.
  50. In the "up" method, we want to create a new timestamp column called "published_at".
  51. It should be nullable by default.
  52. In the "down" method, we can just drop this column.
  53. Open our Video model.
  54. We now want to add this "published_at" column to our "fillable" array.
  55. And we also want to cast it as a "datetime".
  56. Since we've updated our database schema, we now need to migrate.
  57. In the terminal window, run "sail artisan migrate".
  58. We'll now create a new controller to handle the publishing and un-publishing of
  59. videos.
  60. Create a new singleton controller.
  61. And we'll call it "Admin\VideoPublishController".
  62. We can also set the parent to the Video model.
  63. Open it up.
  64. And remove all actions except the "store" action.
  65. And the "destroy" action.
  66. We can also remove this.
  67. We're going to use POST requests to the "store" action to publish the video and
  68. DELETE requests to the "destroy" action to un-publish the video.
  69. Open up your routes/web.php file.
  70. And we need to register the routes for that singleton resource.
  71. We add the "creatable" method as well to register a POST route as by default
  72. singleton resources don't register routes for creation of new singleton
  73. resources.
  74. If we run the route:list command,
  75. we should now see two new routes for publishing and un-publishing in videos.
  76. In our VideoPublishController, we simply want to set the "published_at"
  77. attribute of the Video model to the current date and time in the "store" action
  78. and set it to null in the "destroy" action.
  79. So let's do that.
  80. Go back to your app.js file.
  81. Let's make an Axios request in the "toggle" method we just created.
  82. [typing sounds]
  83. In the then callback, we don't need to do anything. In the catch callback, we
  84. need to reset the "checked" value back to the previous value if there was an
  85. error publishing or un-publishing in the video, and we can also display a
  86. JavaScript alert.
  87. We need to go back to our video index view and add the initial arguments for
  88. our component.
  89. By default we have two: we have the videos current published status and the URL
  90. for updating the video.
  91. [typing sounds]
  92. For the first argument, we check if the video's "published_at" attribute is not null.
  93. If it's not null, it means the video is published and "checked" should be true.
  94. For the second argument, we'll set it to the published store route.
  95. Let's go back to our VideoPublishController and update the return types of
  96. these methods.
  97. [typing sounds]
  98. Back in the browser, if we toggle a couple of these, we should see that they're
  99. now working.
  100. If we look in the database, we should see that some rows have "published_at"
  101. values now.
  102. This is all well and good, but we actually have an issue here.
  103. At the moment, we're currently able to publish videos that are in the process
  104. of being uploaded or that aren't ready yet.
  105. To fix this, we can add a guard to the "store" method in our VideoPublishController
  106. that aborts the request if the video is not ready for publishing.
  107. To be published, a video needs to meet the following criteria: it needs to have
  108. a description, the "upload_status" needs to be "complete", and the "mux_status"
  109. needs to be "ready".
  110. We can add a method to our Video model encapsulating this criteria.
  111. Open up your Video model and define a new "canBePublished" method that's
  112. going to return a boolean.
  113. In this method, we're simply going to return a boolean result of the above
  114. expression.
  115. [typing sounds]
  116. This method will return true if there's a description, if the "upload_status"
  117. equals "complete", and the "mux_status" equals "ready".
  118. If any of these are false, then the method will return false as well. Back in
  119. our publish controller, we can abort the request if that method returns false.
  120. [typing sounds]
  121. If the video cannot be published, then a 400 Bad Request response will be
  122. returned instead of the model being updated.
  123. We can test this in the browser by finding the video whose "upload_status" isn't
  124. "complete". If you try to publish, say, this video, we now get an error message
  125. and the toggle should go back to "off".
  126. And there we have it. We now have simple administration panel where we can
  127. upload videos, list videos, edit video details, and publish or un-publish
  128. videos.
  129. Now that we can actually publish videos, we'll look at displaying them in the
  130. front end of our application, and also playing uploaded videos in the browser.
Connect GitHub