Add ability to change class instructor
This commit is contained in:
parent
f88941993c
commit
868aa018a4
|
@ -15,6 +15,7 @@ import datetime, time
|
||||||
|
|
||||||
from . import models, fields, utils, utils_ldap, utils_auth, utils_stats
|
from . import models, fields, utils, utils_ldap, utils_auth, utils_stats
|
||||||
from .. import settings, secrets
|
from .. import settings, secrets
|
||||||
|
from .permissions import is_admin_director
|
||||||
|
|
||||||
class UsageSerializer(serializers.ModelSerializer):
|
class UsageSerializer(serializers.ModelSerializer):
|
||||||
first_name = serializers.SerializerMethodField()
|
first_name = serializers.SerializerMethodField()
|
||||||
|
@ -482,7 +483,7 @@ class SessionSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Session
|
model = models.Session
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = ['old_instructor', 'instructor']
|
read_only_fields = ['old_instructor']
|
||||||
|
|
||||||
def get_student_count(self, obj):
|
def get_student_count(self, obj):
|
||||||
return len([x for x in obj.students.all() if x.attendance_status != 'Withdrawn'])
|
return len([x for x in obj.students.all() if x.attendance_status != 'Withdrawn'])
|
||||||
|
@ -503,6 +504,17 @@ class SessionSerializer(serializers.ModelSerializer):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
if not self.initial_data.get('instructor_id', None):
|
||||||
|
raise ValidationError(dict(instructor_id='This field is required.'))
|
||||||
|
|
||||||
|
member = get_object_or_404(models.Member, id=self.initial_data['instructor_id'])
|
||||||
|
if not (is_admin_director(member.user) or member.is_instructor):
|
||||||
|
raise ValidationError(dict(instructor_id='Member is not an instructor.'))
|
||||||
|
|
||||||
|
validated_data['instructor'] = member.user
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
class SessionListSerializer(SessionSerializer):
|
class SessionListSerializer(SessionSerializer):
|
||||||
students = None
|
students = None
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,8 @@ export function InstructorClassAttendance(props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function InstructorClassEditor(props) {
|
function InstructorClassEditor(props) {
|
||||||
const { input, setInput, error, editing } = props;
|
const { input, setInput, error, editing, token } = props;
|
||||||
|
const [editInstructor, setEditInstructor] = useState(false);
|
||||||
|
|
||||||
const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value });
|
const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value });
|
||||||
const handleUpload = (e, v) => setInput({ ...input, [v.name]: e.target.files[0] });
|
const handleUpload = (e, v) => setInput({ ...input, [v.name]: e.target.files[0] });
|
||||||
|
@ -245,6 +246,38 @@ function InstructorClassEditor(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='class-editor'>
|
<div className='class-editor'>
|
||||||
|
{editing &&
|
||||||
|
(editInstructor ?
|
||||||
|
<>
|
||||||
|
<Form.Field error={error.instructor_id}>
|
||||||
|
<label>Instructor (search)</label>
|
||||||
|
<MembersDropdown
|
||||||
|
token={token}
|
||||||
|
{...makeProps('instructor_id')}
|
||||||
|
onChange={handleValues}
|
||||||
|
initial={input.instructor_name}
|
||||||
|
/>
|
||||||
|
{error.instructor_id && <Label pointing prompt>
|
||||||
|
{error.instructor_id}
|
||||||
|
</Label>}
|
||||||
|
</Form.Field>
|
||||||
|
|
||||||
|
<Message info>
|
||||||
|
<Message.Header>Are you sure?</Message.Header>
|
||||||
|
<p>Only the new instructor will be able to edit this class.</p>
|
||||||
|
</Message>
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
<Button
|
||||||
|
onClick={() => setEditInstructor(true)}
|
||||||
|
>
|
||||||
|
Change instructor
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
<p/>
|
||||||
|
|
||||||
<Form.Input
|
<Form.Input
|
||||||
label='Cost ($) — 0 for free'
|
label='Cost ($) — 0 for free'
|
||||||
{...makeProps('cost')}
|
{...makeProps('cost')}
|
||||||
|
@ -326,7 +359,7 @@ export function InstructorClassDetail(props) {
|
||||||
<Form onSubmit={handleSubmit}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<Header size='small'>Edit Class</Header>
|
<Header size='small'>Edit Class</Header>
|
||||||
|
|
||||||
<InstructorClassEditor editing input={input} setInput={setInput} error={error} />
|
<InstructorClassEditor editing input={input} setInput={setInput} error={error} token={token} />
|
||||||
|
|
||||||
<Form.Button loading={loading} error={error.non_field_errors}>
|
<Form.Button loading={loading} error={error.non_field_errors}>
|
||||||
Submit
|
Submit
|
||||||
|
@ -402,7 +435,7 @@ export function InstructorClassList(props) {
|
||||||
|
|
||||||
<p>Documentation: <a href='https://wiki.protospace.ca/Be_a_Course_Instructor' target='_blank' rel='noopener noreferrer'>https://wiki.protospace.ca/Be_a_Course_Instructor</a></p>
|
<p>Documentation: <a href='https://wiki.protospace.ca/Be_a_Course_Instructor' target='_blank' rel='noopener noreferrer'>https://wiki.protospace.ca/Be_a_Course_Instructor</a></p>
|
||||||
|
|
||||||
<InstructorClassEditor input={input} setInput={setInput} error={error} />
|
<InstructorClassEditor input={input} setInput={setInput} error={error} token={token} />
|
||||||
|
|
||||||
<Form.Button loading={loading} error={error.non_field_errors}>
|
<Form.Button loading={loading} error={error.non_field_errors}>
|
||||||
Submit
|
Submit
|
||||||
|
|
Loading…
Reference in New Issue
Block a user