Skip to content

feat: enhance XBlock structure and update existing APIs#4

Merged
viv-helix merged 7 commits intomainfrom
feat/refactor_and_implement_save_API_functionality
Nov 21, 2025
Merged

feat: enhance XBlock structure and update existing APIs#4
viv-helix merged 7 commits intomainfrom
feat/refactor_and_implement_save_API_functionality

Conversation

@Faraz32123
Copy link
Copy Markdown
Contributor

In this commit,

  • Add save API functionality and made sure previous code is there. We'll use whats there or write new code accordingly, Will do cleansing in the end once its complete.

Previous related PR #3 where we removed old code(We can keep it for now and clean it in the end as some of that code is working).

Screen.Recording.2025-11-19.at.2.37.27.PM.mov

In this commit,
- Add save API functionality and made sure previous code is there. We'll use whats there or write new code accordingly, Will do cleansing in the end once its complete.

Co-authored-by: [Muhammad Faraz Maqsood] <fmaqsood@2u.com>
Co-authored-by: [Vivek Jagdishbhai Ambaliya] <vjagdishbhaiambaliya-apphelix@2u.com>
Copilot AI review requested due to automatic review settings November 19, 2025 09:41
@Faraz32123 Faraz32123 changed the title fix: recover previous code as well Feat: Add save API functionality Nov 19, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR aims to restore previously removed code while adding new save API functionality for the games XBlock. The changes include updating package metadata, adding image upload and settings persistence handlers, and renaming fields for consistency.

Key Changes

  • Added new API handlers (save_settings, get_settings, upload_image) for managing game configuration
  • Renamed type field to game_type and list to cards throughout the codebase for consistency
  • Updated package metadata in setup.py with proper versioning, dependencies, and entry points

Reviewed Changes

Copilot reviewed 10 out of 12 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
setup.py Updated package metadata, version to 1.0.0, added proper dependencies (XBlock, web-fragments, Django), and fixed entry point path
games/games.py Added new API handlers for saving settings and uploading images, renamed fields from type to game_type, introduced duplicate field and import issues
games/static/js/src/games.js Updated references from type to game_type, commented out timer update code, added new card loading/display functions
games/static/html/games.html Changed template variable from self.title to self.game_type
.gitignore Added patterns to ignore build artifacts (*.egg-info/, dist/, build/)
games_xblock.egg-info/* Removed generated egg-info files (should be gitignored)
.DS_Store Added macOS system file (should not be committed)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Comment thread games/games.py Outdated
Copilot AI review requested due to automatic review settings November 21, 2025 06:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 14 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread games/games.py
)

# Alias for cards - handlers.py uses 'list' field name
list = cards
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Field aliasing via assignment creates a reference to the default value rather than the field itself. This means xblock.list will always reference the empty list [] and won't reflect changes to xblock.cards. Use a property instead or update all handler references to use cards directly.

Suggested change
list = cards
@property
def list(self):
return self.cards

Copilot uses AI. Check for mistakes.
Comment thread games/handlers/common.py
}
"""
try:
new_game_type = data.get("game_type", GAME_TYPE.FLASHCARDS)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing validation for game_type input. The handler should validate that the provided game_type is one of the valid values defined in GAME_TYPE.VALID to prevent invalid game types from being saved.

Suggested change
new_game_type = data.get("game_type", GAME_TYPE.FLASHCARDS)
new_game_type = data.get("game_type", GAME_TYPE.FLASHCARDS)
if new_game_type not in GAME_TYPE.VALID:
return {
"success": False,
"error": f"Invalid game_type '{new_game_type}'. Must be one of: {', '.join(GAME_TYPE.VALID)}"
}

Copilot uses AI. Check for mistakes.
if (!data.cards || data.cards.length === 0) {
html = '<p class="no-cards">No cards available yet. Add cards in the Studio editor.</p>';
} else {
html += '<h3>Game Type: ' + data.game_type + '</h3>';
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential XSS vulnerability. User-controlled data data.game_type is directly concatenated into HTML without escaping. Use proper HTML escaping or DOM manipulation methods to prevent XSS attacks.

Copilot uses AI. Check for mistakes.
html += '<div class="card-number">Card ' + (index + 1) + '</div>';

if (card.term_image) {
html += '<div class="card-image"><img src="' + card.term_image + '" alt="Term image"></div>';
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential XSS vulnerability. The card.term_image URL is directly concatenated into HTML without validation or escaping. Malicious URLs could contain JavaScript. Similar issue exists for card.definition_image on line 587.

Copilot uses AI. Check for mistakes.
Comment on lines +569 to +597
var html = '';

if (!data.cards || data.cards.length === 0) {
html = '<p class="no-cards">No cards available yet. Add cards in the Studio editor.</p>';
} else {
html += '<h3>Game Type: ' + data.game_type + '</h3>';
html += '<div class="cards-list">';

data.cards.forEach(function(card, index) {
html += '<div class="card-item">';
html += '<div class="card-number">Card ' + (index + 1) + '</div>';

if (card.term_image) {
html += '<div class="card-image"><img src="' + card.term_image + '" alt="Term image"></div>';
}
html += '<div class="card-term"><strong>Term:</strong> ' + card.term + '</div>';

if (card.definition_image) {
html += '<div class="card-image"><img src="' + card.definition_image + '" alt="Definition image"></div>';
}
html += '<div class="card-definition"><strong>Definition:</strong> ' + card.definition + '</div>';

html += '</div>';
});

html += '</div>';
}

container.html(html);
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential XSS vulnerability. The card.term and card.definition (line 589) text content is directly concatenated into HTML without escaping. Use proper HTML escaping or text-safe DOM methods like textContent.

Suggested change
var html = '';
if (!data.cards || data.cards.length === 0) {
html = '<p class="no-cards">No cards available yet. Add cards in the Studio editor.</p>';
} else {
html += '<h3>Game Type: ' + data.game_type + '</h3>';
html += '<div class="cards-list">';
data.cards.forEach(function(card, index) {
html += '<div class="card-item">';
html += '<div class="card-number">Card ' + (index + 1) + '</div>';
if (card.term_image) {
html += '<div class="card-image"><img src="' + card.term_image + '" alt="Term image"></div>';
}
html += '<div class="card-term"><strong>Term:</strong> ' + card.term + '</div>';
if (card.definition_image) {
html += '<div class="card-image"><img src="' + card.definition_image + '" alt="Definition image"></div>';
}
html += '<div class="card-definition"><strong>Definition:</strong> ' + card.definition + '</div>';
html += '</div>';
});
html += '</div>';
}
container.html(html);
container.empty();
if (!data.cards || data.cards.length === 0) {
container.append($('<p class="no-cards">No cards available yet. Add cards in the Studio editor.</p>'));
} else {
container.append($('<h3>').text('Game Type: ' + data.game_type));
var cardsList = $('<div class="cards-list"></div>');
data.cards.forEach(function(card, index) {
var cardItem = $('<div class="card-item"></div>');
cardItem.append($('<div class="card-number"></div>').text('Card ' + (index + 1)));
if (card.term_image) {
cardItem.append($('<div class="card-image"></div>').append(
$('<img>').attr('src', card.term_image).attr('alt', 'Term image')
));
}
var cardTerm = $('<div class="card-term"></div>');
cardTerm.append($('<strong>').text('Term:'));
cardTerm.append(' ');
cardTerm.append(document.createTextNode(card.term));
cardItem.append(cardTerm);
if (card.definition_image) {
cardItem.append($('<div class="card-image"></div>').append(
$('<img>').attr('src', card.definition_image).attr('alt', 'Definition image')
));
}
var cardDef = $('<div class="card-definition"></div>');
cardDef.append($('<strong>').text('Definition:'));
cardDef.append(' ');
cardDef.append(document.createTextNode(card.definition));
cardItem.append(cardDef);
cardsList.append(cardItem);
});
container.append(cardsList);
}

Copilot uses AI. Check for mistakes.
Comment thread games/handlers/common.py
Comment on lines +104 to +108
validated_cards.append(
{
CARD_FIELD.TERM: card.get(CARD_FIELD.TERM, ""),
CARD_FIELD.TERM_IMAGE: card.get(CARD_FIELD.TERM_IMAGE, ""),
CARD_FIELD.DEFINITION: card.get(CARD_FIELD.DEFINITION, ""),
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty strings are used as defaults after validation confirms term and definition exist. This means if the validation passes but the values are empty strings, blank cards will be saved. Consider validating that term and definition are non-empty strings, not just present in the dictionary.

Suggested change
validated_cards.append(
{
CARD_FIELD.TERM: card.get(CARD_FIELD.TERM, ""),
CARD_FIELD.TERM_IMAGE: card.get(CARD_FIELD.TERM_IMAGE, ""),
CARD_FIELD.DEFINITION: card.get(CARD_FIELD.DEFINITION, ""),
# Ensure term and definition are non-empty strings
term = card.get(CARD_FIELD.TERM, "")
definition = card.get(CARD_FIELD.DEFINITION, "")
if not isinstance(term, str) or not term.strip():
return {
"success": False,
"error": "Each card's term must be a non-empty string",
}
if not isinstance(definition, str) or not definition.strip():
return {
"success": False,
"error": "Each card's definition must be a non-empty string",
}
validated_cards.append(
{
CARD_FIELD.TERM: term,
CARD_FIELD.TERM_IMAGE: card.get(CARD_FIELD.TERM_IMAGE, ""),
CARD_FIELD.DEFINITION: definition,

Copilot uses AI. Check for mistakes.
Comment thread games/games.py
Comment on lines 44 to 48
list_length = Integer(
default=len(list.default),
default=len(cards.default),
scope=Scope.content,
help="A field for the length of the list for convenience."
)

#Flashcard game fields------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
list_index = Integer(
default=0,
scope=Scope.settings,
help="Determines which flashcard from the list is currently visible."
help="A field for the length of the list for convenience.",
)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing list_length as a separate field creates a potential inconsistency where list_length could become out of sync with the actual length of cards. Consider using a property or computing this dynamically from len(self.cards) when needed.

Copilot uses AI. Check for mistakes.
});

return {};
// return {};
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Commented-out return statement suggests incomplete refactoring. The function should either return an object as before or the comment should be removed if the return is no longer needed.

Suggested change
// return {};

Copilot uses AI. Check for mistakes.
Comment thread games/handlers/common.py
Comment on lines +65 to +66
except Exception as e:
return Response(json_body={"success": False, "error": str(e)}, status=400)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exposing raw exception messages to clients can leak sensitive implementation details. Consider logging the full exception and returning a generic error message to the client, or at least sanitize the error message.

Copilot uses AI. Check for mistakes.
Comment thread games/handlers/common.py
Comment on lines +127 to +128
except Exception as e:
return {"success": False, "error": str(e)}
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exposing raw exception messages can leak sensitive implementation details. Consider logging the exception and returning a sanitized error message. Similar issue to upload_image handler.

Copilot uses AI. Check for mistakes.
@viv-helix viv-helix changed the title Feat: Add save API functionality feat: enhance XBlock structure and update existing APIs Nov 21, 2025
@viv-helix viv-helix merged commit 68dae13 into main Nov 21, 2025
7 checks passed
@papphelix papphelix deleted the feat/refactor_and_implement_save_API_functionality branch November 21, 2025 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants