@@ -23,6 +23,7 @@ import Tour from "./Tour.vue";
2323import Confirm from " ./Confirm.vue" ;
2424import HeaderNav from " ./HeaderNav.vue" ;
2525import StudentDropdown from " ./StudentDropdown.vue" ;
26+ import toFilePath from " ./utils/toFilePath" ;
2627
2728export default {
2829 components: {
@@ -60,30 +61,13 @@ export default {
6061 links: Object
6162 },
6263 mounted () {
63- const items = { ... localStorage };
64- const key = this .currentExercise .workshop .code + ' .' + this .currentExercise .exercise .slug ;
65- for (const localStorageKey in items) {
66- if (localStorageKey .startsWith (key)) {
67- const fileContent = items[localStorageKey]; // Content of what is in file
68- const fileName = localStorageKey .substring (key .length + 1 );
69- let foundFile = false ;
70- for (const file of this .studentFiles ) {
71- if (file .name === fileName) {
72- file .content = fileContent;
73- foundFile = true ;
74- break ;
75- }
76- }
64+ const files = this .getSavedFiles ();
65+ for (const fileName in files) {
66+ const fileContent = files[fileName];
67+ const folderParts = fileName .split (" /" );
7768
78- if (! foundFile) {
79- const file = {
80- name: fileName,
81- parent: null ,
82- content: fileContent,
83- };
84- this .studentFiles .push (file);
85- }
86- }
69+ this .createFileInFolderStructure (this .studentFiles , folderParts, fileContent);
70+ this .studentFiles = this .toTree (this .studentFiles );
8771 }
8872 },
8973 data () {
@@ -93,7 +77,10 @@ export default {
9377 return a .name === this .entryPoint ? - 1 : 0 ;
9478 });
9579
96- const studentFiles = this .toTree (this .initialFiles );
80+ const initialFileCopy = this .initialFiles .map (file => {
81+ return {... file}
82+ });
83+ const studentFiles = this .toTree (initialFileCopy);
9784
9885 return {
9986 firstRunLoaded: false ,
@@ -129,9 +116,91 @@ export default {
129116 },
130117 },
131118 methods: {
119+ getSavedFiles () {
120+ const items = { ... localStorage };
121+ const key = this .currentExercise .workshop .code + ' .' + this .currentExercise .exercise .slug ;
122+
123+ const files = {};
124+ for (const localStorageKey in items) {
125+ if (localStorageKey .startsWith (key)) {
126+ files[localStorageKey .substring (key .length + 1 )] = items[localStorageKey];
127+ }
128+ }
129+ return files;
130+ },
131+ async resetFiles () {
132+ const confirm = this .$refs .confirm ;
133+
134+ const ok = await confirm .show ({
135+ title: " Resetting..." ,
136+ message: " File tree will be completely reset. All of your code will be deleted. Are you sure you want to continue?" ,
137+ okMessage: " Confirm" ,
138+ });
139+
140+ if (! ok) {
141+ return ;
142+ }
143+
144+ const key = this .currentExercise .workshop .code + ' .' + this .currentExercise .exercise .slug ;
145+ const files = this .getSavedFiles ();
146+ for (const fileName in files) {
147+ localStorage .removeItem (key + ' .' + fileName);
148+ }
149+
150+ const initialFileCopy = this .initialFiles .map (file => {
151+ return {... file}
152+ });
153+
154+ this .studentFiles = this .toTree (initialFileCopy);
155+ this .openFiles = [this .studentFiles [0 ]];
156+ this .activeTab = 0 ;
157+ },
158+ createFileInFolderStructure (rootFolder , parts , fileContent ) {
159+ if (parts .length === 1 ) {
160+ const file = rootFolder .find (child => child .name === parts[0 ]);
161+ if (file) {
162+ file .content = fileContent;
163+ return ;
164+ }
165+
166+ rootFolder .push ({ name: parts[0 ], content: fileContent });
167+ return ;
168+ }
169+
170+ const directories = parts;
171+ const fileName = directories .pop ();
172+
173+ let currentDirectory = rootFolder .find (directory => directory .name === directories[0 ]);
174+
175+ if (! currentDirectory) {
176+ currentDirectory = { name: directories .shift (), children: [] };
177+ rootFolder .push (currentDirectory);
178+ }
179+
180+ currentDirectory = directories .reduce ((parent , name ) => {
181+ return this .findOrCreateDirectory (parent, name);
182+ }, currentDirectory);
183+
184+ const file = { name: fileName, content: fileContent };
185+ currentDirectory .children .push (file);
186+ },
187+ findOrCreateDirectory (directory , name ) {
188+ let subdirectory = directory .children .find (child => child .name === name);
189+
190+ if (! subdirectory) {
191+ subdirectory = { name, children: [] };
192+ directory .children .push (subdirectory);
193+ }
194+
195+ return subdirectory;
196+ },
132197 saveSolution (file ) {
133- localStorage .setItem (this .currentExercise .workshop .code + ' .' + this .currentExercise .exercise .slug + ' .' + file .name , file .content );
134- console .log (file);
198+ const filePath = toFilePath (file);
199+
200+ localStorage .setItem (
201+ this .currentExercise .workshop .code + ' .' + this .currentExercise .exercise .slug + ' .' + filePath,
202+ file .content
203+ );
135204 },
136205 resetState () {
137206 const currentExercise = this .currentExercise ;
@@ -186,7 +255,7 @@ export default {
186255 this .openPassNotification = false ;
187256 },
188257 deleteFileOrFolder (file ) {
189- const confirm = this .$refs .deleteFileConfirm ;
258+ const confirm = this .$refs .confirm ;
190259 const openFiles = this .openFiles ;
191260 const findAndActivateNearestTab = this .findAndActivateNearestTab ;
192261 const entryPoint = this .entryPoint ;
@@ -348,7 +417,7 @@ export default {
348417 :first-run-loaded =" firstRunLoaded"
349418 :first-verify-loaded =" firstVerifyLoaded" :problem-modal-open =" openProblemModal" ></tour >
350419
351- <confirm ref =" deleteFileConfirm " ></confirm >
420+ <confirm ref =" confirm " ></confirm >
352421
353422 <pass-notification
354423 v-if =" openPassNotification"
@@ -365,7 +434,8 @@ export default {
365434 :file-select-function =" studentSelectFile"
366435 :initial-selected-item =" studentFiles[0]"
367436 :delete-function =" deleteFileOrFolder"
368- show-controls />
437+ show-controls
438+ @reset =" resetFiles" />
369439 </div >
370440 <div class =" flex border-l border-solid border-gray-600 p-4 h-full"
371441 :class =" [openResults ? 'w-3/5' : 'w-4/5']" >
0 commit comments