Skip to content

Commit

Permalink
KURSP-926: add announcements link on the course page
Browse files Browse the repository at this point in the history
  • Loading branch information
ThereseRingPersen committed Nov 8, 2023
1 parent a2336d2 commit 11bda6f
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 26 deletions.
34 changes: 34 additions & 0 deletions src/js/modules/announcements/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import api from "../../api/api";

export async function getAllUnreadAnnouncementsForCourse() {
const courseId = api.getCurrentCourseId();
let totalUnread = 0;

try {
const announcements = await new Promise((resolve, reject) => {
api.getAnnouncementsForCourse(courseId, (announcements) => {
resolve(announcements);
}, reject);
});

announcements.forEach((announcement) => {
if (announcement.read_state === 'unread' || announcement.unread_count > 0) {
totalUnread++;
}
});

return {
url: `/courses/${courseId}/announcements`,
count: totalUnread,
};
} catch (error) {
// Handle any errors, e.g., invalid URLs or API failures
console.error('Error:', error);
return {
url: '',
count: 0,
};
}
}


1 change: 1 addition & 0 deletions src/js/modules/announcements/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getAllUnreadAnnouncementsForCourse } from './data'
43 changes: 43 additions & 0 deletions src/vue/components/announcements/Announcements-container.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<Announcements :count="data.count" :url="data.url" v-if="!loading" />
</template>

<script>
import { defineComponent, ref, onMounted } from 'vue';
import { getAllUnreadAnnouncementsForCourse } from '../../../js/modules/announcements/index'
import Announcements from './Announcements';
export default defineComponent({
name: 'AnnouncementsContainer',
setup() {
const data = ref({
url: '',
count: 0
});
const loading = ref(true);
onMounted(
async () => {
try {
const response = await getAllUnreadAnnouncementsForCourse();
data.value = {
url: response.url,
count: response.count
};
} catch (error) {
console.error('Error fetching data:', error);
} finally {
loading.value = false;
}
});
return {
data,
loading
};
},
components: {
Announcements
}
});
</script>
9 changes: 7 additions & 2 deletions src/vue/components/announcements/announcements.stories.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import Announcements from './announcements.vue';
import Announcements from './Announcements.vue';

export default {
title: 'Components/Announcements',
};

export const Default = () => ({
components: { Announcements },
template: '<Announcements :count="3" />',
template: '<Announcements :count="3" :url=" " />',
});

export const NoNewAnnouncements = () => ({
components: { Announcements },
template: '<Announcements :count="0" :url=" " />',
});
49 changes: 39 additions & 10 deletions src/vue/components/announcements/announcements.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
<template>
<a href="link-to-announcements" class="course-page-announcements__container">
<h3 class="course-page-announcements__title">
<Icon aria-hidden="true" class="announcements-icon" name="campaign" size="2em" />
<span>Kunngjøringer</span>
</h3>
<div class="course-page-announcements__count">{{ count }}</div>
</a>
<a :href="concatenatedUrl" class="course-page-announcements__container">
<h3 class="course-page-announcements__title">
<Icon aria-hidden="true" class="announcements-icon" name="campaign" size="2em" />
<span>Kunngjøringer</span>
</h3>
<div class="course-page-announcements__count" v-if="count > 0">{{ count }}</div>
</a>
</template>

<script setup>
import Icon from '../icon/Icon.vue'
const { props } = defineProps(['count']);
import Icon from '../icon/Icon.vue';
import { computed } from 'vue';
const props = defineProps({
count: Number,
url: String,
});
const concatenatedUrl = computed(() => {
try {
const currentLocation = window.location.href;
const baseUrlMatch = currentLocation.match(/^(https?:\/\/[^/]+)/);
const baseUrl = baseUrlMatch ? baseUrlMatch[1] : '';
return baseUrl + props.url;
} catch (error) {
// Handle any errors, e.g., invalid URLs
console.error('Error:', error);
// Use a default URL or an empty string if an error occurs
return '';
}
});
</script>





<style lang="scss">
@import '../../design/box-shadow';
@import '../../design/colors.scss';
Expand All @@ -33,6 +57,11 @@ const { props } = defineProps(['count']);
gap: 0.5rem;
background-color: map-get($color-palette-steel, background, 200);
@include box-shadow(medium);
margin: 0 1rem 1.25rem 1rem;
&:hover{
text-decoration: none;
color: $primary-hover-color;
}
}
&__title {
font-size: 1.125rem;
Expand All @@ -50,7 +79,7 @@ const { props } = defineProps(['count']);
justify-content: center;
align-items: center;
position: relative;
top: -0.25rem;
top: 0.065rem;
width: 1rem;
height: 1rem;
font-size: 0.875rem;
Expand Down
2 changes: 2 additions & 0 deletions src/vue/components/announcements/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import AnnouncementContainer from './Announcements-container.vue'
export default AnnouncementContainer
3 changes: 0 additions & 3 deletions src/vue/components/course-modules/CourseModuleContainer.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<template>
<CourseModules :nodes="data" v-if="!loading" />
</template>

<script>
import { defineComponent, ref, onMounted } from 'vue';
import { fetchModulesForCourse } from '../../../js/modules/module-selector/index.js';
Expand Down Expand Up @@ -35,5 +34,3 @@ export default defineComponent({
}
});
</script>


37 changes: 26 additions & 11 deletions src/vue/components/course-modules/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
// Import the necessary Vue and component
import { createApp } from "vue";
import CourseModuleContainer from "./CourseModuleContainer";

import AnnouncementsContainer from "../announcements/index";
import CourseModuleContainer from "./CourseModuleContainer";

export function renderCourseModules(id) {
// Create a Vue app instance
const app = createApp(CourseModuleContainer);
const appContainer = document.createElement('div');
appContainer.id= 'moduleSelector'
// Mount the Vue app to a specific HTML element with an ID
// Get the parent element
const parentElement = document.getElementById(id);
parentElement.insertBefore(appContainer, parentElement.firstChild);

// Mount the Vue app to the element
app.mount(appContainer);
// Create a Vue app instance for Announcements
const announcementsApp = createApp(AnnouncementsContainer);
const announcementsContainer = document.createElement("div");
announcementsContainer.id = "announcementsContainer";

// Create a Vue app instance for CourseModuleContainer
const courseModuleApp = createApp(CourseModuleContainer);
const courseModuleContainer = document.createElement("div");
courseModuleContainer.id = "moduleSelector";

// Mount the Announcements app to its container
announcementsApp.mount(announcementsContainer);

// Mount the CourseModuleContainer app to its container
courseModuleApp.mount(courseModuleContainer);

// Insert courseModuleContainer before any other content
parentElement.insertBefore(courseModuleContainer, parentElement.firstChild);

// Insert announcementsContainer before any other content
parentElement.insertBefore(announcementsContainer, parentElement.firstChild);


}




0 comments on commit 11bda6f

Please sign in to comment.