diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ceefedb --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.python-version +.venv/ +db.sqlite3 +__pycache__ +media/ +.env +.temp diff --git a/peacock/membership/admin.py b/peacock/membership/admin.py index 5af2943..a0df2b5 100644 --- a/peacock/membership/admin.py +++ b/peacock/membership/admin.py @@ -2,6 +2,7 @@ # Register your models here. from django.contrib import admin -from .models import Member +from .models import Member, Contribution -admin.site.register(Member) \ No newline at end of file +admin.site.register(Member) +admin.site.register(Contribution) diff --git a/peacock/membership/management/commands/getprinfo.py b/peacock/membership/management/commands/getprinfo.py new file mode 100644 index 0000000..49b5301 --- /dev/null +++ b/peacock/membership/management/commands/getprinfo.py @@ -0,0 +1,56 @@ +from django.core.management.base import BaseCommand, CommandError +from django.utils import timezone + +from membership.models import Member, Contribution +from projects.models import Project + +import os, json + +import requests + +class Command(BaseCommand): + help = "Get contribution information from GitHub for all members" + + def handle(self, *args, **options): + + with open("projects.txt", "r") as file: + repos = file.read().split() + + headers = {"Authorization": os.environ["GH_TOKEN"]} + + for member in Member.objects.all(): + url = f'https://api.github.com/search/issues?q=type:pr+author:{member.github_handle}&per_page=100' + while url is not None: + res = requests.get(url, headers=headers) + # set url to the next page, or None is no next page + url = None + for link in res.headers["Link"].split(","): + parts = link.strip().split(";") + if parts[1].strip() == 'rel="next"': + url = parts[0].strip("<").strip(">") + # parse and handle results + prs_json = json.loads(res.text)["items"] + for pr in prs_json: + repo = "/".join(pr["repository_url"].split("/")[-2:]) + id = "/".join(pr["html_url"].split("/")[-4:]) + if repo in repos: + pr_obj = list(Contribution.objects.filter(gh_id=pr["id"])) + if len(pr_obj) != 0: + obj = pr_obj[0] + obj.title = pr["title"] + obj.state = pr["state"] + obj.merged_at = pr.get("merged_at", None) + obj.save() + else: + obj = Contribution.objects.create( + id = id, + gh_id = pr["id"], + author = member, + html_url = pr["html_url"], + repo = Project.objects.get(full_name=repo), + title = pr["title"], + state = pr["state"], + created_at = pr["created_at"], + merged_at = pr.get("merged_at", None) + ) + obj.save() diff --git a/peacock/membership/migrations/0001_initial.py b/peacock/membership/migrations/0001_initial.py index 9f74883..fd08259 100644 --- a/peacock/membership/migrations/0001_initial.py +++ b/peacock/membership/migrations/0001_initial.py @@ -1,8 +1,10 @@ -# Generated by Django 5.1 on 2024-08-29 20:15 +# Generated by Django 5.1.1 on 2024-09-10 00:02 import django.contrib.auth.models import django.contrib.auth.validators +import django.db.models.deletion import django.utils.timezone +from django.conf import settings from django.db import migrations, models @@ -12,6 +14,7 @@ class Migration(migrations.Migration): dependencies = [ ('auth', '0012_alter_user_first_name_max_length'), + ('projects', '0001_initial'), ] operations = [ @@ -29,7 +32,18 @@ class Migration(migrations.Migration): ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('twitter_url', models.CharField(max_length=100)), + ('website_url', models.URLField(blank=True, null=True)), + ('twitter_url', models.URLField(blank=True, null=True)), + ('linkedin_url', models.URLField(blank=True, null=True)), + ('mastodon_url', models.URLField(blank=True, null=True)), + ('bio', models.CharField(blank=True, max_length=1000, null=True)), + ('avatar', models.ImageField(blank=True, null=True, upload_to='images/')), + ('pronouns', models.CharField(blank=True, max_length=40, null=True)), + ('location', models.CharField(blank=True, max_length=100, null=True)), + ('github_handle', models.CharField(max_length=40)), + ('confirmed_status', models.BooleanField(default=False)), + ('approved_status', models.BooleanField(default=False)), + ('approved_by', models.CharField(blank=True, max_length=40, null=True)), ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), ], @@ -42,4 +56,18 @@ class Migration(migrations.Migration): ('objects', django.contrib.auth.models.UserManager()), ], ), + migrations.CreateModel( + name='Contribution', + fields=[ + ('id', models.CharField(max_length=100, primary_key=True, serialize=False)), + ('gh_id', models.PositiveIntegerField()), + ('html_url', models.URLField()), + ('title', models.CharField(max_length=200)), + ('state', models.CharField(max_length=10)), + ('created_at', models.DateTimeField()), + ('merged_at', models.DateTimeField(blank=True, null=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='projects.project')), + ], + ), ] diff --git a/peacock/membership/models.py b/peacock/membership/models.py index 6c957de..028acbd 100644 --- a/peacock/membership/models.py +++ b/peacock/membership/models.py @@ -7,13 +7,36 @@ # avatar: (optional) # pronouns (optional) # location (?) -# List of projects. (optional for now) +# List of projects. (optional for now) **imprement later** # GitHub handle: connect with GitHub API. # confirmed status: whether email address is confirmed # approval status: whether approved by us. (True false) # approved by: the username of the admin who approved from django.contrib.auth.models import AbstractUser from django.db import models +from projects.models import Project class Member(AbstractUser): - twitter_url = models.CharField(max_length=100) + website_url = models.URLField(null=True, blank=True) + twitter_url = models.URLField(null=True, blank=True) + linkedin_url = models.URLField(null=True, blank=True) + mastodon_url = models.URLField(null=True, blank=True) + bio = models.CharField(max_length=1000, null=True, blank=True) + avatar = models.ImageField(upload_to='images/', null=True, blank=True) + pronouns = models.CharField(max_length=40, null=True, blank=True) + location = models.CharField(max_length=100, null=True, blank=True) + github_handle = models.CharField(max_length=40) + confirmed_status = models.BooleanField(default = False) + approved_status = models.BooleanField(default = False) + approved_by = models.CharField(max_length=40, null=True, blank=True) + +class Contribution(models.Model): + id = models.CharField(max_length=100, primary_key=True) + gh_id = models.PositiveIntegerField() + author = models.ForeignKey(Member, on_delete=models.CASCADE) + html_url = models.URLField() + repo = models.ForeignKey(Project, on_delete=models.CASCADE) + title = models.CharField(max_length=200) + state = models.CharField(max_length=10) + created_at = models.DateTimeField() + merged_at = models.DateTimeField(null=True, blank=True) diff --git a/peacock/membership/urls.py b/peacock/membership/urls.py index a9d7f56..b28c1dc 100644 --- a/peacock/membership/urls.py +++ b/peacock/membership/urls.py @@ -4,4 +4,5 @@ urlpatterns = [ path("", views.index, name="index"), -] \ No newline at end of file + path("/", views.profile, name="profile"), +] diff --git a/peacock/membership/views.py b/peacock/membership/views.py index 94cd2e8..16cecce 100644 --- a/peacock/membership/views.py +++ b/peacock/membership/views.py @@ -1,5 +1,6 @@ from django.http import HttpResponse from django.template import loader +from django.shortcuts import get_object_or_404, render from .models import Member @@ -12,4 +13,9 @@ def index(request): context = {"members" : members } - return HttpResponse(template.render(context, request)) \ No newline at end of file + return HttpResponse(template.render(context, request)) + +def profile(request, username): + member = get_object_or_404(Member, username=username) + return render(request, "membership/profile.html", {"member": member}) + diff --git a/peacock/pages/__init__.py b/peacock/pages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/peacock/pages/admin.py b/peacock/pages/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/peacock/pages/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/peacock/pages/apps.py b/peacock/pages/apps.py new file mode 100644 index 0000000..cdd024b --- /dev/null +++ b/peacock/pages/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PagesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'pages' diff --git a/peacock/pages/migrations/__init__.py b/peacock/pages/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/peacock/pages/models.py b/peacock/pages/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/peacock/pages/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/peacock/pages/tests.py b/peacock/pages/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/peacock/pages/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/peacock/pages/urls.py b/peacock/pages/urls.py new file mode 100644 index 0000000..0776fc4 --- /dev/null +++ b/peacock/pages/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("/", views.page, name="page"), +] diff --git a/peacock/pages/views.py b/peacock/pages/views.py new file mode 100644 index 0000000..bc8f923 --- /dev/null +++ b/peacock/pages/views.py @@ -0,0 +1,9 @@ +from django.shortcuts import render +import markdown + + +def page(request, page_slug): + f = open(f"static/pages/{page_slug}.md","r") + f = f.read() + html = markdown.markdown(f) + return render(request, "pages/page.html", {"content": html}) diff --git a/peacock/peacock/settings.py b/peacock/peacock/settings.py index 7f03c13..fcc8ce0 100644 --- a/peacock/peacock/settings.py +++ b/peacock/peacock/settings.py @@ -11,6 +11,7 @@ """ from pathlib import Path +import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -37,7 +38,9 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'membership' + 'membership', + 'pages', + 'projects' ] MIDDLEWARE = [ @@ -55,7 +58,7 @@ TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [BASE_DIR / "templates"], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -117,10 +120,17 @@ # https://docs.djangoproject.com/en/4.2/howto/static-files/ STATIC_URL = 'static/' +STATICFILES_DIRS = [ + BASE_DIR / "static", +] +# STATIC_ROOT = os.path.join(BASE_DIR, 'static') # Default primary key field type # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -AUTH_USER_MODEL = 'membership.Member' \ No newline at end of file +AUTH_USER_MODEL = 'membership.Member' + +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_URL = '/media/' diff --git a/peacock/peacock/urls.py b/peacock/peacock/urls.py index f3e4d05..ec75686 100644 --- a/peacock/peacock/urls.py +++ b/peacock/peacock/urls.py @@ -16,8 +16,14 @@ """ from django.contrib import admin from django.urls import include, path +from django.conf import settings +from django.conf.urls.static import static +from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path("membership/", include("membership.urls")), -] + path("pages/", include("pages.urls")), + path('', TemplateView.as_view(template_name='index.html')), +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + # + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/peacock/projects.txt b/peacock/projects.txt new file mode 100644 index 0000000..d45eca4 --- /dev/null +++ b/peacock/projects.txt @@ -0,0 +1,29 @@ +pandas-dev/pandas +numpy/numpy +scikit-learn/scikit-learn +scikit-image/scikit-image +pola-rs/polars +pola-rs/pyo3-polars +pallets/flask +django/django +adamchainz/django-htmx +PyO3/pyo3 +PyO3/maturin +astral-sh/uv +astral-sh/ruff +pytest-dev/pytest +HypothesisWorks/hypothesis +pygame/pygame +Rapptz/discord.py +tox-dev/tox +fastapi/fastapi +pydantic/pydantic +tensorflow/tensorflow +keras-team/keras +pytorch/pytorch +matplotlib/matplotlib +bokeh/bokeh +plotly/dash +mwaskom/seaborn +napari/napari +narwhals-dev/narwhals diff --git a/peacock/projects/__init__.py b/peacock/projects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/peacock/projects/admin.py b/peacock/projects/admin.py new file mode 100644 index 0000000..f19ae66 --- /dev/null +++ b/peacock/projects/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +from .models import Owner, Project + +admin.site.register(Owner) +admin.site.register(Project) diff --git a/peacock/projects/apps.py b/peacock/projects/apps.py new file mode 100644 index 0000000..afae498 --- /dev/null +++ b/peacock/projects/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ProjectsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'projects' diff --git a/peacock/projects/management/commands/getprojectinfo.py b/peacock/projects/management/commands/getprojectinfo.py new file mode 100644 index 0000000..e0606ea --- /dev/null +++ b/peacock/projects/management/commands/getprojectinfo.py @@ -0,0 +1,70 @@ +from django.core.management.base import BaseCommand, CommandError +from django.utils import timezone + +from projects.models import Owner, Project + +import os, json + +import requests + +class Command(BaseCommand): + help = "Get project information from GitHub" + + def handle(self, *args, **options): + + with open("projects.txt", "r") as file: + repos = file.read().split() + + headers = {"Authorization": os.environ["GH_TOKEN"]} + + for repo in repos: + url = "https://api.github.com/repos/" + repo + res = requests.get(url, headers=headers) + repo_json = json.loads(res.text) + # create owner object + owner_json = repo_json["owner"] + owner_obj = list(Owner.objects.filter(name=owner_json["login"])) + if len(owner_obj) != 0: + obj = owner_obj[0] + obj.html_url=owner_json["html_url"] + obj.avatar_url = owner_json["avatar_url"] + obj.last_info_update = timezone.now() + obj.save() + print(f"Owner object ({owner_json["login"]}) updated.") + else: + obj = Owner.objects.create( + name=owner_json["login"], + html_url=owner_json["html_url"], + avatar_url = owner_json["avatar_url"], + gh_id = owner_json["id"], + last_info_update = timezone.now() + ) + obj.save() + print(f"Owner object ({owner_json["login"]}) created.") + + # create project object + + repo_obj = list(Project.objects.filter(gh_id=repo_json["id"])) + + if len(repo_obj) != 0: + pobj = repo_obj[0] + pobj.full_name = repo_json["full_name"] + pobj.owner = obj + pobj.repo_name = repo_json["name"] + pobj.html_url = repo_json["html_url"] + pobj.description = repo_json["description"] + pobj.last_info_update = models.DateTimeField("last info update") + pobj.save() + print(f"Project object ({repo_json["full_name"]}) updated.") + else: + pobj = Project.objects.create( + full_name = repo_json["full_name"], + owner = obj, + repo_name = repo_json["name"], + html_url = repo_json["html_url"], + description = repo_json["description"], + gh_id = repo_json["id"], + last_info_update = timezone.now() + ) + pobj.save() + print(f"Project object ({repo_json["full_name"]}) created.") diff --git a/peacock/projects/migrations/0001_initial.py b/peacock/projects/migrations/0001_initial.py new file mode 100644 index 0000000..b5dd674 --- /dev/null +++ b/peacock/projects/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# Generated by Django 5.1.1 on 2024-09-10 00:02 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Owner', + fields=[ + ('name', models.CharField(max_length=40, primary_key=True, serialize=False)), + ('html_url', models.URLField()), + ('avatar_url', models.URLField()), + ('gh_id', models.PositiveIntegerField()), + ('last_info_update', models.DateTimeField()), + ], + ), + migrations.CreateModel( + name='Project', + fields=[ + ('full_name', models.CharField(max_length=40, primary_key=True, serialize=False)), + ('repo_name', models.CharField(max_length=40)), + ('html_url', models.URLField()), + ('description', models.CharField(max_length=1000)), + ('gh_id', models.PositiveIntegerField()), + ('last_info_update', models.DateTimeField()), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='projects.owner')), + ], + ), + ] diff --git a/peacock/projects/migrations/__init__.py b/peacock/projects/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/peacock/projects/models.py b/peacock/projects/models.py new file mode 100644 index 0000000..04b77dd --- /dev/null +++ b/peacock/projects/models.py @@ -0,0 +1,18 @@ +from django.db import models + + +class Owner(models.Model): + name = models.CharField(max_length=40, primary_key=True) + html_url = models.URLField() + avatar_url = models.URLField() + gh_id = models.PositiveIntegerField() + last_info_update = models.DateTimeField() + +class Project(models.Model): + full_name = models.CharField(max_length=40, primary_key=True) + owner = models.ForeignKey(Owner, on_delete=models.CASCADE) + repo_name = models.CharField(max_length=40) + html_url = models.URLField() + description = models.CharField(max_length=1000) + gh_id = models.PositiveIntegerField() + last_info_update = models.DateTimeField() diff --git a/peacock/projects/tests.py b/peacock/projects/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/peacock/projects/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/peacock/projects/views.py b/peacock/projects/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/peacock/projects/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/peacock/static/css/w3.css b/peacock/static/css/w3.css new file mode 100644 index 0000000..e4d8f8e --- /dev/null +++ b/peacock/static/css/w3.css @@ -0,0 +1,235 @@ +/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */ +html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} +/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ +html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} +article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item} +audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} +audio:not([controls]){display:none;height:0}[hidden],template{display:none} +a{background-color:transparent}a:active,a:hover{outline-width:0} +abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} +b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000} +small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none} +code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} +button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold} +button,input{overflow:visible}button,select{text-transform:none} +button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button} +button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0} +button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText} +fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} +legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} +[type=checkbox],[type=radio]{padding:0} +[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} +[type=search]{-webkit-appearance:textfield;outline-offset:-2px} +[type=search]::-webkit-search-decoration{-webkit-appearance:none} +::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} +/* End extract */ +html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} +h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px} +.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace} +h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} +hr{border:0;border-top:1px solid #eee;margin:20px 0} +.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} +.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} +.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} +.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} +.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} +.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} +.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} +.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} +.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} +.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} +.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} +.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} +.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} +.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} +.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} +.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} +.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} +.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} +.w3-dropdown-hover:hover .w3-dropdown-content{display:block} +.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} +.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} +.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} +.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px} +.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} +.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} +.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} +.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} +.w3-main,#main{transition:margin-left .4s} +.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} +.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} +.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} +.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} +.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} +.w3-bar .w3-button{white-space:normal} +.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} +.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} +.w3-responsive{display:block;overflow-x:auto} +.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, +.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} +.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} +.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} +.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} +.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} +@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} +.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} +.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} +@media (min-width:9993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} +.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} +.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} +.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px} +.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px} +.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} +.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} +.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} +@media (max-width:1205px){.w3-auto{max-width:95%}} +@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} +.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative} +.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} +.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} +@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} +@media (min-width:9993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} +@media (max-width:9992px) and (min-width:601px){.w3-hide-medium{display:none!important}} +@media (max-width:9992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}} +.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} +.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} +.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} +.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} +.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} +.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} +.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} +.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} +.w3-display-position{position:absolute} +.w3-circle{border-radius:50%} +.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} +.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} +.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} +.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} +.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} +.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} +.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} +.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} +.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} +.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} +.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} +.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} +.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} +.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} +.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} +.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} +.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} +.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} +.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} +.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} +.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} +.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} +.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} +.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} +.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} +.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} +.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} +.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} +.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} +.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} +.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} +.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} +.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} +.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} +.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} +.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} +.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} +.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important} +.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important} +.w3-left{float:left!important}.w3-right{float:right!important} +.w3-button:hover{color:#000!important;background-color:#ccc!important} +.w3-transparent,.w3-hover-none:hover{background-color:transparent!important} +.w3-hover-none:hover{box-shadow:none!important} +/* Colors */ +.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important} +.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important} +.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important} +.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important} +.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important} +.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important} +.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important} +.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important} +.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important} +.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important} +.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important} +.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important} +.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important} +.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important} +.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important} +.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important} +.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important} +.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important} +.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important} +.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important} +.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important} +.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important} +.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important} +.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important} +.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important} +.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important} +.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important} +.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important} +.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important} +.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important} +.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important} +.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important} +.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important} +.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important} +.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important} +.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important} +.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important} +.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important} +.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important} +.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important} +.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important} +.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important} +.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important} +.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important} +.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important} +.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important} +.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important} +.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important} +.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important} +.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important} +.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important} +.w3-text-white,.w3-hover-text-white:hover{color:#fff!important} +.w3-text-black,.w3-hover-text-black:hover{color:#000!important} +.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important} +.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important} +.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important} +.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important} +.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important} +.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important} +.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important} +.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important} +.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important} +.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important} +.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important} +.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important} +.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important} +.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important} +.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important} +.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important} +.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important} +.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important} +.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important} +.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important} +.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important} +.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important} +.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important} +.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important} +.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important} +.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important} +.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important} +.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important} +.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important} +.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important} +.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important} diff --git a/peacock/static/images/femalecodertocat.png b/peacock/static/images/femalecodertocat.png new file mode 100644 index 0000000..92a5f22 Binary files /dev/null and b/peacock/static/images/femalecodertocat.png differ diff --git a/peacock/static/pages/about.md b/peacock/static/pages/about.md new file mode 100644 index 0000000..47711ad --- /dev/null +++ b/peacock/static/pages/about.md @@ -0,0 +1,3 @@ +# About this project + +This project aims to help to encourage under-represented folks to contribute to open source Python libraries. diff --git a/peacock/static/pages/coc.md b/peacock/static/pages/coc.md new file mode 100644 index 0000000..ec27fca --- /dev/null +++ b/peacock/static/pages/coc.md @@ -0,0 +1,137 @@ +# Code of Conduct + +The Python community is made up of members from around the globe with a diverse set of skills, personalities, and experiences. It is through these differences that our community experiences great successes and continued growth. When you're working with members of the community, this Code of Conduct will help steer your interactions and keep Python a positive, successful, and growing community. + +## Our Community + +Members of the Python community are open, considerate, and respectful. Behaviours that reinforce these values contribute to a positive environment, and include: + +Being open. Members of the community are open to collaboration, whether it's on PEPs, patches, problems, or otherwise. +Focusing on what is best for the community. We're respectful of the processes set forth in the community, and we work within them. +Acknowledging time and effort. We're respectful of the volunteer efforts that permeate the Python community. We're thoughtful when addressing the efforts of others, keeping in mind that often times the labor was completed simply for the good of the community. +Being respectful of differing viewpoints and experiences. We're receptive to constructive comments and criticism, as the experiences and skill sets of other members contribute to the whole of our efforts. +Showing empathy towards other community members. We're attentive in our communications, whether in person or online, and we're tactful when approaching differing views. +Being considerate. Members of the community are considerate of their peers -- other Python users. +Being respectful. We're respectful of others, their positions, their skills, their commitments, and their efforts. +Gracefully accepting constructive criticism. When we disagree, we are courteous in raising our issues. +Using welcoming and inclusive language. We're accepting of all who wish to take part in our activities, fostering an environment where anyone can participate and everyone can make a difference. +Our Standards +Every member of our community has the right to have their identity respected. The Python community is dedicated to providing a positive experience for everyone, regardless of age, gender identity and expression, sexual orientation, disability, physical appearance, body size, ethnicity, nationality, race, or religion (or lack thereof), education, or socio-economic status. + +## Inappropriate Behavior + +Examples of unacceptable behavior by participants include: + +- Harassment of any participants in any form +- Deliberate intimidation, stalking, or following +- Logging or taking screenshots of online activity for harassment purposes +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Violent threats or language directed against another person +- Incitement of violence or harassment towards any individual, including encouraging a person to commit suicide or to engage in self-harm +- Creating additional online accounts in order to harass another person or circumvent a ban +- Sexual language and imagery in online communities or in any conference venue, including talks +- Insults, put downs, or jokes that are based upon stereotypes, that are exclusionary, or that hold others up for ridicule +- Excessive swearing +- Unwelcome sexual attention or advances +- Unwelcome physical contact, including simulated physical contact (eg, textual descriptions like "hug" or "backrub") without consent or after a request to stop +- Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others +- Sustained disruption of online community discussions, in-person presentations, or other in-person events +- Continued one-on-one communication after requests to cease +- Other conduct that is inappropriate for a professional audience including people of many different backgrounds +- Community members asked to stop any inappropriate behavior are expected to comply immediately. + +## Consequences + +If a participant engages in behavior that violates this code of conduct, the Python community Code of Conduct team may take any action they deem appropriate, including warning the offender or expulsion from the community and community events with no refund of event tickets. The full list of consequences for inappropriate behavior is listed in the Enforcement Procedures. + +Thank you for helping make this a welcoming, friendly community for everyone. + +## Scope + +PSF Events +This Code of Conduct applies to the following people at events hosted by the Python Software Foundation, and events hosted by projects under the PSF's fiscal sponsorship: + +- staff +- Python Software Foundation board members +- speakers +- panelists +- tutorial or workshop leaders +- poster presenters +- people invited to meetings or summits +- exhibitors +- organizers +- volunteers +- all attendees + +The Code of Conduct applies in official venue event spaces, including: + +- exhibit hall or vendor tabling area +- panel and presentation rooms +- hackathon or sprint rooms +- tutorial or workshop rooms +- poster session rooms +- summit or meeting rooms +- staff areas +- con suite +- meal areas +- party suites +- walkways, hallways, elevators, and stairs that connect any of the above spaces + +The Code of Conduct applies to interactions with official event accounts on social media spaces and phone applications, including: + +- comments made on official conference phone apps +- comments made on event video hosting services +- comments made on the official event hashtag or panel hashtags + +Event organizers will enforce this code throughout the event. Each event is required to provide a Code of Conduct committee that receives, evaluates, and acts on incident reports. Each event is required to provide contact information for the committee to attendees. The event Code of Conduct committee may (but is not required to) ask for advice from the Python Software Foundation Code of Conduct work group. The Python Software Foundation Code of Conduct work group can be reached by emailing conduct-wg@python.org. + +## PSF Online Spaces + +This Code of Conduct applies to the following online spaces: + +- The python-ideas, core-mentorship, python-dev, docs mailing lists +- All other mailing lists hosted on python.org +- Python Software Foundation Zulip chat server +- Python Software Foundation hosted Discourse server discuss.python.org +- Code repositories, issue trackers, and pull requests made against any Python Software Foundation controlled GitHub organization +- The python.org mercurial server hg.python.org +- Any other online space administered by the Python Software + +## Foundation + +This Code of Conduct applies to the following people in official Python Software Foundation online spaces: + +- PSF Members, including Fellows +- admins of the online space +- maintainers +- reviewers +- contributors +- all community members + +Each online space listed above is required to provide the following information to the Python Software Foundation Code of Conduct work group: + +contact information for any administrators/moderators + +Each online space listed above is encouraged to provide the following information to community members: + +a welcome message with a link to this Code of Conduct and the contact information for making an incident report conduct-wg@python.org +The Python Software Foundation Code of Conduct work group will receive and evaluate incident reports from the online communities listed above. The Python Software Foundation Code of Conduct work group will work with online community administrators/moderators to suggest actions to take in response to a report. In cases where the administrators/moderators disagree on the suggested resolution for a report, the Python Software Foundation Code of Conduct work group may choose to notify the Python Software Foundation board. + +## Contact Information + +If you believe that someone is violating the code of conduct, or have any other concerns, please contact a member of the Python Software Foundation Code of Conduct work group immediately. They can be reached by emailing conduct-wg@python.org + +## Procedure for Handling Incidents + +Python Software Foundation Community Member Procedure For Reporting Code of Conduct Incidents + +Python Software Foundation Code of Conduct Working Group Enforcement Procedures + +## License +This Code of Conduct is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. + +Creative Commons License + +## Attributions + +This Code of conduct is created in the spirit of the [Python Software Foundation Code of conduct](https://policies.python.org/python.org/code-of-conduct/). diff --git a/peacock/templates/head.html b/peacock/templates/head.html new file mode 100644 index 0000000..7bdcd85 --- /dev/null +++ b/peacock/templates/head.html @@ -0,0 +1,12 @@ + +Peacock + + +{% load static %} + + + + + diff --git a/peacock/templates/index.html b/peacock/templates/index.html new file mode 100644 index 0000000..a38962f --- /dev/null +++ b/peacock/templates/index.html @@ -0,0 +1,238 @@ + + +{% include "head.html" %} + + +{% include "top.html" %} + +{% include "menu.html" %} + + +
+ + +
+
My Dashboard
+
+ +
+
+
+
+
+

52

+
+
+

Messages

+
+
+
+
+
+
+

99

+
+
+

Views

+
+
+
+
+
+
+

23

+
+
+

Shares

+
+
+
+
+
+
+

50

+
+
+

Users

+
+
+
+ +
+
+
+
Regions
+ Google Regional Map +
+
+
Feeds
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New record, over 90 views.10 mins
Database error.15 mins
New record, over 40 users.17 mins
New comments.25 mins
Check transactions.28 mins
CPU overload.35 mins
New shares.39 mins
+
+
+
+
+
+
General Stats
+

New Visitors

+
+
+25%
+
+ +

New Users

+
+
50%
+
+ +

Bounce Rate

+
+
75%
+
+
+
+ +
+
Countries
+ + + + + + + + + + + + + + + + + + + + + + + + + +
United States65%
UK15.7%
Russia5.6%
Spain2.1%
India1.9%
France1.5%

+ +
+
+
+
Recent Users
+
    +
  • + + Mike
    +
  • +
  • + + Jill
    +
  • +
  • + + Jane
    +
  • +
+
+
+ +
+
Recent Comments
+
+
+ +
+
+

John Sep 29, 2014, 9:12 PM

+

Keep up the GREAT work! I am cheering for you!! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.


+
+
+ +
+
+ +
+
+

Bo Sep 28, 2014, 10:15 PM

+

Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.


+
+
+
+
+
+
+
+
Demographic
+

Language

+

Country

+

City

+
+
+
System
+

Browser

+

OS

+

More

+
+
+
Target
+

Users

+

Active

+

Geo

+

Interests

+
+
+
+ + +
+

FOOTER

+

Powered by w3.css

+
+ + +
+ +{% include "script.html" %} + + + diff --git a/peacock/membership/templates/membership/index.html b/peacock/templates/membership/index.html similarity index 100% rename from peacock/membership/templates/membership/index.html rename to peacock/templates/membership/index.html diff --git a/peacock/templates/membership/profile.html b/peacock/templates/membership/profile.html new file mode 100644 index 0000000..9cc191e --- /dev/null +++ b/peacock/templates/membership/profile.html @@ -0,0 +1,21 @@ + + +{% include "head.html" %} + + +{% include "top.html" %} + +{% include "menu.html" %} + + +
+ +{% include "membership/profile_content.html" %} + + +
+ +{% include "script.html" %} + + + diff --git a/peacock/templates/membership/profile_content.html b/peacock/templates/membership/profile_content.html new file mode 100644 index 0000000..b9d6acb --- /dev/null +++ b/peacock/templates/membership/profile_content.html @@ -0,0 +1,39 @@ +
+ {% if member.avatar %} + {{ member.username}}'s avatar picture' + {% endif %} +

{{member.first_name}} {{member.last_name}}

+

{{member.username}} + {% if member.pronouns %} + · {{member.pronouns}} + {% endif %} +

+ {% if member.bio %} +
{{member.bio}}
+ {% endif %} +
+ {% if member.location %} +
Location: {{member.location}}
+ {% endif %} + GitHub: {{member.github_handle}} + {% if member.website_url %} +
Website: + {{member.website_url}} +
+ {% endif %} + {% if member.twitter_url %} +
Twitter: + {{member.twitter_url}} +
+ {% endif %} + {% if member.linkedin_url %} +
LinkedIn: + {{member.linkedin_url}} +
+ {% endif %} + {% if member.mastodon_url %} +
Mastodon: + {{member.mastodon_url}} +
+ {% endif %} +
diff --git a/peacock/templates/menu.html b/peacock/templates/menu.html new file mode 100644 index 0000000..174107a --- /dev/null +++ b/peacock/templates/menu.html @@ -0,0 +1,47 @@ + + + + + +
diff --git a/peacock/templates/pages/page.html b/peacock/templates/pages/page.html new file mode 100644 index 0000000..bccaa7f --- /dev/null +++ b/peacock/templates/pages/page.html @@ -0,0 +1,23 @@ + + +{% include "head.html" %} + + +{% include "top.html" %} + +{% include "menu.html" %} + + +
+ +
+ {{ content | safe }} +
+ + +
+ +{% include "script.html" %} + + + diff --git a/peacock/templates/script.html b/peacock/templates/script.html new file mode 100644 index 0000000..5eb5360 --- /dev/null +++ b/peacock/templates/script.html @@ -0,0 +1,24 @@ + diff --git a/peacock/templates/top.html b/peacock/templates/top.html new file mode 100644 index 0000000..415dfef --- /dev/null +++ b/peacock/templates/top.html @@ -0,0 +1,5 @@ + +
+ + Logo +
diff --git a/requirements.txt b/requirements.txt index 68d357c..e816a4a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,4 @@ -django \ No newline at end of file +django +pillow +markdown +requests