Backend: Some tweaks for project ids, ordering the tags. Frontend: Added full support for tags.

This commit is contained in:
Yohan Boujon 2024-01-28 18:34:05 +01:00
parent 7d829cc22f
commit 1a3297199f
9 changed files with 61 additions and 28 deletions

View file

@ -38,6 +38,7 @@ pub struct Experience {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct Project { pub struct Project {
pub id: Option<i32>,
pub date_done: Option<NaiveDate>, pub date_done: Option<NaiveDate>,
pub title: Option<String>, pub title: Option<String>,
pub description: Option<String>, pub description: Option<String>,

View file

@ -83,7 +83,7 @@ async fn skills(
)> { )> {
let project = sqlx::query_as!( let project = sqlx::query_as!(
Project, Project,
"SELECT date_done, title, description, github_link, picture_name, type_project FROM public.project WHERE project.info_id = $1 ORDER BY date_done DESC", "SELECT id, date_done, title, description, github_link, picture_name, type_project FROM public.project WHERE project.info_id = $1 ORDER BY date_done DESC",
id id
) )
.fetch_all(&pool) .fetch_all(&pool)
@ -155,7 +155,8 @@ async fn alltags(Path(info_id): Path<i32>, State(pool): State<PgPool>) -> Json<V
SELECT project_id, software, icon, type_icon, color SELECT project_id, software, icon, type_icon, color
FROM public.softwares s FROM public.softwares s
JOIN public.project_tags pt ON s.id = pt.softwares_id JOIN public.project_tags pt ON s.id = pt.softwares_id
WHERE pt.info_id = $1; WHERE pt.info_id = $1
ORDER BY project_id;
", ",
info_id info_id

View file

@ -1,29 +1,39 @@
<script> <script>
import SvgIcon from "@jamescoyle/svelte-icon"; import SvgIcon from "@jamescoyle/svelte-icon";
import "$lib/css/pill.css"; import "$lib/css/pill.css";
import { mdiHelp } from "@mdi/js"; import { mdiHelp } from "@mdi/js";
import { shouldColorBeWhite } from "$lib/js/color.js"; import { shouldColorBeWhite } from "$lib/js/color.js";
export let name = "Unknown"; export let name = "Unknown";
export let icon = mdiHelp; export let icon = mdiHelp;
export let color = "#000000"; export let color = "#000000";
export let type_icon = "mdi"; export let type_icon = "mdi";
export let shadow_color = null;
const white = shouldColorBeWhite(color.slice(1)); const white = shouldColorBeWhite(color.slice(1));
const style = `background-color: ${color}; let style;
if (shadow_color === null) {
style = `background-color: ${color};
box-shadow: 0px 8px 18px -1px ${color}60;`; box-shadow: 0px 8px 18px -1px ${color}60;`;
} else {
style = `background-color: ${color};
box-shadow: 0px 8px 18px -1px ${shadow_color}60;`;
}
</script> </script>
<div class={white ? "pill-container pill-white" : "pill-container pill-black"} {style}> <div
{#if type_icon === "simpleicons"} class={white ? "pill-container pill-white" : "pill-container pill-black"}
<img {style}
height="20" >
width="20" {#if type_icon === "simpleicons"}
src="https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/{icon}.svg" <img
alt={name} height="20"
/> width="20"
{:else} src="https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/{icon}.svg"
<SvgIcon type="mdi" path={icon} size="20" /> alt={name}
{/if} />
<p>{name}</p> {:else}
<SvgIcon type="mdi" path={icon} size="20" />
{/if}
<p>{name}</p>
</div> </div>

View file

@ -3,6 +3,7 @@
import "$lib/css/project-popup.css"; import "$lib/css/project-popup.css";
import "$lib/css/slide.css"; import "$lib/css/slide.css";
import Pill from "$lib/components/pill.svelte";
import { showPopup, popupDatas } from "$lib/js/popup.js"; import { showPopup, popupDatas } from "$lib/js/popup.js";
import SvgIcon from "@jamescoyle/svelte-icon"; import SvgIcon from "@jamescoyle/svelte-icon";
import { import {
@ -16,7 +17,7 @@
mdiLink, mdiLink,
mdiTag, mdiTag,
mdiBookMultiple, mdiBookMultiple,
mdiDownload mdiDownload,
} from "@mdi/js"; } from "@mdi/js";
// Variables // Variables
@ -25,11 +26,13 @@
let active = false; let active = false;
// Informations // Informations
export let tags;
let title = "Title"; let title = "Title";
let date = "Date"; let date = "Date";
let type_project = "Type of project"; let type_project = "Type of project";
let picture; let picture;
let description = "Description"; let description = "Description";
let id = 0;
async function popupShowed(data) { async function popupShowed(data) {
/** /**
@ -45,6 +48,7 @@
type_project = data.type_project; type_project = data.type_project;
picture = (await import(`/src/lib/img/${data.picture_name}`)).default; picture = (await import(`/src/lib/img/${data.picture_name}`)).default;
description = data.description; description = data.description;
id = data.id;
// Active set to true after the await to avoid conflict when clicking outside while the popup hasn't showed yet. // Active set to true after the await to avoid conflict when clicking outside while the popup hasn't showed yet.
active = true; active = true;
} }
@ -140,6 +144,19 @@
<SvgIcon size="35" path={mdiTag} type="mdi" /> <SvgIcon size="35" path={mdiTag} type="mdi" />
<p class="slide-subtitle slide-aftericon">Tags</p> <p class="slide-subtitle slide-aftericon">Tags</p>
</div> </div>
<div class="project-popup-link-container">
{#each tags as tag}
{#if tag.project_id === id}
<Pill
name={tag.lang}
type_icon={tag.type_icon}
icon={tag.icon}
color="#F8F1F1"
shadow_color="#261C2C"
/>
{/if}
{/each}
</div>
</div> </div>
<!-- Text --> <!-- Text -->
<div> <div>

View file

@ -17,6 +17,7 @@
const project_type = data.type_project; const project_type = data.type_project;
let picture; let picture;
const popDataObject = { const popDataObject = {
id: data.id,
title: data.title, title: data.title,
date: issued_date, date: issued_date,
type_project: data.type_project, type_project: data.type_project,

View file

@ -11,6 +11,7 @@
align-items: center; align-items: center;
font-family: 'Urbanist', sans-serif; font-family: 'Urbanist', sans-serif;
font-weight: 700; font-weight: 700;
cursor: default;
} }
.pill-white { .pill-white {

View file

@ -12,8 +12,9 @@ export function processData(data) {
const experiences = arrangeById(data.experience); const experiences = arrangeById(data.experience);
const education = arrangeById(data.education); const education = arrangeById(data.education);
const skills = data.skills; const skills = data.skills;
const tags = data.tags;
return {info, experiences, education, skills}; return {info, experiences, education, skills, tags};
} else { } else {
return null; // Indicates an error return null; // Indicates an error
} }

View file

@ -18,7 +18,7 @@ export async function load(context) {
} }
const infos = []; const infos = [];
const dataToGather = ['info', 'education', 'experience', 'skills/1']; const dataToGather = ['info', 'education', 'experience', 'skills/1', 'tags/1'];
for (const url of dataToGather) { for (const url of dataToGather) {
const res = await fetchData(url); const res = await fetchData(url);
if (res.status == 0) { if (res.status == 0) {
@ -41,5 +41,6 @@ export async function load(context) {
softwares: infos[3][2], softwares: infos[3][2],
languages: infos[3][3], languages: infos[3][3],
}, },
tags: infos[4],
}; };
} }

View file

@ -76,7 +76,7 @@
<svelte:window bind:scrollY bind:innerHeight bind:innerWidth on:scroll={sidebarScrollingHandler} on:resize={mobileCheck} /> <svelte:window bind:scrollY bind:innerHeight bind:innerWidth on:scroll={sidebarScrollingHandler} on:resize={mobileCheck} />
{#if data.status == 0} {#if data.status == 0}
<ProjectsPopup/> <ProjectsPopup tags={cv.tags} />
<div class="container-cv"> <div class="container-cv">
<!-- SIDEBAR DIV (LEFT) --> <!-- SIDEBAR DIV (LEFT) -->
<div class="sidebar" bind:this={sidebar}> <div class="sidebar" bind:this={sidebar}>