New Website in VueJS #6

Open
alice wants to merge 11 commits from new-website into main
9 changed files with 104 additions and 36 deletions
Showing only changes of commit 9944f24c4b - Show all commits

View file

@ -8,4 +8,4 @@ cover: "/img/wifi-pass.png"
link: "https://auth.lab.students.cs.unibo.it" link: "https://auth.lab.students.cs.unibo.it"
--- ---
In ADM Lab è presente una rete Wi-Fi dedicata agli studenti, che consente di accedere a Internet e alle risorse del laboratorio. Per connettersi alla rete Wi-Fi, è necessario conoscere le credenziali per connettersi all'Access Point. Una volta connessi si aprirà il captive portal, dove potete registarvi e creare le vostre credenziali ADM. Queste possono essere usate per accedere sì alla rete, ma anche a tutti i servizi che abbiamo realizzato e richiedono un'autenticazione, come [sasso](projects/sasso). In ADM Lab è presente una rete Wi-Fi dedicata agli studenti, che consente di accedere a Internet e alle risorse del laboratorio. Per connettersi alla rete Wi-Fi, è necessario conoscere le credenziali per connettersi all'Access Point. Una volta connessi si aprirà il captive portal, dove potete registarvi e creare le vostre credenziali ADM. Queste possono essere usate per accedere sì alla rete, ma anche a tutti i servizi che abbiamo realizzato e richiedono un'autenticazione, come [sasso](projects/sasso).

View file

@ -8,7 +8,7 @@
href="/src/assets/ADMstaff_logo-favicon.png" href="/src/assets/ADMstaff_logo-favicon.png"
/> />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ADMStaff - University of Bologna</title> <title>ADMStaff</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View file

@ -20,7 +20,8 @@
/> />
</svg> </svg>
</span> </span>
<span class="inline text-lg text-base-content/70 transition-colors group-hover:text-primary" <span
class="inline text-lg text-base-content/70 transition-colors group-hover:text-primary"
>ADMStaff</span >ADMStaff</span
> >
<span class="blinking-cursor ml-1"></span> <span class="blinking-cursor ml-1"></span>
@ -30,7 +31,10 @@
<div class="navbar-center hidden lg:flex"> <div class="navbar-center hidden lg:flex">
<ul class="menu menu-horizontal px-1 gap-1"> <ul class="menu menu-horizontal px-1 gap-1">
<li v-for="link in links" :key="link.path"> <li v-for="link in links" :key="link.path">
<RouterLink :to="link.path" class="text-base-content hover:text-primary"> <RouterLink
:to="link.path"
class="text-base-content hover:text-primary"
>
{{ $t(link.nameKey) }} {{ $t(link.nameKey) }}
</RouterLink> </RouterLink>
</li> </li>
@ -50,7 +54,11 @@
</div> </div>
<div class="dropdown dropdown-end lg:hidden"> <div class="dropdown dropdown-end lg:hidden">
<label tabindex="0" class="btn btn-ghost btn-square" aria-label="Open navigation menu"> <label
tabindex="0"
class="btn btn-ghost btn-square"
aria-label="Open navigation menu"
>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"

View file

@ -13,7 +13,7 @@ import { computed } from "vue";
export function useMeta(options) { export function useMeta(options) {
const { const {
title, title,
description = "ADMStaff - Amministratori di Sistemi e Reti - University of Bologna", description = "ADMStaff - gruppo di studenti di Informatica dell'Università di Bologna",
image, image,
url, url,
type = "website", type = "website",

View file

@ -8,4 +8,4 @@ export function resolveAssetPath(url) {
} }
return `/${url}`; return `/${url}`;
} }

View file

@ -1,13 +1,15 @@
<template> <template>
<div> <div>
<!-- About Section con cursore --> <!-- About Section con cursore -->
<div class="flex flex-col md:flex-row md:items-center md:mx-[5%] mb-12 md:my-12 md:gap-5"> <div
class="flex flex-col md:flex-row md:items-center md:mx-[5%] mb-12 md:my-12 md:gap-5"
>
<img <img
src="@/assets/ADMstaff_logo-modern-trasp.png" src="@/assets/ADMstaff_logo-modern-trasp.png"
alt="ADMStaff Logo" alt="ADMStaff Logo"
class="md:w-1/3" class="md:w-1/3"
/> />
<h4 id="about-text" class=" md:text-xl"> <h4 id="about-text" class="md:text-xl">
ADMstaff nasce come gruppo che fornisce servizi da studenti per ADMstaff nasce come gruppo che fornisce servizi da studenti per
studenti.<br /><br /> studenti.<br /><br />
Il nostro obiettivo è sperimentare e fare pratica su ciò che ci Il nostro obiettivo è sperimentare e fare pratica su ciò che ci

View file

@ -1,7 +1,9 @@
<template> <template>
<div class="max-w-4xl mx-auto"> <div class="max-w-4xl mx-auto">
<div v-if="loading" class="text-center py-12"> <div v-if="loading" class="text-center py-12">
<span class="text-primary">Loading<span class="blinking-cursor"></span></span> <span class="text-primary"
>Loading<span class="blinking-cursor"></span
></span>
</div> </div>
<div v-else-if="error" class="text-center py-12"> <div v-else-if="error" class="text-center py-12">

View file

@ -4,14 +4,18 @@
<p class="text-xs uppercase tracking-[0.3em] text-secondary mb-3"> <p class="text-xs uppercase tracking-[0.3em] text-secondary mb-3">
Selected work Selected work
</p> </p>
<h1 class="text-4xl sm:text-5xl font-bold text-primary mb-4 leading-tight"> <h1
class="text-4xl sm:text-5xl font-bold text-primary mb-4 leading-tight"
>
Projects<span class="blinking-cursor"></span> Projects<span class="blinking-cursor"></span>
</h1> </h1>
</section> </section>
<div v-if="loading" class="space-y-8"> <div v-if="loading" class="space-y-8">
<div class="grid gap-6 lg:grid-cols-[1.25fr_0.75fr]"> <div class="grid gap-6 lg:grid-cols-[1.25fr_0.75fr]">
<div class="animate-pulse rounded-3xl border border-base-300 bg-base-200/70 p-6 lg:p-8 min-h-[22rem]"> <div
class="animate-pulse rounded-3xl border border-base-300 bg-base-200/70 p-6 lg:p-8 min-h-[22rem]"
>
<div class="h-4 w-24 rounded bg-base-300 mb-6"></div> <div class="h-4 w-24 rounded bg-base-300 mb-6"></div>
<div class="h-10 w-3/4 rounded bg-base-300 mb-4"></div> <div class="h-10 w-3/4 rounded bg-base-300 mb-4"></div>
<div class="h-4 w-full rounded bg-base-300 mb-3"></div> <div class="h-4 w-full rounded bg-base-300 mb-3"></div>
@ -34,7 +38,9 @@
</div> </div>
<div v-else-if="error" class="text-center py-12"> <div v-else-if="error" class="text-center py-12">
<div class="max-w-md mx-auto rounded-3xl border border-base-300 bg-base-200 p-8"> <div
class="max-w-md mx-auto rounded-3xl border border-base-300 bg-base-200 p-8"
>
<span class="text-red-500 block mb-4">Error loading projects</span> <span class="text-red-500 block mb-4">Error loading projects</span>
<p class="text-base-content/75 mb-6"> <p class="text-base-content/75 mb-6">
Non riesco a caricare lelenco in questo momento. Non riesco a caricare lelenco in questo momento.
@ -55,12 +61,18 @@
class="group overflow-hidden rounded-[2rem] border border-base-300 bg-base-200/80 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-xl hover:border-primary/40" class="group overflow-hidden rounded-[2rem] border border-base-300 bg-base-200/80 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-xl hover:border-primary/40"
> >
<div class="grid lg:grid-cols-[1.2fr_0.8fr] min-h-[20rem]"> <div class="grid lg:grid-cols-[1.2fr_0.8fr] min-h-[20rem]">
<div class="order-2 lg:order-1 p-6 sm:p-8 lg:p-10 flex flex-col justify-between gap-6"> <div
class="order-2 lg:order-1 p-6 sm:p-8 lg:p-10 flex flex-col justify-between gap-6"
>
<div> <div>
<p class="text-xs uppercase tracking-[0.28em] text-secondary mb-4"> <p
class="text-xs uppercase tracking-[0.28em] text-secondary mb-4"
>
Featured project Featured project
</p> </p>
<h2 class="text-3xl sm:text-4xl font-bold text-primary mb-4 leading-tight group-hover:text-base-content transition-colors"> <h2
class="text-3xl sm:text-4xl font-bold text-primary mb-4 leading-tight group-hover:text-base-content transition-colors"
>
{{ featuredProject.frontmatter.title }} {{ featuredProject.frontmatter.title }}
</h2> </h2>
<div <div
@ -80,7 +92,11 @@
v-if="featuredServiceLink" v-if="featuredServiceLink"
:href="featuredServiceLink" :href="featuredServiceLink"
:target="isExternalLink(featuredServiceLink) ? '_blank' : null" :target="isExternalLink(featuredServiceLink) ? '_blank' : null"
:rel="isExternalLink(featuredServiceLink) ? 'noopener noreferrer' : null" :rel="
isExternalLink(featuredServiceLink)
? 'noopener noreferrer'
: null
"
class="inline-flex items-center rounded-full border border-base-300 bg-base-100/80 px-4 py-2 text-base-content/80 hover:border-primary/50 hover:text-primary transition-colors" class="inline-flex items-center rounded-full border border-base-300 bg-base-100/80 px-4 py-2 text-base-content/80 hover:border-primary/50 hover:text-primary transition-colors"
> >
Vai al servizio Vai al servizio
@ -99,14 +115,20 @@
class="h-auto max-h-[10rem] w-full max-w-[20rem] object-contain transition-transform duration-500 group-hover:scale-[1.03]" class="h-auto max-h-[10rem] w-full max-w-[20rem] object-contain transition-transform duration-500 group-hover:scale-[1.03]"
/> />
</div> </div>
<div v-else class="flex h-full min-h-[12rem] lg:min-h-[20rem] items-center justify-center p-8 text-secondary"> <div
v-else
class="flex h-full min-h-[12rem] lg:min-h-[20rem] items-center justify-center p-8 text-secondary"
>
No cover available No cover available
</div> </div>
</div> </div>
</div> </div>
</article> </article>
<div v-if="items.length > 1" class="grid gap-5 md:grid-cols-2 xl:grid-cols-3"> <div
v-if="items.length > 1"
class="grid gap-5 md:grid-cols-2 xl:grid-cols-3"
>
<article <article
v-for="project in items.slice(1)" v-for="project in items.slice(1)"
:key="project.path" :key="project.path"
@ -119,16 +141,24 @@
:alt="project.frontmatter.title" :alt="project.frontmatter.title"
class="h-full w-full object-contain transition-transform duration-500 group-hover:scale-[1.03]" class="h-full w-full object-contain transition-transform duration-500 group-hover:scale-[1.03]"
/> />
<div v-else class="flex h-full items-center justify-center text-secondary"> <div
v-else
class="flex h-full items-center justify-center text-secondary"
>
No cover available No cover available
</div> </div>
</div> </div>
<div class="p-5 sm:p-6"> <div class="p-5 sm:p-6">
<h2 class="text-xl sm:text-2xl font-bold text-primary mb-3 leading-snug group-hover:text-base-content transition-colors"> <h2
class="text-xl sm:text-2xl font-bold text-primary mb-3 leading-snug group-hover:text-base-content transition-colors"
>
{{ project.frontmatter.title }} {{ project.frontmatter.title }}
</h2> </h2>
<div class="text-base-content/75 line-clamp-3" v-html="getExcerpt(project.html, 140)"></div> <div
class="text-base-content/75 line-clamp-3"
v-html="getExcerpt(project.html, 140)"
></div>
<div class="mt-5 flex flex-wrap items-center gap-2 text-sm"> <div class="mt-5 flex flex-wrap items-center gap-2 text-sm">
<RouterLink <RouterLink
:to="`/projects/${project.slug}`" :to="`/projects/${project.slug}`"
@ -139,8 +169,14 @@
<a <a
v-if="getProjectLink(project)" v-if="getProjectLink(project)"
:href="getProjectLink(project)" :href="getProjectLink(project)"
:target="isExternalLink(getProjectLink(project)) ? '_blank' : null" :target="
:rel="isExternalLink(getProjectLink(project)) ? 'noopener noreferrer' : null" isExternalLink(getProjectLink(project)) ? '_blank' : null
"
:rel="
isExternalLink(getProjectLink(project))
? 'noopener noreferrer'
: null
"
class="inline-flex items-center rounded-full border border-base-300 bg-base-100/80 px-3 py-1.5 font-medium text-base-content/80 hover:border-primary/50 hover:text-primary transition-colors" class="inline-flex items-center rounded-full border border-base-300 bg-base-100/80 px-3 py-1.5 font-medium text-base-content/80 hover:border-primary/50 hover:text-primary transition-colors"
> >
Review

Same story of HomeView for the parser and sanitize

Same story of HomeView for the parser and sanitize
Vai al servizio Vai al servizio
@ -150,11 +186,17 @@
</article> </article>
</div> </div>
<div v-else-if="items.length === 1" class="rounded-3xl border border-dashed border-base-300 bg-base-200/50 p-8 text-secondary"> <div
v-else-if="items.length === 1"
class="rounded-3xl border border-dashed border-base-300 bg-base-200/50 p-8 text-secondary"
>
Solo un progetto disponibile per ora. Solo un progetto disponibile per ora.
</div> </div>
<div v-else class="rounded-3xl border border-dashed border-base-300 bg-base-200/50 p-8 text-secondary"> <div
v-else
class="rounded-3xl border border-dashed border-base-300 bg-base-200/50 p-8 text-secondary"
>
Nessun progetto trovato. Nessun progetto trovato.
</div> </div>
</div> </div>
@ -173,14 +215,18 @@ const { items, loading, error, reload } = useContentList("/content/projects/");
const resolveCover = (cover) => resolveAssetPath(cover); const resolveCover = (cover) => resolveAssetPath(cover);
const featuredProject = computed(() => items.value[0] ?? null); const featuredProject = computed(() => items.value[0] ?? null);
const featuredServiceLink = computed(() => getProjectLink(featuredProject.value)); const featuredServiceLink = computed(() =>
getProjectLink(featuredProject.value),
);
function getExcerpt(html, length) { function getExcerpt(html, length) {
if (!html) return ""; if (!html) return "";
const div = document.createElement("div"); const div = document.createElement("div");
div.innerHTML = html; div.innerHTML = html;
const text = (div.textContent || div.innerText || "").replace(/\s+/g, " ").trim(); const text = (div.textContent || div.innerText || "")
.replace(/\s+/g, " ")
.trim();
if (text.length <= length) { if (text.length <= length) {
return `<p>${text}</p>`; return `<p>${text}</p>`;
@ -188,7 +234,8 @@ function getExcerpt(html, length) {
const shortened = text.substring(0, length); const shortened = text.substring(0, length);
const lastSpace = shortened.lastIndexOf(" "); const lastSpace = shortened.lastIndexOf(" ");
const finalText = lastSpace > 0 ? shortened.substring(0, lastSpace) : shortened; const finalText =
lastSpace > 0 ? shortened.substring(0, lastSpace) : shortened;
return `<p>${finalText}...</p>`; return `<p>${finalText}...</p>`;
} }

View file

@ -10,8 +10,12 @@
aria-controls="wiki-sidebar-panel" aria-controls="wiki-sidebar-panel"
> >
<span class="flex flex-col items-start"> <span class="flex flex-col items-start">
<span class="text-sm font-semibold text-base-content">Sommario e Indice pagina</span> <span class="text-sm font-semibold text-base-content"
<span class="text-xs text-base-content/70">{{ mobileSidebarSummary }}</span> >Sommario e Indice pagina</span
>
<span class="text-xs text-base-content/70">{{
mobileSidebarSummary
}}</span>
</span> </span>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -45,7 +49,8 @@
aria-label="Wiki sidebar" aria-label="Wiki sidebar"
> >
<div class="mb-4 flex items-center justify-between md:hidden"> <div class="mb-4 flex items-center justify-between md:hidden">
<span class="text-sm font-semibold uppercase tracking-wide text-primary" <span
class="text-sm font-semibold uppercase tracking-wide text-primary"
>Wiki menu</span >Wiki menu</span
> >
<button <button
Review

An icon would look better :)

An icon would look better :)
@ -133,7 +138,9 @@
v-else v-else
class="bg-base-200 rounded-lg border border-base-300 p-4 sm:p-6 lg:p-8" class="bg-base-200 rounded-lg border border-base-300 p-4 sm:p-6 lg:p-8"
> >
<h1 class="mb-5 text-2xl font-bold text-primary sm:text-3xl lg:mb-6 lg:text-4xl"> <h1
class="mb-5 text-2xl font-bold text-primary sm:text-3xl lg:mb-6 lg:text-4xl"
>
{{ pageTitle }}<span class="blinking-cursor"></span> {{ pageTitle }}<span class="blinking-cursor"></span>
</h1> </h1>
<div <div
@ -230,7 +237,10 @@ function parseSidebarLine(line) {
if (line.startsWith("###") || line.startsWith("- ###")) { if (line.startsWith("###") || line.startsWith("- ###")) {
return { return {
type: "heading", type: "heading",
text: line.replace(/^-\s*/, "").replace(/^###\s*/, "").trim(), text: line
.replace(/^-\s*/, "")
.replace(/^###\s*/, "")
.trim(),
}; };
} }
@ -400,8 +410,7 @@ async function loadPage(slug) {
} }
// Estrai titolo // Estrai titolo
const titleMatch = content.match(/^#\s+(.+)$/m); const titleMatch = content.match(/^#\s+(.+)$/m);
pageTitle.value = pageTitle.value = titleMatch?.[1] || normalizedSlug.replace(/-/g, " ");
titleMatch?.[1] || normalizedSlug.replace(/-/g, " ");
// Rimuovi solo il primo H1 iniziale (se presente) // Rimuovi solo il primo H1 iniziale (se presente)
const contentWithoutMainTitle = content.replace(/^\s*#\s+.+(?:\r?\n)+/, ""); const contentWithoutMainTitle = content.replace(/^\s*#\s+.+(?:\r?\n)+/, "");