16 Commits

Author SHA1 Message Date
44a1d44cd1 Merge branch 'feature/docker-build' into 'marietje-zuid'
Add Docker build and docker compose file

See merge request technicie/MarietjeDjango!78
2024-03-05 09:32:24 +01:00
2e65d7fd89 Merge branch 'wkuijltjes/searchfield' into 'marietje-zuid'
Auto-select search field in request tab

Closes #42

See merge request technicie/MarietjeDjango!88
2024-02-27 22:37:35 +01:00
521c047225 Auto-select search field in request tab 2024-02-27 22:37:35 +01:00
0a3b2d2a8c Merge branch 'wkuijltjes/streepje' into 'marietje-zuid'
Fix streepje from issue #48

Closes #48

See merge request technicie/MarietjeDjango!84
2024-02-27 21:08:48 +01:00
13448a2eec Merge branch 'fix/remember-song-details-unfold' into 'marietje-zuid'
Keep song details unfolded between refreshes

Closes #79

See merge request technicie/MarietjeDjango!86
2024-02-27 20:56:24 +01:00
fe186ffa99 Merge branch 'feature/remember-plays-at-in' into 'marietje-zuid'
Store plays at/in in cookie

Closes #73

See merge request technicie/MarietjeDjango!87
2024-02-27 20:28:31 +01:00
e30cc33ffc Merge branch 'oslomp/remove_pipeline' into 'marietje-zuid'
disabled deployment pipeline

See merge request technicie/MarietjeDjango!85
2024-02-27 20:20:18 +01:00
4d797691b1 Disable deployment pipeline
It is broken since the migration to the new server.
2024-02-27 20:20:18 +01:00
e45940772f Fix streepje from issue #48 2024-02-27 13:04:01 +01:00
77728c9a82 Replace shift shit with array filter
Co-Authored-By: Olaf Slomp <git@oslomp.nl>
2024-02-27 12:48:52 +01:00
08cd59ce09 Store plays at/in in cookie
Closes #73
2024-02-27 12:16:38 +01:00
ad94fe7930 Keep song details unfolded between refreshes
Closes #79
2024-02-27 12:11:43 +01:00
5acf553269 feat(queue): re-add song details on mobile view
Closes #62
2024-02-21 15:50:20 +01:00
ec66f09a79 Merge branch 'feature/marietje-4.1-in-header' into 'marietje-zuid'
Marietje in header and fix load times for upload page

Adds the Marietje header back into the mobile view. Also fixes an issue
with the upload page loading taking a long time due to a large id3
library.
Finally, this fixes errors running the pipeline: the project name is
changed to the folder name (marietje) and a typo was removed from one
of the maintainer names.

Closes #39, #37, and #44

See merge request technicie/MarietjeDjango!65
2024-02-21 15:42:01 +01:00
4768271aee Marietje in header and fix load times for upload page 2024-02-21 15:40:41 +01:00
3d78ca954f Add Docker build and docker compose file 2023-10-14 11:21:30 +02:00
9 changed files with 221 additions and 46 deletions

4
.dockerignore Normal file
View File

@ -0,0 +1,4 @@
marietje/db.sqlite3
marietje/static
docker-compose.yml.example
docker-compose.yml

View File

@ -16,7 +16,8 @@ black:
script:
- 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
only: ['marietje-zuid']
before_script:

26
Dockerfile Normal file
View 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/

View 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

View 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"))

View File

@ -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)

View File

@ -53,18 +53,6 @@ button[type="button"] i {
min-width: 90px;
}
.song-info {
position: absolute;
padding: 8px;
background: silver;
white-space: nowrap;
z-index: 1;
}
#queue-time-header {
cursor: pointer;
}
footer {
text-align: center;
}
@ -98,7 +86,7 @@ footer {
border-top: 3px double var(--text-color);
}
tr.requested_song{
.ownsong {
border-left: 1px solid var(--text-color);
}

View File

@ -13,7 +13,7 @@
</button>
</li>
<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
</button>
</li>
@ -78,19 +78,50 @@
<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-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>
</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>
</thead>
<tbody class="queuebody">
<template v-for="(song, index) in queue">
<tr :class="{ marietjequeue: (song.user === null),
underline_cell: (index === queue[-1]),
currentsong: (index === 0),}">
<td class="artist">${ song.song.artist }$</td>
<td class="title">${ song.song.title }$</td>
underline_cell: (index === queue[-1]),
currentsong: (index === 0),
ownsong: (this.user_data.id === song.user?.id && index !== 0),
}"
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">
<template v-if="song.user === null">
Marietje
@ -142,7 +173,7 @@
<th>Report</th>
</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>
</tr>
</thead>
@ -248,17 +279,22 @@
clockInterval: null,
started_at: null,
playsIn: true,
songs_show_details_on_mobile: [],
}
},
watch: {
playsIn: {
handler(val, oldVal) {
this.update_infobar();
setCookie("PLAYS_IN", this.playsIn, 14);
}
},
},
mounted() {
this.clockInterval = setInterval(this.update_song_times, 1000);
const stored_playsIn = getCookie("PLAYS_IN");
this.playsIn = (stored_playsIn !== "false");
},
unmounted() {
clearInterval(this.clockInterval);
@ -427,6 +463,19 @@
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");
</script>
@ -533,6 +582,7 @@
}
});
},
request_song(song_id) {
fetch('/api/v1/queues/current/request/', {
method: 'POST',
@ -564,6 +614,7 @@
}
});
},
report_song(song_id) {
let message = prompt("What is wrong with the song?");
if (message === null) {
@ -601,9 +652,14 @@
}
});
},
update_page(page_number) {
this.page_number = page_number;
}
},
select_textinput() {
this.$refs.search_textinput.select();
},
}
}).mount('#request-container');
</script>

31
resources/entrypoint.sh Normal file
View 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