Changeset - 630bf4086135
[Not reviewed]
11 29 11
Joel Addison - 18 months ago 2022-12-07 14:08:54
joel@addison.net.au
Everything Open 2023 - Initial Setup
47 files changed with 406 insertions and 512 deletions:
0 comments (0 inline, 0 general)
.gitlab-ci.yml
Show inline comments
 
stages:
 
  - build
 
  - deploy
 

	
 
variables:
 
  DOCKER_TLS_CERTDIR: "/certs"
 
  CONTAINER_PREFIX: 2022
 
  CONTAINER_PREFIX: 2023
 
  CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/$CONTAINER_PREFIX:$CI_COMMIT_SHA
 

	
 
build-image:
 
  image: docker:git
 
  stage: build
 
  services:
 
  - docker:dind
 
  script:
 
    - apk update && apk add git
 
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
 
    - docker build --pull -f docker/Dockerfile -t $CONTAINER_IMAGE .
 
    - docker push $CONTAINER_IMAGE
 
  only:
 
    - "2022"
 
    - conf/2023
 

	
 
k8s-deploy-staging:
 
  image: google/cloud-sdk
 
  stage: deploy
 
  script:
 
  - echo "${CA_CERT}" > cert.crt
 
  - kubectl config set-cluster cluster --server="${KUBE_SERVER}" --embed-certs=true --certificate-authority=cert.crt
 
  - kubectl config set-context cluster --cluster=cluster --namespace=lca2022-staging --user=gitlab-ci
 
  - kubectl config set-context cluster --cluster=cluster --namespace=eo2023-staging --user=gitlab-ci
 
  - kubectl config use-context cluster
 
  - kubectl --token "${KUBE_TOKEN}" set image deployment/symposion-app symposion-app=$CONTAINER_IMAGE
 
  when: manual
 
  only:
 
  - dev/2022
 
  - dev/2023
 
  environment:
 
    name: 2022/staging
 
    url: https://staging-lca2022.gc2020.org/
 
    name: 2023/staging
 
    url: https://staging-eo2023.osaconftools.net/
 

	
 
k8s-deploy-prod:
 
  image: google/cloud-sdk
 
  stage: deploy
 
  script:
 
  - echo "${CA_CERT}" > cert.crt
 
  - kubectl config set-cluster cluster --server="${KUBE_SERVER}" --embed-certs=true --certificate-authority=cert.crt
 
  - kubectl config set-context cluster --cluster=cluster --namespace=lca2022-prod --user=gitlab-ci
 
  - kubectl config set-context cluster --cluster=cluster --namespace=eo2023-prod --user=gitlab-ci
 
  - kubectl config use-context cluster
 
  - kubectl --token "${KUBE_TOKEN}" set image deployment/symposion-app symposion-app=$CONTAINER_IMAGE
 
  when: manual
 
  only:
 
  - "2022"
 
  - conf/2023
 
  environment:
 
    name: 2022/prod
 
    url: https://lca2022.linux.org.au
 
    name: 2023/prod
 
    url: https://2023.everythingopen.au/
 

	
 
.docs_template: &sphinx
 
  image: alpine
 
  script:
 
  - apk --no-cache add py3-pip python3-dev make
 
  - pip install sphinx
 
  - cd docs
 
  - make html
 
  - cd ..
 
  - mv docs/_build/html public
 
  artifacts:
 
    paths:
 
    - public
 

	
 
pages:
 
  <<: *sphinx
 
  stage: build
 
  only:
 
  - master
 
  - "2022"
 
  - conf/2023
 
  environment:
 
    name: docs
 
    url: https://laconfdev.gitlab.io/symposion_app/
 

	
 
build-sphinx:
 
  <<: *sphinx
 
  stage: build
 
  except:
 
  - master
 
  - "2022"
 
  - conf/2023
fixtures/2022/auth.permission.json
Show inline comments
 
deleted file
fixtures/2022/conference.section.json
Show inline comments
 
deleted file
fixtures/2022/proposals.proposalsection.json
Show inline comments
 
deleted file
fixtures/conference.json
Show inline comments
 
[
 
{
 
  "model": "symposion_conference.conference",
 
  "pk": 1,
 
  "fields": {
 
    "title": "linux.conf.au 2022",
 
    "start_date": "2022-01-14",
 
    "end_date": "2022-01-16",
 
    "timezone": "Australia/Canberra"
 
    "title": "Everything Open 2023",
 
    "start_date": "2023-03-14",
 
    "end_date": "2023-03-16",
 
    "timezone": "Australia/Melbourne"
 
  }
 
}
 
]
fixtures/flatpages.json
Show inline comments
 
[
 
{
 
  "model": "flatpages.flatpage",
 
  "pk": 1,
 
  "fields": {
 
    "url": "/",
 
    "title": "Home Page",
 
    "content": "Here is the home page for LCA.\r\n\r\nOther pages to come.",
 
    "content": "Here is the home page.\r\n\r\nOther pages to come.",
 
    "enable_comments": false,
 
    "template_name": "",
 
    "registration_required": false,
 
    "sites": [
 
      1
 
    ]
 
  }
 
}
 
]
fixtures/sessions/auth.group.json
Show inline comments
 
file renamed from fixtures/2022/auth.group.json to fixtures/sessions/auth.group.json
fixtures/sessions/auth.permission.json
Show inline comments
 
new file 100644
 
[
 
{
 
  "model": "auth.permission",
 
  "fields": {
 
    "name": "Can review Main Conference",
 
    "content_type": [
 
      "reviews",
 
      ""
 
    ],
 
    "codename": "can_review_main"
 
  }
 
},
 
{
 
  "model": "auth.permission",
 
  "fields": {
 
    "name": "Can manage Main Conference",
 
    "content_type": [
 
      "reviews",
 
      ""
 
    ],
 
    "codename": "can_manage_main"
 
  }
 
}
 
]
fixtures/sessions/conference.section.json
Show inline comments
 
new file 100644
 
[
 
{
 
  "model": "symposion_conference.section",
 
  "pk": 1,
 
  "fields": {
 
    "conference": 1,
 
    "name": "Main Conference",
 
    "slug": "main",
 
    "start_date": "2023-03-14",
 
    "end_date": "2023-03-16"
 
  }
 
}
 
]
fixtures/sessions/proposals.proposalkind.json
Show inline comments
 
file renamed from fixtures/2022/proposals.proposalkind.json to fixtures/sessions/proposals.proposalkind.json
 
[
 
{
 
  "model": "symposion_proposals.proposalkind",
 
  "pk": 1,
 
  "fields": {
 
    "section": 1,
 
    "name": "Talk",
 
    "slug": "talk"
 
  }
 
},
 
{
 
  "model": "symposion_proposals.proposalkind",
 
  "pk": 3,
 
  "pk": 2,
 
  "fields": {
 
    "section": 2,
 
    "name": "Miniconf",
 
    "slug": "miniconf"
 
    "section": 1,
 
    "name": "Tutorial",
 
    "slug": "tutorial"
 
  }
 
}
 
]
fixtures/sessions/proposals.proposalsection.json
Show inline comments
 
new file 100644
 
[
 
{
 
  "model": "symposion_proposals.proposalsection",
 
  "pk": 1,
 
  "fields": {
 
    "section": 1,
 
    "start": "2022-12-07T12:00:00Z",
 
    "end": "2023-01-09T12:00:00Z",
 
    "closed": false,
 
    "published": true
 
  }
 
}
 
]
fixtures/sessions/teams.team.json
Show inline comments
 
file renamed from fixtures/2022/teams.team.json to fixtures/sessions/teams.team.json
 
[
 
{
 
  "model": "teams.team",
 
  "pk": 1,
 
  "fields": {
 
    "slug": "main-proposals",
 
    "name": "linux.conf.au Sessions Team",
 
    "description": "Team looking after the linux.conf.au Call for Sessions",
 
    "name": "Sessions Team",
 
    "description": "Team looking after the Call for Sessions",
 
    "access": "invitation",
 
    "created": "2019-06-23T08:16:34.032Z",
 
    "permissions": [
 
      [
 
        "can_review_main",
 
        "reviews",
 
        ""
 
      ],
 
      [
 
        "can_review_miniconf",
 
        "reviews",
 
        ""
 
      ]
 
    ],
 
    "manager_permissions": [
 
      [
 
        "can_manage_main",
 
        "reviews",
 
        ""
 
      ],
 
      [
 
        "can_review_main",
 
        "reviews",
 
        ""
 
      ]
 
    ]
 
  }
 
},
 
{
 
  "model": "teams.team",
 
  "pk": 2,
 
  "fields": {
 
    "slug": "organising-team",
 
    "name": "linux.conf.au Organising Team",
 
    "description": "The organising team for linux.conf.au",
 
    "name": "Organising Team",
 
    "description": "The conference organising team",
 
    "access": "invitation",
 
    "created": "2019-08-26T22:59:09.265Z",
 
    "permissions": [
 
      [
 
        "can_review_main",
 
        "reviews",
 
        ""
 
      ],
 
      [
 
        "can_review_miniconf",
 
        "reviews",
 
        ""
 
      ]
 
    ],
 
    "manager_permissions": []
 
  }
 
}
 
]
fixtures/sites.json
Show inline comments
 
[
 
{
 
  "model": "sites.site",
 
  "pk": 1,
 
  "fields": {
 
    "domain": "lca2022.linux.org.au",
 
    "name": "linux.conf.au 2022"
 
    "domain": "2023.everythingopen.au",
 
    "name": "Everything Open 2023"
 
  }
 
}
 
]
fixtures/sitetree.json
Show inline comments
...
 
@@ -110,49 +110,49 @@
 
    "title": "News",
 
    "hint": "",
 
    "url": "/news/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 3,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 6,
 
  "fields": {
 
    "title": "About LCA2022",
 
    "title": "About Everything Open",
 
    "hint": "",
 
    "url": "/about/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 2,
 
    "sort_order": 6,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 7,
 
  "fields": {
 
    "title": "Location",
k8s/deployment_template.jsonnet
Show inline comments
...
 
@@ -100,49 +100,49 @@ function (slug, sha) {
 
                          "secretKeyRef": {
 
                            "key": "STRIPE_PUBLIC_KEY",
 
                            "name": "symposion-app-config"
 
                          }
 
                        }
 
                      },
 
                      {
 
                        "name": "STRIPE_SECRET_KEY",
 
                        "valueFrom": {
 
                          "secretKeyRef": {
 
                            "key": "STRIPE_SECRET_KEY",
 
                            "name": "symposion-app-config"
 
                          }
 
                        }
 
                      },
 
                      {
 
                        "name": "SYMPOSION_DEV_MODE",
 
                        "value": "LAPTOP"
 
                      },
 
                      {
 
                        "name": "ANALYTICS_KEY",
 
                        "value": "UA-000000000-1"
 
                      }
 
                    ],
 
                    "image": "asia.gcr.io/linuxconfsydney/symposion_app_2022_dev:" + sha,
 
                    "image": "registry.gitlab.com/laconfdev/symposion_app/2023:" + sha,
 
                    "imagePullPolicy": "Always",
 
                    "livenessProbe": {
 
                      "failureThreshold": 3,
 
                      "httpGet": {
 
                        "path": "/admin/login/",
 
                        "port": 8000,
 
                        "scheme": "HTTP"
 
                      },
 
                      "initialDelaySeconds": 180,
 
                      "periodSeconds": 10,
 
                      "successThreshold": 1,
 
                      "timeoutSeconds": 5
 
                    },
 
                    "name": app,
 
                    "ports": [
 
                      {
 
                        "containerPort": 8000,
 
                        "protocol": "TCP"
 
                      }
 
                    ],
 
                    "resources": {},
 
                    "terminationMessagePath": "/dev/termination-log",
 
                    "terminationMessagePolicy": "File"
 
                  }
make_dev_container.sh
Show inline comments
...
 
@@ -5,43 +5,43 @@ IMAGE_NAME=${1:-symposion_app}
 
if [ -e ./symposion-tools ]; then
 
    pushd ./symposion-tools
 
    ./save_db_from_docker.sh
 
    popd
 
fi
 

	
 
# Check for docker running
 
if ! docker info >/dev/null 2>&1; then
 
    echo "Docker does not seem to be running. Please start it and retry."
 
    exit 1
 
fi
 

	
 
docker image build -f docker/Dockerfile -t ${IMAGE_NAME} --target symposion_dev .
 
docker container stop symposion
 
docker container rm symposion
 
docker container create --env-file docker/laptop-mode-env -p 28000:8000 -v $(pwd):/app/symposion_app --name symposion ${IMAGE_NAME}
 
docker container start symposion
 
## When we started the container and mounted . into /app/symposion_app, it hides the static/build directory
 
## As a kludge, re-run collectstatic to recreate it
 
## Possible alternative here: don't mount all of ., just mount the bits that we'd live to have update live
 
docker exec symposion ./manage.py collectstatic --noinput -v 0
 
docker exec symposion ./manage.py migrate
 
docker exec symposion ./manage.py loaddata ./fixtures/{conference,sites,sitetree,flatpages}.json
 
docker exec symposion ./manage.py create_review_permissions
 
docker exec symposion ./manage.py loaddata ./fixtures/????/*.json
 
docker exec symposion ./manage.py loaddata ./fixtures/sessions/*.json
 
docker exec symposion ./manage.py populate_inventory
 

	
 
if [ -e ./symposion-tools ]; then
 
    pushd ./symposion-tools
 
    ./fixture_to_docker.sh fixtures/dev_dummy_superuser.json
 
    ./fixture_to_docker.sh fixtures/????_*.json
 
    popd
 
else
 
    echo Now creating a Django superuser. Please enter a
 
    docker exec -it symposion ./manage.py createsuperuser --username admin1 --email root@example.com
 
fi
 

	
 
set +x
 
echo "Now you can log into http://localhost:28000/admin"
 
echo "Username: admin1      Password: the one you just typed twice"
 
echo "If you need to test as a non-admin user, create one at"
 
echo "http://localhost:28000/admin/auth/user/add/ - then log out"
 
echo "and log back in at http://localhost:28000"
pinaxcon/proposals/admin.py
Show inline comments
...
 
@@ -2,50 +2,44 @@ from django.contrib import admin
 

	
 
from pinaxcon.proposals import models
 
from symposion.proposals import models as symposion_models
 
from symposion.reviews.models import ProposalResult
 

	
 
class CategoryAdmin(admin.ModelAdmin):
 

	
 
    class AdditionalSpeakerInline(admin.TabularInline):
 
        model = symposion_models.AdditionalSpeaker
 

	
 
    class ProposalResultInline(admin.TabularInline):
 
        model = ProposalResult
 
        readonly_fields = ["score"]
 
        fields = ["status"]
 

	
 
    inlines = [
 
        AdditionalSpeakerInline,
 
        ProposalResultInline,
 
    ]
 

	
 

	
 
models_to_register = [
 
    models.TalkProposal,
 
    models.TutorialProposal,
 
    models.MiniconfProposal,
 
    ### LCA2022 Miniconfs
 
    models.GlamCommunityProposal,
 
    models.KernelProposal,
 
    models.OpenHardwareProposal,
 
    models.SysAdminProposal,
 
]
 

	
 
for model in models_to_register:
 
    admin.site.register(model, CategoryAdmin,
 
                        list_display = [
 
                            "id",
 
                            "title",
 
                            "speaker",
 
                            "speaker_email",
 
                            "kind",
 
                            "target_audience",
 
                            "status",
 
                            "cancelled",
 
                        ],
 
                        list_filter = [
 
                            "result__status",
 
                            "cancelled",
 
                        ],
 
    )
 

	
pinaxcon/proposals/forms.py
Show inline comments
 
import copy
 

	
 
from django import forms
 

	
 
from pinaxcon.proposals.fields import HelpTextField
 
from pinaxcon.proposals import models
 

	
 

	
 
DEFAULT_FIELDS =  [
 
    "title",
 
    "primary_topic",
 
    "target_audience",
 
    "experience_level",
 
    "abstract",
 
    "private_abstract",
 
    "content_warning",
 
    "technical_requirements",
 
    "project",
 
    "project_url",
 
    "video_url",
 
    "require_approval",
 
    "recording_release",
 
    "materials_release",
 
]
 

	
 
MINICONF_SESSION_FORMAT_FIELDS = copy.copy(DEFAULT_FIELDS)
 

	
 
class ProposalForm(forms.ModelForm):
 

	
 
    required_css_class = 'label-required'
 

	
 
    def clean_description(self):
 
        value = self.cleaned_data["description"]
 
        if len(value) > 400:
 
            raise forms.ValidationError(
 
                u"The description must be less than 400 characters"
 
            )
 
        return value
 

	
 

	
 
class TalkProposalForm(ProposalForm):
 

	
 
    class Meta:
 
        model = models.TalkProposal
 
        fields = copy.copy(DEFAULT_FIELDS)
 

	
 

	
 
class TutorialProposalForm(ProposalForm):
 

	
 
    class Meta:
 
        model = models.TutorialProposal
 
        fields = copy.copy(DEFAULT_FIELDS)
 

	
 

	
 
class MiniconfProposalForm(ProposalForm):
 

	
 
    class Meta:
 
        model = models.MiniconfProposal
 
        fields = [
 
            "title",
 
            "abstract",
 
            "private_abstract",
 
            "technical_requirements",
 
            "recording_release",
 
            "materials_release",
 
        ]
 

	
 
### LCA2022 Miniconfs
 

	
 
class MiniconfSessionProposalForm(ProposalForm):
 
    pass
 

	
 

	
 
class GlamCommunityProposalForm(MiniconfSessionProposalForm):
 

	
 
    class Meta:
 
        model = models.GlamCommunityProposal
 
        fields = MINICONF_SESSION_FORMAT_FIELDS
 

	
 

	
 
class KernelProposalForm(MiniconfSessionProposalForm):
 

	
 
    class Meta:
 
        model = models.KernelProposal
 
        fields = MINICONF_SESSION_FORMAT_FIELDS
 

	
 

	
 
HARDWARE_FIELDS = copy.copy(MINICONF_SESSION_FORMAT_FIELDS)
 
HARDWARE_FIELDS.insert(4, "talk_format")
 

	
 
class OpenHardwareProposalForm(MiniconfSessionProposalForm):
 

	
 
    def __init__(self, *a, **k):
 
        super(OpenHardwareProposalForm, self).__init__(*a, **k)
 
        self.fields['talk_format'].required = True
 

	
 
    class Meta:
 
        model = models.OpenHardwareProposal
 
        fields = HARDWARE_FIELDS
 

	
 

	
 
class SysAdminProposalForm(MiniconfSessionProposalForm):
 

	
 
    class Meta:
 
        model = models.SysAdminProposal
 
        fields = MINICONF_SESSION_FORMAT_FIELDS
pinaxcon/proposals/migrations/0004_auto_20210809_2026.py
Show inline comments
 
deleted file
pinaxcon/proposals/migrations/0004_auto_20221208_0102.py
Show inline comments
 
new file 100644
 
# Generated by Django 2.2.28 on 2022-12-07 14:02
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('symposion_schedule', '0008_auto_20190122_0815'),
 
        ('symposion_reviews', '0001_initial'),
 
        ('symposion_proposals', '0003_auto_20170702_2250'),
 
        ('proposals', '0003_auto_20170702_2227'),
 
    ]
 

	
 
    operations = [
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='content_warning',
 
            field=models.TextField(blank=True, help_text='This will be shown on the schedule to give attendees advanced warning of topics covered in the session. ', verbose_name='Content Warning'),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='content_warning_html',
 
            field=models.TextField(blank=True),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='experience_level',
 
            field=models.IntegerField(choices=[(1, 'Beginner'), (2, 'Intermediate'), (3, 'Advanced')], help_text='What level of experience will your session be pitched at?'),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='primary_topic',
 
            field=models.IntegerField(choices=[(1, 'Linux'), (2, 'Software'), (3, 'Hardware'), (4, 'Firmware'), (5, 'System Administration / Operations'), (6, 'Security'), (7, 'Documentation'), (8, 'Community'), (9, 'Science & Data'), (10, 'Galleries, Libraries, Archives & Museums (GLAM)'), (11, 'Multimedia'), (12, 'Aerospace / UAV'), (13, 'Agriculture'), (14, 'Other')], help_text='What is the primary topic area for your session?'),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='require_approval',
 
            field=models.BooleanField(default=False, help_text='Do you require further approval from your employer or institution before you can confirm your availability to present?'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='content_warning',
 
            field=models.TextField(blank=True, help_text='This will be shown on the schedule to give attendees advanced warning of topics covered in the session. ', verbose_name='Content Warning'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='content_warning_html',
 
            field=models.TextField(blank=True),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='experience_level',
 
            field=models.IntegerField(choices=[(1, 'Beginner'), (2, 'Intermediate'), (3, 'Advanced')], help_text='What level of experience will your session be pitched at?'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='primary_topic',
 
            field=models.IntegerField(choices=[(1, 'Linux'), (2, 'Software'), (3, 'Hardware'), (4, 'Firmware'), (5, 'System Administration / Operations'), (6, 'Security'), (7, 'Documentation'), (8, 'Community'), (9, 'Science & Data'), (10, 'Galleries, Libraries, Archives & Museums (GLAM)'), (11, 'Multimedia'), (12, 'Aerospace / UAV'), (13, 'Agriculture'), (14, 'Other')], help_text='What is the primary topic area for your session?'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='require_approval',
 
            field=models.BooleanField(default=False, help_text='Do you require further approval from your employer or institution before you can confirm your availability to present?'),
 
        ),
 
        migrations.AlterField(
 
            model_name='talkproposal',
 
            name='recording_release',
 
            field=models.BooleanField(default=True, help_text="I allow Linux Australia to release any recordings of presentations covered by this proposal, on YouTube under the standard YouTube licence, and on other platforms under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (<a href='https://creativecommons.org/licenses/by-nc-sa/4.0/'> CC BY-NC-SA 4.0</a>) licence."),
 
        ),
 
        migrations.AlterField(
 
            model_name='talkproposal',
 
            name='target_audience',
 
            field=models.IntegerField(choices=[(4, 'Developer'), (3, 'Community'), (1, 'End User'), (2, 'Business')], help_text='Who is the target audience for your session?'),
 
        ),
 
        migrations.AlterField(
 
            model_name='tutorialproposal',
 
            name='recording_release',
 
            field=models.BooleanField(default=True, help_text="I allow Linux Australia to release any recordings of presentations covered by this proposal, on YouTube under the standard YouTube licence, and on other platforms under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (<a href='https://creativecommons.org/licenses/by-nc-sa/4.0/'> CC BY-NC-SA 4.0</a>) licence."),
 
        ),
 
        migrations.AlterField(
 
            model_name='tutorialproposal',
 
            name='target_audience',
 
            field=models.IntegerField(choices=[(4, 'Developer'), (3, 'Community'), (1, 'End User'), (2, 'Business')], help_text='Who is the target audience for your session?'),
 
        ),
 
        migrations.DeleteModel(
 
            name='MiniconfProposal',
 
        ),
 
    ]
pinaxcon/proposals/models.py
Show inline comments
 
from django.db import models
 
from django.utils.translation import ugettext_lazy as _
 

	
 
from symposion.proposals.models import ProposalBase
 
from symposion.text_parser import parse
 

	
 

	
 
class Proposal(ProposalBase):
 

	
 
    TARGET_USER = 1
 
    TARGET_BUSINESS = 2
 
    TARGET_COMMUNITY = 3
 
    TARGET_DEVELOPER = 4
 

	
 
    TARGET_AUDIENCES = [
 
        (TARGET_DEVELOPER, "Developer"),
 
        (TARGET_COMMUNITY, "Community"),
 
        (TARGET_USER, "End User"),
 
        (TARGET_BUSINESS, "Business"),
 
    ]
 

	
 
    TOPIC_LINUX = 1
 
    TOPIC_SOFTWARE = 2
 
    TOPIC_HARDWARE = 3
 
    TOPIC_FIRMWARE = 4
 
    TOPIC_SYSADMIN = 5
 
    TOPIC_SECURITY = 6
 
    TOPIC_DOCUMENTATION = 7
 
    TOPIC_COMMUNITY = 8
 
    TOPIC_SCIENCE = 9
 
    TOPIC_GLAM = 10
 
    TOPIC_MULTIMEDIA = 11
 
    TOPIC_AEROSPACE = 12
 
    TOPIC_AGRICULTURE = 13
 
    TOPIC_OTHER = 14
 

	
 
    PROPOSAL_TOPIC = [
 
        (TOPIC_LINUX, "Linux"),
 
        (TOPIC_SOFTWARE, "Software"),
 
        (TOPIC_HARDWARE, "Hardware"),
 
        (TOPIC_FIRMWARE, "Firmware"),
 
        (TOPIC_SYSADMIN, "System Administration / Operations"),
 
        (TOPIC_SECURITY, "Security"),
 
        (TOPIC_DOCUMENTATION, "Documentation"),
 
        (TOPIC_COMMUNITY, "Community"),
 
        (TOPIC_SCIENCE, "Science & Data"),
 
        (TOPIC_GLAM, "Galleries, Libraries, Archives & Museums (GLAM)"),
 
        (TOPIC_MULTIMEDIA, "Multimedia"),
 
        (TOPIC_AEROSPACE, "Aerospace / UAV"),
 
        (TOPIC_AGRICULTURE, "Agriculture"),
 
        (TOPIC_OTHER, "Other"),
 
    ]
 

	
 
    LEVEL_BEGINNER = 1
 
    LEVEL_INTERMEDIATE = 2
 
    LEVEL_ADVANCED = 3
 

	
 
    EXPERIENCE_LEVEL = [
 
        (LEVEL_BEGINNER, "Beginner"),
 
        (LEVEL_INTERMEDIATE, "Intermediate"),
 
        (LEVEL_ADVANCED, "Advanced"),
 
    ]
 

	
 
    target_audience = models.IntegerField(
 
        choices=TARGET_AUDIENCES,
 
        help_text="Who is the target audience for your session?",
 
    )
 

	
 
    recording_release = models.BooleanField(
 
        default=True,
 
        help_text="I allow Linux Australia to release any recordings of "
 
        "presentations covered by this proposal, on YouTube under the "
 
        "standard YouTube licence, and on other platforms under the "
 
        "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
 
        "(<a href='https://creativecommons.org/licenses/by-nc-sa/4.0/'> "
 
        "CC BY-NC-SA 4.0</a>) licence."
 
    )
 

	
 
    materials_release = models.BooleanField(
 
        default=True,
 
        help_text="I allow Linux Australia to release any other material "
 
        "(such as slides) from presentations covered by this proposal, under "
 
        "the <a "
 
        "href='https://creativecommons.org/licenses/by-sa/3.0/au/deed.en'> "
 
        "Creative Commons Attribution-Share Alike Australia 3.0 Licence</a>"
 
    )
 

	
 
    class Meta:
 
        abstract = True
 

	
 

	
 
class SessionProposal(Proposal):
 
    """
 
    Base Session Proposal
 

	
 
    This is not a meta class as we want a single table to store the common
 
    data across all session proposal types.
 
    """
 

	
 
    TOPIC_SOFTWARE = 1
 
    TOPIC_HARDWARE = 2
 
    TOPIC_FIRMWARE = 3
 
    TOPIC_KERNEL = 4
 
    TOPIC_DOCUMENTATION = 5
 
    TOPIC_COMMUNITY = 6
 
    TOPIC_SECURITY = 7
 
    TOPIC_OPERATIONS = 8
 
    TOPIC_OTHER = 9
 

	
 
    PROPOSAL_TOPIC = [
 
        (TOPIC_SOFTWARE, "Software"),
 
        (TOPIC_HARDWARE, "Hardware"),
 
        (TOPIC_FIRMWARE, "Firmware"),
 
        (TOPIC_KERNEL, "Linux Kernel"),
 
        (TOPIC_DOCUMENTATION, "Documentation"),
 
        (TOPIC_COMMUNITY, "Community"),
 
        (TOPIC_SECURITY, "Security"),
 
        (TOPIC_OPERATIONS, "Deployment & Operations"),
 
        (TOPIC_OTHER, "Other"),
 
    ]
 

	
 
    LEVEL_BEGINNER = 1
 
    LEVEL_INTERMEDIATE = 2
 
    LEVEL_ADVANCED = 3
 

	
 
    EXPERIENCE_LEVEL = [
 
        (LEVEL_BEGINNER, "Beginner"),
 
        (LEVEL_INTERMEDIATE, "Intermediate"),
 
        (LEVEL_ADVANCED, "Advanced"),
 
    ]
 

	
 
    primary_topic = models.IntegerField(
 
        choices=PROPOSAL_TOPIC,
 
        help_text="What is the primary topic area for your session?"
 
    )
 

	
 
    experience_level = models.IntegerField(
 
        choices=EXPERIENCE_LEVEL,
 
        help_text="What level of experience will your session be pitched at?"
 
    )
 

	
 
    require_approval = models.BooleanField(
 
        default=False,
 
        help_text="Do you require further approval from your employer or "
 
        "institution before you can confirm your availability to present?"
 
    )
 

	
 

	
 
class TalkProposal(SessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "talk proposal"
 

	
 

	
 
class TutorialProposal(SessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "tutorial proposal"
 

	
 

	
 
class MiniconfProposal(Proposal):
 
    """
 
    Miniconf Proposal
 

	
 
    Note that this is just a Proposal, not a SessionProposal, as it does not
 
    require a number of fields that the others use.
 
    """
 

	
 
    target_audience = models.IntegerField(choices=Proposal.TARGET_AUDIENCES,
 
                                          default=Proposal.TARGET_DEVELOPER)
 

	
 
    class Meta:
 
        verbose_name = "miniconf proposal"
 

	
 

	
 
class MiniconfSessionProposal(SessionProposal):
 
    """
 
    Base Miniconf Session Proposal
 
    """
 
    content_warning = models.TextField(
 
        "Content Warning",
 
        help_text=_("This will be shown on the schedule to give attendees "
 
                    "advanced warning of topics covered in the session. "),
 
        blank=True,
 
    )
 
    content_warning_html = models.TextField(blank=True)
 

	
 
    class Meta:
 
        abstract = True
 

	
 
    def save(self, *args, **kwargs):
 
        self.content_warning_html = parse(self.content_warning)
 
        return super(Proposal, self).save(*args, **kwargs)
 

	
 
class GlamCommunityProposal(MiniconfSessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "GO GLAM Miniconf Proposal"
 

	
 

	
 
class KernelProposal(MiniconfSessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "Kernel Miniconf Proposal"
 

	
 

	
 
class OpenHardwareProposal(MiniconfSessionProposal):
 

	
 
    FORMAT_PRESENTATION = 1
 
    FORMAT_TUTORIAL = 2
 
    FORMAT_HANDS_ON = 3
 

	
 
    TALK_FORMATS = [
 
        (FORMAT_PRESENTATION, "Presentation"),
 
        (FORMAT_TUTORIAL, "Tutorial"),
 
        (FORMAT_HANDS_ON, "Hands-on"),
 
    ]
 

	
 
    talk_format = models.IntegerField(
 
        choices=TALK_FORMATS,
 
        default=FORMAT_PRESENTATION,
 
        help_text="Will your session be a presentation, tutorial or hands-on "
 
        "(e.g how to use KiCAD or some other tooling)?"
 
    )
 
class TalkProposal(Proposal):
 

	
 
    class Meta:
 
        verbose_name = "Open Hardware Miniconf Proposal"
 
        verbose_name = "talk proposal"
 

	
 

	
 
class SysAdminProposal(MiniconfSessionProposal):
 
class TutorialProposal(Proposal):
 

	
 
    class Meta:
 
        verbose_name = "System Administration Miniconf Proposal"
 
        verbose_name = "tutorial proposal"
pinaxcon/registrasion/forms.py
Show inline comments
...
 
@@ -4,33 +4,34 @@ from django import forms
 

	
 

	
 
class YesNoField(forms.TypedChoiceField):
 

	
 
    def __init__(self, *args, **kwargs):
 
        kwargs['required'] = True
 
        super(YesNoField, self).__init__(
 
            *args,
 
            coerce=lambda x: x in ['True', 'Yes', True],
 
            choices=((None, '--------'), (False, 'No'), (True, 'Yes')),
 
            **kwargs
 
        )
 

	
 

	
 
class ProfileForm(forms.ModelForm):
 
    ''' A form for requesting badge and profile information. '''
 

	
 
    required_css_class = 'label-required'
 

	
 
    class Meta:
 
        model = models.AttendeeProfile
 
        exclude = [
 
            'attendee',
 
            'children',
 
            'lca_announce',
 
            'lca_chat',
 
            'future_conference',
 
        ]
 
        widgets = {
 
            'past_lca': forms.widgets.CheckboxSelectMultiple
 
        }
 
        field_classes = {
 
            "of_legal_age": YesNoField,
 
        }
pinaxcon/registrasion/management/commands/populate_inventory.py
Show inline comments
...
 
@@ -106,49 +106,49 @@ class Command(BaseCommand):
 
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
        #     limit_per_user=1,
 
        #     order=30,
 
        # )
 
        # self.pdns_category = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Professional Delegates Networking Session Ticket",
 
        #     description="Tickets to our Professional Delegates Networking session. "
 
        #                 "This event will be held on the evening of "
 
        #                 f"{settings.PDNS_TICKET_DATE: %A %d %B} "
 
        #                 "and is restricted to Professional Ticket "
 
        #                 "holders, speakers, miniconf organisers, and invited "
 
        #                 "guests.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
 
        #     limit_per_user=1,
 
        #     order=40,
 
        # )
 
        # self.t_shirt = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Shirt",
 
        #     description="Commemorative conference shirts, featuring the "
 
        #                 f"linux.conf.au {settings.LCA_START.year} artwork. "
 
        #                 f"linux.conf.au {settings.CONF_START.year} artwork. "
 
        #                 "View the <a href=\"/attend/shirts/\">"
 
        #                 "sizing guide</a>.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_ITEM_QUANTITY,
 
        #     order=50,
 
        # )
 
        # self.accommodation = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Accommodation at University of Tasmania",
 
        #     description="Accommodation at the University of Tasmania colleges "
 
        #                 "and apartments. You can come back and book your "
 
        #                 "accommodation at a later date, provided rooms remain "
 
        #                 "available. Rooms may only be booked from Sunday 15 "
 
        #                 "January--Saturday 21 January. If you wish to stay "
 
        #                 "for only a part of the 6-day period, you must book "
 
        #                 "accommodation for the full 6-day period. Rooms at "
 
        #                 "other hotels, including Wrest Point can be booked "
 
        #                 "elsewhere. For full details, see [LINK]our "
 
        #                 "accommodation page.[/LINK]",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
 
        #     limit_per_user=1,
 
        #     order=50,
pinaxcon/registrasion/migrations/0001_initial.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
# Generated by Django 1.9.7 on 2016-09-22 06:25
 
from __future__ import unicode_literals
 

	
 
from django.db import migrations, models
 
import django.db.models.deletion
 
import django_countries.fields
 

	
 

	
 
_PAST_EVENTS = (
 
    (1999, "1999 Melbourne (CALU)"),
 
    (2001, "2001 Sydney"),
 
    (2002, "2002 Brisbane"),
 
    (2003, "2003 Perth"),
 
    (2004, "2004 Adelaide"),
 
    (2005, "2005 Canberra"),
 
    (2006, "2006 Dunedin"),
 
    (2007, "2007 Sydney"),
 
    (2008, "2008 Melbourne"),
 
    (2009, "2009 Hobart"),
 
    (2010, "2010 Wellington"),
 
    (2011, "2011 Brisbane"),
 
    (2012, "2012 Ballarat"),
 
    (2013, "2013 Canberra"),
 
    (2014, "2014 Perth"),
 
    (2015, "2015 Auckland"),
 
    (2016, "2016 Geelong"),
 
    (2017, "2017 Hobart"),
 
    (2018, "2018 Sydney"),
 
    (2019, "2019 Christchurch"),
 
    (2020, "2020 Gold Coast"),
 
    (2021, "2021 Online"),
 
    (1999, "CALU 1999 Melbourne"),
 
    (2001, "LCA2001 Sydney"),
 
    (2002, "LCA2002 Brisbane"),
 
    (2003, "LCA2003 Perth"),
 
    (2004, "LCA2004 Adelaide"),
 
    (2005, "LCA2005 Canberra"),
 
    (2006, "LCA2006 Dunedin"),
 
    (2007, "LCA2007 Sydney"),
 
    (2008, "LCA2008 Melbourne"),
 
    (2009, "LCA2009 Hobart"),
 
    (2010, "LCA2010 Wellington"),
 
    (2011, "LCA2011 Brisbane"),
 
    (2012, "LCA2012 Ballarat"),
 
    (2013, "LCA2013 Canberra"),
 
    (2014, "LCA2014 Perth"),
 
    (2015, "LCA2015 Auckland"),
 
    (2016, "LCA2016 Geelong"),
 
    (2017, "LCA2017 Hobart"),
 
    (2018, "LCA2018 Sydney"),
 
    (2019, "LCA2019 Christchurch"),
 
    (2020, "LCA2020 Gold Coast"),
 
    (2021, "LCA2021 Online"),
 
    (2022, "LCA2022 Online"),
 
)
 

	
 

	
 
def populate(apps, schema_editor):
 
    PastEvent = apps.get_model("pinaxcon_registrasion","PastEvent")
 

	
 
    all_such = PastEvent.objects.all()
 
    by_year = dict((event.year, event) for event in all_such)
 

	
 
    events = []
 
    for past_event in _PAST_EVENTS:
 
        if past_event[0] in by_year:
 
            continue
 
        events.append(PastEvent(
 
            year=past_event[0],
 
            name=past_event[1],
 
        ))
 

	
 
    PastEvent.objects.bulk_create(events)
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    initial = True
pinaxcon/registrasion/migrations/0015_auto_20221208_0102.py
Show inline comments
 
new file 100644
 
# Generated by Django 2.2.28 on 2022-12-07 14:02
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('pinaxcon_registrasion', '0014_auto_20201123_2319'),
 
    ]
 

	
 
    operations = [
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='address_line_1',
 
            field=models.CharField(blank=True, help_text='This address, if provided, will appear on your invoices. It is also where we will ship your Open Hardware Kit if you are allocated one.', max_length=1024, verbose_name='Address line 1'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='children',
 
            field=models.CharField(blank=True, help_text="Everything Open is a family friendly conference and provides free child-care for pre-school children from 6 months up to 5 years. We hope to also provide a programme for older children and will let you know closer to the conference. If you're wanting to bring your children, please let us know their age(s) so we can ensure we have enough spaces available.", max_length=256, verbose_name='Child Ages and Information'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='lca_chat',
 
            field=models.BooleanField(blank=True, default=False, help_text='lca-chat is a high-traffic mailing list used by attendees during the week of the conference for general discussion.', verbose_name='Subscribe to the chat mailing list'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='of_legal_age',
 
            field=models.BooleanField(blank=True, help_text='Being under 18 will not stop you from attending the conference. We need to know whether you are over 18 to allow us to cater for you at venues that serve alcohol.', verbose_name='Are you over 18?'),
 
        ),
 
        migrations.AlterField(
 
            model_name='attendeeprofile',
 
            name='past_lca',
 
            field=models.ManyToManyField(blank=True, to='pinaxcon_registrasion.PastEvent', verbose_name='Which past events have you attended?'),
 
        ),
 
    ]
pinaxcon/registrasion/models.py
Show inline comments
...
 
@@ -152,78 +152,78 @@ class AttendeeProfile(rego.AttendeeProfileBase):
 
                  "conference. We need to know whether you are over 18 to "
 
                  "allow us to cater for you at venues that serve alcohol.",
 
        blank=True,
 
    )
 
    dietary_restrictions = models.CharField(
 
        verbose_name="Food allergies, intolerances, or dietary restrictions",
 
        max_length=256,
 
        blank=True,
 
    )
 
    accessibility_requirements = models.CharField(
 
        verbose_name="Accessibility-related requirements",
 
        max_length=256,
 
        blank=True,
 
    )
 
    gender = models.CharField(
 
        verbose_name="Gender",
 
        help_text="Gender data will only be used for demographic purposes.",
 
        max_length=64,
 
        blank=True,
 
    )
 

	
 
    children = models.CharField(
 
        verbose_name="Child Ages and Information",
 
        max_length=256,
 
        help_text="Linux.conf.au is a family friendly conference and provides "
 
        help_text="Everything Open is a family friendly conference and provides "
 
            "free child-care for pre-school children from 6 months up to 5 years. We "
 
            "hope to also provide a programme for older children and will let you "
 
            "know closer to the conference. If you're wanting to bring your children "
 
            "to LCA, please let us know their age(s) so we can ensure we have "
 
            "know closer to the conference. If you're wanting to bring your children, "
 
            "please let us know their age(s) so we can ensure we have "
 
            "enough spaces available.",
 
        blank=True
 
    )
 

	
 
    linux_australia = models.BooleanField(
 
        verbose_name="Linux Australia membership",
 
        help_text="Select this field to register for free "
 
                  "<a href='http://www.linux.org.au/'>Linux Australia</a> "
 
                  "membership.",
 
        blank=True,
 
    )
 

	
 
    lca_announce = models.BooleanField(
 
        verbose_name="Subscribe to lca-announce list",
 
        help_text="Select to be subscribed to the low-traffic lca-announce "
 
                  "mailing list",
 
        blank=True,
 
    )
 

	
 
    lca_chat = models.BooleanField(
 
        verbose_name="Subscribe to the LCA chat list",
 
        verbose_name="Subscribe to the chat mailing list",
 
        help_text="lca-chat is a high-traffic mailing list used by "
 
                  "attendees during the week of the conference for general "
 
                  "discussion.",
 
        blank=True,
 
        default=False,
 
    )
 

	
 
    future_conference = models.BooleanField(
 
        verbose_name = "Reuse my login for future Linux Australia conferences?",
 
        help_text="Select to have your login details made available to future "
 
                  "Linux Australia conferences who share the same Single Sign "
 
                  "On system.",
 
        blank=True,
 
        default=False,
 
    )
 

	
 
    past_lca = models.ManyToManyField(
 
        PastEvent,
 
        verbose_name="Which past linux.conf.au events have you attended?",
 
        verbose_name="Which past events have you attended?",
 
        blank=True,
 
    )
 

	
 
    def first_name(self):
 
        return wrap(self.name, 15, break_long_words=False)[0]
 

	
 
    def last_name(self):
 
        names = wrap(self.name, 15, break_long_words=False)
 
        return names[1] if len(names) > 1 else ''
pinaxcon/settings.py
Show inline comments
...
 
@@ -342,56 +342,50 @@ LOGGING = {
 
        },
 
    },
 
    'root': {
 
        'handlers': ['console', 'djdt_log'],
 
        'level': 'DEBUG'
 
    },
 
}
 
FIXTURE_DIRS = [
 
    os.path.join(PROJECT_ROOT, "fixtures"),
 
]
 

	
 
AUTHENTICATION_BACKENDS = [
 
    'symposion.teams.backends.TeamPermissionsBackend',
 
    'django.contrib.auth.backends.ModelBackend',
 
    'djangosaml2.backends.Saml2Backend',
 
]
 

	
 
LOGIN_URL = '/saml2/login/'
 
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
 

	
 
CONFERENCE_ID = 1
 
PROPOSAL_FORMS = {
 
    "talk": "pinaxcon.proposals.forms.TalkProposalForm",
 
    "tutorial": "pinaxcon.proposals.forms.TutorialProposalForm",
 
    "miniconf": "pinaxcon.proposals.forms.MiniconfProposalForm",
 
    ### LCA2022 Miniconfs
 
    "glam-community-miniconf": "pinaxcon.proposals.forms.GlamCommunityProposalForm",
 
    "kernel-miniconf": "pinaxcon.proposals.forms.KernelProposalForm",
 
    "open-hardware-miniconf": "pinaxcon.proposals.forms.OpenHardwareProposalForm",
 
    "sysadmin-miniconf": "pinaxcon.proposals.forms.SysAdminProposalForm",
 
}
 
MAIN_CONFERENCE_PROPOSAL_KINDS = ("Talk", "Miniconf")
 
MAIN_CONFERENCE_PROPOSAL_KINDS = ("Talk",)
 

	
 
# Registrasion bits:
 
ATTENDEE_PROFILE_MODEL = "pinaxcon.registrasion.models.AttendeeProfile"
 
ATTENDEE_PROFILE_FORM = "pinaxcon.registrasion.forms.ProfileForm"
 
INVOICE_CURRENCY = "AUD"
 
GST_RATE =  Decimal('0.1')
 
TICKET_PRODUCT_CATEGORY = 1
 
TERMS_PRODUCT_CATEGORY = 2
 
ATTENDEE_PROFILE_FORM = "pinaxcon.registrasion.forms.ProfileForm"
 

	
 
#REGIDESK
 
REGIDESK_BOARDING_GROUP = "Ready For Boarding"
 

	
 
# CSRF custom error screen
 
CSRF_FAILURE_VIEW = "pinaxcon.csrf_view.csrf_failure"
 

	
 
# Use nose to run all tests
 
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
 

	
 
# Tell nose to measure coverage on the 'foo' and 'bar' apps
 
NOSE_ARGS = [
 
    '--with-coverage',
 
    '--cover-package=registrasion.controllers,registrasion.models',
 
]
...
 
@@ -434,49 +428,49 @@ SAML_CONFIG = {
 
    'metadata': saml2_idp_metadata,
 
    'debug': 0,
 
    'key_file': saml2_signing_key,
 
    'cert_file': saml2_signing_crt,
 
    'encryption_keypairs': [{
 
        'key_file': saml2_encr_key,
 
        'cert_file': saml2_encr_crt,
 
    }],
 
    'contact_person': saml2_contact,
 
    'valid_for': 10,
 
}
 

	
 
if 'SAML_CONFIG_LOADER' in os.environ:
 
    SAML_CONFIG_LOADER = os.environ.get('SAML_CONFIG_LOADER')
 

	
 
DEFAULT_FILE_STORAGE = os.environ.get('DEFAULT_FILE_STORAGE', 'gapc_storage.storage.GoogleCloudStorage')
 
GAPC_STORAGE = {
 
    'num_retries': 2,
 
}
 

	
 
SETTINGS_EXPORT = [
 
    'DEBUG',
 
    'ANALYTICS_KEY',
 
    'TIME_ZONE',
 
    'LCA_START',
 
    'CONF_START',
 
    'CONFERENCE_EMAIL',
 
]
 

	
 
if DEV_MODE and DEV_MODE == "LAPTOP":
 
    print("ENABLING LAPTOP MODE")
 
    from .devmode_settings import *
 

	
 

	
 
class Category(object):
 
    tickets = []
 

	
 
    @classmethod
 
    def order(cls, ticket) -> int:
 
        return (cls.tickets.index(ticket) + 1) * 10
 

	
 

	
 
@dataclass(frozen=True)
 
class Ticket:
 
    name: str
 
    regular_price: Decimal
 
    earlybird_price: Decimal
 

	
 
    def earlybird_discount(self):
 
        return self.regular_price - self.earlybird_price
...
 
@@ -497,59 +491,59 @@ class DinnerTicket:
 
class PenguinDinnerTicket(DinnerTicket):
 
    pass
 

	
 

	
 
class SpeakersDinnerTicket(DinnerTicket):
 
    pass
 

	
 

	
 
class SpeakersDinnerCat(Category):
 
    @classmethod
 
    def create(cls, name: str, price: Decimal, description: str, reservation: timedelta) -> SpeakersDinnerTicket:
 
        t = SpeakersDinnerTicket(name, price, description, reservation, cls)
 
        cls.tickets.append(t)
 
        return t
 

	
 

	
 
class PenguinDinnerCat(Category):
 
    @classmethod
 
    def create(cls, name: str, price: Decimal, description: str, reservation: timedelta) -> PenguinDinnerTicket:
 
        t = PenguinDinnerTicket(name, price, description, reservation, cls)
 
        cls.tickets.append(t)
 
        return t
 

	
 

	
 
CONFERENCE_NAME = os.environ.get('CONFERENCE_NAME', 'linux.conf.au')
 
CONFERENCE_NAME_SHORT = os.environ.get('CONFERENCE_NAME_SHORT', 'LCA')
 
CONFERENCE_NAME = os.environ.get('CONFERENCE_NAME', 'Everything Open')
 
CONFERENCE_NAME_SHORT = os.environ.get('CONFERENCE_NAME_SHORT', 'EO')
 
CONFERENCE_EMAIL = os.environ.get('CONFERENCE_EMAIL', DEFAULT_FROM_EMAIL)
 
LCA_TZINFO = pytz.timezone(TIME_ZONE)
 
LCA_START = LCA_TZINFO.localize(datetime(2022, 1, 14))
 
LCA_END = LCA_TZINFO.localize(datetime(2022, 1, 16))
 
LCA_MINICONF_END = LCA_TZINFO.localize(datetime(2022, 1, 14, 23, 59))
 
EARLY_BIRD_DEADLINE = LCA_TZINFO.localize(datetime(2022, 12, 1))
 
PENGUIN_DINNER_TICKET_DATE = date(2022, 1, 14)
 
SPEAKER_DINNER_TICKET_DATE = date(2022, 1, 15)
 
PDNS_TICKET_DATE = date(2022, 1, 16)
 
CONF_TZINFO = pytz.timezone(TIME_ZONE)
 
CONF_START = CONF_TZINFO.localize(datetime(2023, 3, 14))
 
CONF_END = CONF_TZINFO.localize(datetime(2023, 3, 16))
 
CONF_MINICONF_END = CONF_TZINFO.localize(datetime(2023, 3, 14, 23, 59))
 
EARLY_BIRD_DEADLINE = CONF_TZINFO.localize(datetime(2023, 1, 28))
 
PENGUIN_DINNER_TICKET_DATE = date(2023, 3, 15)
 
SPEAKER_DINNER_TICKET_DATE = date(2023, 3, 14)
 
PDNS_TICKET_DATE = date(2023, 3, 16)
 

	
 
TSHIRT_PRICE = Decimal("25.00")
 

	
 
CONTRIBUTOR = Ticket("Contributor", Decimal("300.00"), Decimal("250.00"))
 
PROFESSIONAL = Ticket("Professional", Decimal("125.00"), Decimal("100.00"))
 
HOBBYIST = Ticket("Hobbyist", Decimal("70.00"), None)
 
STUDENT = Ticket("Student", Decimal("30.00"), None)
 
MINICONF_ONLY = Ticket("Miniconf Only", Decimal("25.00"), None)
 

	
 
MEDIA = Ticket("Media", Decimal("0.0"), None)
 
SPEAKER = Ticket("Speaker", Decimal("0.0"), None)
 
SPONSOR = Ticket("Sponsor", Decimal("0.0"), None)
 

	
 
CONFERENCE_ORG = Ticket("Conference Organiser", Decimal("0.0"), None)
 
CONFERENCE_VOL = Ticket("Conference Volunteer", Decimal("0.0"), None)
 

	
 
PENGUIN_DINNER = PenguinDinnerCat
 
PENGUIN_DINNER_ADULT = PenguinDinnerCat.create(
 
    "Adult", Decimal("95.00"),
 
    "Includes an adult's meal and full beverage service.",
 
    timedelta(hours=1))
 
PENGUIN_DINNER_CHILD = PenguinDinnerCat.create(
 
    "Child", Decimal("50.00"),
 
    "Children 14 and under. "
pinaxcon/templates/nav.html
Show inline comments
 
{% load sitetree %}
 
{% load static %}
 

	
 
<nav class="navbar navbar-expand-lg navbar-light bg-blaze">
 
<nav class="navbar navbar-expand-lg navbar-light bg-dawn-sea">
 
  <div class="container">
 
    <a class="navbar-brand" href="/">
 
      <img src="{% static 'lca/lca2022.svg' %}" alt="linux.conf.au 2022 logo" height="56px">
 
      <img src="{% static 'img/eo2023.svg' %}" alt="Everything Open 2023 logo" height="56px">
 
    </a>
 

	
 
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
 
      <span class="navbar-toggler-icon"></span>
 
    </button>
 

	
 
    {% sitetree_menu from "main" include "trunk" template "sitetree_header.html" %}
 
  </div>
 
</nav>
pinaxcon/templates/registrasion/badge.svg
Show inline comments
...
 
@@ -76,49 +76,49 @@
 
        <path d="M137.47,361.4a1.5,1.5,0,0,1,.53,1.22,1.48,1.48,0,0,1-.53,1.2,2.2,2.2,0,0,1-1.45.44h-1.4v1.6h-.35V361H136A2.2,2.2,0,0,1,137.47,361.4Zm-.25,2.2a1.39,1.39,0,0,0,0-2,1.84,1.84,0,0,0-1.2-.34h-1.4v2.65H136A1.9,1.9,0,0,0,137.22,363.6Z" fill="#231f20"/>
 
        <path d="M142.15,364.12H139a1.47,1.47,0,0,0,.22.76,1.35,1.35,0,0,0,.55.51,1.55,1.55,0,0,0,.78.19,1.76,1.76,0,0,0,.66-.13,1.48,1.48,0,0,0,.51-.38l.2.23a1.67,1.67,0,0,1-.6.44,2,2,0,0,1-.78.15,1.94,1.94,0,0,1-1-.24,1.61,1.61,0,0,1-.67-.65,1.93,1.93,0,0,1-.24-1,1.9,1.9,0,0,1,.23-1,1.71,1.71,0,0,1,.62-.66,1.73,1.73,0,0,1,.9-.24,1.67,1.67,0,0,1,.89.24,1.62,1.62,0,0,1,.62.65,1.88,1.88,0,0,1,.23.95Zm-2.42-1.46a1.44,1.44,0,0,0-.5.48,1.68,1.68,0,0,0-.21.71h2.8a1.6,1.6,0,0,0-.21-.7,1.38,1.38,0,0,0-.5-.49,1.44,1.44,0,0,0-.69-.17A1.41,1.41,0,0,0,139.73,362.66Z" fill="#231f20"/>
 
        <path d="M146.12,362.58a1.59,1.59,0,0,1,.4,1.15v2.13h-.35v-2.1a1.29,1.29,0,0,0-.32-.94,1.13,1.13,0,0,0-.87-.32,1.31,1.31,0,0,0-1,.38,1.42,1.42,0,0,0-.37,1v1.94h-.35v-3.65h.33V363a1.38,1.38,0,0,1,.57-.6,1.67,1.67,0,0,1,.88-.22A1.46,1.46,0,0,1,146.12,362.58Z" fill="#231f20"/>
 
        <path d="M151.25,362.21v3.26a1.8,1.8,0,0,1-.44,1.35,1.85,1.85,0,0,1-1.33.43,3,3,0,0,1-.95-.15,1.94,1.94,0,0,1-.72-.43l.19-.27a1.81,1.81,0,0,0,.66.39,2.21,2.21,0,0,0,.82.14,1.46,1.46,0,0,0,1.07-.34,1.43,1.43,0,0,0,.35-1.08v-.61a1.52,1.52,0,0,1-.62.61,1.79,1.79,0,0,1-.9.22,1.87,1.87,0,0,1-.92-.23,1.67,1.67,0,0,1-.66-.63,1.78,1.78,0,0,1-.24-.92,1.74,1.74,0,0,1,.24-.91,1.54,1.54,0,0,1,.66-.63,1.87,1.87,0,0,1,.92-.23,1.84,1.84,0,0,1,.91.23,1.42,1.42,0,0,1,.63.63v-.83Zm-1.07,3a1.35,1.35,0,0,0,.54-.52,1.6,1.6,0,0,0,0-1.51,1.42,1.42,0,0,0-.54-.52,1.62,1.62,0,0,0-.77-.18,1.58,1.58,0,0,0-.76.18,1.42,1.42,0,0,0-.54.52,1.6,1.6,0,0,0,0,1.51,1.35,1.35,0,0,0,.54.52,1.59,1.59,0,0,0,.76.19A1.63,1.63,0,0,0,150.18,365.23Z" fill="#231f20"/>
 
        <path d="M155.94,362.21v3.65h-.34v-.78a1.31,1.31,0,0,1-.54.6,1.64,1.64,0,0,1-.84.21,1.39,1.39,0,0,1-1.52-1.55v-2.13h.35v2.11a1.26,1.26,0,0,0,.31.93,1.18,1.18,0,0,0,.89.33,1.27,1.27,0,0,0,1-.39,1.45,1.45,0,0,0,.36-1v-2Z" fill="#231f20"/>
 
        <path d="M157.39,361.24a.29.29,0,0,1,0-.4.29.29,0,0,1,.21-.09.32.32,0,0,1,.2.08.3.3,0,0,1,.08.2.32.32,0,0,1-.08.21.32.32,0,0,1-.2.08A.32.32,0,0,1,157.39,361.24Zm0,1h.35v3.65h-.35Z" fill="#231f20"/>
 
        <path d="M162.12,362.58a1.59,1.59,0,0,1,.4,1.15v2.13h-.35v-2.1a1.33,1.33,0,0,0-.31-.94,1.15,1.15,0,0,0-.88-.32,1.32,1.32,0,0,0-1,.38,1.42,1.42,0,0,0-.37,1v1.94h-.35v-3.65h.33V363a1.38,1.38,0,0,1,.57-.6,1.67,1.67,0,0,1,.88-.22A1.46,1.46,0,0,1,162.12,362.58Z" fill="#231f20"/>
 
        <path d="M166.13,365.71a1.91,1.91,0,0,1-.76-.48l.16-.26a2,2,0,0,0,.7.44,2.39,2.39,0,0,0,.92.17,1.75,1.75,0,0,0,1.06-.26.82.82,0,0,0,.35-.7.75.75,0,0,0-.18-.52,1.35,1.35,0,0,0-.47-.3,7.75,7.75,0,0,0-.76-.22,6.12,6.12,0,0,1-.86-.26,1.29,1.29,0,0,1-.56-.39,1,1,0,0,1-.22-.7,1.2,1.2,0,0,1,.18-.65,1.33,1.33,0,0,1,.58-.48,2.48,2.48,0,0,1,1-.17,2.72,2.72,0,0,1,.8.12,2.25,2.25,0,0,1,.68.32l-.14.29a2.11,2.11,0,0,0-.64-.31,2.49,2.49,0,0,0-.7-.11,1.62,1.62,0,0,0-1,.28.85.85,0,0,0-.35.7.76.76,0,0,0,.19.53,1.27,1.27,0,0,0,.47.3,7.75,7.75,0,0,0,.76.22,7.84,7.84,0,0,1,.86.26,1.43,1.43,0,0,1,.55.38,1,1,0,0,1,.23.69,1.13,1.13,0,0,1-.19.65,1.28,1.28,0,0,1-.59.47,2.42,2.42,0,0,1-1,.18A2.77,2.77,0,0,1,166.13,365.71Z" fill="#231f20"/>
 
        <path d="M172.78,362.42a1.79,1.79,0,0,1,.65.66,2.12,2.12,0,0,1,0,1.92,1.79,1.79,0,0,1-.65.66,1.91,1.91,0,0,1-.93.23,1.62,1.62,0,0,1-.87-.23,1.54,1.54,0,0,1-.61-.63v2.19H170v-5h.34v.86a1.53,1.53,0,0,1,.61-.65,1.66,1.66,0,0,1,.88-.24A1.81,1.81,0,0,1,172.78,362.42Zm-.19,3a1.4,1.4,0,0,0,.53-.55,1.76,1.76,0,0,0,0-1.59,1.4,1.4,0,0,0-.53-.55,1.48,1.48,0,0,0-.76-.19,1.44,1.44,0,0,0-.75.19,1.32,1.32,0,0,0-.52.55,1.68,1.68,0,0,0,0,1.59,1.32,1.32,0,0,0,.52.55,1.45,1.45,0,0,0,.75.2A1.49,1.49,0,0,0,172.59,365.38Z" fill="#231f20"/>
 
        <path d="M175.24,365.65a1.68,1.68,0,0,1-.66-.66,2.1,2.1,0,0,1,0-1.91,1.74,1.74,0,0,1,.66-.66,1.94,1.94,0,0,1,1.87,0,1.79,1.79,0,0,1,.65.66,2,2,0,0,1,0,1.91,1.72,1.72,0,0,1-.65.66,1.94,1.94,0,0,1-1.87,0Zm1.69-.27a1.38,1.38,0,0,0,.52-.55,1.76,1.76,0,0,0,0-1.59,1.38,1.38,0,0,0-.52-.55,1.51,1.51,0,0,0-.76-.19,1.44,1.44,0,0,0-.75.19,1.32,1.32,0,0,0-.52.55,1.68,1.68,0,0,0,0,1.59,1.32,1.32,0,0,0,.52.55,1.45,1.45,0,0,0,.75.2A1.51,1.51,0,0,0,176.93,365.38Z" fill="#231f20"/>
 
        <path d="M182,362.58a1.59,1.59,0,0,1,.39,1.15v2.13H182v-2.1a1.29,1.29,0,0,0-.31-.94,1.14,1.14,0,0,0-.87-.32,1.31,1.31,0,0,0-1,.38,1.43,1.43,0,0,0-.38,1v1.94h-.35v-3.65h.34V363a1.36,1.36,0,0,1,.56-.6,1.7,1.7,0,0,1,.89-.22A1.46,1.46,0,0,1,182,362.58Z" fill="#231f20"/>
 
        <path d="M183.88,365.76a1.65,1.65,0,0,1-.62-.34l.16-.28a1.87,1.87,0,0,0,.58.32,2.24,2.24,0,0,0,.73.12,1.49,1.49,0,0,0,.82-.18.59.59,0,0,0,.26-.5.5.5,0,0,0-.14-.37.83.83,0,0,0-.36-.19,4.52,4.52,0,0,0-.58-.14,5,5,0,0,1-.7-.16,1.11,1.11,0,0,1-.45-.3.76.76,0,0,1-.19-.56.88.88,0,0,1,.36-.72,1.68,1.68,0,0,1,1-.28,2.35,2.35,0,0,1,.69.1,1.62,1.62,0,0,1,.56.26l-.16.28a1.73,1.73,0,0,0-.51-.25,2.33,2.33,0,0,0-.59-.08,1.27,1.27,0,0,0-.77.19.58.58,0,0,0-.26.49.5.5,0,0,0,.15.39.79.79,0,0,0,.36.2c.14,0,.34.09.6.14a7,7,0,0,1,.69.17,1.07,1.07,0,0,1,.44.28.77.77,0,0,1,.18.54.84.84,0,0,1-.38.73,1.79,1.79,0,0,1-1.06.27A2.63,2.63,0,0,1,183.88,365.76Z" fill="#231f20"/>
 
        <path d="M187.63,365.65A1.72,1.72,0,0,1,187,365a2,2,0,0,1,0-1.91,1.79,1.79,0,0,1,.65-.66,1.85,1.85,0,0,1,.94-.24,1.79,1.79,0,0,1,.93.24,1.74,1.74,0,0,1,.66.66,2,2,0,0,1,0,1.91,1.68,1.68,0,0,1-.66.66,1.79,1.79,0,0,1-.93.24A1.85,1.85,0,0,1,187.63,365.65Zm1.69-.27a1.4,1.4,0,0,0,.53-.55,1.76,1.76,0,0,0,0-1.59,1.4,1.4,0,0,0-.53-.55,1.58,1.58,0,0,0-1.5,0,1.34,1.34,0,0,0-.53.55,1.76,1.76,0,0,0,0,1.59,1.34,1.34,0,0,0,.53.55,1.51,1.51,0,0,0,1.5,0Z" fill="#231f20"/>
 
        <path d="M192.34,362.39a1.7,1.7,0,0,1,.87-.21v.34h-.08a1.21,1.21,0,0,0-1,.38,1.57,1.57,0,0,0-.34,1.06v1.9h-.35v-3.65h.34v.8A1.27,1.27,0,0,1,192.34,362.39Z" fill="#231f20"/>
 
        <path d="M194.29,365.76a1.73,1.73,0,0,1-.62-.34l.16-.28a1.87,1.87,0,0,0,.58.32,2.3,2.3,0,0,0,.74.12,1.43,1.43,0,0,0,.81-.18.57.57,0,0,0,.27-.5.47.47,0,0,0-.15-.37.79.79,0,0,0-.35-.19,4.52,4.52,0,0,0-.58-.14,5,5,0,0,1-.7-.16,1.08,1.08,0,0,1-.46-.3.81.81,0,0,1-.19-.56.86.86,0,0,1,.37-.72,1.67,1.67,0,0,1,1-.28,2.3,2.3,0,0,1,.69.1,1.53,1.53,0,0,1,.56.26l-.16.28a1.73,1.73,0,0,0-.51-.25,2.33,2.33,0,0,0-.59-.08,1.29,1.29,0,0,0-.77.19.58.58,0,0,0-.26.49.5.5,0,0,0,.15.39.91.91,0,0,0,.36.2c.14,0,.34.09.6.14a6.32,6.32,0,0,1,.69.17,1.07,1.07,0,0,1,.44.28.73.73,0,0,1,.19.54.87.87,0,0,1-.38.73,1.82,1.82,0,0,1-1.07.27A2.63,2.63,0,0,1,194.29,365.76Z" fill="#231f20"/>
 
        <rect y="317.34" width="297.64" height="37.27" fill="#00b1c5"/>
 
        <path d="M175.69,399.54a13.12,13.12,0,1,1,0-26.24,12.52,12.52,0,0,1,9,3.61l-2.53,2.53a9.12,9.12,0,0,0-6.46-2.56,9.54,9.54,0,0,0,0,19.07,8.75,8.75,0,0,0,6.62-2.62,7.47,7.47,0,0,0,2-4.51H176v-3.59h11.8a11.5,11.5,0,0,1,.2,2.24,11.85,11.85,0,0,1-3.11,8.39A12,12,0,0,1,175.69,399.54Z" fill="#557ebf"/>
 
        <path d="M206.9,391.1a8.45,8.45,0,1,1-8.45-8.45A8.34,8.34,0,0,1,206.9,391.1Zm-3.7,0a4.77,4.77,0,1,0-4.75,5.12A4.86,4.86,0,0,0,203.2,391.1Z" fill="#ea4535"/>
 
        <path d="M225.9,391.09a8.45,8.45,0,1,1-8.45-8.45A8.34,8.34,0,0,1,225.9,391.09Zm-3.7,0a4.77,4.77,0,1,0-4.75,5.12A4.86,4.86,0,0,0,222.2,391.09Z" fill="#f9bc15"/>
 
        <path d="M244,383.15v15.17c0,6.24-3.68,8.8-8,8.8a8,8,0,0,1-7.48-5l3.23-1.35a4.66,4.66,0,0,0,4.25,3c2.79,0,4.52-1.73,4.52-5v-1.21h-.13a5.77,5.77,0,0,1-4.45,1.92,8.47,8.47,0,0,1,0-16.9,5.86,5.86,0,0,1,4.45,1.89h.13v-1.38Zm-3.27,8c0-3-2-5.15-4.51-5.15s-4.51,2.18-4.51,5.15,2,5.09,4.51,5.09S240.68,394.07,240.68,391.12Z" fill="#557ebf"/>
 
        <path d="M250.66,374.21V399H247V374.21Z" fill="#36a852"/>
 
        <path d="M265.49,393.87l2.88,1.92a8.4,8.4,0,0,1-7,3.75,8.26,8.26,0,0,1-8.38-8.45c0-5,3.61-8.45,8-8.45s6.53,3.49,7.23,5.38l.39,1-11.3,4.67a4.3,4.3,0,0,0,4.1,2.56A4.82,4.82,0,0,0,265.49,393.87Zm-8.87-3,7.56-3.13a3.28,3.28,0,0,0-3.14-1.79A4.63,4.63,0,0,0,256.62,390.83Z" fill="#ea4535"/>
 
        <rect x="160.95" y="373.04" width="112" height="36" fill="none"/>
 
        <text transform="translate(84.43 102.23)" font-size="15" fill="#231f20" font-family="SourceSansPro-Regular, Source Sans Pro">Janua<tspan x="38.69" y="0" letter-spacing="0.02em">r</tspan>
 
            <tspan x="44.26" y="0">y 14 - 16 2022</tspan>
 
            <tspan x="44.26" y="0">y 14 - 16 2023</tspan>
 
        </text>
 
        <g id="Layer_2" data-name="Layer 2">
 
            <g id="emperor">
 
                <path d="M256.88,261.71a24.47,24.47,0,0,0,.69,2.7c.18.24,1.25,4.65,1.31,4.83s1.27,3.41,1.33,3.65.75,2.64.86,3.3.7,4.07.7,4.73.05,2.4.05,2.64v3.59a29.61,29.61,0,0,1-.11,3.65,28.94,28.94,0,0,1-.75,4,11.44,11.44,0,0,1-1.22,3.36c-.33.61-.63,1.2-.92,1.2a7.23,7.23,0,0,1-2-2.34c.34-2.76,1.55-4.62,1.84-8.51a85.54,85.54,0,0,0,0-8.63c-.15-2.46-1.14-12.94-1.32-13.3a15.43,15.43,0,0,1-.58-1.74A10.23,10.23,0,0,1,256.88,261.71Z" fill="#d2d3d4"/>
 
                <path d="M258.3,257.3s-.75,2.93-.75,3.42-.52.82-.23,2,1.15,4.32,1.38,5.1c.1.34.49,1.43.93,2.72.58,1.66,1.26,3.65,1.55,4.77.52,2,1.28,11.51.81,14.44s-1.55,9.18-2,10.08-.92,1-1.45.66a3.9,3.9,0,0,1-1.1-1.62,10.69,10.69,0,0,0-.75-1.32,10.24,10.24,0,0,0,.4-1.44c.12-.66.06.3.64,1.26s1.1,1.8,1.5,1.08a11.51,11.51,0,0,0,1.68-4.32c.06-1.56.87-3.78.81-6.65s-.23-8.21-.46-9.41a46.4,46.4,0,0,0-1.22-5.16c-.29-.53-2.26-7.6-2.42-8a9,9,0,0,1-.76-2.87c.12-.6,1-3.59,1-3.9A3.31,3.31,0,0,1,258.3,257.3Z" fill="#231f20"/>
 
                <path d="M246.39,245.73a33.05,33.05,0,0,1,4.59-.36c.44.18,2.69,1.62,2.69,1.62s2.69,2.87,2.86,4,.7,8.81.78,9.08a26.09,26.09,0,0,1-.43,2.6,13.09,13.09,0,0,0,0,2c.09.72.78,4.31.86,4.76s.61,3.87.7,4.31.35,3.87.35,4.23.34,3.59.34,3.86v4.77c0,.27-.52,4.41-.6,5.12s-1.82,6.11-1.74,6.38-2.69,6.2-2.69,6.83-1.55,2.6-2,3.05A24.68,24.68,0,0,1,247.6,310a16.91,16.91,0,0,1-4.33.54c-.61,0-7.73-.45-8.23-.45s-1.91-1-2.17-1.08-1-1.09-1.31-1.18a9.16,9.16,0,0,1-1.91-1.88,21.34,21.34,0,0,1-.61-2.07c-.17-.63-.69-4.14-.78-4.59s-.43-3.23-.6-3.77.17-6.29-.09-7.28,1.91-8.53,2.08-9.34,3.64-8.72,3.47-10.25.87-11.59.95-12.58,2.34-4.58,3.12-5.3S244.22,246.09,246.39,245.73Z" fill="#fff"/>
 
                <path d="M254.8,249.32s-2-2.33-1.48-1.7-1.47-.81-1.47-.81-.52.36-.6.09-.27.28-.44.63-.6-.63-.6-.63l-.44.62-.69-.43-.35,1.08-.69-.54.43,1.08h-.95l.61.62-1.22-.17.35,1.07-.87-.35.09.71-.78-.19.34.81h-.69l.26.39.27.42-.69-.28.61.81-.61-.09-.61-.28-1-1.78.86-3.14,2.69-1.71,2.88-.09,2,.27,2.69,2.34Z" fill="#6e6f72"/>
 
                <g clip-path="url(#clip-path)">
 
                    <g clip-path="url(#clip-path-2)">
 
                        <image width="111" height="129" transform="translate(243.01 246.45) scale(0.13)" xlink:href="data:image/png;base64,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" style="isolation:isolate"/>
 
                    </g>
 
                </g>
 
                <path d="M228.52,288.06a34.68,34.68,0,0,0-.4,6.17c.23,1.86.4,4.25.46,4.67s.06,2,.12,2.58a27.83,27.83,0,0,0,.63,3.36,6.45,6.45,0,0,0,2,2.7,9.68,9.68,0,0,1,1.12.91c.49.45.78.79,1,.82l2,.44a3.13,3.13,0,0,1-1.8-.07,18.61,18.61,0,0,1-4-3.42c-.58-.9-1.11-4.26-1.22-5.16s-1.33-4.91-1.45-5.93a23.74,23.74,0,0,1-.11-4C227,290.53,227.77,289.91,228.52,288.06Z" fill="#231f20"/>
 
                <path d="M253.79,277.25c0,.14.39.28.61,0a11.94,11.94,0,0,0,1.3-3.55,16,16,0,0,0-.35-5.76,12.17,12.17,0,0,1-.17-3.19c.08-.45,2-3.91,2.25-4.45a16.2,16.2,0,0,0,.87-3.06c0-.12,0-.33.05-.61a9.72,9.72,0,0,0-.44-3.75,22.49,22.49,0,0,0-2.56-4.76c-.35-.35-1.56-1.22-1.86-1.62a5.3,5.3,0,0,0-2.74-1.35,4.8,4.8,0,0,0-1.6.09c-.3.05-.52,0,1.46.48a6,6,0,0,1,3.93,3.19,13,13,0,0,1,.59,2.9c.13.63.1,3.93-1.89,5.64a4.53,4.53,0,0,1-2.52,1.53c-.55,0-2-1.24-2.65-1.29-.36,0-.65.18-.83.72a2.77,2.77,0,0,0,.35,1.8c.09.17.25.58.41,1,.09.24.18.49.28.71.27.5-.83.16-1.68-.46a7,7,0,0,1-1.56-1.89,3.76,3.76,0,0,0,1.6,2.34,12.88,12.88,0,0,1,3.86,3.42,31.08,31.08,0,0,1,2.91,5.08,6.5,6.5,0,0,1,.65,1.84,10.9,10.9,0,0,1,0,2C254.05,275,253.88,276.08,253.79,277.25Z" fill="#231f20"/>
 
                <path d="M251.7,264.58s1.66,2.48,1.86,3a15.91,15.91,0,0,1,1.22,3.28,9.51,9.51,0,0,1,0,3.1c-.24,1.14-.35.95-.35.95a11.46,11.46,0,0,0-.43-3.78c-.48-1.44-1.3-2.88-1.57-3.55S251.32,264.53,251.7,264.58Z" fill="#f15b2b"/>
 
                <path d="M251.92,262c.08-.14.09-.45.4-.22s.55.36.6.76,0,.68-.13.77-.69-.18-.82-.32A1.51,1.51,0,0,1,251.92,262Z" fill="#595a5c"/>
 
                <path d="M252.36,262.28a.83.83,0,0,1,.26.36c0,.18,0,.45-.09.41a.66.66,0,0,1-.39-.36,2.28,2.28,0,0,1,0-.45S252.27,262.15,252.36,262.28Z" fill="#231f20"/>
 
                <path d="M251.94,245.62s.31.52-.51.36a7.47,7.47,0,0,0-3.65.12,2.87,2.87,0,0,0-1.73,2.64c-.12,1.68-1,1.38-1.5,2.34-.24.48,1.1,3.17,1.1,3.17s-2.78-3.06-5.73-2.51c-.94.17-3.18,1.55-4.63,5.33-.57,1.48-1.1,8.51-1.1,9.11s-.35,5.63-1.33,8c-.24.55-3,9.1-3.7,11.75s-2.55,8.62-2.9,9.35a15,15,0,0,1-1.61,3.11c-.46.36.23,1-.47.36s-.81-2.88-.69-3.72.7-4.31.81-5-.34-2.87,0-4.67.06-5.27,1-8.45c1.37-4.5,4.1-6,5-9.35a94.93,94.93,0,0,0,1.56-9.71,20.9,20.9,0,0,1,4.16-8.57c1.85-2.28,3.35-4.2,5.09-4.44a14,14,0,0,1,4-.06c.92.12,2.6.12,3.75.18A5.4,5.4,0,0,1,251.94,245.62Z" fill="#424143"/>
 
                <path d="M244.6,254.91c.35.36,1,1.5,1.56,1.26.69-.32-.28-1.74-.7-2.34a6.55,6.55,0,0,0-2-1.68c-.46-.17-2.37-1-3.41-.59a6.12,6.12,0,0,0-2.83,1.73,9.6,9.6,0,0,0-2.32,3.54,30.41,30.41,0,0,0-.86,5.93c0,1.14-.28,5-.37,5.8s-.55,4.63-.55,4.87a15.79,15.79,0,0,0,1.22-4c.18-1.31.34-3.66.4-5a30.14,30.14,0,0,1,.64-5.27,9.39,9.39,0,0,1,1.85-4.26c1.27-1.38,1.89-1.66,2.54-1.74a5.16,5.16,0,0,1,3.18.6A4.26,4.26,0,0,1,244.6,254.91Z" fill="#231f20"/>
 
                <path d="M253.16,306.82s.25-.21,1.27.24a2.94,2.94,0,0,1,1.79,1.43,16.66,16.66,0,0,1,.58,1.68,15,15,0,0,1,.27,1.74c0,.6-.3,1.38-.4,1.08s-.29-.78-.64-.9c-.62-.21-.57-.72-.86-1s.17.24-.06,1-.35.66-.58.9-.35.6-.75.66-.17-.12-.12-.66-.34-1.93-.34-1.26a2.9,2.9,0,0,1-.64,1.08,1.18,1.18,0,0,1-.92.36s-.41.66-.76.72,0-.06-.17-.83.12-1.2-.52-1.68.58,0-.63,0-3.13-.18-3.36-.77,3.36-.72,4.57-1.74,2.25-2.1,2.25-2.1" fill="#424143"/>
 
                <path d="M256.83,264.75c.31,2.71,1.18,5.37,1.47,8.1.32,3,.55,6,.7,9a35.82,35.82,0,0,1-.55,9.81,83.21,83.21,0,0,1-3.57,11.12c-.8,2.05-1.49,3.91-3.42,5.14a15.76,15.76,0,0,1-8.45,2.25,1.27,1.27,0,0,0,0,.67,16.07,16.07,0,0,0,8.09-2c1.91-1.11,2.65-2.56,3.46-4.53a75.82,75.82,0,0,0,3.76-11.38,32.86,32.86,0,0,0,.85-8.95c-.13-3.14-.21-6.28-.57-9.4-.17-1.46-.31-2.92-.55-4.37-.34-2-.94-4-1.17-5.95,0-.26-.06.38-.05.48Z" fill="#231f20"/>
 
                <path d="M232.78,308.9c-.55-.29-.35,1.26.72,2.23a5.42,5.42,0,0,0,3.24,1.2,2.71,2.71,0,0,1,1.79.6c.58.36,1.21.3,1.33.66s.63-.66.35-1.14-.35-.78-.53-.84.64,1,1.11,1.26,1.15.55,1.38.42.63-.48.86,0,.41-.12.38-.51a.55.55,0,0,0-.14-.33,9.24,9.24,0,0,1-.87-.9,10.69,10.69,0,0,1,2,1.2c.18.3.29-.6.18-1.08s-.53-.71-.87-1-1-1.43-1.74-1.67-1.38-.09-1.67-.24a5.26,5.26,0,0,0-4.11.24A3.3,3.3,0,0,1,232.78,308.9Z" fill="#424143"/>
 
                <path d="M240,312.21a4.18,4.18,0,0,0-.55-1,2.32,2.32,0,0,0-.78-.48l-.67-.12c-.05,0-.27-.06-.4-.09a.49.49,0,0,1-.35-.36,1,1,0,0,0,.55.24,4.57,4.57,0,0,1,1.33.28A2,2,0,0,1,240,312.21Z" fill="#231f20"/>
 
                <path d="M240,309.78l.67.23.32.07c.34.06,1.07.14,1.21.57a6.12,6.12,0,0,0,.35.93c-.44-.39-.35-.66-.55-.83a2.89,2.89,0,0,0-1.13-.45C240.52,310.19,240.15,309.84,240,309.78Z" fill="#231f20"/>
pinaxcon/templates/site_base.html
Show inline comments
 
{% load static %}
 
{% load i18n %}
 
{% load sitetree %}
 
{% load sass_tags %}
 
{% load capture_tags %}
 

	
 
{% capture as head_title silent %}{% block head_title_base %}{% if SITE_NAME %}{{ SITE_NAME }} | {% endif %}{% block head_title %}{% endblock %}{% endblock %}{% endcapture %}
 

	
 
<!DOCTYPE html>
 

	
 
<html lang="en">
 
<head>
 
  <meta charset="utf-8">
 
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
 
  <meta name="description" content="">
 
  <meta name="viewport" content="width=device-width, initial-scale=1">
 

	
 
  <title>{{ head_title }}</title>
 

	
 
  <meta property="og:type" content="website" />
 

	
 
  <!-- Cards -->
 
  <meta property="og:title" content="{{ head_title }}">
 
  <meta property="og:description" content="linux.conf.au 2022 - Jan 14-16 2022, Online, Worldwide" />
 
  <meta property="og:description" content="Everything Open 2023 - March 14-16 2023, Melbourne, Australia" />
 
  <meta property="og:url" content="{{ request.scheme }}://{{ request.get_host }}{{ request.path }}">
 
  <meta name="twitter:site" content="@linuxconfau">
 
  <meta name="twitter:site" content="@_everythingopen">
 
  <meta name="twitter:image:alt" content="{{ head_title }}" />
 
  <meta name="twitter:card" content="summary">
 
  <meta name="twitter:image" content="{{ request.scheme }}://{{ request.get_host }}/media/img/card/lca_badge.1ef714c1.png" />
 
  <meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}/media/img/card/lca_badge.1ef714c1.png" />
 
  <meta name="twitter:image" content="{{ request.scheme }}://{{ request.get_host }}/media/img/card/eo-badge.ba30d338.png" />
 
  <meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}/media/img/card/eo-badge.ba30d338.png" />
 
  <meta property="og:image:width" content="400" />
 
  <meta property="og:image:height" content="400" />
 

	
 
  {% block styles %}
 
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
 
  <link href="{% sass_src 'scss/app.scss' %}" rel="stylesheet" type="text/css" />
 
  {% block extra_style %}{% endblock %}
 
  {% endblock %}
 

	
 
  {% block extra_head_base %}
 
  {% block extra_head %}{% endblock %}
 
  {% endblock %}
 

	
 
  <script type="text/javascript">
 
    var CONF_TZ = "{{ settings.TIME_ZONE }}";
 
  </script>
 
</head>
 
<body class="{% block body_class %}{% endblock %}">
 
  {% block template_overrides %}{% endblock %}
 
  <header class="clearfix d-print-none">
 
    {% block alert %}{% endblock %}
 
    {% block navbar %}{% include 'nav.html' %}{% endblock %}
 
  </header>
 

	
...
 
@@ -100,49 +100,54 @@
 
    <script>
 
      window.dataLayer = window.dataLayer || [];
 
      function gtag(){dataLayer.push(arguments);}
 
      gtag('js', new Date());
 
      gtag('config', '{{ settings.ANALYTICS_KEY }}');
 
    </script>
 
    {% else %}
 
    <!--no-analytics-->
 
    {% endif %}
 
    {% block extra_script %}
 
    {% endblock %}
 
    {% block scripts_extra %}{% endblock %}
 
    {% endblock %}
 

	
 
    {% block extra_body_base %}
 
    {% block extra_body %}
 
    {% endblock %}
 
    {% endblock %}
 
  </main>
 

	
 
  <footer class="footer mt-4 d-print-none">
 
    <div class="container py-4">
 
      <div class="row">
 
        <div class="col-md-4 pb-4">
 
          <strong>linux.conf.au 2022</strong> <br>
 
          Jan 14-16 2022 <br>
 
          Online, Worldwide <br>
 
          <a href="mailto:{{ settings.CONFERENCE_EMAIL }}" alt="Email"><i class="far fa-envelope"></i></a>&nbsp;&nbsp;
 
          <a href="https://twitter.com/linuxconfau" alt="Twitter"><i class="fab fa-twitter"></i></a>&nbsp;&nbsp;
 
          <a href="https://www.facebook.com/linuxconferenceaustralia/" alt="Facebook"><i class="fab fa-facebook"></i></a>
 
          <strong>Everything Open 2023</strong> <br>
 
          March 14-16 2023 <br>
 
          Naarm (Melbourne), Australia <br>
 
          Timezone: AEDT - UTC+11 <br>
 
          <a href="mailto:contact@everythingopen.au" alt="Email"><i class="bi-envelope-fill"></i></a>&nbsp;&nbsp;<a
 
            href="https://twitter.com/_everythingopen" alt="Twitter"><i class="bi-twitter"></i></a>&nbsp;&nbsp;<a
 
            href="https://www.linkedin.com/showcase/everythingopen/" alt="LinkedIn"><i class="bi-linkedin"></i></a>
 

	
 
          <a href="mailto:{{ settings.CONFERENCE_EMAIL }}" alt="Email"><i class="far fa-envelope"></i></a>&nbsp;&nbsp;<a
 
            href="https://twitter.com/_everythingopen" alt="Twitter"><i class="fab fa-twitter"></i></a>&nbsp;&nbsp;<a
 
            href="https://www.facebook.com/linuxconferenceaustralia/" alt="Facebook"><i class="fab fa-facebook"></i></a>&nbsp;&nbsp;<a
 
            href="https://www.linkedin.com/showcase/everythingopen/" alt="LinkedIn"><i class="fab fa-linkedin"></i></a>
 
        </div>
 
        <div class="col-md-4 pb-4 text-center">
 
          <img src="{% static 'lca/lca_horiz_colour.svg' %}" alt="linux.conf.au logo" class="footer-logo">
 
          <a href="https://linux.org.au"><img src="{% static 'lca/la_logo.svg' %}" alt="Linux Australia logo" class="footer-image"></a>
 
          <a href="https://linux.org.au"><img src="{% static 'img/la_logo.svg' %}" alt="Linux Australia logo" class="footer-image"></a>
 
        </div>
 
        <div class="col-md-4 pb-4 text-right">
 
          <small>
 
            <a href="#">Back to top</a><br>
 
            &copy; 2021 linux.conf.au and <a href="http://linux.org.au/">Linux Australia</a><br>
 
            &copy; 2022 Everything Open and <a href="http://linux.org.au/">Linux Australia</a><br>
 
            Linux is a registered trademark of Linus Torvalds <br>
 
            <a href="/colophon/">Colophon</a>
 
          </small>
 
        </div>
 
      </div>
 
    </div>
 
  </footer>
 

	
 
</body>
 
</html>
pinaxcon/templates/symposion/dashboard/_categories.html
Show inline comments
...
 
@@ -51,49 +51,49 @@
 
      <p>The conference is now open. Please join us to watch talks and interact with the other delegates.</p>
 
      <div>
 
        <a class="btn btn-lg btn-primary" role="button" href="{% venueless_login_url %}">Launch Conference</a>
 
      </div>
 
    </div>
 
  </div>
 
  {% endif %}
 
  {% endflag %}
 

	
 
  <div class="row">
 
    <div class="col-md-6 mb-3 mb-md-0">
 
      <h3>Attendee Profile</h3>
 
      <p>If you would like to change the details on your badge or your attendee statistics, you may edit your attendee profile here.</p>
 
      <div>
 
        <a class="btn btn-primary" role="button" href="{% url "attendee_edit" %}">Edit attendee profile</a>
 
        {% flag "badge_preview" %}
 
        <a class="btn btn-info" role="button" href="{% url "user_badge" %}">Preview my badge</a>
 
        {% endflag %}
 
      </div>
 
    </div>
 
    <div class="col-md-6 mb-3 mb-md-0">
 
      <h3>Account Management</h3>
 
      <p>If you would like to change your registered email address or password, you can use our self-service account management portal</p>
 
      <div>
 
        <a class="btn btn-primary" role="button" href="https://login.linux.conf.au/manage/">Account Management</a>
 
        <a class="btn btn-primary" role="button" href="https://login.everythingopen.au/manage/">Account Management</a>
 
      </div>
 
    </div>
 
  </div>
 

	
 
  {% items_pending as pending %}
 
  <div class="row">
 
    <div class="col-12">
 
      <h3 class="my-3">Account</h3>
 
    </div>
 
  </div>
 

	
 
  <div class="row">
 
    {% if pending %}
 
    <div class="col-md-6 mb-3">
 
      <h4>Items pending payment</h4>
 
      {% include "registrasion/_items_list.html" with items=pending %}
 
      <a class="btn btn-primary" role="button" href="{% url "checkout" %}"><i class="fa fa-credit-card"></i> Check out and pay</a>
 
      <a class="btn btn-secondary" role="button" href="{% url "voucher_code" %}">Apply voucher</a>
 
    </div>
 
    {% endif %}
 

	
 
    {% items_purchased as purchased %}
 
    {% if purchased %}
 
    <div class="col-md-6 mb-3">
pinaxcon/templates/symposion/proposals/_proposal_fields.html
Show inline comments
...
 
@@ -90,48 +90,59 @@
 
        </tr>
 
        {% endfor %}
 
      </tbody>
 
    </table>
 
  </div>
 
</div>
 
{% endif %}
 

	
 
<div class="row">
 
  <label class="list-label col-md-2">Abstract</label>
 
  <div class="col-md-10">
 
    <div class="abstract monospace-text">{{ proposal.abstract_html|safe }}&nbsp;</div>
 
    <p></p>
 
  </div>
 
</div>
 

	
 
<div class="row">
 
  <label class="list-label col-md-2">Private Abstract</label>
 
  <div class="col-md-10">
 
    <div class="private_abstract monospace-text">{{ proposal.private_abstract_html|safe }}&nbsp;</div>
 
    <p></p>
 
  </div>
 
</div>
 

	
 
<div class="row">
 
  <label class="list-label col-md-2">Content Warning</label>
 
  <div class="col-md-10">
 
    {% if proposal.content_warning_html %}
 
    <div class="content_warning monospace-text">{{ proposal.content_warning_html|safe }}</div>
 
    {% else %}
 
    <div class="content_warning monospace-text"><b>No Content Warning Provided</b></div>
 
    {% endif %}
 
  </div>
 
</div>
 

	
 
<div class="row">
 
  <label class="list-label col-md-2">Project</label>
 
  <div class="col-md-10">
 
    {% if proposal.project %}
 
    <p>{{ proposal.project|safe }}&nbsp;</p>
 
    {% else %}
 
    <p><b>None Provided</b></p>
 
    {% endif %}
 
  </div>
 
</div>
 

	
 
<div class="row">
 
  <label class="list-label col-md-2">Project URL</label>
 
  <div class="col-md-10">
 
    {% if proposal.project_url %}
 
    <p><a href="{{ proposal.project_url|safe }}">{{ proposal.project_url|safe }}</a>&nbsp;</p>
 
    {% else %}
 
    <p><b>None Provided</b></p>
 
    {% endif %}
 
  </div>
 
</div>
 

	
 
<div class="row">
 
  <label class="list-label col-md-2">Video URL</label>
pinaxcon/templates/symposion/schedule/schedule_conference.html
Show inline comments
...
 
@@ -25,49 +25,49 @@
 
    <div class="col">
 
      <ul class="nav nav-pills flex-column flex-md-row" id="schedule-tabs" role="tablist">
 
        {% for section in sections %}
 
        {% for timetable in section.days %}
 
          <li class="nav-item flex-md-fill text-md-center">
 
            {% include "symposion/schedule/_schedule_nav_link.html" with active=forloop.first label=timetable.day.date|date:"l" date=timetable.day.date|date:"Y-m-d" %}
 
          </li>
 
        {% endfor %}
 
      {% endfor %}
 
      </ul>
 
    </div>
 
  </div>
 

	
 
  <div class="tab-content d-print-block my-3" id="schedule-tabContent">
 
    {% for section in sections %}
 
      {% cache 600 "schedule-table" section.schedule.section %}
 
      {% for timetable in section.days %}
 
      <div class="row tab-pane fade {% if forloop.first %}show active{% endif %} d-print-block" id="{{ timetable.day.date|date:"l"|lower}}" role="tabpanel" aria-labelledby="schedule_day_{{ timetable.day.date|date:"l"|lower}}-tab">
 
        <div class="col-12">
 
          <h2 class="my-4">
 
            {{ section.schedule.section.name }}
 
            <span class="clearfix d-sm-block d-md-none"></span>
 
            <small class="text-muted">{{ timetable.day.date|date:"l" }}, {{ timetable.day.date }}</small>
 
          </h2>
 
          <p class="timezone-info small">Conference times are in {{ settings.LCA_START|date:'T' }} (UTC{{ settings.LCA_START|date:'O' }}). <span class="d-print-none">Current talks will be highlighted.</span></p>
 
          <p class="timezone-info small">Conference times are in {{ settings.CONF_START|date:'T' }} (UTC{{ settings.CONF_START|date:'O' }}). <span class="d-print-none">Current talks will be highlighted.</span></p>
 
          <div class="table-responsive d-none d-md-block">
 
            {% include "symposion/schedule/_grid.html" %}
 
          </div>
 
          <div class="mobile-schedule d-sm-block d-md-none">
 
            {% include "symposion/schedule/_mobile.html" %}
 
          </div>
 
        </div>
 
      </div>
 
      {% endfor %}
 
      {% endcache %}
 
    {% endfor %}
 
  </div>
 
{% endblock %}
 

	
 
{% block scripts_extra %}
 
  <script type="text/javascript">
 
    window.addEventListener("hashchange", function(event) {
 
      var fragment = window.location.hash.toLowerCase().substring(1);
 

	
 
      if (!fragment) {
 
        return;
 
      };
 

	
 
      var tab_id = "#schedule_day_" + fragment + "-tab";
pinaxcon/templates/symposion/schedule/schedule_detail.html
Show inline comments
 
{% extends "symposion/schedule/base.html" %}
 

	
 
{% load i18n %}
 
{% load cache %}
 
{% load lca2018_tags %}
 
{% load sitetree %}
 

	
 
{% block head_title %}{{ schedule.section.name }} Schedule{% endblock %}
 
{% block page_title %}{{ schedule.section.name }} Schedule{% endblock%}
 

	
 
{% block content %}
 
  {% cache 600 "schedule-detail-table" schedule.section %}
 
    {% for timetable in days %}
 
    <div class="row timetable-day">
 
      <div class="col-12">
 
        <h2 class="my-4">
 
          {{ timetable.day.date|date:"l" }}, {{ timetable.day.date }}
 
        </h2>
 
        <p class="timezone-info small">Conference times are in {{ settings.LCA_START|date:'T' }} (UTC{{ settings.LCA_START|date:'O' }}). <span class="d-print-none">Current talks will be highlighted.</span></p>
 
        <p class="timezone-info small">Conference times are in {{ settings.CONF_START|date:'T' }} (UTC{{ settings.CONF_START|date:'O' }}). <span class="d-print-none">Current talks will be highlighted.</span></p>
 
        <div class="table-responsive d-none d-md-block">
 
          {% include "symposion/schedule/_grid.html" %}
 
        </div>
 
        <div class="mobile-schedule d-sm-block d-md-none">
 
          {% include "symposion/schedule/_mobile.html" %}
 
        </div>
 
      </div>
 
    </div>
 
    {% endfor %}
 
  {% endcache %}
 
{% endblock %}
pinaxcon/templates/symposion/schedule/schedule_edit.html
Show inline comments
...
 
@@ -3,38 +3,38 @@
 
{% load i18n %}
 

	
 
{% block head_title %}Conference Schedule Edit{% endblock %}
 
{% block page_title %}Conference Schedule Edit{% endblock %}
 

	
 
{% block content %}
 
  <div class="row">
 
    <div class="col-12">
 
      <h2>Schedule Admin</h2>
 
      <form class="form-horizontal" id="schedule-builder" action="." method="post" enctype="multipart/form-data">
 
        {% csrf_token %}
 
        {{ form.as_p }}
 
        <input type="submit" name="submit" value="Submit" />
 
        <input type="submit" id="delete" name="delete" value="Delete Schedule" />
 
      </form>
 
    </div>
 
  </div>
 

	
 
  {% for timetable in days %}
 
  <div class="row">
 
    <div class="col-12">
 
      <h2 class="my-4">
 
        {{ timetable.day.date|date:"l" }}, {{ timetable.day.date }}
 
      </h2>
 
      <p class="timezone-info small">Conference times are in {{ settings.LCA_START|date:'T' }} (UTC{{ settings.LCA_START|date:'O' }}). <span class="d-print-none">Current talks will be highlighted.</span></p>
 
      <p class="timezone-info small">Conference times are in {{ settings.CONF_START|date:'T' }} (UTC{{ settings.CONF_START|date:'O' }}). <span class="d-print-none">Current talks will be highlighted.</span></p>
 
      <div class="table-responsive d-none d-md-block">
 
        {% include "symposion/schedule/_grid.html" with edit_schedule=True %}
 
      </div>
 
      <div class="mobile-schedule d-sm-block d-md-none">
 
        {% include "symposion/schedule/_mobile.html" with edit_schedule=True %}
 
      </div>
 
    </div>
 
  </div>
 
  {% endfor %}
 

	
 
  <div class="modal fade" id="slotEditModal"></div>
 
{% endblock %}
 

	
static/src/img/eo2023.svg
Show inline comments
 
new file 100644
 
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="180" height="35" viewBox="0 0 180 35"><path d="M14,15.85v.83H5.34V4.08h8.43v.83H6.26v5H13v.81H6.26v5.16Z" fill="#fff"/><path d="M27.27,4.08l-5.62,12.6h-.91L15.12,4.08h1l5.09,11.41,5.1-11.41Z" fill="#fff"/><path d="M38,15.85v.83H29.3V4.08h8.43v.83H30.22v5h6.72v.81H30.22v5.16Z" fill="#fff"/><path d="M50.09,16.68l-3-4.21a9.37,9.37,0,0,1-1.23.09h-3.6v4.12h-.92V4.08h4.52a5.65,5.65,0,0,1,3.73,1.13,3.84,3.84,0,0,1,1.35,3.12A3.85,3.85,0,0,1,48,12.27l3.15,4.41Zm-4.23-4.93a4.69,4.69,0,0,0,3.08-.89A3.12,3.12,0,0,0,50,8.33,3.11,3.11,0,0,0,48.94,5.8a4.69,4.69,0,0,0-3.08-.89h-3.6v6.84Z" fill="#fff"/><path d="M58,12.34v4.34h-.92V12.34L52,4.08h1l4.55,7.42,4.56-7.42h1Z" fill="#fff"/><path d="M67.73,4.91H63.2V4.08h10v.83H68.65V16.68h-.92Z" fill="#fff"/><path d="M85.71,4.08v12.6H84.8v-6H76.37v6h-.92V4.08h.92v5.8H84.8V4.08Z" fill="#fff"/><path d="M90.11,4.08H91v12.6h-.91Z" fill="#fff"/><path d="M105.68,4.08v12.6h-.76L96.33,5.74V16.68h-.91V4.08h.77l8.57,11V4.08Z" fill="#fff"/><path d="M119.07,10.44H120v4.71a5.49,5.49,0,0,1-2,1.21,7.56,7.56,0,0,1-2.49.41,6.76,6.76,0,0,1-3.37-.83,6,6,0,0,1-2.36-2.28,6.37,6.37,0,0,1-.86-3.28,6.34,6.34,0,0,1,.86-3.27,6,6,0,0,1,2.36-2.29A6.92,6.92,0,0,1,115.47,4a7.26,7.26,0,0,1,2.55.44,5.57,5.57,0,0,1,2,1.29l-.57.61a4.72,4.72,0,0,0-1.77-1.14,6.29,6.29,0,0,0-2.17-.35,6,6,0,0,0-2.93.72,5.21,5.21,0,0,0-2,2,5.53,5.53,0,0,0-.74,2.83,5.46,5.46,0,0,0,2.79,4.82,5.91,5.91,0,0,0,2.92.73,5.5,5.5,0,0,0,3.58-1.16Z" fill="#fff"/><path d="M147.91,5.3a3.84,3.84,0,0,1,1.35,3.12,3.81,3.81,0,0,1-1.35,3.1,5.65,5.65,0,0,1-3.73,1.13h-3.6v4.12h-.92V4.17h4.52A5.65,5.65,0,0,1,147.91,5.3Zm-.65,5.64a3.09,3.09,0,0,0,1.06-2.52,3.11,3.11,0,0,0-1.06-2.53A4.69,4.69,0,0,0,144.18,5h-3.6v6.82h3.6A4.69,4.69,0,0,0,147.26,10.94Z"/><path d="M161.05,15.94v.83h-8.7V4.17h8.43V5h-7.51v5H160v.81h-6.72v5.16Z"/><path d="M174.66,4.17v12.6h-.76L165.31,5.83V16.77h-.91V4.17h.77l8.57,11V4.17Z"/><path d="M131.65,4a6.18,6.18,0,0,0-3.33,0,6.35,6.35,0,0,0-1.83.85l.63.63a5.41,5.41,0,0,1,4.26-.63,5.67,5.67,0,0,1,2.56,1.51A5.56,5.56,0,0,1,135.44,9a5.28,5.28,0,0,1,0,2.87,5.65,5.65,0,0,1-1.53,2.57A5.87,5.87,0,0,1,131.31,16a5.32,5.32,0,0,1-2.88,0,5.56,5.56,0,0,1-2.56-1.5,5.56,5.56,0,0,1-1.5-2.56,5.32,5.32,0,0,1,0-2.88,5.61,5.61,0,0,1,.61-1.4l-.63-.62a6.32,6.32,0,0,0-.84,1.83,6.21,6.21,0,0,0,0,3.34,6.7,6.7,0,0,0,4.67,4.67,6.18,6.18,0,0,0,3.33,0,6.69,6.69,0,0,0,3-1.8,6.88,6.88,0,0,0,1.81-3,6.18,6.18,0,0,0,0-3.33,6.83,6.83,0,0,0-4.7-4.7Z" fill="#231f20"/><path d="M43.19,31.11V23.92L39.66,30h-.3l-3.51-6v7.17h-.6v-8.4h.51l3.76,6.49,3.76-6.49h.5v8.4Z"/><path d="M52.52,30.55v.56h-5.8v-8.4h5.62v.55h-5v3.31h4.48v.54H47.33v3.44Z"/><path d="M54.75,22.71h.61v7.84H60.2v.56H54.75Z"/><path d="M68.13,27.48a2,2,0,0,1,.48,1.41,1.91,1.91,0,0,1-.78,1.64,3.93,3.93,0,0,1-2.32.58H61.77v-8.4h3.5a3.57,3.57,0,0,1,2.13.55,1.87,1.87,0,0,1,.76,1.59,1.91,1.91,0,0,1-.38,1.22,2.08,2.08,0,0,1-1,.7A2.34,2.34,0,0,1,68.13,27.48Zm-5.75-4.25v3.35h2.87a3,3,0,0,0,1.7-.42,1.48,1.48,0,0,0,.59-1.26A1.44,1.44,0,0,0,67,23.66a2.94,2.94,0,0,0-1.7-.43Zm5,6.92a1.68,1.68,0,0,0,0-2.62,3.31,3.31,0,0,0-1.85-.42H62.38v3.47h3.13A3.22,3.22,0,0,0,67.36,30.15Z"/><path d="M72.12,30.61a4.09,4.09,0,0,1-1.56-1.53,4.26,4.26,0,0,1,1.56-5.88,4.82,4.82,0,0,1,4.47,0,4.07,4.07,0,0,1,1.56,1.52,4.47,4.47,0,0,1,0,4.37,4,4,0,0,1-1.56,1.52,4.74,4.74,0,0,1-4.47,0Zm4.14-.49a3.56,3.56,0,0,0,1.35-1.32,3.8,3.8,0,0,0,.49-1.89A3.75,3.75,0,0,0,77.61,25a3.52,3.52,0,0,0-1.35-1.33,4,4,0,0,0-3.82,0A3.52,3.52,0,0,0,71.09,25a3.65,3.65,0,0,0-.49,1.89,3.7,3.7,0,0,0,.49,1.89,3.56,3.56,0,0,0,1.35,1.32,4,4,0,0,0,3.82,0Z"/><path d="M81.66,30.24a3.74,3.74,0,0,1-.88-2.7V22.71h.61v4.81a3.31,3.31,0,0,0,.7,2.31,2.65,2.65,0,0,0,2.06.77,2.62,2.62,0,0,0,2-.77,3.31,3.31,0,0,0,.71-2.31V22.71h.61v4.83a3.74,3.74,0,0,1-.89,2.7,3.77,3.77,0,0,1-5,0Z"/><path d="M96.2,31.11l-2-2.81a6.07,6.07,0,0,1-.81.06H91v2.75h-.62v-8.4h3a3.77,3.77,0,0,1,2.48.75,2.56,2.56,0,0,1,.9,2.08,2.7,2.7,0,0,1-.51,1.67,2.77,2.77,0,0,1-1.46,1l2.1,2.94Zm-2.82-3.29a3.11,3.11,0,0,0,2.05-.6,2.06,2.06,0,0,0,.71-1.68,2.1,2.1,0,0,0-.71-1.69,3.17,3.17,0,0,0-2.05-.59H91v4.56Z"/><path d="M105.84,22.71v8.4h-.5l-5.73-7.3v7.3H99v-8.4h.52L105.23,30V22.71Z"/><path d="M114.57,30.55v.56h-5.8v-8.4h5.62v.55h-5v3.31h4.48v.54h-4.48v3.44Z"/><path d="M123.61,30.55v.56h-5.77v-.44l3.55-3.52a5.09,5.09,0,0,0,.94-1.2,2.33,2.33,0,0,0,.25-1,1.53,1.53,0,0,0-.55-1.26,2.36,2.36,0,0,0-1.58-.46,3.66,3.66,0,0,0-1.38.24,2.66,2.66,0,0,0-1,.73l-.43-.38a3.16,3.16,0,0,1,1.22-.85,4.4,4.4,0,0,1,1.67-.3,3,3,0,0,1,2,.6,2,2,0,0,1,.73,1.62,2.65,2.65,0,0,1-.29,1.23,5.38,5.38,0,0,1-1.08,1.37l-3.09,3.08Z" fill="#fff"/><path d="M126.29,30.64a3.28,3.28,0,0,1-1.16-1.48,6.26,6.26,0,0,1,0-4.51,3.34,3.34,0,0,1,1.16-1.48,3.07,3.07,0,0,1,3.42,0,3.43,3.43,0,0,1,1.17,1.48,6.41,6.41,0,0,1,0,4.51,3.37,3.37,0,0,1-1.17,1.48,3,3,0,0,1-3.42,0Zm3.11-.48a2.78,2.78,0,0,0,.94-1.27,5.16,5.16,0,0,0,.34-2,5.21,5.21,0,0,0-.34-2,2.78,2.78,0,0,0-.94-1.27,2.45,2.45,0,0,0-2.8,0,2.85,2.85,0,0,0-.94,1.27,5.42,5.42,0,0,0-.33,2,5.37,5.37,0,0,0,.33,2,2.85,2.85,0,0,0,.94,1.27,2.45,2.45,0,0,0,2.8,0Z" fill="#fff"/><path d="M138.2,30.55v.56h-5.77v-.44L136,27.15a4.83,4.83,0,0,0,.94-1.2,2.2,2.2,0,0,0,.25-1,1.53,1.53,0,0,0-.55-1.26,2.35,2.35,0,0,0-1.57-.46,3.71,3.71,0,0,0-1.39.24,2.66,2.66,0,0,0-1,.73l-.43-.38a3.16,3.16,0,0,1,1.22-.85,4.4,4.4,0,0,1,1.67-.3,3,3,0,0,1,2,.6,2,2,0,0,1,.73,1.62,2.77,2.77,0,0,1-.28,1.23,5.87,5.87,0,0,1-1.08,1.37l-3.1,3.08Z" fill="#fff"/><path d="M144,27a2.18,2.18,0,0,1,.72,1.7,2.42,2.42,0,0,1-.33,1.26,2.25,2.25,0,0,1-1,.85,3.68,3.68,0,0,1-1.6.32,4.81,4.81,0,0,1-1.71-.31,3,3,0,0,1-1.25-.82l.31-.47a3,3,0,0,0,1.11.74,3.88,3.88,0,0,0,1.54.29,2.58,2.58,0,0,0,1.72-.5,1.84,1.84,0,0,0,0-2.73,3,3,0,0,0-1.84-.49h-.53v-.44l2.49-3.18h-4.48v-.55h5.27v.43l-2.52,3.23A3.27,3.27,0,0,1,144,27Z" fill="#fff"/></svg>
static/src/img/la_logo.svg
Show inline comments
 
file renamed from static/src/lca/la_logo.svg to static/src/img/la_logo.svg
static/src/lca/lca2022.svg
Show inline comments
 
deleted file
static/src/lca/lca_horiz_blue.svg
Show inline comments
 
deleted file
static/src/lca/lca_horiz_colour.svg
Show inline comments
 
deleted file
vendor/regidesk/regidesk/models.py
Show inline comments
...
 
@@ -198,39 +198,39 @@ class CheckIn(models.Model):
 
            best = 0
 
            for presentation in self.user.speaker_profile.presentations.all():
 
                if presentation.section.id == 1:
 
                    # Main Conference Speaker
 
                    best = 1
 
                if best == 0 and presentation.section.id == 2:
 
                    # Miniconf Organiser
 
                    best = 2
 

	
 
            if best == 1:
 
                traits.append("speaker")
 
            elif best == 2:
 
                traits.append("miniconf_org")
 
            else:
 
                traits.append("miniconf_speaker")
 

	
 
        return traits
 

	
 
    def _generate_venueless_token(self):
 
        """ Generate token for Venueless login """
 
        if not self.venueless_traits:
 
            return ""
 

	
 
        issued_at = datetime.datetime.utcnow()
 
        expiry = settings.LCA_END + datetime.timedelta(days=1)
 
        expiry = settings.CONF_END + datetime.timedelta(days=1)
 
        if self.user.attendee.ticket_type == "Miniconf Only":
 
            # Miniconf only ticket holders have limited access
 
            expiry = settings.LCA_MINICONF_END
 
            expiry = settings.CONF_MINICONF_END
 

	
 
        payload = {
 
            "iss": settings.VENUELESS_TOKEN_ISSUER,
 
            "aud": settings.VENUELESS_AUDIENCE,
 
            "iat": issued_at,
 
            "exp": expiry,
 
            "uid": self.venueless_user_id,
 
            "traits": self.venueless_traits.split(','),
 
        }
 
        token = jwt.encode(payload, settings.VENUELESS_SECRET, algorithm="HS256")
 
        return token
vendor/regidesk/regidesk/templates/regidesk/ci_overview.html
Show inline comments
...
 
@@ -15,67 +15,67 @@
 
<!-- {% total_items_purchased 5 as pdns_count %} -->
 
{% ticket_type as ticket_type %}
 

	
 
<a type="button" class="btn btn-outline-primary" href="{% url 'regidesk:check_in_scanner' %}">Return to scanning page</a>
 

	
 
<div class="card my-3">
 
    <div class="card-header">Content Check</div>
 
    <div class="card-body">
 
        <dl class="card-text row">
 
            <dt class="col-sm-3">Ticket type</dt>
 
            <dd class="col-sm-9">{{ ticket_type }}</dd>
 

	
 
            <dt class="col-sm-3">Name</dt>
 
            <dd class="col-sm-9">{{ user.attendee.attendeeprofilebase.attendeeprofile.name }}</dd>
 

	
 
            <dt class="col-sm-3">Company</dt>
 
            <dd class="col-sm-9">{% if ticket_type == "Student" or ticket_type == "Hobbyist" or "Only" in ticket_type %}{% else %}{{ user.attendee.attendeeprofilebase.attendeeprofile.company }}{% endif %}</dd>
 

	
 
            <dt class="col-sm-3">Free Text 1</dt>
 
            <dd class="col-sm-9">{{ user.attendee.attendeeprofilebase.attendeeprofile.free_text_1 }}</dd>
 

	
 
            <dt class="col-sm-3">Free Text 2</dt>
 
            <dd class="col-sm-9">{{ user.attendee.attendeeprofilebase.attendeeprofile.free_text_2 }}</dd>
 

	
 
            {% comment "Not needed for LCA2022 online" %}
 
            {% comment "Not needed for EO2023" %}
 
            <dt class="col-sm-3">Penguin Dinner Tickets</dt>
 
            <dd class="col-sm-9">{{ penguin_dinner_count }}</dd>
 

	
 
            <dt class="col-sm-3">Speaker Dinner Tickets</dt>
 
            <dd class="col-sm-9">{{ speakers_dinner_count }}</dd>
 

	
 
            <dt class="col-sm-3">PDNS Tickets</dt>
 
            <dd class="col-sm-9">{{ pdns_count }}</dd>
 
            {% endcomment %}
 

	
 
            <dt class="col-sm-3">Over 18 years</dt>
 
            <dd class="col-sm-9">{% if user.attendee.attendeeprofilebase.attendeeprofile.of_legal_age %}Yes{% else %}<strong class="red">NO</strong>{% endif %}</dd>
 

	
 
            <dt class="col-sm-3">Username</dt>
 
            <dd class="col-sm-9">{{ user.username }}</dd>
 
        </dl>
 

	
 
        {% comment "Not needed for LCA2022 online" %}
 
        {% comment "Not needed for EO2023" %}
 
        <h4>Shirts ordered</h4>
 
        <table class="table card-text">
 
            {% for shirt in shirts%}
 
            <tr>
 
                <td>{{ shirt.product }}</td>
 
                <td>{{ shirt.quantity }}</td>
 
            </tr>
 
            {% endfor %}
 
        </table>
 
        {% endcomment %}
 
    </div>
 
</div>
 

	
 
<div class="card my-3">
 
    <div class="card-header">Venueless</div>
 
    <div class="card-body">
 
        <dl class="card-text row">
 
            <dt class="col-sm-3">User Id</dt>
 
            <dd class="col-sm-9">{{ check_in.venueless_user_id }}</dd>
 

	
 
            <dt class="col-sm-3">Traits</dt>
 
            <dd class="col-sm-9">{{ check_in.venueless_traits }}</dd>
 

	
 
            <dt class="col-sm-3">Token</dt>
...
 
@@ -107,76 +107,76 @@
 
    </div>
 
</div>
 

	
 
<div class="card {% if check_in.badge_printed %}border-success{% else %}border-danger{% endif %} my-3">
 
    <div class="card-header {% if check_in.badge_printed %}text-white bg-success{% endif %}">Badge</div>
 
    <div class="card-body">
 
        <dl class="row card-text">
 
            <dt class="col-sm-3">Status</dt>
 
            <dd class="col-sm-9">{% if check_in.badge_printed %}Marked{% else %}Not marked{% endif %} as printed</dd>
 
        </dl>
 
        <form method="post" class="d-inline-block">
 
            <input type="checkbox" name="badge" value="badge" checked hidden>
 
            <input class="btn btn-secondary" type="submit" value="Mark Badge as Printed">
 
        </form>
 
        <form method="post" class="d-inline-block">
 
            <input type="checkbox" name="unbadge" value="unbadge" checked hidden>
 
            <input class="btn btn-danger pull-right" type="submit" value="Reprint Badge">
 
        </form>
 
        <p class="d-inline-block">
 
            <a class="btn btn-outline-info" href="{% url 'badge_print' user.id %}" target="_blank">Preview Badge for Printing</a>
 
        </p>
 
    </div>
 
</div>
 

	
 
{% comment "Not needed for LCA2022 online" %}
 
{% comment "Not needed for EO2023" %}
 
<div class="card {% if check_in.schwag_given %}border-success{% else %}border-danger{% endif %} my-3">
 
    <div class="card-header {% if check_in.schwag_given %}text-white bg-success{% endif %}">Schwag</div>
 
    <div class="card-body">
 
        <dl class="row card-text">
 
            <dt class="col-sm-3">Status</dt>
 
            <dd class="col-sm-9">{% if check_in.schwag_given %}Marked{% else %}Not marked{% endif %} as given</dd>
 
        </dl>
 
        <form method="post">
 
            <input type="checkbox" name="schwag" value="schwag" checked hidden>
 
            <input class="btn {% if check_in.schwag_given %}btn-warning{% else %}btn-primary{% endif %}" type="submit" value="Give Schwag">
 
        </form>
 
    </div>
 
</div>
 
{% endcomment %}
 

	
 
<div class="card my-3">
 
    <div class="card-header">Log Exception</div>
 
    <div class="card-body">
 
        <form method="post" class="card-text">
 
            <textarea class="form-control" rows="3" name="exception">{{ check_in.review_text }}</textarea>
 
            <p class="help-block">Reminder: Please tell attendee to email the conference team with the details as well.</p>
 
            <input class="btn btn-primary" type="submit" value="Log Information">
 
        </form>
 
    </div>
 
</div>
 

	
 
{% comment "Not needed for LCA2022 online" %}
 
{% comment "Not needed for EO2023" %}
 
<div class="card my-3 {% if check_in.checked_in_bool and check_in.schwag_given %}border-success{% elif check_in.checked_in_bool or check_in.schwag_given %}card-warning{% else %}card-danger{% endif %}">
 
    <div class="card-header {% if check_in.checked_in_bool and check_in.schwag_given %}text-white bg-success{% elif check_in.checked_in_bool or check_in.schwag_given %}bg-warning{% endif %}">Bulk actions</div>
 
    <div class="card-body">
 
        <p>Mark attendee as checked in and schwag given</p>
 
        <dl class="row card-text">
 
            <dt class="col-sm-3">Status</dt>
 
            <dd class="col-sm-9">
 
                {% if check_in.checked_in_bool or check_in.schwag_given %}
 
                One of the items in bulk action is marked as given already
 
                {% else %}
 
                Both items are marked as unreceived
 
                {% endif %}
 
            </dd>
 
        </dl>
 
        <form method="post">
 
            <input type="checkbox" name="bulk" value="bulk" checked hidden>
 
            <input class="btn btn-primary" type="submit" value="Check In and Give Schwag">
 
        </form>
 
    </div>
 
</div>
 
{% endcomment %}
 

	
 
<a type="button" class="btn btn-outline-primary" href="{% url 'regidesk:check_in_scanner' %}">Return to scanning page</a>
 

	
vendor/registrasion/registrasion/views.py
Show inline comments
...
 
@@ -327,49 +327,49 @@ def _guided_registration_products(request, mode):
 
                sections.append(section)
 
                seen_categories.append(category)
 

	
 
    # Update the cache with the newly calculated values
 
    cat_ids = [cat.id for cat in seen_categories]
 
    request.session[SESSION_KEY] = {MODE_KEY: mode, CATS_KEY: cat_ids}
 

	
 
    return sections
 

	
 

	
 
@login_required
 
def _guided_registration_profile_and_voucher(request):
 
    voucher_form, voucher_handled = _handle_voucher(request, "voucher")
 
    profile_form, profile_handled = _handle_profile(request, "profile")
 

	
 
    voucher_section = GuidedRegistrationSection(
 
        title="Voucher Code",
 
        form=voucher_form,
 
    )
 

	
 
    profile_section = GuidedRegistrationSection(
 
        title="Profile and Personal Information",
 
        form=profile_form,
 
        description=("<div class=\"text-info\"><em>You can come back and edit these details any time before "
 
                     "January 1 2022.</em></div>"),
 
                     "March 10 2023.</em></div>"),
 
    )
 

	
 
    return [voucher_section, profile_section]
 

	
 

	
 
@login_required
 
def review(request):
 
    ''' View for the review page. '''
 

	
 
    return render(
 
        request,
 
        "registrasion/review.html",
 
        {},
 
    )
 

	
 

	
 
@login_required
 
def edit_profile(request):
 
    ''' View for editing an attendee's profile
 

	
 
    The user must be logged in to edit their profile.
 

	
 
    Returns:
 
        redirect or render:
vendor/symposion/schedule/views.py
Show inline comments
...
 
@@ -200,48 +200,49 @@ def schedule_presentation_detail(request, pk):
 
        section = presentation.proposal.kind.section
 
        if hasattr(section, 'schedule'):
 
            schedule = presentation.proposal.kind.section.schedule
 

	
 
    if not request.user.is_staff:
 
        # 3) Is proposal unpublished?
 
        if presentation.unpublish or not (schedule and schedule.published):
 
            raise Http404()
 

	
 
    ctx = {
 
        "presentation": presentation,
 
        "schedule": schedule,
 
    }
 
    return render(request, "symposion/schedule/presentation_detail.html", ctx)
 

	
 

	
 
def has_contact_perm(user):
 
    return user.has_perm('symposion_speakers.can_view_contact_details') or user.is_staff
 

	
 

	
 
def make_speaker_dict(speaker, can_view_contact_details):
 
    return {
 
        'name': speaker.name,
 
        'twitter': speaker.twitter_username,
 
        'mastodon': speaker.mastodon_username,
 
        'contact': speaker.email if can_view_contact_details else 'redacted',
 
        'picture_url': speaker_photo(None, speaker, 120),
 
        'code': speaker.code,
 
        'biography': speaker.biography,
 
        'username': speaker.user.username if can_view_contact_details else '',
 
    }
 

	
 

	
 
def schedule_json(request):
 
    slots = Slot.objects.filter(
 
        day__schedule__published=True,
 
        day__schedule__hidden=False
 
    ).order_by("start")
 

	
 
    can_view_contact_details = has_contact_perm(request.user)
 

	
 
    protocol = request.META.get('HTTP_X_FORWARDED_PROTO', 'http')
 
    data = []
 
    for slot in slots:
 
        rooms = list(slot.rooms)
 
        slot_data = {
 
            "room": ", ".join(room.name for room in rooms),
 
            "rooms": [room.name for room in rooms],
 
            "start": slot.start_datetime.isoformat(),
...
 
@@ -265,63 +266,65 @@ def schedule_json(request):
 
            if slot.content.unpublish and not request.user.is_staff:
 
                continue
 

	
 
            track_name = None
 
            if len(rooms) == 1:
 
                track = rooms[0].track_set.filter(day=slot.day).first()
 
                if track:
 
                    track_name = track.name
 

	
 
            slot_data.update({
 
                "name": slot.content.title,
 
                "authors": [make_speaker_dict(s, can_view_contact_details) for s in slot.content.speakers()],
 
                "abstract": slot.content.abstract,
 
                "conf_url": "%s://%s%s" % (
 
                    protocol,
 
                    Site.objects.get_current().domain,
 
                    reverse("schedule_presentation_detail", args=[slot.content.pk])
 
                ),
 
                "cancelled": slot.content.cancelled,
 
                "released": slot.content.proposal.recording_release,
 
                "track": track_name,
 
            })
 
            if not slot.content.speaker.twitter_username == '':
 
                slot_data["twitter_id"] = slot.content.speaker.twitter_username
 
            if not slot.content.speaker.mastodon_username == '':
 
                slot_data["mastodon_id"] = slot.content.speaker.mastodon_username
 
        else:
 
            slot_data.update({
 
                "name": slot.content_override if slot.content_override else "Slot",
 
            })
 
        data.append(slot_data)
 

	
 
    return HttpResponse(
 
        json.dumps({"schedule": data}, indent=2),
 
        content_type="application/json"
 
    )
 

	
 

	
 
class EventFeed(ICalFeed):
 

	
 
    product_id = '-//linux.conf.au/schedule//EN'
 
    product_id = '-//2023.everythingopen.au/schedule//EN'
 
    timezone = settings.TIME_ZONE
 
    filename = 'conference.ics'
 

	
 
    def description(self):
 
        return Conference.objects.all().first().title
 

	
 
    def items(self):
 
        return Slot.objects.filter(
 
            day__schedule__published=True,
 
            day__schedule__hidden=False
 
        ).exclude(
 
            kind__label='shortbreak'
 
        ).order_by("start")
 

	
 
    def item_title(self, item):
 
        if hasattr(item.content, 'proposal'):
 
            title = item.content.title
 
        else:
 
            title = item.kind if item.kind else "Slot"
 
        return title
 

	
 
    def item_description(self, item):
 
        if hasattr(item.content, 'proposal'):
 
            description = "Speaker: %s\n%s" % (
vendor/symposion/speakers/forms.py
Show inline comments
 
from django import forms
 

	
 
from symposion.speakers.models import Speaker
 

	
 

	
 
class SpeakerForm(forms.ModelForm):
 

	
 
    required_css_class = 'label-required'
 

	
 
    class Meta:
 
        model = Speaker
 
        fields = [
 
            "name",
 
            "pronouns",
 
            "biography",
 
            "experience",
 
            "photo",
 
            #"telephone",
 
            "telephone",
 
            "local_timezone",
 
            "homepage",
 
            "twitter_username",
 
            "mastodon_username",
 
            "accessibility",
 
            #"travel_assistance",
 
            #"accommodation_assistance",
 
            #"assistance",
 
            "travel_assistance",
 
            "accommodation_assistance",
 
            "assistance",
 
            "agreement",
 
        ]
 

	
 
    def __init__(self, *a, **k):
 
        super(SpeakerForm, self).__init__(*a, **k)
 
        self.fields['agreement'].required = True
 
        self.fields['biography'].required = True
 
        self.fields['local_timezone'].required = True
 

	
 
    def clean_twitter_username(self):
 
        value = self.cleaned_data["twitter_username"]
 
        if value.startswith("@"):
 
            value = value[1:]
 
        return value
vendor/symposion/speakers/migrations/0011_auto_20221208_0102.py
Show inline comments
 
new file 100644
 
# Generated by Django 2.2.28 on 2022-12-07 14:02
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('symposion_speakers', '0010_speaker_local_timezone'),
 
    ]
 

	
 
    operations = [
 
        migrations.AddField(
 
            model_name='speaker',
 
            name='mastodon_username',
 
            field=models.CharField(blank=True, help_text='Your Mastodon account', max_length=100),
 
        ),
 
        migrations.AddField(
 
            model_name='speaker',
 
            name='pronouns',
 
            field=models.CharField(blank=True, max_length=20, verbose_name='Pronouns'),
 
        ),
 
        migrations.AlterField(
 
            model_name='speaker',
 
            name='assistance',
 
            field=models.TextField(blank=True, help_text='We have budget set aside to provide financial assistance to speakers and attendees who might otherwise find it difficult to attend. Please provide details on why you require travel and/or accommodation assistance in order to present your proposed sessions. For travel assistance, please also tell us where you will be coming from (country, state, etc) to assist with planning.', verbose_name='Travel/Accommodation assistance details'),
 
        ),
 
        migrations.AlterField(
 
            model_name='speaker',
 
            name='travel_assistance',
 
            field=models.BooleanField(blank=True, default=False, help_text='Check this box if you require assistance to travel to the conference in order to present your proposed sessions.', verbose_name='Travel assistance required'),
 
        ),
 
    ]
vendor/symposion/speakers/models.py
Show inline comments
...
 
@@ -5,115 +5,124 @@ from django.urls import reverse
 
from django.utils.translation import ugettext_lazy as _
 

	
 
from django.contrib.auth import get_user_model
 

	
 
from timezone_field import TimeZoneField
 

	
 
from symposion import constants
 
from symposion.text_parser import parse
 

	
 
User = get_user_model()
 

	
 

	
 
class Speaker(models.Model):
 

	
 
    user = models.OneToOneField(
 
        User,
 
        null=True,
 
        related_name="speaker_profile",
 
        verbose_name=_("User"),
 
        on_delete=models.CASCADE,
 
    )
 
    name = models.CharField(verbose_name=_("Name"), max_length=100,
 
                            help_text=_("As you would like it to appear in the"
 
                                        " conference programme."))
 
    pronouns = models.CharField(verbose_name=_("Pronouns"),
 
        max_length=20,
 
        blank=True,
 
    )
 
    biography = models.TextField(
 
        blank=True,
 
        help_text=_("This will appear on the conference website and in the "
 
                    "programme.  Please write in the third person, eg 'Alice "
 
                    "is a Moblin hacker...', 150-200 words. " +
 
                    constants.TEXT_FIELD_MONOSPACE_NOTE),
 
        verbose_name=_("Biography"),
 
    )
 
    biography_html = models.TextField(blank=True)
 
    experience = models.TextField(
 
        blank=True,
 
        help_text=_("Have you had any experience presenting elsewhere? If so, "
 
                    "we'd like to know. Anything you put here will only be "
 
                    "seen by the organisers and reviewers; use it to convince "
 
                    "them why they should accept your proposal. " +
 
                    constants.TEXT_FIELD_MONOSPACE_NOTE),
 
        verbose_name=_("Speaking experience"),
 
    )
 
    experience_html = models.TextField(blank=True)
 
    photo = models.ImageField(upload_to="speaker_photos", blank=True, verbose_name=_("Photo"))
 
    telephone = models.CharField(
 
        max_length=15,
 
        help_text=_(u"The conference team will need this to contact you "
 
                    "during the conference week. If you don't have one, or do "
 
                    "not wish to provide it, then enter NONE in this field.")
 
    )
 
    local_timezone = TimeZoneField(
 
        blank=True,
 
        verbose_name=_("Local Timezone"),
 
        help_text=_("Your local timezone, preferably the one you will use to "
 
                    "present from. The conference organisers will "
 
                    "use this to assist with scheduling talks.")
 
    )
 
    homepage = models.URLField(
 
        blank=True,
 
        help_text=_(u"Your home page, if you have one")
 
    )
 
    twitter_username = models.CharField(
 
        max_length=15,
 
        blank=True,
 
        help_text=_(u"Your Twitter account")
 
    )
 
    mastodon_username = models.CharField(
 
        max_length=100,
 
        blank=True,
 
        help_text=_(u"Your Mastodon account")
 
    )
 
    accessibility = models.TextField(
 
        blank=True,
 
        help_text=_("Let us know how we can help you during the conference, for example "
 
                    "your accessibility requirements, whether you require access to child "
 
                    "minding facilities, or anything else you think we should know about."),
 
        verbose_name=_("Other requirements"))
 
    accessibility_html = models.TextField(blank=True)
 
    travel_assistance = models.BooleanField(
 
        blank=True,
 
        default=False,
 
        help_text=_("Check this box if you require assistance to travel to linux.conf.au "
 
        help_text=_("Check this box if you require assistance to travel to the conference "
 
                    "in order to present your proposed sessions."),
 
        verbose_name=_("Travel assistance required"),
 
    )
 
    accommodation_assistance = models.BooleanField(
 
        blank=True,
 
        default=False,
 
        help_text=_("Check this box if you require us to provide you with accommodation "
 
                    "in order to present your proposed sessions."),
 
        verbose_name=_("Accommodation assistance required"),
 
    )
 
    assistance = models.TextField(
 
        blank=True,
 
        help_text=_("We have budget set aside to provide financial assistance to "
 
                    "linux.conf.au speakers and attendees who might otherwise find it difficult to attend. "
 
                    "speakers and attendees who might otherwise find it difficult to attend. "
 
                    "Please provide details on why you require travel and/or accommodation assistance "
 
                    "in order to present your proposed sessions. "
 
                    "For travel assistance, please also tell us where you will be coming from "
 
                    "(country, state, etc) to assist with planning."),
 
        verbose_name=_("Travel/Accommodation assistance details"))
 
    assistance_html = models.TextField(blank=True)
 
    agreement = models.BooleanField(
 
        default=False,
 
        help_text=_("I agree to the "
 
                    "<a href=\"/attend/terms-and-conditions\"> "
 
                    "terms and conditions of attendance</a>, and I have read, "
 
                    "understood, and agree to act according to the standards set "
 
                    "forth in our "
 
                    "<a href=\"/attend/code-of-conduct\">"
 
                    "Code of Conduct</a>.")
 
    )
 

	
 
    annotation = models.TextField(verbose_name=_("Annotation"))  # staff only
 
    invite_email = models.CharField(max_length=200, unique=True, null=True, db_index=True, verbose_name=_("Invite_email"))
 
    invite_token = models.CharField(max_length=40, db_index=True, verbose_name=_("Invite token"))
 
    created = models.DateTimeField(
 
        default=datetime.datetime.now,
 
        editable=False,
 
        verbose_name=_("Created")
0 comments (0 inline, 0 general)