Skip to content
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

SKIL-487 #769

Merged
merged 88 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
d2ba837
started working on deleting teams
Mr615-TN Oct 11, 2024
bb0c4f9
Merge branch 'master' into SKIL-487
Mr615-TN Oct 11, 2024
47cb884
working on AdminDeleteTeam.js
Mr615-TN Oct 12, 2024
a603632
working on admin delete teams
Mr615-TN Oct 12, 2024
9330303
working on AdminDeleteTeam.js
Mr615-TN Oct 12, 2024
7031e72
working on AdminDeleteTeam.js
Mr615-TN Oct 12, 2024
1488a16
working on AdminDeleteTeam.js
Mr615-TN Oct 12, 2024
33a3939
did a minor change, but still need to finish
Mr615-TN Oct 12, 2024
610caf6
added a little bit to the AdminDeleteTeam.js, need to do the return s…
Mr615-TN Oct 13, 2024
256ec7a
added basic return statement which is currently similar to AdminAddTe…
Mr615-TN Oct 13, 2024
caed60f
continued reworking admin Delete Team
Mr615-TN Oct 13, 2024
fec8a4a
finished reworking the AdminDeleteTeam.js
Mr615-TN Oct 13, 2024
019ce79
added some more stuff in AdminDeleteTeam.js and removed some stuff
Mr615-TN Oct 13, 2024
8661ca0
started working on adding delete teams tab, but not sure if its neces…
Mr615-TN Oct 14, 2024
04f95cc
added to AppState.js and also added a todo for me to fix
Mr615-TN Oct 14, 2024
ea26d1b
added to AppState.js and also added a todo for me to fix
Mr615-TN Oct 14, 2024
7492c06
fixed the issue I had, but I need to do some more things to get funct…
Mr615-TN Oct 14, 2024
8bce217
Merge branch 'master' into SKIL-487
Mr615-TN Oct 15, 2024
9831ae5
misunderstood the task and went down the wrong rabbit hole of doing t…
Mr615-TN Oct 15, 2024
b1a5c51
Merge branch 'master' into SKIL-487
Mr615-TN Oct 15, 2024
d5f1eff
working on SKIL-487
Mr615-TN Oct 15, 2024
5a1f07e
Merge branch 'master' into SKIL-487
Mr615-TN Oct 16, 2024
c588a53
working on SKIL-487
Mr615-TN Oct 16, 2024
e8db3d1
working on skil-487
Mr615-TN Oct 16, 2024
d353b6d
Merge branch 'master' into SKIL-487
Mr615-TN Oct 17, 2024
0f31a44
removed a line that was unnnecessary
Mr615-TN Oct 18, 2024
dc56a57
working on Delete button
Mr615-TN Oct 20, 2024
c1e65f1
uncommented my deleteTeams portion, but need to figure out how to get…
Mr615-TN Oct 20, 2024
1aeeb60
Started figuring out way to delete team in adminViewTeams
Mr615-TN Oct 20, 2024
25e5b8a
Merge branch 'master' into SKIL-487
Mr615-TN Oct 21, 2024
7cfbe58
added deleteTeam function for AdminViewTeams.js
Mr615-TN Oct 21, 2024
41d1fc7
Merge branch 'master' into SKIL-487
Mr615-TN Oct 22, 2024
9146871
Merge branch 'master' into SKIL-487
Mr615-TN Oct 22, 2024
691df06
working on SKIL-487
Mr615-TN Oct 22, 2024
26a1a39
commented out the deleteTeam function in AdminViewTeams.js, doesn't s…
Mr615-TN Oct 23, 2024
807f002
added console.log to see what is going on
Mr615-TN Oct 24, 2024
5fe51ef
Merge branch 'master' into SKIL-487
Mr615-TN Oct 24, 2024
8c1ed12
Merge branch 'master' into SKIL-487
Mr615-TN Oct 24, 2024
6d8b0a6
Merge branch 'SKIL-487' of https://github.com/Lunatic-Labs/rubricapp …
Mr615-TN Oct 24, 2024
e7b4d71
working on SKIL-487
Mr615-TN Oct 24, 2024
e0ea1f4
Merge branch 'master' into SKIL-487
Mr615-TN Oct 25, 2024
1d1e1bc
testing delete teams
Mr615-TN Oct 25, 2024
91f6e08
working on Delete Teams
Mr615-TN Oct 25, 2024
9de95ad
working on DeleteTeams, getting bad response, need to figure out why
Mr615-TN Oct 26, 2024
389574d
Merge branch 'master' into SKIL-487
Mr615-TN Oct 28, 2024
300df0d
trying something to see if the delete teams button actually deleted t…
Mr615-TN Oct 28, 2024
94f55a2
tried some other changes, but it didn't work so came back to a slight…
Mr615-TN Oct 28, 2024
047de04
Merge branch 'master' into SKIL-487
Mr615-TN Oct 29, 2024
bd07439
Merge branch 'master' into SKIL-487
Mr615-TN Oct 29, 2024
7f1e60c
testing boolean and printing associated tasks
Mr615-TN Oct 30, 2024
fa4a2bd
testing boolean and printing associated tasks
Mr615-TN Oct 30, 2024
c435f22
adding stuff
Mr615-TN Oct 30, 2024
0170323
I think I got it working? I don't know if it is the right way, but it…
Mr615-TN Oct 30, 2024
a06b685
Merge branch 'master' into SKIL-487
Mr615-TN Oct 30, 2024
cd84711
testing
Mr615-TN Oct 30, 2024
e30516e
trying something to delete teams, but for some reason, get_assessment…
Mr615-TN Oct 30, 2024
a8be5a9
slightly edited the code to try it see if delete teams is work, but i…
Mr615-TN Oct 30, 2024
a6bd7c8
tried another method to retrive assessment tasks for the team id, but…
Mr615-TN Oct 30, 2024
844cdc8
Merge branch 'master' into SKIL-487
Mr615-TN Oct 31, 2024
374d6c4
made some changes on friday but were never changed
Mr615-TN Nov 4, 2024
3dd3ad8
Merge branch 'master' into SKIL-487
Mr615-TN Nov 4, 2024
00f3318
Merge branch 'master' into SKIL-487
Mr615-TN Nov 4, 2024
4557b1b
I think the delete teams functionality is working
Mr615-TN Nov 5, 2024
0a7f833
removed some not necessary code and tried some stuff
Mr615-TN Nov 5, 2024
480fc78
other than the notification explaining why you can't delete teams tha…
Mr615-TN Nov 5, 2024
0f1bc22
working on deleteTeams functionailty, it is almost done, just putting…
Mr615-TN Nov 6, 2024
4f75ec5
working on trying to get the notification stuff up and the auto refre…
Mr615-TN Nov 6, 2024
f6ef780
minor modifications, but kind of stuck on what to do
Mr615-TN Nov 6, 2024
0b5e92e
currently, componentDidUpdate automatically refreshes the page if del…
Mr615-TN Nov 7, 2024
239b3fd
Merge branch 'master' into SKIL-487
Mr615-TN Nov 7, 2024
841acd6
trying something, for some reason, the delete teams stuff is not bein…
Mr615-TN Nov 7, 2024
65bb2ac
Merge branch 'master' into SKIL-487
Mr615-TN Nov 11, 2024
55250e1
Merge branch 'master' into SKIL-487
Mr615-TN Nov 12, 2024
bb78ada
working on fixing the issue I have
Mr615-TN Nov 13, 2024
5616383
Merge branch 'master' into SKIL-487
Mr615-TN Nov 13, 2024
ed2eeb2
working on trying to figure out why the async stuff is not working
Mr615-TN Nov 13, 2024
94a6e33
workign on trying ot figure out error
Mr615-TN Nov 13, 2024
907b500
fixed my docker issue, now to get the notification and refresh setup
Mr615-TN Nov 13, 2024
a4b4a57
in the process of figuring out the notification and page refresh stuff
Mr615-TN Nov 13, 2024
12444c6
working on getting notification and auto refresh working
Mr615-TN Nov 14, 2024
236d1a9
testing stuff to see if notifs and auto refresh can work
Mr615-TN Nov 16, 2024
93889aa
I am pretty sure I got it working now
Mr615-TN Nov 16, 2024
126a881
commented out console.logs and print statements
Mr615-TN Nov 17, 2024
9be210c
testing stuff
Mr615-TN Nov 18, 2024
b96083b
removed console.logs and print statements
Mr615-TN Nov 18, 2024
43ba0b4
Merge branch 'master' into SKIL-487
Mr615-TN Nov 19, 2024
b670a93
removed extra print statement
Mr615-TN Nov 19, 2024
a955cc2
removed extra unnecessary code
Mr615-TN Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions BackEndFlask/controller/Routes/Completed_assessment_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,26 @@ def get_all_completed_assessments():
except Exception as e:
return create_bad_response(f"An error occurred retrieving all completed assessments: {e}", "completed_assessments", 400)

@bp.route('/completed_assessment', methods = ['GET'])
@jwt_required()
@bad_token_check()
@AuthCheck()
def get_completed_assessment_by_team_or_user_id():
try:
completed_assessment_id = request.args.get("completed_assessment_id")
unit = request.args.get("unit")
if not completed_assessment_id:
return create_bad_response("No completed_assessment_id provided", "completed_assessments", 400)

if unit == "team":
one_completed_assessment = get_completed_assessment_with_team_name(completed_assessment_id)
elif unit == "user":
one_completed_assessment = get_completed_assessment_with_user_name(completed_assessment_id)
else:
create_bad_response("Invalid unit provided", "completed_assessments", 400)
return create_good_response(completed_assessment_schema.dump(one_completed_assessment), 200, "completed_assessments")
except Exception as e:
return create_bad_response(f"An error occurred fetching a completed assessment: {e}", "completed_assessments", 400)

@bp.route('/completed_assessment', methods = ['POST'])
@jwt_required()
Expand Down
45 changes: 38 additions & 7 deletions BackEndFlask/controller/Routes/Team_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
get_team_by_course_id,
create_team,
get_teams_by_observer_id,
replace_team
replace_team,
delete_team
)
from models.assessment_task import get_assessment_tasks_by_team_id
from models.completed_assessment import completed_assessment_team_or_user_exists
from models.team_user import *
from controller.security.CustomDecorators import AuthCheck, bad_token_check
from models.queries import (
Expand Down Expand Up @@ -94,14 +97,14 @@ def get_nonfull_adhoc_teams():
try:
if request.args and request.args.get("assessment_task_id"):
assessment_task_id = int(request.args.get("assessment_task_id"))
valid_teams = [{"team_name": f"Team {team}", "team_id": team} for team in get_all_nonfull_adhoc_teams(assessment_task_id)]
return create_good_response(valid_teams, 200, "teams")

valid_teams = [{"team_name": f"Team {team}", "team_id": team} for team in get_all_nonfull_adhoc_teams(assessment_task_id)]

return create_good_response(valid_teams, 200, "teams")

except Exception as e:
return create_bad_response(f"An error occurred getting nonfull adhoc teams {e}", "teams", 400)


@bp.route('/team', methods = ['POST'])
@jwt_required()
Expand Down Expand Up @@ -167,6 +170,34 @@ def update_team_user_by_edit():
except Exception as e:
return create_bad_response(f"An error occurred updating a team: {e}", "teams", 400)

@bp.route('/team', methods = ['DELETE'])
@jwt_required()
@bad_token_check()
@AuthCheck()
def delete_selected_teams():
try:
if request.args and request.args.get("team_id"):
team_id = int(request.args.get("team_id"))
team = get_team(team_id)
if not team:
return create_bad_response("Team does not exist", "teams", 400)

associated_tasks = completed_assessment_team_or_user_exists(team_id, user_id=None)
if associated_tasks is None:
associated_tasks = []
if len(associated_tasks) > 0:
refetched_tasks = completed_assessment_team_or_user_exists(team_id, user_id=None)
if not refetched_tasks:
delete_team(team_id)
return create_good_response([], 200, "teams")
else:
return create_bad_response("Cannot delete team with associated tasks", "teams", 400)
else:
delete_team(team_id)
return create_good_response([], 200, "teams")

except Exception as e:
return create_bad_response(f"An error occurred deleting a team: {e}", "teams", 400)

class TeamSchema(ma.Schema):
class Meta:
Expand Down
3 changes: 1 addition & 2 deletions BackEndFlask/models/assessment_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def get_assessment_tasks_by_role_id(role_id):

@error_log
def get_assessment_tasks_by_team_id(team_id):
return db.session.query(AssessmentTask).join(Team, AssessmentTask.course_id == Team.course_id).filter(
db.session.query(AssessmentTask).join(Team, AssessmentTask.course_id == Team.course_id).filter(
Team.team_id == team_id
and
(
Expand All @@ -72,7 +72,6 @@ def get_assessment_tasks_by_team_id(team_id):
(AssessmentTask.due_date >= Team.date_created and AssessmentTask.due_date <= Team.active_until)
)
).all()

@error_log
def get_assessment_task(assessment_task_id):
one_assessment_task = AssessmentTask.query.filter_by(assessment_task_id=assessment_task_id).first()
Expand Down
8 changes: 8 additions & 0 deletions BackEndFlask/models/completed_assessment.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ def completed_assessment_exists(team_id, assessment_task_id, user_id):
else:
return CompletedAssessment.query.filter_by(user_id=user_id, assessment_task_id=assessment_task_id).first()

@error_log
def completed_assessment_team_or_user_exists(team_id, user_id):
if team_id is not None:
return CompletedAssessment.query.filter_by(team_id=team_id).all()
elif user_id is not None:
return CompletedAssessment.query.filter_by(user_id=user_id).all()
else:
return []

@error_log
def create_completed_assessment(completed_assessment_data):
Expand Down
258 changes: 146 additions & 112 deletions FrontEndReact/src/View/Admin/View/ViewTeams/AdminViewTeams.js
Original file line number Diff line number Diff line change
@@ -1,118 +1,152 @@
import 'bootstrap/dist/css/bootstrap.css';
import React, { Component } from 'react';
import ErrorMessage from '../../../Error/ErrorMessage.js';
import ViewTeams from './ViewTeams.js';
import { genericResourceGET, parseUserNames } from '../../../../utility.js';
import { Box, Button, Typography } from '@mui/material';
import Loading from '../../../Loading/Loading.js';
import SuccessMessage from '../../../Success/SuccessMessage.js';


import "bootstrap/dist/css/bootstrap.css";
import React, { Component } from "react";
import ErrorMessage from "../../../Error/ErrorMessage.js";
import ViewTeams from "./ViewTeams.js";
import { genericResourceGET,
parseUserNames } from "../../../../utility.js";
import { Box, Button, Typography } from "@mui/material";
import Loading from "../../../Loading/Loading.js";
import SuccessMessage from "../../../Success/SuccessMessage.js";

class AdminViewTeams extends Component {
constructor(props) {
super(props);

this.state = {
errorMessage: null,
isLoaded: false,
teams: null,
users: null
}
}

componentDidMount() {
var navbar = this.props.navbar;
var state = navbar.state;
var chosenCourse = state.chosenCourse;

genericResourceGET(`/team?course_id=${chosenCourse["course_id"]}`, "teams", this);

var url = (
chosenCourse["use_tas"] ?
`/user?course_id=${chosenCourse["course_id"]}&role_id=4` :
`/user?uid=${chosenCourse["admin_id"]}`
);

genericResourceGET(url, "users", this);
constructor(props) {
super(props);

this.state = {
errorMessage: null,
isLoaded: false,
teams: null,
users: null,
prevTeamsLength: 0,
successMessage: null
};
}


fetchData = () => {
var navbar = this.props.navbar;
var state = navbar.state;
var chosenCourse = state.chosenCourse;

genericResourceGET(
`/team?course_id=${chosenCourse["course_id"]}`,
"teams",
this,
);

var url = chosenCourse["use_tas"]
? `/user?course_id=${chosenCourse["course_id"]}&role_id=4`
: `/user?uid=${chosenCourse["admin_id"]}`;

genericResourceGET(url, "users", this);
};

componentDidMount() {
this.fetchData();
}


componentDidUpdate(){
if (this.state.teams && this.state.teams.length !== this.state.prevTeamsLength) {
this.setState({ prevTeamsLength: this.state.teams.length });
this.fetchData();
}

render() {
const {
errorMessage,
isLoaded,
teams,
users
} = this.state;

var navbar = this.props.navbar;

navbar.adminViewTeams.teams = teams;
navbar.adminViewTeams.users = users ? parseUserNames(users) : [];

var setNewTab = navbar.setNewTab;
var setAddTeamTabWithUsers = navbar.setAddTeamTabWithUsers;

if (errorMessage) {
return(
<div className='container'>
<ErrorMessage
fetchedResource={"Teams"}
errorMessage={errorMessage}
/>
</div>
)

} else if (!isLoaded || !teams || !users) {
return(
<Loading />
)

} else {
return(
<Box>
{navbar.state.successMessage !== null &&
<div className='container'>
<SuccessMessage
successMessage={navbar.state.successMessage}
aria-label="adminViewTeamsSuccessMessage"
/>
</div>
}
<Box sx={{mb:"20px"}}className="subcontent-spacing" >
<Typography sx={{fontWeight:'700'}} variant="h5">Teams</Typography>
<Box sx={{display:"flex", gap:"20px"}}>
<Button className='primary-color'
variant='contained'
onClick={() => {
setNewTab("AdminTeamBulkUpload");
}}
aria-label="adminBulkUploadButton"
>
Team Bulk Upload
</Button>
<Button className='primary-color'
variant='contained'
onClick={() => {
setAddTeamTabWithUsers(users);
}}
aria-label="adminAddTeamButton"
>
Add Team
</Button>
</Box>
</Box>
<Box className="table-spacing">
<ViewTeams
navbar={this.props.navbar}
teams={teams}
users={users ? parseUserNames(users) : []}
/>
</Box>
</Box>
)
}
}
setErrorMessage = (message) => {
this.setState({ errorMessage: message });
// Clear error message after 3 seconds
setTimeout(() => {
this.setState({ errorMessage: null });
}, 3000);
}

setSuccessMessage = (message) => {
this.setState({ successMessage: message });
// Clear success message after 3 seconds
setTimeout(() => {
this.setState({ successMessage: null });
}, 3000);
}
render() {
const { errorMessage, isLoaded, teams, users, successMessage } = this.state;

var navbar = this.props.navbar;

navbar.adminViewTeams.teams = teams;
navbar.adminViewTeams.users = users ? parseUserNames(users) : [];

var setNewTab = navbar.setNewTab;
var setAddTeamTabWithUsers = navbar.setAddTeamTabWithUsers;

if (errorMessage) {
return (
<div className="container">
<ErrorMessage fetchedResource={"Teams"} errorMessage={errorMessage} />
</div>
);
} else if (!isLoaded || !teams || !users) {
return <Loading />;
} else {
return (
<Box>
{successMessage && (
<div className="container">
<SuccessMessage
successMessage={successMessage}
aria-label="adminViewTeamsSuccessMessage"
/>
</div>
)}
{errorMessage && (
<div className="container">
<ErrorMessage
fetchedResource={"Teams"}
errorMessage={errorMessage}
aria-label="adminViewTeamsErrorMessage"
/>
</div>
)}
<Box sx={{ mb: "20px" }} className="subcontent-spacing">
<Typography sx={{ fontWeight: "700" }} variant="h5">
Teams
</Typography>
<Box sx={{ display: "flex", gap: "20px" }}>
<Button
className="primary-color"
variant="contained"
onClick={() => {
setNewTab("AdminTeamBulkUpload");
}}
aria-label="adminBulkUploadButton"
>
Team Bulk Upload
</Button>
<Button
className="primary-color"
variant="contained"
onClick={() => {
setAddTeamTabWithUsers(users);
}}
aria-label="adminAddTeamButton"
>
Add Team
</Button>
</Box>
</Box>
<Box className="table-spacing">
<ViewTeams
navbar={this.props.navbar}
teams={teams}
users={users ? parseUserNames(users) : []}
onError={this.setErrorMessage}
onSuccess={this.setSuccessMessage}
refreshData={this.fetchData}
/>
</Box>
</Box>
);
}
}
}

export default AdminViewTeams;
export default AdminViewTeams;
Loading
Loading