├── .dockerignore ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.txt ├── README.md ├── community ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_community_discord_webhook_url.py │ ├── 0003_auto_20210607_0009.py │ ├── 0004_auto_20220122_1707.py │ ├── 0005_auto_20220831_1948.py │ └── __init__.py ├── models.py ├── templates │ └── community │ │ ├── admin │ │ ├── community_create.html │ │ ├── community_list.html │ │ └── user_list.html │ │ ├── calendar_iframe.html │ │ ├── community_admin_update.html │ │ ├── community_list.html │ │ ├── community_page.html │ │ ├── community_ranking.html │ │ ├── community_update.html │ │ ├── create_league.html │ │ ├── includes │ │ ├── calendar.html │ │ ├── community_widget_checkbox.html │ │ ├── leagues_table.html │ │ ├── members_table.html │ │ ├── new_user_table.html │ │ └── tournaments_table.html │ │ └── ranking_table.html ├── templatetags │ ├── __init__.py │ └── community_tags.py ├── urls.py ├── views.py └── widget.py ├── conftest.py ├── discord_bind ├── __init__.py ├── admin.py ├── apps.py ├── conf.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── urls.py └── views.py ├── docker-compose.yml ├── docker.sh ├── docs ├── docker.md ├── getting_started.md ├── production_update_list.md ├── readme_short.md └── translation.md ├── fancysearch ├── __init__.py ├── urls.py └── views.py ├── fixtures └── initial_data.json ├── fullcalendar ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_publicevent_community.py │ ├── 0003_auto_20210502_0856.py │ ├── 0004_auto_20210530_1609.py │ ├── 0005_auto_20210530_1620.py │ └── __init__.py ├── models.py ├── static │ ├── fullcalendar │ │ ├── calendar.js │ │ └── styles │ │ │ ├── custom.css │ │ │ ├── fullcalendar.css │ │ │ ├── micromodal.css │ │ │ └── rangeslider.css │ ├── jquery.countdown │ │ └── jquery.countdown.min.js │ └── lib │ │ ├── cupertino │ │ ├── images │ │ │ ├── ui-bg_diagonals-thick_90_eeeeee_40x40.png │ │ │ ├── ui-bg_glass_100_e4f1fb_1x400.png │ │ │ ├── ui-bg_glass_50_3baae3_1x400.png │ │ │ ├── ui-bg_glass_80_d7ebf9_1x400.png │ │ │ ├── ui-bg_highlight-hard_100_f2f5f7_1x100.png │ │ │ ├── ui-bg_highlight-hard_70_000000_1x100.png │ │ │ ├── ui-bg_highlight-soft_100_deedf7_1x100.png │ │ │ ├── ui-bg_highlight-soft_25_ffef8f_1x100.png │ │ │ ├── ui-icons_2694e8_256x240.png │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ ├── ui-icons_3d80b3_256x240.png │ │ │ ├── ui-icons_72a7cf_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ └── jquery-ui.min.css │ │ ├── jquery-ui.min.js │ │ ├── jquery.min.js │ │ └── moment.min.js ├── templates │ └── fullcalendar │ │ ├── admin_cal_event_list.html │ │ ├── calendar_main_view.html │ │ ├── calevent_create_form.html │ │ ├── calevent_update_form.html │ │ ├── category_create_form.html │ │ ├── category_update_form.html │ │ ├── event_list_sidebar.html │ │ ├── includes │ │ ├── admin_category_table.html │ │ ├── admin_event_table.html │ │ ├── cal-modal.html │ │ ├── event_list.html │ │ └── modal.html │ │ ├── messages │ │ ├── game_appointment.txt │ │ ├── game_cancel.txt │ │ ├── game_request.txt │ │ └── game_request_accepted.txt │ │ ├── publicevent_create_form.html │ │ └── publicevent_update_form.html ├── templatetags │ └── calendar_tags.py ├── urls.py └── views.py ├── home ├── __init__.py ├── image_formats.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_sponsor.py │ ├── 0003_auto_20221109_0955.py │ └── __init__.py ├── models.py ├── static │ └── js │ │ └── osr_datatable_loader.js ├── templates │ └── home │ │ ├── full_width_page.html │ │ ├── home_page.html │ │ ├── includes │ │ ├── blog_list_item.html │ │ ├── carousel.html │ │ ├── contact.html │ │ ├── event_list_item.html │ │ ├── excerpt.html │ │ ├── forum_post_excerpt.html │ │ ├── front_boxes.html │ │ ├── front_boxes_members.html │ │ ├── homepage_intro.html │ │ ├── intro.html │ │ ├── person_list_item.html │ │ ├── poll.html │ │ ├── prev_next.html │ │ ├── related_links.html │ │ ├── search_box.html │ │ ├── socials.html │ │ ├── socials_footer.html │ │ ├── socials_header.html │ │ ├── sponsors_block.html │ │ ├── streamfield.html │ │ └── we_provide.html │ │ ├── stream_field_entry_page.html │ │ └── tags │ │ ├── adverts.html │ │ ├── datatable.html │ │ └── sponsors.html └── templatetags │ ├── datatable_tags.py │ └── osr_tags.py ├── league ├── __init__.py ├── admin.py ├── apps.py ├── cron.py ├── fixtures │ ├── initial_data.json │ └── pytest_fixtures.py ├── forms.py ├── go_federations.py ├── middleware.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20210408_1934.py │ ├── 0003_leagueevent_self_join.py │ ├── 0004_leagueevent_rules_type.py │ ├── 0005_sgf_rules.py │ ├── 0006_leagueevent_servers.py │ ├── 0007_auto_20210413_2047.py │ ├── 0008_auto_20210422_1317.py │ ├── 0009_auto_20210504_2046.py │ ├── 0010_auto_20220121_2247.py │ ├── 0011_auto_20221012_1244.py │ ├── 0012_auto_20221012_1246.py │ └── __init__.py ├── models.py ├── ogs.py ├── static │ └── league │ │ └── js │ │ ├── goquest_sgf.js │ │ ├── manage_league_user.js │ │ ├── players_list.js │ │ ├── random_game.js │ │ └── sgfs_datatable.js ├── templates │ ├── emails │ │ ├── email_confirm.txt │ │ ├── no_games.txt │ │ └── welcome.txt │ └── league │ │ ├── account.html │ │ ├── account_activity.html │ │ ├── admin │ │ ├── base.html │ │ ├── create_all_profiles.html │ │ ├── create_forfeit.html │ │ ├── dashboard.html │ │ ├── download_ffg_tou.html │ │ ├── event_edit.html │ │ ├── event_list.html │ │ ├── events.html │ │ ├── populate.html │ │ ├── sgf_edit.html │ │ ├── sgf_list.html │ │ ├── update_all_profiles.html │ │ ├── update_all_sgf_check_code.html │ │ ├── update_wont_play.html │ │ ├── upload_sgf.html │ │ ├── user_send_mail.html │ │ └── users.html │ │ ├── archive.html │ │ ├── archives_games.html │ │ ├── archives_players.html │ │ ├── base.html │ │ ├── division_update_form.html │ │ ├── event.html │ │ ├── games.html │ │ ├── iframe │ │ ├── archives_games.html │ │ └── games.html │ │ ├── includes │ │ ├── admin_edit_divisions.html │ │ ├── admin_league_form.html │ │ ├── admin_nav.html │ │ ├── ajax_setup.html │ │ ├── event.html │ │ ├── game_info.html │ │ ├── game_table_view.html │ │ ├── games.html │ │ ├── games_iframe.html │ │ ├── league.html │ │ ├── league_nav.html │ │ ├── no_profile_users_table.html │ │ ├── results.html │ │ ├── results_ladder.html │ │ ├── results_league.html │ │ ├── sgf_errors.html │ │ ├── sgrfs_datatable.html │ │ ├── user_infos.html │ │ ├── user_infos_member.html │ │ ├── user_nav.html │ │ └── vs.html │ │ ├── leagueevent_create_form.html │ │ ├── leagueevent_update_form.html │ │ ├── players.html │ │ ├── profile.html │ │ ├── profile_update.html │ │ ├── random_game.html │ │ ├── results.html │ │ ├── results_iframe.html │ │ ├── scrap_list.html │ │ └── timezone_update.html ├── templatetags │ ├── __init__.py │ └── league_tags.py ├── tests │ ├── __init__.py │ ├── snapshots │ │ ├── __init__.py │ │ └── snap_test_views.py │ ├── test_models.py │ ├── test_utils.py │ └── test_views.py ├── urls.py ├── utils.py └── views.py ├── locale ├── es │ └── LC_MESSAGES │ │ ├── django.mo │ │ └── django.po └── fr │ └── LC_MESSAGES │ ├── django.mo │ └── django.po ├── manage.py ├── openstudyroom ├── __init__.py ├── mistune.py ├── settings │ ├── __init__.py │ ├── base.py │ ├── dev.py │ ├── local.py │ ├── production.py │ └── test.py ├── static │ ├── css │ │ ├── bootstrap.min.css │ │ ├── league.css │ │ ├── openstudyroom.css │ │ ├── puput.css │ │ └── sidemenu.css │ ├── js │ │ ├── glift_1_1_2.min.js │ │ ├── openstudyroom.js │ │ └── shortcode.min.js │ ├── mdeditor │ │ ├── bootstrap-markdown.js │ │ └── bootstrap-markdown.min.css │ └── nouislider │ │ ├── nouislider.css │ │ ├── nouislider.d.ts │ │ ├── nouislider.js │ │ ├── nouislider.min.css │ │ ├── nouislider.min.js │ │ ├── nouislider.min.mjs │ │ └── nouislider.mjs ├── templates │ ├── 404.html │ ├── 500.html │ ├── account │ │ ├── email.html │ │ ├── email │ │ │ ├── email_confirmation_message.txt │ │ │ ├── email_confirmation_subject.txt │ │ │ ├── invite_user.txt │ │ │ ├── invite_user_subject.txt │ │ │ ├── password_change.txt │ │ │ ├── password_change_subject.txt │ │ │ ├── password_reset.txt │ │ │ └── password_reset_subject.txt │ │ ├── email_confirm.html │ │ ├── email_confirmation_sent.html │ │ ├── email_confirmed.html │ │ ├── login.html │ │ ├── logout.html │ │ ├── password_change.html │ │ ├── password_reset.html │ │ ├── password_reset_done.html │ │ ├── password_reset_from_key.html │ │ ├── password_reset_from_key_done.html │ │ ├── signup.html │ │ ├── signup_closed.html │ │ └── verification_sent.html │ ├── base.html │ ├── board_base.html │ ├── comments │ │ └── form.html │ ├── forum_conversation │ │ └── topic_detail.html │ ├── forum_member │ │ ├── forum_profile_detail.html │ │ ├── forum_profile_update.html │ │ ├── subscription_topic_list.html │ │ ├── topic_subscribe.html │ │ ├── topic_unsubscribe.html │ │ └── user_posts_list.html │ ├── full_width.html │ ├── iframe.html │ ├── includes │ │ └── django_comments_xtd │ │ │ └── comment_content.html │ ├── left_sidebar.html │ ├── menu.html │ ├── postman │ │ ├── archives.html │ │ ├── base.html │ │ ├── base_folder.html │ │ ├── base_write.html │ │ ├── email_user.txt │ │ ├── email_user_subject.txt │ │ ├── email_visitor.txt │ │ ├── email_visitor_subject.txt │ │ ├── inbox.html │ │ ├── inc_subject_ex.html │ │ ├── reply.html │ │ ├── sent.html │ │ ├── trash.html │ │ ├── view.html │ │ └── write.html │ ├── puput │ │ ├── base.html │ │ ├── blog_page.html │ │ ├── entry_links.html │ │ ├── entry_page.html │ │ └── entry_page_header.html │ ├── right_sidebar.html │ ├── sidebar.html │ ├── site_base.html │ └── table_block │ │ └── blocks │ │ └── table.html ├── urls.py ├── widget.py └── wsgi.py ├── pyproject.toml ├── pytest.ini ├── requirements.txt ├── requirements_dev.txt ├── requirements_prod.txt ├── robots.txt ├── run.sh ├── search ├── __init__.py ├── templates │ └── search │ │ └── search.html └── views.py ├── stats ├── __init__.py ├── migrations │ └── __init__.py ├── model.py ├── static │ └── stats │ │ └── stats.js ├── templates │ └── stats │ │ └── overview.html ├── urls.py └── views.py ├── tournament ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── static │ └── css │ │ └── tournament.css ├── templates │ ├── test.html │ └── tournament │ │ ├── about.html │ │ ├── brackets.html │ │ ├── calendar.html │ │ ├── create_calendar_event.html │ │ ├── edit_about.html │ │ ├── edit_profile.html │ │ ├── games.html │ │ ├── groups.html │ │ ├── includes │ │ ├── bracket_forfeit_buttons.html │ │ ├── bracket_view.html │ │ ├── event_list.html │ │ ├── group_results_manage.html │ │ ├── group_table.html │ │ ├── manage_bracket.html │ │ ├── manage_menu.html │ │ └── tournament_menu.html │ │ ├── manage.html │ │ ├── manage_brackets.html │ │ ├── manage_events.html │ │ ├── manage_games.html │ │ ├── manage_groups.html │ │ ├── manage_settings.html │ │ ├── players.html │ │ ├── prizes.html │ │ ├── rules.html │ │ ├── tournament_create_form.html │ │ ├── tournament_list.html │ │ ├── tournament_view.html │ │ ├── tournamentevent_update_form.html │ │ └── upload_sgf.html ├── templatetags │ ├── __init__.py │ └── tournament_tags.py ├── urls.py ├── utils.py └── views.py └── wgo ├── __init__.py ├── admin.py ├── apps.py ├── migrations └── __init__.py ├── models.py ├── static └── wgo │ ├── glift_shortcode.js │ ├── shortcode.js │ ├── tsumego.js │ ├── wgo.min.js │ ├── wgo.player.css │ ├── wgo.player.min.js │ └── wood1.jpg ├── templates └── wgo │ ├── tsumego.html │ ├── wgo_iframe.html │ └── wgoblock.html ├── templatetags ├── __init__.py └── wgo_tags.py ├── tsumegos ├── cho-1-elementary.sgf ├── cho-2-intermediate.sgf ├── cho-3-advanced.sgf ├── gokyoshumyo.sgf └── hatsuyoron.sgf ├── urls.py └── views.py /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | Dockerfile 3 | docs/docker.md 4 | docker.sh 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/actions/guides/building-and-testing-python 2 | 3 | name: CI 4 | 5 | on: 6 | push: 7 | branches: '*' 8 | pull_request: 9 | branches: '*' 10 | 11 | jobs: 12 | ci: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - uses: actions/setup-python@v4 19 | with: 20 | python-version: '3.7' 21 | cache: 'pip' 22 | 23 | - name: install dependencies 24 | run: pip3 install --quiet --requirement requirements_dev.txt 25 | 26 | - name: pytest 27 | run: ./manage.py makemigrations && pytest --create-db 28 | 29 | - run: ruff check --format=github . 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.pot 3 | *.pyc 4 | __pycache__/ 5 | /static 6 | media 7 | /.idea 8 | *.sqlite3 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "charliermarsh.ruff", 4 | "ms-python.isort", 5 | "ms-python.vscode-pylance", 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [120], 3 | } 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-bullseye as base_build 2 | # Do not buffer python's stdout or stderr 3 | ENV PYTHONUNBUFFERED 1 4 | # Create the app directory 5 | RUN mkdir /app 6 | WORKDIR /app 7 | 8 | ADD requirements.txt /app/ 9 | ADD requirements_dev.txt /app/ 10 | 11 | RUN pip install -r requirements_dev.txt 12 | 13 | FROM base_build as webserver 14 | EXPOSE 8000 15 | # https://github.com/climu/openstudyroom/issues/267 16 | RUN rm -r /usr/local/lib/python3.7/site-packages/machina/locale 17 | ADD run.sh /app/ 18 | CMD ["./run.sh"] 19 | 20 | FROM base_build as dev 21 | ADD requirements_dev.txt /app/ 22 | RUN pip install -r requirements_dev.txt 23 | RUN apt-get update -y 24 | RUN apt-get install -y gettext 25 | # https://github.com/climu/openstudyroom/issues/267 26 | RUN rm -r /usr/local/lib/python3.7/site-packages/machina/locale 27 | 28 | FROM dev as cli 29 | ENTRYPOINT /bin/bash 30 | 31 | FROM dev as ruff 32 | ENTRYPOINT /usr/local/bin/ruff check . 33 | -------------------------------------------------------------------------------- /community/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/community/__init__.py -------------------------------------------------------------------------------- /community/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Community 4 | 5 | # Register your models here. 6 | mymodels = [Community] 7 | 8 | admin.site.register(mymodels) 9 | -------------------------------------------------------------------------------- /community/migrations/0002_community_discord_webhook_url.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-06-03 20:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('community', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='community', 15 | name='discord_webhook_url', 16 | field=models.URLField(blank=True, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /community/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/community/migrations/__init__.py -------------------------------------------------------------------------------- /community/templates/community/admin/community_create.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | {% block heading %} 4 | 7 | {%endblock%} 8 | {% block content %} 9 | 10 |
{% csrf_token %} 11 | {%bootstrap_form form %} 12 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 13 |
14 | 15 | {% trans "Cancel" %} 16 | {% endblock %} 17 | {% block extra_css %} 18 | {{ form.media.css }} 19 | {% endblock extra_css %} 20 | 21 | {% block extra_js %} 22 | {{ form.media.js }} 23 | {% endblock extra_js %} 24 | -------------------------------------------------------------------------------- /community/templates/community/community_admin_update.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | {% block heading %} 4 | 7 | {%endblock%} 8 | {% block content %} 9 |
{% csrf_token %} 10 | {%bootstrap_form form %} 11 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 12 |
13 | {% endblock %} 14 | 15 | {% block extra_css %} 16 | {{ form.media.css }} 17 | {% endblock extra_css %} 18 | 19 | {% block extra_js %} 20 | {{ form.media.js }} 21 | {% endblock extra_js %} 22 | -------------------------------------------------------------------------------- /community/templates/community/community_list.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 community_tags forum_markup_tags i18n %} 3 | {% block title %}OSR - {% trans "Communities" %} {% endblock %} 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | 10 | {% block content %} 11 |
12 |

{% trans "The Open Study Room have and always will be a project to help online go community organising and setting up go leagues. " %} 13 | {% trans "With that in mind, we are very happy to host some league for other friendly go community." %}

14 |

{% trans "Below is the list of the public communities OSR is hosting. Joining a community will allow you to play in their leagues." %}

15 |

{% trans "If you want your community to run some leagues using the OSR league system, contact us at openstudyroom@gmail.com." %}

16 |
17 | {% for community in communitys %} 18 |
19 |
20 | {{community |community_link}} 21 |
22 |
23 | {{community.description |safe|rendered|truncatewords_html:30}} 24 |
25 |
26 | {% endfor %} 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /community/templates/community/community_ranking.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | 10 | {% block content %} 11 | 12 |
13 | 14 |
15 |

{% trans "Generate league ranking file" %}

16 |
17 |
18 |

{% trans "Select a period when the leagues have been played" %}

19 |
20 |
21 | {% csrf_token %} 22 | {{ form.as_p }} 23 | {% bootstrap_button "Download" button_type="submit" button_class="btn-primary" %} 24 |
25 |
26 |
27 | 28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /community/templates/community/community_update.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags community_tags i18n %} 3 | {% block heading %} 4 | 7 | {%endblock%} 8 | {% block content %} 9 |
{% csrf_token %} 10 | {%bootstrap_form form %} 11 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 12 |
13 | 14 | 17 | 18 | 19 | 20 | {% endblock %} 21 | {% block extra_css %} 22 | {{ form.media.css }} 23 | {% endblock extra_css %} 24 | 25 | {% block extra_js %} 26 | {{ form.media.js }} 27 | {% endblock extra_js %} 28 | -------------------------------------------------------------------------------- /community/templates/community/create_league.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | {% block title %}{{community.name}} - {% trans "Create new league" %}{% endblock %} 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | {% block content %} 10 |
11 |
12 | {% trans "Create new league" %} 13 |
{% csrf_token %} 14 | {% bootstrap_form form %} 15 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 16 |
17 |
18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /community/templates/community/includes/calendar.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/community/templates/community/includes/calendar.html -------------------------------------------------------------------------------- /community/templates/community/includes/community_widget_checkbox.html: -------------------------------------------------------------------------------- 1 | {% load forum_markup_tags%} 2 | 3 |
4 | {% for community in communities %} 5 |
6 | 12 |
13 | 14 | {% endfor %} 15 |
16 | -------------------------------------------------------------------------------- /community/templates/community/includes/leagues_table.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap3 league_tags %} 2 | {% load l10n i18n %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {% if admin %} 14 | 15 | 16 | {% endif %} 17 | 18 | 19 | {% for league in leagues %} 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | {% if admin %} 33 | 34 | 35 | {% endif %} 36 | 37 | {% endfor %} 38 | 39 |
{% trans "name" %}{% trans "begin" %}{% trans "ends" %}{% trans "divisions" %}{% trans "players" %}{% trans "games" %}{% trans "edit" %} {% trans "copy" %}
22 | {{league | event_link}} 23 | {% if not league.is_public %} 24 | 25 | {% endif %} 26 | {{league.begin_time |date:"Y-m-d"}}{{league.end_time |date:"Y-m-d"}}{{ league.number_divisions }}{{league.number_players}}{{ league.number_games}} {% bootstrap_icon 'wrench' %}
40 | -------------------------------------------------------------------------------- /community/templates/community/includes/tournaments_table.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap3 league_tags static tz%} 2 | {% load l10n i18n %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% if admin %} 10 | 11 | 12 | {% endif %} 13 | 14 | 15 | 16 | {% for tournament in tournaments %} 17 | 18 | 19 | 20 | 21 | 22 | {% if admin %} 23 | 28 | 38 | {% endif %} 39 | 40 | {% endfor %} 41 | 42 | 43 |
{% trans "name" %}{% trans "begin time" %}{% trans "end time" %} {% trans "manage" %}{% trans "delete" %}
{{tournament.name}}{{tournament.begin_time |date:"Y-m-d"}}{{tournament.end_time |date:"Y-m-d"}} 24 | 25 | {% bootstrap_icon 'wrench' %} 26 | 27 | 29 |
30 | {% csrf_token %} 31 | 32 | 33 | 36 |
37 |
44 | -------------------------------------------------------------------------------- /community/templates/community/ranking_table.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load tz static league_tags bootstrap3 i18n %} 3 | {% load datatable_tags %} 4 | 5 | {% block title %}{% trans "Ranking" %}{% endblock %} 6 | {% block content %} 7 | 8 |

{% blocktrans with community_slug=community.slug %}{{community_slug}} player's rankings{% endblocktrans %}

9 | {% get_meijin as meijin %} 10 | 11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | {{ datatable_config | datatable_tag }} 22 | 23 | 24 | {% endblock %} 25 | 26 | {% block extra_js %} 27 | 41 | {% endblock %} -------------------------------------------------------------------------------- /community/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/community/templatetags/__init__.py -------------------------------------------------------------------------------- /community/templatetags/community_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.urls import reverse 3 | from django.utils.safestring import mark_safe 4 | 5 | register = template.Library() 6 | 7 | @register.filter() 8 | def community_link(community, slug=None): 9 | if community is None: 10 | return '' 11 | link = '' + community.name + '' 17 | return mark_safe(link) 18 | 19 | @register.filter() 20 | def new_member_communities(user): 21 | communities = user.groups.\ 22 | filter(name__icontains='_community_new_member').\ 23 | values_list('new_user_community__name', flat=True) 24 | return mark_safe(', '.join(communities)) 25 | -------------------------------------------------------------------------------- /community/widget.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Community 4 | 5 | 6 | class Community_select(forms.CheckboxSelectMultiple): 7 | template_name = 'community/includes/community_widget_checkbox.html' 8 | 9 | def get_context(self, name, value, attrs): 10 | context = super().get_context(name, value, attrs) 11 | communities = Community.objects.filter(private=False) 12 | context['communities'] = communities 13 | return context 14 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | # ruff: noqa: F401 2 | import freezegun 3 | import pytest 4 | 5 | from league.fixtures.pytest_fixtures import ( 6 | cho_chikun, 7 | kobayashi_koichi, 8 | league_event, 9 | ogs_response, 10 | registry, 11 | sgf_cho_vs_kobayashi, 12 | sgf_text, 13 | ) 14 | 15 | FROZEN_TIME = '2020-05-29T11:14:00' 16 | 17 | 18 | @pytest.fixture(autouse=True) 19 | def freeze_time(): 20 | with freezegun.freeze_time(FROZEN_TIME): 21 | yield 22 | -------------------------------------------------------------------------------- /discord_bind/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016, Mark Rogaski 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | ''' 26 | # following PEP 386 27 | __version__ = '0.2.0' 28 | 29 | default_app_config = 'discord_bind.apps.DiscordBindConfig' 30 | -------------------------------------------------------------------------------- /discord_bind/apps.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016, Mark Rogaski 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | ''' 26 | # ruff: noqa: F401 27 | from django.apps import AppConfig 28 | from django.utils.translation import ugettext_lazy as _ 29 | 30 | 31 | class DiscordBindConfig(AppConfig): 32 | """ Application config """ 33 | name = 'discord_bind' 34 | verbose_name = _('Discord Binding') 35 | 36 | def ready(self): 37 | from . import conf 38 | -------------------------------------------------------------------------------- /discord_bind/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/discord_bind/migrations/__init__.py -------------------------------------------------------------------------------- /discord_bind/urls.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016, Mark Rogaski 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | ''' 26 | from __future__ import unicode_literals 27 | 28 | from django.conf.urls import url 29 | 30 | from . import views 31 | 32 | urlpatterns = [ 33 | url(r'^$', views.index, name='discord_bind_index'), 34 | url(r'^cb$', views.callback, name='discord_bind_callback'), 35 | ] 36 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | app: 5 | container_name: openstudyroom-dev 6 | image: openstudyroom-dev 7 | init: true 8 | restart: always 9 | build: 10 | context: . 11 | target: webserver 12 | volumes: 13 | - ./:/app/ 14 | ports: 15 | - 8000:8000 16 | cli: 17 | container_name: openstudyroom-cli 18 | image: openstudyroom-cli 19 | init: true 20 | build: 21 | context: . 22 | target: cli 23 | volumes: 24 | - ./:/app/ 25 | stdin_open: true 26 | ruff: 27 | container_name: openstudyroom-ruff 28 | image: openstudyroom-ruff 29 | init: true 30 | build: 31 | context: . 32 | target: ruff 33 | volumes: 34 | - ./:/app/ 35 | stdin_open: true 36 | -------------------------------------------------------------------------------- /docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -uvo pipefail 4 | 5 | NAME=osr_django 6 | PORTS='-p 8000:8000' 7 | VOLUME="-v $(pwd):/app" 8 | 9 | docker stop $NAME 10 | docker rm $NAME 11 | set -e 12 | docker build -t osr/$NAME . --target webserver 13 | docker run --restart=always --name=$NAME $PORTS $VOLUME -d osr/$NAME -------------------------------------------------------------------------------- /docs/readme_short.md: -------------------------------------------------------------------------------- 1 | ## OSR? 2 | Yes, the [Open Study Room](https://openstudyroom.org/)! 3 | 4 | A community of go players who share, build and organize knowledge, opportunities and resources for learning, studying and playing Go online as part of a thriving worldwide community. 5 | 6 | ## Meet us on discord! 7 | 8 | We are friendly and hang around [here](https://discord.gg/b7meDjX). 9 | 10 | ## Want to help us ? 11 | Thanks! 12 | 13 | You should take a look at our [contributing guidelines](/CONTRIBUTING.md) 14 | 15 | ## Want to use OSR website for your go community? 16 | Cool! You should take a look at [this page](/docs/production_update_list). -------------------------------------------------------------------------------- /fancysearch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fancysearch/__init__.py -------------------------------------------------------------------------------- /fancysearch/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from . import views 4 | 5 | app_name = 'fullcalendar' 6 | 7 | 8 | urlpatterns = [ 9 | url( 10 | r'^users/', 11 | views.users_search, 12 | name='users_search', 13 | ), 14 | url( 15 | r'^pages/', 16 | views.pages_search, 17 | name='pages_search', 18 | ), 19 | url( 20 | r'^blog/', 21 | views.blog_search, 22 | name='blog_search', 23 | ), 24 | url( 25 | r'^forum/', 26 | views.forum_search, 27 | name='forum_search', 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /fullcalendar/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/__init__.py -------------------------------------------------------------------------------- /fullcalendar/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import GameAppointmentEvent, GameRequestEvent, PublicEvent 4 | 5 | # Register your models here. 6 | mymodels = [PublicEvent, GameRequestEvent, GameAppointmentEvent] 7 | 8 | admin.site.register(mymodels) 9 | -------------------------------------------------------------------------------- /fullcalendar/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FullcalendarConfig(AppConfig): 5 | name = 'fullcalendar' 6 | -------------------------------------------------------------------------------- /fullcalendar/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.forms import ModelForm 3 | from pytz import utc 4 | 5 | from .models import Category, PublicEvent 6 | 7 | 8 | class UTCPublicEventForm(ModelForm): 9 | """a form that force time to be entered with UTC""" 10 | start = forms.DateTimeField(input_formats=['%d/%m/%Y %H:%M'], widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M')) 11 | end = forms.DateTimeField(input_formats=['%d/%m/%Y %H:%M'], widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M')) 12 | 13 | class Meta: 14 | model = PublicEvent 15 | fields = ('title', 'start', 'end', 'url', 'description', 'category') 16 | 17 | def clean(self): 18 | """convert replace timezones to utc""" 19 | cleaned_data = self.cleaned_data 20 | cleaned_data['start'] = cleaned_data['start'].replace(tzinfo=utc) 21 | cleaned_data['end'] = cleaned_data['end'].replace(tzinfo=utc) 22 | return cleaned_data 23 | 24 | def __init__(self, *args, **kwargs): 25 | """ 26 | Init categories choices depending on community in kwargs 27 | """ 28 | community_pk = kwargs.pop('community_pk', None) 29 | super(UTCPublicEventForm, self).__init__(*args, **kwargs) 30 | if self.instance.pk is None: 31 | # if we create new event, we check if community_pk was in kwargs 32 | if community_pk is None: 33 | categories = Category.objects.filter(community=None) 34 | else: 35 | categories = Category.objects.filter(community__pk=community_pk) 36 | else: 37 | categories = Category.objects.filter(community=self.instance.community) 38 | self.fields['category'].queryset = categories 39 | 40 | 41 | class CategoryForm(ModelForm): 42 | class Meta: 43 | model = Category 44 | fields = ('name', 'color') 45 | -------------------------------------------------------------------------------- /fullcalendar/migrations/0002_publicevent_community.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-30 16:16 2 | # ruff: noqa: E501 3 | 4 | import django.db.models.deletion 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('community', '0001_initial'), 12 | ('fullcalendar', '0001_initial'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='publicevent', 18 | name='community', 19 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='community.Community'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /fullcalendar/migrations/0003_auto_20210502_0856.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-05-02 08:56 2 | # ruff: noqa: E501 3 | 4 | import colorful.fields 5 | import django.db.models.deletion 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('community', '0001_initial'), 13 | ('fullcalendar', '0002_publicevent_community'), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Category', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('name', models.CharField(max_length=20)), 22 | ('color', colorful.fields.RGBColorField(null=True)), 23 | ('community', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='community.Community')), 24 | ], 25 | ), 26 | migrations.AddField( 27 | model_name='publicevent', 28 | name='category', 29 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='fullcalendar.Category'), 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /fullcalendar/migrations/0004_auto_20210530_1609.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-05-30 16:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0009_auto_20210504_2046'), 10 | ('fullcalendar', '0003_auto_20210502_0856'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='gamerequestevent', 16 | name='divisions', 17 | field=models.ManyToManyField(blank=True, to='league.Division'), 18 | ), 19 | migrations.AddField( 20 | model_name='gamerequestevent', 21 | name='private', 22 | field=models.BooleanField(default=False), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /fullcalendar/migrations/0005_auto_20210530_1620.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-05-30 16:20 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0009_auto_20210504_2046'), 10 | ('fullcalendar', '0004_auto_20210530_1609'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='gameappointmentevent', 16 | name='divisions', 17 | field=models.ManyToManyField(blank=True, to='league.Division'), 18 | ), 19 | migrations.AddField( 20 | model_name='gameappointmentevent', 21 | name='private', 22 | field=models.BooleanField(default=False), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /fullcalendar/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/migrations/__init__.py -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_glass_50_3baae3_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_glass_50_3baae3_1x400.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-icons_2694e8_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-icons_2694e8_256x240.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-icons_3d80b3_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-icons_3d80b3_256x240.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-icons_72a7cf_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-icons_72a7cf_256x240.png -------------------------------------------------------------------------------- /fullcalendar/static/lib/cupertino/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/fullcalendar/static/lib/cupertino/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/calevent_create_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags static tz i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Create new event" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 | {% timezone "UTC" %} 12 |
13 |
14 | {% trans "Create new event" %} 15 |
{% trans "Please enter times in UTC/GMT time" %}
16 | 17 |
{% csrf_token %} 18 | {%bootstrap_form form %} 19 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 20 |
21 | 22 |
23 | {% endtimezone %} 24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/calevent_update_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags static tz i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Edit an event" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 | {% timezone "UTC" %} 12 |
13 |
14 | {% blocktrans with object_title=object.title %}Edit the event {{object_title}}{% endblocktrans %} 15 |
{% trans "Please enter times in UTC/GMT time with the format dd/mm/yyyy hh:mm" %}
16 | 17 |
{% csrf_token %} 18 | {%bootstrap_form form %} 19 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 20 |
21 |
22 | {% csrf_token %} 23 | 24 | 27 |
28 |
29 | {% endtimezone %} 30 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/category_create_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Create new category" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 |
12 |
13 |
{% csrf_token %} 14 | {%bootstrap_form form %} 15 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 16 |
17 | 18 |
19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/category_update_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Edit a category" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 |
12 |
13 |
{% csrf_token %} 14 | {%bootstrap_form form %} 15 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 16 |
17 | 18 |
19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/event_list_sidebar.html: -------------------------------------------------------------------------------- 1 | {%load tz calendar_tags l10n i18n %} 2 | {% get_current_timezone as TIME_ZONE %} 3 | 4 | 49 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/includes/admin_category_table.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap3 i18n %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% for category in categories %} 12 | 13 | 14 | 15 | 16 | 25 | 26 | {% endfor %} 27 | 28 |
{% trans "Name" %}{% trans "Color" %} {% trans "Edit" %}{% trans "Delete" %}
{{category.name}}{{category.color}}{% bootstrap_icon 'wrench' %} 17 |
18 | {% csrf_token %} 19 | 20 | 23 |
24 |
29 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/includes/admin_event_table.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap3 league_tags static tz %} 2 | {% load l10n i18n %} 3 | {% localize off %} 4 | {% timezone "UTC" %} 5 | {% language 'en' %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for event in public_events %} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | 38 | 39 | 40 | {% endfor %} 41 | 42 | 43 |
{% trans "Title" %}{% trans "Begin Time (UTC/24h)" %}{% trans "End Time (UTC/24h)" %}{% trans "Category" %} {% trans "Edit" %}{% trans "Delete" %}
{{event.title}}{{event.start |date:'M d, Y H:i'}}{{event.end |date:'M d, Y H:i'}}{{event.category.name}} 25 | 26 | {% bootstrap_icon 'wrench' %} 27 | 28 | 30 |
31 | {% csrf_token %} 32 | 33 | 36 |
37 |
44 | {% endlanguage %} 45 | {% endtimezone %} 46 | {% endlocalize %} 47 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/includes/cal-modal.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | 27 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/includes/event_list.html: -------------------------------------------------------------------------------- 1 | {%load tz calendar_tags l10n i18n %} 2 | {% get_current_timezone as TIME_ZONE %} 3 |

{% blocktrans with TIME_ZONE=TIME_ZONE %}OSR Events ({{TIME_ZONE}}){% endblocktrans %}

4 | {% get_now as now %} 5 | {% public_events as public_events%} 6 |
3 %} class="pre-scrollable" {% endif %}> 7 | {% for cal_event in public_events %} 8 | {% if cal_event.url %} {% endif %} 9 |
10 |
11 |
12 |

13 | {% if cal_event.start.date == now.date %} 14 | {% trans "Today !" %} 15 | {% else %} 16 | {{cal_event.start|date:"d, M"}} 17 | {% endif %} 18 |

19 | 20 |

{{cal_event.start|time:"TIME_FORMAT"}}

21 |
22 |
23 |

24 | {{cal_event.title}} 25 |

26 |
27 | {{cal_event.description}} 28 |
29 |
30 |
31 |
32 | {% if cal_event.url %}
{% endif %} 33 | {% endfor %} 34 |
35 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/messages/game_appointment.txt: -------------------------------------------------------------------------------- 1 | {% load l10n i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello ! 5 | 6 | This message was automaticly sent to you to inform you that the user {{user.username}} have planned a game appointment with you on the {{date|utc}} UTC. 7 | 8 | Thanks for playing in the Open Study Room ! 9 | {% endlanguage %} 10 | {% endlocalize %} 11 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/messages/game_cancel.txt: -------------------------------------------------------------------------------- 1 | {% load l10n i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello ! 5 | 6 | This message was automaticly sent to you to inform that the user {{user.username}} has cancelled your game appointment on {{date|utc}} UTC. 7 | 8 | Thanks for playing in the Open Study Room ! 9 | {% endlanguage %} 10 | {% endlocalize %} 11 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/messages/game_request.txt: -------------------------------------------------------------------------------- 1 | {% load l10n i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello ! 5 | 6 | This message was automatically sent to you to inform you that the user {{sender.username}} want to play on {{date|utc}} UTC. 7 | 8 | You can either accept or decline this game request on your calendar. 9 | 10 | Thanks for playing in the Open Study Room ! 11 | {% endlanguage %} 12 | {% endlocalize %} -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/messages/game_request_accepted.txt: -------------------------------------------------------------------------------- 1 | {% load l10n i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello ! 5 | 6 | This message was automaticly sent to you to inform you that the user {{user.username}} have accepted your game request ! 7 | 8 | You should play a game with him on the {{date|utc}} UTC. 9 | 10 | Thanks for playing in the Open Study Room ! 11 | {% endlanguage %} 12 | {% endlocalize %} 13 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/publicevent_create_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags static tz i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Create new event" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 | {% timezone "UTC" %} 12 |
13 |
14 | {% trans "Create new event" %} 15 |
{% trans "Please enter times in UTC/GMT time" %}
16 | 17 |
{% csrf_token %} 18 | {%bootstrap_form form %} 19 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 20 |
21 | 22 |
23 |
24 | {% endtimezone %} 25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /fullcalendar/templates/fullcalendar/publicevent_update_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags static tz i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Edit an event" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 | {% timezone "UTC" %} 12 |
13 |
14 | {% blocktrans with object_title=object.title %}Edit the event {{object_title}}{% endblocktrans %} 15 |
{% trans "Please enter times in UTC/GMT time with the format dd/mm/yyyy hh:mm" %}
16 | 17 |
{% csrf_token %} 18 | {%bootstrap_form form %} 19 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 20 |
21 |
22 | {% csrf_token %} 23 | 24 | 27 |
28 |
29 |
30 | {% endtimezone %} 31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /fullcalendar/templatetags/calendar_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.utils import timezone 3 | from django.utils.safestring import mark_safe 4 | 5 | from fullcalendar.models import GameAppointmentEvent, PublicEvent 6 | 7 | register = template.Library() 8 | 9 | 10 | @register.simple_tag(takes_context=True) 11 | def public_events(context): 12 | request = context['request'] 13 | user = request.user 14 | events = list(PublicEvent.objects.filter(community=None).order_by('-start')[:5]) 15 | if user.is_authenticated and user.is_league_member(): 16 | my_games = list(GameAppointmentEvent.get_future_games(user)) 17 | events = my_games + events 18 | communities = user.get_communities() 19 | for community in communities: 20 | events += list(community.publicevent_set.order_by('-start')[:5]) 21 | events = sorted(events, key=lambda k: k.start, reverse=True)[:5] 22 | return events 23 | 24 | 25 | @register.simple_tag() 26 | def get_now(): 27 | return timezone.now() 28 | 29 | 30 | @register.simple_tag() 31 | def tz_offset(): 32 | tz = timezone.get_current_timezone() 33 | return timezone.localtime(timezone.now(), tz).utcoffset().total_seconds() 34 | 35 | @register.simple_tag() 36 | def checkbox(label, id=None, className=None, label_class='', value=None, checked=True): 37 | checked = ' checked' if checked else '' 38 | id = ' id="' + id + '" ' if id else '' 39 | className = ' class="' + className + '" ' if className else '' 40 | value = ' value="' + str(value) + '" ' if value else '' 41 | html = '
' 43 | return mark_safe(html) 44 | -------------------------------------------------------------------------------- /home/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/home/__init__.py -------------------------------------------------------------------------------- /home/image_formats.py: -------------------------------------------------------------------------------- 1 | from wagtail.images.formats import Format, register_image_format 2 | 3 | register_image_format(Format('right-200', 'right-200', 'richtext-image right', 'width-200')) 4 | register_image_format(Format('left-200', 'left-200', 'richtext-image left', 'width-200')) 5 | -------------------------------------------------------------------------------- /home/migrations/0002_sponsor.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.14 on 2022-11-09 09:23 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('home', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='Sponsor', 15 | fields=[ 16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 17 | ('name', models.TextField(blank=True, max_length=100, null=True)), 18 | ('image', models.URLField(blank=True, null=True)), 19 | ('url', models.URLField(blank=True, null=True)), 20 | ('order', models.IntegerField(blank=True, null=True)), 21 | ], 22 | options={ 23 | 'ordering': ['order'], 24 | }, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /home/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/home/migrations/__init__.py -------------------------------------------------------------------------------- /home/static/js/osr_datatable_loader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | (function(osr_datatable_loader){ 3 | // closure var 4 | let datatable = undefined 5 | 6 | // init function 7 | osr_datatable_loader.init = function(config){ 8 | // create the datatable 9 | datatable = $('#'+config.id).DataTable({ 10 | ajax: { 11 | url: config.url, 12 | dataSrc: 'data' 13 | }, 14 | columns: config.columns.map(function(el){ 15 | return { 16 | data: el.key 17 | } 18 | }) 19 | }); 20 | 21 | 22 | } 23 | // update data source 24 | osr_datatable_loader.update_data_source = function(new_url){ 25 | datatable.clear().draw() 26 | datatable.ajax.url(new_url) 27 | datatable.ajax.reload() 28 | } 29 | })(window.osr_datatable_loader = window.osr_datatable_loader || {}) -------------------------------------------------------------------------------- /home/templates/home/full_width_page.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load wagtailcore_tags %} 3 | {% block body_class %}full-width-page{% endblock %} 4 | 5 | {% block content %} 6 | 7 | {% if self.body %} 8 |
9 | {% include "home/includes/streamfield.html" with content=self.body %} 10 |
11 | {% endif %} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /home/templates/home/includes/blog_list_item.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags wagtailimages_tags %} 2 | 3 | {# Individual blog item in a list - used on blog index and home page #} 4 | 5 |
6 | {% if blog.feed_image %} 7 |
8 | {% image blog.feed_image width-200 as img %} 9 | 10 |
11 | {% endif %} 12 |
13 |

{{ blog.title }}

14 |

{{ blog.date }}

15 | {% if blog.search_description %} 16 |

{{ blog.search_description }}

17 | {% endif %} 18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /home/templates/home/includes/contact.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 | {% if contact.address_1 %} 6 |
Address 1
7 |
{{ contact.address_1 }}
8 | {% endif %} 9 | 10 | {% if contact.address_2 %} 11 |
Address 2
12 |
{{ contact.address_2 }}
13 | {% endif %} 14 | 15 | {% if contact.city %} 16 |
City
17 |
{{ contact.city }}
18 | {% endif %} 19 | 20 | {% if contact.country %} 21 |
Country
22 |
{{ contact.country }}
23 | {% endif %} 24 | 25 | {% if contact.post_code %} 26 |
Post code
27 |
{{ contact.post_code }}
28 | {% endif %} 29 |
30 |
31 | {% if contact.telephone %} 32 |
Telephone
33 |
{{ contact.telephone }}
34 | {% endif %} 35 | 36 | {% if contact.email %} 37 |
Email
38 |
{{ contact.email }}
39 | {% endif %} 40 |
41 |
42 |
43 |
44 |
-------------------------------------------------------------------------------- /home/templates/home/includes/event_list_item.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags wagtailimages_tags %} 2 | 3 | {# Individual event item in a list - used on event index and home page #} 4 | 5 |
6 | {% if event.feed_image %} 7 |
8 | {% image event.feed_image width-200 as img %} 9 | 10 |
11 | {% endif %} 12 |
13 |

{{ event.title }}

14 |

{{ event.date_from }}{% if event.date_to %} to {{ event.date_to }}{% endif %}

15 | {% if event.search_description %} 16 |

{{ event.search_description }}

17 | {% endif %} 18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /home/templates/home/includes/excerpt.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags %} 2 | {% if entry.excerpt %} 3 | {{ entry.excerpt|richtext|striptags }} 4 | {% else %} 5 | {{ entry.body|richtext|truncatewords:30|striptags }} 6 | {% endif %} 7 | -------------------------------------------------------------------------------- /home/templates/home/includes/forum_post_excerpt.html: -------------------------------------------------------------------------------- 1 | {% load forum_markup_tags %} 2 | {{content|safe|rendered|truncatewords:30|striptags }} 3 | -------------------------------------------------------------------------------- /home/templates/home/includes/intro.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags %} 2 | 3 | {% if intro %} 4 |
5 | {{ intro|richtext }} 6 |
7 | {% endif %} -------------------------------------------------------------------------------- /home/templates/home/includes/person_list_item.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags wagtailimages_tags %} 2 | 3 | {# Individual person item in a list - used on people index and home page #} 4 | 5 |
6 | {% if person.feed_image %} 7 |
8 | {% image person.feed_image width-200 as img %} 9 | 10 |
11 | {% endif %} 12 |
13 |

{{ person.first_name }} {{ person.last_name }}

14 | {% if person.search_description %} 15 |

{{ person.search_description }}

16 | {% endif %} 17 |
18 |
19 |
20 | -------------------------------------------------------------------------------- /home/templates/home/includes/prev_next.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags i18n %} 2 | 3 | {% if self.depth > 3 %}{# Previous and next buttons are not relevant for the home page and categories #} 4 | {% with prev=self.get_prev_siblings.live.first next=self.get_next_siblings.live.first %} 5 | 21 | {% endwith %} 22 | {% endif %} 23 | -------------------------------------------------------------------------------- /home/templates/home/includes/related_links.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% if related_links %} 3 | 4 |
5 |
6 |
7 |
8 |

{% trans "Related links" %}

9 |
10 |
11 | 16 |
17 |
18 |
19 |
20 | {% endif %} 21 | -------------------------------------------------------------------------------- /home/templates/home/includes/search_box.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 |
3 |
4 |
5 |
6 | 7 |
8 | 11 |
12 |
13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /home/templates/home/includes/socials.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /home/templates/home/includes/socials_footer.html: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /home/templates/home/includes/socials_header.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | Discord 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Patreon 22 | 23 |
24 | -------------------------------------------------------------------------------- /home/templates/home/includes/sponsors_block.html: -------------------------------------------------------------------------------- 1 | {% load osr_tags %} 2 | {% sponsors %} 3 | -------------------------------------------------------------------------------- /home/templates/home/tags/adverts.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags %} 2 | 3 | {% for advert in adverts %} 4 | 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /home/templates/home/tags/datatable.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | {% for col in columns %} 6 | 7 | {% endfor %} 8 | 9 | 10 | 11 | 12 | 13 |
{{ col.title }}
14 | 15 | {% block extra_js %} 16 | 17 | 18 | 19 | 28 | {% endblock %} -------------------------------------------------------------------------------- /home/templates/home/tags/sponsors.html: -------------------------------------------------------------------------------- 1 |
2 | {% for sponsor in sponsors %} 3 | 14 | {% endfor %} 15 |
16 | -------------------------------------------------------------------------------- /home/templatetags/datatable_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | @register.filter() 6 | def datatable_tag(config): 7 | t = template.loader.get_template('home/tags/datatable.html') 8 | 9 | result = t.render(config) 10 | return result 11 | 12 | # return render(request, 'lld/lld_sections.html',{'document': document}) 13 | # return mark_safe(html) 14 | -------------------------------------------------------------------------------- /home/templatetags/osr_tags.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from django import template 3 | from machina.core.db.models import get_model 4 | from machina.core.loading import get_class 5 | 6 | from home.models import Advert, Sponsor 7 | 8 | Forum = get_model('forum', 'Forum') 9 | Topic = get_model('forum_conversation', 'Topic') 10 | TopicPollVoteForm = get_class('forum_polls.forms', 'TopicPollVoteForm') 11 | register = template.Library() 12 | 13 | @register.inclusion_tag('home/tags/adverts.html', takes_context=True) 14 | def adverts(context): 15 | return { 16 | 'adverts': Advert.objects.all(), 17 | 'request': context['request'], 18 | } 19 | 20 | @register.inclusion_tag('home/tags/sponsors.html', takes_context=True) 21 | def sponsors(context): 22 | return { 23 | 'sponsors': Sponsor.objects.all(), 24 | } 25 | 26 | @register.simple_tag() 27 | def last_topics(request): 28 | allowed_forums = request.forum_permission_handler._get_forums_for_user(request.user,[ 'can_read_forum']) 29 | last_topics = Topic.objects.filter(forum__in=allowed_forums).order_by('-last_post_on')[:4] 30 | return last_topics 31 | 32 | 33 | @register.simple_tag() 34 | def discord_users(): 35 | r = requests.get('https://discordapp.com/api/guilds/287487891003932672/widget.json') 36 | disc_users = r.json()['members'] 37 | return disc_users 38 | 39 | @register.simple_tag() 40 | def get_poll_form(poll): 41 | return TopicPollVoteForm(poll=poll) 42 | -------------------------------------------------------------------------------- /league/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/league/__init__.py -------------------------------------------------------------------------------- /league/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | from .models import Division, LeagueEvent, LeaguePlayer, Profile, Registry, Sgf, User 5 | 6 | #we create groups new_user, league_member and league_admin to help manage the league 7 | #if not Group.objects.filter(name='new_user').exists(): 8 | # group = Group.objects.create(name='new_user') 9 | 10 | #if not Group.objects.filter(name='league_admin').exists(): 11 | # group = Group.objects.create(name='league_admin') 12 | 13 | #if not Group.objects.filter(name='league_member').exists(): 14 | # group = Group.objects.create(name='league_member') 15 | 16 | @admin.register(User) 17 | class UserAdmin(admin.ModelAdmin): 18 | search_fields = ['username'] 19 | 20 | mymodels = [ 21 | Sgf, 22 | LeagueEvent, 23 | Division, 24 | LeaguePlayer, 25 | Registry, 26 | Profile, 27 | ] 28 | admin.site.register(mymodels) 29 | -------------------------------------------------------------------------------- /league/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class LeagueConfig(AppConfig): 5 | name = 'league' 6 | -------------------------------------------------------------------------------- /league/cron.py: -------------------------------------------------------------------------------- 1 | from django_cron import CronJobBase, Schedule 2 | 3 | from .views import scraper 4 | 5 | 6 | class ScraperCronJob(CronJobBase): 7 | RUN_EVERY_MINS = 2 # every 5 mins 8 | schedule = Schedule(run_every_mins=RUN_EVERY_MINS) 9 | code = 'league.scraper_cron_job' # a unique code 10 | 11 | def do(self): 12 | scraper() 13 | -------------------------------------------------------------------------------- /league/middleware.py: -------------------------------------------------------------------------------- 1 | import pytz 2 | from django.utils import timezone 3 | from django.utils.deprecation import MiddlewareMixin 4 | 5 | 6 | class TimezoneMiddleware(MiddlewareMixin): 7 | 8 | def process_request(self, request): 9 | user = request.user 10 | if user.is_authenticated and hasattr(user, 'profile') and user.profile.timezone is not None: 11 | if user.profile.timezone == '---------': 12 | timezone.activate(pytz.timezone('UTC')) 13 | else: 14 | timezone.activate(pytz.timezone(user.profile.timezone)) 15 | else: 16 | timezone.deactivate() 17 | -------------------------------------------------------------------------------- /league/migrations/0003_leagueevent_self_join.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-09 10:05 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0002_auto_20210408_1934'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='leagueevent', 15 | name='self_join', 16 | field=models.BooleanField(default=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /league/migrations/0004_leagueevent_rules_type.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-11 19:26 2 | # ruff: noqa: E501 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('league', '0003_leagueevent_self_join'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='leagueevent', 16 | name='rules_type', 17 | field=models.CharField(blank=True, choices=[('aga', 'AGA'), ('chinese', 'Chinese'), ('japanese', 'Japanese'), ('korean', 'Korean'), ('new_zealand', 'New Zealand')], max_length=15, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /league/migrations/0005_sgf_rules.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-11 22:02 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0004_leagueevent_rules_type'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='sgf', 15 | name='rules', 16 | field=models.CharField(blank=True, max_length=20), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /league/migrations/0006_leagueevent_servers.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-12 16:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0005_sgf_rules'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='leagueevent', 15 | name='servers', 16 | field=models.CharField(blank=True, default='KGS,OGS', max_length=20, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /league/migrations/0007_auto_20210413_2047.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-13 20:47 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0006_leagueevent_servers'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='profile', 15 | name='egf_id', 16 | field=models.PositiveIntegerField(blank=True, default=0, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='profile', 20 | name='egf_rank', 21 | field=models.CharField(blank=True, max_length=40), 22 | ), 23 | migrations.AddField( 24 | model_name='profile', 25 | name='ffg_licence_number', 26 | field=models.PositiveIntegerField(blank=True, default=0, null=True), 27 | ), 28 | migrations.AddField( 29 | model_name='profile', 30 | name='ffg_rank', 31 | field=models.CharField(blank=True, max_length=40), 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /league/migrations/0008_auto_20210422_1317.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-04-22 13:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0007_auto_20210413_2047'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='profile', 15 | name='ffg_licence_number', 16 | field=models.CharField(blank=True, max_length=10, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /league/migrations/0009_auto_20210504_2046.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.20 on 2021-05-04 20:46 2 | # ruff: noqa: E501 3 | 4 | import machina.core.validators 5 | import machina.models.fields 6 | from django.db import migrations, models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('league', '0008_auto_20210422_1317'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='division', 18 | name='_informations_rendered', 19 | field=models.TextField(blank=True, editable=False, null=True), 20 | ), 21 | migrations.AddField( 22 | model_name='division', 23 | name='informations', 24 | field=machina.models.fields.MarkupTextField(blank=True, no_rendered_field=True, null=True, validators=[machina.core.validators.NullableMaxLengthValidator(2000)]), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /league/migrations/0010_auto_20220121_2247.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.24 on 2022-01-21 22:47 2 | # ruff: noqa: E501 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('league', '0009_auto_20210504_2046'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='leagueevent', 16 | name='event_type', 17 | field=models.CharField(choices=[('ladder', 'ladder'), ('league', 'league'), ('meijin', 'meijin'), ('dan', 'dan'), ('ddk', 'ddk'), ('sdk', 'sdk'), ('tournament', 'tournament')], default='ladder', max_length=10), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /league/migrations/0011_auto_20221012_1244.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.14 on 2022-10-12 12:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0010_auto_20220121_2247'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='user', 15 | name='first_name', 16 | field=models.CharField(blank=True, max_length=150, verbose_name='first name'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /league/migrations/0012_auto_20221012_1246.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.14 on 2022-10-12 12:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('league', '0011_auto_20221012_1244'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='profile', 15 | name='ogs_username', 16 | field=models.CharField(blank=True, max_length=60), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /league/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/league/migrations/__init__.py -------------------------------------------------------------------------------- /league/ogs.py: -------------------------------------------------------------------------------- 1 | """Get data from ogs api.""" 2 | from math import ceil, log 3 | 4 | import requests 5 | 6 | 7 | def rating2rank(ogs_rating): 8 | """Return a human readable go rank from a OGS rating number""" 9 | total = ceil(30 - (log(ogs_rating / 525) * 23.15)) # https://forums.online-go.com/t/2021-rating-and-rank-adjustments/33389 10 | if total <= 0: 11 | return str(abs(total - 1)) + 'd' 12 | else: 13 | return str(total) + 'k' 14 | 15 | def get_user_rank(id_number): 16 | """Test if a id is registered in ogs and return his rank if so. 17 | Otherwise we return None""" 18 | if not id_number: 19 | return None 20 | url = 'https://online-go.com/api/v1/players/?id=' + str(id_number) 21 | request = requests.get(url, timeout=10).json() 22 | # Test if id exists at OGS. 23 | if request['count'] == 1: 24 | rating = request['results'][0]['ratings']['overall']['rating'] 25 | return rating2rank(rating) 26 | else: 27 | return None 28 | 29 | 30 | def get_user_id(username): 31 | """Test if a username is registered in ogs and return his id if so. 32 | Otherwise we return 0""" 33 | if not username: 34 | return 0 35 | url = 'https://online-go.com/api/v1/players/?username=' + username 36 | request = requests.get(url).json() 37 | # Test if usernmae exists at OGS. 38 | if request['count'] == 1: 39 | return request['results'][0]['id'] 40 | else: 41 | return 0 42 | 43 | def get_online_users(): 44 | url = 'https://online-go.com/termination-api/chat/group-1843/users' 45 | request = requests.get(url, timeout=10).json() 46 | return request 47 | -------------------------------------------------------------------------------- /league/static/league/js/goquest_sgf.js: -------------------------------------------------------------------------------- 1 | function parseSGF(sgf) { 2 | let index = sgf.indexOf(';'); 3 | const prefix = sgf.substr(0, index); 4 | sgf = sgf.substr(index + 1); 5 | index = sgf.indexOf(';'); 6 | const header = sgf.substr(0, index); 7 | const moves = sgf.substr(index + 1); 8 | return [prefix, header, moves]; 9 | } 10 | 11 | function parseHeader(headerStr) { 12 | const re = /([A-Z]{2})\[([^\[\]]*)\]/g; 13 | const header = {}; 14 | let match; 15 | while (match = re.exec(headerStr)) { 16 | header[match[1]] = match[2]; 17 | } 18 | return header; 19 | } 20 | 21 | function formatHeader(header) { 22 | const headerParts = Object.entries(header).map(([k, v]) => `${k}[${v}]`); 23 | return headerParts.join(''); 24 | } 25 | 26 | function updateSGF(sgf, date){ 27 | const [prefix, headerStr, moves] = parseSGF(sgf); 28 | const header = parseHeader(headerStr); 29 | header['PC'] = 'GOQUEST'; 30 | header['TM'] = '180'; 31 | header['OT'] = '2 fischer'; 32 | header['C'] = '#OSR'; 33 | header['DT'] = date; 34 | 35 | const newSGF = [prefix, formatHeader(header), moves].join(';'); 36 | return newSGF; 37 | } 38 | -------------------------------------------------------------------------------- /league/templates/emails/email_confirm.txt: -------------------------------------------------------------------------------- 1 | {% load l10n i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello {{user.username}}, 5 | 6 | You registered on Open Study Room website on the {{user.date_joined | date:"d/m/Y"}} but you didn't confirm your email since then. 7 | 8 | Since you have to confirm your email to use OSR website we deleted your registration. 9 | 10 | You are more than welcome to register again. If you do, please don't forget to confirm your email this time. 11 | 12 | Feel free to contact us at openstudyroom@gmail.com if you have any issue or question. 13 | 14 | openstudyroom.org 15 | {% endlanguage %} 16 | {% endlocalize %} 17 | -------------------------------------------------------------------------------- /league/templates/emails/no_games.txt: -------------------------------------------------------------------------------- 1 | {% load i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello {{user.username}}, 5 | 6 | We noticed your registration, however we require that each user has played at least one game on KGS or OGS. We can see that you have not yet played any games there under the handle '{{user.kgs_username}}'(KGS) {%if user.profile.ogs_id > 0%} or '{{user.profile.ogs_username}}'(OGS){% endif %}. 7 | 8 | We do this to make sure that you are really a go player and not a robot. Please feel free to register again when you have played a game. 9 | 10 | openstudyroom.org 11 | {% endlanguage %} 12 | {% endlocalize %} 13 | -------------------------------------------------------------------------------- /league/templates/emails/welcome.txt: -------------------------------------------------------------------------------- 1 | {% load i18n tz %} 2 | {% localize off %} 3 | {% language 'en' %} 4 | Hello and welcome to the Open Study Room, {{user.username}}! 5 | 6 | You have just been accepted as an OSR member, and we are glad to have you onboard. 7 | 8 | After logging in, you should take a look at your profile page, located at openstudyroom.org/profile/ 9 | There you will be able to manage your e-mail address and passwords. 10 | 11 | You can now also use our forums and join our Discord server at https://discord.gg/b7meDjX . 12 | 13 | Looking forward to see you there! 14 | 15 | openstudyroom.org 16 | {% endlanguage %} 17 | {% endlocalize %} 18 | -------------------------------------------------------------------------------- /league/templates/league/admin/base.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% extends "full_width.html" %} 3 | 4 | {% block title %}{% trans "OSR league admin" %}{% endblock %} 5 | 6 | {%block page_intro %} 7 | {% if request.user.is_league_admin %} 8 |
9 |
10 | 23 |
24 |
25 | 26 | {% endif %} 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /league/templates/league/admin/create_all_profiles.html: -------------------------------------------------------------------------------- 1 | {% extends "league/admin/base.html" %} 2 | {% load wagtailcore_tags %} 3 | {% load league_tags %} 4 | {% load bootstrap3 %} 5 | {% load i18n %} 6 | {% block title %}{% trans "Update all sgfs" %}{% endblock %} 7 | {% block heading %} 8 | 11 | {%endblock%} 12 | {% block content %} 13 |
14 |
15 |

{% trans "Dear admin," %}

16 |

{% trans "Please pay attention to this message and don't proceed before reading." %}

17 |

{% trans "In this page, you will create a profile for all users that don't have one." %}

18 |

{% trans "If you don't understand what this is about, you should just leave this page." %}

19 |

{% trans "If you have any doubt what so ever about wether you should continue or not, you should leave this page." %}

20 |
21 | 24 |
25 |
26 | {% csrf_token %} 27 | 28 | 32 | 33 |
34 |
35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /league/templates/league/admin/download_ffg_tou.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | 3 | {% load bootstrap3 league_tags i18n l10n tz %} 4 | 5 | {% block title %}{% trans "OSR league admin" %} - {% trans "Leagues" %}{% endblock %} 6 | 7 | {% block heading %} 8 | 11 | {%endblock%} 12 | {% block content %} 13 | 14 | {% localize off %} 15 | {% language 'en' %} 16 | {% timezone "UTC" %} 17 |
18 | 19 |
{% csrf_token %} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {% for user in users %} 30 | 31 | 32 | 43 | 44 | {% endfor %} 45 | 46 |
PlayerFFG Licence
{{ user.username }} 33 | 42 |
47 | 48 | {% bootstrap_button "Download" button_type="submit" button_class="btn-primary" %} 49 |
50 | 51 |
52 | {% endtimezone %} 53 | {% endlanguage %} 54 | {% endlocalize %} 55 | 56 | {% endblock %} 57 | 58 | {% block extra_css %} 59 | {{ form.media.css }} 60 | {% endblock extra_css %} 61 | 62 | {% block extra_js %} 63 | {{ form.media.js }} 64 | {% endblock extra_js %} 65 | -------------------------------------------------------------------------------- /league/templates/league/admin/event_edit.html: -------------------------------------------------------------------------------- 1 | {{ edit_event.name }} 2 | -------------------------------------------------------------------------------- /league/templates/league/admin/events.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags l10n i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "League" %}{% endblock %} 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | {% block content %} 10 |
11 |

12 | {% trans "List of OSR leagues" %} 13 | 14 | 17 | 18 |

19 | {% trans "Community leagues are blue" %}
20 |
21 | {% include "league/admin/event_list.html" with events=events %} 22 |
23 | 24 |
25 | 26 | {% endblock %} 27 | 28 | 29 | {% block extra_js %} 30 | 31 | 32 | 33 | 34 | 35 | 47 | 48 | {% endblock %} 49 | -------------------------------------------------------------------------------- /league/templates/league/admin/update_all_profiles.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load wagtailcore_tags i18n %} 3 | {% load league_tags %} 4 | {% load bootstrap3 %} 5 | 6 | {% block body_class %}user{% endblock %} 7 | 8 | {% block title %}{% trans "Update all sgfs check code" %}{% endblock %} 9 | {% block heading %} 10 | 13 | {%endblock%} 14 | {% block content %} 15 |
16 |
17 |

{% trans "Dear admin," %}

18 |

{% trans "Please pay attention to this message and don't proceed before reading." %}

19 |

{% trans "In this page, can update some profiles datas." %}

20 |

{% trans "If you don't understand what this is about, you should just leave this page." %}

21 |

{% trans "If you have any doubt what so ever about wether you should continue or not, you should leave this page." %}

22 |

{% trans "If you just did read the code of views.update_all_profiles and understand what you are doing, you may proceed." %}

23 |
24 |
25 | Back to admin 26 |
27 |
28 |
29 | {% csrf_token %} 30 | 31 | 35 | 36 |
37 |
38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /league/templates/league/admin/update_all_sgf_check_code.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load wagtailcore_tags i18n %} 3 | {% load league_tags %} 4 | {% load bootstrap3 %} 5 | 6 | {% block body_class %}user{% endblock %} 7 | 8 | {% block title %}{% trans "Update all sgfs check code" %}{% endblock %} 9 | {% block heading %} 10 | 13 | {%endblock%} 14 | {% block content %} 15 |
16 |
17 |

{% trans "Dear admin," %

18 |

{% trans "Please pay attention to this message and don't proceed before reading." %

19 |

{% trans "In this page, you can rescan all sgf in our db and update their check_code." %

20 |

{% trans "If you don't understand what this is about, you should just leave this page." %

21 |

{% trans "If you have any doubt what so ever about wether you should continue or not, you should leave this page." %

22 |

{% trans "If you just changed our check_code and positively want to update all sgf check code, you may proceed." %

23 |
24 | 27 |
28 |
29 | {% csrf_token %} 30 | 31 | 35 | 36 |
37 |
38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /league/templates/league/admin/user_send_mail.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Send mail" %}{% endblock %} 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | {% block content %} 10 | 11 |
12 | {% csrf_token %} 13 | {% bootstrap_form form %} 14 | 17 |
18 | 19 | 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /league/templates/league/base.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load static community_tags forum_markup_tags i18n %} 3 | {% block heading%} 4 | 8 | {%endblock%} 9 | {% block extra_css %} 10 | 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /league/templates/league/division_update_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | 4 | {% comment %}Translators: it's a title : division_name edit{% endcomment %} 5 | {% block title %}{% blocktrans with division_name=object.name %} {{division_name}} edit {% endblocktrans %}{% endblock %} 6 | {% block heading %} 7 | 11 | {%endblock%} 12 | {% block content %} 13 |
{% csrf_token %} 14 | {%bootstrap_form form %} 15 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 16 |
17 | 18 | {% endblock %} 19 | {% block extra_css %} 20 | {{ form.media.css }} 21 | {% endblock extra_css %} 22 | 23 | {% block extra_js %} 24 | {{ form.media.js }} 25 | {% endblock extra_js %} 26 | -------------------------------------------------------------------------------- /league/templates/league/iframe/archives_games.html: -------------------------------------------------------------------------------- 1 | {% extends "iframe.html" %} 2 | {% load league_tags wgo_tags l10n i18n static %} 3 | 4 | {% block title %}Archives - Games {% if sgf %}- {{sgf.black.username}} vs {{sgf.white.username}} {%endif %}{% endblock %} 5 | {% block extra_head_js %} 6 | 31 | {% endblock %} 32 | 33 | {% block content %} 34 | {% include "league/includes/game_table_view.html" %} 35 | {% endblock %} 36 | 37 | {% block extra_css %} 38 | 39 | 40 | {% endblock %} 41 | {% block extra_js %} 42 | {% include "league/includes/sgrfs_datatable.html" with sgfs_data_json=sgfs_data_json %} 43 | {% endblock %} 44 | -------------------------------------------------------------------------------- /league/templates/league/iframe/games.html: -------------------------------------------------------------------------------- 1 | {% extends "iframe.html" %} 2 | {% load tz static league_tags wgo_tags bootstrap3 l10n i18n%} 3 | 4 | {% block extra_head_js %} 5 | 31 | {% endblock %} 32 | {% block content %} 33 | 34 | {% include "league/includes/game_table_view.html" with event=event %} 35 | {% endblock %} 36 | 37 | {% block extra_js %} 38 | {% get_current_language as LANGUAGE_CODE %} 39 | {% include "league/includes/sgrfs_datatable.html" with sgfs_data_json=sgfs_data_json %} 40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /league/templates/league/includes/admin_nav.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 15 | -------------------------------------------------------------------------------- /league/templates/league/includes/ajax_setup.html: -------------------------------------------------------------------------------- 1 | // we will do some ajax post request and hence we will need to grab csrf from cookie. 2 | // https://docs.djangoproject.com/en/1.11/ref/csrf/#ajax 3 | function getCookie(name) { 4 | var cookieValue = null; 5 | if (document.cookie && document.cookie !== '') { 6 | var cookies = document.cookie.split(';'); 7 | for (var i = 0; i < cookies.length; i++) { 8 | var cookie = jQuery.trim(cookies[i]); 9 | // Does this cookie string begin with the name we want? 10 | if (cookie.substring(0, name.length + 1) === (name + '=')) { 11 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 12 | break; 13 | } 14 | } 15 | } 16 | return cookieValue; 17 | } 18 | var csrftoken = getCookie('csrftoken'); 19 | $.ajaxSetup({ headers: { "X-CSRFToken": csrftoken } }); 20 | // end of csrftoken cookie set up 21 | -------------------------------------------------------------------------------- /league/templates/league/includes/event.html: -------------------------------------------------------------------------------- 1 | {% load l10n i18n %} 2 |

{% trans "Infos" %}

3 |

{% blocktrans with event_name=event.name event_begin=event.begin_time |date:"M d, Y" %}The {{event_name}} started on {{event_begin}} and {% endblocktrans %}{% if close %}{% trans "stopped" %}{% else %}{% trans "will stop" %}{%endif%} {% blocktrans with event_end=event.end_time |date:"M d, Y" %}on {{event_end}}.{% endblocktrans %}

4 |

{% blocktrans with event_number_players=event.number_players event_number_games=event.number_games event_number_divisions=event.number_divisions event_percent_game_played=event.percent_game_played event_possible_games=event.possible_games %}{{event_number_players}} players played {{event_number_games}} games in {{event_number_divisions}} divisions. That is {{event_percent_game_played}} % of {{event_possible_games}} possible games.{% endblocktrans %}

5 | {% if close %} 6 |

{% trans "winners" %}

7 | {% endif %} 8 | 9 | -------------------------------------------------------------------------------- /league/templates/league/includes/game_info.html: -------------------------------------------------------------------------------- 1 | {% load league_tags bootstrap3 l10n i18n %} 2 | {% get_meijin as meijin %} 3 | 4 |

5 | 6 | {% if event %} 7 | {% if event.event_type == "tournament" %} 8 | {% bootstrap_icon 'link' %} 9 | {% else %} 10 | {% bootstrap_icon 'link' %} 11 | {% endif %} 12 | {% else %} 13 | {% bootstrap_icon 'link' %} 14 | {% endif %} 15 | 16 | 17 | {{sgf.white |user_link:meijin}} vs {{sgf.black |user_link:meijin}} {% blocktrans with a_date=sgf.date %}on {{a_date}}{% endblocktrans %} : {{sgf.result}} 18 | 19 | 20 | {% bootstrap_icon 'save' %} 21 | 22 | 23 |

24 | -------------------------------------------------------------------------------- /league/templates/league/includes/game_table_view.html: -------------------------------------------------------------------------------- 1 | {% load static league_tags wgo_tags bootstrap3 l10n i18n %} 2 | 3 |
4 |
5 |
6 |
7 | {% if event %} 8 | {% blocktrans with event=event %}Games from {{event}}{% endblocktrans %} 9 | {% else %} 10 | {% trans "All OSR games" %} 11 | {% endif %} 12 |
13 | {# don't forget to add data-community-pk or data-event-pk! #} 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
{% trans "date" %}{% trans "white" %}{% trans "black" %}{% trans "result" %}
23 |
24 |
25 |
26 |
27 | {% if sgf %} 28 | {% include "league/includes/game_info.html" %} 29 | {% endif %} 30 |
31 | {% if sgf %} 32 |
33 |
34 | {% else %} 35 |
36 |
37 | {% trans "Click a game result to see it." %} 38 |
39 |
40 | {% endif %} 41 |
42 |
43 | -------------------------------------------------------------------------------- /league/templates/league/includes/games.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags league_tags i18n %} 2 | {% get_meijin as meijin %} 3 | {% load static %} 4 | 5 | 16 | {# generate a table from a game queryset #} 17 | {# don't forget to add data-community-pk or data-event-pk! #} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
{% trans "date" %}{% trans "white" %}{% trans "black" %}{% trans "result" %}
27 | -------------------------------------------------------------------------------- /league/templates/league/includes/games_iframe.html: -------------------------------------------------------------------------------- 1 | {% load wagtailcore_tags league_tags l10n i18n %} 2 | 3 | {# generate a table from a game queryset #} 4 | {# don't forget to add the extrajs when including this ! #} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% for game in games %} 15 | 16 | 17 | {% if game.winner == game.white %} 18 | 19 | 20 | 21 | {% else %} 22 | 23 | 24 | {%endif%} 25 | 26 | 27 | {% endfor %} 28 | 29 |
{% trans "date" %}{% trans "white" %}{% trans "black" %}{% trans "result" %}
{{ game.sgf.date |date:"M d, Y" }} {{ game.white.user | user_link}} {{ game.black.user | user_link }} {{ game.white.user | user_link }} {{ game.black.user | user_link }} {{ game |game_iframe_link }}
30 | -------------------------------------------------------------------------------- /league/templates/league/includes/league.html: -------------------------------------------------------------------------------- 1 | {% load l10n i18n %} 2 | 8 | 9 | 10 |

Infos

11 |

{% blocktrans with event_name=event.name event_begin=event.begin_time |date:"M d, Y" %}The {{event_name}} started on {{event_begin}} and {% endblocktrans %}{% if close %}{% trans "stopped" %}{% else %}{% trans "will stop" %}{%endif%} {% blocktrans with event_end=event.end_time |date:"M d, Y" %}on {{event_end}}.{% endblocktrans %}

12 |

{% blocktrans with event_number_players=event.number_players event_number_games=event.number_games event_number_divisions=event.number_divisions event_percent_game_played=event.percent_game_played event_possible_games=event.possible_games %}{{event_number_players}} players played {{event_number_games}} games in {{event_number_divisions}} divisions. That is {{event_percent_game_played}} % of {{event_possible_games}} possible games.{% endblocktrans %}

13 | {% if close %} 14 |

{% trans "winners" %}

15 | {% endif %} 16 | 17 | -------------------------------------------------------------------------------- /league/templates/league/includes/results.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | {% for player in players %} 17 | 18 | {% endfor %} 19 | 20 | 21 | {% for player in players %} 22 | 23 | 24 | 25 | {% for opponent in players %} 26 | 27 | {% if forloop.counter == forloop.parentloop.counter %} 28 | 37 | {% endif %} 38 | {% endfor %} 39 | 40 | {% endfor %} 41 | 42 |
{% trans "player" %} {% trans "score" %} {{ player.kgs_username }}
{{forloop.counter}}. {{player.user | user_link}} {{player.score}} 29 | {% else %} 30 | 31 | {% if opponent.kgs_username in player.get_results %} 32 | 33 | {% html_one_result %} 34 | 35 | {% endif %} 36 |
43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /league/templates/league/includes/results_ladder.html: -------------------------------------------------------------------------------- 1 | {% load league_tags i18n %} 2 | {% get_meijin as meijin %} 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | {% for player in results %} 11 | 14 | {% endfor %} 15 | 16 | 17 | {% for player in results %} 18 | 19 | 22 | 23 | {% for opponent in results %} 24 | {% html_one_result_2 forloop.parentloop.counter forloop.counter %} 25 | {% endfor %} 26 | 27 | {% endfor %} 28 | 29 |
{% trans "player" %}{% trans "score" %} 12 |
{{ player.user.username }}
13 |
20 | {{forloop.counter}}. {{player.user | user_link:meijin}} 21 | {{ player.score }}
30 |
31 | -------------------------------------------------------------------------------- /league/templates/league/includes/results_league.html: -------------------------------------------------------------------------------- 1 | {% load league_tags i18n %} 2 | {% get_meijin as meijin %} 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% for player in results %} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 34 | 35 | {% endfor %} 36 | 37 |
{% trans "rank" %}{% trans "player" %}{% trans "score" %}{% trans "wins" %}{% trans "loss" %}{% trans "games" %}{% trans "results" %}
{{forloop.counter}}{{player.user | user_link:meijin}}{{ player.score }}{{ player.n_win }} {{ player.n_loss }}{{ player.n_games }} 27 | {% for opponent in results %} 28 | {% if forloop.counter == forloop.parentloop.counter %} 29 | {% else %} 30 | {% html_one_result %} 31 | {% endif %} 32 | {% endfor %} 33 |
38 |
39 | -------------------------------------------------------------------------------- /league/templates/league/includes/sgf_errors.html: -------------------------------------------------------------------------------- 1 | {% load league_tags i18n %} 2 | 3 | {% if sgf.league_valid %} 4 |
5 |
6 | {% trans "This SGF is valid for those events:" %} 7 |
8 | 9 | {% for event in valid_events %} 10 | 11 | {% endfor %} 12 |
{{event | event_link}}
13 |
14 | {% else %} 15 |
16 |
17 | {% trans "This SGF is valid for no events." %} 18 |
19 |
20 | {% endif %} 21 | 22 | 23 |
24 |
25 | {% trans "Not valid events." %} 26 |
27 | 28 | {% for dict in errors %} 29 | {% if dict.errors %} 30 | {% if dict.league is None %} 31 | 32 | {% else %} 33 | 34 | {% endif %} 35 | 36 | {% for error in dict.errors %} 37 | 38 | {% endfor %} 39 | {% endif %} 40 | 41 | {% endfor %} 42 | 43 |
{% trans "Global errors" %}
{{ dict.league |event_link}}
{{error}}
44 | 45 |
46 | -------------------------------------------------------------------------------- /league/templates/league/includes/sgrfs_datatable.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /league/templates/league/includes/vs.html: -------------------------------------------------------------------------------- 1 | {% load forum_markup_tags l10n i18n bootstrap3 league_tags%} 2 | 3 | {% if user != request.user %} 4 | 5 |

{% blocktrans with username=user.username %}Your results against {{username}}.{% endblocktrans %}

6 | 7 | {% if sgfs_links %} 8 | 9 |
10 | 11 |
12 | {{user_lost_games}} 13 |
14 | 15 |
16 | {{user_won_games}} 17 |
18 | 19 |
20 | 21 |
22 | {% for sgf in sgfs_links %} 23 |

24 | {{sgf|sgf_result}} 25 | 26 | {{sgf.date|date:"SHORT_DATE_FORMAT"}}

27 | {% endfor %} 28 |
29 | 30 | {% else %} 31 |
{% trans "You didn't play any games against each other yet." %}
32 | 33 | {% endif %} 34 | {% endif %} 35 | -------------------------------------------------------------------------------- /league/templates/league/leagueevent_create_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags tz i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Create new event" %}{% endblock %} 4 | {% block heading %} 5 | 14 | {%endblock%} 15 | {% block content %} 16 | {% timezone "UTC" %} 17 |
18 | 19 | {% if copy_from%} 20 | {% blocktrans with league_copy_from=copy_from %}Copy {{league_copy_from}} league{% endblocktrans %} 21 | {% else %} 22 | {% trans "Create new league" %} 23 | {% endif %} 24 | 25 | {% include 'league/includes/admin_league_form.html' %} 26 |
27 | 28 | {% endtimezone %} 29 | {% endblock %} 30 | 31 | {% block extra_css %} 32 | {{ form.media.css }} 33 | {% endblock extra_css %} 34 | 35 | {% block extra_js %} 36 | {{ form.media.js }} 37 | {% endblock extra_js %} 38 | -------------------------------------------------------------------------------- /league/templates/league/profile_update.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | 4 | 5 | {% block title %}{% trans "OSR league admin" %} - {% trans "Leagues" %}{% endblock %} 6 | 7 | {% block heading %} 8 | 11 | {%endblock%} 12 | {% block content %} 13 | 14 | {% include 'league/includes/user_nav.html' with active='league' %} 15 | 16 |
{% csrf_token %} 17 | {%bootstrap_field form.bio %} 18 | {%bootstrap_field form.country %} 19 | {%bootstrap_field form.egf_id %} 20 | {%bootstrap_field form.ffg_licence_number %} 21 | 22 | 23 | 24 |
25 | {% trans "Please make sure all the league games you have played so far are on the results before changing your KGS or OGS usernames." %} 26 |
27 | {%bootstrap_field form.ogs_username %} 28 | {%bootstrap_field form.kgs_username %} 29 | {%bootstrap_field form.go_quest_username %} 30 | 31 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 32 | 33 | cancel 34 | 35 |
36 | {% endblock %} 37 | {% block extra_css %} 38 | {{ form.media.css }} 39 | {% endblock extra_css %} 40 | 41 | {% block extra_js %} 42 | {{ form.media.js }} 43 | {% endblock extra_js %} 44 | -------------------------------------------------------------------------------- /league/templates/league/random_game.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags tz static l10n i18n %} 3 | {% block title %}{% trans "OSR league" %} - {% trans "Random game" %}{% endblock %} 4 | 5 | {% block extra_head_js%} 6 | 7 | 8 | 9 | 10 | {% endblock %} 11 | {% block heading %} 12 | 17 | {% endblock %} 18 | 19 | {% block content %} 20 | {% get_meijin as meijin %} 21 | Random game from to for players ranks - 22 | 23 |
24 |
25 | 26 |
27 | {% csrf_token %} 28 | 29 | {% bootstrap_form form %} 30 | 31 | 32 |
33 | 34 | {% if sgf %} 35 | 36 |
37 | {% blocktrans with sgf_white=sgf.white | user_link:meijin sgf_black=sgf.black | user_link:meijin sgf_date=sgf.date %}{{sgf_white}} vs {{sgf_black}} on {{sgf_date}} {% endblocktrans %} link 38 |
39 | {% endif %} 40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /league/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/league/templatetags/__init__.py -------------------------------------------------------------------------------- /league/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/league/tests/__init__.py -------------------------------------------------------------------------------- /league/tests/snapshots/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/league/tests/snapshots/__init__.py -------------------------------------------------------------------------------- /league/tests/test_models.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from league import models 4 | 5 | 6 | @pytest.mark.django_db 7 | class TestSgfModel: 8 | def test_get_players( 9 | self, 10 | cho_chikun, 11 | kobayashi_koichi, 12 | sgf_text, 13 | league_event, 14 | ): 15 | b = models.LeaguePlayer.objects.create( 16 | user=cho_chikun, 17 | kgs_username='nomeNEST', 18 | event=league_event, 19 | ) 20 | w = models.LeaguePlayer.objects.create( 21 | user=kobayashi_koichi, 22 | kgs_username='climu', 23 | event=league_event, 24 | ) 25 | sgf_m = models.Sgf.objects.create(p_status=2, sgf_text=sgf_text) 26 | sgf_m.parse() 27 | black, white = sgf_m.get_players(league_event) 28 | assert black == b and white == w 29 | 30 | 31 | @pytest.mark.django_db 32 | class TestUserModel: 33 | def test_check_ogs(self, cho_chikun, requests_mock, ogs_response): 34 | expected_url = f'https://online-go.com/api/v1/players/{cho_chikun.profile.ogs_id}/games/' 35 | requests_mock.get(expected_url, json=ogs_response) 36 | cho_chikun.check_ogs([]) 37 | assert requests_mock.called 38 | -------------------------------------------------------------------------------- /league/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from league import utils 4 | 5 | 6 | class TestUtils: 7 | def test_parse_sgf_string(self, sgf_text): 8 | parsed = utils.parse_sgf_string(sgf_text) 9 | expected = { 10 | 'date': datetime.datetime(2016, 11, 19, 0, 0), 11 | 'result': 'W+36.50', 12 | 'bplayer': 'nomenest', 13 | 'wplayer': 'climu', 14 | 'komi': 0.50, 15 | 'board_size': 19, 16 | 'time': 60, 17 | 'byo': '1x10 byo-yomi', 18 | 'place': 'The KGS Go Server at http://www.gokgs.com/', 19 | 'number_moves': 268, 20 | 'check_code': '20161119climunomenestmnhnimcf11', 21 | 'handicap': 1, 22 | 'rules': 'Japanese', 23 | } 24 | assert parsed == expected 25 | 26 | def test_parse_ogs_iso8601_datetime(self): 27 | parsed = utils.parse_ogs_iso8601_datetime( 28 | '2019-04-30T14:41:18.183258-04:00') 29 | expected = datetime.datetime(2019, 4, 30, 18, 41, 18, 183258) 30 | assert parsed == expected 31 | parsed = utils.parse_ogs_iso8601_datetime( 32 | '2019-04-30T14:41:18.183258Z') 33 | expected = datetime.datetime(2019, 4, 30, 14, 41, 18, 183258) 34 | assert parsed == expected 35 | -------------------------------------------------------------------------------- /league/tests/test_views.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | 5 | @pytest.mark.usefixtures('registry') 6 | @pytest.mark.django_db() 7 | class TestGamesDatatableAPI: 8 | @pytest.fixture() 9 | def make_request(self, client): 10 | def _make_request(*args, **kwargs): 11 | url = reverse('league:games_api') 12 | return client.get(url, *args, **kwargs) 13 | return _make_request 14 | 15 | def test_with_no_sgfs(self, make_request): 16 | response = make_request() 17 | assert response.status_code == 200 18 | assert response.json() == { 19 | 'data': [], 20 | 'draw': 0, 21 | 'recordsTotal': 0, 22 | } 23 | 24 | @pytest.mark.usefixtures('sgf_cho_vs_kobayashi') 25 | def test_with_sgf( 26 | self, 27 | make_request, 28 | snapshot, 29 | ): 30 | response = make_request() 31 | assert response.status_code == 200 32 | snapshot.assert_match(response.json()) 33 | 34 | def test_league_dne( 35 | self, 36 | make_request, 37 | ): 38 | response = make_request(data={'league': '-1'}) 39 | assert response.status_code == 404 40 | 41 | @pytest.mark.usefixtures('sgf_cho_vs_kobayashi') 42 | def test_with_league( 43 | self, 44 | make_request, 45 | league_event, 46 | snapshot, 47 | ): 48 | response = make_request(data={'league': league_event.pk}) 49 | assert response.status_code == 200 50 | snapshot.assert_match(response.json()) 51 | -------------------------------------------------------------------------------- /locale/es/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/locale/es/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /locale/fr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/locale/fr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import absolute_import, unicode_literals 4 | 5 | import os 6 | import sys 7 | 8 | if __name__ == '__main__': 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openstudyroom.settings.local') 10 | 11 | from django.core.management import execute_from_command_line 12 | 13 | execute_from_command_line(sys.argv) 14 | -------------------------------------------------------------------------------- /openstudyroom/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/openstudyroom/__init__.py -------------------------------------------------------------------------------- /openstudyroom/mistune.py: -------------------------------------------------------------------------------- 1 | import mistune 2 | 3 | 4 | class osr_renderer(mistune.Renderer): 5 | def autolink(self, link, is_email=False): 6 | """ All point here is to disable autolink feature.""" 7 | return link 8 | 9 | def image(self, src, title, text): 10 | """Rendering a image with title and text. 11 | :param src: source link of the image. 12 | :param title: title text of the image. 13 | :param text: alt text of the image. 14 | """ 15 | src = mistune.escape_link(src) 16 | text = mistune.escape(text, quote=True) 17 | if title: 18 | title = mistune.escape(title, quote=True) 19 | html = '%s' % html 23 | 24 | 25 | 26 | def osr_markdown(string, *args, **kwargs): 27 | renderer = osr_renderer() 28 | markdown = mistune.Markdown(renderer=renderer) 29 | return markdown(mistune.escape(string)) 30 | -------------------------------------------------------------------------------- /openstudyroom/settings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/openstudyroom/settings/__init__.py -------------------------------------------------------------------------------- /openstudyroom/settings/local.py: -------------------------------------------------------------------------------- 1 | # ruff: noqa: F405 2 | import os 3 | 4 | from .base import * # noqa: F403 5 | 6 | DEBUG = True 7 | 8 | # for discord testing api without https 9 | os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' 10 | 11 | INSTALLED_APPS += [ 12 | 'debug_toolbar', 13 | ] 14 | 15 | MIDDLEWARE += [ 16 | 'debug_toolbar.middleware.DebugToolbarMiddleware', 17 | ] 18 | 19 | DEBUG_TOOLBAR_PANELS = [ 20 | 'debug_toolbar.panels.timer.TimerPanel', 21 | 'debug_toolbar.panels.settings.SettingsPanel', 22 | 'debug_toolbar.panels.headers.HeadersPanel', 23 | 'debug_toolbar.panels.request.RequestPanel', 24 | 'debug_toolbar.panels.sql.SQLPanel', 25 | 'debug_toolbar.panels.staticfiles.StaticFilesPanel', 26 | 'debug_toolbar.panels.templates.TemplatesPanel', 27 | 'debug_toolbar.panels.cache.CachePanel', 28 | 'debug_toolbar.panels.signals.SignalsPanel', 29 | 'debug_toolbar.panels.logging.LoggingPanel', 30 | 'debug_toolbar.panels.redirects.RedirectsPanel', 31 | ] 32 | 33 | SECRET_KEY = 'yourlocalsecretkey' 34 | 35 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 36 | 37 | DISCORD_CLIENT_ID = 'xxxxxxxxxxxxxxxxx' 38 | DISCORD_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxx' 39 | 40 | SITE_URL = 'http://127.0.0.1:8000' 41 | 42 | # Base URL to use when referring to full URLs within the Wagtail admin backend - 43 | # e.g. in notification emails. Don't include '/admin' or a trailing slash 44 | BASE_URL = 'http://127.0.0.1:8000' 45 | -------------------------------------------------------------------------------- /openstudyroom/settings/test.py: -------------------------------------------------------------------------------- 1 | from .base import * # noqa: F403 2 | 3 | # By default an in-memory sqlite DB is used 4 | # This is slow to develop with since each test run needs to re-migrate 5 | DATABASES['default']['TEST'] = { # noqa: F405 6 | 'NAME': 'db_test.sqlite3', 7 | } 8 | 9 | DEBUG = True 10 | 11 | SECRET_KEY = 'test' 12 | 13 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 14 | 15 | DISCORD_CLIENT_ID = 'xxxxxxxxxxxxxxxxx' 16 | DISCORD_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxx' 17 | 18 | SITE_URL = 'http://test.test:8000' 19 | -------------------------------------------------------------------------------- /openstudyroom/static/css/league.css: -------------------------------------------------------------------------------- 1 | .table-responsive { 2 | margin-top: 4rem; 3 | } 4 | table#example { 5 | width:auto; 6 | overflow-x: visible; 7 | } 8 | table#example th{ 9 | text-align: center; 10 | min-width: 4rem; 11 | } 12 | table#example th, table#example td{ 13 | padding: 0.75rem; 14 | } 15 | .even-row { 16 | background-color:#f8f8f8; 17 | } 18 | .kgs_username{ 19 | transform: rotate(-60deg); 20 | transform-origin: 0 0; 21 | position: absolute; 22 | margin-top: -10px; 23 | } 24 | .inactive{ 25 | background-color: #ececec; 26 | color: #b9b9b9; 27 | } 28 | .inactive > a { 29 | color:#76b9f3; 30 | } 31 | .disabled { 32 | background-color: #cccccc; 33 | } 34 | .bold { 35 | font-weight: 600; 36 | } 37 | .even-col, .odd-col { 38 | text-align: center; 39 | } 40 | -------------------------------------------------------------------------------- /openstudyroom/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load i18n %} 3 | {% block body_class %}template-404{% endblock %} 4 | 5 | {% block content %} 6 |

{% trans "Page not found" %}

7 | 8 |

{% trans "Sorry, this page could not be found." %}

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /openstudyroom/templates/500.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% trans "Internal server error" %} 11 | 12 | 13 | 14 |

{% trans "Internal server error" %}

15 | 16 |

{% trans "Sorry, there seems to be an error. Please try again soon." %}

17 | 18 | 19 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/email_confirmation_message.txt: -------------------------------------------------------------------------------- 1 | {% load i18n account %}{% blocktrans with site_name=current_site.name %}A user on {{ site_name }} has created an account using this email address. 2 | 3 | To confirm this email address, go to {{ activate_url }} 4 | 5 | If you did not sign up for this site, you can ignore this message. 6 | {% endblocktrans %} 7 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/email_confirmation_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=current_site.name %}Confirm email address for {{ site_name }}{% endblocktrans %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/invite_user.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with name=current_site.name %}You have been invited to sign up at {{ name }}. 2 | 3 | {{ signup_url }} 4 | {% endblocktrans %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/invite_user_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with name=current_site.name %}Create an account on {{ name }}{% endblocktrans %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/password_change.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with now=user.account.now %}This is the email notification to confirm your password has been changed on {{ now }}.{% endblocktrans %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/password_change_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% trans "Change password email notification" %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/password_reset.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=current_site.name %}You're receiving this email because you or someone else has requested a password for your user account at {{ site_name }}. 2 | It can be safely ignored if you did not request a password reset. Click the link below to reset your password. 3 | 4 | {{ password_reset_url }} 5 | {% endblocktrans %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email/password_reset_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=current_site.name %}[{{ site_name }}] Password reset{% endblocktrans %} -------------------------------------------------------------------------------- /openstudyroom/templates/account/email_confirm.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load i18n %} 4 | {% load account %} 5 | {% block title %} Confirm e-mail{% endblock %} 6 | {% block heading %} 7 | 10 | {%endblock%} 11 | 12 | {% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %} 13 | 14 | 15 | {% block content %} 16 | 17 | 18 | {% if confirmation %} 19 | 20 | {% user_display confirmation.email_address.user as user_display %} 21 | 22 |

{% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}

23 | 24 |
25 | {% csrf_token %} 26 | 27 |
28 | 29 | {% else %} 30 | 31 | {% url 'account_email' as email_url %} 32 | 33 |

{% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktrans %}

34 | 35 | {% endif %} 36 | 37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/email_confirmation_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Confirm your email address" %}{% endblock %} 6 | 7 | {% block body %} 8 |

{% trans "Confirm your email address" %}

9 | 10 |

{% blocktrans %}We have sent you an email to {{ email }} for verification. Follow the link provided to finalize the signup process. If you do not receive it within a few minutes, contact us at openstudyroom@gmail.com.{% endblocktrans %}

11 |

{% trans "Go back" %}

12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/email_confirmed.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Email confirmed" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Email confirmed" %}

9 |

{% blocktrans with email=confirmation.email_address.email %}You have confirmed {{ email }}{% endblocktrans %}

10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load account %} 4 | 5 | {% load bootstrap3 i18n %} 6 | {% block title %}{% trans "Log in" %} {% endblock %} 7 | {% block heading %} 8 | 11 | {% endblock %} 12 | 13 | {% block content %} 14 |
15 |
16 |
17 | {% csrf_token %} 18 | {% bootstrap_form form %} 19 | {% if redirect_field_value %} 20 | 21 | {% endif %} 22 | 23 | {% trans "Forgot your password?" %} 24 |
25 |
26 |
27 | 28 |
29 |
30 | {% endblock %} 31 | 32 | {% block extra_js %} 33 | 38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load bootstrap3 i18n %} 4 | 5 | {% block heading %} 6 | 9 | {% endblock %} 10 | {% block content %} 11 |
12 |
13 |
14 |
15 | {% csrf_token %} 16 |

{% trans "Are you sure you want to log out?" ?}

17 | 18 |
19 |
20 |
21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | 4 | {% load bootstrap3 i18n %} 5 | 6 | {% block body_class %}account account-password{% endblock %} 7 | 8 | {% block title %} {% trans "Change password" %}{% endblock %} 9 | {% block heading %} 10 | 13 | {%endblock%} 14 | {% block content %} 15 |
16 | {% include 'league/includes/user_nav.html' with active='manage' %} 17 | 18 |
19 |
20 |
21 |
22 | {% trans "Change password" %} 23 |
24 | {% csrf_token %} 25 | {% bootstrap_form form %} 26 | 27 |
28 |
29 |
30 |
31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/password_reset.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | 4 | {% load bootstrap3 i18n %} 5 | {% load account %} 6 | 7 | {% user_display request.user as user_display %} 8 | {% block title %}{% trans "Reset your password" %}{% endblock %} 9 | {% block heading %} 10 | 13 | {%endblock%} 14 | {% block content %} 15 | 16 |
17 |
18 |
19 |

{% trans "Forgotten your password? Enter your email address below, and we'll send you an email allowing you to reset it." %}

20 |
21 |
22 | {% csrf_token %} 23 | {% bootstrap_form form %} 24 | 25 | 28 |
29 |
30 |
31 |
32 |
33 | 34 | {% endblock %} 35 | 36 | {% block extra_js %} 37 | 40 | {% endblock %} 41 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load account i18n %} 3 | {% block title %}{% trans "Password reset email sent" %}{% endblock %} 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | 10 | {% block content %} 11 |

{% trans "We have sent you an email. If you do not receive it within a few minutes, you should contact us." %}

12 | 13 | {% if user.is_authenticated %} 14 | {% include "account/snippets/already_logged_in.html" %} 15 | {% endif %} 16 | 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/password_reset_from_key.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load bootstrap3 %} 4 | {% load i18n %} 5 | 6 | {% block title %}{% if token_fail %}{% trans "Bad token" %}{% else %}{% trans "Change Password" %}{% endif %}{% endblock %} 7 | {% block heading %} 8 | 11 | {%endblock%} 12 | 13 | {% block content %} 14 |
15 | 16 | {% if token_fail %} 17 | {% url 'account_reset_password' as passwd_reset_url %} 18 |

{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %}

19 | {% else %} 20 | {% if form %} 21 |
22 |
23 | {% csrf_token %} 24 | {% bootstrap_form form %} 25 | 26 |
27 |
28 | {% else %} 29 |

{% trans 'Your password is now changed.' %}

30 | {% endif %} 31 | {% endif %} 32 | 33 |
34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/password_reset_from_key_done.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load bootstrap3 %} 4 | {% load i18n %} 5 | 6 | {% block title %}{% trans "Password Changed" %}{% endblock %} 7 | {% block heading %} 8 | 12 | {%endblock%} 13 | 14 | {% block content %} 15 |

{% blocktrans %}Your password is now changed. Feel free to Login{% endblocktrans %}

16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/signup_closed.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | {% load i18n %} 3 | 4 | 5 | {% block content %} 6 |

{% trans "This site is in private beta" %}

7 |

{% trans "If you have signup code you can enter it below." %}

8 |
9 |
10 |
11 |
12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /openstudyroom/templates/account/verification_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "full_width.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block title %}{% trans "Welcome" %}{% endblock %} 6 | 7 | {% block content %} 8 | 9 |

{% trans "Welcome to the Open Study Room!" %}

10 | 11 |

{% trans "Your adventure now begins, as you just joined a young and enthusiastic online community dedicated to playing, studying and teaching Go." %}

12 |

{% trans "Very soon, our team will add you as an OSR member. Then you will have your own profile page, you'll be able to play league games and use our forum. Make sure to verify your e-mail and check that you have either a valid KGS or OGS account. These two criteria are mandatory in order to join the OSR." %}

13 | 14 |

{% blocktrans %}In the meantime, you might want to check out our FAQ to be sure you got a good grasp of what the OSR is about.{% endblocktrans %}

15 | 16 |

{% blocktrans %}You are also very welcome to meet us in our discord server, in the Open Study Room on KGS (Room list -> Social), and to join our OGS group.{% endblocktrans %}

17 | 18 |

{% blocktrans %}We have sent you an email to you for verification. Please follow the link provided to finalize the signup process. If you do not receive it within a few minutes, contact us at openstudyroom@gmail.com.{% endblocktrans %}

19 | 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /openstudyroom/templates/forum_member/subscription_topic_list.html: -------------------------------------------------------------------------------- 1 | {% extends 'board_base.html' %} 2 | {% load i18n %} 3 | 4 | {% block sub_title %}{% trans "Topics that you are subscribed to" %}{% endblock sub_title %} 5 | 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "Topics that you are subscribed to" %}

11 |
12 |
13 |
14 |
15 | {% if paginator.count > 0 %} 16 |

17 | {% blocktrans trimmed count counter=paginator.count %} 18 | {{ counter }} topic found 19 | {% plural %} 20 | {{ counter }} topics found 21 | {% endblocktrans %} 22 |

23 | {% endif %} 24 |
25 |
26 | {% with "pagination-sm" as pagination_size %} 27 | {% include "partials/pagination.html" %} 28 | {% endwith %} 29 |
30 |
31 | {% trans "Not topics found." as empty_message %} 32 | {% with topic_list_title="Topics" empty_message=empty_message %} 33 | {% include "forum_conversation/topic_list.html" %} 34 | {% endwith %} 35 |
36 |
37 | {% with "pagination-sm" as pagination_size %} 38 | {% include "partials/pagination.html" %} 39 | {% endwith %} 40 |
41 |
42 | {% endblock content %} 43 | -------------------------------------------------------------------------------- /openstudyroom/templates/forum_member/topic_subscribe.html: -------------------------------------------------------------------------------- 1 | {% extends 'board_base.html' %} 2 | {% load i18n %} 3 | {% load forum_conversation_tags %} 4 | 5 | {{% block sub_title %}{% trans "Subscribe to topic" %}{% endblock sub_title %} 6 | 7 | {% block content %} 8 |
9 |
10 |
11 |
12 |

{% trans "Subscribe to topic" %}

13 |
14 |
15 |
{% trans "Would you like to subscribe to this topic?" %}
16 |
{% csrf_token %} 17 | 18 | 19 | {% trans "No" %} 20 |
21 |
22 |
23 |
24 |
25 | {% endblock content %} 26 | -------------------------------------------------------------------------------- /openstudyroom/templates/forum_member/topic_unsubscribe.html: -------------------------------------------------------------------------------- 1 | {% extends 'board_base.html' %} 2 | {% load i18n %} 3 | {% load forum_conversation_tags %} 4 | 5 | {{% block sub_title %}{% trans "Unsubscribe from topic" %}{% endblock sub_title %} 6 | 7 | {% block content %} 8 |
9 |
10 |
11 |
12 |

{% trans "Unsubscribe from topic" %}

13 |
14 |
15 |
{% trans "Would you like to unsubscribe from this topic?" %}
16 |
{% csrf_token %} 17 | 18 | 19 | {% trans "No" %} 20 |
21 |
22 |
23 |
24 |
25 | {% endblock content %} 26 | -------------------------------------------------------------------------------- /openstudyroom/templates/full_width.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | 4 | {% block page_content %} 5 |
6 | {% block content %} {% endblock %} 7 | 8 |
9 | 10 | {% endblock %} 11 | 12 | {% block extra_js %}{% endblock %} 13 | -------------------------------------------------------------------------------- /openstudyroom/templates/includes/django_comments_xtd/comment_content.html: -------------------------------------------------------------------------------- 1 | {% load forum_markup_tags%} 2 | {{content|safe|rendered}} 3 | -------------------------------------------------------------------------------- /openstudyroom/templates/left_sidebar.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_content %} 3 |
4 |
5 | {% block sidebar %} {% endblock %} 6 |
7 | 8 |
9 | {% block content %} {% endblock %} 10 |
11 |
12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/archives.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base_folder.html" %} 2 | {% load i18n bootstrap3 %} 3 | {% block pm_folder_title %}{% trans "Archived Messages" %}{% endblock %} 4 | {% block pm_archive_button %}{% endblock %} 5 | {% block pm_undelete_button %}{% endblock %} 6 | {% block pm_footer_info %} 7 |

{% trans "Messages in this folder will never be removed. You can use this folder for long term storage." %}

8 | {% endblock %} 9 | 10 | {% block sidebar %} 11 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/base.html: -------------------------------------------------------------------------------- 1 | {% extends "left_sidebar.html" %} 2 | {% load i18n static %}{% load postman_tags bootstrap3%} 3 | {% block title %}{% trans "Messaging" %} 4 | 5 | {% endblock %} 6 | 7 | {% block heading %} 8 | 11 | 12 | 13 | {% include 'league/includes/user_nav.html' with active='messages' %} 14 | 15 | {% endblock %} 16 | {% block sidebar %} 17 | 25 | {% endblock %} 26 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/base_write.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base.html" %} 2 | {% load i18n static bootstrap3 %} 3 | {% block extrahead %}{{ block.super }} 4 | {% if autocompleter_app.is_active %}{# using the available admin jQuery is enough #} 5 | {# should not be necessary since AS v1.3 with AJAX_SELECT_BOOTSTRAP set #} 6 | {##} 7 | {% endif %} 8 | {{ form.media }}{# for ajax_selects (v1.3.6 at least) #} 9 | {% endblock %} 10 | {% block content %} 11 |
12 |

{% block pm_write_title %}{% endblock %}

13 |
{% csrf_token %} 14 | 15 | {% block pm_write_recipient %}{% endblock %} 16 | {% bootstrap_form form layout="table"%} 17 | 18 |
19 | 20 |
21 |
22 | {% endblock %} 23 | 24 | 25 | {% block sidebar %} 26 | 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/email_user.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% autoescape off %} 2 | Hello {{object.obfuscated_recipient}} 3 | {% if action == 'rejection' %} 4 | {% blocktrans with object.sent_at|date:"DATETIME_FORMAT" as date and object.obfuscated_recipient as recipient %}On {{ date }}, you asked to send a message to the user '{{ recipient }}'.{% endblocktrans %} 5 | 6 | {% trans "Your message has been rejected by the moderator" %}{% if object.moderation_reason %}{% trans ", for the following reason:" %} 7 | {{ object.moderation_reason }}{% else %}.{% endif %} 8 | 9 | {% else %}{# 'acceptance' #} 10 | 11 | {% blocktrans with object.obfuscated_sender as sender %}You have received a message from the user '{{ sender }}'{% endblocktrans %}: 12 | {%endif%} 13 | --------------------------------------------- 14 | {{object.body}} 15 | --------------------------------------------- 16 | Hope you enjoy your time in the Open Study Room ! 17 | 18 | openstudyroom.org 19 | {% endautoescape %} 20 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/email_user_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% autoescape off %}{% blocktrans with object.subject as subject and site.name as sitename %}Message "{{ subject }}" on the site {{ sitename }}{% endblocktrans %}{% endautoescape %} -------------------------------------------------------------------------------- /openstudyroom/templates/postman/email_visitor.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% autoescape off %}{% trans "Dear visitor," %} 2 | {% if action == 'rejection' %} 3 | {% blocktrans with object.sent_at|date:"DATETIME_FORMAT" as date and object.recipient as recipient %}On {{ date }}, you asked to send a message to the user '{{ recipient }}'.{% endblocktrans %} 4 | 5 | {% trans "Your message has been rejected by the moderator" %}{% if object.moderation_reason %}{% trans ", for the following reason:" %} 6 | {{ object.moderation_reason }}{% else %}.{% endif %} 7 | 8 | {% trans "As a reminder, please find below the content of your message." %} 9 | {% else %}{# 'acceptance' #} 10 | {% blocktrans with object.parent.sent_at|date:"DATETIME_FORMAT" as date and object.sender as sender %}On {{ date }}, you sent a message to the user '{{ sender }}'.{% endblocktrans %} 11 | {% trans "Please find below the answer from your correspondent." %} 12 | {% endif %} 13 | 14 | {% trans "Thank you again for your interest in our services." %} 15 | {% trans "For more comfort, we encourage you to open an account on the site." %} 16 | {% trans "The site administrator" %} 17 | 18 | {% blocktrans %}Note: This message is issued by an automated system. 19 | Do not reply, this would not be taken into account.{% endblocktrans %} 20 | ------------------------------------------------------- 21 | {{ object.body }} 22 | -------------------------------------------------------{% endautoescape %} -------------------------------------------------------------------------------- /openstudyroom/templates/postman/email_visitor_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% autoescape off %}{% blocktrans with object.subject as subject and site.name as sitename %}Message "{{ subject }}" on the site {{ sitename }}{% endblocktrans %}{% endautoescape %} -------------------------------------------------------------------------------- /openstudyroom/templates/postman/inbox.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base_folder.html" %} 2 | {% load i18n %}{% load postman_tags bootstrap3 %} 3 | {% block pm_folder_title %}{% trans "Received Messages" %}{% endblock %} 4 | {% block pm_undelete_button %}{% endblock %} 5 | {% block pm_recipient_header %}{% endblock %} 6 | {% block pm_date %}{% trans "Received" %}{% endblock %} 7 | {% block pm_recipient_cell %}{% endblock %} 8 | 9 | {% block sidebar %} 10 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/inc_subject_ex.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | This file is intended to be included, such as in postman/base_folder.html: 3 | {% include "postman/inc_subject_ex.html" %} 4 | 5 | It provides an extended subject, as a replacement to a simple {{ message.subject }} tag. 6 | Enhancements are: 7 | * limit the subject length to a few words 8 | * if there is still room up to a maximum number of words, then add the very first words of the body, 9 | in a grey style. 10 | 11 | Examples: 12 | With a total of at most 12 words, and 5 words of subject. 13 | With body: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod." 14 | 15 | With subject: "a subject of great interest for you": 16 | "a subject of great interest ... - Lorem ipsum dolor sit amet, consectetur ..." 17 | 18 | With subject: "a great interest": 19 | "a great interest - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed ..." 20 | 21 | {% endcomment %}{% load postman_tags %}{% with message.subject|truncatewords:5 as truncated_subject %}{{ truncated_subject }} 22 | {% with truncated_subject|wordcount as subject_wc %}{% with 12|sub:subject_wc as wc %}{% if message.body and wc > 0 %} - {{ message.body|truncatewords:wc }}{% endif %}{% endwith %}{% endwith %}{% endwith %} -------------------------------------------------------------------------------- /openstudyroom/templates/postman/reply.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base_write.html" %} 2 | {% load i18n %} 3 | {% block pm_write_title %}{% trans "Reply"%}{% endblock %} 4 | {% block pm_write_recipient %}{{ recipient }}{% endblock %} -------------------------------------------------------------------------------- /openstudyroom/templates/postman/sent.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base_folder.html" %} 2 | {% load i18n bootstrap3 %} 3 | {% block pm_folder_title %}{% trans "Sent Messages" %}{% endblock %} 4 | {% block pm_undelete_button %}{% endblock %} 5 | {% block pm_read_button %}{% endblock %} 6 | {% block pm_unread_button %}{% endblock %} 7 | {% block pm_sender_header %}{% endblock %} 8 | {% block pm_date %}{% trans "Sent" %}{% endblock %} 9 | {% block pm_sender_cell %}{% endblock %} 10 | 11 | {% block sidebar %} 12 | 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/trash.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base_folder.html" %} 2 | {% load i18n bootstrap3 %} 3 | {% block pm_folder_title %}{% trans "Deleted Messages" %}{% endblock %} 4 | {% block pm_delete_button %}{% endblock %} 5 | {% block pm_archive_button %}{% endblock %} 6 | {% block pm_subject %}{# no link #} 7 | {% include "postman/inc_subject_ex.html" %} 8 | {% endblock %} 9 | {% block pm_footer_info %} 10 |

{% trans "Messages in this folder can be removed from time to time. For long term storage, use instead the archive folder." %}

11 | {% endblock %} 12 | 13 | {% block sidebar %} 14 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /openstudyroom/templates/postman/write.html: -------------------------------------------------------------------------------- 1 | {% extends "postman/base_write.html" %} 2 | {% load i18n %} 3 | {% block pm_write_title %}{% trans "Write"%}{% endblock %} 4 | -------------------------------------------------------------------------------- /openstudyroom/templates/puput/entry_links.html: -------------------------------------------------------------------------------- 1 | {% load wagtailroutablepage_tags puput_tags %} 2 | 3 | 33 | -------------------------------------------------------------------------------- /openstudyroom/templates/puput/entry_page_header.html: -------------------------------------------------------------------------------- 1 | {% load wagtailroutablepage_tags puput_tags %} 2 | 3 | 15 | -------------------------------------------------------------------------------- /openstudyroom/templates/right_sidebar.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block page_content %} 3 |
4 |
5 |
6 | {% block content %} {% endblock %} 7 |
8 |
9 | {% block sidebar %} {% endblock %} 10 |
11 |
12 |
13 | 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /openstudyroom/templates/sidebar.html: -------------------------------------------------------------------------------- 1 | {% load static i18n wagtailcore_tags wagtailimages_tags puput_tags compress wagtailroutablepage_tags %} 2 | {% load league_tags osr_tags%} 3 | 4 |
5 | {% include 'home/includes/socials.html' %} 6 | 7 | 8 | 9 | 10 |
11 | {% include 'fullcalendar/event_list_sidebar.html' %} 12 | {% adverts %} 13 | {% last_topics request as topics %} 14 | 15 | 28 | -------------------------------------------------------------------------------- /openstudyroom/templates/site_base.html: -------------------------------------------------------------------------------- 1 | {% load static wagtailuserbar %} 2 | {% load menu_tags %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {% block head_title %}{% endblock %} 13 | {% block title %} 14 | {% if self.seo_title %}{{ self.seo_title }}{% else %}{{ self.title }}{% endif %} 15 | {% endblock %} 16 | {% block title_suffix %} 17 | {% with self.get_site.site_name as site_name %} 18 | {% if site_name %}- {{ site_name }}{% endif %} 19 | {% endwith %} 20 | {% endblock %} 21 | 22 | 23 | 24 | 25 | {# Global stylesheets #} 26 | 27 | 28 | {% block extra_css %} 29 | {# Override this in templates to add extra stylesheets #} 30 | {% endblock %} 31 | 32 | 33 | 34 | {% wagtailuserbar %} 35 | 36 | {% block content %}{% endblock %} 37 | 38 | {# Global javascript #} 39 | 40 | 41 | {% block extra_js %} 42 | {# Override this in templates to add extra javascript #} 43 | {% endblock %} 44 | 45 | 46 | -------------------------------------------------------------------------------- /openstudyroom/widget.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.forms.widgets import Textarea 4 | 5 | 6 | class MarkdownTextareaWidget(Textarea): 7 | """ A simple Textarea widget using the simplemde JS library to provide Markdown editor. """ 8 | class Media: 9 | css = { 10 | 'all': ('mdeditor/bootstrap-markdown.min.css', ), 11 | } 12 | js = ( 13 | 'mdeditor/bootstrap-markdown.js', 14 | '//cdnjs.cloudflare.com/ajax/libs/marked/0.3.6/marked.min.js', 15 | '//cdnjs.cloudflare.com/ajax/libs/ace/1.2.9/ace.js', 16 | ) 17 | 18 | def render(self, name, value, attrs=None, renderer=None): 19 | attrs = {} if attrs is None else attrs 20 | classes = attrs.get('classes', '') 21 | #attrs['id'] = "markdown-editor" 22 | attrs['data-provide'] = 'markdown' 23 | attrs['data-height'] = '500' 24 | attrs['class'] = classes + ' machina-mde-markdown' 25 | return super(MarkdownTextareaWidget, self).render(name, value, attrs) 26 | -------------------------------------------------------------------------------- /openstudyroom/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for openstudyroom project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ 8 | """ 9 | 10 | from __future__ import absolute_import, unicode_literals 11 | 12 | import os 13 | 14 | from django.core.wsgi import get_wsgi_application 15 | 16 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openstudyroom.settings.local') 17 | 18 | application = get_wsgi_application() 19 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.ruff] 2 | line-length = 120 3 | select = [ 4 | 'E', 'F', 'I', 5 | 'YTT', 'COM', 'T10', 'DJ', 'ISC', 'G', 'PIE', 'Q', 'RSE', 6 | 'PLE', 7 | 'RUF', 8 | ] 9 | ignore = ['DJ001', 'ISC002', 'RUF005'] 10 | [tool.ruff.flake8-quotes] 11 | docstring-quotes = 'double' 12 | inline-quotes = 'single' 13 | multiline-quotes = 'single' 14 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | DJANGO_SETTINGS_MODULE = openstudyroom.settings.test 3 | addopts = --reuse-db 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.8 2 | bs4==0.0.1 3 | certifi==2022.12.7 4 | chardet==3.0.4 5 | defusedxml==0.6.0 6 | Django==3.1.14 7 | django-comments-xtd==2.9.5 8 | django-allauth==0.42.0 9 | django-annoying==0.10.3 10 | django-anymail==4.2 11 | django-appconf==1.0.5 12 | django-bootstrap3==15.0.0 13 | django-cogwheels==0.3 14 | django-colorful==1.3 15 | django-common-helpers==0.9.0 16 | django-compressor==3.1 17 | django-countries==7.2.1 18 | django-cron==0.5.0 19 | django-debug-toolbar==3.2.1 20 | django-el-pagination==3.3.0 21 | django-haystack==3.0 22 | django-js-asset==1.1.0 23 | django-machina==1.1.2 24 | django-mathfilters==0.4.0 25 | django-modelcluster==5.2 26 | django-mptt==0.12 27 | django-postman==4.0 28 | django-social-share==1.3.0 29 | django-taggit==1.0 30 | django-treebeard==4.3 31 | django-widget-tweaks==1.4.1 32 | djangorestframework==3.13 33 | draftjs-exporter==2.1.6 34 | gunicorn==19.6.0 35 | html5lib==0.999999999 36 | idna==2.6 37 | isort==4.2.15 38 | lazy-object-proxy==1.3.1 39 | mccabe==0.6.1 40 | mistune==0.8.4 41 | oauthlib==2.0.1 42 | olefile==0.44 43 | packaging==16.8 44 | Pillow==9.3.0 45 | puput==1.1.3 46 | pybbm==0.18.4 47 | pyparsing==2.1.10 48 | python-dateutil==2.8.1 49 | python3-openid==3.0.10 50 | pytz==2020.1 51 | raven==6.4.0 52 | rcssmin==1.1.0 53 | requests==2.25.0 54 | requests-oauthlib==0.7.0 55 | rjsmin==1.2.0 56 | six==1.11.0 57 | sorl-thumbnail==12.3 58 | sqlparse==0.2.3 59 | Unidecode==0.4.21 60 | urllib3==1.26.5 61 | vobject==0.9.5 62 | wagtail==2.15.2 63 | wagtailmenus==3.0.2 64 | wagtail-localize==0.9.5 65 | webencodings==0.5.1 66 | Willow==1.4 67 | wrapt==1.10.11 68 | -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | astroid==2.3.0 3 | freezegun==0.3.15 4 | pytest==5.4.2 5 | pytest-django==3.9.0 6 | ruff==0.0.260 7 | snapshottest==0.6.0 8 | requests-mock==1.8.0 9 | -------------------------------------------------------------------------------- /requirements_prod.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | psycopg2-binary==2.7.5 -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /league/ 3 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | # This is ugly but it works. 6 | if [ ! -f db.sqlite3 ]; then 7 | wget --quiet https://cdn.discordapp.com/attachments/287520917255356416/1066436504597053570/db.sqlite3 8 | fi 9 | 10 | ./manage.py makemigrations 11 | ./manage.py migrate 12 | ./manage.py runserver 0.0.0.0:8000 13 | -------------------------------------------------------------------------------- /search/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/search/__init__.py -------------------------------------------------------------------------------- /search/templates/search/search.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load static wagtailcore_tags i18n %} 3 | 4 | {% block body_class %}template-searchresults{% endblock %} 5 | {% block title %}{% trans "Search" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Search" %}

9 | 10 |
11 | 12 | 13 |
14 | 15 | {% if search_results %} 16 |
    17 | {% for result in search_results %} 18 |
  • 19 |

    {{ result }}

    20 | {% if result.search_description %} 21 | {{ result.search_description|safe }} 22 | {% endif %} 23 |
  • 24 | {% endfor %} 25 |
26 | 27 | {% if search_results.has_previous %} 28 | {% trans "Previous" %} 29 | {% endif %} 30 | 31 | {% if search_results.has_next %} 32 | {% trans "Next" %} 33 | {% endif %} 34 | {% elif search_query %} 35 | {% trans "No results found" %} 36 | {% endif %} 37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /search/views.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | 3 | from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator 4 | from django.shortcuts import render 5 | from wagtail.core.models import Page 6 | from wagtail.search.models import Query 7 | 8 | 9 | def search(request): 10 | search_query = request.GET.get('query', None) 11 | page = request.GET.get('page', 1) 12 | 13 | # Search 14 | if search_query: 15 | search_results = Page.objects.live().search(search_query) 16 | query = Query.get(search_query) 17 | 18 | # Record hit 19 | query.add_hit() 20 | else: 21 | search_results = Page.objects.none() 22 | 23 | # Pagination 24 | paginator = Paginator(search_results, 10) 25 | try: 26 | search_results = paginator.page(page) 27 | except PageNotAnInteger: 28 | search_results = paginator.page(1) 29 | except EmptyPage: 30 | search_results = paginator.page(paginator.num_pages) 31 | 32 | return render(request, 'search/search.html', { 33 | 'search_query': search_query, 34 | 'search_results': search_results, 35 | }) 36 | -------------------------------------------------------------------------------- /stats/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/stats/__init__.py -------------------------------------------------------------------------------- /stats/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/stats/migrations/__init__.py -------------------------------------------------------------------------------- /stats/model.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/stats/model.py -------------------------------------------------------------------------------- /stats/static/stats/stats.js: -------------------------------------------------------------------------------- 1 | function config_from_json(json, name){ 2 | 3 | var labels = json.map(function(e) { 4 | return moment(e.month).format('YYYY MM') 5 | }); 6 | 7 | var values = json.map(function(e) { 8 | return e.total 9 | }); 10 | 11 | var config = { 12 | type: 'line', 13 | data: { 14 | labels: labels, 15 | datasets: [{ 16 | label: name, 17 | data: values, 18 | backgroundColor: 'rgba(0, 119, 204, 0.3)' 19 | }] 20 | }, 21 | options: { 22 | scales: { 23 | xAxes: [{ 24 | time: { 25 | displayFormats: { 26 | month: 'MMM YYYY' 27 | } 28 | } 29 | }] 30 | } 31 | } 32 | } 33 | return config 34 | } 35 | -------------------------------------------------------------------------------- /stats/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from . import views 4 | 5 | app_name = 'stats' 6 | 7 | urlpatterns = [ 8 | url( 9 | r'^$', 10 | views.overview, 11 | name='overview', 12 | ), 13 | ] 14 | -------------------------------------------------------------------------------- /tournament/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/tournament/__init__.py -------------------------------------------------------------------------------- /tournament/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Bracket, Match, Tournament 4 | 5 | mymodels = [Tournament, Bracket, Match] 6 | 7 | admin.site.register(mymodels) 8 | -------------------------------------------------------------------------------- /tournament/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/tournament/migrations/__init__.py -------------------------------------------------------------------------------- /tournament/static/css/tournament.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Flex Layout Specifics 3 | */ 4 | .bracket{ 5 | display:flex; 6 | flex-direction:row; 7 | } 8 | .round{ 9 | display:flex; 10 | flex-direction:column; 11 | justify-content:center; 12 | list-style:none; 13 | width: 200px; 14 | min-width: 200px; 15 | 16 | padding:5px; 17 | } 18 | .round .spacer{ flex-grow:1; } 19 | .round .spacer:first-child, 20 | .round .spacer:last-child{ flex-grow:.5; } 21 | 22 | .round .game-spacer{ 23 | flex-grow:1; 24 | } 25 | 26 | .big_spacer{ 27 | min-height: 45px; 28 | } 29 | .match{ 30 | min-height: 82px; 31 | padding:0px; 32 | margin:0; 33 | } 34 | 35 | .round-control-top{ 36 | padding:0px 1px 5px 1px; 37 | margin:0; 38 | } 39 | 40 | .round-control-botom{ 41 | padding:5px 1px 0px 1px; 42 | margin:0; 43 | } 44 | 45 | .match-display{ 46 | min-height: 60px; 47 | padding:0px; 48 | margin:0; 49 | } 50 | 51 | .player{ 52 | height: 20px; 53 | } 54 | 55 | .row-flex, .row-flex > div[class*='col-'] { 56 | display: -webkit-box; 57 | display: -moz-box; 58 | display: -ms-flexbox; 59 | display: -webkit-flex; 60 | display: flex; 61 | flex-wrap: wrap; 62 | flex:1 1 auto; 63 | } 64 | 65 | .row-flex-wrap { 66 | -webkit-flex-flow: row wrap; 67 | align-content: flex-start; 68 | flex:0; 69 | } 70 | 71 | .row-flex > div[class*='col-'], .container-flex > div[class*='col-'] { 72 | margin:-.2px; /* hack adjust for wrapping */ 73 | } 74 | 75 | .container-flex > div[class*='col-'] div,.row-flex > div[class*='col-'] div { 76 | width:100%; 77 | } 78 | 79 | 80 | .flex-col { 81 | display: flex; 82 | display: -webkit-flex; 83 | flex: 1 100%; 84 | flex-flow: column nowrap; 85 | } 86 | 87 | .flex-grow { 88 | display: flex; 89 | -webkit-flex: 2; 90 | flex: 2; 91 | } 92 | -------------------------------------------------------------------------------- /tournament/templates/test.html: -------------------------------------------------------------------------------- 1 | http://jsfiddle.net/dauruk0512/w6dLuvys/1/ 2 | http://jsfiddle.net/d39hmc6k/ 3 | http://jsfiddle.net/XY8Hs/60/ 4 | -------------------------------------------------------------------------------- /tournament/templates/tournament/about.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags%} 3 | {% block extra_css %} 4 | 5 | 6 | 7 | {% endblock %} 8 | 9 | 10 | 11 | {% block title %}{{tournament.name}}{% endblock %} 12 | 13 | {% block heading %} 14 | 17 |
{{tournament.description|safe|rendered}}
18 | 19 | {%endblock%} 20 | 21 | {% block content %} 22 | 23 | {% include 'tournament/includes/tournament_menu.html' with active="about"%} 24 | 25 | {% if admin %} 26 | 31 | {% endif %} 32 | 33 |
34 | {% if events %} 35 |
36 |

{{tournament.about|safe|rendered}}

37 |
38 |
39 | {% include 'tournament/includes/event_list.html'%} 40 |
41 | {% else %} 42 |

{{tournament.about|safe|rendered}}

43 | {% endif %} 44 |
45 | 46 | 47 | {%endblock%} 48 | -------------------------------------------------------------------------------- /tournament/templates/tournament/brackets.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags i18n %} 3 | {% block extra_css %} 4 | 5 | 6 | {% endblock %} 7 | 8 | {% block title %}{% blocktrans with tournament_name=tournament.name %}{{tournament_name}} - Brackets{% endblocktrans %}{% endblock %} 9 | 10 | {% block heading %} 11 | 14 |
{{tournament.description|safe|rendered}}
15 | {%endblock%} 16 | 17 | {% block content %} 18 | 19 | {% include 'tournament/includes/tournament_menu.html' with active="brackets" %} 20 | {% include 'tournament/includes/bracket_view.html'%} 21 | 22 | {%endblock%} 23 | -------------------------------------------------------------------------------- /tournament/templates/tournament/create_calendar_event.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static tz i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Create new event" %}{% endblock %} 4 | 5 | {% block extra_css %} 6 | 7 | 8 | {% endblock %} 9 | 10 | {% block heading %} 11 | 14 | {%endblock%} 15 | {% block content %} 16 | {% timezone "UTC" %} 17 | 18 | 19 | {% include 'tournament/includes/tournament_menu.html' with active="calendar" %} 20 | 21 | 25 |
26 |
27 | {% trans "Create new event" %} 28 |
{% trans "Please enter times in UTC/GMT time" %}
29 | 30 |
{% csrf_token %} 31 | {%bootstrap_form form %} 32 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 33 |
34 | 35 |
36 |
37 | 38 | {% endtimezone %} 39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /tournament/templates/tournament/edit_about.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags i18n %} 3 | {% block extra_css %} 4 | 5 | 6 | {{ form.media.css }} 7 | 8 | {% endblock %} 9 | 10 | 11 | {% block title %}{{tournament.name}}{% endblock %} 12 | 13 | {% block heading %} 14 | 17 | {%endblock%} 18 | 19 | {% block content %} 20 | {% include 'tournament/includes/tournament_menu.html' with active="about" %} 21 | 22 |
{% csrf_token %} 23 | {%bootstrap_form form %} 24 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 25 |
26 | 27 | {% trans "Cancel" %} 28 | 29 | 30 | 31 | {% endblock %} 32 | 33 | {% block extra_js %} 34 | {{ form.media.js }} 35 | {% endblock extra_js %} 36 | -------------------------------------------------------------------------------- /tournament/templates/tournament/edit_profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | {% block title %}{% trans "Edit a user profile" %}{% endblock %} 4 | 5 | {% block heading %} 6 | 9 | {%endblock%} 10 | {% block content %} 11 | 12 |
{% csrf_token %} 13 | {% bootstrap_field form.bio %} 14 | {% bootstrap_field form.picture_url %} 15 | {%bootstrap_field form.country %} 16 | 17 | 18 |
19 | {% trans "Please make sure all the league games you have played so far are on the results before changing your KGS or OGS usernames." %}" 20 |
21 | {%bootstrap_field form.ogs_username %} 22 | {%bootstrap_field form.kgs_username %} 23 | 24 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 25 | 26 | cancel 27 | 28 |
29 | {% endblock %} 30 | {% block extra_css %} 31 | {{ form.media.css }} 32 | {% endblock extra_css %} 33 | 34 | {% block extra_js %} 35 | {{ form.media.js }} 36 | {% endblock extra_js %} 37 | -------------------------------------------------------------------------------- /tournament/templates/tournament/groups.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags i18n %} 3 | {% block extra_css %} 4 | 5 | 6 | {% endblock %} 7 | 8 | {% block title %}{% blocktrans with tournament_name=tournament.name %}{{tournament_name}} - Groups{% endblocktrans %}{% endblock %} 9 | 10 | {% block heading %} 11 | 14 |
{{tournament.description|safe|rendered}}
15 | 16 | {%endblock%} 17 | 18 | {% block content %} 19 | {% include 'tournament/includes/tournament_menu.html' with active="groups" %} 20 | 21 | {% if groups %} 22 |
23 | {% for group in groups %} 24 |
25 |

{{group.name}}

26 | {% include 'tournament/includes/group_table.html' with results=group.results %} 27 |
28 | 29 | {% if forloop.counter|divisibleby:2 %} 30 |
31 |
32 | {% endif %} 33 | {% endfor %} 34 |
35 | {% else %} 36 | {% trans "There is no group in this tournament!" %}" 37 | {% endif %} 38 |
39 | 40 | {% include 'tournament/includes/bracket_view.html'%} 41 | 42 | {%endblock%} 43 | -------------------------------------------------------------------------------- /tournament/templates/tournament/includes/bracket_forfeit_buttons.html: -------------------------------------------------------------------------------- 1 | 2 | {% if match.winner %} 3 | {% if match.winner != player %} 4 |
5 | {% csrf_token %} 6 | 7 | 8 | 17 |
18 | {% endif %} 19 | {% else %} 20 |
21 | {% csrf_token %} 22 | 23 | 24 | 33 |
34 | {% endif %} 35 | -------------------------------------------------------------------------------- /tournament/templates/tournament/includes/event_list.html: -------------------------------------------------------------------------------- 1 | {%load tz calendar_tags l10n i18n %} 2 | {% get_current_timezone as TIME_ZONE %} 3 | 4 | 48 | -------------------------------------------------------------------------------- /tournament/templates/tournament/includes/group_results_manage.html: -------------------------------------------------------------------------------- 1 | {% load league_tags i18n %} 2 | {% get_meijin as meijin %} 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | {% for player in results %} 11 | 14 | {% endfor %} 15 | 16 | 17 | {% for player in results %} 18 | 19 | 22 | 23 | {% for opponent in results %} 24 | 25 | {% if forloop.counter == forloop.parentloop.counter %} 26 | 31 | {% endif %} 32 | {% endfor %} 33 | 34 | {% endfor %} 35 | 36 |
{% trans "player" %}{% trans "score" %} 12 |
{{ player.user.username }}
13 |
20 | {{forloop.counter}}. {{player.user | user_link:meijin}} 21 | {{ player.score }} 27 | {% else %} 28 | 29 | {% html_one_result %} 30 |
37 |
38 | -------------------------------------------------------------------------------- /tournament/templates/tournament/includes/manage_bracket.html: -------------------------------------------------------------------------------- 1 | {% for rounds in bracket.rounds %} 2 | -------------------------------------------------------------------------------- /tournament/templates/tournament/includes/manage_menu.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 24 | -------------------------------------------------------------------------------- /tournament/templates/tournament/prizes.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags i18n %} 3 | {% block extra_css %} 4 | 5 | 6 | {% endblock %} 7 | 8 | 9 | 10 | {% block title %}{{tournament.name}} - {% trans "Prizes" %}{% endblock %} 11 | 12 | {% block heading %} 13 | 16 |
{{tournament.description|safe|rendered}}
17 | 18 | {%endblock%} 19 | 20 | {% block content %} 21 | {% include 'tournament/includes/tournament_menu.html' with active="prizes"%} 22 | 23 | {% if admin %} 24 | 29 | {% endif %} 30 | 31 |

{{tournament.prizes|safe|rendered}}

32 | 33 | {%endblock%} 34 | -------------------------------------------------------------------------------- /tournament/templates/tournament/rules.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags i18n %} 3 | {% block extra_css %} 4 | 5 | 6 | {% endblock %} 7 | 8 | 9 | 10 | {% block title %}{{tournament.name}} - {% trans "Rules" %}{% endblock %} 11 | 12 | {% block heading %} 13 | 16 |
{{tournament.description|safe|rendered}}
17 | {%endblock%} 18 | 19 | {% block content %} 20 | {% include 'tournament/includes/tournament_menu.html' with active="rules"%} 21 | 22 | {% if admin %} 23 | 28 | {% endif %} 29 | 30 |

{{tournament.rules|safe|rendered}}

31 | 32 | {%endblock%} 33 | -------------------------------------------------------------------------------- /tournament/templates/tournament/tournament_create_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'league/admin/base.html' %} 2 | {% load bootstrap3 league_tags i18n %} 3 | {% block title %}{% trans "OSR league admin" %} - {% trans "Create new event" %}{% endblock %} 4 | {% block heading %} 5 | 8 | {%endblock%} 9 | {% block content %} 10 |
11 |
12 | {% trans "Create new tournament" %} 13 |
{% csrf_token %} 14 | {% bootstrap_form form %} 15 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 16 |
17 |
18 |
19 | 20 | {% endblock %} 21 | 22 | {% block extra_css %} 23 | {{ form.media.css }} 24 | {% endblock extra_css %} 25 | 26 | {% block extra_js %} 27 | {{ form.media.js }} 28 | {% endblock extra_js %} 29 | -------------------------------------------------------------------------------- /tournament/templates/tournament/tournament_view.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 league_tags static forum_markup_tags%} 3 | {% block extra_css %} 4 | 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block title %}{{tournament.name}}{% endblock %} 10 | 11 | {% block heading %} 12 | 15 | {%endblock%} 16 | 17 | {% block content %} 18 | {% include 'tournament/includes/tournament_menu.html' %} 19 |

{{tournament.description|safe|rendered}}

20 | {% if groups %} 21 |
22 | 23 | {% for group in groups %} 24 |
25 |

{{group.name}}

26 | {% include 'league/includes/results_ladder.html' with results=group.results %} 27 |
28 | {% endfor %} 29 |
30 | {% endif %} 31 |
32 | 33 | {% include 'tournament/includes/bracket_view.html'%} 34 | 35 | {%endblock%} 36 | -------------------------------------------------------------------------------- /tournament/templates/tournament/tournamentevent_update_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'full_width.html' %} 2 | {% load bootstrap3 tz league_tags static i18n %} 3 | {% block extra_css %} 4 | 5 | 6 | {% endblock %} 7 | 8 | {% block title %}{% trans "OSR tournament admin" %} - {% trans "Edit an event" %}{% endblock %} 9 | 10 | {% block heading %} 11 | 14 | {%endblock%} 15 | {% block content %} 16 | {% timezone "UTC" %} 17 |
18 |
19 | {% blocktrans with object_title=object.title %}Edit the event {{object_title}}{% endblocktrans %} 20 |
{% trans "Please enter times in UTC/GMT time with the format dd/mm/yyyy hh:mm" %}
21 | 22 |
{% csrf_token %} 23 | {%bootstrap_form form %} 24 | {% bootstrap_button "Save" button_type="submit" button_class="btn-primary" %} 25 |
26 |
27 | {% csrf_token %} 28 | 29 | 32 |
33 |
34 |
35 | 36 | {% endtimezone %} 37 | 38 | {% endblock %} 39 | -------------------------------------------------------------------------------- /tournament/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/tournament/templatetags/__init__.py -------------------------------------------------------------------------------- /tournament/utils.py: -------------------------------------------------------------------------------- 1 | """Some utils.""" 2 | from django.shortcuts import get_object_or_404 3 | 4 | from .models import Match, TournamentPlayer 5 | 6 | 7 | def save_round(round, matches): 8 | """Just to avoid nested loops""" 9 | for match_id, players in matches.items(): 10 | match = get_object_or_404(Match, pk=match_id, round=round) 11 | if match.sgf is None: 12 | if len(players) > 0: 13 | player_1 = get_object_or_404(TournamentPlayer, pk=players[0], event=round.bracket.tournament) 14 | match.player_1 = player_1 15 | match.player_2 = None 16 | if len(players) == 2: 17 | player_2 = get_object_or_404(TournamentPlayer, pk=players[1], event=round.bracket.tournament) 18 | match.player_2 = player_2 19 | if len(players) < 3: 20 | match.save() 21 | else: 22 | match.player_1 = None 23 | match.player_2 = None 24 | match.save() 25 | return 26 | -------------------------------------------------------------------------------- /wgo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/__init__.py -------------------------------------------------------------------------------- /wgo/admin.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/admin.py -------------------------------------------------------------------------------- /wgo/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class WgoConfig(AppConfig): 5 | name = 'wgo' 6 | -------------------------------------------------------------------------------- /wgo/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/migrations/__init__.py -------------------------------------------------------------------------------- /wgo/models.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/models.py -------------------------------------------------------------------------------- /wgo/static/wgo/glift_shortcode.js: -------------------------------------------------------------------------------- 1 | /* 2 | converts the settings in the goban tag to JSON 3 | We have 2 indexes: start and equal. 4 | Start starts at 0. 5 | We look for the first '=' after start that index equal. then we: 6 | - get key by looking for the space between start and equal. 7 | - get value by looking for first space after equal. New index : start 8 | 9 | we loop until no equal is to be found after start. 10 | ugly isn't it? 11 | */ 12 | 13 | function glift_html(comments){ 14 | 15 | tag_open = '
' 17 | 18 | 19 | return tag_open + tag_close ; 20 | 21 | } 22 | /* 23 | replaces the first [goban][/goban] in str by a html goban 24 | */ 25 | function glift_html_single(str){ 26 | //check if there is a goban tag 27 | regex_main = /\[ *?glift.*?\](.|\n)*?\[ *?\/ *?glift *?\]/ 28 | if(!regex_main.test(str)) 29 | return false 30 | 31 | //find relevant text 32 | goban = str.match(regex_main)[0] 33 | 34 | tag = goban.match(/\[ *?glift.*?\]/)[0] 35 | endtag = goban.match(/\[ *?\/ *?glift *?\]/)[0] 36 | comments = goban.substring(tag.length,goban.length-endtag.length) 37 | 38 | /* 39 | goban_final = function_that_makes_goban_html(tags_to_JSON(tag),comments) 40 | */ 41 | goban_final = glift_html(comments) //temp 42 | 43 | return str.replace(regex_main,goban_final) 44 | } 45 | 46 | /* 47 | replaces every [goban][/goban] in str by a html goban 48 | */ 49 | function glift_preprocessor(str){ 50 | while(x = glift_html_single(str)){str = x} 51 | return str 52 | } 53 | -------------------------------------------------------------------------------- /wgo/static/wgo/wgo.player.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/static/wgo/wgo.player.min.js -------------------------------------------------------------------------------- /wgo/static/wgo/wood1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/static/wgo/wood1.jpg -------------------------------------------------------------------------------- /wgo/templates/wgo/tsumego.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | -------------------------------------------------------------------------------- /wgo/templates/wgo/wgo_iframe.html: -------------------------------------------------------------------------------- 1 | {% load static wgo_tags%} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /wgo/templates/wgo/wgoblock.html: -------------------------------------------------------------------------------- 1 | {% load wgo_tags %} 2 |
3 |
4 |
5 |
6 | -------------------------------------------------------------------------------- /wgo/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/climu/openstudyroom/f05941fc87f822824b250b8a7330f6d1e589d71e/wgo/templatetags/__init__.py -------------------------------------------------------------------------------- /wgo/templatetags/wgo_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def prepare_sgf(sgf): 8 | sgf = sgf.replace(';B[]', '').replace(';W[]', '').replace(';)', '').replace(':/', '').replace(';-)', '') 9 | return sgf 10 | 11 | @register.filter 12 | def prepare_sgf_file(value): 13 | f = value.file 14 | f.open(mode='rb') 15 | sgf = f.read() 16 | sgf = str(sgf, 'utf-8') 17 | sgf = sgf.replace(chr(34), '') 18 | return sgf 19 | # return "(;PB[Black]PW[White]RE[B+R];B[qd];W[dd];B[pq];W[dq];B[fc])" 20 | -------------------------------------------------------------------------------- /wgo/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from . import views 4 | 5 | app_name = 'wgo' 6 | 7 | 8 | urlpatterns = [ 9 | url( 10 | r'^tsumego-api/$', 11 | views.tsumego_api, 12 | name='tsumego_api', 13 | ), 14 | ] 15 | -------------------------------------------------------------------------------- /wgo/views.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | 4 | from django.http import HttpResponse 5 | 6 | from openstudyroom.settings.base import BASE_DIR 7 | 8 | 9 | def tsumego_api(request): 10 | """ 11 | Returns one random tsumego from the folowing sets: 12 | - 0 cho elementary 13 | - 1 cho intermediate 14 | - 2 cho advanced 15 | - 3 gokyoshumyo 16 | - 4 hatsuyoron 17 | """ 18 | set = random.choice(['cho-1-elementary', 'cho-2-intermediate', 'cho-3-advanced', 'gokyoshumyo', 'hatsuyoron']) 19 | sgf_file = open(os.path.join(BASE_DIR, 'wgo/tsumegos/' + set + '.sgf'), 'r') 20 | tsumego = random.choice(sgf_file.readlines()) 21 | sgf_file.close() 22 | return HttpResponse(tsumego, content_type='text/plain') 23 | --------------------------------------------------------------------------------