mirror of https://github.com/nocodb/nocodb
DarkPhoenix2704
2 months ago
8 changed files with 149 additions and 45 deletions
@ -0,0 +1,77 @@ |
|||||||
|
<script setup lang="ts"> |
||||||
|
import { unified } from 'unified' |
||||||
|
import remarkParse from 'remark-parse' |
||||||
|
import remarkRehype from 'remark-rehype' |
||||||
|
import rehypeSanitize from 'rehype-sanitize' |
||||||
|
import rehypeStringify from 'rehype-stringify' |
||||||
|
import { YoutubeVue3 } from 'youtube-vue3' |
||||||
|
import type { ProductFeedItem } from '../../../lib/types' |
||||||
|
import { extractYoutubeVideoId } from '../../../utils/urlUtils' |
||||||
|
import { timeAgo } from '~/utils/datetimeUtils' |
||||||
|
const props = defineProps<{ |
||||||
|
item: ProductFeedItem |
||||||
|
}>() |
||||||
|
|
||||||
|
const { getPossibleAttachmentSrc } = useAttachment() |
||||||
|
|
||||||
|
const { |
||||||
|
item: { CreatedAt, Description, Url, Title, Tags, 'Feed Source': source, Images }, |
||||||
|
} = props |
||||||
|
|
||||||
|
const feedIcon = { |
||||||
|
'Twitter': iconMap.twitter, |
||||||
|
'Youtube': iconMap.youtube, |
||||||
|
'Github Release': iconMap.githubSolid, |
||||||
|
} |
||||||
|
|
||||||
|
const renderedText = computedAsync(async () => { |
||||||
|
return await unified() |
||||||
|
.use(remarkParse) |
||||||
|
.use(remarkRehype) |
||||||
|
.use(rehypeSanitize) |
||||||
|
.use(rehypeStringify) |
||||||
|
.process( |
||||||
|
Description.replace(/!\[.*?\]\(.*?\)/g, '') |
||||||
|
.substring(0, 300) |
||||||
|
.concat('...'), |
||||||
|
) |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<div class="bg-white rounded-2xl" style="width: 656px"> |
||||||
|
<div class="flex items-center justify-between px-5 py-5"> |
||||||
|
<div class="flex items-center gap-3"> |
||||||
|
<component :is="feedIcon[source]" class="w-4 h-4 stroke-transparent" /> |
||||||
|
<span class="font-weight-medium leading-5"> |
||||||
|
{{ source }} |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<div class="text-sm text-gray-700 leading-5"> |
||||||
|
{{ timeAgo(CreatedAt) }} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<template v-if="source === 'Github Release'"> |
||||||
|
<LazyCellAttachmentPreviewImage v-if="Images?.length" :srcs="getPossibleAttachmentSrc(Images[0], 'card_cover')" /> |
||||||
|
<div class="prose pl-5 mt-5" v-html="renderedText"></div> |
||||||
|
</template> |
||||||
|
<template v-else-if="source === 'Youtube'"> |
||||||
|
<YoutubeVue3 :videoid="extractYoutubeVideoId(Url)" :height="410" :width="656" :autoplay="0" /> |
||||||
|
<div class="p-5 flex flex-col text-gray-900 gap-4"> |
||||||
|
<div class="text-2xl font-semibold"> |
||||||
|
{{ Title }} |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="font-weight-base"> |
||||||
|
{{ Description.substring(0, 200).concat('...') }} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<!-- |
||||||
|
<template v-else-if="source === 'Twitter'"> |
||||||
|
<Tweet align="center" conversation="all" class="mt-6" :tweet-url="Url" /> |
||||||
|
</template> --> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<style scoped lang="scss"></style> |
@ -1,5 +1,37 @@ |
|||||||
<script setup lang="ts"></script> |
<script setup lang="ts"> |
||||||
|
const { socialFeed, loadFeed } = useProductFeed() |
||||||
|
|
||||||
<template>Recents Feed</template> |
const scrollContainer = ref<HTMLElement>() |
||||||
|
|
||||||
|
const { isLoading } = useInfiniteScroll( |
||||||
|
scrollContainer, |
||||||
|
async () => { |
||||||
|
if (isLoading.value) return |
||||||
|
const data = ( |
||||||
|
await loadFeed({ |
||||||
|
type: 'all', |
||||||
|
loadMore: true, |
||||||
|
}) |
||||||
|
).filter((item) => item['Feed Source'] !== 'Twitter') |
||||||
|
|
||||||
|
socialFeed.value = [...socialFeed.value, ...data] |
||||||
|
}, |
||||||
|
{ distance: 1, interval: 2000 }, |
||||||
|
) |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<div |
||||||
|
ref="scrollContainer" |
||||||
|
:style="{ |
||||||
|
height: 'calc(100dvh - var(--toolbar-height) - 3.25rem)', |
||||||
|
}" |
||||||
|
class="overflow-y-auto nc-scrollbar-md w-full" |
||||||
|
> |
||||||
|
<div class="flex flex-col items-center gap-6"> |
||||||
|
<FeedRecentsCard v-for="feed in socialFeed" :key="feed.Id" :item="feed" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
<style scoped lang="scss"></style> |
<style scoped lang="scss"></style> |
||||||
|
Loading…
Reference in new issue