138 lines
3.3 KiB
Vue

<template>
<div>
<h1>{{ $t('widget.news.title') }}</h1>
<ul class="scrollable">
<li v-for="item in newsItems" :key="item.id">
<h2>{{ item.title }}</h2>
<div class="content" v-if="shouldTruncate(item.content)">
<div v-html="truncateMarkdownContent(item.content)"></div>
<span class="read-more" @click="() => openModal(item)">Read more</span>
</div>
<div class="content" v-else>
<div v-html="convertMarkdownToHtml(item.content)"></div>
</div>
<modal v-if="showModal" @close="closeModal">
<template #header>
<p class="news-title">{{ item.title }}</p>
</template>
<template #body>
<p class="news-date">{{ formatDate(item.startdate) }}</p>
<div v-html="convertMarkdownToHtml(item.content)"></div>
</template>
</modal>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import {makeFetch} from "ChillMainAssets/lib/api/apiMethods";
import Modal from '../../_components/Modal.vue'; // Adjust the import path
import { marked } from 'marked';
import DOMPurify from 'dompurify';
const newsItems = ref([])
const selectedArticle = ref(null);
const showModal = ref(false);
const openModal = (item) => {
selectedArticle.value = item;
showModal.value = true;
};
const closeModal = () => {
selectedArticle.value = null;
showModal.value = false;
};;
const shouldTruncate = (content, maxLength = 100) => {
return content.length > maxLength;
};
const truncateContent = (content, maxLength = 100) => {
if (shouldTruncate(content, maxLength)) {
return content.slice(0, maxLength) + '...';
} else {
return content;
}
};
const convertMarkdownToHtml = (markdown) => {
const rawHtml = marked(markdown);
return DOMPurify.sanitize(rawHtml)
};
const truncateMarkdownContent = (content, maxLength = 100) => {
const htmlContent = convertMarkdownToHtml(content);
return truncateContent(htmlContent, maxLength);
};
const formatDate = (datetime) => {
return new Date(datetime.date).toDateString()
}
onMounted(() => {
makeFetch('GET', '/api/1.0/main/news.json')
.then((response) => {
newsItems.value = response.results
})
.catch((error) => {
console.error('Error fetching news items', error);
})
})
</script>
<style scoped>
ul {
list-style: none;
padding: 0;
}
li {
margin-bottom: 20px;
overflow: hidden;
}
h2 {
margin-bottom: 10px;
}
.content {
max-height: 100px; /* Adjust the max height as needed */
overflow: hidden;
}
.scrollable {
overflow-y: auto;
max-height: 150px; /* Same as .content max-height */
margin-bottom: 10px; /* To give space for the scrollbar */
}
button {
cursor: pointer;
background-color: #3498db;
color: #fff;
border: none;
padding: 5px 10px;
border-radius: 3px;
}
.read-more {
color: #3498db; /* Adjust the color as needed */
cursor: pointer;
}
.news-date {
font-style: italic;
}
.news-title {
font-weight: bold;
text-transform: uppercase;
}
</style>