initial implementation of project references

This commit is contained in:
Tobias Gerwin 2023-02-08 22:52:22 +01:00
parent db8db2db6a
commit b7258a9ea1
18 changed files with 417 additions and 8 deletions

View File

@ -2,7 +2,7 @@
<div class="2xl:p-1 py-1 grid grid-cols-1 sm:grid-cols-[minmax(300px,_1fr)_3fr] gap-1 items-center bg-black fixed top-0 left-0 right-0 z-10 max-w-screen-2xl container mx-auto">
<div id="mTobiasGerwin" class="py-4 text-center bg-petrol-500 h-full w-full text-white">Tobias Gerwin</div>
<div id="mTobiasGerwin" class="py-4 text-center bg-petrol-500 h-full w-full text-white cursor-pointer">Tobias Gerwin</div>
<button id="btnOpenMenu" class="sm:hidden absolute inset-y-0 right-2 text-white">
@ -13,9 +13,10 @@
</button>
<div id="menu" class="panel sm:py-2 sm:px-0 sm:space-y-0 space-y-4 text-center sm:bg-white bg-celeste-300 sm:h-full h-0 sm:w-full w-1/2 sm:flex sm:flex-row flex-col justify-around sm:relative absolute right-0">
<div id="mProjekte" class="hover:bg-petrol-500 p-2 sm:mt-0 mt-4 transition hover:scale-105 hover:text-white cursor-pointer">
<a href="/projekte/"
id="mProjekte" class="hover:bg-petrol-500 p-2 sm:mt-0 mt-4 transition hover:scale-105 hover:text-white cursor-pointer">
Projekte
</div>
</a>
<div id="mUeberMich" class="hover:bg-petrol-500 p-2 transition hover:scale-105 hover:text-white cursor-pointer">
Über mich
</div>
@ -29,7 +30,7 @@
<script>
document.getElementById("btnOpenMenu").addEventListener("click", toggleMenu);
['mTobiasGerwin', 'mProjekte', 'mUeberMich', 'mKontakt'].forEach(elId => {
['mTobiasGerwin', 'mUeberMich', 'mKontakt'].forEach(elId => {
document.getElementById(elId).addEventListener("click", closeMenu);
document.getElementById(elId).addEventListener("click", scrollPage);
});

View File

@ -51,6 +51,7 @@ else:
INSTALLED_APPS = [
'home.apps.HomeConfig',
'projekte.apps.ProjekteConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',

View File

@ -14,9 +14,10 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.urls import include, path
from home import views as home_views
from projekte import views as projekte_views
from . import views
urlpatterns = [
@ -25,9 +26,11 @@ urlpatterns = [
urlpatterns += [
path('', home_views.index, name='index'),
path('impressum', home_views.impressum, name='impressum'),
path('datenschutz', home_views.datenschutz, name='datenschutz'),
path('kontakt', home_views.kontakt, name='kontakt'),
path('projekt/', include('projekte.urls')),
path('projekte/', projekte_views.index,),
path('impressum/', home_views.impressum, name='impressum'),
path('datenschutz/', home_views.datenschutz, name='datenschutz'),
path('kontakt/', home_views.kontakt, name='kontakt'),
]
urlpatterns += [
path('favicon.ico', views.favicon, name='favicon'),

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ProjekteConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'projekte'

View File

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,45 @@
{
"title": "DCA-BAU.DE",
"tags": [
"Projektmanagement", "Programmierung", "Administration"
],
"short_description": "DCA-BAU.DE ist die Software für eine professionelle Baustelledokumentation, -controlling und Auswertung mit visualsiertem SOLL/IST-Vergleich und integriertem Bautagebuch.",
"functions": [
],
"stack_list": [
"django",
"Vue.js",
"bootstrap",
"nginx",
"gunicorn",
"PostgreSQL",
"ubuntu"
],
"participant": "WINKEL + MANGELS Beratende Ingenieure Partnerschaftsgesellschaft mbB, Neuss",
"participant_logo": "https://bauberatung.wmbm.eu/wp-content/uploads/2021/04/wmbm_bauberatung_logo_L.svg",
"participant_link": "https://bauberatung.wmbm.eu/",
"participant_head": "WINKEL + MANGELS Beratende Ingenieure Partnerschaftsgesellschaft mbB<br>Heerdterbuschstraße 10<br>41460 Neuss",
"time": "2021-2022...",
"effort": "~100 AT",
"case_study": [
{
"tag": "p",
"content": ""
},
{
"tag": "p",
"content": ""
},
{
"tag": "img",
"alt": "Logo WhatsImmo",
"src": "https://whatsimmo.tobias-gerwin.de/static/WhatsImmo/img/logo.svg",
"caption": "Logo WhatsImmo"
},
{
}
],
"quote": "",
"quote_author": "Dr. Jörg Mangels"
}

View File

@ -0,0 +1,57 @@
{
"title": "WhatsImmo",
"tags": [
"Projektmanagement", "Programmierung", "Datenmigration"
],
"short_description": "Progressive Web-App für Hausverwaltungen.",
"functions": [
"Hierarchische Objektverwaltung",
"Auftragsverwaltung",
"Kontaktverwaltung",
"Chat-Funktion für alle Nutzer (WebSocket)",
"Progressive Web App (zur Installation auf Android Geräten)",
"Berechtigungskonzept",
"Datei Up-/ Download (per drag & drop)",
"Bildergallery (inkl. automatischer Komprimierung)",
"PDF-Vorschau",
"Automatischer E-Mail abruf und Auftragszuordnung (IMAP-Postfach)"
],
"stack_list": [
"<a class=\"hover:text-white transition\" href=\"https://docs.djangoproject.com\" target=\"_blank\">django</a>",
"Vue.js",
"tailwindcss",
"nginx",
"gunicorn",
"daphne",
"redis",
"SQLite",
"ubuntu"
],
"participant": "WINKEL + MANGELS GmbH, Neuss",
"participant_logo": "https://immobilien.wmbm.eu/wp-content/uploads/2021/05/wmbm_immobilien_logo_L.svg",
"participant_link": "https://immobilien.wmbm.eu",
"participant_head": "WINKEL + MANGELS GmbH<br>Heerdterbuschstraße 10<br>41460 Neuss",
"time": "10-11/2022",
"effort": "~30 AT",
"case_study": [
{
"tag": "p",
"content": ""
},
{
"tag": "p",
"content": ""
},
{
"tag": "img",
"alt": "Logo WhatsImmo",
"src": "https://whatsimmo.tobias-gerwin.de/static/WhatsImmo/img/logo.svg",
"caption": "Logo WhatsImmo"
},
{
}
],
"quote": "",
"quote_author": "Dr. Jörg Mangels"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

View File

View File

@ -0,0 +1,109 @@
{% extends "base.html" %}
{% load static %}
{% block extra_css %}
{% endblock %}
{% block body_class %}{% endblock %}
{% block content %}
{% include "header.html" %}
<main
class="bg-white 2xl:px-1 px-0 space-y-1 relative top-[68px] min-h-[calc(100vh-88px)] pb-[100px] container mx-auto max-w-screen-md">
<div class="mt-4 py-10 px-6 border-petrol-500 border-[0.5px] shadow-[0_35px_60px_-15px_rgba(0,0,0,0.7)]">
<div class="grid grid-cols-2">
<div>
<div class="flex">
<div class="bg-petrol-500 border-2 border-petrol-500">
<img class="object-contains h-28" src="/favicon.ico" alt="">
</div>
</div>
<div class="text-xs">
Immobilienmngt Beratung und IT<br>
Tobias Gerwin<br>
Oberbilker Allee 109<br>
40227 Düsseldorf<br>
Steuernummer: 133/5096/3252<br>
</div>
</div>
<div>
<div class="flex justify-end">
<a href="{{ participant_link }}" target="_blank">
<img class="object-contains h-28" src="{{ participant_logo }}" alt="Logo des Unternehmens: {{ participant }}">
</a>
</div>
<div class="text-xs text-right">
{{ participant_head }}
</div>
</div>
</div>
<h1 class="referenz border-y-2 border-petrol-500">
{{ title }}
</h1>
<h2 class="referenz">Key-Facts</h2>
<div class="grid gap-2 grid-cols-[120px_1fr_62px_60px] text-sm">
<div class="font-bold">Projektzeitraum:</div>
<div>{{ time }}</div>
<div class="font-bold">Aufwand:</div>
<div class="text-right">{{ effort }}</div>
<div class="font-bold">Leistungen:</div>
<div class="col-span-3 flex flex-wrap" colspan="3">
{% for tag in tags %}
<div class="px-2 py-0.5 mr-1 mb-1 rounded-lg bg-petrol-500 text-white text-sm">
{{ tag }}
</div>
{% endfor %}
</div>
<div class="font-bold">Funktionen:</div>
<div class="col-span-3">
{% for function in functions %}
<div class="grid grid-cols-[12px_1fr] items-start gap-4">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
class="mt-1 w-3 h-3 text-petrol-500">
<rect x="1" y="1" width="22" height="22" />
<path d="M 22.026296,2.1250279 C 9.8847251,11.19086 14.722256,30.081726 7.5560565,11.274574" fill="none"
stroke-linecap="round" stroke-width="2" />
</svg>
<div>{{ function }}</div>
</div>
{% endfor %}
</div>
<div class="font-bold">Stack:</div>
<div class="col-span-3 flex flex-wrap" colspan="3">
{% for stack in stack_list %}
<div class="px-2 py-0.5 mr-1 mb-1 rounded-lg bg-black text-lime-500 text-sm">
{{ stack }}
</div>
{% endfor %}
</div>
</div>
<h2 class="referenz">Case-Study</h2>
{{ case_study }}
{% if quote %}
<h2 class="referenz">Kundenzitat</h2>
<p class="referenz italic font-sans text-center ml-10 p-6 bg-gray-100 text-gray-600 border-l-4 border-gray-600">
"{{ quote }}"<br>
<span class="font-bold">- {{ quote_author }} -</span>
</p>
{% endif %}
</div>
</main>
{% endblock %}

View File

@ -0,0 +1,47 @@
{% extends "base.html" %}
{% load static %}
{% block extra_css %}
{% endblock %}
{% block body_class %}{% endblock %}
{% block content %}
{% include "header.html" %}
<main class="bg-white 2xl:px-1 px-0 space-y-1 relative top-[68px] min-h-[calc(100vh-88px)] pb-[80px] container mx-auto max-w-screen-md">
<div class="py-10 grid gap-2">
{% for referenz in referenzList %}
<a href="/projekt/{{ referenz.filename }}/" class="border-b-2 last:border-b-0">
<div class="p-1 hover:bg-gray-200">
<div class="flex items-center space-x-2">
<h2 class="font-bold text-3xl">{{ referenz.title }}</h2>
{% for tag in referenz.tags %}
<div class="px-2 py-0.5 rounded-lg bg-petrol-500 text-white text-sm">
{{ tag }}
</div>
{% endfor %}
</div>
<div>
<table class="text-left text-base text-gray-400">
<tr>
<th class="">Beschreibung:</th>
<td>{{ referenz.short_description }}</td>
</tr>
<tr>
<th class="">Auftraggeber:in:</th>
<td>{{ referenz.participant }}</td>
</tr>
<tr>
<th class="">Projektzeitraum:</th>
<td>{{ referenz.time }}</td>
</tr>
</table>
</div>
</div></a>
{% endfor %}
</div>
</main>
{% endblock %}

View File

@ -0,0 +1,49 @@
{% load static %}
<div class="text-sm grid gap-4">
<p class="">
Egal ob Gebäudemanager, Objektverwalter oder Hausverwaltungen, alle erfassen Information, tauschen diese aus und halten
sie nach, um ihren Kunden eine professionelle Dienstleistung zu bieten. Instant-Messenger, die Office-Suite und einige
spezifische Datenbanken halten die Informationen vor, die das Tagesgeschäft erfordert. Viel Aufwand fällt im Backoffice
bei der Zusammenführung der unterschiedlichen Datenpools an.
</p>
<p class="">
Das Foto, das der Kollege im Einsatz schnell via Smartphone gesendet hat, zu welchem Objekt gehörte das noch gleich?
Solche und ähnliche Probleme sollten mit der Entwicklung von „WhatsImmo“ behoben werden.
</p>
<div class="grid justify-center">
<img src="https://whatsimmo.tobias-gerwin.de/static/WhatsImmo/img/logo.svg" alt="Logo WhatsImmo">
<p class="text-xs text-gray-600"><span class="font-bold">Abb.:</span> Logo WhatsImmo</p>
</div>
<p>
WhatsImmo bietet mit seiner Objektverwaltung eine hierarchische Organisation
aller Informationen im Bereich des Immobilienmanagements. Von
Liegenschaften über Gebäude, Stockwerke und Zonen bis hin zu Räumen.
</p>
<div class="grid justify-center">
<img src="{% static 'projekte/img/Screenshot_WhatsImmo_Onjektverwaltung_leer.png' %}" alt="Screenshot der Objektverwaltung. Es wurden erste hierarchische Objekt in der linken Spalte angelegt. Kontakte, Dokumente oder Bilder sind noch nicht erfasst worden."
class="border-petrol-500 border-[0.5px]">
<p class="text-xs text-gray-600">
<span class="font-bold">Abb.:</span>
Screenshot der Objektverwaltung. Es wurden erste hierarchische
Objekt in der linken Spalte angelegt. Kontakte, Dokumente
oder Bilder sind noch nicht erfasst worden.
</p>
</div>
<p class="">
Beliebig viele Kontakte, Bilder und typisierte Dateien (Verträge, Schriftverkehr, Rechnungen, etc.) können erfasst
werden. Durch das responsive Design sind die Daten von jedem Endgerät aus leicht zugänglich.
Aufträge werden in der angeschlossenen Auftragsverwaltung nachverfolgt. Die Auftragsverwaltung ist in Chat-Gruppen
organisiert. Die Mitarbeiter:innen zur Auftragserfüllung sind Teilnehmer:innen der Chat-Gruppe und erhalten in Echtzeit
über das WebSocket-Protokoll neue Nachrichten.
Als Progressive Web App (PWA) ist eine einfache Installation auf dem Smartphone (derzeit nur Android) möglich und bietet
somit den Komfort einer nativen App.
</p>
</div>

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,8 @@
from django.urls import path
from . import views
app_name = 'projekte'
urlpatterns = [
# path('', views.index, name='index'),
path('<str:name>/', views.referenz, name='referenz'),
]

View File

@ -0,0 +1,74 @@
from django.shortcuts import render
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
from django.http import Http404
from pathlib import Path
import json
import os
# Create your views here.
REFERENZ_DIR = Path(__file__).resolve().parent
STACK_LINK = {
'django': "<a class=\"hover:text-white transition\" href=\"https://docs.djangoproject.com\" target=\"_blank\">django</a>",
'bootstrap': "<a class=\"hover:text-white transition\" href=\"https://getbootstrap.com/\" target=\"_blank\">bootstrap</a>",
'Vue.js': "<a class=\"hover:text-white transition\" href=\"https://vuejs.org/\" target=\"_blank\">Vue.js</a>",
'tailwindcss': "<a class=\"hover:text-white transition\" href=\"https://tailwindcss.com/\" target=\"_blank\">tailwindcss</a>",
'nginx': "<a class=\"hover:text-white transition\" href=\"https://nginx.org/\" target=\"_blank\">nginx</a>",
'gunicorn': "<a class=\"hover:text-white transition\" href=\"https://gunicorn.org/\" target=\"_blank\">gunicorn</a>",
'daphne': "<a class=\"hover:text-white transition\" href=\"https://github.com/django/daphne\" target=\"_blank\">daphne</a>",
'redis': "<a class=\"hover:text-white transition\" href=\"https://redis.io/\" target=\"_blank\">redis</a>",
'SQLite': "<a class=\"hover:text-white transition\" href=\"https://www.sqlite.org\" target=\"_blank\">SQLite</a>",
'PostgreSQL': "<a class=\"hover:text-white transition\" href=\"https://www.postgresql.org/\" target=\"_blank\">PostgreSQL</a>",
'ubuntu': "<a class=\"hover:text-white transition\" href=\"https://ubuntu.com/\" target=\"_blank\">ubuntu</a>",
}
def index(request):
referenzList: list = []
for root, dirs, files in os.walk(os.path.join(REFERENZ_DIR, 'referenzen')):
print(root, dirs, files)
for file in files:
with open(os.path.join(root, file), "r") as f:
data:dict = json.loads(f.read())
referenzList.append({
'title': data['title'],
'tags': data['tags'],
'short_description': data['short_description'],
'participant': data['participant'],
'time': data['time'],
'filename': file[:-5]
})
return render(request, 'referenzen.html', {'referenzList': referenzList})
def referenz(request, name):
if not os.path.exists(os.path.join(REFERENZ_DIR, 'referenzen', f'{name}.json')):
raise Http404
with open(os.path.join(REFERENZ_DIR, 'referenzen', f'{name}.json'), "r") as f:
context = json.loads(f.read())
context.update({
'filename': name,
'participant_head': mark_safe(context['participant_head']),
'case_study': render_to_string(name+'.html', {}),
})
save_stack_list:list = []
for stack in context['stack_list']:
save_stack_list.append(mark_safe(STACK_LINK.get(stack, stack)))
context['stack_list'] = save_stack_list
return render(request, 'referenz.html', context)