16 Commits

Author SHA1 Message Date
coja
732640cf90 [Page] language change fix 2026-05-03 03:18:29 +02:00
coja
a3193cb498 [Page] statute strange unicodes 2026-05-03 01:23:39 +02:00
coja
1c0be34ecf [Page] syntax fixes and formating 2026-05-03 01:18:16 +02:00
coja
629c5b02bf [Page] deconference 2026-05-03 00:59:18 +02:00
coja
b1f8b7a378 [Makefile] revert 2026-05-03 00:56:13 +02:00
coja
599d143c78 [Jinja2] lang btn and cleanup 2026-05-03 00:55:31 +02:00
coja
0724816c88 [Jinja2] init 2026-05-02 23:18:51 +02:00
coja
9eca59f80f [Doc] csv check 2026-05-02 05:05:26 +02:00
coja
c3ae746d83 [Doc] update 2026-05-02 04:49:06 +02:00
coja
a66da9b2d5 [Page] statute update 2026-05-02 04:17:07 +02:00
coja
e9147b34cb [Page] support monero wallet removed 2026-05-02 04:03:12 +02:00
coja
02c2dcc9fc [CSV] parsing csv with DictReader instead 2026-05-02 04:00:17 +02:00
coja
749574c8dc [Doc] cleanup 2026-05-02 03:58:58 +02:00
coja
c40f101540 [JS] Wrapped everything to DOM Loaded 2026-05-02 03:56:03 +02:00
coja
5958bbc24f [Doc] readme update for makefile 2026-05-02 03:45:29 +02:00
coja
d9c93d1182 [Makefile] init 2026-05-02 03:44:52 +02:00
31 changed files with 913 additions and 539 deletions

31
Makefile Normal file
View File

@@ -0,0 +1,31 @@
.PHONY: build events dev stop help prep
help:
@echo "Available commands:"
@echo " make prep - Create venv and install requirements"
@echo " make events - Update site from CSV (build pages + images)"
@echo " make dev - Start development server"
@echo " make stop - Stop development server"
@echo " make build - Full website build sequence"
@echo " make help - Show this help message"
prep:
python3 -m venv .venv
./.venv/bin/pip install --upgrade pip
./.venv/bin/pip install -r requirements.txt
build:
./.venv/bin/python atom_gen.py
./.venv/bin/python prep.py
./.venv/bin/python build_pages.py
events:
./.venv/bin/python build_pages.py
./.venv/bin/python image_poster.py
dev:
nginx -p . -c nginx.dev.conf
stop:
nginx -p . -s stop

View File

@@ -1,40 +1,50 @@
# Decentrala
dmz.rs/decentrala.org website
[dmz.rs](https://dmz.rs/) / [decentrala.org](https://decentrala.org) website
## Setup
First, prepare the virtual environment and install dependencies:
```sh
make prep
```
## Build site
Run
To build the complete website:
```sh
python atom_gen.py
python prep.py
python build_pages.py
make build
```
Complete website will be contained in `site/`. You can copy this to server.
The complete website will be contained in `site/`. You can copy this to your server.
## Development server
To start a development server, first build site, then run (possibly with `sudo`)
To start a development server, first build the site, then run (possibly with `sudo`):
```sh
nginx -p . -c nginx.dev.conf
make dev
```
To stop it:
```sh
nginx -p . -s stop
make stop
```
## Events
To update events, update the `events.csv` then run commands
To update events, update `dogadjaji.csv` then run:
```sh
python build_pages.py # builds html out of csv
python image_poster.py # generates images for events
make events
```
For checking the csv data, suggestion is the [tennis pkg](https://github.com/gurgeous/tennis), with example command:
```sh
tennis -nt --zebra --color on --theme dark --tail 20 dogadjaji.csv
```

View File

@@ -1,4 +1,4 @@
#! /usr/bin/env python3
from jinja2 import Environment, FileSystemLoader
import os
PAGES = [
@@ -14,34 +14,47 @@ PAGES = [
{'name': 'deconference', 'titleSR': 'Dekonferencija', 'titleEN': 'Deconference', 'style': 'deconference'},
]
def buildPage(filename: str, pageTitle: str, pageHtml: str, pageStyle: str, template: str) -> str:
template = template.replace('<!--TITLE-->', pageTitle)
style = '' if not pageStyle else f'<link rel=\"stylesheet\" href=\"/styles/{pageStyle}.css\">'
template = template.replace('<!--ADDITIONAL_STYLE-->', style)
template = template.replace('PAGE_NAME', filename)
template = template.replace('<!--MAIN-->', pageHtml)
return template
env = Environment(loader=FileSystemLoader('template'))
def main():
os.makedirs('site/en/', exist_ok=True)
with open('template/page-en.html') as fTempEN, open('template/page-sr.html') as fTempSR:
templateSR = fTempSR.read()
templateEN = fTempEN.read()
for page in PAGES:
with open(f'pages/sr/{page["name"]}.html') as f:
pageHtml = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Studenti su nasli bug' /></div>"
pageHtml += f.read()
html = buildPage(page['name'], page['titleSR'], pageHtml, page['style'], templateSR)
f = open(f'site/{page["name"]}.html', 'w')
f.write(html)
f.close()
with open(f'pages/en/{page["name"]}.html') as f:
pageHtml = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Students found the bug' /></div>"
pageHtml += f.read()
html = buildPage(page['name'], page['titleEN'], pageHtml, page['style'], templateEN)
f = open(f'site/en/{page["name"]}.html', 'w')
f.write(html)
f.close()
for page in PAGES:
# Build SR Page
with open(f'pages/sr/{page["name"]}.html') as f:
page_content = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Studenti su nasli bug' /></div>"
page_content += f.read()
sr_html = env.get_template('page-sr.html').render(
title=page['titleSR'],
content=page_content,
extra_styles=f'<link rel="stylesheet" href="/styles/{page["style"]}.css">' if page['style'] else '',
lang="sr",
sr_link=f"/en/{page['name']}",
current_path=f"/{page['name']}" if page['name'] != 'index' else "/"
)
sr_filename = "index.html" if page['name'] == 'index' else f"{page['name']}.html"
with open(f'site/{sr_filename}', 'w') as f:
f.write(sr_html)
# Build EN Page
with open(f'pages/en/{page["name"]}.html') as f:
page_content = "<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Students found the bug' /></div>"
page_content += f.read()
en_html = env.get_template('page-en.html').render(
title=page['titleEN'],
content=page_content,
extra_styles=f'<link rel="stylesheet" href="/styles/{page["style"]}.css">' if page['style'] else '',
lang="en",
sr_link=f"/{page['name']}",
current_path=f"/en/{page['name']}" if page['name'] != 'index' else "/en/"
)
en_filename = "index.html" if page['name'] == 'index' else f"{page['name']}.html"
with open(f'site/en/{en_filename}', 'w') as f:
f.write(en_html)
if __name__ == '__main__':
main()

View File

@@ -1,4 +1,4 @@
datum, vreme, lokacija, tema, tip, link, temaE
datum, vreme, lokacija, tema, tip, link, temaEN
20-12-2022, 19:00, DC Krov https://www.openstreetmap.org/node/10594728522, Uvod u računarske mreže,,,
03-01-2023, 19:00, DC Krov https://www.openstreetmap.org/node/10594728522, Hackathon žurka, hack,,
16-01-2023, 19:00, DC Krov https://www.openstreetmap.org/node/10594728522, Privatnost na internetu, workshop,,
1 datum vreme lokacija tema tip link temaE temaEN
2 20-12-2022 19:00 DC Krov https://www.openstreetmap.org/node/10594728522 Uvod u računarske mreže
3 03-01-2023 19:00 DC Krov https://www.openstreetmap.org/node/10594728522 Hackathon žurka hack
4 16-01-2023 19:00 DC Krov https://www.openstreetmap.org/node/10594728522 Privatnost na internetu workshop

View File

@@ -1,12 +1,17 @@
<h1>About us</h1>
<dl>
<dt>Statute:</dt>
<dd> We make decisions by direct democracy. Our statute can be found at <a href="/en/statute"> statute page</a></dd>
<dd>
We make decisions by direct democracy. Our statute can be found at
<a href="/en/statute"> statute page</a>
</dd>
<dt>Contact:</dt>
<dd>
You can send mail to <a href="mailto:dmz@dmz.rs">dmz@dmz.rs</a> or you can register on <a href="https://forum.dmz.rs">our Forum</a>.
Also, we are available on the <a href="https://balkan.fedive.rs/@decentrala">Fediverse!</a>
You can send mail to <a href="mailto:dmz@dmz.rs">dmz@dmz.rs</a> or you can
register on <a href="https://forum.dmz.rs">our Forum</a>. Also, we are
available on the
<a href="https://balkan.fedive.rs/@decentrala">Fediverse!</a>
If you find a bug on the site, please do tell us. We would be very grateful.
</dd>
</dl>

View File

@@ -14,10 +14,13 @@
</p>
<div class="auth-wrap">
<p><a href="/account/register/">Register</a></p>
<p></p>
<p><a href="/account/unregister/">Delete account</a></p>
<p></p>
<p><a href="/account/changepassword/">Change password</a></p>
<p></p>
<p>
<a href="/account/register/">Register</a>
</p>
<p>
<a href="/account/unregister/">Delete account</a>
</p>
<p>
<a href="/account/changepassword/">Change password</a>
</p>
</div>

View File

@@ -1,2 +1,2 @@
Ova stranica je trenutno u izradi...

View File

@@ -1,34 +1,95 @@
<h1>Deconference</h1>
<h2 id="program"><a href="#program">Program</a></h2>
<p>11:00 Otvaranje<p>
<p>12:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty">Cryptoparty</a><p>
<p>14:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/hakaton">Hakaton</a><p>
<p>16:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/lightningtalks">Lightning talks</a><p>
<p>18:00 Diskusije<p>
<p>20:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty">Cryptoparty</a><p>
<p>22:00 Kraj<p>
<p>11:00 Otvaranje</p>
<p></p>
<p>
12:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty"
>Cryptoparty</a
>
</p>
<p></p>
<p>
14:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/hakaton">Hakaton</a>
</p>
<p></p>
<p>
16:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/lightningtalks"
>Lightning talks</a
>
</p>
<p></p>
<p>18:00 Diskusije</p>
<p></p>
<p>
20:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty"
>Cryptoparty</a
>
</p>
<p></p>
<p>22:00 Kraj</p>
<p></p>
<h2 id="what"><a href="#what">What?</a></h2>
<p>Deconference is the inaugural conference organized by <a href="https://dmz.rs">Decentrala</a>, a Belgrade hackerspace. It serves as a platform for individuals to present and discuss ideas related to decentralization in all its forms.</p>
<p>
Deconference is the inaugural conference organized by
<a href="https://dmz.rs">Decentrala</a>, a Belgrade hackerspace. It serves as
a platform for individuals to present and discuss ideas related to
decentralization in all its forms.
</p>
<h2 id="when-and-where"><a href="#when-and-where">When & Where?</a></h2>
<p>Deconference will take place all day on Sunday, September 15, 2024, at Cultural Center Magacin, located at <a href="https://osm.org/go/xf3Fz31te?node=1226456745">Kraljevića Marka 4-8, Belgrade</a>. The evening prior, a social gathering will be hosted at <a href="https://dckrov.rs/">Community Center Krov</a>, located at <a href="https://osm.org/go/xf3HQQdIH">Kraljice Marije 47, Belgrade</a>.</p>
<p>
Deconference will take place all day on Sunday, September 15, 2024, at
Cultural Center Magacin, located at
<a href="https://osm.org/go/xf3Fz31te?node=1226456745"
>Kraljevića Marka 4-8, Belgrade</a
>. The evening prior, a social gathering will be hosted at
<a href="https://dckrov.rs/">Community Center Krov</a>, located at
<a href="https://osm.org/go/xf3HQQdIH">Kraljice Marije 47, Belgrade</a>.
</p>
<h2 id="why"><a href="#why">Why?</a></h2>
<p>Decentrala was founded by a small group of enthusiasts united by the idea of technological decentralization. Over the past year and a half, we've organized over 160 events—lectures, workshops, discussions, hackathons—aimed at democratizing technological knowledge and educating people about privacy, open source principles, the right to repair (and how to repair), digital assets, and usage rights. Since day one, our approach has been to inform individuals about alternatives rather than impose opinions upon them.</p>
<p>
Decentrala was founded by a small group of enthusiasts united by the idea of
technological decentralization. Over the past year and a half, we've organized
over 160 events—lectures, workshops, discussions, hackathons—aimed at
democratizing technological knowledge and educating people about privacy, open
source principles, the right to repair (and how to repair), digital assets,
and usage rights. Since day one, our approach has been to inform individuals
about alternatives rather than impose opinions upon them.
</p>
<p>Through engaging with diverse visitors, many from non-technical backgrounds, we've come to realize that decentralization encompasses more than just "open technology." Many activists and organizations today advocate for various forms of decentralization. Therefore, we welcome stories about decentralization from diverse perspectives.</p>
<p>
Through engaging with diverse visitors, many from non-technical backgrounds,
we've come to realize that decentralization encompasses more than just "open
technology." Many activists and organizations today advocate for various forms
of decentralization. Therefore, we welcome stories about decentralization from
diverse perspectives.
</p>
<h2 id="who"><a href="#who">Who?</a></h2>
<p>Deconference is an open platform for anyone interested in discussing, demonstrating, or exploring decentralization. You can register your event by emailing <a href="mailto:dekonferencija@dmz.rs">dekonferencija@dmz.rs</a> up until the day of the Deconference (September 15).</p>
<p>
Deconference is an open platform for anyone interested in discussing,
demonstrating, or exploring decentralization. You can register your event by
emailing <a href="mailto:dekonferencija@dmz.rs">dekonferencija@dmz.rs</a> up
until the day of the Deconference (September 15).
</p>
<p>We will update this section as topics are confirmed.</p>
<h2 id="how"><a href="#how">How?</a></h2>
<p>The Deconference is funded by the organizers' private assets. Like all of Decentrala's activities, Deconference is free for all attendees. Unfortunately, we are unable to provide grants to lecturers or presenters.</p>
<p>
The Deconference is funded by the organizers' private assets. Like all of
Decentrala's activities, Deconference is free for all attendees.
Unfortunately, we are unable to provide grants to lecturers or presenters.
</p>
<p>Decentrala accepts donations exclusively from individuals.</p>

View File

@@ -1,27 +1,68 @@
<h1>Welcome!</h1>
<p>
We are <em>Decentrala</em> - a group of enthusiasts gathered around the idea of decentralization and knowledge sharing.
Here are some more facts about us:
We are <em>Decentrala</em> - a group of enthusiasts gathered around the idea
of decentralization and knowledge sharing. Here are some more facts about us:
</p>
<dl>
<dt>Motivation:</dt>
<dd>Decentralization promotes <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#odrzivost">sustainability</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#dostupnost">availability</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#pristupacnost">accesibility</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#nezavisnost">autonomy</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#privatnost">privacy</a> and <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#sloboda">freedom</a>. On those networks we have less <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#manipulacija">manipulation</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#propaganda">propaganda</a>, ads, and <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#neopterecenost-paznje-sporednim-stvarima">are not designed to lock your attention (dumbing down)</a>.
<a href="https://forum.dmz.rs/t/zasto-nam-je-decentralizacija-bitna/506/1">Tell us why decentralization is important to you</a>
<dd>
Decentralization promotes
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#odrzivost"
>sustainability</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#dostupnost"
>availability</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#pristupacnost"
>accesibility</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#nezavisnost"
>autonomy</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#privatnost"
>privacy</a
>
and
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#sloboda"
>freedom</a
>. On those networks we have less
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#manipulacija"
>manipulation</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#propaganda"
>propaganda</a
>, ads, and
<a
href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#neopterecenost-paznje-sporednim-stvarima"
>
are not designed to lock your attention (dumbing down)
</a>
.
<a href="https://forum.dmz.rs/t/zasto-nam-je-decentralizacija-bitna/506/1">
Tell us why decentralization is important to you
</a>
</dd>
<dt>Knowledge:</dt>
<dd>
All our workshops are free and open to everyone.
Also, if you have something to share, feel free to announce the event on the <a href="https://forum.dmz.rs"></a>Forum</a>.
All our workshops are free and open to everyone. Also, if you have something
to share, feel free to announce the event on the
<a href="https://forum.dmz.rs">Forum</a>.
</dd>
<dt>Actions:</dt>
<dd>From time to time we organize actions, hackathons, crypto parties, exhibitions, etc.</dd>
<dd>
From time to time we organize actions, hackathons, crypto parties,
exhibitions, etc.
</dd>
<dt>Services:</dt>
<dd>Our servers run various services (like e-mail, git, wiki, etc...) that are open to everyone.</dd>
<dd>
Our servers run various services (like e-mail, git, wiki, etc...) that are
open to everyone.
</dd>
</dl>
<p>
If you are still interested, you can create an <a href="/en/account">account</a>
on our server which will enable the use of all our <a href="/en/services">services</a>.
If you want to see first how it all looks, you can come to one of our
<a href="/en/events">event</a>, and meet us there!
If you are still interested, you can create an
<a href="/en/account">account</a> on our server which will enable the use of
all our <a href="/en/services">services</a>. If you want to see first how it
all looks, you can come to one of our <a href="/en/events">event</a>, and meet
us there!
</p>

View File

@@ -43,8 +43,8 @@
<tr>
<td><a href="https://jitsi.dmz.rs/">Jitsi</a></td>
<td>
<a href="https://jitsi.org/">Jitsi.org</a> meeting app, conferences, group video calls, online events, alternative
to zoom.
<a href="https://jitsi.org/">Jitsi.org</a> meeting app, conferences, group
video calls, online events, alternative to zoom.
</td>
</tr>
<!--<tr>

View File

@@ -2,44 +2,76 @@
<div>
<p>
Decentrala is a community, united around the principles of decentralized technology and the spreading of knowledge. 
Decentrala is a community, united around the principles of decentralized
technology and the spreading of knowledge.
</p>
<label>Key values include:</label>
<ul>
<li>Equal access to technology</li>
<li>Free software</li>
<li>Privacy and security</li>
</ul>
<p> Donations are accepted only from individuals, with no conditions or obligations. </p>
<p> Only open-source services are hosted on the Decentrala infrastructure. </p>
<p> Parts of the statute can be defined immutable, and cannot be voted on. </p>
<p>
Every member or group has the right to act in the name of Decentrala,
if their initiatives align with Decentralas goals and statute,
as long as their events are announced and explained on Decentralas public digital communication channels.
<div class="values">
<label>Our key values include:</label>
<ul>
<li>Equal access to technology</li>
<li>Free and open source software</li>
<li>Privacy and security</li>
</ul>
</div>
<p>
Donations are accepted only from individuals, with no conditions or
obligations.
</p>
<p>Only open-source services are hosted on the Decentrala infrastructure.</p>
<p>Parts of the statute can be defined immutable, and cannot be voted on.</p>
<p>
Every member or group has the right to act in the name of Decentrala, if
their initiatives align with Decentrala's goals and statute, as long as
their events are announced and explained on Decentrala's public digital
communication channels.
</p>
<p>
Decentrala rules and statutes are decided independently by a voting body that makes decisions on the principles of direct democracy,
consensus, or by a simple majority of two-thirds of the total number of collective members.
Decentrala rules and statutes are decided independently by a voting body
that makes decisions on the principles of direct democracy, consensus, or by
a simple majority of two-thirds of the total number of collective members.
</p>
</div>
<h2>Voting Body</h2>
<div>
<p>Membership applications are accepted only if two-thirds of attending members vote in favor. </p>
<p>Only members who are physically present have the right to vote.</p
<p>
Membership applications are accepted only if two-thirds of attending members
vote in favor.
</p>
<p>Only members who are physically present have the right to vote.</p>
<p>There is no limit on the number of members of the voting body.</p>
<p> An individual may withdraw from the union at any time, or may be expelled by a two-thirds majority of present members. </p
<p> If a member of a voting body is absent during three consecutive meetings, they are automatically excluded from the voting body. </p>
<p> A member can be re-admitted to the governing body according to the predefined procedure for adding new members, if they are present at that meeting. </p>
<p> The current members of the voting body are using pseudonyms malin, coja, bora, mad3v, txrpe, euffrat, netstat.</p>
<p>
An individual may withdraw from the union at any time, or may be expelled by
a two-thirds majority of present members.
</p>
<p>
If a member of a voting body is absent during three consecutive meetings,
they are automatically excluded from the voting body.
</p>
<p>
A member can be re-admitted to the governing body according to the
predefined procedure for adding new members, if they are present at that
meeting.
</p>
<p>
The current members of the voting body are using pseudonyms malin, coja,
bora, mad3v, txrpe, euffrat, netstat.
</p>
</div>
<h2>Meetings</h2>
<div>
<p> The vote of the polling body is valid if at least three members of the polling body are present. </p>
<p> The meeting time and place of the Decentral Assembly must be announced at least seven days in advance of the meeting on the Decentrala's forum. </p>
<p> The voting body's session should be held at least once every two months. </p>
<p>
The vote of the polling body is valid if at least three members of the
polling body are present.
</p>
<p>
The meeting time and place of the Decentral Assembly must be announced at
least seven days in advance of the meeting on the Decentrala's forum.
</p>
<p>
The voting body's session should be held at least once every two months.
</p>
</div>

View File

@@ -29,11 +29,11 @@
</p>
<ul>
<li>Bitcoin: <i>bc1qjhsfgq79wuzzv32yml9zglwzf9qcwfj3atuy74</i></li>
<li>
<!-- <li>
Monero:
<i
>8BESz45LnxrgCwZP32KieiN1D4LinCfsS1YjdFHfGXrVCmPs35167QsW1gd7qbff4UAtBbT6oWrkbfZnJm71HornVRiRZFS</i
>
</li>
</li> -->
</ul>
</dd>

View File

@@ -1,10 +1,23 @@
<h1>O nama</h1>
<dl>
<dt>Statut:</dt>
<dd> Sve odluke se donose po principu direktne demokratije. Nas statut mozete pogledati na <a href="/statute">stranici za statut</a>. </dd>
<dt>Statut:</dt>
<dd>
Sve odluke se donose po principu direktne demokratije. Nas statut mozete
pogledati na <a href="/statute">stranici za statut</a>.
</dd>
<dt>Kontakt:</dt>
<dd>Možeš nam poslati mejl na adresu <a href="mailto:dmz@dmz.rs">dmz@dmz.rs</a> ili se možeš pridružiti našem <a href="https://forum.dmz.rs">Forumu</a>.</dd>
<dd>Takođe smo dostupni i na <a href="https://balkan.fedive.rs/@decentrala">Fediversu!</a></dd>
<dd>U slučaju da pronađeš <em>bug</em> na sajtu, bili bismo ti jako zahvalni ako nam ga prijaviš.</dd>
<dt>Kontakt:</dt>
<dd>
Možeš nam poslati mejl na adresu
<a href="mailto:dmz@dmz.rs">dmz@dmz.rs</a> ili se možeš pridružiti našem
<a href="https://forum.dmz.rs">Forumu</a>.
</dd>
<dd>
Takođe smo dostupni i na
<a href="https://balkan.fedive.rs/@decentrala">Fediversu!</a>
</dd>
<dd>
U slučaju da pronađeš <em>bug</em> na sajtu, bili bismo ti jako zahvalni ako
nam ga prijaviš.
</dd>
</dl>

View File

@@ -1,2 +1,2 @@
Ova stranica je trenutno u izradi...

View File

@@ -1,35 +1,89 @@
<h1>Dekonferencija</h1>
<h2 id="program"><a href="#program">Program</a></h2>
<p>11:00 Otvaranje<p>
<p>12:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty">Cryptoparty</a><p>
<p>14:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/hakaton">Hakaton</a><p>
<p>16:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/lightningtalks">Lightning talks</a><p>
<p>18:00 Diskusije<p>
<p>20:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty">Cryptoparty</a><p>
<p>22:00 Kraj<p>
<p>11:00 Otvaranje</p>
<p>
12:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty"
>Cryptoparty</a
>
</p>
<p>
14:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/hakaton">Hakaton</a>
</p>
<p>
16:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/lightningtalks"
>Lightning talks</a
>
</p>
<p>18:00 Diskusije</p>
<p>
20:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty"
>Cryptoparty</a
>
</p>
<p>22:00 Kraj</p>
<h2 id="what"><a href="#what">Šta?</a></h2>
<p>Dekonferencija je prva konferencija organizovana od strane <a href="https://dmz.rs">Decentrale</a>, Beogradskog hakerspejsa. Dekonferencija služi kao platforma za predstavljanje i diskusiju ideja decentralizacije u svim svojim oblicima.</p>
<p>
Dekonferencija je prva konferencija organizovana od strane
<a href="https://dmz.rs">Decentrale</a>, Beogradskog hakerspejsa.
Dekonferencija služi kao platforma za predstavljanje i diskusiju ideja
decentralizacije u svim svojim oblicima.
</p>
<h2 id="when-and-where"><a href="#when-and-where">Kad & Gde?</a></h2>
<p>Dekonferencija će se održati u nedelju, 15.-og Septembra, 2024, u Kulturnom Centru Magacin, na adresi <a href="https://osm.org/go/xf3Fz31te?node=1226456745">Kraljevića Marka 4-8, Beograd</a>. Veče pre, održaće se druženje povodom organizovanja konferencije u prostorijama <a href="https://dckrov.rs/">Društvenog Centra Krov</a>, na adresi <a href="https://osm.org/go/xf3HQQdIH">Kraljice Marije 47, Beograd</a>.</p>
<p>
Dekonferencija će se održati u nedelju, 15.-og Septembra, 2024, u Kulturnom
Centru Magacin, na adresi
<a href="https://osm.org/go/xf3Fz31te?node=1226456745"
>Kraljevića Marka 4-8, Beograd</a
>. Veče pre, održaće se druženje povodom organizovanja konferencije u
prostorijama <a href="https://dckrov.rs/">Društvenog Centra Krov</a>, na
adresi <a href="https://osm.org/go/xf3HQQdIH">Kraljice Marije 47, Beograd</a>.
</p>
<h2 id="why"><a href="#why">Zašto?</a></h2>
<p>Decentrala je osnovana od strane male grupe entuzijasta udružene oko ideje decentralizacije tehnologije. Poslednjih godinu i po, organizovali smo više od 160 događaja—predavanja, radionica, diskusija, hakatona—sa ciljem demokratizacije tehnološkog znanja i edukacije o privatnosti, open source principa, prava na popravku (i kako popraviti), digitalna svojina, i pravo korišćenja. Od prvog dana, naš pristup je bio da informišemo pojedince o alternativama umesto da im namećemo naše mišljenje.</p>
<p>
Decentrala je osnovana od strane male grupe entuzijasta udružene oko ideje
decentralizacije tehnologije. Poslednjih godinu i po, organizovali smo više od
160 događaja—predavanja, radionica, diskusija, hakatona—sa ciljem
demokratizacije tehnološkog znanja i edukacije o privatnosti, open source
principa, prava na popravku (i kako popraviti), digitalna svojina, i pravo
korišćenja. Od prvog dana, naš pristup je bio da informišemo pojedince o
alternativama umesto da im namećemo naše mišljenje.
</p>
<p>Vremenom, angažovanjem sa raznovrsnim posetiocima, od kojih su mnogi iz ne-tehničkih sfera, shvatili smo da decentralizacija obuhvata više od samo "otvorene tehnologije." Mnogi aktivisti i organizacije se danas zalažu za različite oblike decentralizacije. Zato, smatramo da su dobrodošle priče decentralizacije iz različitih perspektiva.</p>
<p>
Vremenom, angažovanjem sa raznovrsnim posetiocima, od kojih su mnogi iz
ne-tehničkih sfera, shvatili smo da decentralizacija obuhvata više od samo
"otvorene tehnologije." Mnogi aktivisti i organizacije se danas zalažu za
različite oblike decentralizacije. Zato, smatramo da su dobrodošle priče
decentralizacije iz različitih perspektiva.
</p>
<h2 id="who"><a href="#who">Ko?</a></h2>
<p>Dekonferencija je otvorena platforma za sve zainteresovane za diskusiju, demonstraciju, ili istraživanje decentralizacije. Možete registrovati vaš događaj slanjem email-a na <a href="mailto:dekonferencija@dmz.rs">dekonferencija@dmz.rs</a> do dana Dekonferencije (15.-ti Septembar).</p>
<p>
Dekonferencija je otvorena platforma za sve zainteresovane za diskusiju,
demonstraciju, ili istraživanje decentralizacije. Možete registrovati vaš
događaj slanjem email-a na
<a href="mailto:dekonferencija@dmz.rs">dekonferencija@dmz.rs</a> do dana
Dekonferencije (15.-ti Septembar).
</p>
<p>Osvežićemo ovaj deo kako se teme događaja potvrde.</p>
<h2 id="how"><a href="#how">Kako?</a></h2>
<p>Dekonferencija je finansirana od strane ličnih sredstava organizatora. Kao i sve aktivnosti Decentrale, Dekonferencija je besplatna svima. Nažalost, nismo u stanju da pružimo subvencije predavačima.</p>
<p>
Dekonferencija je finansirana od strane ličnih sredstava organizatora. Kao i
sve aktivnosti Decentrale, Dekonferencija je besplatna svima. Nažalost, nismo
u stanju da pružimo subvencije predavačima.
</p>
<p>Decentrala prihvata donacije isključivo od fizičkih lica.</p>

View File

@@ -1,27 +1,67 @@
<h1>Dobrodošli!</h1>
<p>
Mi smo <em>Decentrala</em> - grupa entuzijasta okupljena oko ideja decentralizacije i slobodnog širenja znanja.
Zvuči interesantno? Evo još nekih stvari o nama:
Mi smo <em>Decentrala</em> - grupa entuzijasta okupljena oko ideja
decentralizacije i slobodnog širenja znanja. Zvuči interesantno? Evo još nekih
stvari o nama:
</p>
<dl>
<dt>Motivacija:</dt>
<dd>Decentralizacijom postizemo <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#odrzivost">odrzivost</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#dostupnost">dostupnost</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#pristupacnost">pristupacnost</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#nezavisnost">nezavisnost</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#privatnost">privatnost</a> i <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#sloboda">slobodu</a>. Na ovim mrezama ima manje <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#manipulacija">manipulacije</a>, <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#propaganda">propagande</a>, reklama, i <a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#neopterecenost-paznje-sporednim-stvarima">nisu dizajnirane za zadrzavanje paznje (zaglupljivanje)</a>.
<a href="https://forum.dmz.rs/t/zasto-nam-je-decentralizacija-bitna/506/1">Recite zasto je vama decentralizacija bitna</a>
<dd>
Decentralizacijom postizemo
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#odrzivost"
>odrzivost</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#dostupnost"
>dostupnost</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#pristupacnost"
>pristupacnost</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#nezavisnost"
>nezavisnost</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#privatnost"
>privatnost</a
>
i
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#sloboda"
>slobodu</a
>. Na ovim mrezama ima manje
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#manipulacija"
>manipulacije</a
>,
<a href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#propaganda"
>propagande</a
>, reklama, i
<a
href="https://wiki.dmz.rs/en/zastojedecentralizacijabitna#neopterecenost-paznje-sporednim-stvarima"
>nisu dizajnirane za zadrzavanje paznje (zaglupljivanje)</a
>.
<a href="https://forum.dmz.rs/t/zasto-nam-je-decentralizacija-bitna/506/1"
>Recite zasto je vama decentralizacija bitna</a
>
</dd>
<dt>Znanje:</dt>
<dd>Sve naše radionice su besplatne i otvorene za sve zainteresovane.
Ako želiš nešto da podeliš najavi se na našem <a href="https://forum.dmz.rs">Forumu</a> i održi radionicu kod nas!
<dd>
Sve naše radionice su besplatne i otvorene za sve zainteresovane. Ako želiš
nešto da podeliš najavi se na našem
<a href="https://forum.dmz.rs">Forumu</a> i održi radionicu kod nas!
</dd>
<dt>Akcije:</dt>
<dd>Povremeno organizujemo različite akcije, hakatone, crypto-partije, izložbe i slične događaje otvorene za sve
zainteresovane. </dd>
<dd>
Povremeno organizujemo različite akcije, hakatone, crypto-partije, izložbe i
slične događaje otvorene za sve zainteresovane.
</dd>
<dt>Servisi:</dt>
<dd>Na našim serverima pokrećemo razne servise (email, git, wiki i druge) koji su otvoreni za sve i koji se mogu
koristiti sa ili bez našeg naloga.</dd>
<dd>
Na našim serverima pokrećemo razne servise (email, git, wiki i druge) koji
su otvoreni za sve i koji se mogu koristiti sa ili bez našeg naloga.
</dd>
</dl>
<p>
Ako si i dalje zainteresovan, možeš napraviti <a href="/account">nalog</a> na našem serveru koji će ti
omogućiti korišćenje svih naših <a href="/services">servisa</a>.
Ako želiš prvo da vidiš kako to sve izgleda u realnosti, možeš doći na neki od naših <a
href="/events">događaja</a>, i tu nas upoznati!
Ako si i dalje zainteresovan, možeš napraviti <a href="/account">nalog</a> na
našem serveru koji će ti omogućiti korišćenje svih naših
<a href="/services">servisa</a>. Ako želiš prvo da vidiš kako to sve izgleda u
realnosti, možeš doći na neki od naših <a href="/events">događaja</a>, i tu
nas upoznati!
</p>

View File

@@ -46,7 +46,8 @@
<tr>
<td><a href="https://jitsi.dmz.rs/">Jitsi</a></td>
<td>
<a href="https://jitsi.org/">Jitsi.org</a> aplikacija za sastanke, groupne video pozive, online dogadjaje, alternativa za zoom.
<a href="https://jitsi.org/">Jitsi.org</a> aplikacija za sastanke, groupne
video pozive, online dogadjaje, alternativa za zoom.
</td>
</tr>
<!--<tr>

View File

@@ -3,9 +3,16 @@
<div>
<p>
Decentrala je zajednica okupljena oko decentralizacije tehnologija i širenja
znanja. Decentralizacija uključuje ravnopravnost korišćenja tehnologije,
slobodnog softvera, privatnost i bezbednost.
znanja.
</p>
<div class="values">
<label> Decentralizacija uključuje: </label>
<ul>
<li>Ravnopravnost korišćenja tehnologije</li>
<li>Slobodan software otvorenog koda</li>
<li>Privatnost i bezbednost.</li>
</ul>
</div>
<p>
Na Decentralinoj arhitekturi hostuju se samo servisi koji su otvorenog koda
</p>
@@ -51,7 +58,8 @@
dodavanja novog clana, ako je prisutan na tom sastanku.
</p>
<p>
Trenutni članovi glasačkog tela su pod pseudonimom malin, coja, bora, mad3v, txrpe, euffrat, netstat.
Trenutni članovi glasačkog tela su pod pseudonimom malin, coja, bora, mad3v,
txrpe, euffrat, netstat.
</p>
</div>

View File

@@ -27,11 +27,13 @@
<p>Takođe primamo donacije u bitcoinu i moneru na adresama:</p>
<ul>
<li>Bitcoin: <i>bc1qjhsfgq79wuzzv32yml9zglwzf9qcwfj3atuy74</i></li>
<!--
<li>
Monero:
<i
>8BESz45LnxrgCwZP32KieiN1D4LinCfsS1YjdFHfGXrVCmPs35167QsW1gd7qbff4UAtBbT6oWrkbfZnJm71HornVRiRZFS</i
>
</li>
-->
</ul>
</dd>

271
prep.py
View File

@@ -1,7 +1,7 @@
#! /usr/bin/env python3
from jinja2 import Environment, FileSystemLoader
import csv
from datetime import datetime
import os
DAYS_SR = ["PON", "UTO", "SRE", "ČET", "PET", "SUB", "NED"]
DAYS_EN = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]
@@ -18,22 +18,20 @@ TYPES_DICT = {
"party": ("zabava", "entertainment"),
}
env = Environment(loader=FileSystemLoader('template'))
def load_events(csv_path:str) -> list[dict]:
events = []
with open(csv_path) as csv_file:
csv_reader = csv.reader(csv_file, skipinitialspace=True)
next(csv_reader, None)
with open(csv_path, encoding='utf-8') as csv_file:
csv_reader = csv.DictReader(csv_file, skipinitialspace=True)
for event in csv_reader:
event_date = event[0]
event_date = event["datum"]
event_date_parsed = datetime.strptime(event_date, "%d-%m-%Y").date()
event_time = event[1]
event_location = event[2]
event_title = event[3]
types = event[4].split()
try:
link = event[5]
except IndexError:
link = ""
event_time = event["vreme"]
event_location = event["lokacija"]
event_title = event["tema"]
types = event["tip"].split()
link = event.get("link", "")
current_event = {"date":event_date_parsed,
"time":event_time,
"location": event_location,
@@ -43,50 +41,11 @@ def load_events(csv_path:str) -> list[dict]:
events.append(current_event)
return events
def build_html(events: list[dict], dayNames: list[str], typesNames: dict) -> str:
events_html = []
for event in events:
title = event["title"]
location = event["location"]
date = event["date"]
date = dayNames[date.weekday()]+", "+str(date.day)+". "+str(date.month)+". "+str(date.year)+", "
time = event["time"]+"h"
event_html = []
event_html.append(f"<div class='date'>{date} {time}</div>")
if event["link"] != "":
event_html.append(f"<div class='title'><a href=\"{event['link']}\">{title}</a></div>")
else:
event_html.append(f"<div class='title'>{title}</div>")
if "https://" in location:
place,link = location.split("https://")
event_html.append(f"<div class='place'><a href=\"https://{link}\" target='_blank'>@{place.strip()}</a></div>")
else:
event_html.append(f"<div class='place'>@{location.strip()}</div>")
if len(event["types"]) != 0:
types_list = "<div class='types'>"
last_item = event["types"][-1]
for t in event["types"]:
if typesNames.get(t) is not None:
types_list += typesNames.get(t)
if t != last_item:
types_list += ', '
else:
print(f"Unknown type {t}!")
types_list += "</div>"
event_html.append(types_list)
event_html = "".join(event_html)
events_html.append(f"\n<div class='event'>{event_html}</div>")
return events_html
def build_ical(events: list[dict]) -> str:
today = datetime.today().now()
# Header
events_ical = ""
with open("template/head.ical", "r") as file:
events_ical += file.read()
# Events
for event in events:
title = event["title"]
location = event["location"]
@@ -95,85 +54,165 @@ def build_ical(events: list[dict]) -> str:
url = event["link"]
uid = str(date.month).zfill(2) + str(date.day).zfill(2) + time[:2]
date = str(date.year) + str(date.month).zfill(2) + str(date.day).zfill(2)
date_str = str(date.year) + str(date.month).zfill(2) + str(date.day).zfill(2)
created = str(today.year) + str(today.month).zfill(2) + str(today.day).zfill(2) + "T" + str(today.hour).zfill(2) + str(today.minute).zfill(2) + str(today.second).zfill(2) + "Z"
date = date + "T" + time.replace(":", "") + "00"
date_str = date_str + "T" + time.replace(":", "") + "00"
event_template = ""
with open("template/event.ical", "r") as file:
event_template += file.read()
event_template = event_template.replace("<!--UID-->", uid)
event_template = event_template.replace("<!--CREATED-->", created)
event_template = event_template.replace("<!--DATE-->", date)
event_template = event_template.replace("<!--TITLE-->", title)
event_template = event_template.replace("<!--URL-->", url)
if location.startswith("DC Krov"):
event_template = event_template.replace("<!--LOCATION-->", "DC Krov\\, Kraljice Marije 47\\, 6\\, Beograd\\, Serbia")
elif location.startswith("Matematički fakultet (Učionica 153)"):
event_template = event_template.replace("<!--LOCATION-->", "Matematički fakultet\\, Svetog Nikole 39\\, Beograd\\, Serbia")
else:
event_template = event_template.replace("<!--LOCATION-->", location)
event_template_str = env.get_template("event.ical").render(
UID=uid,
CREATED=created,
DATE=date_str,
TITLE=title,
URL=url,
LOCATION="DC Krov\\, Kraljice Marije 47\\, 6\\, Beograd\\, Serbia" if location.startswith("DC Krov") else ("Matematički fakultet\\, Svetog Nikole 39\\, Beograd\\, Serbia" if location.startswith("Matematički fakultet (Učionica 153)") else location)
)
events_ical += event_template_str
events_ical += event_template
# Footer
with open("template/end.ical", "r") as file:
events_ical += file.read()
return events_ical
events = sorted(load_events("dogadjaji.csv"), key=lambda e: e["date"])
def render_page(template_name, output_path, context):
template = env.get_template(template_name)
with open(output_path, "w") as file:
file.write(template.render(context))
# Main execution
events = sorted(load_events("dogadjaji.csv"), key=lambda e: e["date"])
today = datetime.today().date()
past_events = list(filter(lambda e: e["date"] <= today, events))
past_events.reverse()
new_events = list(filter(lambda e: e["date"] >= today, events))
past_events = sorted([e for e in events if e["date"] <= today], key=lambda e: e["date"], reverse=True)
new_events = [e for e in events if e["date"] >= today]
sr_types = {k: v[0] for k, v in TYPES_DICT.items()}
en_types = {k: v[1] for k, v in TYPES_DICT.items()}
page_template = ""
# Build Serbian Pages
render_page("events-sr.html", "pages/sr/events.html", {
"lang": "sr",
"title": "Događaji",
"sr_link": "/events_archive",
"events_html": env.from_string("""
{% for event in events %}
<div class='event'>
<div class='date'>{{ event.date.strftime('%a, %d. %b. %Y') }}, {{ event.time }}h</div>
{% if event.link %}
<div class='title'><a href="{{ event.link }}">{{ event.title }}</a></div>
{% else %}
<div class='title'>{{ event.title }}</div>
{% endif %}
{% if 'https://' in event.location %}
{% set place, link = event.location.split('https://') %}
<div class='place'><a href="https://{{ link }}" target='_blank'>@{{ place.strip() }}</a></div>
{% else %}
<div class='place'>@{{ event.location.strip() }}</div>
{% endif %}
{% if event.types %}
<div class='types'>
{% for t in event.types %}
{{ types_names.get(t, t) }}{% if not loop.last %}, {% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
""").render(events=new_events, types_names=sr_types)
})
sr_types = {}
en_types = {}
render_page("events-en.html", "pages/en/events.html", {
"lang": "en",
"title": "Events",
"sr_link": "/events_archive",
"events_html": env.from_string("""
{% for event in events %}
<div class='event'>
<div class='date'>{{ event.date.strftime('%a, %d. %b. %Y') }}, {{ event.time }}h</div>
{% if event.link %}
<div class='title'><a href="{{ event.link }}">{{ event.title }}</a></div>
{% else %}
<div class='title'>{{ event.title }}</div>
{% endif %}
{% if 'https://' in event.location %}
{% set place, link = event.location.split('https://') %}
<div class='place'><a href="https://{{ link }}" target='_blank'>@{{ place.strip() }}</a></div>
{% else %}
<div class='place'>@{{ event.location.strip() }}</div>
{% endif %}
{% if event.types %}
<div class='types'>
{% for t in event.types %}
{{ types_names.get(t, t) }}{% if not loop.last %}, {% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
""").render(events=new_events, types_names=en_types)
})
for key, value_pair in TYPES_DICT.items():
sr_types[key] = value_pair[0]
en_types[key] = value_pair[1]
# Build Archive Pages
render_page("events_archive-sr.html", "pages/sr/events_archive.html", {
"lang": "sr",
"title": "Arhiva događaja",
"sr_link": "/events",
"events_html": env.from_string("""
{% for event in events %}
<div class='event'>
<div class='date'>{{ event.date.strftime('%a, %d. %b. %Y') }}, {{ event.time }}h</div>
{% if event.link %}
<div class='title'><a href="{{ event.link }}">{{ event.title }}</a></div>
{% else %}
<div class='title'>{{ event.title }}</div>
{% endif %}
{% if 'https://' in event.location %}
{% set place, link = event.location.split('https://') %}
<div class='place'><a href="https://{{ link }}" target='_blank'>@{{ place.strip() }}</a></div>
{% else %}
<div class='place'>@{{ event.location.strip() }}</div>
{% endif %}
{% if event.types %}
<div class='types'>
{% for t in event.types %}
{{ types_names.get(t, t) }}{% if not loop.last %}, {% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
""").render(events=past_events, types_names=sr_types)
})
# Build Serbian Events page
new_events_html = build_html(new_events, DAYS_SR, sr_types)
with open("template/events-sr.html", "r") as file:
page_template = ([line for line in file])
with open("pages/sr/events.html", "w") as file:
file.writelines(page_template + new_events_html)
# Build English Events page
new_events_html = build_html(new_events, DAYS_EN, en_types)
with open("template/events-en.html", "r") as file:
page_template = ([line for line in file])
with open("pages/en/events.html", "w") as file:
file.writelines(page_template + new_events_html)
# Build Serbian Archive page
past_events_html = build_html(past_events, DAYS_SR, sr_types)
with open("template/events_archive-sr.html", "r") as file:
page_template = ([line for line in file])
with open("pages/sr/events_archive.html", "w") as file:
file.writelines(page_template + past_events_html)
# Build English Archive page
past_events_html = build_html(past_events, DAYS_EN, en_types)
with open("template/events_archive-en.html", "r") as file:
page_template = ([line for line in file])
with open("pages/en/events_archive.html", "w") as file:
file.writelines(page_template + past_events_html)
new_events_ical = build_ical(new_events)
render_page("events_archive-en.html", "pages/en/events_archive.html", {
"lang": "en",
"title": "Events archive",
"sr_link": "/en/events",
"events_html": env.from_string("""
{% for event in events %}
<div class='event'>
<div class='date'>{{ event.date.strftime('%a, %d. %b. %Y') }}, {{ event.time }}h</div>
{% if event.link %}
<div class='title'><a href="{{ event.link }}">{{ event.title }}</a></div>
{% else %}
<div class='title'>{{ event.title }}</div>
{% endif %}
{% if 'https://' in event.location %}
{% set place, link = event.location.split('https://') %}
<div class='place'><a href="https://{{ link }}" target='_blank'>@{{ place.strip() }}</a></div>
{% else %}
<div class='place'>@{{ event.location.strip() }}</div>
{% endif %}
{% if event.types %}
<div class='types'>
{% for t in event.types %}
{{ types_names.get(t, t) }}{% if not loop.last %}, {% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
""").render(events=past_events, types_names=en_types)
})
# Build ical
with open("site/events.ical", "w") as file:
file.write(build_ical(new_events))

View File

@@ -4,3 +4,4 @@ freetype-py
python-dateutil
feedgen
pillow
jinja2

View File

@@ -1,21 +1,7 @@
<!doctype html>
<html lang="sr">
<head>
<script>
(function () {
const theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme === "dark" || (!theme && prefersDark))
document.documentElement.classList.add("dark");
})();
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <pre>
<!--
*@@*
*@@@@*
*@@*
@@ -35,76 +21,144 @@
| | | | _|| | | _| | \| | | | | |_) | / _ \ | | / _ \
| |_| | |__| |___| |___| |\ | | | | _ < / ___ \| |___ / ___ \
|____/|_____\____|_____|_| \_| |_| |_| \_\/_/ \_\_____/_/ \_\
-->
</pre> -->
<script>
(function () {
const theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme === "dark" || (!theme && prefersDark))
document.documentElement.classList.add("dark");
})();
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/styles/reset.css" />
<link rel="stylesheet" href="/styles/style.css" />
<link rel="stylesheet" href="/styles/deconference.css">
<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon" />
<script src="/scripts/main.js" defer></script>
<script src="/scripts/main.js"></script>
<title>Dekonferencija Decentrala</title>
<link rel="alternate" hreflang="en" href="/en/deconference" />
<link rel="alternate" hreflang="sr" href="/en/deconference" />
</head>
<body>
<header>
<a id="logo" href="/">
<img src="/img/logo-light.svg" alt="Logo" />
Decentrala
<img src="/img/logo-light.svg" alt="Logo" /> Decentrala
</a>
<button id="theme-switcher"></button>
<a class="lang" hreflang="en" href="/en/deconference">EN</a>
</header>
<main>
<div class="page-wrap">
<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Studenti su nasli bug' /></div><h1>Dekonferencija</h1>
<div class="page-wrap">
<div class='cover-wrap'><img src='/img/students_bug.jpg' alt='Studenti su nasli bug' /></div><h1>Dekonferencija</h1>
<h2 id="program"><a href="#program">Program</a></h2>
<p>11:00 Otvaranje<p>
<p>12:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty">Cryptoparty</a><p>
<p>14:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/hakaton">Hakaton</a><p>
<p>16:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/lightningtalks">Lightning talks</a><p>
<p>18:00 Diskusije<p>
<p>20:00 <a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty">Cryptoparty</a><p>
<p>22:00 Kraj<p>
<p>11:00 Otvaranje</p>
<p>
12:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty"
>Cryptoparty</a
>
</p>
<p>
14:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/hakaton">Hakaton</a>
</p>
<p>
16:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/lightningtalks"
>Lightning talks</a
>
</p>
<p>18:00 Diskusije</p>
<p>
20:00
<a href="https://wiki.dmz.rs/en/decentrala/dogadjaji/cryptoparty"
>Cryptoparty</a
>
</p>
<p>22:00 Kraj</p>
<h2 id="what"><a href="#what">Šta?</a></h2>
<p>Dekonferencija je prva konferencija organizovana od strane <a href="https://dmz.rs">Decentrale</a>, Beogradskog hakerspejsa. Dekonferencija služi kao platforma za predstavljanje i diskusiju ideja decentralizacije u svim svojim oblicima.</p>
<p>
Dekonferencija je prva konferencija organizovana od strane
<a href="https://dmz.rs">Decentrale</a>, Beogradskog hakerspejsa.
Dekonferencija služi kao platforma za predstavljanje i diskusiju ideja
decentralizacije u svim svojim oblicima.
</p>
<h2 id="when-and-where"><a href="#when-and-where">Kad & Gde?</a></h2>
<p>Dekonferencija će se održati u nedelju, 15.-og Septembra, 2024, u Kulturnom Centru Magacin, na adresi <a href="https://osm.org/go/xf3Fz31te?node=1226456745">Kraljevića Marka 4-8, Beograd</a>. Veče pre, održaće se druženje povodom organizovanja konferencije u prostorijama <a href="https://dckrov.rs/">Društvenog Centra Krov</a>, na adresi <a href="https://osm.org/go/xf3HQQdIH">Kraljice Marije 47, Beograd</a>.</p>
<p>
Dekonferencija će se održati u nedelju, 15.-og Septembra, 2024, u Kulturnom
Centru Magacin, na adresi
<a href="https://osm.org/go/xf3Fz31te?node=1226456745"
>Kraljevića Marka 4-8, Beograd</a
>. Veče pre, održaće se druženje povodom organizovanja konferencije u
prostorijama <a href="https://dckrov.rs/">Društvenog Centra Krov</a>, na
adresi <a href="https://osm.org/go/xf3HQQdIH">Kraljice Marije 47, Beograd</a>.
</p>
<h2 id="why"><a href="#why">Zašto?</a></h2>
<p>Decentrala je osnovana od strane male grupe entuzijasta udružene oko ideje decentralizacije tehnologije. Poslednjih godinu i po, organizovali smo više od 160 događaja—predavanja, radionica, diskusija, hakatona—sa ciljem demokratizacije tehnološkog znanja i edukacije o privatnosti, open source principa, prava na popravku (i kako popraviti), digitalna svojina, i pravo korišćenja. Od prvog dana, naš pristup je bio da informišemo pojedince o alternativama umesto da im namećemo naše mišljenje.</p>
<p>
Decentrala je osnovana od strane male grupe entuzijasta udružene oko ideje
decentralizacije tehnologije. Poslednjih godinu i po, organizovali smo više od
160 događaja—predavanja, radionica, diskusija, hakatona—sa ciljem
demokratizacije tehnološkog znanja i edukacije o privatnosti, open source
principa, prava na popravku (i kako popraviti), digitalna svojina, i pravo
korišćenja. Od prvog dana, naš pristup je bio da informišemo pojedince o
alternativama umesto da im namećemo naše mišljenje.
</p>
<p>Vremenom, angažovanjem sa raznovrsnim posetiocima, od kojih su mnogi iz ne-tehničkih sfera, shvatili smo da decentralizacija obuhvata više od samo "otvorene tehnologije." Mnogi aktivisti i organizacije se danas zalažu za različite oblike decentralizacije. Zato, smatramo da su dobrodošle priče decentralizacije iz različitih perspektiva.</p>
<p>
Vremenom, angažovanjem sa raznovrsnim posetiocima, od kojih su mnogi iz
ne-tehničkih sfera, shvatili smo da decentralizacija obuhvata više od samo
"otvorene tehnologije." Mnogi aktivisti i organizacije se danas zalažu za
različite oblike decentralizacije. Zato, smatramo da su dobrodošle priče
decentralizacije iz različitih perspektiva.
</p>
<h2 id="who"><a href="#who">Ko?</a></h2>
<p>Dekonferencija je otvorena platforma za sve zainteresovane za diskusiju, demonstraciju, ili istraživanje decentralizacije. Možete registrovati vaš događaj slanjem email-a na <a href="mailto:dekonferencija@dmz.rs">dekonferencija@dmz.rs</a> do dana Dekonferencije (15.-ti Septembar).</p>
<p>
Dekonferencija je otvorena platforma za sve zainteresovane za diskusiju,
demonstraciju, ili istraživanje decentralizacije. Možete registrovati vaš
događaj slanjem email-a na
<a href="mailto:dekonferencija@dmz.rs">dekonferencija@dmz.rs</a> do dana
Dekonferencije (15.-ti Septembar).
</p>
<p>Osvežićemo ovaj deo kako se teme događaja potvrde.</p>
<h2 id="how"><a href="#how">Kako?</a></h2>
<p>Dekonferencija je finansirana od strane ličnih sredstava organizatora. Kao i sve aktivnosti Decentrale, Dekonferencija je besplatna svima. Nažalost, nismo u stanju da pružimo subvencije predavačima.</p>
<p>
Dekonferencija je finansirana od strane ličnih sredstava organizatora. Kao i
sve aktivnosti Decentrale, Dekonferencija je besplatna svima. Nažalost, nismo
u stanju da pružimo subvencije predavačima.
</p>
<p>Decentrala prihvata donacije isključivo od fizičkih lica.</p>
</div>
</div>
</main>
<footer>
<button class="hamburger closed">
<img src="/img/strelica-closed-light.svg" alt="Menu" />
</button>
<nav class="menu">
<a href="/events">Događaji</a>
<a href="/services">Servisi</a>
<a href="/statute">Statut</a>
<a href="/about">O nama</a>
<a class="account" href="/account">Nalog</a>
<a href="/account">Nalog</a>
<a href="/support">Podrška</a>
</nav>
<span class="links">
@@ -123,4 +177,4 @@
</span>
</footer>
</body>
</html>
</html>

View File

@@ -1,59 +1,62 @@
const getById = (id) => document.getElementById(id);
const getByClass = (className) => document.getElementsByClassName(className)[0];
window.addEventListener("DOMContentLoaded", () => {
const themeBtn = getById("theme-switcher");
const hamburger = getByClass("hamburger");
const hamburgerIcon = hamburger.children[0]
const menu = document.getElementsByTagName("nav")[0];
const imgs = document.getElementsByTagName("img");
const main = document.getElementsByTagName("main")[0];
const isMenuOpen = () => hamburger.classList.contains("open");
const theme = window.localStorage.getItem("theme");
const getById = (id) => document.getElementById(id);
const getByClass = (className) => document.getElementsByClassName(className)[0];
/* Functions */
const themeBtn = getById("theme-switcher");
const hamburger = getByClass("hamburger");
const hamburgerIcon = hamburger.children[0]
const menu = document.getElementsByTagName("nav")[0];
const imgs = document.getElementsByTagName("img");
const main = document.getElementsByTagName("main")[0];
const isMenuOpen = () => hamburger.classList.contains("open");
const theme = window.localStorage.getItem("theme");
const changeToDarkTheme = () => {
document.documentElement.classList.add("dark");
themeBtn?.setAttribute("title", "turn the light on");
Array.from(imgs).forEach((img) => {
if (img.src.includes("-light")) img.src = img.src.replace("-light", "-dark");
/* Functions */
const changeToDarkTheme = () => {
document.documentElement.classList.add("dark");
themeBtn?.setAttribute("title", "turn the light on");
Array.from(imgs).forEach((img) => {
if (img.src.includes("-light")) img.src = img.src.replace("-light", "-dark");
});
}
const changeToLightTheme = () => {
document.documentElement.classList.remove("dark");
themeBtn?.setAttribute("title", "turn the light off");
Array.from(imgs).forEach((img) => {
if (img.src.includes("-dark")) img.src = img.src.replace("-dark", "-light");
});
}
const closeMenu = () => {
hamburger.classList = "hamburger closed"
hamburgerIcon.src = hamburgerIcon.src.replace("opened", "closed");
menu.classList = "menu closed";
}
const openMenu = () => {
hamburger.classList = "hamburger open"
hamburgerIcon.src = hamburgerIcon.src.replace("closed", "opened");
menu.classList = "menu open";
}
/* Listeners */
window.addEventListener("resize", () => isMenuOpen() && closeMenu());
main.addEventListener("click", () => isMenuOpen() && closeMenu());
hamburger?.addEventListener("click", () => isMenuOpen() ? closeMenu() : openMenu());
themeBtn.addEventListener("click", () => {
const title = themeBtn.getAttribute("title") ?? "off"
if (title.indexOf("off") !== -1) changeToDarkTheme();
else changeToLightTheme();
});
}
const changeToLightTheme = () => {
document.documentElement.classList.remove("dark");
themeBtn?.setAttribute("title", "turn the light off");
Array.from(imgs).forEach((img) => {
if (img.src.includes("-dark")) img.src = img.src.replace("-dark", "-light");
});
}
/* Rest */
const closeMenu = () => {
hamburger.classList = "hamburger closed"
hamburgerIcon.src = hamburgerIcon.src.replace("opened", "closed");
menu.classList = "menu closed";
}
const openMenu = () => {
hamburger.classList = "hamburger open"
hamburgerIcon.src = hamburgerIcon.src.replace("closed", "opened");
menu.classList = "menu open";
}
/* Listeners */
window.addEventListener("resize", () => isMenuOpen() && closeMenu());
main.addEventListener("click", () => isMenuOpen() && closeMenu());
hamburger.addEventListener("click", () => isMenuOpen() ? closeMenu() : openMenu());
themeBtn.addEventListener("click", () => {
const title = themeBtn.getAttribute("title") ?? "off"
if (title.indexOf("off") !== -1) changeToDarkTheme();
else changeToLightTheme();
});
/* Rest */
const userPerfersDark = window?.matchMedia?.("(prefers-color-scheme: dark)").matches
if (!theme && userPerfersDark) changeToDarkTheme();
else theme === "light" ? changeToLightTheme() : changeToDarkTheme();
const userPerfersDark = window?.matchMedia?.("(prefers-color-scheme: dark)").matches
if (!theme && userPerfersDark) changeToDarkTheme();
else theme === "light" ? changeToLightTheme() : changeToDarkTheme();
})

View File

@@ -8,3 +8,15 @@ h2 {
p {
padding-bottom: 1.5rem;
}
.values {
margin-bottom: 1.5rem;
label {
display: block;
padding-bottom: 1rem;
}
ul > li {
padding-left: 1.5rem;
}
}

87
template/base.html Normal file
View File

@@ -0,0 +1,87 @@
<!doctype html>
<html lang="{{ lang }}">
<head>
<!--
*@@*
*@@@@*
*@@*
||
||
*@@* *@@* *@@*
*@@@@*===*@@@@*===*@@@@*
*@@* *@@* *@@*
|| //
|| //
*@@*//
*@@@@*
*@@*
____ _____ ____ _____ _ _ _____ ____ _ _ _
| _ \| ____/ ___| ____| \ | |_ _| _ \ / \ | | / \
| | | | _|| | | _| | \| | | | | |_) | / _ \ | | / _ \
| |_| | |__| |___| |___| |\ | | | | _ < / ___ \| |___ / ___ \
|____/|_____\____|_____|_| \_| |_| |_| \_\/_/ \_\_____/_/ \_\
-->
<script>
(function () {
const theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme === "dark" || (!theme && prefersDark))
document.documentElement.classList.add("dark");
})();
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/styles/reset.css" />
<link rel="stylesheet" href="/styles/style.css" />
{% block extra_styles %}{% endblock %}
<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon" />
<script src="/scripts/main.js"></script>
<title>{{ title }} Decentrala</title>
<link rel="alternate" hreflang="sr" href="{{ sr_link }}" />
</head>
<body>
<header>
<a id="logo" href="/">
<img src="/img/logo-{{ 'dark' if is_dark else 'light' }}.svg" alt="Logo" /> Decentrala
</a>
<button id="theme-switcher"></button>
<a class="lang" hreflang="{{ 'sr' if lang == 'en' else 'en' }}" href="{{ current_path.replace('/en/', '/') if lang == 'en' else ('/en' + current_path if not current_path.startswith('/en/') else current_path) }}">{{ 'SR' if lang == 'en' else 'EN' }}</a>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<button class="hamburger closed">
<img src="/img/strelica-closed-{{ 'dark' if is_dark else 'light' }}.svg" alt="Menu" />
</button>
<nav class="menu">
{% set base_path = '/en/' if lang == 'en' else '/' %}
<a href="{{ base_path }}events">{{ 'Događaji' if lang == 'sr' else 'Events' }}</a>
<a href="{{ base_path }}services">{{ 'Servisi' if lang == 'sr' else 'Services' }}</a>
<a href="{{ base_path }}statute">{{ 'Statut' if lang == 'sr' else 'Statute' }}</a>
<a href="{{ base_path }}about">{{ 'O nama' if lang == 'sr' else 'About us' }}</a>
<a href="{{ base_path }}account">{{ 'Nalog' if lang == 'sr' else 'Account' }}</a>
<a href="{{ base_path }}support">{{ 'Podrška' if lang == 'sr' else 'Support' }}</a>
</nav>
<span class="links">
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
<img src="/img/cc-{{ 'dark' if is_dark else 'light' }}.svg" alt="CreativeCommons" />
</a>
<a href="{{ base_path }}webring">
<img src="/img/w-{{ 'dark' if is_dark else 'light' }}.svg" alt="Webring" />
</a>
<a href="https://gitea.dmz.rs/Decentrala/website">
<img src="/img/git-{{ 'dark' if is_dark else 'light' }}.svg" alt="SourceCode" />
</a>
<a href="https://balkan.fedive.rs/@decentrala">
<img src="/img/mastodon-{{ 'dark' if is_dark else 'light' }}.svg" alt="Mastodon" />
</a>
</span>
</footer>
</body>
</html>

View File

@@ -1,19 +1,22 @@
{% block content %}
<h1>Events</h1>
<div class="description">
<p>
Following list contains all forthcoming events. Held events are listed in
<a href="/en/events_archive">archive</a>.
<a href="/{{ lang }}/events_archive">archive</a>.
</p>
<p>
Events are also available as an
<a href="https://dmz.rs/events.ical">ical</a> file.
</p>
<p>We also provide <a href="https://dmz.rs/events.ical">ical</a> file</p>
<p>
<a href="https://wiki.dmz.rs/en/kako-pronaci-prostor" target="_blank">
Short description
</a>
<a href="https://wiki.dmz.rs/en/kako-pronaci-prostor" target="_blank">Short description</a>
how to find a space
</p>
</div>
<div class="events-list">
{{ events_html|safe }}
</div>
{% endblock %}

View File

@@ -1,18 +1,22 @@
{% block content %}
<h1>Događaji</h1>
<div class="description">
<p>
Naredna lista sadrži sve predstojeće događaje. Za listu održanih događaja
pogledaj <a href="/events_archive">arhivu</a>.
pogledaj <a href="/{{ lang }}/events_archive">arhivu</a>.
</p>
<p>
Događaje možeš učitati i sa
<a href="https://dmz.rs/events.ical">ical</a> datotekom.
</p>
<p>
<a href="https://wiki.dmz.rs/en/kako-pronaci-prostor" target="_blank">
Kratako uputstvo
</a>
<a href="https://wiki.dmz.rs/en/kako-pronaci-prostor" target="_blank">Kratako uputstvo</a>
kako pronaci prostor
</p>
</div>
<div class="events-list">
{{ events_html|safe }}
</div>
{% endblock %}

View File

@@ -1,6 +1,14 @@
<h1>Events archive</h1>
{% block title %}Events archive{% endblock %}
{% block content %}
<h1 class="title">Events archive</h1>
<p>
All events that we organized so far. You can find future events on
<a href="/en/events">Events page</a>
<a href="/{{ lang }}/events">Events page</a>
</p>
<br />
<div class="events-list">
{{ events_html|safe }}
</div>
{% endblock %}

View File

@@ -1,6 +1,14 @@
<h1>Arhiva događaja</h1>
{% block title %}Arhiva događaja{% endblock %}
{% block content %}
<h1 class="title">Arhiva događaja</h1>
<p>
Svi događaji koje smo do sada organzivali. Predstojeće događaje možeš naći
<a href="/events">ovde</a>
<a href="/{{ lang }}/events">ovde</a>
</p>
<br />
<div class="events-list">
{{ events_html|safe }}
</div>
{% endblock %}

View File

@@ -1,90 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<script>
(function () {
const theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme === "dark" || (!theme && prefersDark))
document.documentElement.classList.add("dark");
})();
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{% extends "base.html" %}
<!-- <pre>
{% block title %}{{ title }} Decentrala{% endblock %}
*@@*
*@@@@*
*@@*
||
||
*@@* *@@* *@@*
*@@@@*===*@@@@*===*@@@@*
*@@* *@@* *@@*
|| //
|| //
*@@*//
*@@@@*
*@@*
{% block extra_styles %}{{ extra_styles|safe }}{% endblock %}
____ _____ ____ _____ _ _ _____ ____ _ _ _
| _ \| ____/ ___| ____| \ | |_ _| _ \ / \ | | / \
| | | | _|| | | _| | \| | | | | |_) | / _ \ | | / _ \
| |_| | |__| |___| |___| |\ | | | | _ < / ___ \| |___ / ___ \
|____/|_____\____|_____|_| \_| |_| |_| \_\/_/ \_\_____/_/ \_\
</pre> -->
<link rel="stylesheet" href="/styles/reset.css" />
<link rel="stylesheet" href="/styles/style.css" />
<!--ADDITIONAL_STYLE-->
<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon" />
<script src="/scripts/main.js"></script>
<title><!--TITLE--> Decentrala</title>
<link rel="alternate" hreflang="sr" href="/PAGE_NAME" />
</head>
<body>
<header>
<a id="logo" href="/en/index">
<img src="/img/logo-light.svg" alt="Logo" /> Decentrala
</a>
<button id="theme-switcher"></button>
<a class="lang" hreflang="sr" href="/PAGE_NAME">SR</a>
</header>
<main>
<div class="page-wrap">
<!--MAIN-->
</div>
</main>
<footer>
<button class="hamburger closed">
<img src="/img/strelica-closed-light.svg" alt="Menu" />
</button>
<nav class="menu">
<a href="/en/events">Events</a>
<a href="/en/services">Services</a>
<a href="/en/statute">Statute</a>
<a href="/en/about">About</a>
<a href="/en/account">Account</a>
<a href="/en/support">Support</a>
</nav>
<span class="links">
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
<img src="/img/cc-light.svg" alt="CreativeCommons" />
</a>
<a href="/en/webring">
<img src="/img/w-light.svg" alt="Webring" />
</a>
<a href="https://gitea.dmz.rs/Decentrala/website">
<img src="/img/git-light.svg" alt="SourceCode" />
</a>
<a href="https://balkan.fedive.rs/@decentrala">
<img src="/img/mastodon-light.svg" alt="Mastodon" />
</a>
</span>
</footer>
</body>
</html>
{% block content %}
<div class="page-wrap">
{{ content|safe }}
</div>
{% endblock %}

View File

@@ -1,91 +1,11 @@
<!doctype html>
<html lang="sr">
<head>
<script>
(function () {
const theme = localStorage.getItem("theme");
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
if (theme === "dark" || (!theme && prefersDark))
document.documentElement.classList.add("dark");
})();
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{% extends "base.html" %}
<!-- <pre>
{% block title %}{{ title }} Decentrala{% endblock %}
*@@*
*@@@@*
*@@*
||
||
*@@* *@@* *@@*
*@@@@*===*@@@@*===*@@@@*
*@@* *@@* *@@*
|| //
|| //
*@@*//
*@@@@*
*@@*
{% block extra_styles %}{{ extra_styles|safe }}{% endblock %}
____ _____ ____ _____ _ _ _____ ____ _ _ _
| _ \| ____/ ___| ____| \ | |_ _| _ \ / \ | | / \
| | | | _|| | | _| | \| | | | | |_) | / _ \ | | / _ \
| |_| | |__| |___| |___| |\ | | | | _ < / ___ \| |___ / ___ \
|____/|_____\____|_____|_| \_| |_| |_| \_\/_/ \_\_____/_/ \_\
</pre> -->
<link rel="stylesheet" href="/styles/reset.css" />
<link rel="stylesheet" href="/styles/style.css" />
<!--ADDITIONAL_STYLE-->
<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon" />
<script src="/scripts/main.js" defer></script>
<title><!--TITLE--> Decentrala</title>
<link rel="alternate" hreflang="en" href="/en/PAGE_NAME" />
</head>
<body>
<header>
<a id="logo" href="/">
<img src="/img/logo-light.svg" alt="Logo" />
Decentrala
</a>
<button id="theme-switcher"></button>
<a class="lang" hreflang="en" href="/en/PAGE_NAME">EN</a>
</header>
<main>
<div class="page-wrap">
<!--MAIN-->
</div>
</main>
<footer>
<button class="hamburger closed">
<img src="/img/strelica-closed-light.svg" alt="Menu" />
</button>
<nav class="menu">
<a href="/events">Događaji</a>
<a href="/services">Servisi</a>
<a href="/statute">Statut</a>
<a href="/about">O nama</a>
<a class="account" href="/account">Nalog</a>
<a href="/support">Podrška</a>
</nav>
<span class="links">
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
<img src="/img/cc-light.svg" alt="CreativeCommons" />
</a>
<a href="/webring">
<img src="/img/w-light.svg" alt="Webring" />
</a>
<a href="https://gitea.dmz.rs/Decentrala/website">
<img src="/img/git-light.svg" alt="SourceCode" />
</a>
<a href="https://balkan.fedive.rs/@decentrala">
<img src="/img/mastodon-light.svg" alt="Mastodon" />
</a>
</span>
</footer>
</body>
</html>
{% block content %}
<div class="page-wrap">
{{ content|safe }}
</div>
{% endblock %}