add projects view and template

This commit is contained in:
2024-11-10 04:47:40 +01:00
parent 5eb0246863
commit a3de4dcb43
21 changed files with 350 additions and 65 deletions

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@
# will have compiled files and executables # will have compiled files and executables
debug/ debug/
target/ target/
node_modules/
# include cargo lock # include cargo lock
!Cargo.lock !Cargo.lock

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,31 @@
document.addEventListener('DOMContentLoaded', () => {
const carousels = document.querySelectorAll('[id^="carousel-"]');
carousels.forEach((carousel) => {
let buttons = carousel.querySelectorAll('.carousel-button');
let activeSlide = 0;
buttons.forEach((button, index) => {
button.addEventListener('click', () => {
let currentSlide = carousel.querySelector(
'.carousel-item:not(.opacity-0)'
);
if (currentSlide) {
currentSlide.classList.add('opacity-0');
}
let newSlide = carousel.querySelectorAll('.carousel-item')[index];
if (newSlide) {
newSlide.classList.remove('opacity-0');
}
activeSlide = index;
});
});
setInterval(() => {
if (buttons.length === 0 || buttons.length === 1) {
return;
}
let nextSlide = (activeSlide + 1) % buttons.length;
buttons[nextSlide].click();
}, 3000);
});
});

View File

@@ -13,7 +13,7 @@
/> />
</head> </head>
<body class="bg-gray-800"> <body class="bg-gray-800 scroll-smooth">
<div class="flex flex-col h-full min-h-screen text-white"> <div class="flex flex-col h-full min-h-screen text-white">
{% include "website/components/navbar.html" %} {% include "website/components/navbar.html" %}
<div <div

View File

@@ -17,7 +17,7 @@
&copy; Gabriel Kaszewski, 2024. All rights reserved. &copy; Gabriel Kaszewski, 2024. All rights reserved.
</p> </p>
<p> <p>
Made with <span class="text-red-500 fa-solid fa-heart"></span> in Poland Made with 💗 in Poland
</p> </p>
<span class="flex-1"></span> <span class="flex-1"></span>
<a href="/projects"> Projects </a> <a href="/projects"> Projects </a>

View File

@@ -123,30 +123,33 @@
</div> </div>
<div class="w-full mt-8"></div> <div class="w-full mt-8"></div>
<div <div
class="flex flex-col items-center justify-center gap-4 rounded md:w-fit max-w-[60ch] text-[1.25rem] leading-[1.8] text-left p-4 text-pretty" id="who-am-i"
class="flex flex-col items-center justify-center gap-4 p-4 rounded md:w-fit"
> >
<h3 class="mt-4 mb-2 text-5xl font-bold tracking-tight">Who am I? 🤔</h3> <h3 class="mt-4 mb-2 text-5xl font-bold tracking-tight">Who am I? 🤔</h3>
<section class="leading-relaxed text-white"> <section class="prose text-white md:prose-lg lg:prose-xl">
<p> <p>
Hi, my name is Gabriel Kaszewski, and I am a Bioinformatics student 🧬 and Hi, my name is Gabriel Kaszewski, and I am a Bioinformatics student 🧬 and
self-taught full-stack developer 💻. self-taught full-stack developer 💻.
</p> </p>
<p> <p>
I started coding when I was 11 🚀. I love solving problems and writing My journey with programming started when I was 11 🚀. I love solving problems and creating software that
software 👨‍💻. resolves them 👨‍💻.
</p> </p>
<p> <p>
Currently, I am working as a Python Developer at digimonkeys.com 🐒. I am Currently, I am working as a Python Developer at digimonkeys.com 🐒. In my free time I like to read about
very passionate about Computer Science 💾. new technologies and work on my projects 📚.
</p> </p>
</section> </section>
</div> </div>
<div id="skills" class="flex flex-col items-center justify-center gap-4 p-4 rounded md:w-fit">
<h3 class="mt-4 mb-2 text-5xl font-bold tracking-tight">Skills 🛠️</h3> <h3 class="mt-4 mb-2 text-5xl font-bold tracking-tight">Skills 🛠️</h3>
{% for skill in skills %} {{ chip::chip(text=skill.name) }} {%endfor%} {% for skill in skills %} {{ chip::chip(text=skill.name) }} {%endfor%}
<section class="flex flex-wrap justify-center w-1/2 gap-4"></section> </div>
<div id="experience" class="flex flex-col items-center justify-center gap-4 p-4 rounded md:w-fit">
<h3 class="mt-4 mb-2 text-5xl font-bold tracking-tight">Experience 📈</h3> <h3 class="mt-4 mb-2 text-5xl font-bold tracking-tight">Experience 📈</h3>
{% for job in jobs %} {% for job in jobs %}
<div class="flex flex-col gap-2 p-4 text-black bg-gray-100 rounded-lg"> <div class="flex flex-col gap-2 p-4 text-black bg-gray-50 rounded-lg max-w-[20rem] shadow-lg">
<h4 class="text-2xl"> <h4 class="text-2xl">
<span class="fas fa-user-circle"></span> {{ job.position }} <span class="fas fa-user-circle"></span> {{ job.position }}
</h4> </h4>
@@ -165,9 +168,12 @@
</h6> </h6>
{% endif %} {% endif %}
<p class="font-bold"><span class="fas fa-microchip"></span> Technologies</p> <p class="font-bold"><span class="fas fa-microchip"></span> Technologies</p>
{% for technology in job.technologies %} {{ chip::chip(text=technology.name) <div class="flex flex-wrap items-center w-full gap-2">
{% for technology in job.technologies %} {{ chip::chip(text=technology)
}} {% endfor %} }} {% endfor %}
</div> </div>
</div>
{%endfor%} {%endfor%}
</div>
<section class="flex flex-col flex-wrap justify-center gap-4 m-4"></section> <section class="flex flex-col flex-wrap justify-center gap-4 m-4"></section>
{% endblock content %} {% endblock content %}

View File

@@ -0,0 +1,16 @@
{% macro image_carousel(id, thumbnails) %}
<div id="{{ id }}" class="carousel relative shadow-lg w-full max-w-full md:max-w-[50hw] h-[40rem]">
<div class="relative w-full h-full overflow-hidden carousel-inner">
{% for thumbnail in thumbnails %}
<div class="carousel-item absolute inset-0 w-full h-full {% if forloop.first %}{% else %} opacity-0 {% endif %} transition-opacity ease-in-out delay-250 duration-500">
<img alt="slide" src="{{ thumbnail }}" class="object-cover w-full h-full">
</div>
{% endfor %}
</div>
<div class="absolute bottom-0 z-50 flex justify-center w-full gap-2 py-2">
{% for thumbnail in thumbnails %}
<button class="carousel-button" data-target="{{ forloop.counter0 }}"></button>
{% endfor %}
</div>
</div>
{% endmacro image_carousel %}

View File

@@ -0,0 +1,98 @@
{% import "website/macros/chip.html" as chip %}
{% import "website/macros/image_carousel.html" as image_carousel %}
{% macro project_item(project) %}
<script src="/static/js/project-item.js"></script>
<div class="flex items-center justify-between w-full h-full gap-4 text-white">
<div class="flex flex-col w-full gap-4 m-4 md:w-1/3">
<div class="prose">
<h1 class="text-white">{{ project.name }}</h1>
<p class="text-white whitespace-pre-wrap">{{ project.short_description }}</p>
</div>
<div class="flex flex-wrap justify-center gap-2 md:justify-start">
{% for technology in project.technologies %}
{{ chip::chip(text=technology) }}
{% endfor %}
</div>
<a href="/projects/{{ project.name }}"
class="w-full p-2 text-center border border-yellow-400 rounded-xl hover:bg-yellow-400">Read more</a>
<div class="flex flex-wrap gap-2 sm:justify-center md:justify-start">
{% if project.githubUrl %}
<a href="{{ project.github_url }}" target="_blank" rel="noopener noreferrer"
class="w-full p-2 text-center border border-yellow-400 rounded-xl hover:bg-yellow-400">
<span class="fa-brands fa-github"></span>
CODE
</a>
{% endif %}
{% if project.visitUrl %}
<a href="{{ project.visit_url }}" target="_blank" rel="noopener noreferrer"
class="w-full p-2 text-center border border-yellow-400 rounded-xl hover:bg-yellow-400">
<span class="fas fa-eye"></span>
LIVE
</a>
{% endif %}
{% if project.downloadUrl %}
<a href="{{ project.download_url }}" target="_blank" rel="noopener noreferrer"
class="w-full p-2 text-center border border-yellow-400 rounded-xl hover:bg-yellow-400">
<span class="fas fa-cloud-download-alt"></span>
DOWNLOAD
</a>
{% endif %}
</div>
{% if project.thumbnails|length > 0 %}
<div class="w-full m-2 md:hidden">
{% set carousel_id = "carousel-mobile-" ~ project.id %}
{{ image_carousel::image_carousel(id=carousel_id, thumbnails=project.thumbnails) }}
</div>
{% endif %}
{% if project.thumbnails|length == 0 %}
<div class="w-full m-2 md:hidden">
<div class="bg-gradient-to-r from-violet-600 to-indigo-600 shadow-lg w-full max-w-full md:max-w-[50hw] h-[40rem] flex items-center justify-center">
{% if project.category == "Desktop" %}
<svg title="desktop" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-app-window"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M10 4v4"/><path d="M2 8h20"/><path d="M6 4v4"/></svg>
{% endif %}
{% if project.category == "Mobile" %}
<svg title="mobile" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-smartphone"><rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/></svg>
{%endif%}
{% if project.category == "Web" %}
<svg title="web" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>
{%endif%}
{% if project.category == "Api" %}
<svg title="API" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-monitor-cog"><path d="M12 17v4"/><path d="m15.2 4.9-.9-.4"/><path d="m15.2 7.1-.9.4"/><path d="m16.9 3.2-.4-.9"/><path d="m16.9 8.8-.4.9"/><path d="m19.5 2.3-.4.9"/><path d="m19.5 9.7-.4-.9"/><path d="m21.7 4.5-.9.4"/><path d="m21.7 7.5-.9-.4"/><path d="M22 13v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"/><path d="M8 21h8"/><circle cx="18" cy="6" r="3"/></svg>
{%endif%}
{% if project.category == "Game" %}
<svg title="game" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-gamepad-2"><line x1="6" x2="10" y1="11" y2="11"/><line x1="8" x2="8" y1="9" y2="13"/><line x1="15" x2="15.01" y1="12" y2="12"/><line x1="18" x2="18.01" y1="10" y2="10"/><path d="M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"/></svg>
{%endif%}
</div>
</div>
{% endif %}
</div>
{% if project.thumbnails|length > 0 %}
<div class="hidden m-2 md:flex md:w-1/2">
{% set carousel_id = "carousel-desktop-" ~ project.id %}
{{ image_carousel::image_carousel(id=carousel_id, thumbnails=project.thumbnails) }}
</div>
{% endif %}
{% if project.thumbnails|length == 0 %}
<div class="hidden m-2 md:flex md:w-1/2">
<div class="bg-gradient-to-r from-violet-600 to-indigo-600 shadow-lg w-full max-w-full md:max-w-[50hw] h-[40rem] flex items-center justify-center">
{% if project.category == "Desktop" %}
<svg title="desktop" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-app-window"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M10 4v4"/><path d="M2 8h20"/><path d="M6 4v4"/></svg>
{% endif %}
{% if project.category == "Mobile" %}
<svg title="mobile" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-smartphone"><rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/></svg>
{%endif%}
{% if project.category == "Web" %}
<svg title="web" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>
{%endif%}
{% if project.category == "Api" %}
<svg title="API" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-monitor-cog"><path d="M12 17v4"/><path d="m15.2 4.9-.9-.4"/><path d="m15.2 7.1-.9.4"/><path d="m16.9 3.2-.4-.9"/><path d="m16.9 8.8-.4.9"/><path d="m19.5 2.3-.4.9"/><path d="m19.5 9.7-.4-.9"/><path d="m21.7 4.5-.9.4"/><path d="m21.7 7.5-.9-.4"/><path d="M22 13v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"/><path d="M8 21h8"/><circle cx="18" cy="6" r="3"/></svg>
{%endif%}
{% if project.category == "Game" %}
<svg title="game" xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-gamepad-2"><line x1="6" x2="10" y1="11" y2="11"/><line x1="8" x2="8" y1="9" y2="13"/><line x1="15" x2="15.01" y1="12" y2="12"/><line x1="18" x2="18.01" y1="10" y2="10"/><path d="M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"/></svg>
{%endif%}
</div>
</div>
{% endif %}
</div>
{% endmacro project_item %}

View File

@@ -1,6 +1,10 @@
{% import "website/macros/project_item.html" as project_item %}
{% extends "website/base.html" %} {% block content %} {% extends "website/base.html" %} {% block content %}
<span class="m-8"></span> <span class="m-8"></span>
<div class="flex flex-col w-full gap-4 m-4"> <div class="flex flex-col w-full gap-4 m-4">
<h1 class="text-5xl font-bold text-center">My projects</h1> <h1 class="text-5xl font-bold text-center">My projects</h1>
{% for project in projects %}
{{ project_item::project_item(project=project) }}
{% endfor %}
</div> </div>
{% endblock content %} {% endblock content %}

BIN
bun.lockb Normal file

Binary file not shown.

14
package.json Normal file
View File

@@ -0,0 +1,14 @@
{
"name": "gabrielkaszewski_rs",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"@tailwindcss/typography": "^0.5.15"
}
}

View File

@@ -8,3 +8,4 @@ pub mod tasks;
pub mod views; pub mod views;
pub mod workers; pub mod workers;
pub mod filters; pub mod filters;
pub mod shared;

View File

@@ -17,11 +17,3 @@ pub struct JobWithTechnologies {
pub technologies: Vec<String>, pub technologies: Vec<String>,
pub still_working: bool, pub still_working: bool,
} }
pub fn get_technologies_from_string(technologies: &str) -> Vec<String> {
technologies
.split(',')
.map(|s| s.to_string())
.filter(|s| !s.trim().is_empty())
.collect()
}

View File

@@ -7,20 +7,7 @@ impl ActiveModelBehavior for ActiveModel {
// extend activemodel below (keep comment for generators) // extend activemodel below (keep comment for generators)
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
struct ProjectWithTechnologies {
pub id: i32,
pub name: String,
pub technologies: Vec<String>,
pub short_description: String,
pub description: Option<String>,
pub category: String,
pub github_url: Option<String>,
pub download_url: Option<String>,
pub visit_url: Option<String>,
}
#[derive(Debug)]
pub enum Category { pub enum Category {
Web, Web,
Mobile, Mobile,
@@ -28,3 +15,33 @@ pub enum Category {
Game, Game,
Api, Api,
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProjectDto {
pub id: i32,
pub name: String,
pub short_description: String,
pub description: Option<String>,
pub category: Category,
pub github_url: Option<String>,
pub download_url: Option<String>,
pub visit_url: Option<String>,
pub technologies: Vec<String>,
pub thumbnails: Vec<String>,
}
pub fn get_category_from_string(category: &str) -> Category {
match category {
"Web" => Category::Web,
"Mobile" => Category::Mobile,
"Desktop" => Category::Desktop,
"Game" => Category::Game,
"Api" => Category::Api,
"web" => Category::Web,
"mobile" => Category::Mobile,
"desktop" => Category::Desktop,
"game" => Category::Game,
"api" => Category::Api,
_ => Category::Desktop,
}
}

View File

@@ -1,9 +1,9 @@
use loco_rs::prelude::*; use loco_rs::prelude::*;
use crate::models::{ use crate::{models::{
_entities::jobs::{Entity, Model}, _entities::jobs::{Entity, Model},
jobs::{get_technologies_from_string, JobWithTechnologies}, jobs::JobWithTechnologies,
}; }, shared::get_technologies_from_string::get_technologies_from_string};
pub async fn get_all_jobs(ctx: &AppContext) -> Result<Vec<Model>> { pub async fn get_all_jobs(ctx: &AppContext) -> Result<Vec<Model>> {
let jobs = Entity::find().all(&ctx.db).await?; let jobs = Entity::find().all(&ctx.db).await?;

View File

@@ -2,3 +2,4 @@ pub mod data;
pub mod jobs; pub mod jobs;
pub mod skills; pub mod skills;
pub mod website; pub mod website;
pub mod projects;

69
src/services/projects.rs Normal file
View File

@@ -0,0 +1,69 @@
use loco_rs::prelude::*;
use crate::{models::{_entities::{project_thumbnails, projects::{self, Entity, Model}}, projects::{get_category_from_string, ProjectDto}}, shared::get_technologies_from_string::get_technologies_from_string};
pub async fn get_all_projects(ctx: &AppContext) -> Result<Vec<Model>> {
let projects = Entity::find().all(&ctx.db).await?;
Ok(projects)
}
pub async fn get_project_by_id(ctx: &AppContext, id: i32) -> Result<Model> {
let project = Entity::find_by_id(id).one(&ctx.db).await?;
let project = project.ok_or_else(|| ModelError::EntityNotFound)?;
Ok(project)
}
pub async fn get_archived_projects(ctx: &AppContext) -> Result<Vec<Model>> {
let archived_projects = Entity::find()
.filter(
model::query::condition()
.eq(projects::Column::IsArchived, true)
.build(),
)
.all(&ctx.db)
.await?;
Ok(archived_projects)
}
pub async fn get_highlighted_projects(ctx: &AppContext) -> Result<Vec<Model>> {
let highlighted_projects = Entity::find()
.filter(
model::query::condition()
.eq(projects::Column::IsHighlighted, true)
.build(),
)
.all(&ctx.db)
.await?;
Ok(highlighted_projects)
}
pub async fn get_all_projects_dto(ctx: &AppContext) -> Result<Vec<ProjectDto>> {
let projects_with_thumbnails = Entity::find()
.find_with_related(project_thumbnails::Entity)
.all(&ctx.db)
.await?;
let projects_dto = projects_with_thumbnails
.into_iter()
.map(|(project, thumbnails)| {
let thumbnails = thumbnails
.into_iter()
.map(|thumbnail| thumbnail.data_id.to_string())
.collect();
ProjectDto {
id: project.id,
name: project.name,
short_description: project.short_description,
description: project.description,
category: get_category_from_string(&project.category),
github_url: project.github_url,
download_url: project.download_url,
visit_url: project.visit_url,
technologies: get_technologies_from_string(&project.technology),
thumbnails,
}
})
.collect();
Ok(projects_dto)
}

View File

@@ -0,0 +1,7 @@
pub fn get_technologies_from_string(technologies: &str) -> Vec<String> {
technologies
.split(',')
.map(|s| s.to_string())
.filter(|s| !s.trim().is_empty())
.collect()
}

1
src/shared/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod get_technologies_from_string;

View File

@@ -14,9 +14,9 @@ pub async fn index(v: impl ViewRenderer, ctx: &AppContext) -> Result<impl IntoRe
} }
pub async fn projects(v: impl ViewRenderer, ctx: &AppContext) -> Result<impl IntoResponse> { pub async fn projects(v: impl ViewRenderer, ctx: &AppContext) -> Result<impl IntoResponse> {
// let projects = services::projects::get_all_projects(ctx).await?; let projects = services::projects::get_all_projects_dto(ctx).await?;
format::render().view(&v, "website/projects.html", data!({"projects": {}})) format::render().view(&v, "website/projects.html", data!({"projects": projects}))
} }
pub async fn about(v: impl ViewRenderer) -> Result<impl IntoResponse> { pub async fn about(v: impl ViewRenderer) -> Result<impl IntoResponse> {

27
tsconfig.json Normal file
View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}