Skip to content

Commit 8d2f1fa

Browse files
authored
Merge pull request #19 from Sachin1801/fix/feedback-1809
Fix: directory filtering and selection for student accounts
2 parents d9761a4 + 3ff5b2f commit 8d2f1fa

6 files changed

Lines changed: 121 additions & 57 deletions

File tree

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎dist/templates/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/svg+xml" href="python-icon.svg"><link rel="alternate icon" href="python-icon.svg"><link rel="shortcut icon" href="python-icon.svg"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet"><script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script><link href="/static/css/prism-tomorrow-consistent.css" rel="stylesheet"/><script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script><title>CS3 IDE</title><script defer="defer" src="static/js/chunk-vendors.99c95c1c.js"></script><script defer="defer" src="static/js/app.e9c47725.js"></script><link href="static/css/chunk-vendors.6b1238e4.css" rel="stylesheet"><link href="static/css/app.94ef51a2.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but Python Web IDE doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
1+
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/svg+xml" href="python-icon.svg"><link rel="alternate icon" href="python-icon.svg"><link rel="shortcut icon" href="python-icon.svg"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet"><script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script><link href="/static/css/prism-tomorrow-consistent.css" rel="stylesheet"/><script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script><title>CS3 IDE</title><script defer="defer" src="static/js/chunk-vendors.99c95c1c.js"></script><script defer="defer" src="static/js/app.bf7c19e0.js"></script><link href="static/css/chunk-vendors.6b1238e4.css" rel="stylesheet"><link href="static/css/app.94ef51a2.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but Python Web IDE doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

‎src/components/element/pages/ide/dialog/DialogNewFile.vue‎

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
</div>
2323
<div class="directory-tree" v-if="showDirectoryTree">
2424
<div
25-
v-for="dir in directories"
25+
v-for="dir in visibleDirectories"
2626
:key="dir.path"
2727
class="directory-item"
2828
:class="{
@@ -137,6 +137,12 @@ export default {
137137
if (!this.fileName) return '';
138138
const lastDot = this.fileName.lastIndexOf('.');
139139
return lastDot > 0 ? this.fileName.substring(lastDot) : '';
140+
},
141+
visibleDirectories() {
142+
return this.directories.filter(dir => {
143+
// Apply student visibility filtering
144+
return this.isDirectoryVisibleToStudent(dir.path);
145+
});
140146
}
141147
},
142148
components: {
@@ -160,11 +166,11 @@ export default {
160166
if (!this.currentUser || this.currentUser.role !== 'student') {
161167
return true; // Show all directories to professors and when not logged in
162168
}
163-
164-
const userPath = `Local/${this.currentUser.username}`;
165-
166-
// Show only the student's own Local/{username}/ directory and its subdirectories
167-
return path === '/' || path.startsWith(userPath);
169+
170+
// For students, since they have their own isolated project (Local/username),
171+
// all directories within their project should be visible to them.
172+
// The project-level filtering already ensures they only see their own project.
173+
return true;
168174
},
169175
170176
loadDirectoryStructure() {
@@ -173,10 +179,12 @@ export default {
173179
// Build directory tree from all projects
174180
this.directories = [];
175181
this.ideInfo.multiRootData.children.forEach(project => {
176-
// For students, only show the Local project (where they can create files)
182+
// For students, only show projects that start with "Local" (student's own directory)
177183
if (this.currentUser && this.currentUser.role === 'student') {
178-
if (project.label !== 'Local') {
179-
return; // Skip non-Local projects for students
184+
// For students, the project is named "Local/username" not just "Local"
185+
const expectedProjectPrefix = `Local/${this.currentUser.username}`;
186+
if (!project.label.startsWith('Local/') || project.label !== expectedProjectPrefix) {
187+
return; // Skip projects that aren't the student's own Local directory
180188
}
181189
}
182190
@@ -188,10 +196,11 @@ export default {
188196
// Fallback to single project mode
189197
const projectLabel = this.ideInfo.currProj.data.label || this.ideInfo.currProj.data.name;
190198
191-
// For students, only process if it's the Local project
199+
// For students, only process if it's their own Local project
192200
if (this.currentUser && this.currentUser.role === 'student') {
193-
if (projectLabel !== 'Local') {
194-
this.directories = []; // Don't show any directories for non-Local projects
201+
const expectedProjectName = `Local/${this.currentUser.username}`;
202+
if (projectLabel !== expectedProjectName) {
203+
this.directories = []; // Don't show any directories for non-student projects
195204
return;
196205
}
197206
}
@@ -201,8 +210,8 @@ export default {
201210
202211
// For students, always force default to Local project and their Local directory
203212
if (this.currentUser && this.currentUser.role === 'student') {
204-
// Always default students to the Local project
205-
this.currentProject = 'Local';
213+
// Always default students to the Local project (which is named Local/{username})
214+
this.currentProject = `Local/${this.currentUser.username}`;
206215
207216
// Always default to their user directory, regardless of current selection
208217
const userPath = `Local/${this.currentUser.username}`;
@@ -211,8 +220,18 @@ export default {
211220
if (userDir) {
212221
this.currentPath = userPath;
213222
} else {
214-
// Fallback to Local root if user directory not found
215-
this.currentPath = '/';
223+
// For students, since their "Local" project maps to their personal directory,
224+
// default to the root of the Local project, which should display as "Local/{username}"
225+
// We need to find the first available directory or use the project root
226+
if (this.directories.length > 0) {
227+
// Use the first directory that's not a root-level project
228+
const expectedProjectName = `Local/${this.currentUser.username}`;
229+
const firstDir = this.directories.find(dir => !dir.isRoot && dir.projectName === expectedProjectName);
230+
this.currentPath = firstDir ? firstDir.path : '/';
231+
} else {
232+
// If no directories are found, use root which will display as the project name
233+
this.currentPath = '/';
234+
}
216235
}
217236
} else {
218237
// For professors, set current path to selected node if it's a directory
@@ -296,6 +315,10 @@ export default {
296315
297316
if (this.currentProject) {
298317
if (path === '/') {
318+
// Special case for students: when they're in Local project root, show their username
319+
if (this.currentUser && this.currentUser.role === 'student' && this.currentProject === 'Local') {
320+
return `Local/${this.currentUser.username}`;
321+
}
299322
return this.currentProject;
300323
}
301324
// Only add project name if path doesn't already contain it
@@ -429,10 +452,27 @@ export default {
429452
},
430453
async onCreate() {
431454
if (!this.fileName || this.fileNameError) return;
432-
455+
433456
const fileName = this.fileName;
434-
const parentPath = this.currentPath;
435-
const projectName = this.currentProject || this.ideInfo.currProj?.data?.name || this.ideInfo.currProj?.config?.name;
457+
let parentPath = this.currentPath;
458+
let projectName = this.currentProject || this.ideInfo.currProj?.data?.name || this.ideInfo.currProj?.config?.name;
459+
460+
// Special handling for students: translate Local project paths to actual student directory
461+
if (this.currentUser && this.currentUser.role === 'student' && projectName === 'Local') {
462+
// For students, when they're in the "Local" project, we need to send the actual student path
463+
if (parentPath === '/' || parentPath === `Local/${this.currentUser.username}`) {
464+
// Student is at their root directory, send the actual path
465+
parentPath = `Local/${this.currentUser.username}`;
466+
projectName = ''; // Clear project name since we're sending the full path
467+
} else if (parentPath.startsWith(`Local/${this.currentUser.username}/`)) {
468+
// Student is in a subdirectory, path is already correct
469+
projectName = ''; // Clear project name since we're sending the full path
470+
} else {
471+
// Fallback: ensure student path is correct
472+
parentPath = `Local/${this.currentUser.username}${parentPath === '/' ? '' : parentPath}`;
473+
projectName = ''; // Clear project name since we're sending the full path
474+
}
475+
}
436476
437477
// Check if file already exists
438478
const existingFile = this.checkFileExists(fileName, parentPath, projectName);

‎src/components/element/pages/ide/dialog/DialogNewFolder.vue‎

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ export default {
159159
if (!this.currentUser || this.currentUser.role !== 'student') {
160160
return true; // Show all directories to professors and when not logged in
161161
}
162-
163-
const userPath = `Local/${this.currentUser.username}`;
164-
165-
// Show only the student's own Local/{username}/ directory and its subdirectories
166-
return path === '/' || path.startsWith(userPath);
162+
163+
// For students, since they have their own isolated project (Local/username),
164+
// all directories within their project should be visible to them.
165+
// The project-level filtering already ensures they only see their own project.
166+
return true;
167167
},
168168
169169
loadDirectoryStructure() {
@@ -172,10 +172,12 @@ export default {
172172
// Build directory tree from all projects
173173
this.directories = [];
174174
this.ideInfo.multiRootData.children.forEach(project => {
175-
// For students, only show the Local project (where they can create folders)
175+
// For students, only show projects that start with "Local" (student's own directory)
176176
if (this.currentUser && this.currentUser.role === 'student') {
177-
if (project.label !== 'Local') {
178-
return; // Skip non-Local projects for students
177+
// For students, the project is named "Local/username" not just "Local"
178+
const expectedProjectPrefix = `Local/${this.currentUser.username}`;
179+
if (!project.label.startsWith('Local/') || project.label !== expectedProjectPrefix) {
180+
return; // Skip projects that aren't the student's own Local directory
179181
}
180182
}
181183
@@ -187,10 +189,11 @@ export default {
187189
// Fallback to single project mode
188190
const projectLabel = this.ideInfo.currProj.data.label || this.ideInfo.currProj.data.name;
189191
190-
// For students, only process if it's the Local project
192+
// For students, only process if it's their own Local project
191193
if (this.currentUser && this.currentUser.role === 'student') {
192-
if (projectLabel !== 'Local') {
193-
this.directories = []; // Don't show any directories for non-Local projects
194+
const expectedProjectName = `Local/${this.currentUser.username}`;
195+
if (projectLabel !== expectedProjectName) {
196+
this.directories = []; // Don't show any directories for non-student projects
194197
return;
195198
}
196199
}
@@ -214,21 +217,13 @@ export default {
214217
});
215218
}
216219
217-
// For students, always force default to Local project and their Local directory
220+
// For students, always force default to their Local project and directory
218221
if (this.currentUser && this.currentUser.role === 'student') {
219-
// Always default students to the Local project
220-
this.currentProject = 'Local';
221-
222-
// Always default to their user directory, regardless of current selection
223-
const userPath = `Local/${this.currentUser.username}`;
224-
// Check if the user's directory exists in the directories list
225-
const userDir = this.directories.find(dir => dir.path === userPath);
226-
if (userDir) {
227-
this.currentPath = userPath;
228-
} else {
229-
// Fallback to Local root if user directory not found
230-
this.currentPath = '/';
231-
}
222+
// Always default students to their Local/username project
223+
this.currentProject = `Local/${this.currentUser.username}`;
224+
225+
// Always default to their user directory root (which is the project root for them)
226+
this.currentPath = '/';
232227
} else {
233228
// For professors, set current path to selected node if it's a directory
234229
if (this.ideInfo.nodeSelected) {
@@ -366,6 +361,10 @@ export default {
366361
367362
if (this.currentProject) {
368363
if (path === '/') {
364+
// Special case for students: when they're in Local project root, show their username
365+
if (this.currentUser && this.currentUser.role === 'student' && this.currentProject === 'Local') {
366+
return `Local/${this.currentUser.username}`;
367+
}
369368
return this.currentProject;
370369
}
371370
// Only add project name if path doesn't already contain it
@@ -440,16 +439,36 @@ export default {
440439
},
441440
async onCreate() {
442441
if (!this.folderName || this.folderNameError) return;
443-
442+
444443
this.creating = true;
445-
444+
446445
try {
447446
const folderName = this.folderName;
448-
const parentPath = this.currentPath;
449-
const projectName = this.currentProject || this.ideInfo.currProj?.data?.name || this.ideInfo.currProj?.config?.name;
447+
let parentPath = this.currentPath;
448+
let projectName = this.currentProject || this.ideInfo.currProj?.data?.name || this.ideInfo.currProj?.config?.name;
450449
451450
// Handle root-level folder creation for professors
452451
const isRootCreation = parentPath === 'ROOT_LEVEL';
452+
453+
if (!isRootCreation) {
454+
// Special handling for students: translate Local project paths to actual student directory
455+
if (this.currentUser && this.currentUser.role === 'student' && projectName === 'Local') {
456+
// For students, when they're in the "Local" project, we need to send the actual student path
457+
if (parentPath === '/' || parentPath === `Local/${this.currentUser.username}`) {
458+
// Student is at their root directory, send the actual path
459+
parentPath = `Local/${this.currentUser.username}`;
460+
projectName = ''; // Clear project name since we're sending the full path
461+
} else if (parentPath.startsWith(`Local/${this.currentUser.username}/`)) {
462+
// Student is in a subdirectory, path is already correct
463+
projectName = ''; // Clear project name since we're sending the full path
464+
} else {
465+
// Fallback: ensure student path is correct
466+
parentPath = `Local/${this.currentUser.username}${parentPath === '/' ? '' : parentPath}`;
467+
projectName = ''; // Clear project name since we're sending the full path
468+
}
469+
}
470+
}
471+
453472
const actualParentPath = isRootCreation ? '' : parentPath;
454473
const actualProjectName = isRootCreation ? '' : projectName;
455474
@@ -568,7 +587,12 @@ export default {
568587
return null;
569588
},
570589
visibleDirectories() {
571-
return this.directories.filter(dir => this.isDirectoryVisible(dir));
590+
return this.directories.filter(dir => {
591+
// Apply both collapse filtering and student visibility filtering
592+
const isVisible = this.isDirectoryVisible(dir);
593+
const isStudentVisible = this.isDirectoryVisibleToStudent(dir.path);
594+
return isVisible && isStudentVisible;
595+
});
572596
}
573597
}
574598
}

0 commit comments

Comments
 (0)