Skip to content

Commit

Permalink
Merge branch 'master' into issue-5700
Browse files Browse the repository at this point in the history
  • Loading branch information
ragesoss authored Jun 20, 2024
2 parents 56f3eac + f7aabc9 commit 626aa73
Show file tree
Hide file tree
Showing 291 changed files with 7,511 additions and 2,551 deletions.
6 changes: 4 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ Metrics/ClassLength:
- 'app/controllers/courses_controller.rb'
- 'app/controllers/users_controller.rb'
- 'app/controllers/assignments_controller.rb'
- 'lib/course_creation_manager.rb'
- 'lib/importers/revision_score_importer.rb'
- 'lib/wizard_timeline_manager.rb'
- 'lib/wiki_course_edits.rb'
- 'lib/training/wiki_slide_parser.rb'
- 'lib/wiki_assignment_output.rb'
- 'lib/course_training_progress_manager.rb'

Metrics/AbcSize:
Max: 23 # We should bring this down, ideally to the default of 15
Expand Down Expand Up @@ -85,6 +87,8 @@ Style/AsciiComments:
Enabled: false # We need non-ascii characters to document Wikipedia stuff.
Style/ParallelAssignment:
Enabled: false # We generally use this only to initialize empty variables.
Style/RedundantAssignment: # Same as Style/RedundantReturn, sometimes enhances clarity
Enabled: false
Style/RedundantReturn:
Enabled: false # Sometimes a redundant return enhances clarity.
Style/SymbolArray:
Expand Down Expand Up @@ -172,8 +176,6 @@ Style/OptionalBooleanParameter:
Enabled: false
Style/ExplicitBlockArgument:
Enabled: false
Style/RedundantAssignment:
Enabled: false
Style/KeywordParametersOrder:
Enabled: false
RSpec/StubbedMock:
Expand Down
9 changes: 9 additions & 0 deletions app/assets/images/check-grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions app/assets/images/check_green.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions app/assets/images/check_grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/images/clear-red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/assets/images/clear_red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/assets/images/discard-news.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions app/assets/images/discard-news_red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions app/assets/images/link-blue.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions app/assets/images/news_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions app/assets/images/news_icon_grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions app/assets/images/pencil-blue.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions app/assets/images/post-news.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions app/assets/images/post-news_blue.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/three-dots-vertical.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions app/assets/javascripts/actions/admin_course_notes_action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import API from '../utils/api';
import logErrorMessage from '../utils/log_error_message';
import { ADD_NOTIFICATION } from '../constants/notifications';

import {
RECEIVE_NOTES_LIST,
ADD_NEW_NOTE_TO_LIST,
DELETE_NOTE_FROM_LIST,
UPDATE_NOTES_LIST
} from '../constants';

// Helper function to dispatch notifications
const sendNotification = (dispatch, type, messageKey, dynamicValue) => {
const notificationConfig = {
message: I18n.t(messageKey, dynamicValue),
closable: true,
type: type === 'Success' ? 'success' : 'error',
};

dispatch({
type: ADD_NOTIFICATION,
notification: notificationConfig,
});
};

// Action creator to fetch all admin course notes for a given courseId
export const fetchAllAdminCourseNotes = courseId => async (dispatch) => {
try {
const notesList = await API.fetchAllAdminCourseNotes(courseId);
dispatch({ type: RECEIVE_NOTES_LIST, notes_list: notesList });
} catch (error) {
logErrorMessage('Error fetching course notes:', error);
}
};

// Action creator to save the updated/Edited admin course note to Database
export const saveUpdatedAdminCourseNote = adminCourseNoteDetails => async (dispatch, getState) => {
if ((adminCourseNoteDetails.title.trim().length === 0) || (adminCourseNoteDetails.text.trim().length === 0)) {
return sendNotification(dispatch, 'Error', 'notes.empty_fields');
}

const status = await API.saveUpdatedAdminCourseNote(adminCourseNoteDetails);

if (status?.success) {
sendNotification(dispatch, 'Success', 'notes.updated');

const updatedNotesList = getState().adminCourseNotes.notes_list.map((note) => {
if (note.id === adminCourseNoteDetails.id) {
return {
...note,
title: adminCourseNoteDetails.title,
text: adminCourseNoteDetails.text,
edited_by: status.admin_course_note.edited_by,
updated_at: status.admin_course_note.updated_at
};
}
return note;
});

dispatch({ type: UPDATE_NOTES_LIST, updatedNotesList: updatedNotesList });
} else {
const messageKey = 'notes.failure';
const dynamicValue = { operation: 'update' };
sendNotification(dispatch, 'Error', messageKey, dynamicValue);
}
};

// Action creator to create a new admin course note for a given courseId
export const createAdminCourseNote = (courseId, adminCourseNoteDetails) => async (dispatch) => {
if ((adminCourseNoteDetails.title.trim().length === 0) || (adminCourseNoteDetails.text.trim().length === 0)) {
return sendNotification(dispatch, 'Error', 'notes.empty_fields');
}

const noteDetails = await API.createAdminCourseNote(courseId, adminCourseNoteDetails);

if (noteDetails?.id) {
sendNotification(dispatch, 'Success', 'notes.created');
dispatch({ type: ADD_NEW_NOTE_TO_LIST, newNote: noteDetails });
} else {
const messageKey = 'notes.failure';
const dynamicValue = { operation: 'create' };
sendNotification(dispatch, 'Error', messageKey, dynamicValue);
}
};

// Action creator to delete a course note from the list based on its ID
export const deleteAdminNoteFromList = noteId => async (dispatch) => {
const status = await API.deleteAdminCourseNote(noteId);

if (status?.success) {
sendNotification(dispatch, 'Success', 'notes.deleted');
dispatch({ type: DELETE_NOTE_FROM_LIST, deletedNoteId: noteId });
} else {
sendNotification(dispatch, 'Error', 'notes.delete_note_error');
}
};
109 changes: 109 additions & 0 deletions app/assets/javascripts/actions/news_action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
RECEIVE_NEWS_CONTENT_LIST,
UPDATE_NEWS_CONTENT,
CANCEL_NEWS_UPDATE,
PERSIST_NEWS_CONTENT,
DELETE_NEWS_CONTENT,
CREATE_NEWS_CONTENT,
RESET_CREATE_NEWS_CONTENT,
ADD_NEWS_TO_LIST,
} from '../constants';
import logErrorMessage from '../utils/log_error_message';
import API from '../utils/api';
import { find } from 'lodash';

// Fetch all news content from the server
export const fetchAllNewsContent = () => async (dispatch) => {
try {
// Fetch the news content list from the API
const newsContentList = await API.fetchNews();

// Dispatch an action to store the fetched news content list in the Redux store
dispatch({ type: RECEIVE_NEWS_CONTENT_LIST, news_content_list: newsContentList });

return true;
} catch (error) {
// Log an error message if fetching fails
logErrorMessage('Error fetching news content:', error);
}
};

// Create or cache new news content
export const createNewsContent = (newsContent, post = false) => async (dispatch, getState) => {
if (post) {
try {
// If `post` is true, create news on the server
const newsDetails = await API.createNews(getState().news.create_news);
if (newsDetails?.id) {
// If the creation is successful, dispatch actions to add the new news to the list and persist the updated list
dispatch({ type: ADD_NEWS_TO_LIST, newNews: newsDetails });
dispatch({ type: PERSIST_NEWS_CONTENT, news_content_list: getState().news.news_content_list });
return newsDetails;
}
} catch (error) {
// Log an error message if fetching fails
logErrorMessage('Error creating news content:', error);
}
}
// If `post` is false, cache the new news content locally
dispatch({ type: CREATE_NEWS_CONTENT, content: newsContent });
};

// Cache edited news content locally
export const cacheNewsContentEdit = ({ content, id }) => (dispatch) => {
dispatch({ type: UPDATE_NEWS_CONTENT, news: { content, id } });
};

// Cancel editing of news content and revert to persisted state
export const cancelNewsContentEditing = () => (dispatch, getState) => {
// Get the persisted news content from the state
const newsContent = getState().persistedNews;
// Dispatch an action to cancel the update and revert to persisted news content
dispatch({ type: CANCEL_NEWS_UPDATE, news_content: newsContent });
};

// Save edited news content to the server
export const saveEditedNewsContent = (newsId = null) => async (dispatch, getState) => {
// Find the news item to be updated by its ID using lodash's `find` method
const newsItem = find(getState().news.news_content_list, { id: newsId });
const { id, content } = newsItem;

try {
// Call the API to update the news content on the server
const status = await API.updateNews({ id, content });

if (status?.id) {
// If the update is successful, dispatch an action to persist the updated list
dispatch({
type: PERSIST_NEWS_CONTENT,
news_content_list: getState().news.news_content_list
});
return status.id;
}
} catch (error) {
// Log an error message if fetching fails
logErrorMessage('Error fetching updating news content:', error);
}
};

// Delete selected news content
export const deleteSelectedNewsContent = newsId => async (dispatch, getState) => {
try {
// Call the API to delete the news content by its ID
const status = await API.deleteNews(newsId);

if (status.id === newsId) {
// If the deletion is successful, dispatch actions to remove the news from the list and persist the updated list
dispatch({ type: DELETE_NEWS_CONTENT, news_id: newsId });
dispatch({ type: PERSIST_NEWS_CONTENT, news_content_list: getState().news.news_content_list });
}
} catch (error) {
// Log an error message if fetching fails
logErrorMessage('Error fetching updating news content:', error);
}
};

// Reset the state related to creating news content
export const resetCreateNewsState = () => (dispatch) => {
dispatch({ type: RESET_CREATE_NEWS_CONTENT });
};
Loading

0 comments on commit 626aa73

Please sign in to comment.