-
Notifications
You must be signed in to change notification settings - Fork 1
Feat 331 data export #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Feat 331 data export #320
Changes from 19 commits
71f2eb9
e0050f5
cbf44b7
70959a4
3d46271
84929b5
d2e38b7
c14978e
dd0a3c4
64611c6
2085c4d
edd21cd
6fa0e01
34ac245
e183f30
f9c80c7
f815db5
a7a4d9e
0df5ba8
a450787
39a99b8
ef0d0e1
8470d76
49546e8
273ffac
f47705f
a3803f3
2d86415
54587a7
4b3b583
8a4953c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,21 +18,24 @@ | |
| :fields="dataSelectionFields" | ||
| /> | ||
| </template> | ||
|
|
||
| <template #step-2> | ||
|
|
||
| <div v-if="dataSelection.exportType === 'reviewerList'"> | ||
| <p>Exporting a list of all study sessions with hash:</p> | ||
| <p> | ||
| Total Studies: {{ studies.length }}<br> | ||
| Total Study Sessions: {{ studySessions.length }} | ||
| </p> | ||
| </div> | ||
| <div v-else-if="['submissions', 'grades'].includes(dataSelection.exportType)"> | ||
| <StepSelectStudents | ||
| <div v-else-if="['submissions', 'grades', 'documents', 'studies', 'userBehaviour'].includes(dataSelection.exportType)"> | ||
| <StepSelectUsers | ||
| v-if="dataSelection.projectId" | ||
| v-model="submissionSelection" | ||
| :project-id="dataSelection.projectId" | ||
| :project-id="dataSelection.projectId" | ||
| :export-type="dataSelection.exportType" | ||
| v-model="userSelection" | ||
| /> | ||
| <!-- We send the project ID and get the selected students back --> | ||
| <!-- We send the project ID and get the selected users back --> | ||
| </div> | ||
| <div v-else> | ||
| <p>Exporting all data</p> | ||
|
|
@@ -50,30 +53,57 @@ | |
| </p> | ||
| </div> | ||
| </template> | ||
| <template | ||
| v-if="['submissions', 'grades'].includes(dataSelection.exportType)" | ||
| #step-3 | ||
| > | ||
| <StepOptions | ||
| v-model:generate-aliases="generateAliases" | ||
| v-model:faker-seed="fakerSeed" | ||
| v-model:grade-format="gradeFormat" | ||
| v-model:merge-csv-files="mergeCsvFiles" | ||
| :show-grade-format="dataSelection.exportType === 'grades'" | ||
| /> | ||
| <!-- We get the info back if user wants to generate aliases and the seed that should be used for this --> | ||
|
|
||
|
|
||
| <template #step-3> | ||
| <div v-if="['submissions', 'grades'].includes(dataSelection.exportType)"> | ||
| <StepOptions | ||
| v-model:generate-aliases="generateAliases" | ||
| v-model:faker-seed="fakerSeed" | ||
| v-model:grade-format="gradeFormat" | ||
| v-model:merge-csv-files="mergeCsvFiles" | ||
| :show-grade-format="dataSelection.exportType === 'grades'" | ||
| /> | ||
| <!-- We get the info back if user wants to generate aliases and the seed that should be used for this --> | ||
| </div> | ||
| <div v-else-if="['documents'].includes(dataSelection.exportType)"> | ||
| <StepOptionsDocuments | ||
| v-model:selectedTypes="selectedDocumentTypes" | ||
| v-model:excludeNonConsentingEdits="excludeNonConsentingEdits" | ||
| v-model:excludeNonConsentingAnnotations="excludeNonConsentingAnnotations" | ||
| /> | ||
| <!-- We get the desired document types as well as if non consenting users' edits should be included --> | ||
| </div> | ||
| <div v-else-if="['studies'].includes(dataSelection.exportType)"> | ||
| <StepOptionsStudies | ||
| :project-id="dataSelection.projectId" | ||
| v-model:selectedWorkflowIds="selectedWorkflowIds" | ||
| v-model:includeEmptyStudies="includeEmptyStudies" | ||
| v-model:includeDocumentFiles="includeStudyDocumentFiles" | ||
| v-model:includeGrades="includeStudyGrades" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The parent binds |
||
| v-model:includeAiScores="includeStudyIncludeAiScores" | ||
| v-model:excludeNonConsentingEdits="excludeNonConsentingEdits" | ||
| v-model:excludeNonConsentingAnnotations="excludeNonConsentingAnnotations" | ||
| /> | ||
| </div> | ||
| <div v-else-if="['userBehaviour'].includes(dataSelection.exportType)"> | ||
| <StepOptionsUserBehaviour | ||
| v-model:outputFormat="behaviourOutputFormat" | ||
| v-model:fileFormat="behaviourFileFormat" | ||
| /> | ||
| </div> | ||
| </template> | ||
|
|
||
| <template | ||
| v-if="['submissions', 'grades'].includes(dataSelection.exportType)" | ||
| v-if="['submissions', 'grades', 'documents', 'studies', 'userBehaviour'].includes(dataSelection.exportType)" | ||
| #step-4 | ||
| > | ||
| <StepConfirmDownload | ||
| v-if="['submissions', 'grades'].includes(dataSelection.exportType)" | ||
| <StepConfirmDownload | ||
| :wait="wait" | ||
| :generate-aliases="generateAliases" | ||
| :submission-selection="submissionSelection" | ||
| :user-selection="userSelection" | ||
| :export-type="dataSelection.exportType" | ||
| /> | ||
| <!-- We send the info the generateAliases because it is needed to show the warning talking about the mapping CSV --> | ||
| </template> | ||
| </StepperModal> | ||
| </template> | ||
|
|
@@ -87,20 +117,23 @@ import JSZip from 'jszip'; | |
| import FileSaver from 'file-saver'; | ||
| import Quill from "quill"; | ||
| import {dbToDelta} from "editor-delta-conversion"; | ||
| import StepSelectStudents from "@/components/dashboard/projects/export/StepSelectStudents.vue"; | ||
| import StepSelectUsers from "@/components/dashboard/projects/export/StepSelectUsers.vue"; | ||
| import StepOptions from "@/components/dashboard/projects/export/StepOptions.vue"; | ||
| import StepOptionsDocuments from "@/components/dashboard/projects/export/StepOptionsDocuments.vue"; | ||
| import StepOptionsStudies from "@/components/dashboard/projects/export/StepOptionsStudies.vue"; | ||
| import StepOptionsUserBehaviour from "@/components/dashboard/projects/export/StepOptionsUserBehaviour.vue"; | ||
| import StepConfirmDownload from "@/components/dashboard/projects/export/StepConfirmDownload.vue"; | ||
| import getServerURL from "@/assets/serverUrl.js"; | ||
|
|
||
|
|
||
| /** | ||
| * ProjectModal - modal component for adding and editing projects | ||
| * | ||
| * @author Dennis Zyska, Mélissa Loew, Linyin Huang | ||
| * @author Dennis Zyska, Mélissa Loew | ||
| */ | ||
| export default { | ||
| name: "ExportProjectModal", | ||
| components: { StepperModal, BasicForm, StepSelectStudents, StepOptions, StepConfirmDownload }, | ||
| components: { StepperModal, BasicForm, StepSelectUsers, StepOptions, StepOptionsDocuments, StepOptionsStudies, StepOptionsUserBehaviour, StepConfirmDownload }, | ||
| subscribeTable: [{ | ||
| table: "document", | ||
| }, { | ||
|
|
@@ -119,6 +152,14 @@ export default { | |
| table: "tag_set", | ||
| }, { | ||
| table: "tag" | ||
| }, { | ||
| table: "document_data", | ||
| }, { | ||
| table: "study_step", | ||
| }, { | ||
| table: "configuration", | ||
| }, { | ||
| table: "workflow", | ||
| } | ||
| ], | ||
| provide() { | ||
|
|
@@ -135,37 +176,68 @@ export default { | |
| filter: [], | ||
| wait: false, | ||
| // Data for Export Submissions | ||
| submissionSelection: [], | ||
| userSelection: [], | ||
| generateAliases:false, | ||
| fakerSeed: 846569412, | ||
| gradeFormat: "json", | ||
| mergeCsvFiles: false | ||
| mergeCsvFiles: false, | ||
| selectedDocumentTypes: [0, 1, 2, 4], | ||
| excludeNonConsentingEdits: false, | ||
| excludeNonConsentingAnnotations: false, | ||
| selectedWorkflowIds: [], | ||
| includeStudyDocumentFiles: true, | ||
| includeStudyGrades: true, | ||
| includeStudyIncludeAiScores: true, | ||
| includeEmptyStudies: true, | ||
| behaviourOutputFormat: 'single', | ||
| behaviourFileFormat: 'json', | ||
| }; | ||
| }, | ||
| computed: { | ||
| stepValid() { | ||
| if (["submissions", "grades"].includes(this.dataSelection.exportType)) { | ||
| return [ | ||
| !!this.dataSelection.projectId && !!this.dataSelection.exportType, // must select a valid project and export type | ||
| this.submissionSelection.length > 0, // must select at least one student | ||
| this.userSelection.length > 0, // must select at least one student | ||
| true, | ||
| true | ||
| ]; | ||
| } else if (this.dataSelection.exportType === "documents") { | ||
| return [ | ||
| !!this.dataSelection.projectId && !!this.dataSelection.exportType, | ||
| this.userSelection.length > 0, | ||
| this.selectedDocumentTypes.length > 0, | ||
| true, | ||
| ]; | ||
| } else if (this.dataSelection.exportType === 'studies') { | ||
| return [ | ||
| !!this.dataSelection.projectId && !!this.dataSelection.exportType, | ||
| this.userSelection.length > 0, | ||
| this.selectedWorkflowIds.length > 0, | ||
| true, | ||
| ]; | ||
| } else if (this.dataSelection.exportType === 'userBehaviour') { | ||
| return [ | ||
| !!this.dataSelection.projectId && !!this.dataSelection.exportType, | ||
| this.userSelection.length > 0, | ||
| true, | ||
| true, | ||
| ]; | ||
| } | ||
| return [ | ||
| !!this.dataSelection.projectId && !!this.dataSelection.exportType, | ||
| true | ||
| ]; | ||
| }, | ||
| steps() { | ||
| if (["submissions", "grades"].includes(this.dataSelection.exportType)) { | ||
| if (["submissions", "grades", "documents", "studies", "userBehaviour"].includes(this.dataSelection.exportType)) { | ||
| return [ | ||
| { title: "Settings" }, | ||
| { title: "Select Students" }, | ||
| { title: "Select Users" }, | ||
| { title: "Options" }, | ||
| { title: "Confirm Download" } | ||
| ]; | ||
| } | ||
| } | ||
| return [ | ||
| {title: "Settings"}, | ||
| {title: "Confirmation"} | ||
|
|
@@ -191,6 +263,9 @@ export default { | |
| {name: "Export a list of all reviewers", value: "reviewerList"}, | ||
| {name: "Export submissions", value: "submissions"}, | ||
| {name: "Export grades", value: "grades"}, | ||
| {name: "Export documents", value:"documents"}, | ||
| {name: "Export studies", value: "studies"}, | ||
| ...(this.$store.getters["auth/isAdmin"] ? [{name: "Export user behaviour", value: "userBehaviour"}] : []), | ||
| {name: "All", value: "all"}, | ||
| ], | ||
| required: true, | ||
|
|
@@ -249,13 +324,35 @@ export default { | |
| return this.$store.getters["table/project/getAll"]; | ||
| }, | ||
| }, | ||
| watch: { | ||
| 'dataSelection.exportType'() { | ||
| this.userSelection = []; | ||
| }, | ||
| 'dataSelection.projectId'() { | ||
| this.userSelection = []; | ||
| } | ||
| }, | ||
| methods: { | ||
| open(projectId) { | ||
| this.dataSelection.projectId = projectId; | ||
| this.$refs.exportStepper.open(); | ||
| }, | ||
| hide() { | ||
| this.filter = []; | ||
| this.userSelection = []; | ||
| this.generateAliases = false; | ||
| this.fakerSeed = 846569412; | ||
| this.selectedDocumentTypes = [0, 1, 2, 4]; | ||
| this.excludeNonConsentingEdits = false; | ||
| this.excludeNonConsentingAnnotations = false; | ||
| this.selectedWorkflowIds = []; | ||
| this.includeStudyDocumentFiles = true; | ||
| this.includeStudyGrades = true; | ||
| this.includeStudyIncludeAiScores = true; | ||
| this.includeEmptyStudies = true; | ||
| this.wait = false; | ||
| this.behaviourOutputFormat = 'single'; | ||
| this.behaviourFileFormat = 'json'; | ||
| }, | ||
| downloadData() { | ||
| if (this.dataSelection.exportType === "reviewerList") { | ||
|
|
@@ -264,6 +361,12 @@ export default { | |
| this.downloadSubmissions(); | ||
| } else if (this.dataSelection.exportType === "grades") { | ||
| this.downloadGrades(); | ||
| } else if (this.dataSelection.exportType === "documents") { | ||
| this.downloadDocuments(); | ||
| } else if (this.dataSelection.exportType === 'studies') { | ||
| this.downloadStudies(); | ||
| } else if (this.dataSelection.exportType === 'userBehaviour') { | ||
| this.downloadUserBehaviour(); | ||
| } else { | ||
| this.downloadAllData(); | ||
| } | ||
|
|
@@ -327,7 +430,7 @@ export default { | |
| async downloadSubmissions() { | ||
| try { | ||
| // get the selected student's user ids | ||
| const selectedUserIds = this.submissionSelection.map(row => row.userId); | ||
| const selectedUserIds = this.userSelection.map(row => row.userId); | ||
|
|
||
| // call helper function to trigger the stream download | ||
| this.triggerStreamDownload({ | ||
|
|
@@ -346,7 +449,7 @@ export default { | |
| }, | ||
| async downloadGrades() { | ||
| try { | ||
| const selectedUserIds = this.submissionSelection.map(row => row.userId); | ||
| const selectedUserIds = this.userSelection.map(row => row.userId); | ||
| this.triggerStreamDownload({ | ||
| projectId: this.dataSelection.projectId, | ||
| exportType: 'grades', | ||
|
|
@@ -362,6 +465,61 @@ export default { | |
| this.$toast.error("An error occurred starting the stream. Please try again."); | ||
| } | ||
| }, | ||
| async downloadDocuments() { | ||
| try { | ||
| const selectedUserIds = this.userSelection.map(row => row.userId); | ||
| this.triggerStreamDownload({ | ||
| projectId: this.dataSelection.projectId, | ||
| exportType: 'documents', | ||
| userIds: selectedUserIds, | ||
| documentTypes: this.selectedDocumentTypes, | ||
| excludeNonConsentingEdits: this.excludeNonConsentingEdits, | ||
| excludeNonConsentingAnnotations: this.excludeNonConsentingAnnotations | ||
| }); | ||
|
|
||
| this.$refs.exportStepper.close(); | ||
| } catch (error) { | ||
| console.error("Streaming error:", error); | ||
| this.$toast.error("An error occurred starting the stream. Please try again."); | ||
| } | ||
| }, | ||
| async downloadStudies() { | ||
| try { | ||
| const selectedUserIds = this.userSelection.map(row => row.userId); | ||
| this.triggerStreamDownload({ | ||
| projectId: this.dataSelection.projectId, | ||
| exportType: 'studies', | ||
| userIds: selectedUserIds, | ||
| workflowIds: this.selectedWorkflowIds, | ||
| includeEmptyStudies: this.includeEmptyStudies, | ||
| includeDocumentFiles: this.includeStudyDocumentFiles, | ||
| includeGrades: this.includeStudyGrades, | ||
| excludeNonConsentingEdits: this.excludeNonConsentingEdits, | ||
| excludeNonConsentingAnnotations: this.excludeNonConsentingAnnotations, | ||
| includeAiScores: this.includeStudyIncludeAiScores | ||
| }); | ||
| this.$refs.exportStepper.close(); | ||
| } catch (error) { | ||
| console.error("Streaming error:", error); | ||
| this.$toast.error("An error occurred starting the stream. Please try again."); | ||
| } | ||
| }, | ||
| async downloadUserBehaviour() { | ||
| try { | ||
| const selectedUserIds = this.userSelection.map(row => row.userId); | ||
| this.triggerStreamDownload({ | ||
| projectId: this.dataSelection.projectId, | ||
| exportType: 'userBehaviour', | ||
| userIds: selectedUserIds, | ||
| behaviourOutputFormat: this.behaviourOutputFormat, | ||
| behaviourFileFormat: this.behaviourFileFormat, | ||
| }); | ||
| this.$refs.exportStepper.close(); | ||
| } catch (error) { | ||
| console.error("Streaming error:", error); | ||
| this.$toast.error("An error occurred starting the stream. Please try again."); | ||
| } | ||
| }, | ||
| async downloadAllData() { | ||
| this.wait = true; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.