Compare commits
10 Commits
0bbe9d9fd9
...
5efcee12a9
Author | SHA1 | Date | |
---|---|---|---|
5efcee12a9 | |||
b838c79cdb | |||
e8abfaf51b | |||
55711d68c1 | |||
2b539a45d2 | |||
2895d295e4 | |||
74d7564bdc | |||
0d164a1f31 | |||
2395bc215d | |||
9a7ce60913 |
@ -1,6 +1,7 @@
|
|||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
||||||
RUN apk --no-cache add python3 inkscape bash imagemagick ttf-opensans
|
RUN apk --no-cache add python3 inkscape bash imagemagick ttf-opensans
|
||||||
|
RUN apk --no-cache add py3-pip && pip3 install django tzdata gunicorn
|
||||||
|
|
||||||
ADD backend /root/zetikettes
|
ADD backend /root/zetikettes
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ RUN mkdir -p /usr/share/fonts/TTF \
|
|||||||
&& cp /root/zetikettes/fonts/*.ttf /usr/share/fonts/TTF/ \
|
&& cp /root/zetikettes/fonts/*.ttf /usr/share/fonts/TTF/ \
|
||||||
&& fc-cache -fv
|
&& fc-cache -fv
|
||||||
|
|
||||||
|
|
||||||
# the script will look for templates in /data
|
# the script will look for templates in /data
|
||||||
WORKDIR /root/zetikettes
|
WORKDIR /root/zetikettes/zetikettes
|
||||||
CMD /usr/bin/python3 web.py
|
CMD /usr/bin/gunicorn zetikettes.wsgi -b 0.0.0.0:8000 --timeout 600
|
||||||
|
22
README.md
22
README.md
@ -21,7 +21,7 @@ Test
|
|||||||
----
|
----
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run --rm -it -v $PWD/templates:/data zetikettes /bin/bash /root/zetikettes/mkjam.sh
|
docker run --rm -it -v $PWD/templates:/data zetikettes /bin/bash /root/zetikettes/old/mkjam.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This should produce a .pdf in `templates/`. Open it to check that
|
This should produce a .pdf in `templates/`. Open it to check that
|
||||||
@ -34,10 +34,28 @@ Run
|
|||||||
docker run -d --rm -p 127.0.0.1:8000:8000 -v /var/lib/zetikettes/templates:/data zetikettes
|
docker run -d --rm -p 127.0.0.1:8000:8000 -v /var/lib/zetikettes/templates:/data zetikettes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Notes for deploying
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.h3 Initialize empty database
|
||||||
|
```
|
||||||
|
python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
.h3 Prepare static files
|
||||||
|
```
|
||||||
|
python manage.py collectstatic
|
||||||
|
```
|
||||||
|
The files will be in `www_static/` and need to be moved to `/var/lib/zetikettes/www_static`
|
||||||
|
|
||||||
|
.h3 Change host settings
|
||||||
|
If not deploying on `aerith.ponteilla.net`, you'll need to edit `backend/zetikettes/zetikettes/settings.py` to change a couple things in there.
|
||||||
|
|
||||||
|
|
||||||
Change available templates
|
Change available templates
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
1. go to /zetikettes/newtikette.html or konami code from main app
|
1. go to /zetikettes/admin
|
||||||
1. add the newtikette
|
1. add the newtikette
|
||||||
1. still no need to restart the container (magic!)
|
1. still no need to restart the container (magic!)
|
||||||
2. profit.
|
2. profit.
|
||||||
|
51
backend/zetikettes/tikette/migrations/0001_initial.py
Normal file
51
backend/zetikettes/tikette/migrations/0001_initial.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Generated by Django 4.2.2 on 2023-07-03 14:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tikategory',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=50)),
|
||||||
|
('landscape', models.BooleanField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name_plural': 'tikategoriez',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tisub',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=50)),
|
||||||
|
('descritpion', models.TextField()),
|
||||||
|
('default', models.TextField()),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name_plural': 'tisubz',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tikette',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('title', models.CharField(max_length=100)),
|
||||||
|
('svg', models.FileField(upload_to='')),
|
||||||
|
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tikette.tikategory')),
|
||||||
|
('subs', models.ManyToManyField(to='tikette.tisub')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name_plural': 'tikettz',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -1,16 +1,5 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
class Tikategory(models.Model):
|
|
||||||
name = models.CharField(max_length=50)
|
|
||||||
landscape = models.BooleanField()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name_plural = "tikategoriez"
|
|
||||||
|
|
||||||
|
|
||||||
class Tisub(models.Model):
|
class Tisub(models.Model):
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
descritpion = models.TextField()
|
descritpion = models.TextField()
|
||||||
@ -23,11 +12,22 @@ class Tisub(models.Model):
|
|||||||
verbose_name_plural = "tisubz"
|
verbose_name_plural = "tisubz"
|
||||||
|
|
||||||
|
|
||||||
|
class Tikategory(models.Model):
|
||||||
|
name = models.CharField(max_length=50)
|
||||||
|
landscape = models.BooleanField()
|
||||||
|
subs = models.ManyToManyField(Tisub)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name_plural = "tikategoriez"
|
||||||
|
|
||||||
|
|
||||||
class Tikette(models.Model):
|
class Tikette(models.Model):
|
||||||
title = models.CharField(max_length=100)
|
title = models.CharField(max_length=100)
|
||||||
category = models.ForeignKey(Tikategory, on_delete=models.CASCADE)
|
category = models.ForeignKey(Tikategory, on_delete=models.CASCADE)
|
||||||
svg = models.FileField()
|
svg = models.FileField()
|
||||||
subs = models.ManyToManyField(Tisub)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
@ -16,7 +16,7 @@ def index(request):
|
|||||||
'category': x.category.name,
|
'category': x.category.name,
|
||||||
'sticker': x.svg.name,
|
'sticker': x.svg.name,
|
||||||
'landscape': x.category.landscape,
|
'landscape': x.category.landscape,
|
||||||
'subs': {x.name: x.default for x in x.subs.all()},
|
'subs': {x.name: x.default for x in x.category.subs.all()},
|
||||||
} for x in Tikette.objects.all()]
|
} for x in Tikette.objects.all()]
|
||||||
return JsonResponse({'status': 'ok', 'tikettes': tikettes}, headers=CORS)
|
return JsonResponse({'status': 'ok', 'tikettes': tikettes}, headers=CORS)
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
#TIKETTE_OUT_DIR = BASE_DIR / 'data'
|
#TIKETTE_OUT_DIR = BASE_DIR / 'data'
|
||||||
TIKETTE_OUT_DIR = Path('/data')
|
TIKETTE_OUT_DIR = Path('/data')
|
||||||
MEDIA_ROOT = TIKETTE_OUT_DIR
|
MEDIA_ROOT = TIKETTE_OUT_DIR
|
||||||
MEDIA_URL = 'data/'
|
MEDIA_URL = '/data/'
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
@ -29,7 +29,8 @@ SECRET_KEY = 'django-insecure-64qxpe55#9wy=5@#dl0)3w7ywxh48m!f&!slp9e7v4lh@hjdct
|
|||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = ['*']
|
||||||
|
CSRF_TRUSTED_ORIGINS = ['https://*.ponteilla.net']
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
@ -81,7 +82,7 @@ WSGI_APPLICATION = 'zetikettes.wsgi.application'
|
|||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
'NAME': TIKETTE_OUT_DIR / 'db.sqlite3',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +123,8 @@ USE_TZ = True
|
|||||||
|
|
||||||
STATIC_URL = 'static/'
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
STATIC_ROOT = 'www_static'
|
||||||
|
|
||||||
# Default primary key field type
|
# Default primary key field type
|
||||||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ function loadAll(zetikettes) {
|
|||||||
$.post(backend_api, JSON.stringify(req))
|
$.post(backend_api, JSON.stringify(req))
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
const pdfbtn = $(`<a class="btn" href="${backend_api}/data/${data.file}" target="_blank">open pdf</a>`);
|
const pdfbtn = $(`<a class="btn" href="${backend_api}data/${data.file}" target="_blank">open pdf</a>`);
|
||||||
action.append(pdfbtn);
|
action.append(pdfbtn);
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
@ -67,7 +67,7 @@ function konami() {
|
|||||||
$(document).keydown(function (e) {
|
$(document).keydown(function (e) {
|
||||||
if (e.keyCode === k[n++]) {
|
if (e.keyCode === k[n++]) {
|
||||||
if (n === k.length) {
|
if (n === k.length) {
|
||||||
document.location.href = 'newtikette.html';
|
document.location.href = backend_api + 'admin';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -82,7 +82,7 @@ $(document).ready(async () => {
|
|||||||
url: backend_api + 'list',
|
url: backend_api + 'list',
|
||||||
timeout: 1000,
|
timeout: 1000,
|
||||||
});
|
});
|
||||||
loadAll(resp.tikettes);
|
loadAll(resp.tikettes.sort((a, b) => (a.title < b.title) ? -1 : 1));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
const appbody = $("#appbody");
|
const appbody = $("#appbody");
|
||||||
appbody.append(`<li>Could not reach backend server`);
|
appbody.append(`<li>Could not reach backend server`);
|
||||||
|
18
nginx_locations
Normal file
18
nginx_locations
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# prod site
|
||||||
|
location /zetikettes {
|
||||||
|
alias /var/lib/zetikettes/frontend;
|
||||||
|
}
|
||||||
|
location /zetikettes/srv/static {
|
||||||
|
alias /var/lib/zetikettes/www_static;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /zetikettes/srv {
|
||||||
|
proxy_pass http://127.0.0.1:8000;
|
||||||
|
proxy_set_header SCRIPT_NAME /zetikettes/srv;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
|
||||||
|
# generating stuff takes time
|
||||||
|
proxy_read_timeout 10m;
|
||||||
|
|
||||||
|
client_max_body_size 10M;
|
||||||
|
}
|
16
zetikettes.service
Normal file
16
zetikettes.service
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Zetikettes backend service
|
||||||
|
After=docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/docker run --rm --name %n \
|
||||||
|
-p 127.0.0.1:8000:8000 \
|
||||||
|
-v /var/lib/zetikettes/data:/data \
|
||||||
|
zetikettes
|
||||||
|
Restart=on-failure
|
||||||
|
ExecStartPre=-/usr/bin/docker exec %n stop
|
||||||
|
ExecStartPre=-/usr/bin/docker rm %n
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
Loading…
Reference in New Issue
Block a user