mirror of
https://gitlab.science.ru.nl/technicie/MarietjeDjango.git
synced 2025-12-13 18:32:20 +01:00
Compare commits
16 Commits
feature/ma
...
44a1d44cd1
| Author | SHA1 | Date | |
|---|---|---|---|
| 44a1d44cd1 | |||
| 2e65d7fd89 | |||
| 521c047225 | |||
| 0a3b2d2a8c | |||
| 13448a2eec | |||
| fe186ffa99 | |||
| e30cc33ffc | |||
| 4d797691b1 | |||
| e45940772f | |||
| 77728c9a82 | |||
| 08cd59ce09 | |||
| ad94fe7930 | |||
| 5acf553269 | |||
| ec66f09a79 | |||
| 4768271aee | |||
| 3d78ca954f |
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
marietje/db.sqlite3
|
||||||
|
marietje/static
|
||||||
|
docker-compose.yml.example
|
||||||
|
docker-compose.yml
|
||||||
@ -16,7 +16,8 @@ black:
|
|||||||
script:
|
script:
|
||||||
- poetry run black --quiet --check marietje
|
- poetry run black --quiet --check marietje
|
||||||
|
|
||||||
deploy:
|
# TODO: Fix the deploy stage, as it has not been adapted to the new server Marietje runs on. The . disables the stage.
|
||||||
|
.deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
only: ['marietje-zuid']
|
only: ['marietje-zuid']
|
||||||
before_script:
|
before_script:
|
||||||
|
|||||||
26
Dockerfile
Normal file
26
Dockerfile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
FROM python:3.11
|
||||||
|
MAINTAINER Tartarus Technicie
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
ENV DJANGO_SETTINGS_MODULE marietje.settings.production
|
||||||
|
ENV PATH /root/.poetry/bin:${PATH}
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
|
|
||||||
|
WORKDIR /marietje/src
|
||||||
|
COPY resources/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
COPY poetry.lock pyproject.toml /marietje/src/
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
mkdir --parents /marietje/src/ && \
|
||||||
|
mkdir --parents /marietje/log/ && \
|
||||||
|
mkdir --parents /marietje/static/ && \
|
||||||
|
chmod +x /usr/local/bin/entrypoint.sh && \
|
||||||
|
\
|
||||||
|
curl -sSL https://install.python-poetry.org | python3 - && \
|
||||||
|
export PATH="/root/.local/bin:$PATH" && \
|
||||||
|
poetry config --no-interaction --no-ansi virtualenvs.create false && \
|
||||||
|
poetry install --no-interaction --no-ansi --no-dev
|
||||||
|
|
||||||
|
|
||||||
|
COPY marietje /marietje/src/website/
|
||||||
43
docker-compose.yml.example
Normal file
43
docker-compose.yml.example
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
services:
|
||||||
|
reverse-proxy:
|
||||||
|
container_name: 'marietje-reverse-proxy'
|
||||||
|
image: nginx:latest
|
||||||
|
restart: 'always'
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
volumes:
|
||||||
|
- ./data/shared/media/:/marietje/media/
|
||||||
|
- ./data/shared/static/:/marietje/static/
|
||||||
|
- ./data/reverse-proxy/conf.d/:/etc/nginx/conf.d/
|
||||||
|
- ./data/reverse-proxy/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
networks:
|
||||||
|
- marietje-network
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build: "."
|
||||||
|
restart: 'always'
|
||||||
|
container_name: 'marietje-backend'
|
||||||
|
volumes:
|
||||||
|
- ./data/shared/static/:/marietje/src/website/static/
|
||||||
|
- ./data/shared/media/:/marietje/src/website/media/
|
||||||
|
- ./data/backend/log/:/marietje/log/
|
||||||
|
environment:
|
||||||
|
DJANGO_SECRET_KEY: '[Django Secret key]'
|
||||||
|
VIRTUAL_HOST: '[Marietje hostname]'
|
||||||
|
VIRTUAL_PROTO: 'uwsgi'
|
||||||
|
DJANGO_ALLOWED_HOST: 'marietje-zuid.nl'
|
||||||
|
DJANGO_MYSQL_NAME: 'marietje'
|
||||||
|
DJANGO_MYSQL_USER: 'marietje'
|
||||||
|
DJANGO_MYSQL_PASSWORD: '[Marietje zuid database password]'
|
||||||
|
DJANGO_MYSQL_HOST: 'localhost'
|
||||||
|
DJANGO_MYSQL_PORT: '3306'
|
||||||
|
DJANGO_BERTHA_HOST: 'bach.science.ru.nl'
|
||||||
|
DJANGO_BERTHA_PORT: '1234'
|
||||||
|
networks:
|
||||||
|
- marietje-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
marietje-network:
|
||||||
|
driver: bridge
|
||||||
49
marietje/marietje/settings/production.py
Normal file
49
marietje/marietje/settings/production.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from .base import *
|
||||||
|
|
||||||
|
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY")
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = [os.environ.get("DJANGO_ALLOWED_HOST")]
|
||||||
|
|
||||||
|
SESSION_COOKIE_SECURE = True
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.mysql',
|
||||||
|
'NAME': os.environ.get("DJANGO_MYSQL_NAME"),
|
||||||
|
'USER': os.environ.get("DJANGO_MYSQL_USER"),
|
||||||
|
'PASSWORD': os.environ.get("DJANGO_MYSQL_PASSWORD"),
|
||||||
|
'HOST': os.environ.get("DJANGO_MYSQL_HOST"),
|
||||||
|
'PORT': os.environ.get("DJANGO_MYSQL_PORT"),
|
||||||
|
'OPTIONS': {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
# https://docs.djangoproject.com/en/3.2/topics/logging/
|
||||||
|
|
||||||
|
LOGGING = {
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": False,
|
||||||
|
"handlers": {
|
||||||
|
"file": {
|
||||||
|
"level": "INFO",
|
||||||
|
"class": "logging.FileHandler",
|
||||||
|
"filename": "/marietje/log/django.log",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"loggers": {
|
||||||
|
"": {
|
||||||
|
"handlers": ["file"],
|
||||||
|
"level": "DEBUG",
|
||||||
|
"propagate": True,
|
||||||
|
}, # noqa
|
||||||
|
}, # noqa
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_URL = 'https://marietje-zuid.science.ru.nl'
|
||||||
|
|
||||||
|
BERTHA_HOST = (os.environ.get("DJANGO_BERTHA_HOST"), os.environ.get("DJANGO_BERTHA_PORT"))
|
||||||
@ -1,23 +0,0 @@
|
|||||||
from .base import *
|
|
||||||
|
|
||||||
SECRET_KEY = '******'
|
|
||||||
|
|
||||||
DEBUG = False
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['marietje-zuid.nl']
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.mysql',
|
|
||||||
'NAME': 'marietje',
|
|
||||||
'USER': 'marietje',
|
|
||||||
'PASSWORD': '******',
|
|
||||||
'HOST': 'localhost',
|
|
||||||
'PORT': '3306',
|
|
||||||
'OPTIONS': {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE_URL = 'https://marietje-zuid.science.ru.nl'
|
|
||||||
|
|
||||||
BERTHA_HOST = ('bach.science.ru.nl', 1234)
|
|
||||||
@ -53,18 +53,6 @@ button[type="button"] i {
|
|||||||
min-width: 90px;
|
min-width: 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.song-info {
|
|
||||||
position: absolute;
|
|
||||||
padding: 8px;
|
|
||||||
background: silver;
|
|
||||||
white-space: nowrap;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#queue-time-header {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@ -98,7 +86,7 @@ footer {
|
|||||||
border-top: 3px double var(--text-color);
|
border-top: 3px double var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.requested_song{
|
.ownsong {
|
||||||
border-left: 1px solid var(--text-color);
|
border-left: 1px solid var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item me-3" role="presentation">
|
<li class="nav-item me-3" role="presentation">
|
||||||
<button class="nav-link" id="request-tab" data-bs-toggle="tab" data-bs-target="#request"
|
<button onclick="request_vue.select_textinput()" class="nav-link" id="request-tab" data-bs-toggle="tab" data-bs-target="#request"
|
||||||
type="button" role="tab" aria-controls="request" aria-selected="false">Request
|
type="button" role="tab" aria-controls="request" aria-selected="false">Request
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@ -78,19 +78,50 @@
|
|||||||
<td class="col-md-4">Title</td>
|
<td class="col-md-4">Title</td>
|
||||||
<td class="col-md-2 d-sm-table-cell d-none">Requested By</td>
|
<td class="col-md-2 d-sm-table-cell d-none">Requested By</td>
|
||||||
<td class="col-md-1 text-info d-sm-table-cell d-none" style="cursor: pointer;">
|
<td class="col-md-1 text-info d-sm-table-cell d-none" style="cursor: pointer;">
|
||||||
<span v-if="playsIn" id="timeswitch" class="btn btn-link p-0" v-on:click="playsIn = false">Plays In</span>
|
<span v-if="playsIn" class="btn btn-link p-0" v-on:click="playsIn = false">Plays In</span>
|
||||||
<span v-else class="btn btn-link p-0" v-on:click="playsIn = true">Plays At</span>
|
<span v-else class="btn btn-link p-0" v-on:click="playsIn = true">Plays At</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="col-md-1 control-icons">Control</td>
|
<td class="col-md-1">
|
||||||
|
<span class="control-icons">Control</span>
|
||||||
|
<span v-if="playsIn" class="btn btn-link p-0 d-sm-none" v-on:click="toggle_details(song)">(Plays in)</span>
|
||||||
|
<span v-else class="btn btn-link p-0 d-sm-none" v-on:click="toggle_details(song)">(Plays At)</span>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="queuebody">
|
<tbody class="queuebody">
|
||||||
<template v-for="(song, index) in queue">
|
<template v-for="(song, index) in queue">
|
||||||
<tr :class="{ marietjequeue: (song.user === null),
|
<tr :class="{ marietjequeue: (song.user === null),
|
||||||
underline_cell: (index === queue[-1]),
|
underline_cell: (index === queue[-1]),
|
||||||
currentsong: (index === 0),}">
|
currentsong: (index === 0),
|
||||||
<td class="artist">${ song.song.artist }$</td>
|
ownsong: (this.user_data.id === song.user?.id && index !== 0),
|
||||||
<td class="title">${ song.song.title }$</td>
|
}"
|
||||||
|
v-on:click="toggle_details(song)">
|
||||||
|
<td>
|
||||||
|
<span class="artist">${ song.song.artist }$</span>
|
||||||
|
<span v-if="show_details(song)" class="requested-by d-sm-none d-block small mt-3 fw-normal">
|
||||||
|
Requested by:<br>
|
||||||
|
<template v-if="song.user === null">
|
||||||
|
Marietje
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
${ song.user.name }$
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="title">${ song.song.title }$</span>
|
||||||
|
<span v-if="show_details(song) && song.time_until_song_seconds > 0" class="plays-at d-sm-none d-block small mt-3 fw-normal" style="text-align: right">
|
||||||
|
<span v-if="playsIn">Plays In:</span>
|
||||||
|
<span v-else>Plays At:</span>
|
||||||
|
<br>
|
||||||
|
<template v-if="song.time_until_song_seconds !== null && song.time_until_song_seconds > 0 && playsIn === true">
|
||||||
|
${ song.time_until_song_seconds.secondsToMMSS() }$
|
||||||
|
</template>
|
||||||
|
<template v-else-if="playsIn === false && song.plays_at !== null && song.played === false">
|
||||||
|
${ song.plays_at.timestampToHHMMSS() }$
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td class="d-sm-table-cell d-none requested-by">
|
<td class="d-sm-table-cell d-none requested-by">
|
||||||
<template v-if="song.user === null">
|
<template v-if="song.user === null">
|
||||||
Marietje
|
Marietje
|
||||||
@ -142,7 +173,7 @@
|
|||||||
<th>Report</th>
|
<th>Report</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="5"><input id="search-all" class="search-input" type="text"
|
<th colspan="5"><input id="search-all" class="search-input" type="text" ref="search_textinput"
|
||||||
v-model="search_input"/></th>
|
v-model="search_input"/></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -248,17 +279,22 @@
|
|||||||
clockInterval: null,
|
clockInterval: null,
|
||||||
started_at: null,
|
started_at: null,
|
||||||
playsIn: true,
|
playsIn: true,
|
||||||
|
songs_show_details_on_mobile: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
playsIn: {
|
playsIn: {
|
||||||
handler(val, oldVal) {
|
handler(val, oldVal) {
|
||||||
this.update_infobar();
|
this.update_infobar();
|
||||||
|
setCookie("PLAYS_IN", this.playsIn, 14);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.clockInterval = setInterval(this.update_song_times, 1000);
|
this.clockInterval = setInterval(this.update_song_times, 1000);
|
||||||
|
|
||||||
|
const stored_playsIn = getCookie("PLAYS_IN");
|
||||||
|
this.playsIn = (stored_playsIn !== "false");
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
clearInterval(this.clockInterval);
|
clearInterval(this.clockInterval);
|
||||||
@ -427,6 +463,19 @@
|
|||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
show_details(song) {
|
||||||
|
return this.songs_show_details_on_mobile.includes(song.id);
|
||||||
|
},
|
||||||
|
toggle_details(song) {
|
||||||
|
if (!this.show_details(song)) {
|
||||||
|
this.songs_show_details_on_mobile.push(song.id);
|
||||||
|
} else {
|
||||||
|
// Deze filter is gehaat door Kees, gemaakt door Olaf. Bedankt, Olaf. Duurde wel even.
|
||||||
|
this.songs_show_details_on_mobile = this.songs_show_details_on_mobile.filter(
|
||||||
|
value => value !== song.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}).mount("#queue-container");
|
}).mount("#queue-container");
|
||||||
</script>
|
</script>
|
||||||
@ -533,6 +582,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
request_song(song_id) {
|
request_song(song_id) {
|
||||||
fetch('/api/v1/queues/current/request/', {
|
fetch('/api/v1/queues/current/request/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -564,6 +614,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
report_song(song_id) {
|
report_song(song_id) {
|
||||||
let message = prompt("What is wrong with the song?");
|
let message = prompt("What is wrong with the song?");
|
||||||
if (message === null) {
|
if (message === null) {
|
||||||
@ -601,9 +652,14 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
update_page(page_number) {
|
update_page(page_number) {
|
||||||
this.page_number = page_number;
|
this.page_number = page_number;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
select_textinput() {
|
||||||
|
this.$refs.search_textinput.select();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}).mount('#request-container');
|
}).mount('#request-container');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
31
resources/entrypoint.sh
Normal file
31
resources/entrypoint.sh
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
touch -a /marietje/log/uwsgi.log
|
||||||
|
touch -a /marietje/log/django.log
|
||||||
|
|
||||||
|
cd /marietje/src/website
|
||||||
|
|
||||||
|
./manage.py migrate --no-input
|
||||||
|
./manage.py collectstatic --no-input
|
||||||
|
|
||||||
|
chown --recursive www-data:www-data /marietje/
|
||||||
|
|
||||||
|
echo "Starting uwsgi server."
|
||||||
|
uwsgi --chdir=/marietje/src/website \
|
||||||
|
--module=marietje.wsgi:application \
|
||||||
|
--master --pidfile=/tmp/project-master.pid \
|
||||||
|
--socket=:8000 \
|
||||||
|
--processes=5 \
|
||||||
|
--uid=www-data --gid=www-data \
|
||||||
|
--harakiri=20 \
|
||||||
|
--post-buffering=16384 \
|
||||||
|
--max-requests=5000 \
|
||||||
|
--thunder-lock \
|
||||||
|
--vacuum \
|
||||||
|
--logfile-chown \
|
||||||
|
--logto2=/marietje/log/uwsgi.log \
|
||||||
|
--ignore-sigpipe \
|
||||||
|
--ignore-write-errors \
|
||||||
|
--disable-write-exception
|
||||||
Reference in New Issue
Block a user