mirror of
https://github.com/Superredstone/patrickcanal.it.git
synced 2026-09-29 05:37:52 +02:00
Compare commits
7
Commits
06d759e809
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83443e11cc
|
||
|
|
c8cf7ea7cd
|
||
|
|
f0888c4168
|
||
|
|
c2e5f9a3a2
|
||
|
|
6a4e6ba9c5
|
||
|
|
f54c4efb1d
|
||
|
|
02568054f1
|
+8
-3
@@ -5,19 +5,24 @@ from portfolio import models
|
|||||||
|
|
||||||
@admin.register(models.JobExperience)
|
@admin.register(models.JobExperience)
|
||||||
class JobExperienceAdmin(admin.ModelAdmin):
|
class JobExperienceAdmin(admin.ModelAdmin):
|
||||||
pass
|
list_display = ["company", "position", "start", "end"]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.JobTask)
|
@admin.register(models.JobTask)
|
||||||
class JobTaskAdmin(admin.ModelAdmin):
|
class JobTaskAdmin(admin.ModelAdmin):
|
||||||
pass
|
list_display = ["job__company", "description", "job__start", "job__end"]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.Company)
|
@admin.register(models.Company)
|
||||||
class CompanyAdmin(admin.ModelAdmin):
|
class CompanyAdmin(admin.ModelAdmin):
|
||||||
pass
|
list_display = ["name", "location"]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.Project)
|
@admin.register(models.Project)
|
||||||
class ProjectAdmin(admin.ModelAdmin):
|
class ProjectAdmin(admin.ModelAdmin):
|
||||||
list_display = ["name", "short_description"]
|
list_display = ["name", "short_description"]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(models.ProjectTag)
|
||||||
|
class ProjectTagAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ["name", "color"]
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 6.1.1 on 2026-09-15 17:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('portfolio', '0003_project_alter_jobtask_job'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='company',
|
||||||
|
name='color',
|
||||||
|
field=models.CharField(default='000000', max_length=6, verbose_name='Color (hex)'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='company',
|
||||||
|
name='logo',
|
||||||
|
field=models.FileField(upload_to='portfolio/companies_logo/'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 6.1.1 on 2026-09-15 18:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('portfolio', '0004_company_color_alter_company_logo'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ProjectTag',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=25, verbose_name='Name')),
|
||||||
|
('color', models.CharField(default='000000', max_length=6, verbose_name='Color (hex)')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='project',
|
||||||
|
name='tags',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='projects', to='portfolio.projecttag', verbose_name='Tags'),
|
||||||
|
),
|
||||||
|
]
|
||||||
+33
-1
@@ -9,7 +9,14 @@ class Company(models.Model):
|
|||||||
location = models.CharField(
|
location = models.CharField(
|
||||||
verbose_name=_("Location"), max_length=255, blank=False, null=False
|
verbose_name=_("Location"), max_length=255, blank=False, null=False
|
||||||
)
|
)
|
||||||
logo = models.FileField(upload_to="uploads/portfolio/companies_logo/")
|
color = models.CharField(
|
||||||
|
verbose_name=_("Color (hex)"),
|
||||||
|
max_length=6,
|
||||||
|
null=False,
|
||||||
|
blank=False,
|
||||||
|
default="000000",
|
||||||
|
)
|
||||||
|
logo = models.FileField(upload_to="portfolio/companies_logo/")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -50,6 +57,22 @@ class JobTask(models.Model):
|
|||||||
return self.job.__str__()
|
return self.job.__str__()
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTag(models.Model):
|
||||||
|
name = models.CharField(
|
||||||
|
verbose_name=_("Name"), max_length=25, blank=False, null=False
|
||||||
|
)
|
||||||
|
color = models.CharField(
|
||||||
|
verbose_name=_("Color (hex)"),
|
||||||
|
max_length=6,
|
||||||
|
null=False,
|
||||||
|
blank=False,
|
||||||
|
default="000000",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Project(models.Model):
|
class Project(models.Model):
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
verbose_name=_("Name"), max_length=256, null=False, blank=False
|
verbose_name=_("Name"), max_length=256, null=False, blank=False
|
||||||
@@ -58,3 +81,12 @@ class Project(models.Model):
|
|||||||
verbose_name=_("Short description"), max_length=512, blank=False, null=False
|
verbose_name=_("Short description"), max_length=512, blank=False, null=False
|
||||||
)
|
)
|
||||||
url = models.URLField(verbose_name=_("URL"), blank=True, null=False)
|
url = models.URLField(verbose_name=_("URL"), blank=True, null=False)
|
||||||
|
tags = models.ManyToManyField(
|
||||||
|
ProjectTag,
|
||||||
|
verbose_name=_("Tags"),
|
||||||
|
blank=True,
|
||||||
|
related_name="projects",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|||||||
@@ -97,7 +97,7 @@
|
|||||||
<p class="text-primary mb-0">{{ je.start }} - {% if je.end %}{{ je.end }}{% else %}{% trans "today" %}{% endif %}</p>
|
<p class="text-primary mb-0">{{ je.start }} - {% if je.end %}{{ je.end }}{% else %}{% trans "today" %}{% endif %}</p>
|
||||||
<h2 class="fs-2">{{ je.position }}</h2>
|
<h2 class="fs-2">{{ je.position }}</h2>
|
||||||
<div>
|
<div>
|
||||||
<div class="text-danger">{{ je.company.name }}</div>
|
<div style="color: #{{ je.company.color }};">{{ je.company.name }}</div>
|
||||||
<div class="text-secondary">{{ je.company.location }}</div>
|
<div class="text-secondary">{{ je.company.location }}</div>
|
||||||
<div class="mt-2 text-white">
|
<div class="mt-2 text-white">
|
||||||
{% for jt in je.job_tasks.all %}
|
{% for jt in je.job_tasks.all %}
|
||||||
|
|||||||
@@ -1,29 +1,21 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mt-4">
|
<div class="container mt-2 mt-md-4">
|
||||||
<div class="row row-deck row-cards">
|
<form class="mb-2 mb-md-4">
|
||||||
{% for project in object_list %}
|
<div class="form-floating">
|
||||||
<div class="col-md-4">
|
<input type="text"
|
||||||
{% if project.url %}
|
class="form-control"
|
||||||
<a class="card card-link card-link-pop"
|
id="floating-name"
|
||||||
href="{{ project.url }}"
|
placeholder=""
|
||||||
target="_blank">
|
name="query"
|
||||||
<div class="card-body">
|
autocomplete="off"
|
||||||
<h4>{{ project.name }}</h4>
|
hx-target="#projects"
|
||||||
<p>{{ project.short_description }}</p>
|
hx-get="{% url 'projects-query' %}"
|
||||||
</div>
|
hx-trigger="load, input, delay:200ms" />
|
||||||
</a>
|
<label for="floating-name">{% trans "Search" %}</label>
|
||||||
{% else %}
|
</div>
|
||||||
<div class="card">
|
</form>
|
||||||
<div class="card-body">
|
<div id="projects"></div>
|
||||||
<h4>{{ project.name }}</h4>
|
|
||||||
<p>{{ project.short_description }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<div class="row row-deck row-cards">
|
||||||
|
{% for project in object_list %}
|
||||||
|
<div class="col-md-4">
|
||||||
|
{% if project.url %}
|
||||||
|
<a class="card card-link card-link-pop"
|
||||||
|
href="{{ project.url }}"
|
||||||
|
target="_blank">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4>{{ project.name }}</h4>
|
||||||
|
<p>{{ project.short_description }}</p>
|
||||||
|
<div>
|
||||||
|
{% for t in project.tags.all %}
|
||||||
|
<div class="badge text-white fs-5"
|
||||||
|
style="background-color: #{{ t.color }}">{{ t }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4>{{ project.name }}</h4>
|
||||||
|
<p>{{ project.short_description }}</p>
|
||||||
|
<div>
|
||||||
|
{% for t in project.tags.all %}
|
||||||
|
<div class="badge text-white fs-5"
|
||||||
|
style="background-color: #{{ t.color }}">{{ t }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
@@ -5,6 +5,7 @@ from portfolio import views
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.PortfolioView.as_view(), name="portfolio"),
|
path("", views.PortfolioView.as_view(), name="portfolio"),
|
||||||
path("projects/", views.ProjectList.as_view(), name="projects"),
|
path("projects/", views.ProjectList.as_view(), name="projects"),
|
||||||
|
path("projects/query/", views.ProjectListQuery.as_view(), name="projects-query"),
|
||||||
path("contact/", views.ContactSend.as_view(), name="contact"),
|
path("contact/", views.ContactSend.as_view(), name="contact"),
|
||||||
path("company/<int:pk>/logo/", views.CompanyLogo.as_view(), name="company-logo"),
|
path("company/<int:pk>/logo/", views.CompanyLogo.as_view(), name="company-logo"),
|
||||||
]
|
]
|
||||||
|
|||||||
+19
-2
@@ -1,4 +1,5 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db.models import Q
|
||||||
from django.http.response import FileResponse, HttpResponseBadRequest
|
from django.http.response import FileResponse, HttpResponseBadRequest
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import DetailView, ListView, TemplateView
|
from django.views.generic import DetailView, ListView, TemplateView
|
||||||
@@ -18,9 +19,8 @@ class PortfolioView(TemplateView):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ProjectList(ListView):
|
class ProjectList(TemplateView):
|
||||||
template_name = "project_list.html"
|
template_name = "project_list.html"
|
||||||
model = models.Project
|
|
||||||
|
|
||||||
|
|
||||||
class ContactSend(TemplateView):
|
class ContactSend(TemplateView):
|
||||||
@@ -49,3 +49,20 @@ class CompanyLogo(DetailView):
|
|||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
company = self.get_object()
|
company = self.get_object()
|
||||||
return FileResponse(company.logo)
|
return FileResponse(company.logo)
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectListQuery(ListView):
|
||||||
|
template_name = "project_list_query.html"
|
||||||
|
model = models.Project
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
query = self.request.GET.get("query")
|
||||||
|
if not query:
|
||||||
|
return super().get_queryset()
|
||||||
|
|
||||||
|
return (
|
||||||
|
super()
|
||||||
|
.get_queryset()
|
||||||
|
.filter(Q(name__contains=query) | Q(tags__name__contains=query))
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user