mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-05 07:19:49 +00:00
138 lines
3.3 KiB
Vue
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>
|