From f8e72629551fc91e9c308afd0a2abf29fbb95578 Mon Sep 17 00:00:00 2001 From: Ahmed Helal Ahmed Date: Sat, 4 Sep 2021 08:56:54 +0200 Subject: [PATCH] Add validation layer for storing channel and depend on link not identifier - Add validation layer for storing channel and depend on link - Add pagination for channels - Redirect to channels index when click on dashboard - Enhance title of pages --- .env.example | 4 +- .../Controllers/IndexingChannelController.php | 10 +- .../Controllers/StoringChannelController.php | 6 +- app/Http/Requests/StoreChannelRequest.php | 56 +++++ .../GettingChannelIdByLinkService.php | 28 +++ config/youtube.php | 1 + public/css/app.css | 222 ++---------------- public/js/app.js | 127 +++++++--- resources/js/Layouts/AppLayout.vue | 2 +- resources/js/Pages/Channels/Videos/index.vue | 2 +- resources/js/Pages/Channels/index.vue | 53 +++-- routes/web.php | 8 +- 12 files changed, 253 insertions(+), 266 deletions(-) create mode 100644 app/Http/Requests/StoreChannelRequest.php create mode 100644 app/Services/GettingChannelIdByLinkService.php diff --git a/.env.example b/.env.example index 57461d2..dec9b2d 100644 --- a/.env.example +++ b/.env.example @@ -17,7 +17,7 @@ DB_PASSWORD= BROADCAST_DRIVER=log CACHE_DRIVER=file FILESYSTEM_DRIVER=local -QUEUE_CONNECTION=sync +QUEUE_CONNECTION=database SESSION_DRIVER=database SESSION_LIFETIME=120 @@ -53,4 +53,6 @@ YOUTUBE_BASE_URL_API="https://www.googleapis.com/youtube/v3/" # To get API key for Youtube https://developers.google.com/youtube/v3/getting-started YOUTUBE_API_KEY= YOUTUBE_CHANNEL_URL_API="${YOUTUBE_BASE_URL_API}channels" +YOUTUBE_CHANNEL_videos_URL_API="${YOUTUBE_BASE_URL_API}playlistItems" YOUTUBE_VIDEO_BASE_LINK="https://www.youtube.com/watch?v=" +YOUTUBE_CHANNEL_SEARCH_API="${YOUTUBE_BASE_URL_API}search" diff --git a/app/Http/Controllers/IndexingChannelController.php b/app/Http/Controllers/IndexingChannelController.php index fffb925..69a68ac 100644 --- a/app/Http/Controllers/IndexingChannelController.php +++ b/app/Http/Controllers/IndexingChannelController.php @@ -8,7 +8,13 @@ class IndexingChannelController { public function __invoke() { - - return inertia()->render('Channels/index', ['channels' => Channel::all()]); + return inertia()->render( + 'Channels/index', + [ + 'channels' => Channel::where('user_id', auth()->id()) + ->withCount('videos') + ->paginate() + ] + ); } } diff --git a/app/Http/Controllers/StoringChannelController.php b/app/Http/Controllers/StoringChannelController.php index db93453..2069363 100644 --- a/app/Http/Controllers/StoringChannelController.php +++ b/app/Http/Controllers/StoringChannelController.php @@ -4,14 +4,14 @@ namespace App\Http\Controllers; +use App\Http\Requests\StoreChannelRequest; use App\Models\Channel; -use Illuminate\Support\Arr; class StoringChannelController { - public function __invoke() + public function __invoke(StoreChannelRequest $request) { - Channel::create(array_merge(request()->only(['name', 'remote_identifier']),['user_id'=>auth()->id()])); + Channel::create($request->validated()); return back(); } diff --git a/app/Http/Requests/StoreChannelRequest.php b/app/Http/Requests/StoreChannelRequest.php new file mode 100644 index 0000000..b747109 --- /dev/null +++ b/app/Http/Requests/StoreChannelRequest.php @@ -0,0 +1,56 @@ + 'required', + 'link' => 'required|url', + 'remote_identifier' => 'required|unique:channels,remote_identifier', + 'user_id' => 'required' + ]; + } + + public function prepareForValidation() + { + $this->merge(['remote_identifier' => $this->link ? $this->getChannelIdFromLink($this->link) : null]); + $this->merge(['user_id' => auth()->id()]); + } + + private function getChannelIdFromLink(string $url): string + { + $parsed = parse_url(rtrim($url, '/')); + if (isset($parsed['path']) && preg_match('/^\/channel\/(([^\/])+?)$/', $parsed['path'], $matches)) { + return $matches[1]; + } + return (new GettingChannelIdByLinkService)->execute($url); + } + + public function messages() + { + return [ + 'remote_identifier.unique' => 'Channel already exists' + ]; + } +} diff --git a/app/Services/GettingChannelIdByLinkService.php b/app/Services/GettingChannelIdByLinkService.php new file mode 100644 index 0000000..f76d7e3 --- /dev/null +++ b/app/Services/GettingChannelIdByLinkService.php @@ -0,0 +1,28 @@ + 'snippet', + 'q' => $link, + 'type' => 'channel', + 'key' => config('youtube.key') + ])->json(); + + return Arr::get($response, 'items.0.snippet.channelId'); + } +} diff --git a/config/youtube.php b/config/youtube.php index e6dd07f..a0c64d6 100644 --- a/config/youtube.php +++ b/config/youtube.php @@ -7,6 +7,7 @@ 'channel' => env('YOUTUBE_CHANNEL_URL_API'), 'videos' => env('YOUTUBE_CHANNEL_videos_URL_API'), 'video_base_link' => env('YOUTUBE_VIDEO_BASE_LINK'), + 'search' => env('YOUTUBE_CHANNEL_SEARCH_API'), ], diff --git a/public/css/app.css b/public/css/app.css index 0fe9061..fb606df 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -1115,18 +1115,10 @@ select { margin-left: auto; margin-right: auto; } -.mx-6 { - margin-left: 1.5rem; - margin-right: 1.5rem; -} .my-1 { margin-top: 0.25rem; margin-bottom: 0.25rem; } -.my-2 { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} .ml-3 { margin-left: 0.75rem; } @@ -1199,15 +1191,6 @@ select { .-mt-px { margin-top: -1px; } -.mb-2 { - margin-bottom: 0.5rem; -} -.mb-3 { - margin-bottom: 0.75rem; -} -.-ml-1 { - margin-left: -0.25rem; -} .-mb-1 { margin-bottom: -0.25rem; } @@ -1217,20 +1200,11 @@ select { .mb-1 { margin-bottom: 0.25rem; } -.mr-6 { - margin-right: 1.5rem; -} -.mr-10 { - margin-right: 2.5rem; -} -.mb-10 { - margin-bottom: 2.5rem; -} -.mb-12 { - margin-bottom: 3rem; +.mb-2 { + margin-bottom: 0.5rem; } -.mr-4 { - margin-right: 1rem; +.mb-3 { + margin-bottom: 0.75rem; } .block { display: block; @@ -1277,18 +1251,9 @@ select { .h-20 { height: 5rem; } -.h-32 { - height: 8rem; -} -.h-screen { - height: 100vh; -} .min-h-screen { min-height: 100vh; } -.min-h-0 { - min-height: 0px; -} .w-5 { width: 1.25rem; } @@ -1331,9 +1296,6 @@ select { .w-20 { width: 5rem; } -.w-32 { - width: 8rem; -} .w-72 { width: 18rem; } @@ -1352,9 +1314,6 @@ select { .max-w-6xl { max-width: 72rem; } -.max-w-sm { - max-width: 24rem; -} .flex-1 { flex: 1 1 0%; } @@ -1391,22 +1350,6 @@ select { .transform { transform: var(--tw-transform); } -@-webkit-keyframes spin { - - to { - transform: rotate(360deg); - } -} -@keyframes spin { - - to { - transform: rotate(360deg); - } -} -.animate-spin { - -webkit-animation: spin 1s linear infinite; - animation: spin 1s linear infinite; -} .cursor-default { cursor: default; } @@ -1433,27 +1376,15 @@ select { .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } -.flex-row { - flex-direction: row; -} .flex-col { flex-direction: column; } .flex-wrap { flex-wrap: wrap; } -.content-center { - align-content: center; -} -.content-between { - align-content: space-between; -} .items-center { align-items: center; } -.justify-start { - justify-content: flex-start; -} .justify-end { justify-content: flex-end; } @@ -1487,16 +1418,16 @@ select { margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); } -.space-y-10 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(2.5rem * var(--tw-space-y-reverse)); -} .space-x-6 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1.5rem * var(--tw-space-x-reverse)); margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse))); } +.space-y-10 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2.5rem * var(--tw-space-y-reverse)); +} .space-x-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1rem * var(--tw-space-x-reverse)); @@ -1505,19 +1436,12 @@ select { .overflow-hidden { overflow: hidden; } -.overflow-x-auto { - overflow-x: auto; -} .overflow-y-auto { overflow-y: auto; } .overflow-y-hidden { overflow-y: hidden; } -.overscroll-auto { - -ms-scroll-chaining: chained; - overscroll-behavior: auto; -} .truncate { overflow: hidden; text-overflow: ellipsis; @@ -1560,9 +1484,6 @@ select { .border-2 { border-width: 2px; } -.border-0 { - border-width: 0px; -} .border-b-2 { border-bottom-width: 2px; } @@ -1601,14 +1522,6 @@ select { --tw-border-opacity: 1; border-color: rgba(156, 163, 175, var(--tw-border-opacity)); } -.border-red-500 { - --tw-border-opacity: 1; - border-color: rgba(239, 68, 68, var(--tw-border-opacity)); -} -.border-gray-900 { - --tw-border-opacity: 1; - border-color: rgba(17, 24, 39, var(--tw-border-opacity)); -} .bg-white { --tw-bg-opacity: 1; background-color: rgba(255, 255, 255, var(--tw-bg-opacity)); @@ -1657,30 +1570,22 @@ select { --tw-bg-opacity: 1; background-color: rgba(229, 231, 235, var(--tw-bg-opacity)); } -.bg-blue-500 { - --tw-bg-opacity: 1; - background-color: rgba(59, 130, 246, var(--tw-bg-opacity)); -} .bg-blue-700 { --tw-bg-opacity: 1; background-color: rgba(29, 78, 216, var(--tw-bg-opacity)); } -.bg-yellow-400 { +.bg-blue-500 { --tw-bg-opacity: 1; - background-color: rgba(251, 191, 36, var(--tw-bg-opacity)); + background-color: rgba(59, 130, 246, var(--tw-bg-opacity)); } -.bg-green-400 { +.bg-purple-500 { --tw-bg-opacity: 1; - background-color: rgba(52, 211, 153, var(--tw-bg-opacity)); + background-color: rgba(139, 92, 246, var(--tw-bg-opacity)); } .bg-red-500 { --tw-bg-opacity: 1; background-color: rgba(239, 68, 68, var(--tw-bg-opacity)); } -.bg-purple-500 { - --tw-bg-opacity: 1; - background-color: rgba(139, 92, 246, var(--tw-bg-opacity)); -} .bg-opacity-25 { --tw-bg-opacity: 0.25; } @@ -1693,9 +1598,6 @@ select { .bg-no-repeat { background-repeat: no-repeat; } -.fill-current { - fill: currentColor; -} .object-cover { -o-object-fit: cover; object-fit: cover; @@ -1706,15 +1608,9 @@ select { .p-6 { padding: 1.5rem; } -.p-1 { - padding: 0.25rem; -} .p-4 { padding: 1rem; } -.p-3 { - padding: 0.75rem; -} .px-4 { padding-left: 1rem; padding-right: 1rem; @@ -1775,10 +1671,6 @@ select { padding-left: 2rem; padding-right: 2rem; } -.px-20 { - padding-left: 5rem; - padding-right: 5rem; -} .px-5 { padding-left: 1.25rem; padding-right: 1.25rem; @@ -1831,12 +1723,6 @@ select { .text-right { text-align: right; } -.align-baseline { - vertical-align: baseline; -} -.align-middle { - vertical-align: middle; -} .font-sans { font-family: Nunito, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } @@ -1895,9 +1781,6 @@ select { .leading-4 { line-height: 1rem; } -.leading-6 { - line-height: 1.5rem; -} .tracking-widest { letter-spacing: 0.1em; } @@ -1975,26 +1858,6 @@ select { --tw-text-opacity: 1; color: rgba(209, 213, 219, var(--tw-text-opacity)); } -.text-blue-500 { - --tw-text-opacity: 1; - color: rgba(59, 130, 246, var(--tw-text-opacity)); -} -.text-yellow-600 { - --tw-text-opacity: 1; - color: rgba(217, 119, 6, var(--tw-text-opacity)); -} -.text-blue-600 { - --tw-text-opacity: 1; - color: rgba(37, 99, 235, var(--tw-text-opacity)); -} -.text-purple-600 { - --tw-text-opacity: 1; - color: rgba(124, 58, 237, var(--tw-text-opacity)); -} -.text-pink-600 { - --tw-text-opacity: 1; - color: rgba(219, 39, 119, var(--tw-text-opacity)); -} .underline { text-decoration: underline; } @@ -2017,9 +1880,6 @@ select { .opacity-25 { opacity: 0.25; } -.opacity-30 { - opacity: 0.3; -} .shadow-sm { --tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); @@ -2138,14 +1998,14 @@ select { --tw-bg-opacity: 1; background-color: rgba(249, 250, 251, var(--tw-bg-opacity)); } -.hover\:bg-blue-700:hover { - --tw-bg-opacity: 1; - background-color: rgba(29, 78, 216, var(--tw-bg-opacity)); -} .hover\:bg-white:hover { --tw-bg-opacity: 1; background-color: rgba(255, 255, 255, var(--tw-bg-opacity)); } +.hover\:bg-blue-700:hover { + --tw-bg-opacity: 1; + background-color: rgba(29, 78, 216, var(--tw-bg-opacity)); +} .hover\:bg-blue-600:hover { --tw-bg-opacity: 1; background-color: rgba(37, 99, 235, var(--tw-bg-opacity)); @@ -2170,22 +2030,18 @@ select { --tw-text-opacity: 1; color: rgba(17, 24, 39, var(--tw-text-opacity)); } -.hover\:text-blue-800:hover { - --tw-text-opacity: 1; - color: rgba(30, 64, 175, var(--tw-text-opacity)); -} .hover\:shadow-xl:hover { --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.hover\:shadow-lg:hover { - --tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} .hover\:shadow-md:hover { --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.hover\:shadow-lg:hover { + --tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} .focus\:z-10:focus { z-index: 10; } @@ -2531,38 +2387,10 @@ select { margin-top: 0px; } - .md\:mb-0 { - margin-bottom: 0px; - } - - .md\:mt-10 { - margin-top: 2.5rem; - } - - .md\:mr-2 { - margin-right: 0.5rem; - } - - .md\:ml-2 { - margin-left: 0.5rem; - } - .md\:grid { display: grid; } - .md\:min-h-full { - min-height: 100%; - } - - .md\:w-1\/2 { - width: 50%; - } - - .md\:w-full { - width: 100%; - } - .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } @@ -2587,14 +2415,6 @@ select { border-left-width: 1px; } - .md\:border-l-2 { - border-left-width: 2px; - } - - .md\:border-dotted { - border-style: dotted; - } - .md\:px-2 { padding-left: 0.5rem; padding-right: 0.5rem; diff --git a/public/js/app.js b/public/js/app.js index 02180c8..0b058c6 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -20681,6 +20681,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.esm-bundler.js"); /* harmony import */ var _Layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/Layouts/AppLayout.vue */ "./resources/js/Layouts/AppLayout.vue"); /* harmony import */ var _inertiajs_inertia__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @inertiajs/inertia */ "./node_modules/@inertiajs/inertia/dist/index.js"); +/* harmony import */ var _Components_Pagination__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/Components/Pagination */ "./resources/js/Components/Pagination.vue"); + @@ -20688,7 +20690,7 @@ __webpack_require__.r(__webpack_exports__); setup: function setup() { var form = (0,vue__WEBPACK_IMPORTED_MODULE_0__.reactive)({ name: null, - remote_identifier: null + link: null }); function submit() { @@ -20701,10 +20703,12 @@ __webpack_require__.r(__webpack_exports__); }; }, props: { - channels: Array + channels: Object, + errors: Object }, components: { - AppLayout: _Layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_1__["default"] + AppLayout: _Layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_1__["default"], + Pagination: _Components_Pagination__WEBPACK_IMPORTED_MODULE_3__["default"] } })); @@ -22606,7 +22610,7 @@ var _hoisted_7 = { "class": "hidden space-x-8 sm:-my-px sm:ml-10 sm:flex" }; -var _hoisted_8 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Dashboard "); +var _hoisted_8 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Channels "); var _hoisted_9 = { "class": "hidden sm:flex sm:items-center sm:ml-6" @@ -24754,7 +24758,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { var _component_app_layout = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("app-layout"); return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_app_layout, { - title: "Dashboard" + title: "Videos" }, { header: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () { return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h2", _hoisted_1, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(_ctx.channel.name) + " (" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(_ctx.videos.total) + ") ", 1 @@ -24921,7 +24925,7 @@ __webpack_require__.r(__webpack_exports__); var _hoisted_1 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h2", { "class": "font-semibold text-xl text-gray-800 leading-tight" -}, " Dashboard ", -1 +}, " Channels ", -1 /* HOISTED */ ); @@ -24937,97 +24941,148 @@ var _hoisted_4 = { var _hoisted_5 = { "class": "w-full " }; -var _hoisted_6 = { + +var _hoisted_6 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h1", { + "class": "text-center mt-10 text-4xl font-bold" +}, "Add channel", -1 +/* HOISTED */ +); + +var _hoisted_7 = { "class": "mb-4" }; -var _hoisted_7 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", { +var _hoisted_8 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", { "class": "block text-gray-700 text-sm font-bold mb-2", "for": "name" -}, " Name ", -1 +}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Name "), /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("code", { + "class": "text-red-600" +}, "*")], -1 /* HOISTED */ ); -var _hoisted_8 = { +var _hoisted_9 = { + key: 0, + "class": "text-red-600" +}; +var _hoisted_10 = { "class": "mb-6" }; -var _hoisted_9 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", { +var _hoisted_11 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", { "class": "block text-gray-700 text-sm font-bold mb-2", - "for": "remote_identifier" -}, " Remote identifier ", -1 + "for": "link" +}, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Link "), /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("code", { + "class": "text-red-600" +}, "*")], -1 /* HOISTED */ ); -var _hoisted_10 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", { +var _hoisted_12 = { + key: 0, + "class": "text-red-600" +}; +var _hoisted_13 = { + key: 1, + "class": "text-red-600" +}; + +var _hoisted_14 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", { "class": "flex items-center justify-between" }, [/*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { "class": "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline", type: "submit" -}, " Submit ")], -1 +}, " Save ")], -1 /* HOISTED */ ); -var _hoisted_11 = { - "class": "text-center p-6 border-gray-200" +var _hoisted_15 = { + "class": "text-center" +}; + +var _hoisted_16 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h1", { + "class": "text-center mt-10 text-4xl font-bold" +}, "Channels", -1 +/* HOISTED */ +); + +var _hoisted_17 = ["href"]; +var _hoisted_18 = { + "class": " text-center items-center p-6 space-x-6 bg-gray-50 rounded-xl shadow-lg hover:shadow-xl transform hover:scale-105 transition duration-500" }; -var _hoisted_12 = ["href"]; -var _hoisted_13 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("p", { +var _hoisted_19 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("p", { "class": "text-center text-gray-500 text-xs" }, " ©2021 Ahmed Helal Ahmed. All rights reserved. ", -1 /* HOISTED */ ); function render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_pagination = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("pagination"); + var _component_app_layout = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("app-layout"); return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_app_layout, { - title: "Dashboard" + title: "Channels" }, { header: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () { return [_hoisted_1]; }), "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () { - return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("form", { + return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_5, [_hoisted_6, (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("form", { "class": "bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4", onSubmit: _cache[2] || (_cache[2] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(function () { return _ctx.submit && _ctx.submit.apply(_ctx, arguments); }, ["prevent"])) - }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_6, [_hoisted_7, (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { + }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_7, [_hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) { return _ctx.form.name = $event; }), "class": "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline", id: "name", type: "text", - placeholder: "Username" + name: "name", + placeholder: "Channel name" }, null, 512 /* NEED_PATCH */ - ), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, _ctx.form.name]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_8, [_hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { + ), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, _ctx.form.name]]), _ctx.errors.name ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(_ctx.errors.name), 1 + /* TEXT */ + )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_10, [_hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) { - return _ctx.form.remote_identifier = $event; + return _ctx.form.link = $event; }), "class": "shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline", - id: "remote_identifier", - type: "text", - placeholder: "Remote identifier" + id: "link", + type: "url", + name: "link", + placeholder: "Channel link" }, null, 512 /* NEED_PATCH */ - ), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, _ctx.form.remote_identifier]])]), _hoisted_10], 32 + ), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, _ctx.form.link]]), _ctx.errors.link ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(_ctx.errors.link), 1 + /* TEXT */ + )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), _ctx.errors.remote_identifier ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_13, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(_ctx.errors.remote_identifier), 1 + /* TEXT */ + )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)]), _hoisted_14], 32 /* HYDRATE_EVENTS */ - )]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_11, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("ul", null, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.channels, function (channel) { - return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("li", { + )]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("section", _hoisted_15, [_hoisted_16, ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)(_ctx.channels.data, function (channel) { + return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", { key: channel.id, - "class": "font-bold" + "class": "font-bold p-6 border-gray-200" }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { href: _ctx.route('channels.show', channel.id) - }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(channel.name), 9 - /* TEXT, PROPS */ - , _hoisted_12)]); + }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_18, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(channel.name) + " - " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(channel.videos_count) + " videos ", 1 + /* TEXT */ + )], 8 + /* PROPS */ + , _hoisted_17)]); }), 128 /* KEYED_FRAGMENT */ - ))])]), _hoisted_13])])])]; + )), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_pagination, { + "class": "mt-6 mb-6 p-2", + links: _ctx.channels.links + }, null, 8 + /* PROPS */ + , ["links"])]), _hoisted_19])])])]; }), _: 1 /* STABLE */ diff --git a/resources/js/Layouts/AppLayout.vue b/resources/js/Layouts/AppLayout.vue index d64e73b..fa9f0ed 100644 --- a/resources/js/Layouts/AppLayout.vue +++ b/resources/js/Layouts/AppLayout.vue @@ -20,7 +20,7 @@ diff --git a/resources/js/Pages/Channels/Videos/index.vue b/resources/js/Pages/Channels/Videos/index.vue index 1309c62..f103eb8 100644 --- a/resources/js/Pages/Channels/Videos/index.vue +++ b/resources/js/Pages/Channels/Videos/index.vue @@ -1,5 +1,5 @@