Skip to content

Commit c9c8a72

Browse files
authored
Merge pull request #62 from SourceCodeOER/import-using-export
feat(import) : reuse export format for import (WIP)
2 parents a9a1f68 + 6199d10 commit c9c8a72

File tree

2 files changed

+94
-19
lines changed

2 files changed

+94
-19
lines changed

components/Gestion/ImportForm.vue

Lines changed: 79 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import {AxiosError} from "axios";
4343
import Icon from "~/components/Symbols/Icon.vue";
4444
import FileInput from "~/components/Input/FileInput.vue";
45+
import {ImportExportFormat} from "~/types/exercise";
4546
4647
@Component({
4748
components: {FileInput, ValidationObserver, Icon}
@@ -56,7 +57,7 @@
5657
5758
@Prop({type: String, required: true}) title!: string;
5859
59-
form: {file: File | null} = {
60+
form: { file: File | null } = {
6061
file: null
6162
};
6263
@@ -84,34 +85,94 @@
8485
const buffer = reader.result as ArrayBuffer;
8586
const string: string = new TextDecoder().decode(buffer);
8687
88+
let jsonInput: ImportExportFormat | any;
89+
// since TypeScript doesn't check type at runtime ; better check that
90+
const isExportFormat = (obj: any) =>
91+
(obj as ImportExportFormat).categories &&
92+
(obj as ImportExportFormat).exercises &&
93+
Array.isArray(obj.exercises) &&
94+
typeof (obj as ImportExportFormat).categories == "object"
95+
;
96+
8797
try {
8898
this.$nuxt.$loading.start();
89-
await this.$axios.$post("/api/bulk/create_exercises", JSON.parse(string));
90-
this.$displaySuccess("L'importation s'est correctement déroulée.");
99+
// first validate the json before anything else
100+
jsonInput = JSON.parse(string);
101+
// at the end, both import type use the same endpoint
102+
let exercises;
103+
104+
// Type Guards to distinct the two types
105+
if (isExportFormat(jsonInput)) {
106+
107+
const exportFormat = jsonInput as ImportExportFormat;
108+
109+
// need that function in the next lines
110+
// Credits to https://gist.github.com/JamieMason/0566f8412af9fe6a1d470aa1e089a752
111+
const groupBy = (key: string) => (array: any[]) =>
112+
array.reduce((objectsByKeyValue, obj) => {
113+
const value = obj[key];
114+
objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
115+
return objectsByKeyValue;
116+
}, {});
117+
118+
// creates or find the category/ies
119+
const tags_categories = Object.values(exportFormat.categories);
120+
const tags_categories_ids: {
121+
id: number,
122+
category: string
123+
}[] = await this.$axios.$post("/api/bulk/create_or_find_tag_categories", tags_categories);
124+
const tags_dictionary = groupBy("category")(tags_categories_ids);
125+
126+
// prepare json
127+
exercises = exportFormat.exercises.map(
128+
ex => ({
129+
title: ex.title,
130+
description: ex.description,
131+
url: ex.url,
132+
state: ex.state,
133+
tags: ex.tags.map(tag => (
134+
{
135+
text: tag.text,
136+
category_id: tags_dictionary[exportFormat.categories[tag.category]][0].id,
137+
state: tag.state
138+
}
139+
))
140+
})
141+
);
142+
143+
} else {
144+
exercises = jsonInput;
145+
}
91146
147+
// Trial time : execute query
148+
await this.$axios.$post("/api/bulk/create_exercises", exercises);
149+
150+
this.$displaySuccess("L'importation s'est correctement déroulée.");
92151
this.$nextTick(() => {
93152
this.form.file;
94153
// @ts-ignore
95154
this.fileObserver.deleteFile();
96155
this.observer.reset();
97156
})
98157
} catch (e) {
99-
const error = e as AxiosError;
100-
101-
if (error.response) {
102-
const status = error.response.status;
103-
104-
if (status === 400) {
105-
this.$displayWarning("Votre fichier ne possède pas le bon format.")
106-
} else if (status === 401) {
107-
this.$displayWarning("Vous n'êtes pas autorisé à effectuer cette action.")
108-
} else if (status === 500) {
109-
this.$displayError("Une erreur est survenue depuis nos serveurs.")
110-
} else {
111-
this.$displayError("Une erreur est survenue.")
112-
}
158+
159+
if (e instanceof SyntaxError || e instanceof TypeError || e instanceof ReferenceError) {
160+
this.$displayError("Le contenu de votre fichier n'est pas correct.");
113161
} else {
114-
this.$displayError("Le contenu de votre fichier n'est pas correct.")
162+
const error = e as AxiosError;
163+
if (error.response) {
164+
const status = error.response.status;
165+
166+
if (status === 400) {
167+
this.$displayWarning("Votre fichier ne possède pas le bon format.")
168+
} else if (status === 401) {
169+
this.$displayWarning("Vous n'êtes pas autorisé à effectuer cette action.")
170+
} else if (status === 500) {
171+
this.$displayError("Une erreur est survenue depuis nos serveurs.")
172+
} else {
173+
this.$displayError("Une erreur est survenue.")
174+
}
175+
}
115176
}
116177
} finally {
117178
this.$nuxt.$loading.finish();

types/exercise.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,18 @@ export interface VoteRequest {
155155
score: number
156156
}
157157

158-
158+
// For import feature that used export ( simplest version )
159+
export interface ImportExportFormat {
160+
categories: { [key: string]: string; },
161+
exercises: {
162+
title: string,
163+
description: string,
164+
state: ExerciseState,
165+
url: null | string,
166+
tags: {
167+
text: string,
168+
category: number,
169+
state: TagState
170+
}[]
171+
}[]
172+
}

0 commit comments

Comments
 (0)