add backend supporting opengraph and comments
This commit is contained in:
@ -1,13 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
avatar: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<div class="comment">
|
||||
<img src="https://cdn.vuetifyjs.com/images/lists/1.jpg" alt="User Avatar" class="avatar"/>
|
||||
<img :src="props.avatar" alt="User Avatar" class="avatar"/>
|
||||
<!-- <img src="https://cdn.vuetifyjs.com/images/lists/1.jpg" alt="User Avatar" class="avatar"/>-->
|
||||
<div class="comment-content">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi.</p>
|
||||
<p>{{props.content}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { onMounted, watch, ref } from 'vue'
|
||||
const BACKEND_URL = 'http://localhost:8080';
|
||||
|
||||
type OpenGraph = {
|
||||
type: string;
|
||||
@ -39,7 +40,7 @@ type OpenGraph = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
const url = defineProps({
|
||||
const props = defineProps({
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
@ -68,119 +69,24 @@ const og = ref<OpenGraph>({
|
||||
},
|
||||
});
|
||||
|
||||
function getOpenGraph() {
|
||||
if (!props.url) {
|
||||
return;
|
||||
}
|
||||
fetch(` ${BACKEND_URL}/api/v1/opengraph?url=${props.url}`)
|
||||
// fetch(`https://anyremark.com/api/v1/opengraph?url=${url}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
og.value = data;
|
||||
});
|
||||
}
|
||||
|
||||
watch(() => props.url, () => {
|
||||
getOpenGraph();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// fetch(`https://anyremark.com/api/opengraph?url=${url}`)
|
||||
// .then(response => response.json())
|
||||
// .then(data => {
|
||||
// og.value = data;
|
||||
// });
|
||||
// og.value = {
|
||||
// type: "video.other",
|
||||
// url: "https://www.youtube.com/watch?v=iedMwhLrFQQ",
|
||||
// title: "Stingrays with Friends - FPV Formation",
|
||||
// description: "My favorite thing to do in this hobby is fly FPV with friends and chase planes.Morning FPV flights with Ben and Eric.If you are interested in this plane (The...",
|
||||
// determiner: "",
|
||||
// site_name: "YouTube",
|
||||
// locale: "",
|
||||
// locales_alternate: "",
|
||||
// images: [
|
||||
// {
|
||||
// url: "https://i.ytimg.com/vi/iedMwhLrFQQ/maxresdefault.jpg",
|
||||
// secure_url: "",
|
||||
// type: "",
|
||||
// width: 1280,
|
||||
// height: 720
|
||||
// }
|
||||
// ],
|
||||
// audios: [],
|
||||
// videos: [
|
||||
// {
|
||||
// url: "https://www.youtube.com/embed/iedMwhLrFQQ",
|
||||
// secure_url: "https://www.youtube.com/embed/iedMwhLrFQQ",
|
||||
// type: "text/html",
|
||||
// width: 1280,
|
||||
// height: 720
|
||||
// }
|
||||
// ],
|
||||
// article: {
|
||||
// published_time: null,
|
||||
// modified_time: null,
|
||||
// expiration_time: null,
|
||||
// section: "",
|
||||
// tags: null,
|
||||
// authors: null
|
||||
// },
|
||||
// };
|
||||
|
||||
console.log(url);
|
||||
|
||||
// og.value = {
|
||||
// "type": "video.other",
|
||||
// "url": "https://vimeo.com/867950660",
|
||||
// "title": "Hands Of Sicily.",
|
||||
// "description": "The hands of a human can tell a million stories. This film is an intimate portrait of Sicily. It simply shows the hands of the people from the island in action.\u0026hellip;",
|
||||
// "determiner": "",
|
||||
// "site_name": "Vimeo",
|
||||
// "locale": "",
|
||||
// "locales_alternate": null,
|
||||
// "images": [
|
||||
// {
|
||||
// "url": "https://i.vimeocdn.com/video/1728918730-bfdfd12d26406a06d263d62fef2da83aea8a684a0eeff059bb2ae6c41eda4aec-d?f=webp",
|
||||
// "secure_url": "https://i.vimeocdn.com/video/1728918730-bfdfd12d26406a06d263d62fef2da83aea8a684a0eeff059bb2ae6c41eda4aec-d?f=webp",
|
||||
// "type": "image/webp",
|
||||
// "width": 1280,
|
||||
// "height": 953
|
||||
// }
|
||||
// ],
|
||||
// "audios": null,
|
||||
// "videos": [
|
||||
// {
|
||||
// "url": "https://player.vimeo.com/video/867950660?autoplay=1\u0026amp;h=f094db59eb",
|
||||
// "secure_url": "https://player.vimeo.com/video/867950660?autoplay=1\u0026amp;h=f094db59eb",
|
||||
// "type": "text/html",
|
||||
// "width": 1280,
|
||||
// "height": 953
|
||||
// }
|
||||
// ],
|
||||
// "article": {
|
||||
// "published_time": null,
|
||||
// "modified_time": null,
|
||||
// "expiration_time": null,
|
||||
// "section": "",
|
||||
// "tags": null,
|
||||
// "authors": null
|
||||
// }
|
||||
// };
|
||||
|
||||
og.value = {
|
||||
"type": "article",
|
||||
"url": "https://github.blog/changelog/2024-11-27-access-a-repositorys-secret-scanning-scan-history-with-the-rest-api/",
|
||||
"title": "Access a repository’s secret scanning scan history with the REST API · GitHub Changelog",
|
||||
"description": "Access a repository's secret scanning scan history with the REST API",
|
||||
"determiner": "",
|
||||
"site_name": "The GitHub Blog",
|
||||
"locale": "en_US",
|
||||
"locales_alternate": null,
|
||||
"images": [
|
||||
{
|
||||
"url": "https://github.blog/wp-content/uploads/2024/08/d34e9c19123898a8a886147f37a1d167130d1c15be6d399a9c4b30ee6f2a7395-1200x630-1.png?fit=1200%2C630",
|
||||
"secure_url": "",
|
||||
"type": "image/png",
|
||||
"width": 1200,
|
||||
"height": 630
|
||||
}
|
||||
],
|
||||
"audios": null,
|
||||
"videos": null,
|
||||
"article": {
|
||||
"published_time": null,
|
||||
"modified_time": null,
|
||||
"expiration_time": null,
|
||||
"section": "",
|
||||
"tags": null,
|
||||
"authors": null
|
||||
}
|
||||
};
|
||||
getOpenGraph();
|
||||
});
|
||||
|
||||
const videoVisible = ref(false);
|
||||
@ -191,45 +97,14 @@ function showVideo() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Show the topic webpage's open graph content-->
|
||||
<!-- server side will use https://github.com/dyatlov/go-opengraph -->
|
||||
<!-- example opengraph output here
|
||||
{
|
||||
"type": "video.other",
|
||||
"url": "https://www.youtube.com/watch?v=iedMwhLrFQQ",
|
||||
"title": "Stingrays with Friends - FPV Formation",
|
||||
"description": "My favorite thing to do in this hobby is fly FPV with friends and chase planes.Morning FPV flights with Ben and Eric.If you are interested in this plane (The...",
|
||||
"determiner": "",
|
||||
"site_name": "YouTube",
|
||||
"locale": "",
|
||||
"locales_alternate": null,
|
||||
"images": [
|
||||
{
|
||||
"url": "https://i.ytimg.com/vi/iedMwhLrFQQ/maxresdefault.jpg",
|
||||
"secure_url": "",
|
||||
"type": "",
|
||||
"width": 1280,
|
||||
"height": 720
|
||||
}
|
||||
],
|
||||
"audios": null,
|
||||
"videos": [
|
||||
{
|
||||
"url": "https://www.youtube.com/embed/iedMwhLrFQQ",
|
||||
"secure_url": "https://www.youtube.com/embed/iedMwhLrFQQ",
|
||||
"type": "text/html",
|
||||
"width": 1280,
|
||||
"height": 720
|
||||
}
|
||||
]
|
||||
}
|
||||
-->
|
||||
<article>
|
||||
<h1><a :href="og.url">{{og.title}}</a></h1>
|
||||
<p>{{og.description}}</p>
|
||||
<h1><a :href="!!og.url ? og.url : props.url">{{!!og.title ? og.title : props.url}}</a></h1>
|
||||
<p v-if="!!og.description">{{og.description}}</p>
|
||||
|
||||
<div class="article-thumb-container" v-if="og.type === 'article'">
|
||||
<img :src="!!og.images.length ? og.images[0].url : ''" alt="Article Thumbnail" />
|
||||
<a :href="props.url" target="_blank">{{props.url}}</a>
|
||||
|
||||
<div class="images-container" v-if="!!og.images?.length && og.type !== 'video.other'">
|
||||
<img v-on:error="() => og.images = []" :src="!!og.images.length ? og.images[0].url : ''" alt="Article Thumbnail" />
|
||||
</div>
|
||||
|
||||
<div class="video-other" v-if="og.type === 'video.other'">
|
||||
@ -239,7 +114,7 @@ function showVideo() {
|
||||
|
||||
<div class="non-yt-container" v-if="!!og.videos?.length && (!og.url.startsWith('https://www.youtube.com') && !og.url.startsWith('https://vimeo.com'))">
|
||||
<div class="thumbnail-container" @click="showVideo" v-if="!videoVisible">
|
||||
<img :src="!!og.images.length ? og.images[0].url : ''" alt="Video Thumbnail" />
|
||||
<img v-on:error="() => og.images = []" :src="!!og.images.length ? og.images[0].url : ''" alt="Video Thumbnail" />
|
||||
<div class="play-button"></div>
|
||||
</div>
|
||||
<div class="thumbnail-container" v-else>
|
||||
@ -261,13 +136,13 @@ article {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.article-thumb-container {
|
||||
.images-container {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.article-thumb-container img {
|
||||
.images-container img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
@ -298,9 +173,6 @@ article {
|
||||
|
||||
.non-yt-container, .non-yt-container>div {
|
||||
width: 100%;
|
||||
/* padding-bottom: 56.25%;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px; */
|
||||
}
|
||||
|
||||
.thumbnail-container {
|
||||
|
@ -2,10 +2,74 @@
|
||||
|
||||
import CommentComponent from '@/components/CommentComponent.vue'
|
||||
import OpenGraphComponent from '@/components/OpenGraphComponent.vue'
|
||||
import { ref } from 'vue'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
const BACKEND_URL = 'http://localhost:8080';
|
||||
|
||||
interface Comment {
|
||||
id: string;
|
||||
content: string;
|
||||
commenter: string;
|
||||
parent_id: string;
|
||||
webpage_id: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
// const url = ref('https://www.youtube.com/watch?v=iedMwhLrFQQ');
|
||||
const url = ref('https://vimeo.com/867950660');
|
||||
// const url = ref('https://vimeo.com/867950660');
|
||||
const url = ref('');
|
||||
const comment = ref('');
|
||||
const comments = ref<Comment[]>([]);
|
||||
|
||||
onMounted(() => {
|
||||
// get target url from query param 'url'
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const urlParam = urlParams.get('url');
|
||||
if (urlParam) {
|
||||
url.value = urlParam;
|
||||
}
|
||||
});
|
||||
|
||||
watch(url, (newVal) => {
|
||||
if (newVal) {
|
||||
getComments();
|
||||
}
|
||||
});
|
||||
|
||||
function getComments() {
|
||||
fetch(`${BACKEND_URL}/api/v1/comments?url=${url.value}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
if (!!data) {
|
||||
comments.value = data;
|
||||
}
|
||||
console.log(data);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSubmit(e: Event) {
|
||||
e.preventDefault();
|
||||
fetch(`${BACKEND_URL}/api/v1/comment`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
url: url.value,
|
||||
comment: comment.value,
|
||||
user_id: 'u_12345'
|
||||
}),
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.ok) {
|
||||
console.log('Comment submitted');
|
||||
comment.value = '';
|
||||
getComments();
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error('Error:', err);
|
||||
});
|
||||
console.log('submit');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -18,13 +82,17 @@ const url = ref('https://vimeo.com/867950660');
|
||||
<section class="comments">
|
||||
<h2>Comments</h2>
|
||||
|
||||
<form class="comment-form">
|
||||
<textarea placeholder="Add a comment..."></textarea>
|
||||
<form class="comment-form" v-on:submit="handleSubmit">
|
||||
<textarea placeholder="Add a comment..." v-model="comment"></textarea>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<div v-for="i in 5" :key="i">
|
||||
<CommentComponent />
|
||||
<div v-for="(remark, i) in comments" :key="i">
|
||||
<CommentComponent :content="remark.content" :avatar="`https://cdn.vuetifyjs.com/images/lists/1.jpg`" />
|
||||
</div>
|
||||
|
||||
<div v-if="comments.length === 0">
|
||||
<p>No comments yet.</p>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
Reference in New Issue
Block a user