17 |
Będziemy z powrotem wkrótce!
18 |
19 |
Przepraszamy za niedogodności, ale przeprowadzamy w tym momencie prace serwisowe. Jeżeli potrzebujesz, zawsze możesz skontaktować się z nami, w przeciwnym razie prosimy o chwilę cierpliwości.
20 |
— Zespół zapisy.ii.uni.wroc.pl
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/zapisy/apps/theses/users.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import User
2 |
3 | from apps.theses.system_settings import get_master_rejecter
4 | from apps.users.models import Employee, is_employee, is_user_in_group
5 |
6 | THESIS_BOARD_GROUP_NAME = "Komisja prac dyplomowych"
7 |
8 |
9 | def get_theses_board():
10 | """Returns all members of the theses board."""
11 | return Employee.objects.select_related(
12 | 'user'
13 | ).filter(user__groups__name=THESIS_BOARD_GROUP_NAME)
14 |
15 |
16 | def get_num_board_members() -> int:
17 | """Returns the number of theses board members."""
18 | return get_theses_board().count()
19 |
20 |
21 | def is_theses_board_member(user: User) -> bool:
22 | """Is the specified user a member of the theses board?"""
23 | return is_user_in_group(user, THESIS_BOARD_GROUP_NAME)
24 |
25 |
26 | def is_master_rejecter(user: User) -> bool:
27 | """Is the specified user a master rejecter of theses board?"""
28 | return is_employee(user) and get_master_rejecter() == user.employee
29 |
--------------------------------------------------------------------------------
/zapisy/apps/grade/poll/templates/poll/tickets_enter.html:
--------------------------------------------------------------------------------
1 | {% extends "grade/base.html" %}
2 |
3 | {% load crispy_forms_tags %}
4 |
5 | {% block main-subtitle %}Wprowadzanie kluczy{% endblock %}
6 | {% block nav-grade-tickets-enter %}active{% endblock %}
7 |
8 | {% block bread %}
9 | {% include 'grade/_breadcrumbs.html' %}
10 |
4 |
{{course.name}}
5 |
6 | {% if user.is_staff or course.owner == user.employee %}
7 |
Edytuj
8 | {% if course.status|status_label == "draft" %}
9 |
12 | Usuń szkic
13 |
14 | {% endif %}
15 | {% endif %}
16 | {% if user.employee %}
17 |
Sklonuj
18 | {% endif %}
19 |
20 |
21 |
22 | {% include 'proposal/proposal_info.html' with course=course %}
23 |
--------------------------------------------------------------------------------
/zapisy/scripts/copy_reservations.py:
--------------------------------------------------------------------------------
1 | from apps.enrollment.courses.models.semester import Semester
2 | from apps.schedule.models.specialreservation import SpecialReservation
3 | from django.contrib.auth.models import User
4 |
5 | current_year = '2018/19'
6 | next_year = '2019/20'
7 |
8 |
9 | def run():
10 | author_id = User.objects.get(username='asm').id
11 | reservations = SpecialReservation.objects.filter(
12 | semester__year=current_year)
13 | for reservation in reservations:
14 | print(reservation)
15 | if input('Confirm (Y/n):') != 'n':
16 | new_reservation = SpecialReservation(
17 | semester=Semester.objects.get(
18 | year=next_year,
19 | type=reservation.semester.type),
20 | title=reservation.title,
21 | classroom=reservation.classroom,
22 | dayOfWeek=reservation.dayOfWeek,
23 | start_time=reservation.start_time,
24 | end_time=reservation.end_time)
25 | new_reservation.save(author_id)
26 |
--------------------------------------------------------------------------------
/zapisy/apps/enrollment/courses/migrations/0015_auto_20190312_1330.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.0.8 on 2019-03-12 13:30
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('courses', '0014_auto_20190212_1313'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='classroom',
15 | name='usos_id',
16 | field=models.PositiveIntegerField(blank=True, null=True, unique=True, verbose_name='ID sali w systemie USOS'),
17 | ),
18 | migrations.AddField(
19 | model_name='semester',
20 | name='usos_kod',
21 | field=models.CharField(blank=True, max_length=20, null=True, unique=True, verbose_name='Kod semestru w systemie USOS'),
22 | ),
23 | migrations.AddField(
24 | model_name='term',
25 | name='usos_id',
26 | field=models.PositiveIntegerField(blank=True, null=True, unique=True, verbose_name='Kod terminu w systemie USOS'),
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/zapisy/apps/users/migrations/0003_auto_20170601_1122.py:
--------------------------------------------------------------------------------
1 | from django.db import models, migrations
2 | import datetime
3 | from django.conf import settings
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('users', '0002_auto_20170529_1617'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='employee',
15 | name='last_news_view',
16 | field=models.DateTimeField(default=datetime.datetime.now),
17 | preserve_default=True,
18 | ),
19 | migrations.AlterField(
20 | model_name='student',
21 | name='last_news_view',
22 | field=models.DateTimeField(default=datetime.datetime.now),
23 | preserve_default=True,
24 | ),
25 | migrations.AlterField(
26 | model_name='userprofile',
27 | name='user',
28 | field=models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
29 | preserve_default=True,
30 | ),
31 | ]
32 |
--------------------------------------------------------------------------------
/zapisy/apps/schedule/migrations/0008_auto_20191119_0017.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.14 on 2019-11-19 00:17
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('schedule', '0007_auto_20190528_0101'),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name='specialreservation',
16 | name='classroom',
17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Classroom', verbose_name='sala'),
18 | ),
19 | migrations.AlterField(
20 | model_name='specialreservation',
21 | name='semester',
22 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Semester', verbose_name='semestr'),
23 | ),
24 | migrations.AlterField(
25 | model_name='specialreservation',
26 | name='title',
27 | field=models.CharField(max_length=255, verbose_name='nazwa'),
28 | ),
29 | ]
30 |
--------------------------------------------------------------------------------
/zapisy/apps/users/migrations/0007_consents.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by Django 1.11.9 on 2018-05-25 06:06
3 | from __future__ import unicode_literals
4 |
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 |
8 |
9 | class Migration(migrations.Migration):
10 |
11 | dependencies = [
12 | ('users', '0006_auto_20180525_0559'),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name='Consents',
18 | fields=[
19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20 | ('granted', models.NullBooleanField(verbose_name='zgoda udzielona')),
21 | ('student', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='consent', to='users.Student')),
22 | ],
23 | options={
24 | 'verbose_name': 'Zgoda na udostępnianie danych osobowych',
25 | 'verbose_name_plural': 'Zgody na udostępnianie danych osobowych',
26 | },
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/infra/db_backups/slack_notifications.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | from slack import WebClient
3 |
4 |
5 | def get_connected_slack_client(secrets_env):
6 | slack_client = WebClient(token=secrets_env.str('SLACK_TOKEN'))
7 | return slack_client
8 |
9 | # for real time connection
10 | # if slack_client.rtm_connect(with_team_state=False):
11 | # return slack_client
12 | #raise RuntimeError('SlackClient.rtm_connect failed')
13 |
14 |
15 | def _send_slack_msg(slack_client, channel_id: str, msg: str):
16 | slack_client.chat_postMessage(
17 | channel=channel_id,
18 | text=msg
19 | )
20 |
21 |
22 | def send_success_notification(slack_client, dev_db_link: str, seconds_elapsed: int, channel_id: str):
23 | msg = f'Databases backed up successfully in {seconds_elapsed} seconds. *Dev DB download link:* {dev_db_link}'
24 | _send_slack_msg(slack_client, channel_id, msg)
25 |
26 |
27 | def send_error_notification(slack_client, error_msg: str, channel_id: str):
28 | msg = f'*Failed to back up databases:*\n```{error_msg}```'
29 | _send_slack_msg(slack_client, channel_id, msg)
30 |
--------------------------------------------------------------------------------
/zapisy/apps/notifications/custom_signals.py:
--------------------------------------------------------------------------------
1 | import django.dispatch
2 |
3 | # Signal senders must provide `instance` and `user` arguments.
4 | # instance: apps.enrollment.courses.models.Group
5 | # user: django.contrib.auth.models.User
6 | student_pulled = django.dispatch.Signal()
7 | # Signal senders must provide the following arguments:
8 | # instance: apps.enrollment.courses.models.Group
9 | # user: django.contrib.auth.models.User
10 | # reason: str
11 | student_not_pulled = django.dispatch.Signal()
12 | # Signal senders must provide the following arguments:
13 | # instance: apps.enrollment.courses.models.Group
14 | # teacher: apps.users.models.Employee
15 | teacher_changed = django.dispatch.Signal()
16 | # Signal senders must provide an argument:
17 | # instance: apps.theses.models.Thesis
18 | thesis_voting_activated = django.dispatch.Signal()
19 | # Signal senders must provide an argument:
20 | # event: apps.schedule.models.event
21 | event_decision = django.dispatch.Signal()
22 | # Signal senders must provide an argument:
23 | # instance: apps.theses.models.Thesis
24 | thesis_accepted = django.dispatch.Signal()
25 |
--------------------------------------------------------------------------------
/zapisy/apps/offer/proposal/migrations/0006_proposal_semester.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 2.1.8 on 2019-05-12 22:12
2 |
3 | import apps.offer.proposal.models
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ('proposal', '0005_proposal'),
11 | ]
12 |
13 | operations = [
14 | migrations.AddField(
15 | model_name='proposal',
16 | name='smtr',
17 | field=models.CharField(choices=[(apps.offer.proposal.models.SemesterChoices('u'), 'nieokreślony'), (apps.offer.proposal.models.SemesterChoices('z'), 'zimowy'), (apps.offer.proposal.models.SemesterChoices('l'), 'letni')], default=apps.offer.proposal.models.SemesterChoices('u'), max_length=1, verbose_name='semestr'),
18 | ),
19 | migrations.RunSQL(
20 | '''UPDATE proposal_proposal
21 | SET smtr=courses_courseinformation.semester
22 | FROM courses_courseinformation
23 | WHERE proposal_proposal.courseinformation_ptr_id=courses_courseinformation.id;
24 | ''',
25 | ),
26 | ]
27 |
--------------------------------------------------------------------------------
/zapisy/apps/schedulersync/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 1.10.8 on 2018-01-24 16:03
2 |
3 |
4 | from django.db import migrations, models
5 | import django.db.models.deletion
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ('courses', '0006_auto_20171216_1754'),
14 | ]
15 |
16 | operations = [
17 | migrations.CreateModel(
18 | name='TermSyncData',
19 | fields=[
20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21 | ('scheduler_id', models.PositiveIntegerField(null=True, unique=True, verbose_name='id grupy w schedulerze')),
22 | ('term', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Term', verbose_name='termin')),
23 | ],
24 | options={
25 | 'verbose_name': 'Obiekt synchronizacji termin\xf3w grup',
26 | 'verbose_name_plural': 'Obiekty synchronizacji termin\xf3w grup',
27 | },
28 | ),
29 | ]
30 |
--------------------------------------------------------------------------------
/zapisy/apps/effects/models.py:
--------------------------------------------------------------------------------
1 | from typing import Set
2 |
3 | from django.db import models
4 |
5 | from apps.enrollment.courses.models.course_instance import CourseInstance
6 | from apps.users.models import Program, Student
7 |
8 |
9 | # Model for completed courses
10 | class CompletedCourses(models.Model):
11 | student = models.ForeignKey(Student, on_delete=models.CASCADE)
12 | course = models.ForeignKey(CourseInstance, on_delete=models.CASCADE)
13 | program = models.ForeignKey(Program, on_delete=models.CASCADE)
14 |
15 | class Meta:
16 | unique_together = ('student', 'course', 'program')
17 |
18 | def get_completed_effects(student: Student) -> Set[str]:
19 | completed_courses = (
20 | CompletedCourses.objects.filter(student=student, program=student.program)
21 | .select_related('course').prefetch_related('course__effects')
22 | )
23 |
24 | done_effects = set()
25 | for record in completed_courses:
26 | for effect in record.course.effects.all():
27 | done_effects.add(effect.group_name)
28 |
29 | return done_effects
30 |
--------------------------------------------------------------------------------
/zapisy/apps/offer/preferences/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.forms.models import modelformset_factory
3 |
4 | from apps.users.models import Employee
5 |
6 | from .models import Preference
7 |
8 |
9 | class PreferenceForm(forms.ModelForm):
10 | class Meta:
11 | model = Preference
12 | fields = ('answer',)
13 | labels = {
14 | 'answer': "",
15 | }
16 |
17 | def __init__(self, *args, **kwargs):
18 | super(PreferenceForm, self).__init__(*args, **kwargs)
19 | self.fields['answer'].widget.attrs['class'] = 'form-select'
20 |
21 |
22 | def prepare_formset(employee: Employee, post=None):
23 | """Creates missing vote objects and returns a formset for the employee."""
24 | Preference.make_preferences(employee)
25 | PreferenceFormset = modelformset_factory(Preference, form=PreferenceForm, extra=0)
26 | qs = Preference.objects.filter(employee=employee).order_by('question__proposal')
27 | if post:
28 | formset = PreferenceFormset(post, queryset=qs)
29 | else:
30 | formset = PreferenceFormset(queryset=qs)
31 | return formset
32 |
--------------------------------------------------------------------------------
/zapisy/apps/common/assets/markdown/render-markdown.ts:
--------------------------------------------------------------------------------
1 | import MarkdownIt from "markdown-it";
2 |
3 | const md = MarkdownIt({
4 | linkify: true,
5 | typographer: true,
6 | quotes: "„”«»",
7 | });
8 |
9 | let callback = function (_mutations: any, _observer: any) {
10 | for (const element of document.querySelectorAll(".markdown")) {
11 | const raw = element.textContent || "";
12 | const rendered = md.render(raw);
13 | element.innerHTML = rendered;
14 | // This way Markdown is not rendered twice.
15 | element.classList.remove("markdown");
16 | element.classList.add("markdown-rendered");
17 | }
18 | };
19 |
20 | // Options for the observer (which mutations to observe)
21 | const config = { attributes: false, childList: true, subtree: false };
22 | // Bind to either #main-content (a view with sidebar like the courses page) or
23 | // #main-content-container (a full-page view like my-proposals).
24 | const targetNode =
25 | document.getElementById("main-content") ||
26 | document.getElementById("main-content-container")!;
27 | let observer = new MutationObserver(callback);
28 | observer.observe(targetNode, config);
29 |
--------------------------------------------------------------------------------
/zapisy/templates/semester_dropdown.html:
--------------------------------------------------------------------------------
1 |