Update Docker build and push workflow and Dockerfile
This commit is contained in:
parent
a39e51e1f5
commit
4cb149f279
22 changed files with 301 additions and 293 deletions
|
|
@ -1 +1,2 @@
|
||||||
venv
|
venv
|
||||||
|
.env
|
||||||
54
.github/workflows/build-deploy.yml
vendored
Normal file
54
.github/workflows/build-deploy.yml
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
name: Docker Build and Push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- name: Setup Chrome
|
||||||
|
uses: nanasess/setup-chromedriver@v2
|
||||||
|
- name: Install dependencies
|
||||||
|
run: python -m pip install -r requirements.txt
|
||||||
|
- name: Test build
|
||||||
|
run: python manage.py test
|
||||||
|
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: test
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Build & push Docker image
|
||||||
|
uses: mr-smithers-excellent/docker-build-push@v6
|
||||||
|
with:
|
||||||
|
image: c4thebomb/csmb-housewars
|
||||||
|
registry: docker.io
|
||||||
|
addLatest: true
|
||||||
|
multiPlatform: true
|
||||||
|
platform: linux/amd64,linux/arm64/v8
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
draft:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: test
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Draft release
|
||||||
|
uses: release-drafter/release-drafter@v5
|
||||||
|
id: release-draft
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
40
.github/workflows/build-docker.yml
vendored
40
.github/workflows/build-docker.yml
vendored
|
|
@ -1,40 +0,0 @@
|
||||||
name: Commit docker image
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
environment: production
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Cache Docker layers
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache
|
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Login to DockerHub
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
|
||||||
push: true
|
|
||||||
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/collegiate-housewars:latest
|
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
|
||||||
- name: Image digest
|
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
|
||||||
17
.github/workflows/draft-release.yml
vendored
17
.github/workflows/draft-release.yml
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
name: Create release draft
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
draft:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Draft release
|
|
||||||
uses: release-drafter/release-drafter@v5
|
|
||||||
id: release-draft
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
24
.github/workflows/test-build.yml
vendored
24
.github/workflows/test-build.yml
vendored
|
|
@ -1,24 +0,0 @@
|
||||||
name: Test build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: '3.10'
|
|
||||||
- name: Setup Chrome
|
|
||||||
uses: nanasess/setup-chromedriver@v1.0.8
|
|
||||||
- name: Install dependencies
|
|
||||||
run: python -m pip install -r requirements.txt
|
|
||||||
- name: Test build
|
|
||||||
run: python manage.py test
|
|
||||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
|
@ -5,5 +5,9 @@
|
||||||
"editor.defaultFormatter": null,
|
"editor.defaultFormatter": null,
|
||||||
"[dockercompose]": {
|
"[dockercompose]": {
|
||||||
"editor.defaultFormatter": "ms-azuretools.vscode-docker"
|
"editor.defaultFormatter": "ms-azuretools.vscode-docker"
|
||||||
}
|
},
|
||||||
|
"lldb.displayFormat": "auto",
|
||||||
|
"lldb.showDisassembly": "auto",
|
||||||
|
"lldb.dereferencePointers": true,
|
||||||
|
"lldb.consoleMode": "commands"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
from .dev import *
|
from .local import *
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from django.contrib.messages import constants
|
from django.contrib.messages import constants
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
||||||
|
|
||||||
SECURE_SSL_REDIRECT = False
|
SECURE_SSL_REDIRECT = False
|
||||||
SESSION_COOKIE_SECURE = False
|
SESSION_COOKIE_SECURE = False
|
||||||
CSRF_COOKIE_SECURE = False
|
CSRF_COOKIE_SECURE = False
|
||||||
|
|
||||||
# Application definition
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
|
|
@ -21,7 +18,7 @@ INSTALLED_APPS = [
|
||||||
'smart_selects',
|
'smart_selects',
|
||||||
'formtools',
|
'formtools',
|
||||||
|
|
||||||
'housewars.apps.HousewarsConfig'
|
'housewars',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
@ -55,9 +52,6 @@ TEMPLATES = [
|
||||||
|
|
||||||
WSGI_APPLICATION = 'CollegiateHouseWars.wsgi.application'
|
WSGI_APPLICATION = 'CollegiateHouseWars.wsgi.application'
|
||||||
|
|
||||||
# Password validation
|
|
||||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
|
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
|
@ -73,9 +67,6 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
# Internationalization
|
|
||||||
# https://docs.djangoproject.com/en/4.0/topics/i18n/
|
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
TIME_ZONE = 'UTC'
|
TIME_ZONE = 'UTC'
|
||||||
|
|
@ -84,9 +75,6 @@ USE_I18N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = 'static/'
|
STATIC_URL = 'static/'
|
||||||
STATIC_ROOT = BASE_DIR / "staticfiles"
|
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||||
|
|
||||||
|
|
@ -108,9 +96,6 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Default primary key field type
|
|
||||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
|
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
from .defaults import *
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
|
||||||
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
|
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
|
||||||
SECRET_KEY = '*9r50c74r58p#*tnfpadsw*cp&$(^sj585w1u@!y9*eowmwl1*'
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = [
|
|
||||||
'localhost',
|
|
||||||
'127.0.0.1',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from .dev import *
|
from .local import *
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
|
|
|
||||||
17
CollegiateHouseWars/settings/local.py
Normal file
17
CollegiateHouseWars/settings/local.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from .defaults import *
|
||||||
|
|
||||||
|
SECRET_KEY = '*9r50c74r58p#*tnfpadsw*cp&$(^sj585w1u@!y9*eowmwl1*'
|
||||||
|
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = [
|
||||||
|
'localhost',
|
||||||
|
'127.0.0.1',
|
||||||
|
]
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,29 +2,22 @@ import os
|
||||||
|
|
||||||
from .defaults import *
|
from .defaults import *
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
|
||||||
SECRET_KEY = os.environ.get('SECRET_KEY')
|
SECRET_KEY = os.environ.get('SECRET_KEY')
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
DEBUG = False
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = [
|
ALLOWED_HOSTS = [
|
||||||
'housewars.c4thebomb101.com',
|
'csmb-housewars.c4patino.com',
|
||||||
'csmb-housewars.herokuapp.com',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
CSRF_TRUSTED_ORIGINS = [
|
CSRF_TRUSTED_ORIGINS = [
|
||||||
'https://housewars.c4thebomb101.com',
|
'https://csmb-housewars.c4patino.com/'
|
||||||
'https://csmb-housewars.herokuapp.com'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.mysql',
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
'NAME': 'housewars',
|
'NAME': os.environ.get('DATABASE_NAME'),
|
||||||
'USER': os.environ.get('DATABASE_USERNAME'),
|
'USER': os.environ.get('DATABASE_USERNAME'),
|
||||||
'PASSWORD': os.environ.get('DATABASE_PASSWORD'),
|
'PASSWORD': os.environ.get('DATABASE_PASSWORD'),
|
||||||
'HOST': os.environ.get('DATABASE_HOST'),
|
'HOST': os.environ.get('DATABASE_HOST'),
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,7 @@ import os
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
from whitenoise import WhiteNoise
|
from whitenoise import WhiteNoise
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CollegiateHouseWars.settings.prod')
|
||||||
'CollegiateHouseWars.settings.prod')
|
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
application = WhiteNoise(application)
|
application = WhiteNoise(application)
|
||||||
|
|
|
||||||
21
Dockerfile
21
Dockerfile
|
|
@ -1,9 +1,20 @@
|
||||||
# syntax=docker/dockerfile:1
|
FROM python:3.10
|
||||||
FROM python:3.10.6-slim-buster
|
|
||||||
RUN apt update && apt install build-essential default-libmysqlclient-dev -y
|
ENV PYTHONDONTWRITEBYTECODE 1
|
||||||
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt requirements.txt
|
COPY requirements.txt requirements.txt
|
||||||
RUN python -m pip install -r requirements.txt
|
|
||||||
|
RUN pip install --upgrade pip && \
|
||||||
|
pip install -r requirements.txt && \
|
||||||
|
pip install gunicorn
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
RUN python manage.py collectstatic --noinput
|
||||||
|
|
||||||
EXPOSE 8000/tcp
|
EXPOSE 8000/tcp
|
||||||
CMD python manage.py runserver 0.0.0.0:8000
|
|
||||||
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "CollegiateHouseWars.wsgi:application"]
|
||||||
17
Dockerfile.dev
Normal file
17
Dockerfile.dev
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
FROM python:3.10
|
||||||
|
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE 1
|
||||||
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt requirements.txt
|
||||||
|
|
||||||
|
RUN pip install --upgrade pip && \
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8000/tcp
|
||||||
|
|
||||||
|
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
||||||
27
docker-compose.prod.yml
Normal file
27
docker-compose.prod.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
restart: unless-stopped
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64/v8
|
||||||
|
image: c4thebomb/csmb-housewars:${TAG:-latest}
|
||||||
|
env_file:
|
||||||
|
- path: .env
|
||||||
|
required: true
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:8000:8000
|
||||||
|
networks:
|
||||||
|
- housewars
|
||||||
|
- common-network
|
||||||
|
external_links:
|
||||||
|
- mysqldb
|
||||||
|
|
||||||
|
networks:
|
||||||
|
common-network:
|
||||||
|
external: true
|
||||||
|
housewars: {}
|
||||||
|
|
@ -5,10 +5,12 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
ports:
|
ports:
|
||||||
- 8000:8000
|
- 8000:8000
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/app
|
- ./:/app
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- housewars
|
- housewars
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -20,11 +22,12 @@ services:
|
||||||
bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
|
bash -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
|
||||||
mysqldb:
|
mysqldb:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
image: mysql:5.7
|
image: mysql:8.3
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 3306:3306
|
||||||
volumes:
|
volumes:
|
||||||
- housewars-mysql:/var/lib/mysql
|
- housewars-mysql:/var/lib/mysql
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- housewars
|
- housewars
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -34,7 +37,10 @@ services:
|
||||||
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
|
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
housewars-mysql:
|
housewars-mysql:
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
housewars: {}
|
housewars: {}
|
||||||
|
|
|
||||||
|
|
@ -2,38 +2,39 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block step-counter %}
|
{% block step-counter %}
|
||||||
<div class="steps-form">
|
<div class="steps-form">
|
||||||
<div class="steps-row setup-panel">
|
<div class="steps-row setup-panel">
|
||||||
<div class="steps-step">
|
<div class="steps-step">
|
||||||
<button name="wizard_goto_step" class="btn btn-secondary btn-circle" type="submit" value="user">1</button>
|
<button name="wizard_goto_step" class="btn btn-secondary btn-circle" type="submit" value="user">1</button>
|
||||||
<p>Info</p>
|
<p>Info</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="steps-step">
|
<div class="steps-step">
|
||||||
<button name="wizard_goto_step" class="btn btn-primary btn-circle" type="disabled"
|
<button name="wizard_goto_step" class="btn btn-primary btn-circle" type="disabled"
|
||||||
value="activity">2</button>
|
value="activity">2</button>
|
||||||
<p>Activities</p>
|
<p>Activities</p>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ wizard.management_form }}
|
{{ wizard.management_form }}
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="activity1" class="form-label">Activity 1:</label>
|
<label for="activity1" class="form-label">Activity 1:</label>
|
||||||
{{ form.activity1 }}
|
{{ form.activity1 }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="activity2" class="form-label">Activity 2:</label>
|
<label for="activity2" class="form-label">Activity 2:</label>
|
||||||
{{ form.activity2 }}
|
{{ form.activity2 }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group d-flex justify-content-center">
|
<div class="form-group d-flex justify-content-center">
|
||||||
<button name="wizard_goto_step" class="btn btn-outline-primary btn-50" type="submit" value="{{ wizard.steps.prev }}">Previous Step</button>
|
<button name="wizard_goto_step" class="btn btn-outline-primary btn-50" type="submit"
|
||||||
<input id='submit' class="btn btn-outline-primary btn-50" type="submit" value="Submit" />
|
value="{{ wizard.steps.prev }}">Previous Step</button>
|
||||||
</div>
|
<input id='submit' class="btn btn-outline-primary btn-50" type="submit" value="Submit" />
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -18,34 +18,34 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ wizard.management_form }}
|
{{ wizard.management_form }}
|
||||||
|
|
||||||
<label for="name" class="form-label">Name:</label>
|
<label for="name" class="form-label">Name:</label>
|
||||||
<div class="row mb-3" id="name">
|
<div class="row mb-3" id="name">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{{ form.first_name }}
|
{{ form.first_name }}
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
{{ form.last_name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="col">
|
||||||
<label for="email" class="form-label">Email:</label>
|
{{ form.last_name }}
|
||||||
{{ form.email }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
</div>
|
||||||
<label for="grade" class="form-label">Grade:</label>
|
<div class="mb-3">
|
||||||
{{ form.grade }}
|
<label for="email" class="form-label">Email:</label>
|
||||||
</div>
|
{{ form.email }}
|
||||||
<div class="mb-3">
|
</div>
|
||||||
<label for="house" class="form-label">House:</label>
|
<div class="mb-3">
|
||||||
{{ form.house }}
|
<label for="grade" class="form-label">Grade:</label>
|
||||||
</div>
|
{{ form.grade }}
|
||||||
|
</div>
|
||||||
<div class="form-group d-flex justify-content-center">
|
<div class="mb-3">
|
||||||
<input id='submit' class="btn btn-outline-primary btn-100" type="submit" value="Submit" />
|
<label for="house" class="form-label">House:</label>
|
||||||
</div>
|
{{ form.house }}
|
||||||
</form>
|
</div>
|
||||||
{% endblock %}
|
|
||||||
|
<div class="form-group d-flex justify-content-center">
|
||||||
|
<input id='submit' class="btn btn-outline-primary btn-100" type="submit" value="Submit" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{% extends "admin/base_site.html" %}
|
{% extends "admin/base_site.html" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% if subtitle %}
|
{% if subtitle %}
|
||||||
{{ subtitle }} |
|
{{ subtitle }} |
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ title }} | House Wars Admin
|
{{ title }} | House Wars Admin
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block branding %}
|
{% block branding %}
|
||||||
|
|
|
||||||
|
|
@ -1,95 +1,98 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
|
||||||
<meta charset="ISO-8859-1" />
|
|
||||||
<meta name="description" content="A website made by C4 Patino" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
|
||||||
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
|
||||||
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="{% static 'jquery-3.6.1.min.js' %}"></script>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href='{% static "css/main.css" %}' />
|
<head>
|
||||||
<link rel="icon" type="image/x-icon" href='{% static "favicon.ico" %}'>
|
<meta charset="ISO-8859-1" />
|
||||||
|
<meta name="description" content="A website made by C4 Patino" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
<script src="{% static 'smart-selects/admin/js/chainedfk.js' %}"></script>
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
<script src="{% static 'smart-selects/admin/js/chainedm2m.js' %}"></script>
|
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="{% static 'jquery-3.6.1.min.js' %}"></script>
|
||||||
|
|
||||||
{% block title %}
|
<link rel="stylesheet" type="text/css" href='{% static "css/main.css" %}' />
|
||||||
<title>
|
<link rel="icon" type="image/x-icon" href='{% static "favicon.ico" %}'>
|
||||||
{% if title %}{{ title }}{% endif %} | House Wars
|
|
||||||
</title>
|
<script src="{% static 'smart-selects/admin/js/chainedfk.js' %}"></script>
|
||||||
{% endblock %}
|
<script src="{% static 'smart-selects/admin/js/chainedm2m.js' %}"></script>
|
||||||
</head>
|
|
||||||
<body>
|
{% block title %}
|
||||||
<main role="main" class="container-fluid h-100 m-0 p-0">
|
<title>
|
||||||
<div class="row h-100 m-0 p-0">
|
{% if title %}{{ title }}{% endif %} | House Wars
|
||||||
<div class="col-lg-4 col-md-12 p-5">
|
</title>
|
||||||
<div id="step-counter" class="mb-5">
|
{% endblock %}
|
||||||
{% block step-counter %}{% endblock %}
|
</head>
|
||||||
</div>
|
|
||||||
|
<body>
|
||||||
<h2 id="header" class="mt-2 mb-4">{% if formtitle %}{{ formtitle }}{% endif %}</h2>
|
<main role="main" class="container-fluid h-100 m-0 p-0">
|
||||||
|
<div class="row h-100 m-0 p-0">
|
||||||
<!-- Main content -->
|
<div class="col-lg-4 col-md-12 p-5">
|
||||||
{% block content %}{% endblock %}
|
<div id="step-counter" class="mb-5">
|
||||||
|
{% block step-counter %}{% endblock %}
|
||||||
<!-- Message content and form errors -->
|
|
||||||
<div class="mt-2">
|
|
||||||
{% if messages %}
|
|
||||||
{% for message in messages %}
|
|
||||||
<div class="alert alert-{{ message.tags }}">{{ message }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if form.errors %}
|
|
||||||
{% for field in form %}
|
|
||||||
{% for error in field.errors %}
|
|
||||||
<div class="alert alert-danger">{{ error }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% for error in form.non_field_errors %}
|
|
||||||
<div class="alert alert-danger">{{ error }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="banner" class="col row align-items-center m-0 pe-5">
|
|
||||||
<div id="carousel" class="carousel slide m-0 p-0" data-bs-ride="carousel">
|
<h2 id="header" class="mt-2 mb-4">{% if formtitle %}{{ formtitle }}{% endif %}</h2>
|
||||||
<div class="carousel-inner">
|
|
||||||
<div class="carousel-item active">
|
<!-- Main content -->
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5817.JPG" %}'>
|
{% block content %}{% endblock %}
|
||||||
</div>
|
|
||||||
<div class="carousel-item">
|
<!-- Message content and form errors -->
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5818.JPG" %}'>
|
<div class="mt-2">
|
||||||
</div>
|
{% if messages %}
|
||||||
<div class="carousel-item">
|
{% for message in messages %}
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5819.JPG" %}'>
|
<div class="alert alert-{{ message.tags }}">{{ message }}</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
<div class="carousel-item">
|
{% endif %}
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5821.JPG" %}'>
|
|
||||||
</div>
|
{% if form.errors %}
|
||||||
<div class="carousel-item">
|
{% for field in form %}
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5823.JPG" %}'>
|
{% for error in field.errors %}
|
||||||
</div>
|
<div class="alert alert-danger">{{ error }}</div>
|
||||||
<div class="carousel-item">
|
{% endfor %}
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5826.JPG" %}'>
|
{% endfor %}
|
||||||
</div>
|
|
||||||
<div class="carousel-item">
|
{% for error in form.non_field_errors %}
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5849.JPG" %}'>
|
<div class="alert alert-danger">{{ error }}</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
<div class="carousel-item">
|
{% endif %}
|
||||||
<img class="d-block w-100" src='{% static "img/IMG_5856.JPG" %}'>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="banner" class="col row align-items-center m-0 pe-5">
|
||||||
|
<div id="carousel" class="carousel slide m-0 p-0" data-bs-ride="carousel">
|
||||||
|
<div class="carousel-inner">
|
||||||
|
<div class="carousel-item active">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5817.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5818.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5819.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5821.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5823.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5826.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5849.JPG" %}'>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img class="d-block w-100" src='{% static "img/IMG_5856.JPG" %}'>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</div>
|
||||||
</body>
|
</main>
|
||||||
</html>
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -42,10 +42,6 @@ class PointsEntryCreatePageTest(StaticLiveServerTestCase):
|
||||||
Select(self.browser.find_element(By.ID, 'id_activity')).select_by_visible_text('Dodgeball - 30 min')
|
Select(self.browser.find_element(By.ID, 'id_activity')).select_by_visible_text('Dodgeball - 30 min')
|
||||||
Select(self.browser.find_element(By.ID, 'house')).select_by_visible_text('Hawk')
|
Select(self.browser.find_element(By.ID, 'house')).select_by_visible_text('Hawk')
|
||||||
|
|
||||||
# Wait until the Select button with '1st' shows up
|
|
||||||
WebDriverWait(self.browser, timeout=5).until(visibility_of(
|
|
||||||
self.browser.find_element(By.XPATH, "//option[text()='1st']")))
|
|
||||||
|
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
|
|
||||||
Select(self.browser.find_element(By.ID, 'id_award')).select_by_visible_text('1st')
|
Select(self.browser.find_element(By.ID, 'id_award')).select_by_visible_text('1st')
|
||||||
|
|
|
||||||
Reference in a new issue