|
|
|
@ -4,28 +4,28 @@ |
|
|
|
|
<BaseButton |
|
|
|
|
:label="t('Add a link')" |
|
|
|
|
icon="link-add" |
|
|
|
|
class="mr-2 mb-2" |
|
|
|
|
class="mb-2 mr-2" |
|
|
|
|
type="black" |
|
|
|
|
@click="redirectToCreateLink" |
|
|
|
|
/> |
|
|
|
|
<BaseButton |
|
|
|
|
:label="t('Add a category')" |
|
|
|
|
icon="folder-plus" |
|
|
|
|
class="mr-2 mb-2" |
|
|
|
|
class="mb-2 mr-2" |
|
|
|
|
type="black" |
|
|
|
|
@click="redirectToCreateLinkCategory" |
|
|
|
|
/> |
|
|
|
|
<BaseButton |
|
|
|
|
:label="t('Export to PDF')" |
|
|
|
|
icon="file-pdf" |
|
|
|
|
class="mr-2 mb-2" |
|
|
|
|
class="mb-2 mr-2" |
|
|
|
|
type="black" |
|
|
|
|
@click="exportToPDF" |
|
|
|
|
/> |
|
|
|
|
<BaseButton |
|
|
|
|
:label="t('Switch to student view')" |
|
|
|
|
icon="eye-on" |
|
|
|
|
class="mr-2 mb-2" |
|
|
|
|
class="mb-2 mr-2" |
|
|
|
|
type="black" |
|
|
|
|
@click="toggleTeacherStudent" |
|
|
|
|
/> |
|
|
|
@ -51,11 +51,15 @@ |
|
|
|
|
<!-- Render the list of links --> |
|
|
|
|
<LinkCategoryCard v-if="linksWithoutCategory && linksWithoutCategory.length > 0"> |
|
|
|
|
<template #header> |
|
|
|
|
<h5>{{ t('General') }}</h5> |
|
|
|
|
<h5>{{ t("General") }}</h5> |
|
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
<ul> |
|
|
|
|
<li v-for="link in linksWithoutCategory" :key="link.id" class="mb-4"> |
|
|
|
|
<li |
|
|
|
|
v-for="link in linksWithoutCategory" |
|
|
|
|
:key="link.id" |
|
|
|
|
class="mb-4" |
|
|
|
|
> |
|
|
|
|
<LinkItem |
|
|
|
|
:link="link" |
|
|
|
|
@check="checkLink(link.iid, link.url)" |
|
|
|
@ -69,12 +73,18 @@ |
|
|
|
|
</ul> |
|
|
|
|
</LinkCategoryCard> |
|
|
|
|
|
|
|
|
|
<LinkCategoryCard v-for="category in categories" :key="category.info.id"> |
|
|
|
|
|
|
|
|
|
<LinkCategoryCard |
|
|
|
|
v-for="category in categories" |
|
|
|
|
:key="category.info.id" |
|
|
|
|
> |
|
|
|
|
<template #header> |
|
|
|
|
<div class="flex justify-between"> |
|
|
|
|
<div class="flex items-center"> |
|
|
|
|
<BaseIcon class="mr-2" icon="folder-generic" size="big"/> |
|
|
|
|
<BaseIcon |
|
|
|
|
class="mr-2" |
|
|
|
|
icon="folder-generic" |
|
|
|
|
size="big" |
|
|
|
|
/> |
|
|
|
|
<h5>{{ category.info.name }}</h5> |
|
|
|
|
</div> |
|
|
|
|
<div class="flex gap-2"> |
|
|
|
@ -105,7 +115,10 @@ |
|
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
<ul> |
|
|
|
|
<li v-for="link in category.links" :key="link.id"> |
|
|
|
|
<li |
|
|
|
|
v-for="link in category.links" |
|
|
|
|
:key="link.id" |
|
|
|
|
> |
|
|
|
|
<LinkItem |
|
|
|
|
:link="link" |
|
|
|
|
@check="checkLink(link.iid, link.url)" |
|
|
|
@ -118,7 +131,7 @@ |
|
|
|
|
</li> |
|
|
|
|
</ul> |
|
|
|
|
<p v-if="!category.links || category.links === 0"> |
|
|
|
|
{{ t('There are no links in this category') }} |
|
|
|
|
{{ t("There are no links in this category") }} |
|
|
|
|
</p> |
|
|
|
|
</LinkCategoryCard> |
|
|
|
|
</div> |
|
|
|
@ -126,60 +139,59 @@ |
|
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
<script setup> |
|
|
|
|
import EmptyState from "../../components/EmptyState.vue"; |
|
|
|
|
import BaseButton from "../../components/basecomponents/BaseButton.vue"; |
|
|
|
|
import ButtonToolbar from "../../components/basecomponents/ButtonToolbar.vue"; |
|
|
|
|
import {computed, onMounted, ref} from "vue"; |
|
|
|
|
import {useStore} from "vuex"; |
|
|
|
|
import {useRoute, useRouter} from "vue-router"; |
|
|
|
|
import {useI18n} from "vue-i18n"; |
|
|
|
|
import BaseIcon from "../../components/basecomponents/BaseIcon.vue"; |
|
|
|
|
import LinkItem from "../../components/links/LinkItem.vue"; |
|
|
|
|
import {useNotification} from "../../composables/notification"; |
|
|
|
|
import LinkCategoryCard from "../../components/links/LinkCategoryCard.vue"; |
|
|
|
|
import linkService from "../../services/linkService"; |
|
|
|
|
import EmptyState from "../../components/EmptyState.vue" |
|
|
|
|
import BaseButton from "../../components/basecomponents/BaseButton.vue" |
|
|
|
|
import ButtonToolbar from "../../components/basecomponents/ButtonToolbar.vue" |
|
|
|
|
import { computed, onMounted, ref } from "vue" |
|
|
|
|
import { useStore } from "vuex" |
|
|
|
|
import { useRoute, useRouter } from "vue-router" |
|
|
|
|
import { useI18n } from "vue-i18n" |
|
|
|
|
import BaseIcon from "../../components/basecomponents/BaseIcon.vue" |
|
|
|
|
import LinkItem from "../../components/links/LinkItem.vue" |
|
|
|
|
import { useNotification } from "../../composables/notification" |
|
|
|
|
import LinkCategoryCard from "../../components/links/LinkCategoryCard.vue" |
|
|
|
|
import linkService from "../../services/linkService" |
|
|
|
|
|
|
|
|
|
const store = useStore(); |
|
|
|
|
const route = useRoute(); |
|
|
|
|
const router = useRouter(); |
|
|
|
|
const store = useStore() |
|
|
|
|
const route = useRoute() |
|
|
|
|
const router = useRouter() |
|
|
|
|
|
|
|
|
|
const {t} = useI18n(); |
|
|
|
|
const { t } = useI18n() |
|
|
|
|
|
|
|
|
|
const notifications = useNotification() |
|
|
|
|
|
|
|
|
|
const isAuthenticated = computed(() => store.getters["security/isAuthenticated"]); |
|
|
|
|
const isCurrentTeacher = computed(() => store.getters["security/isCurrentTeacher"]); |
|
|
|
|
const isAuthenticated = computed(() => store.getters["security/isAuthenticated"]) |
|
|
|
|
const isCurrentTeacher = computed(() => store.getters["security/isCurrentTeacher"]) |
|
|
|
|
|
|
|
|
|
const linksWithoutCategory = ref([]); |
|
|
|
|
const categories = ref([]); |
|
|
|
|
const linksWithoutCategory = ref([]) |
|
|
|
|
const categories = ref([]) |
|
|
|
|
|
|
|
|
|
const selectedLink = ref(null); |
|
|
|
|
const selectedCategory = ref(null); |
|
|
|
|
const selectedLink = ref(null) |
|
|
|
|
const selectedCategory = ref(null) |
|
|
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
|
linksWithoutCategory.value = []; |
|
|
|
|
categories.value = []; |
|
|
|
|
linksWithoutCategory.value = [] |
|
|
|
|
categories.value = [] |
|
|
|
|
fetchLinks() |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
function editLink(link) { |
|
|
|
|
selectedLink.value = {...link}; |
|
|
|
|
selectedLink.value = { ...link } |
|
|
|
|
router.push({ |
|
|
|
|
name: "UpdateLink", |
|
|
|
|
params: {id: link.iid}, |
|
|
|
|
params: { id: link.iid }, |
|
|
|
|
query: route.query, |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function deleteLink(id) { |
|
|
|
|
try { |
|
|
|
|
await linkService.deleteLink(id) |
|
|
|
|
notifications.showSuccessNotification(t('Link deleted')) |
|
|
|
|
notifications.showSuccessNotification(t("Link deleted")) |
|
|
|
|
fetchLinks() |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error('Error deleting link:', error); |
|
|
|
|
notifications.showErrorNotification(t('Could not delete link')) |
|
|
|
|
console.error("Error deleting link:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not delete link")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -189,45 +201,45 @@ function checkLink(id, url) { |
|
|
|
|
|
|
|
|
|
async function toggleVisibility(link) { |
|
|
|
|
try { |
|
|
|
|
const makeVisible = !link.visible; |
|
|
|
|
const makeVisible = !link.visible |
|
|
|
|
await linkService.toggleLinkVisibility(link.iid, makeVisible) |
|
|
|
|
notifications.showSuccessNotification(t('Link visibility updated')) |
|
|
|
|
notifications.showSuccessNotification(t("Link visibility updated")) |
|
|
|
|
fetchLinks() |
|
|
|
|
linksWithoutCategory.value.forEach((item) => { |
|
|
|
|
if (item.iid === link.iid) { |
|
|
|
|
item.linkVisible = !item.linkVisible; |
|
|
|
|
item.linkVisible = !item.linkVisible |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error('Error deleting link:', error); |
|
|
|
|
notifications.showErrorNotification(t('Could not change visibility of link')) |
|
|
|
|
console.error("Error deleting link:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not change visibility of link")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function moveUp(id, position) { |
|
|
|
|
let newPosition = parseInt(position) - 1; |
|
|
|
|
let newPosition = parseInt(position) - 1 |
|
|
|
|
if (newPosition < 0) { |
|
|
|
|
newPosition = 0; |
|
|
|
|
newPosition = 0 |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
await linkService.moveLink(id, newPosition) |
|
|
|
|
notifications.showSuccessNotification(t('Link moved up')) |
|
|
|
|
notifications.showSuccessNotification(t("Link moved up")) |
|
|
|
|
fetchLinks() |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error("Error moving link up:", error); |
|
|
|
|
notifications.showErrorNotification(t('Could not moved link up')) |
|
|
|
|
console.error("Error moving link up:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not moved link up")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function moveDown(id, position) { |
|
|
|
|
const newPosition = parseInt(position) + 1; |
|
|
|
|
const newPosition = parseInt(position) + 1 |
|
|
|
|
try { |
|
|
|
|
await linkService.moveLink(id, newPosition) |
|
|
|
|
notifications.showSuccessNotification(t('Link moved down')) |
|
|
|
|
notifications.showSuccessNotification(t("Link moved down")) |
|
|
|
|
fetchLinks() |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error("Error moving link down:", error); |
|
|
|
|
notifications.showErrorNotification(t('Could not moved link down')) |
|
|
|
|
console.error("Error moving link down:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not moved link down")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -235,33 +247,33 @@ function redirectToCreateLink() { |
|
|
|
|
router.push({ |
|
|
|
|
name: "CreateLink", |
|
|
|
|
query: route.query, |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function redirectToCreateLinkCategory() { |
|
|
|
|
router.push({ |
|
|
|
|
name: "CreateLinkCategory", |
|
|
|
|
query: route.query, |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function editCategory(category) { |
|
|
|
|
selectedCategory.value = {...category}; |
|
|
|
|
selectedCategory.value = { ...category } |
|
|
|
|
router.push({ |
|
|
|
|
name: "UpdateLinkCategory", |
|
|
|
|
params: {id: category.info.id}, |
|
|
|
|
params: { id: category.info.id }, |
|
|
|
|
query: route.query, |
|
|
|
|
}); |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function deleteCategory(category) { |
|
|
|
|
try { |
|
|
|
|
await linkService.deleteCategory(category.info.id) |
|
|
|
|
notifications.showSuccessNotification(t('Category deleted')) |
|
|
|
|
notifications.showSuccessNotification(t("Category deleted")) |
|
|
|
|
fetchLinks() |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error('Error deleting category:', error); |
|
|
|
|
notifications.showErrorNotification(t('Could not delete category')) |
|
|
|
|
console.error("Error deleting category:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not delete category")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -269,11 +281,11 @@ async function toggleCategoryVisibility(category) { |
|
|
|
|
const makeVisible = !category.info.visible |
|
|
|
|
try { |
|
|
|
|
const updatedLinkCategory = await linkService.toggleCategoryVisibility(category.info.id, makeVisible) |
|
|
|
|
category.info.visible = updatedLinkCategory.linkCategoryVisible; |
|
|
|
|
notifications.showSuccessNotification(t('Visibility of category changed')) |
|
|
|
|
category.info.visible = updatedLinkCategory.linkCategoryVisible |
|
|
|
|
notifications.showSuccessNotification(t("Visibility of category changed")) |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error('Error updating link visibility:', error) |
|
|
|
|
notifications.showErrorNotification(t('Could not change visibility of category')) |
|
|
|
|
console.error("Error updating link visibility:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not change visibility of category")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -287,18 +299,18 @@ function toggleTeacherStudent() { |
|
|
|
|
|
|
|
|
|
async function fetchLinks() { |
|
|
|
|
const params = { |
|
|
|
|
'resourceNode.parent': route.query.parent || null, |
|
|
|
|
'cid': route.query.cid || null, |
|
|
|
|
'sid': route.query.sid || null |
|
|
|
|
}; |
|
|
|
|
"resourceNode.parent": route.query.parent || null, |
|
|
|
|
cid: route.query.cid || null, |
|
|
|
|
sid: route.query.sid || null, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
const data = await linkService.getLinks(params) |
|
|
|
|
linksWithoutCategory.value = data.linksWithoutCategory; |
|
|
|
|
categories.value = data.categories; |
|
|
|
|
linksWithoutCategory.value = data.linksWithoutCategory |
|
|
|
|
categories.value = data.categories |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error('Error fetching links:', error); |
|
|
|
|
notifications.showErrorNotification(t('Could not retrieve links')) |
|
|
|
|
console.error("Error fetching links:", error) |
|
|
|
|
notifications.showErrorNotification(t("Could not retrieve links")) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
</script> |
|
|
|
|