Skip to content

Commit

Permalink
feat: Open Youtube channels, query logic, basic templating without st…
Browse files Browse the repository at this point in the history
…yle #92
  • Loading branch information
shayaulman committed Mar 12, 2022
1 parent b835bac commit 5542c42
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 17 deletions.
13 changes: 7 additions & 6 deletions data/youtubeChannels.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Source: https://tchumim.com/topic/12462/%D7%91%D7%A7%D7%A9%D7%94-%D7%9C%D7%94%D7%9E%D7%9C%D7%A6%D7%95%D7%AA-%D7%A2%D7%9C-%D7%A2%D7%A8%D7%95%D7%A6%D7%99%D7%9D-%D7%A1%D7%A8%D7%98%D7%95%D7%A0%D7%99%D7%9D-%D7%A9%D7%9C-%D7%AA%D7%9B%D7%A0%D7%95%D7%AA-%D7%95%D7%94%D7%9E%D7%A1%D7%AA%D7%A2%D7%A3/22?_=1646950864870
// Note: The id of the channel has to be provided, check this out in case you only have the custom url (actual name of channel): https://stackoverflow.com/a/16326307/10679649

module.exports = [
{ id: 'channel/UCMgmeSgiQrVkYdJwl2aNe7Q' },
{ id: 'channel/UCIld0affiSkmp-KkEit3S_w' },
{ id: 'channel/UC29ju8bIPH5as8OGnQzwJyA' },
{ id: 'channel/UCW5YeuERMmlnqo4oq8vwUpg' },
{ id: 'c/programmingwithmosh' },
{ id: 'c/Freecodecamp' }
{ id: 'UCMgmeSgiQrVkYdJwl2aNe7Q' },
{ id: 'UCIld0affiSkmp-KkEit3S_w' },
{ id: 'UC29ju8bIPH5as8OGnQzwJyA' },
{ id: 'UCW5YeuERMmlnqo4oq8vwUpg' },
{ id: 'UCWv7vMbMWH4-V0ZXdmDpPBA' },
{ id: 'UC8butISFwT-Wl7EV0hUK0BQ' }
];
19 changes: 19 additions & 0 deletions gridsome.server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const axios = require("axios");

const videoTutorials = require("./data/videoTutorials");
const youtubeChannels = require("./data/youtubeChannels");
const redditChannels = require("./data/redditChannels");
const podcasts = require("./data/podcasts");
const blogs = require("./data/blogs");
Expand Down Expand Up @@ -51,6 +52,24 @@ module.exports = function(api) {
}
}

const CHANNELS_BASE_URL = `https://www.googleapis.com/youtube/v3/channels?part=snippet&key=${process.env.GRIDSOME_API_KEY}`;
// TODO: Optimize to use only 1 query for 50 entires like we do with videos
const channelsData = await axios
.all(youtubeChannels.map((channel) => axios.get(`${CHANNELS_BASE_URL}&id=${channel.id}`)))
.then((res) => res.map((r) => r.data));

const YoutubeChannel = actions.addCollection("YoutubeChannel");
channelsData.forEach(({ items }) => {
const data = items[0].snippet;
YoutubeChannel.addNode({
id: data.id,
title: data.title,
customUrl: data.customUrl,
description: data.description,
thumbnails: data.thumbnails
});
});

const RedditChannels = actions.addCollection("Reddit");
redditChannels.forEach((channel) => {
RedditChannels.addNode({
Expand Down
71 changes: 71 additions & 0 deletions src/components/ChannelCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<a target="_blank" :href="`https://www.youtube.com/c/${customUrl}`" :class="{ 'elevation-high': hover }" class="relative w-64 overflow-hidden rounded-md">
<img style="width: 320px; height: 150px" :src="thumbnail" alt :class="{ 'zoom-in': hover }" class="transition duration-300 rounded-t-md" />
<div style="height: 150px" class="relative z-10 w-full px-1 py-3 transition duration-300 bg-custom-bg-card">
<div v-if="isHebrew" class="absolute left-0 z-20 w-10 rounded israel-icon">
<israel-flag-icon class="bg-custom-bg-card" />
</div>
<h2 :class="{ 'rtl right-0': doesContainHebrewLetters([title]) }" class="p-2 px-3 text-sm font-light text-custom-text-secondary">{{ title }}</h2>
</div>
<div class="relative"></div>
<div class="z-40"></div>
</a>
</template>

<script>
import AppLoader from "~/components/UI/AppLoader";
import IsraelFlagIcon from "~/components/UI/IsraelFlagIcon";
export default {
props: {
id: String,
title: String,
isHebrew: Boolean,
thumbnail: String,
customUrl: String,
},
components: {
AppLoader,
IsraelFlagIcon,
},
data() {
return {
now: new Date(),
hover: false,
};
},
methods: {
doesContainHebrewLetters(textArr) {
const HEBREW = RegExp("[\u0590-\u05FF]");
return textArr.some((txt) => HEBREW.test(txt));
},
},
computed: {
direction() {
return this.doesContainHebrewLetters([this.title]) ? "rtl" : "ltr";
},
},
};
</script>

<style scoped>
.israel-icon {
top: -17px;
left: 80%;
}
.zoom-in {
transform: scale(1.02);
}
.elevation-high {
transition: 0.3s ease;
transform: translateY(-1px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.24);
-webkit-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.24);
}
</style>
39 changes: 39 additions & 0 deletions src/components/ChannelList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<div class="flex flex-wrap justify-center max-w-6xl mx-auto mb-24">
<channel-card v-for="channel in $static.channels.edges" :key="channel.id" :title="channel.node.title" :thumbnail="channel.node.thumbnails.default.url" :custom-url="channel.node.customUrl" />
</div>
</template>

<static-query>
{
channels: allYoutubeChannel {
edges {
node {
id,
title,
description,
customUrl,
thumbnails {
default {
url,
width
}
}
}
}
}
}
</static-query>

<script>
import ChannelCard from "@/components/ChannelCard.vue";
export default {
name: "ChannelList",
components: {
ChannelCard,
},
mounted() {
console.log(this.$static.channels.edges);
},
};
</script>
26 changes: 15 additions & 11 deletions src/pages/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@
<Layout>
<section class="mt-24">
<div class="heading">
<div class="mb-16 flex flex-col items-center">
<div class="flex flex-col items-center mb-16">
<h1 class="text-xl text-custom-text-primary">מאגר ענק של מקורות למידה למתכנתים</h1>

<categories-slide />
<h3 class="p-2 text-custom-text-secondary">
שנבדקו ואושרו ע"י
<a
href="https://netfree.link/"
style="color: #00b494"
class="hover:underline"
>נטפרי</a>
<a href="https://netfree.link/" style="color: #00b494" class="hover:underline">נטפרי</a>
</h3>
</div>
</div>
<div id="video-tutorials" class="pt-12 mb-48">
<h1
class="rtl mx-auto w-32 py-2 px-4 text-center text-white bg-custom-brand rounded-full"
>סרטוני הדרכה</h1>
<div class="flex justify-center">
<button @click="contentShow = 'videos'" class="w-32 px-4 py-2 mx-1 text-center text-white rounded-full rtl bg-custom-brand">סרטוני הדרכה</button>
<button @click="contentShow = 'channels'" class="w-32 px-4 py-2 mx-1 text-center text-white rounded-full rtl bg-custom-brand">ערוצים פתוחים</button>
</div>

<h1 class="font m-4 p-2 text-center text-xs text-custom-text-3 font-thin">
<h1 class="p-2 m-4 text-xs font-thin text-center font text-custom-text-3">
במאגר יש כעת
<span>{{ amountOfVideos | number }}</span> סרטונים
</h1>
<tech-list />
<channel-list v-if="contentShow === 'channels'" />
<tech-list v-else />
</div>
</section>
</Layout>
Expand All @@ -45,13 +43,19 @@

<script>
import TechList from "@/components/TechList";
import ChannelList from "@/components/ChannelList";
import CategoriesSlide from "@/components/CategoriesSlide";
export default {
components: {
TechList,
ChannelList,
CategoriesSlide,
},
data: () => ({
contentShow: "videos",
}),
computed: {
amountOfVideos() {
return this.$static.categories.edges.reduce(
Expand Down

0 comments on commit 5542c42

Please sign in to comment.