mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-02-26 01:14:50 +01:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3fcd5fe7e | ||
|
|
b0a3acbdde | ||
|
|
33ce38d74c | ||
|
|
fa51a7fef9 | ||
|
|
d7c072a35c | ||
|
|
c88a6dcf3a | ||
|
|
fcb54a0af2 | ||
|
|
eec2ced481 | ||
|
|
58a6048857 | ||
|
|
93774cca64 | ||
|
|
679f49badc | ||
|
|
b535a12014 | ||
|
|
72876bff43 | ||
|
|
4411022027 | ||
|
|
086210b39d | ||
|
|
73cb2d861b | ||
|
|
1c479ef85a | ||
|
|
51b2b11825 | ||
|
|
414a9bb88a | ||
|
|
f6d1a42b35 | ||
|
|
eb25f8aeb3 | ||
|
|
2ee64a534e | ||
|
|
14073d3555 |
@@ -9,7 +9,6 @@ SECRET_KEY=<GENERATE A SAFE SECRET KEY AND PLACE IT HERE>
|
||||
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
|
||||
OUTBOUND_PORT=9005
|
||||
|
||||
SQL_ENGINE=django.db.backends.postgresql
|
||||
SQL_DATABASE=wygiwyh
|
||||
SQL_USER=wygiwyh
|
||||
SQL_PASSWORD=<INSERT A SAFE PASSWORD HERE>
|
||||
|
||||
25
README.md
25
README.md
@@ -95,31 +95,14 @@ You can now access localhost:OUTBOUND_PORT
|
||||
> [!NOTE]
|
||||
> If you're going to use another IP that isn't localhost, add it to `DJANGO_ALLOWED_HOSTS`, without `http://`
|
||||
|
||||
|
||||
## Building from source
|
||||
Features are only added to main when ready, if you want to run the latest version, you must build from source.
|
||||
|
||||
Features are only added to `main` when ready, if you want to run the latest version, you must build from source.
|
||||
All the required Dockerfiles are [here](https://github.com/eitchtee/WYGIWYH/tree/main/docker/prod).
|
||||
|
||||
```bash
|
||||
# Create a folder for WYGIWYH (optional)
|
||||
$ mkdir WYGIWYH
|
||||
## Unraid
|
||||
|
||||
# Go into the folder
|
||||
$ cd WYGIWYH
|
||||
|
||||
# Clone this repository
|
||||
$ git clone https://github.com/eitchtee/WYGIWYH.git .
|
||||
|
||||
$ cp docker-compose.prod.yml docker-compose.yml
|
||||
$ cp .env.example .env
|
||||
# Now edit both files as you see fit
|
||||
|
||||
# Run the app
|
||||
$ docker compose up -d --build
|
||||
|
||||
# Create the first admin account
|
||||
$ docker compose exec -it web python manage.py createsuperuser
|
||||
```
|
||||
[nwithan8](https://github.com/nwithan8) has kindly provided a Unraid template for WYGIWYH, have a look at the [unraid_templates](https://github.com/nwithan8/unraid_templates) repo.
|
||||
|
||||
# How it works
|
||||
|
||||
|
||||
@@ -126,12 +126,12 @@ WSGI_APPLICATION = "WYGIWYH.wsgi.application"
|
||||
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
|
||||
"NAME": os.environ.get("SQL_DATABASE", BASE_DIR / "db.sqlite3"),
|
||||
"ENGINE": "django.db.backends.postgresql",
|
||||
"NAME": os.environ.get("SQL_DATABASE"),
|
||||
"USER": os.environ.get("SQL_USER", "user"),
|
||||
"PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
|
||||
"HOST": os.environ.get("SQL_HOST", "localhost"),
|
||||
"PORT": "5432",
|
||||
"PORT": os.environ.get("SQL_PORT", "5432"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ AUTH_USER_MODEL = "users.User"
|
||||
LANGUAGE_CODE = "en"
|
||||
LANGUAGES = (
|
||||
("en", "English"),
|
||||
# ("nl", "Nederlands"),
|
||||
("nl", "Nederlands"),
|
||||
("pt-br", "Português (Brasil)"),
|
||||
)
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ def django_to_python_datetime(django_format):
|
||||
def django_to_airdatepicker_datetime(django_format):
|
||||
format_map = {
|
||||
# Time
|
||||
"h": "h", # Hour (12-hour)
|
||||
"h": "hh", # Hour (12-hour)
|
||||
"H": "H", # Hour (24-hour)
|
||||
"i": "m", # Minutes
|
||||
"A": "AA", # AM/PM uppercase
|
||||
@@ -76,7 +76,7 @@ def django_to_airdatepicker_datetime(django_format):
|
||||
def django_to_airdatepicker_datetime_separated(django_format):
|
||||
format_map = {
|
||||
# Time formats
|
||||
"h": "hH", # Hour (12-hour)
|
||||
"h": "hh", # Hour (12-hour)
|
||||
"H": "HH", # Hour (24-hour)
|
||||
"i": "mm", # Minutes
|
||||
"A": "AA", # AM/PM uppercase
|
||||
|
||||
@@ -148,9 +148,14 @@ class AirDateTimePickerInput(widgets.DateTimeInput):
|
||||
|
||||
def format_value(self, value):
|
||||
"""Format the value for display in the widget."""
|
||||
if value:
|
||||
if value and isinstance(value, (datetime.date, datetime.datetime)):
|
||||
self.attrs["data-value"] = datetime.datetime.strftime(
|
||||
value, "%Y-%m-%d %H:%M:00"
|
||||
value, "%Y-%m-%dT%H:%M:00"
|
||||
)
|
||||
elif value and isinstance(value, str):
|
||||
value = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:00")
|
||||
self.attrs["data-value"] = datetime.datetime.strftime(
|
||||
value, "%Y-%m-%dT%H:%M:00"
|
||||
)
|
||||
|
||||
if value is None:
|
||||
@@ -195,6 +200,7 @@ class AirMonthYearPickerInput(AirDatePickerInput):
|
||||
|
||||
# Add data attributes for AirDatepicker configuration
|
||||
attrs["data-now-button-txt"] = _("Today")
|
||||
attrs["data-date-format"] = "MMMM yyyy"
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
@@ -72,7 +72,9 @@ class ExchangeRate(models.Model):
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
if self.from_currency == self.to_currency:
|
||||
raise ValidationError(
|
||||
{"to_currency": _("From and To currencies cannot be the same.")}
|
||||
)
|
||||
# Check if the attributes exist before comparing them
|
||||
if hasattr(self, "from_currency") and hasattr(self, "to_currency"):
|
||||
if self.from_currency == self.to_currency:
|
||||
raise ValidationError(
|
||||
{"to_currency": _("From and To currencies cannot be the same.")}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.5 on 2025-01-25 18:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0015_alter_usersettings_language'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='usersettings',
|
||||
name='language',
|
||||
field=models.CharField(choices=[('auto', 'Auto'), ('en', 'English'), ('nl', 'Nederlands'), ('pt-br', 'Português (Brasil)')], default='auto', max_length=10, verbose_name='Language'),
|
||||
),
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,16 @@
|
||||
<div class="tw-sticky tw-bottom-4 tw-left-0 tw-right-0 tw-z-50 tw-hidden mx-auto tw-w-fit" id="actions-bar"
|
||||
_="on change from #transactions-list or htmx:afterSettle from window
|
||||
if no <input[type='checkbox']:checked/> in #transactions-list
|
||||
add .slide-in-bottom-reverse then settle
|
||||
then add .tw-hidden to #actions-bar
|
||||
then remove .slide-in-bottom-reverse
|
||||
if #actions-bar
|
||||
add .slide-in-bottom-reverse then settle
|
||||
then add .tw-hidden to #actions-bar
|
||||
then remove .slide-in-bottom-reverse
|
||||
end
|
||||
else
|
||||
remove .tw-hidden from #actions-bar
|
||||
then trigger selected_transactions_updated
|
||||
if #actions-bar
|
||||
remove .tw-hidden from #actions-bar
|
||||
then trigger selected_transactions_updated
|
||||
end
|
||||
end
|
||||
end">
|
||||
<div class="card slide-in-bottom">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.11-slim-buster AS python-build-stage
|
||||
FROM python:3.11-slim-bookworm AS python-build-stage
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
build-essential \
|
||||
@@ -8,7 +8,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
COPY ../requirements.txt .
|
||||
RUN pip wheel --wheel-dir /usr/src/app/wheels -r requirements.txt
|
||||
|
||||
FROM python:3.11-slim-buster AS python-run-stage
|
||||
FROM python:3.11-slim-bookworm AS python-run-stage
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.11-slim-buster AS python-build-stage
|
||||
FROM python:3.11-slim-bookworm AS python-build-stage
|
||||
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
build-essential \
|
||||
@@ -17,7 +17,7 @@ RUN --mount=type=cache,target=/root/.npm \
|
||||
npm install --verbose && \
|
||||
npm run build
|
||||
|
||||
FROM python:3.11-slim-buster AS python-run-stage
|
||||
FROM python:3.11-slim-bookworm AS python-run-stage
|
||||
COPY --from=webpack_build /usr/src/frontend/build /usr/src/frontend/build
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import AirDatepicker from 'air-datepicker';
|
||||
import en from 'air-datepicker/locale/en';
|
||||
import ptBr from 'air-datepicker/locale/pt-BR';
|
||||
import nl from 'air-datepicker/locale/nl';
|
||||
import {createPopper} from '@popperjs/core';
|
||||
|
||||
const locales = {
|
||||
'pt': ptBr,
|
||||
'en': en
|
||||
'en': en,
|
||||
'nl': nl
|
||||
};
|
||||
|
||||
function isMobileDevice() {
|
||||
@@ -161,8 +163,8 @@ window.MonthYearPicker = function createDynamicDatePicker(element) {
|
||||
let opts = {...baseOpts, ...positionConfig};
|
||||
|
||||
if (element.dataset.value) {
|
||||
opts["selectedDates"] = [element.dataset.value];
|
||||
opts["startDate"] = [element.dataset.value];
|
||||
opts["selectedDates"] = [new Date(element.dataset.value + "T00:00:00")];
|
||||
opts["startDate"] = [new Date(element.dataset.value + "T00:00:00")];
|
||||
}
|
||||
return new AirDatepicker(element, opts);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user