feat: multi language support (#254)

* feat: multitranslational support

* - completion of settings page
- completion of sidebar

* sidebar rerendering bug fix

* completion of the lesson navigation & materials page

* completion of the course navigation

* completion of requested languages

* - Implementation of Language Picker
- Rename Bug Fixes

* checkpoint save

* - addition of the language picker to the onboarding.
- addition of the language switcher for the lesson notes.

* merge completion

* initialization of the new branch

* add transition.svelte file

* lesson note bug fix

* feat: add translation migration

* completion of translation

* fix height issue of dropdown

* refactoring

* fix: improve code with LOCALE from db

* finally get it fully functional

* connect with AI

* backward compatibility for lesson note

* preserve old content, when generating AI content

* undo translations in upgrade modal

* fix duplicate key issue from codacy trigger

---------

Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
Adeyemi Adetunji
2024-04-19 05:45:48 +01:00
committed by GitHub
co-authored by Rotimi Best
parent ff7d2cee35
commit d75e2f258e
153 changed files with 11264 additions and 1130 deletions
@@ -30,6 +30,8 @@
triggerSendEmail
} from '$lib/utils/services/notification/notification';
import NewsFeedLoader from '$lib/components/Course/components/NewsFeed/NewsFeedLoader.svelte';
import { t } from '$lib/utils/functions/translations.js';
export let data;
let createdComment;
@@ -65,7 +67,7 @@
comment: feed.comment.filter((comment) => comment.id !== id)
}));
return snackbar.success('Comment Deleted');
return snackbar.success('snackbar.course.success.comment_deleted');
};
const addNewReaction = async (reactionType: string, feedId: string, authorId: string) => {
@@ -98,7 +100,7 @@
.eq('id', feedId);
if (response.error) {
return snackbar.error('An error occurred while reacting to news feed');
return snackbar.error('snackbar.course.error.reaction_error');
}
$newsFeed = $newsFeed.map((feed) => {
@@ -118,7 +120,7 @@
});
if (response.error) {
return snackbar.error('An error occurred while creating comment');
return snackbar.error('snackbar.course.error.commenting_error');
}
if (!response.data) return;
@@ -142,7 +144,7 @@
content: comment
};
snackbar.success('Comment added');
snackbar.success('snackbar.course.success.comment_added');
return {
...feed,
@@ -159,12 +161,16 @@
const { response } = await toggleFeedIsPinned(feedId, newIsPinned);
if (response.error) {
return snackbar.error('Failed to toggle pinned feed');
return snackbar.error('snackbar.course.error.toggle_error');
}
$newsFeed = $newsFeed.map((feed) => {
if (feed.id === feedId) {
snackbar.success(`${newIsPinned ? 'Pinned' : 'Unpinned'} Successfully`);
snackbar.success(
`${
newIsPinned ? 'snackbar.course.success.pinned' : 'snackbar.course.success.unpinned'
} snackbar.course.success.successfully`
);
feed.isPinned = newIsPinned;
return feed;
@@ -178,7 +184,7 @@
deleteNewsFeed(id);
const deletedFeed = $newsFeed.filter((feed) => feed.id !== id);
snackbar.success('Feed deleted successfully');
snackbar.success('snackbar.course.success.feed_delete_success');
$newsFeed = deletedFeed;
};
@@ -189,7 +195,7 @@
isLoading = true;
const { data, error } = await fetchNewsFeeds(courseId);
if (error) {
snackbar.error('Failed to fetch news feeds');
snackbar.error('snackbar.course.error.news_feed_fail');
}
if (data) {
$newsFeed = data.map((feedItem) => ({
@@ -198,7 +204,7 @@
}));
}
} catch (error) {
snackbar.error('An error occured while fetching feed');
snackbar.error('snackbar.course.error.feed_fetch_error');
} finally {
isLoading = false;
}
@@ -223,10 +229,14 @@
</script>
<CourseContainer bind:courseId={data.courseId}>
<PageNav title="News Feed" disableSticky={true}>
<PageNav title={$t('course.navItem.news_feed.heading')} disableSticky={true}>
<slot:fragment slot="widget">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<PrimaryButton className="mr-2" label="Add" onClick={() => ($isNewFeedModal.open = true)} />
<PrimaryButton
className="mr-2"
label={$t('course.navItem.news_feed.heading_button.title')}
onClick={() => ($isNewFeedModal.open = true)}
/>
</RoleBasedSecurity>
</slot:fragment>
</PageNav>
@@ -254,9 +264,9 @@
<Box>
<div class="flex justify-between flex-col items-center w-[90%] md:w-96">
<img src="/images/empty-lesson-icon.svg" alt="Lesson" class="my-2.5 mx-auto" />
<h2 class="text-xl my-1.5 font-normal">No post yet</h2>
<h2 class="text-xl my-1.5 font-normal">{$t('course.navItem.news_feed.body_header')}</h2>
<p class="text-sm text-center text-slate-500">
Make a post to your class. Start by clicking on the Add button.
{$t('course.navItem.news_feed.body_content')}
</p>
</div>
</Box>
@@ -266,7 +276,7 @@
<div class="flex items-center gap-2 mb-3">
<PinFilled size={16} />
<p class="text-sm">Pinned</p>
<p class="text-sm">{$t('course.navItem.news_feed.pinned')}</p>
</div>
{/if}
<NewsFeedCard