Backend: Added the ability to gather a project title from a software/programming language. Frontend: Tooltip implementation with backend.
This commit is contained in:
parent
1a3297199f
commit
b9e78d7e49
7 changed files with 168 additions and 8 deletions
|
@ -85,4 +85,10 @@ pub struct AllTags {
|
|||
pub icon: Option<String>,
|
||||
pub type_icon: Option<String>,
|
||||
pub color: Option<String>
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct SimpleProject {
|
||||
pub project_id: Option<i32>,
|
||||
pub title: Option<String>
|
||||
}
|
|
@ -10,7 +10,10 @@ use std::net::SocketAddr;
|
|||
use tower_http::cors::CorsLayer;
|
||||
|
||||
mod db;
|
||||
use db::{Education, Experience, Info, Languages, ProgrammingLanguages, Project, Softwares, Tags, AllTags};
|
||||
use db::{
|
||||
AllTags, Education, Experience, Info, Languages, ProgrammingLanguages, Project, SimpleProject,
|
||||
Softwares, Tags,
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
|
@ -30,6 +33,14 @@ async fn main() -> Result<()> {
|
|||
.route("/skills/:id", get(skills))
|
||||
.route("/tags/:info_id/:project_id", get(tags))
|
||||
.route("/tags/:id", get(alltags))
|
||||
.route(
|
||||
"/getproject_programming/:programming_id",
|
||||
get(getproject_programming),
|
||||
)
|
||||
.route(
|
||||
"/getproject_software/:software_id",
|
||||
get(getproject_software),
|
||||
)
|
||||
.with_state(pool)
|
||||
.layer(CorsLayer::very_permissive());
|
||||
|
||||
|
@ -166,3 +177,41 @@ async fn alltags(Path(info_id): Path<i32>, State(pool): State<PgPool>) -> Json<V
|
|||
.unwrap_or(vec![]);
|
||||
Json(datas)
|
||||
}
|
||||
|
||||
async fn getproject_programming(
|
||||
Path(programming_id): Path<i32>,
|
||||
State(pool): State<PgPool>,
|
||||
) -> Json<Vec<SimpleProject>> {
|
||||
let datas = sqlx::query_as!(
|
||||
SimpleProject,
|
||||
"SELECT project_id, title
|
||||
FROM public.project p
|
||||
JOIN public.project_tags pt ON p.id = pt.project_id
|
||||
WHERE pt.programming_languages_id = $1
|
||||
",
|
||||
programming_id
|
||||
)
|
||||
.fetch_all(&pool)
|
||||
.await
|
||||
.unwrap_or(vec![]);
|
||||
Json(datas)
|
||||
}
|
||||
|
||||
async fn getproject_software(
|
||||
Path(software_id): Path<i32>,
|
||||
State(pool): State<PgPool>,
|
||||
) -> Json<Vec<SimpleProject>> {
|
||||
let datas = sqlx::query_as!(
|
||||
SimpleProject,
|
||||
"SELECT project_id, title
|
||||
FROM public.project p
|
||||
JOIN public.project_tags pt ON p.id = pt.project_id
|
||||
WHERE pt.softwares_id = $1
|
||||
",
|
||||
software_id
|
||||
)
|
||||
.fetch_all(&pool)
|
||||
.await
|
||||
.unwrap_or(vec![]);
|
||||
Json(datas)
|
||||
}
|
||||
|
|
|
@ -9,9 +9,15 @@
|
|||
export let color = "#000000";
|
||||
export let type_icon = "mdi";
|
||||
export let shadow_color = null;
|
||||
export let show_tooltip = false;
|
||||
export let tooltip_data = [];
|
||||
|
||||
const white = shouldColorBeWhite(color.slice(1));
|
||||
let style;
|
||||
let pill_arrow;
|
||||
let pill_tooltip;
|
||||
let main_pill;
|
||||
|
||||
if (shadow_color === null) {
|
||||
style = `background-color: ${color};
|
||||
box-shadow: 0px 8px 18px -1px ${color}60;`;
|
||||
|
@ -19,12 +25,47 @@
|
|||
style = `background-color: ${color};
|
||||
box-shadow: 0px 8px 18px -1px ${shadow_color}60;`;
|
||||
}
|
||||
|
||||
function showingTooltip(visible) {
|
||||
if (visible && tooltip_data.length > 0) {
|
||||
pill_tooltip.style.visibility = "visible";
|
||||
pill_arrow.style.visibility = "visible";
|
||||
// adjusting top
|
||||
pill_tooltip.style.top = `${
|
||||
main_pill.offsetTop - pill_tooltip.offsetHeight - 17
|
||||
}px`;
|
||||
if (white) {
|
||||
pill_tooltip.style.boxShadow = `0px 8px 18px -1px ${color}60`;
|
||||
pill_arrow.style.filter = `drop-shadow(0px 8px 18px ${color}40)`;
|
||||
} else {
|
||||
pill_tooltip.style.boxShadow = `0px 8px 18px -1px #261C2C30`;
|
||||
pill_arrow.style.filter = `drop-shadow(0px 8px 18px #261C2C20)`;
|
||||
}
|
||||
} else {
|
||||
pill_tooltip.style.visibility = "hidden";
|
||||
pill_arrow.style.visibility = "hidden";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={white ? "pill-container pill-white" : "pill-container pill-black"}
|
||||
{style}
|
||||
on:focus={() => true}
|
||||
on:mouseover={() => showingTooltip(true)}
|
||||
on:mouseleave={() => showingTooltip(false)}
|
||||
role="link"
|
||||
tabindex="0"
|
||||
bind:this={main_pill}
|
||||
>
|
||||
{#if show_tooltip === true}
|
||||
<div class="pill-arrow" bind:this={pill_arrow} />
|
||||
<div class="pill-tooltip" bind:this={pill_tooltip}>
|
||||
{#each tooltip_data as td}
|
||||
<p>{td.title}</p>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if type_icon === "simpleicons"}
|
||||
<img
|
||||
height="20"
|
||||
|
|
|
@ -36,4 +36,36 @@
|
|||
|
||||
.pill-container svg {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.pill-tooltip {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
background-color: var(--color-background);
|
||||
color: var(--color-text);
|
||||
min-width: 5rem;
|
||||
border-radius: 0.4rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
visibility: hidden;
|
||||
transition: all .3s ease 0s;
|
||||
box-shadow: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.pill-arrow {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
transform: translateY(-2.2rem);
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
border-left: 20px solid transparent;
|
||||
border-right: 20px solid transparent;
|
||||
border-top: 20px solid var(--color-background);
|
||||
visibility: hidden;
|
||||
transition: all .3s ease 0s;
|
||||
filter: none;
|
||||
}
|
|
@ -13,8 +13,10 @@ export function processData(data) {
|
|||
const education = arrangeById(data.education);
|
||||
const skills = data.skills;
|
||||
const tags = data.tags;
|
||||
const project_programming = data.project_programming;
|
||||
const project_software = data.project_software;
|
||||
|
||||
return {info, experiences, education, skills, tags};
|
||||
return {info, experiences, education, skills, tags, project_programming, project_software};
|
||||
} else {
|
||||
return null; // Indicates an error
|
||||
}
|
||||
|
|
|
@ -18,10 +18,14 @@ export async function load(context) {
|
|||
}
|
||||
|
||||
const infos = [];
|
||||
const dataToGather = ['info', 'education', 'experience', 'skills/1', 'tags/1'];
|
||||
for (const url of dataToGather) {
|
||||
const project_software = [];
|
||||
const project_programming = [];
|
||||
const dataToGather =
|
||||
['info', 'education', 'experience', 'skills/1', 'tags/1'];
|
||||
for (const [index, url] of dataToGather.entries()) {
|
||||
const res = await fetchData(url);
|
||||
if (res.status == 0) {
|
||||
// Pushing data
|
||||
infos.push(res.data);
|
||||
} else {
|
||||
return {
|
||||
|
@ -30,6 +34,30 @@ export async function load(context) {
|
|||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < infos[3][2].length; i++) {
|
||||
const res =
|
||||
await fetchData(`getproject_software/${i + 1}`);
|
||||
if (res.status == 0) {
|
||||
project_software.push(res.data);
|
||||
} else {
|
||||
return {
|
||||
status: res.status
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < infos[3][1].length; i++) {
|
||||
const res =
|
||||
await fetchData(`getproject_programming/${i + 1}`);
|
||||
if (res.status == 0) {
|
||||
project_programming.push(res.data);
|
||||
}
|
||||
else {
|
||||
return {
|
||||
status: res.status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: 0,
|
||||
info: infos[0],
|
||||
|
@ -42,5 +70,7 @@ export async function load(context) {
|
|||
languages: infos[3][3],
|
||||
},
|
||||
tags: infos[4],
|
||||
project_programming: project_programming,
|
||||
project_software: project_software,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -134,14 +134,14 @@
|
|||
<Section icon={mdiPencil} title="Skills" />
|
||||
<SubSection icon={mdiXml} title="Programming Languages"/>
|
||||
<div class="subsection">
|
||||
{#each cv.skills.programming_languages as pilldata}
|
||||
<Pill name={pilldata.lang} type_icon={pilldata.type_icon} icon={pilldata.icon} color={pilldata.color}/>
|
||||
{#each cv.skills.programming_languages as pilldata, index (index)}
|
||||
<Pill name={pilldata.lang} type_icon={pilldata.type_icon} icon={pilldata.icon} color={pilldata.color} show_tooltip={true} tooltip_data={cv.project_programming[index]}/>
|
||||
{/each}
|
||||
</div>
|
||||
<SubSection icon={mdiApplication} title="Software"/>
|
||||
<div class="subsection">
|
||||
{#each cv.skills.softwares as pilldata}
|
||||
<Pill name={pilldata.software} type_icon={pilldata.type_icon} icon={pilldata.icon} color={pilldata.color}/>
|
||||
{#each cv.skills.softwares as pilldata, index (index)}
|
||||
<Pill name={pilldata.software} type_icon={pilldata.type_icon} icon={pilldata.icon} color={pilldata.color} show_tooltip={true} tooltip_data={cv.project_software[index]}/>
|
||||
{/each}
|
||||
</div>
|
||||
<SubSection icon={mdiEarth} title="Languages"/>
|
||||
|
|
Loading…
Add table
Reference in a new issue