<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tjbrown8</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tjbrown8"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Tjbrown8"/>
	<updated>2026-07-21T07:40:27Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2560._Framework_for_Import_and_Export&amp;diff=167420</id>
		<title>CSC/ECE 517 Fall 2025 - E2560. Framework for Import and Export</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2560._Framework_for_Import_and_Export&amp;diff=167420"/>
		<updated>2025-12-03T07:08:46Z</updated>

		<summary type="html">&lt;p&gt;Tjbrown8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The export/import functionality is one of the most valuable tools for instructors when setting up assignments in Expertiza. Instructors often have lists of students, teams, and other data from their learning management systems. The ability to seamlessly export and import this data into Expertiza significantly reduces setup time and effort.&lt;br /&gt;
&lt;br /&gt;
* '''Import Functionality Video''' — https://youtu.be/OYMAJIws0gI&lt;br /&gt;
* '''Export Functionality Video''' — https://youtu.be/vhzYiPaoAK8&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The previous version of Expertiza offered multiple export and import features—for example, exporting students, teams, rubrics, topics, and more. These features typically retrieve data from the database and save it in a specified format. However, the same logic is often duplicated across different implementations for various data types.&lt;br /&gt;
&lt;br /&gt;
The goal of this project is to design and implement a generic export/import framework that can handle various types of data based on input parameters. You will create a module that accepts database table names and column names to determine what data should be exported or imported. This module should be flexible and reusable across all export/import features in Expertiza.&lt;br /&gt;
&lt;br /&gt;
== Design Document ==&lt;br /&gt;
=== Class Diagram ===&lt;br /&gt;
[[File:CSC517Final_4.png|1200px]]&lt;br /&gt;
&lt;br /&gt;
==== Architecture ====&lt;br /&gt;
The system is divided into two main layers:&lt;br /&gt;
&lt;br /&gt;
* '''Backend''' — Handles import/export logic, data validation, and duplicate record management.&lt;br /&gt;
* '''Frontend''' — Provides user interfaces for triggering imports and exports, communicating with backend controllers.&lt;br /&gt;
----&lt;br /&gt;
==== Backend Components ====&lt;br /&gt;
&lt;br /&gt;
===== FieldMapping =====&lt;br /&gt;
Represents the relationship between class fields and their corresponding data columns.&lt;br /&gt;
* '''''Attributes:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;class: Class&amp;lt;/code&amp;gt; — The associated class for data mapping.&lt;br /&gt;
** &amp;lt;code&amp;gt;ordered_fields: Array[String]&amp;lt;/code&amp;gt; — Field order for import/export operations.&lt;br /&gt;
&lt;br /&gt;
===== DuplicateAction (Mixin) =====&lt;br /&gt;
Defines actions to take when duplicate records are detected.&lt;br /&gt;
* '''''Attributes'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;name: String&amp;lt;/code&amp;gt; — Name of the duplicate action.&lt;br /&gt;
* '''''Methods:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;on_duplicate_record()&amp;lt;/code&amp;gt; — Handles logic when a duplicate record is found.&lt;br /&gt;
&lt;br /&gt;
===== ImportableExportable (Mixin) =====&lt;br /&gt;
Provides shared functionality for classes that can be imported or exported.&lt;br /&gt;
* '''''Attributes:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;mandatory_fields: Array[String]&amp;lt;/code&amp;gt; — Fields required for processing.&lt;br /&gt;
** &amp;lt;code&amp;gt;optional_fields: Array[String]&amp;lt;/code&amp;gt; — Fields that can optionally be included.&lt;br /&gt;
** &amp;lt;code&amp;gt;available_duplicate_actions: Array[DuplicateAction]&amp;lt;/code&amp;gt; — List of supported duplicate handling strategies.&lt;br /&gt;
* '''''Methods:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;register_detail(class, field: String)&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;try_insert_record(DuplicateAction)&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;is_duplicate_record()&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;get_detail_field(record, detail_class, detail_field: String)&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;to_hash()&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== ImportExportManager =====&lt;br /&gt;
Acts as the central interface for managing import and export workflows.&lt;br /&gt;
* '''''Methods:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;export(class, mapping: FieldMapping, filename: String)&amp;lt;/code&amp;gt; — Exports class data based on mapping.&lt;br /&gt;
** &amp;lt;code&amp;gt;import(class, mapping: FieldMapping, filename: String, use_header: bool)&amp;lt;/code&amp;gt; — Imports data into the specified class.&lt;br /&gt;
** &amp;lt;code&amp;gt;default_mapping(class)&amp;lt;/code&amp;gt; — Retrieves the default mapping configuration.&lt;br /&gt;
** &amp;lt;code&amp;gt;suggest_filename(class, mode: String)&amp;lt;/code&amp;gt; — Suggests a filename based on class and mode.&lt;br /&gt;
&lt;br /&gt;
===== ImportController =====&lt;br /&gt;
Handles import-related HTTP requests.&lt;br /&gt;
* '''''Endpoints:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;index&amp;lt;/code&amp;gt; — Returns import configuration data.&lt;br /&gt;
** &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt; — Accepts incoming data and triggers import operations.&lt;br /&gt;
* '''''Interactions:'''''&lt;br /&gt;
** Sends mandatory and optional fields, as well as available duplicate actions, to the frontend.&lt;br /&gt;
** Receives chosen ordered fields and duplicate action from the frontend.&lt;br /&gt;
&lt;br /&gt;
===== ExportController =====&lt;br /&gt;
Handles export-related HTTP requests.&lt;br /&gt;
* '''''Endpoints:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;index&amp;lt;/code&amp;gt; — Provides available export configurations.&lt;br /&gt;
** &amp;lt;code&amp;gt;export&amp;lt;/code&amp;gt; — Generates export files based on selected parameters.&lt;br /&gt;
* '''''Interactions:'''''&lt;br /&gt;
** Sends mandatory and optional fields to the frontend.&lt;br /&gt;
** Receives chosen ordered fields for export.&lt;br /&gt;
----&lt;br /&gt;
==== Frontend Components ====&lt;br /&gt;
&lt;br /&gt;
===== Import (.tsx) =====&lt;br /&gt;
* '''''Methods:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;on_import&amp;lt;/code&amp;gt; — Initiates the import process.&lt;br /&gt;
* '''''Interactions:'''''&lt;br /&gt;
** Receives mandatory/optional field data and duplicate actions.&lt;br /&gt;
** Sends selected ordered fields and chosen duplicate handling action back to the backend.&lt;br /&gt;
&lt;br /&gt;
===== Export (.tsx) =====&lt;br /&gt;
* '''''Methods:'''''&lt;br /&gt;
** &amp;lt;code&amp;gt;on_export&amp;lt;/code&amp;gt; — Initiates the export process.&lt;br /&gt;
* '''''Interactions:'''''&lt;br /&gt;
** Receives mandatory/optional field data from backend.&lt;br /&gt;
** Sends selected ordered fields for export.&lt;br /&gt;
----&lt;br /&gt;
==== Data Flow ====&lt;br /&gt;
&lt;br /&gt;
===== Import Sequence =====&lt;br /&gt;
# Frontend requests import configuration.&lt;br /&gt;
# Backend responds with mandatory/optional fields and duplicate actions.&lt;br /&gt;
# User selects ordered fields and a duplicate action.&lt;br /&gt;
# Frontend sends selections to backend for processing via &amp;lt;code&amp;gt;ImportController.import&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Export Sequence =====&lt;br /&gt;
# Frontend requests export configuration.&lt;br /&gt;
# Backend sends available fields.&lt;br /&gt;
# User selects ordered fields to include.&lt;br /&gt;
# Frontend sends selections to backend via &amp;lt;code&amp;gt;ExportController.export&amp;lt;/code&amp;gt;.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram ===&lt;br /&gt;
[[File:CSC517FinalUseCases_2.png]]&lt;br /&gt;
&lt;br /&gt;
==== Primary Actor ====&lt;br /&gt;
&lt;br /&gt;
'''Instructor / Administrator'''&lt;br /&gt;
* Initiates both import and export operations for any class (e.g., Users, Teams, Rubrics).&lt;br /&gt;
* Goal is to efficiently transfer data into or out of the system without requiring separate tools for each entity.&lt;br /&gt;
&lt;br /&gt;
==== Use Cases ====&lt;br /&gt;
&lt;br /&gt;
===== Main Use Cases =====&lt;br /&gt;
&lt;br /&gt;
;Import data for any class from a CSV file&lt;br /&gt;
# The actor uploads a CSV file.&lt;br /&gt;
# The system reads available headers or prompts the actor to select them.&lt;br /&gt;
# The actor confirms header order and selects a duplicate-handling option.&lt;br /&gt;
# The system validates data and imports records according to the selected duplicate policy.&lt;br /&gt;
&lt;br /&gt;
;Export data for any class to a CSV file&lt;br /&gt;
# The actor selects which fields to include.&lt;br /&gt;
# The actor orders these fields as desired.&lt;br /&gt;
# The system generates a downloadable CSV file containing the chosen data.&lt;br /&gt;
&lt;br /&gt;
===== Included Use Cases =====&lt;br /&gt;
&lt;br /&gt;
;Choose/Auto Read Headers Included in the File&lt;br /&gt;
* When importing, the system attempts to automatically detect headers from the uploaded CSV.&lt;br /&gt;
* If headers are missing or unclear, the actor manually specifies them.&lt;br /&gt;
&lt;br /&gt;
;Choose the Order of the Headers&lt;br /&gt;
* Applies to both import and export operations.&lt;br /&gt;
* The actor arranges the order of headers to ensure correct mapping between CSV columns and database fields.&lt;br /&gt;
&lt;br /&gt;
;Choose Headers that will be Included in the File&lt;br /&gt;
* Applies primarily to export operations.&lt;br /&gt;
* The actor selects specific headers to include in the output CSV file, ensuring only relevant data is exported.&lt;br /&gt;
&lt;br /&gt;
==== Relationships ====&lt;br /&gt;
&lt;br /&gt;
* Both the '''Import''' and '''Export''' use cases include the sub-use cases for choosing headers and their order.&lt;br /&gt;
* The actor directly initiates the primary use cases and indirectly interacts with the included ones through system prompts.&lt;br /&gt;
&lt;br /&gt;
==== System Responsibilities ====&lt;br /&gt;
&lt;br /&gt;
* Provide the actor with available class fields and supported duplicate actions.&lt;br /&gt;
* Manage CSV validation, field mapping, and record processing.&lt;br /&gt;
* Generate clear feedback on import/export results (e.g., success, skipped, or error entries).&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== Design Notes ====&lt;br /&gt;
The design emphasizes modularity and extensibility because the same flow supports multiple data entities using a unified import/export framework. &lt;br /&gt;
* Included use cases ensure flexibility for various file structures and actor preferences.&lt;br /&gt;
* Error handling (e.g., missing headers, duplicate data) is encapsulated within the main import process.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Creating CSV for Importing===&lt;br /&gt;
----&lt;br /&gt;
When creating a CSV that will be imported, there are a few guidelines that should be followed to ensure information is uploaded successfully.&lt;br /&gt;
&lt;br /&gt;
;Guidelines&lt;br /&gt;
# CSV should be made with headers that names align with the fields in the program. The names should be in Capital case (ie Name, User id, Txt, etc). These need to align with the program version of the fields (ie. name, user_id, txt) because they will be converted programmatically.&lt;br /&gt;
# CSV must include all mandatory fields and necessary external fields. Optional fields may be included as well. To find these, check the import page for the item you are trying to import. &lt;br /&gt;
# For Headers that refer to an external class, the class name should be appended to the front of the field. (ex. If a user is trying to reference a Role by its name field, the header should be &amp;quot;Role name&amp;quot;, not &amp;quot;name&amp;quot;). &lt;br /&gt;
# For CSVs that contain Duplicate Headers for External classes (Ex. Items and QuestionAdvice), make sure the external class appears in the CSV grouped together and in sequence.&lt;br /&gt;
&lt;br /&gt;
=== Importing a File ===&lt;br /&gt;
----&lt;br /&gt;
The Import Modal is a reusable modal used to upload CSV files for different models (Items, Teams, Users, Assignments, etc.).&lt;br /&gt;
----&lt;br /&gt;
; Opening the Import Modal&lt;br /&gt;
:* From the relevant page (e.g., Items index), click the Import button. This opens the Import &amp;lt;ModelName&amp;gt; modal.&lt;br /&gt;
:* As soon as the modal opens, the frontend automatically calls:&lt;br /&gt;
:*: GET /import/&amp;lt;modelClass&amp;gt; to fetch import metadata for that model. This metadata is what populates the lists at the top of the modal.&lt;br /&gt;
; Field Requirements&lt;br /&gt;
:* At the top of the modal you’ll see three lists: &lt;br /&gt;
:# Mandatory fields – columns that must be present in your import for it to succeed.&lt;br /&gt;
:# Optional fields – extra columns you may include if you have that data.&lt;br /&gt;
:# External fields – related fields that can be pulled from or linked to other records (e.g., questionnaire_name, question_advice_id, etc.)&lt;br /&gt;
:* These lists are read-only and meant to guide how you structure your CSV.&lt;br /&gt;
[[File:ImportFrontend.png|600px]]&lt;br /&gt;
; Selecting a CSV&lt;br /&gt;
:* Under CSV file:&lt;br /&gt;
:# Click Choose File and select your .csv file.&lt;br /&gt;
:# Decide whether your file’s first row is a header row:&lt;br /&gt;
:#* First row contains headers (switch ON)&lt;br /&gt;
:#** Use this if your first row has column names like txt, weight, seq.&lt;br /&gt;
:#** The backend will match CSV headers to field names automatically.&lt;br /&gt;
:#* First row contains headers (switch OFF)&lt;br /&gt;
:#** Use this if your file has no header row (just data).&lt;br /&gt;
[[File:UploadFile.png|600px]]&lt;br /&gt;
; Manual Column Mapping&lt;br /&gt;
:* If “First row contains headers” is OFF, the modal:&lt;br /&gt;
:** Reads the first one or two lines from your CSV.&lt;br /&gt;
:** For each column, shows:&lt;br /&gt;
:*** A dropdown to choose which field this column represents.&lt;br /&gt;
:*** A “First Row Value” snippet so you can see an example value from that column.&lt;br /&gt;
:* You must:&lt;br /&gt;
:*# Go through each column.&lt;br /&gt;
:*# Use the dropdown to select the corresponding field name (e.g., map column 1 → txt, column 2 → weight, etc.).&lt;br /&gt;
:*# Ensure that all mandatory fields appear in at least one column.&lt;br /&gt;
:** If mandatory fields are missing from your selection, the modal will block the import and show a status message.&lt;br /&gt;
[[File:ColumnMapping.png|600px]]&lt;br /&gt;
; Handling Duplicates&lt;br /&gt;
:* In the Duplicate handling section:&lt;br /&gt;
:** If the backend has configured options, you’ll see one or more radio buttons (e.g., skip, overwrite).&lt;br /&gt;
:** Choose how the system should behave if it encounters duplicate records during the import.&lt;br /&gt;
:* If no duplicate options are available, you’ll see: “No duplicate options.”&lt;br /&gt;
; Running the Import&lt;br /&gt;
:* When everything is set:&lt;br /&gt;
:*# Click &amp;quot;import&amp;quot;&lt;br /&gt;
:*# The frontend sends a POST /import/&amp;lt;modelClass&amp;gt; request with:&lt;br /&gt;
:*#* csv_file – the file you selected.&lt;br /&gt;
:*#* use_headers – true or false depending on the toggle.&lt;br /&gt;
:*#* ordered_fields – only included if header mode is off, listing the fields you selected for each column.&lt;br /&gt;
:* While the request is in progress, the modal shows a loading state.&lt;br /&gt;
:* When the response returns, the Status line at the bottom will show either:&lt;br /&gt;
:** A success message from the backend (e.g., “Import complete” or a custom message)&lt;br /&gt;
:** An error message if something went wrong (e.g., missing mandatory fields, invalid format)&lt;br /&gt;
:* You can then close the modal with cancel or by using the close icon.&lt;br /&gt;
[[File:ImportComplete.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=== Exporting a File ===&lt;br /&gt;
----&lt;br /&gt;
; Opening the Export Modal&lt;br /&gt;
:* Click the Export button on the page for the model you want to export (e.g., Teams).&lt;br /&gt;
:* When the modal opens, it automatically makes a request to:&lt;br /&gt;
:*: `GET /export/&amp;lt;modelClass&amp;gt;`&lt;br /&gt;
:* to fetch the field metadata for the selected model.&lt;br /&gt;
; Field Lists Displayed&lt;br /&gt;
:* The modal uses the metadata received from the backend to show three types of fields:&lt;br /&gt;
:# Mandatory fields – These must always be included in the export and cannot be unchecked.&lt;br /&gt;
:# Optional fields – These may be included in the export at the user’s discretion.&lt;br /&gt;
:# External fields – Additional related fields made available for export (if applicable).&lt;br /&gt;
:* Users can hover over an info icon to view the full field list in a tooltip.&lt;br /&gt;
; Choosing Columns to Export&lt;br /&gt;
:* The modal provides a checkbox list of all available fields.&lt;br /&gt;
:* Users may:&lt;br /&gt;
:# Check or uncheck optional fields.&lt;br /&gt;
:# View mandatory fields (locked and always selected).&lt;br /&gt;
:# Reorder any fields using ↑ and ↓ arrows, which determines the ordering of columns in the exported CSV.&lt;br /&gt;
; Column Ordering&lt;br /&gt;
:* Fields appear in the export file in the exact order shown in the modal.&lt;br /&gt;
:* The user can:&lt;br /&gt;
:# Move any non-mandatory field up.&lt;br /&gt;
:# Move any non-mandatory field down.&lt;br /&gt;
:* Mandatory fields are always included and their order can also be adjusted if they are part of the list returned by the backend.&lt;br /&gt;
; Generating the CSV&lt;br /&gt;
:* When satisfied with selections:&lt;br /&gt;
:** Click export&lt;br /&gt;
:* The frontend gathers:&lt;br /&gt;
:** The selected fields&lt;br /&gt;
:* It then generates a CSV where:&lt;br /&gt;
:** The first row contains the field names (in the chosen order)&lt;br /&gt;
:** All following rows contain the corresponding values&lt;br /&gt;
:** A downloadable `.csv` file is automatically created and saved to the user’s system.&lt;br /&gt;
; Status Feedback&lt;br /&gt;
:* The modal displays a status message during and after the export operation, for example:&lt;br /&gt;
:# “Generating CSV…”&lt;br /&gt;
:# “Export complete”&lt;br /&gt;
:* If no fields are selected, the modal will prevent exporting and display a warning.&lt;br /&gt;
[[File:ExportFile.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
* &amp;lt;code&amp;gt;empty.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A completely empty CSV file. This file is used to ensure that if no content is included, the import service will fail gracefully.&lt;br /&gt;
* &amp;lt;code&amp;gt;empty_with_headers.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file that only contains the headers for the User class. This file is used to ensure a file with no records is handled gracefully.&lt;br /&gt;
* &amp;lt;code&amp;gt;multiple_users_no_headers.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file with no headers for importing records for the User class. It contains multiple User records (John Doe, Jane Doe) to import. &lt;br /&gt;
* &amp;lt;code&amp;gt;multiple_users_with_headers.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file with headers for importing records for the User class. It contains multiple User records (John Doe, Jane Doe) to import. &lt;br /&gt;
* &amp;lt;code&amp;gt;questionnaire_item_with_headers.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file with headers for importing records for the Item class. These Items make up a questionnaire. It contains a single Item that needs to be imported.&lt;br /&gt;
* &amp;lt;code&amp;gt;single_user_no_headers.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file with headers for importing records for the User class. It contains a single User (John Doe) who needs to be imported.&lt;br /&gt;
* &amp;lt;code&amp;gt;single_user_with_headers.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file with headers for importing records for the User class. It contains a single User (John Doe) who needs to be imported.&lt;br /&gt;
* &amp;lt;code&amp;gt;users_duplicate_records.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file containing multiple duplicate records that need to be handled.&lt;br /&gt;
* &amp;lt;code&amp;gt;single_user_email_invalid.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file that contains a user with an invalid email. That is an Internal field that needs to be validated.&lt;br /&gt;
* &amp;lt;code&amp;gt;single_user_role_doe_not_exist.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
*: A CSV file that contains a user with a role that does not exist. That is a field from an External Class that needs to be looked up.&lt;br /&gt;
&lt;br /&gt;
=== Unit Testing ===&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
==== ImportableExportableHelper - Importing ====&lt;br /&gt;
----&lt;br /&gt;
;Create tests for each of the different importable classes&lt;br /&gt;
* Show a class with no headers can be imported (User)&lt;br /&gt;
*: This test tries to import the 'single_user_no_headers.csv' file. This file doesn't have headers, so the test passes a list of headers to the import statement. This CSV file calls for the Role Name of the user, which is set to Student. This tests whether the import statement is able to look up a role by its name. It is able to do this because the name is a lookup field for the External Class Role, which is assigned to the User Class.&lt;br /&gt;
* Show a class with headers can be imported (User)&lt;br /&gt;
*: This test tries to import the 'single_user_with_headers.csv' file. This file has headers, so the test passes nil to the header variable of the import statement. This CSV file calls for the Role ID of the user, which is set to 4 (Teaching Assistant). This tests whether the import statement is able to look up a role by its ID. It can do this even though ID is not the set lookup field, because the lookup function uses the primary key if the lookup field isn't in the file.&lt;br /&gt;
* Show a class with multiple records can be imported (User)&lt;br /&gt;
*: This test tries to import the 'multiple_users_with_headers.csv' file. This file contains multiple user records that need to be imported (John Doe and Jane Doe). This tests that multiple records successfully get imported with the right information.&lt;br /&gt;
* Show a class with external create classes can take duplicate headers (Questionnaire w/ multiple Advice)&lt;br /&gt;
*: This test tries to import the 'questionnaire_item_with_headers.csv' file that creates an external class. Not only that, but it can detect if there are multiple instances of this external class and save them individually. &lt;br /&gt;
&lt;br /&gt;
;Create Tests to test Errors/Edge Cases&lt;br /&gt;
* Import a class with external lookup class that doesn't exist&lt;br /&gt;
*: Tries to import a csv with an invalid external field. The user's role doesn't exist, so looking up this field should fail and ultimately cause the import to fail.&lt;br /&gt;
* Import a class with an invalid field (User with ian nvalid email)&lt;br /&gt;
*: Tries to import a csv with an invalid internal field. The user email is validated inside the User class, so make sure that validation raises the correct error.&lt;br /&gt;
* Import an empty CSV (With Headers)&lt;br /&gt;
*: Tries to import an empty csv with no records inside. This is tested with the &amp;lt;code&amp;gt;use_header&amp;lt;/code&amp;gt; option set to true.&lt;br /&gt;
* Import an empty CSV (Without Headers)&lt;br /&gt;
*: Tries to import an empty csv with nothing inside. This is tested with the &amp;lt;code&amp;gt;use_header&amp;lt;/code&amp;gt; option set to false.&lt;br /&gt;
&lt;br /&gt;
==== ImportExportService - Importing ====&lt;br /&gt;
----&lt;br /&gt;
(Taylor - Expand on these)&lt;br /&gt;
;Create tests to make sure the duplicate actions work&lt;br /&gt;
* Try to create with duplicates for the skip action&lt;br /&gt;
* Try to create with duplicates for rename action&lt;br /&gt;
* Try to create with duplicates for update record&lt;br /&gt;
&lt;br /&gt;
;Create Tests to test Errors/Edge Cases&lt;br /&gt;
* Create a test to make sure duplicate action is specified&lt;br /&gt;
* Create a test that doesn't include the mandatory fields&lt;br /&gt;
&lt;br /&gt;
==== ImportExportService -  Exporting ====&lt;br /&gt;
----&lt;br /&gt;
(Taylor - Expand on these)&lt;br /&gt;
;Create tests for each of the different exportable classes&lt;br /&gt;
* Export a class with the default headers&lt;br /&gt;
* Export a class with only the mandatory headers&lt;br /&gt;
* Export a class with only some optional headers&lt;br /&gt;
* Export a class with a different order of headers&lt;br /&gt;
&lt;br /&gt;
;Create tests to test Errors/Edge Cases&lt;br /&gt;
* Export a class with chosen headers that are empty&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Integration Testing ===&lt;br /&gt;
----&lt;br /&gt;
(Taylor)&lt;br /&gt;
&lt;br /&gt;
==== Import Controller ====&lt;br /&gt;
----&lt;br /&gt;
(Taylor)&lt;br /&gt;
&lt;br /&gt;
==== Export Controller ====&lt;br /&gt;
----&lt;br /&gt;
(Taylor)&lt;br /&gt;
&lt;br /&gt;
=== Frontend Testing ===&lt;br /&gt;
----&lt;br /&gt;
==== Import Modal ====&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
* Shows loading state when isLoading is true&lt;br /&gt;
*: Ensures that when `useAPI` reports `isLoading=true`, the modal hides all content and displays a “Loading…” message.&lt;br /&gt;
* Renders field summary and duplicate options from metadata&lt;br /&gt;
*: Confirms that metadata returned from the backend (mandatory, optional, external fields, and duplicate handling actions) are rendered correctly in the modal.&lt;br /&gt;
* Shows status when importing with no file selected&lt;br /&gt;
*: Validates that clicking “import” without choosing a CSV sets an error status message and prevents the import call.&lt;br /&gt;
* Shows column mapping and first-row values when header mode is off&lt;br /&gt;
*: After uploading a CSV and disabling the “First row contains headers” toggle, verifies that the “Column order” UI appears, column dropdowns are rendered, and the first-row preview text is displayed.&lt;br /&gt;
* Calls sendImport when import is valid&lt;br /&gt;
*: Uploads a valid CSV containing mandatory fields and clicks “import.” Checks that the `sendRequest` mock is called, proving that the modal sends a correctly prepared API request.&lt;br /&gt;
* Calls onHide when cancel is clicked&lt;br /&gt;
*: Simulates clicking the “cancel” button and confirms the modal fires the `onHide` callback to close itself.&lt;br /&gt;
&lt;br /&gt;
==== Export Modal ====&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Future work ==&lt;br /&gt;
* Adding event-based entity registration.&lt;br /&gt;
* Extending support for new duplicate resolution policies.&lt;br /&gt;
* Integration with the engine demo for visualization and debugging.&lt;br /&gt;
&lt;br /&gt;
=== Other Notes/Recommendations ===&lt;br /&gt;
* For Items, limit the string values that question_type can be using built-in validation rules as well, or else importing will allow just any string.&lt;br /&gt;
* For Questionnaires, break_before can't be false because of the validation rules. Maybe try this `validates :break_before, inclusion: { in: [true, false] }`&lt;/div&gt;</summary>
		<author><name>Tjbrown8</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025&amp;diff=167132</id>
		<title>CSC/ECE 517 Fall 2025</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025&amp;diff=167132"/>
		<updated>2025-11-19T01:11:09Z</updated>

		<summary type="html">&lt;p&gt;Tjbrown8: /* Final Projects */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[CSC/ECE 517 Fall 2025 - E2550. Response hierarchy and responses_controller back end]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2551. Reimplementing SubmittedContentController]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2552. ProjectTopic and SignedUpTeam]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2553.  Heatgrid and Grades Controller (Frontend + Backend)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2554. Front end for View Submissions Page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2555. Front end for Participants Page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2556. Front ends for Create Teams and Assign Reviewers]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2557. Specialized rubrics for different topic types]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2558. Tabbed view for creating and editing assignments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Final Projects ==&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2560. Framework for Import and Export]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2561. Finish up SubmittedContentController]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2562. Review grading dashboard]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2563. Review tableau]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2564. Review calibration]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2565. Integration of JoinTeamRequests]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2566. Finish DueDates]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2567. Review rubrics varying by round]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2568. Finish tabbed view for Assignments, including Topics and Calibration tabs]]&lt;/div&gt;</summary>
		<author><name>Tjbrown8</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2560._Framework_for_Import_and_Export&amp;diff=167017</id>
		<title>CSC/ECE 517 Fall 2025 - E2560. Framework for Import and Export</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2560._Framework_for_Import_and_Export&amp;diff=167017"/>
		<updated>2025-11-10T06:53:44Z</updated>

		<summary type="html">&lt;p&gt;Tjbrown8: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The export/import functionality is one of the most valuable tools for instructors when setting up assignments in Expertiza. Instructors often have lists of students, teams, and other data from their learning management systems. The ability to seamlessly export and import this data into Expertiza significantly reduces setup time and effort.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The previous version of Expertiza offered multiple export and import features—for example, exporting students, teams, rubrics, topics, and more. These features typically retrieve data from the database and save it in a specified format. However, the same logic is often duplicated across different implementations for various data types.&lt;br /&gt;
&lt;br /&gt;
The goal of this project is to design and implement a generic export/import framework that can handle various types of data based on input parameters. You will create a module that accepts database table names and column names to determine what data should be exported or imported. This module should be flexible and reusable across all export/import features in Expertiza.&lt;br /&gt;
&lt;br /&gt;
== Design Document ==&lt;br /&gt;
=== Class Diagram ===&lt;br /&gt;
[[File:CSC517Final_3.png|1200px]]&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
The system is divided into two main layers:&lt;br /&gt;
&lt;br /&gt;
* '''Backend''' — Handles import/export logic, data validation, and duplicate record management.&lt;br /&gt;
* '''Frontend''' — Provides user interfaces for triggering imports and exports, communicating with backend controllers.&lt;br /&gt;
&lt;br /&gt;
== Backend Components ==&lt;br /&gt;
&lt;br /&gt;
=== FieldMapping ===&lt;br /&gt;
Represents the relationship between class fields and their corresponding data columns.&lt;br /&gt;
* '''Attributes:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;class: Class&amp;lt;/code&amp;gt; — The associated class for data mapping.&lt;br /&gt;
** &amp;lt;code&amp;gt;ordered_fields: Array[String]&amp;lt;/code&amp;gt; — Field order for import/export operations.&lt;br /&gt;
&lt;br /&gt;
=== DuplicateAction (Mixin) ===&lt;br /&gt;
Defines actions to take when duplicate records are detected.&lt;br /&gt;
* '''Attributes:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;name: String&amp;lt;/code&amp;gt; — Name of the duplicate action.&lt;br /&gt;
* '''Methods:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;on_duplicate_record()&amp;lt;/code&amp;gt; — Handles logic when a duplicate record is found.&lt;br /&gt;
&lt;br /&gt;
=== ImportableExportable (Mixin) ===&lt;br /&gt;
Provides shared functionality for classes that can be imported or exported.&lt;br /&gt;
* '''Attributes:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;mandatory_fields: Array[String]&amp;lt;/code&amp;gt; — Fields required for processing.&lt;br /&gt;
** &amp;lt;code&amp;gt;optional_fields: Array[String]&amp;lt;/code&amp;gt; — Fields that can optionally be included.&lt;br /&gt;
** &amp;lt;code&amp;gt;available_duplicate_actions: Array[DuplicateAction]&amp;lt;/code&amp;gt; — List of supported duplicate handling strategies.&lt;br /&gt;
* '''Methods:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;register_detail(class, field: String)&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;try_insert_record(DuplicateAction)&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;is_duplicate_record()&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;get_detail_field(record, detail_class, detail_field: String)&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;to_hash()&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ImportExportManager ===&lt;br /&gt;
Acts as the central interface for managing import and export workflows.&lt;br /&gt;
* '''Methods:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;export(class, mapping: FieldMapping, filename: String)&amp;lt;/code&amp;gt; — Exports class data based on mapping.&lt;br /&gt;
** &amp;lt;code&amp;gt;import(class, mapping: FieldMapping, filename: String, use_header: bool)&amp;lt;/code&amp;gt; — Imports data into the specified class.&lt;br /&gt;
** &amp;lt;code&amp;gt;default_mapping(class)&amp;lt;/code&amp;gt; — Retrieves the default mapping configuration.&lt;br /&gt;
** &amp;lt;code&amp;gt;suggest_filename(class, mode: String)&amp;lt;/code&amp;gt; — Suggests a filename based on class and mode.&lt;br /&gt;
&lt;br /&gt;
=== ImportController ===&lt;br /&gt;
Handles import-related HTTP requests.&lt;br /&gt;
* '''Endpoints:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;index&amp;lt;/code&amp;gt; — Returns import configuration data.&lt;br /&gt;
** &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt; — Accepts incoming data and triggers import operations.&lt;br /&gt;
* '''Interactions:'''&lt;br /&gt;
** Sends mandatory and optional fields, as well as available duplicate actions, to the frontend.&lt;br /&gt;
** Receives chosen ordered fields and duplicate action from the frontend.&lt;br /&gt;
&lt;br /&gt;
=== ExportController ===&lt;br /&gt;
Handles export-related HTTP requests.&lt;br /&gt;
* '''Endpoints:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;index&amp;lt;/code&amp;gt; — Provides available export configurations.&lt;br /&gt;
** &amp;lt;code&amp;gt;export&amp;lt;/code&amp;gt; — Generates export files based on selected parameters.&lt;br /&gt;
* '''Interactions:'''&lt;br /&gt;
** Sends mandatory and optional fields to the frontend.&lt;br /&gt;
** Receives chosen ordered fields for export.&lt;br /&gt;
&lt;br /&gt;
== Frontend Components ==&lt;br /&gt;
&lt;br /&gt;
=== Import (.tsx) ===&lt;br /&gt;
* '''Methods:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;on_import&amp;lt;/code&amp;gt; — Initiates the import process.&lt;br /&gt;
* '''Interactions:'''&lt;br /&gt;
** Receives mandatory/optional field data and duplicate actions.&lt;br /&gt;
** Sends selected ordered fields and chosen duplicate handling action back to the backend.&lt;br /&gt;
&lt;br /&gt;
=== Export (.tsx) ===&lt;br /&gt;
* '''Methods:'''&lt;br /&gt;
** &amp;lt;code&amp;gt;on_export&amp;lt;/code&amp;gt; — Initiates the export process.&lt;br /&gt;
* '''Interactions:'''&lt;br /&gt;
** Receives mandatory/optional field data from backend.&lt;br /&gt;
** Sends selected ordered fields for export.&lt;br /&gt;
&lt;br /&gt;
== Data Flow ==&lt;br /&gt;
&lt;br /&gt;
=== Import Sequence ===&lt;br /&gt;
# Frontend requests import configuration.&lt;br /&gt;
# Backend responds with mandatory/optional fields and duplicate actions.&lt;br /&gt;
# User selects ordered fields and a duplicate action.&lt;br /&gt;
# Frontend sends selections to backend for processing via &amp;lt;code&amp;gt;ImportController.import&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Export Sequence ===&lt;br /&gt;
# Frontend requests export configuration.&lt;br /&gt;
# Backend sends available fields.&lt;br /&gt;
# User selects ordered fields to include.&lt;br /&gt;
# Frontend sends selections to backend via &amp;lt;code&amp;gt;ExportController.export&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Design Notes ==&lt;br /&gt;
The design emphasizes modularity and extensibility. Future work includes:&lt;br /&gt;
* Adding event-based entity registration.&lt;br /&gt;
* Extending support for new duplicate resolution policies.&lt;br /&gt;
* Integration with the engine demo for visualization and debugging.&lt;br /&gt;
&lt;br /&gt;
=== Use Case Diagram ===&lt;br /&gt;
[[File:CSC517FinalUseCases_2.png]]&lt;/div&gt;</summary>
		<author><name>Tjbrown8</name></author>
	</entry>
</feed>