|
42 | 42 | import {AxiosError} from "axios"; |
43 | 43 | import Icon from "~/components/Symbols/Icon.vue"; |
44 | 44 | import FileInput from "~/components/Input/FileInput.vue"; |
| 45 | + import {ImportExportFormat} from "~/types/exercise"; |
45 | 46 |
|
46 | 47 | @Component({ |
47 | 48 | components: {FileInput, ValidationObserver, Icon} |
|
56 | 57 |
|
57 | 58 | @Prop({type: String, required: true}) title!: string; |
58 | 59 |
|
59 | | - form: {file: File | null} = { |
| 60 | + form: { file: File | null } = { |
60 | 61 | file: null |
61 | 62 | }; |
62 | 63 |
|
|
84 | 85 | const buffer = reader.result as ArrayBuffer; |
85 | 86 | const string: string = new TextDecoder().decode(buffer); |
86 | 87 |
|
| 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 | +
|
87 | 97 | try { |
88 | 98 | 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 | + } |
91 | 146 |
|
| 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."); |
92 | 151 | this.$nextTick(() => { |
93 | 152 | this.form.file; |
94 | 153 | // @ts-ignore |
95 | 154 | this.fileObserver.deleteFile(); |
96 | 155 | this.observer.reset(); |
97 | 156 | }) |
98 | 157 | } 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."); |
113 | 161 | } 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 | + } |
115 | 176 | } |
116 | 177 | } finally { |
117 | 178 | this.$nuxt.$loading.finish(); |
|
0 commit comments