Merge branch 'main' of git.phc.dm.unipi.it:phc/website
continuous-integration/drone/push Build is passing Details

main
Luca Lombardo 4 days ago
commit 8a5727fcd6

@ -13,10 +13,11 @@ steps:
image: node:latest image: node:latest
volumes: volumes:
- name: host-website-dist - name: host-website-dist
path: /drone/src/dist path: /mnt/website
commands: commands:
- npm install - npm install
- npm run build - npm run build
- cp -rT ./dist /mnt/website
volumes: volumes:
- name: host-website-dist - name: host-website-dist

@ -1,9 +1,95 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128"> <svg width="1000" height="500" viewBox="0 0 1000 500" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" /> <rect x="80" y="190" width="60" height="120" fill="#1E6733" />
<style> <rect x="160" y="50" width="150" height="60" fill="#1E6733" />
path { fill: #000; } <rect x="140" y="90" width="10" height="50" fill="#ECC333" />
@media (prefers-color-scheme: dark) { <rect x="140" y="200" width="10" height="50" fill="#ECC333" />
path { fill: #FFF; } <rect x="140" y="410" width="10" height="20" fill="#ECC333" />
} <rect x="140" y="350" width="10" height="50" fill="#ECC333" />
</style> <rect x="240" y="110" width="70" height="10" fill="#ECC333" />
</svg> <rect x="250" y="130" width="60" height="130" fill="#1E6733" />
<rect x="340" y="50" width="60" height="120" fill="#1E6733" />
<rect x="340" y="190" width="60" height="120" fill="#1E6733" />
<rect x="590" y="190" width="60" height="120" fill="#1E6733" />
<rect x="690" y="180" width="60" height="120" fill="#1E6733" />
<rect x="690" y="310" width="60" height="140" fill="#1E6733" />
<rect x="690" y="50" width="60" height="120" fill="#1E6733" />
<rect x="590" y="320" width="60" height="130" fill="#1E6733" />
<rect x="590" y="50" width="60" height="130" fill="#1E6733" />
<rect x="420" y="240" width="150" height="60" fill="#1E6733" />
<rect x="340" y="320" width="60" height="130" fill="#1E6733" />
<rect x="240" y="140" width="10" height="50" fill="#ECC333" />
<rect x="350" y="170" width="40" height="10" fill="#ECC333" />
<rect x="330" y="330" width="10" height="50" fill="#ECC333" />
<rect x="160" y="200" width="80" height="60" fill="#1E6733" />
<rect x="650" y="200" width="10" height="50" fill="#ECC333" />
<rect x="750" y="330" width="10" height="60" fill="#ECC333" />
<rect x="800" y="450" width="40" height="10" fill="#ECC333" />
<rect x="850" y="450" width="30" height="10" fill="#ECC333" />
<rect x="750" y="90" width="10" height="50" fill="#ECC333" />
<rect x="810" y="110" width="60" height="10" fill="#ECC333" />
<rect x="580" y="330" width="10" height="50" fill="#ECC333" />
<rect x="580" y="60" width="10" height="50" fill="#ECC333" />
<rect x="710" y="420" width="20" height="20" fill="#C4C4C4" />
<rect x="710" y="390" width="20" height="20" fill="#C4C4C4" />
<rect x="100" y="280" width="20" height="10" fill="#C4C4C4" />
<rect x="100" y="260" width="20" height="10" fill="#C4C4C4" />
<rect x="110" y="210" width="20" height="20" fill="#C4C4C4" />
<rect x="350" y="430" width="40" height="10" fill="#303030" />
<rect x="350" y="410" width="40" height="10" fill="#303030" />
<rect x="350" y="390" width="40" height="10" fill="#303030" />
<rect x="700" y="70" width="20" height="40" fill="#303030" />
<rect x="700" y="120" width="20" height="40" fill="#303030" />
<rect x="610" y="280" width="20" height="20" fill="#C4C4C4" />
<rect x="600" y="240" width="20" height="20" fill="#C4C4C4" />
<rect x="430" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="430" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="430" y="280" width="10" height="10" fill="#C4C4C4" />
<rect x="445" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="445" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="460" y="280" width="40" height="10" fill="#C4C4C4" />
<rect x="475" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="475" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="505" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="505" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="520" y="265" width="10" height="15" fill="#C4C4C4" />
<rect x="505" y="280" width="25" height="10" fill="#C4C4C4" />
<rect x="535" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="535" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="535" y="280" width="10" height="10" fill="#C4C4C4" />
<rect x="445" y="280" width="10" height="10" fill="#C4C4C4" />
<rect x="460" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="460" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="490" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="490" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="520" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="550" y="250" width="10" height="10" fill="#C4C4C4" />
<rect x="550" y="265" width="10" height="10" fill="#C4C4C4" />
<rect x="550" y="280" width="10" height="10" fill="#C4C4C4" />
<rect x="620" y="210" width="20" height="20" fill="#C4C4C4" />
<rect x="370" y="70" width="20" height="30" fill="#303030" />
<rect x="370" y="110" width="20" height="30" fill="#303030" />
<rect x="870" y="440" width="40" height="10" transform="rotate(-90 870 440)" fill="#303030" />
<rect x="890" y="440" width="40" height="10" transform="rotate(-90 890 440)" fill="#303030" />
<rect x="810" y="440" width="40" height="10" transform="rotate(-90 810 440)" fill="#303030" />
<rect x="790" y="440" width="40" height="10" transform="rotate(-90 790 440)" fill="#303030" />
<rect x="270" y="100" width="40" height="10" transform="rotate(-90 270 100)" fill="#303030" />
<rect x="290" y="100" width="40" height="10" transform="rotate(-90 290 100)" fill="#303030" />
<rect x="190" y="100" width="40" height="10" transform="rotate(-90 190 100)" fill="#303030" />
<rect x="170" y="100" width="40" height="10" transform="rotate(-90 170 100)" fill="#303030" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M140 60V170C134.477 170 130 174.477 130 180H90C90 174.477 85.5228 170 80 170V60C85.5228 60 90 55.5228 90 50H130C130 55.5228 134.477 60 140 60Z"
fill="#1E6733" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M130 320H90C90 325.523 85.5229 330 80 330V440C85.5229 440 90 444.477 90 450H130C130 444.477 134.477 440 140 440V330C134.477 330 130 325.523 130 320Z"
fill="#1E6733" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M770 60C775.523 60 780 55.5228 780 50H910C910 55.5228 914.477 60 920 60V100C914.477 100 910 104.477 910 110H780C780 104.477 775.523 100 770 100V60Z"
fill="#1E6733" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M770 400C775.523 400 780 395.523 780 390H910C910 395.523 914.477 400 920 400V440C914.477 440 910 444.477 910 450H780C780 444.477 775.523 440 770 440V400Z"
fill="#1E6733" />
<rect x="750" y="190" width="10" height="40" fill="#ECC333" />
<rect x="750" y="240" width="10" height="20" fill="#ECC333" />
<rect x="400" y="200" width="10" height="40" fill="#ECC333" />
<rect x="400" y="250" width="10" height="20" fill="#ECC333" />
</svg>

Before

Width:  |  Height:  |  Size: 749 B

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

@ -13,7 +13,7 @@
* @param {AppuntiCardProps} param0 * @param {AppuntiCardProps} param0
* @returns * @returns
*/ */
export const AppuntiCard = ({ image, course, title, author, courseYear }) => { export const AppuntiCard = ({ course, title, author, courseYear }) => {
return ( return (
<div class="appunti-item"> <div class="appunti-item">
<div class="thumbnail"></div> <div class="thumbnail"></div>

@ -1,4 +1,4 @@
import { effect, useComputed, useSignal } from '@preact/signals' import { useComputed, useSignal } from '@preact/signals'
import Fuse from 'fuse.js' import Fuse from 'fuse.js'
import { useEffect } from 'preact/hooks' import { useEffect } from 'preact/hooks'
import { ShowMore } from './Paginate' import { ShowMore } from './Paginate'
@ -67,22 +67,22 @@ export const UtentiPage = () => {
$filter.value === 'macchinisti' $filter.value === 'macchinisti'
? $utentiData.value.filter(user => MACCHINISTI.includes(user.uid)) ? $utentiData.value.filter(user => MACCHINISTI.includes(user.uid))
: $filter.value === 'rappstud' : $filter.value === 'rappstud'
? $utentiData.value.filter(user => RAPPSTUD.includes(user.uid)) ? $utentiData.value.filter(user => RAPPSTUD.includes(user.uid))
: $utentiData.value, : $utentiData.value
) )
const $fuse = useComputed( const $fuse = useComputed(
() => () =>
new Fuse($filteredData.value, { new Fuse($filteredData.value, {
keys: ['gecos', 'uid'], keys: ['gecos', 'uid'],
}), })
) )
const $searchText = useSignal('') const $searchText = useSignal('')
const $searchResults = useComputed(() => const $searchResults = useComputed(() =>
$searchText.value.trim().length > 0 $searchText.value.trim().length > 0
? ($fuse.value?.search($searchText.value).map(result => result.item) ?? []) ? $fuse.value?.search($searchText.value).map(result => result.item) ?? []
: $filteredData.value, : $filteredData.value
) )
useEffect(() => { useEffect(() => {
@ -107,7 +107,7 @@ export const UtentiPage = () => {
<> <>
<span class="material-symbols-outlined">{v.icon}</span> {v.label} <span class="material-symbols-outlined">{v.icon}</span> {v.label}
</>, </>,
]), ])
)} )}
</ComboBox> </ComboBox>
<div class="search"> <div class="search">
@ -130,8 +130,8 @@ export const UtentiPage = () => {
{RAPPSTUD.includes(poissonUser.uid) {RAPPSTUD.includes(poissonUser.uid)
? 'account_balance' ? 'account_balance'
: MACCHINISTI.includes(poissonUser.uid) : MACCHINISTI.includes(poissonUser.uid)
? 'construction' ? 'construction'
: 'person'} : 'person'}
</span> </span>
</div> </div>
<div class="text">{poissonUser.gecos}</div> <div class="text">{poissonUser.gecos}</div>

@ -1,9 +1,9 @@
import { useEffect, useMemo, useState } from 'preact/hooks' import { useEffect, useState } from 'preact/hooks'
export const trottleDebounce = <T extends any[], R>( export const trottleDebounce = <T extends any[], R>(
fn: (...args: T) => R, fn: (...args: T) => R,
delay: number, delay: number,
options: { leading?: boolean; trailing?: boolean } = {}, options: { leading?: boolean; trailing?: boolean } = {}
): ((...args: T) => R | undefined) => { ): ((...args: T) => R | undefined) => {
let lastCall = 0 let lastCall = 0
let lastResult: R | undefined let lastResult: R | undefined

@ -25,6 +25,7 @@ const guidesCollection = defineCollection({
id: z.string(), id: z.string(),
title: z.string(), title: z.string(),
description: z.string(), description: z.string(),
author: z.string(),
series: z.string().optional(), series: z.string().optional(),
tags: z.array(z.string()), tags: z.array(z.string()),
}), }),

@ -15,14 +15,19 @@ Git è un sistema di controllo di versione distribuito creato per gestire proget
### **Cos'è Git?** ### **Cos'è Git?**
- **Sistema di controllo di versione**: Gestisce le modifiche al codice sorgente nel tempo. - **Sistema di controllo di versione**: Gestisce le modifiche al codice sorgente nel tempo.
- **Distribuito**: Ogni sviluppatore ha una copia del repository. - **Distribuito**: Ogni sviluppatore ha una copia del repository.
- **Veloce e leggero**: Ottimizzato per la velocità e le prestazioni. - **Veloce e leggero**: Ottimizzato per la velocità e le prestazioni.
### **Perché usare Git?** ### **Perché usare Git?**
- **Tracciabilità**: Ogni modifica è tracciata e reversibile. - **Tracciabilità**: Ogni modifica è tracciata e reversibile.
- **Collaborazione**: Più persone possono lavorare sullo stesso progetto. - **Collaborazione**: Più persone possono lavorare sullo stesso progetto.
- **Backup**: Repository remoto per il backup del codice. - **Backup**: Repository remoto per il backup del codice.
- **Branching**: Lavoriamo su nuove funzionalità senza influenzare il codice principale. - **Branching**: Lavoriamo su nuove funzionalità senza influenzare il codice principale.
--- ---
@ -34,14 +39,19 @@ Git è un sistema di controllo di versione distribuito creato per gestire proget
### **Windows** ### **Windows**
1. Scarichiamo [Git for Windows](https://git-scm.com/download/win). 1. Scarichiamo [Git for Windows](https://git-scm.com/download/win).
2. Seguiamo il wizard di installazione. 2. Seguiamo il wizard di installazione.
3. Durante l'installazione: 3. Durante l'installazione:
- Selezioniamo "Git Bash" come terminale. - Selezioniamo "Git Bash" come terminale.
- Configuriamo un editor di testo (es. Vim o Nano). - Configuriamo un editor di testo (es. Vim o Nano).
### **macOS** ### **macOS**
1. Usiamo `brew` per installare Git: 1. Usiamo `brew` per installare Git:
```bash ```bash
brew install git brew install git
``` ```
@ -49,12 +59,16 @@ Git è un sistema di controllo di versione distribuito creato per gestire proget
### **Linux** ### **Linux**
1. Installiamo Git usando il nostro gestore di pacchetti: 1. Installiamo Git usando il nostro gestore di pacchetti:
- **Debian/Ubuntu**: - **Debian/Ubuntu**:
```bash ```bash
sudo apt update sudo apt update
sudo apt install git sudo apt install git
``` ```
- **Arch Linux**: - **Arch Linux**:
```bash ```bash
sudo pacman -S git sudo pacman -S git
``` ```
@ -83,6 +97,7 @@ git config --list
### **Repository** ### **Repository**
- **Repository locale**: Una cartella sul nostro computer che contiene il nostro progetto. - **Repository locale**: Una cartella sul nostro computer che contiene il nostro progetto.
- **Repository remoto**: Una versione del progetto ospitata su un server (es. GitHub, GitLab). - **Repository remoto**: Una versione del progetto ospitata su un server (es. GitHub, GitLab).
### **Branch** ### **Branch**
@ -160,6 +175,7 @@ Il comando **`git commit`** è utilizzato per registrare le modifiche nel reposi
#### Cosa succede dietro le quinte: #### Cosa succede dietro le quinte:
- Git salva lo stato dei file nell'area di staging in un commit, che viene aggiunto alla cronologia del repository locale. - Git salva lo stato dei file nell'area di staging in un commit, che viene aggiunto alla cronologia del repository locale.
- Ogni commit ha un identificatore unico (hash) che consente di risalire facilmente alle modifiche in qualsiasi momento. - Ogni commit ha un identificatore unico (hash) che consente di risalire facilmente alle modifiche in qualsiasi momento.
--- ---
@ -171,6 +187,7 @@ Il comando **`git commit`** è utilizzato per registrare le modifiche nel reposi
#### Come funziona: #### Come funziona:
1. Dopo aver fatto uno o più commit locali, dobbiamo inviare queste modifiche al repository remoto. 1. Dopo aver fatto uno o più commit locali, dobbiamo inviare queste modifiche al repository remoto.
2. Per fare questo, usiamo il comando **`git push`** seguito dal nome del remoto (di solito `origin` per il repository remoto di default) e dal nome del branch (di solito `main` o `master`, ma potrebbe essere qualsiasi altro nome di branch che stiamo utilizzando). 2. Per fare questo, usiamo il comando **`git push`** seguito dal nome del remoto (di solito `origin` per il repository remoto di default) e dal nome del branch (di solito `main` o `master`, ma potrebbe essere qualsiasi altro nome di branch che stiamo utilizzando).
Comando per inviare le modifiche: Comando per inviare le modifiche:
@ -182,6 +199,7 @@ Il comando **`git commit`** è utilizzato per registrare le modifiche nel reposi
#### Cosa succede dietro le quinte: #### Cosa succede dietro le quinte:
- Git confronta il nostro branch locale con il branch remoto. Se ci sono nuovi commit nel branch remoto che non sono ancora nel nostro branch locale, ci verrà richiesto di fare un **pull** per aggiornare prima di fare il push. - Git confronta il nostro branch locale con il branch remoto. Se ci sono nuovi commit nel branch remoto che non sono ancora nel nostro branch locale, ci verrà richiesto di fare un **pull** per aggiornare prima di fare il push.
- Il nostro repository locale viene sincronizzato con il remoto, rendendo le modifiche visibili a tutti gli altri che hanno accesso al repository remoto. - Il nostro repository locale viene sincronizzato con il remoto, rendendo le modifiche visibili a tutti gli altri che hanno accesso al repository remoto.
#### Errori comuni: #### Errori comuni:
@ -197,15 +215,19 @@ Il comando **`git commit`** è utilizzato per registrare le modifiche nel reposi
#### Come funziona: #### Come funziona:
1. Se altri collaboratori hanno fatto modifiche al repository remoto, possiamo ottenere queste modifiche con **`git pull`**. Questo comando aggiorna il nostro branch locale con le modifiche più recenti dal repository remoto. 1. Se altri collaboratori hanno fatto modifiche al repository remoto, possiamo ottenere queste modifiche con **`git pull`**. Questo comando aggiorna il nostro branch locale con le modifiche più recenti dal repository remoto.
2. Eseguiamo il comando: 2. Eseguiamo il comando:
```bash ```bash
git pull origin main git pull origin main
``` ```
In questo caso, `origin` è il nome del repository remoto (il nome predefinito quando cloni un repository), e `main` è il branch che vogliamo aggiornare. In questo caso, `origin` è il nome del repository remoto (il nome predefinito quando cloni un repository), e `main` è il branch che vogliamo aggiornare.
#### Cosa succede dietro le quinte: #### Cosa succede dietro le quinte:
- **`git fetch`** scarica tutte le modifiche dal repository remoto, ma non le integra ancora nel nostro codice. - **`git fetch`** scarica tutte le modifiche dal repository remoto, ma non le integra ancora nel nostro codice.
- **`git merge`** unisce le modifiche scaricate al nostro branch attuale, risolvendo eventuali conflitti, se necessario. - **`git merge`** unisce le modifiche scaricate al nostro branch attuale, risolvendo eventuali conflitti, se necessario.
#### Errori comuni: #### Errori comuni:
@ -243,13 +265,17 @@ git switch -c <nome-branch>
Per unire un branch nel branch principale (di solito chiamato `main`): Per unire un branch nel branch principale (di solito chiamato `main`):
1. Spostiamoci sul branch principale: 1. Spostiamoci sul branch principale:
```bash ```bash
git checkout main git checkout main
``` ```
2. Eseguiamo il merge del branch desiderato: 2. Eseguiamo il merge del branch desiderato:
```bash ```bash
git merge <nome-branch> git merge <nome-branch>
``` ```
Sostituiamo `<nome-branch>` con il nome del branch che vogliamo unire. Sostituiamo `<nome-branch>` con il nome del branch che vogliamo unire.
### Risoluzione dei conflitti ### Risoluzione dei conflitti
@ -257,15 +283,21 @@ Per unire un branch nel branch principale (di solito chiamato `main`):
Quando due persone modificano lo stesso file, Git può generare un conflitto. Ecco come risolverlo: Quando due persone modificano lo stesso file, Git può generare un conflitto. Ecco come risolverlo:
1. Identifichiamo il file in conflitto: 1. Identifichiamo il file in conflitto:
```bash ```bash
git status git status
``` ```
2. Modifichiamo manualmente il file per risolvere il conflitto. Cerchiamo i segni di conflitto (`<<<<<<<`, `=======`, `>>>>>>>`) e scegliamo quali modifiche mantenere. 2. Modifichiamo manualmente il file per risolvere il conflitto. Cerchiamo i segni di conflitto (`<<<<<<<`, `=======`, `>>>>>>>`) e scegliamo quali modifiche mantenere.
3. Aggiungiamo il file risolto allo stage: 3. Aggiungiamo il file risolto allo stage:
```bash ```bash
git add <file> git add <file>
``` ```
4. Concludiamo con un commit per salvare le modifiche risolte: 4. Concludiamo con un commit per salvare le modifiche risolte:
```bash ```bash
git commit git commit
``` ```
@ -283,10 +315,13 @@ git diff
### **Annullare modifiche** ### **Annullare modifiche**
1. **Prima del commit**: 1. **Prima del commit**:
```bash ```bash
git checkout -- <file> git checkout -- <file>
``` ```
2. **Dopo il commit**: 2. **Dopo il commit**:
```bash ```bash
git reset --soft HEAD~1 git reset --soft HEAD~1
``` ```
@ -302,7 +337,9 @@ git branch -d <nome-branch>
## **10. Best practices** ## **10. Best practices**
- Scriviamo messaggi di commit chiari e descrittivi. - Scriviamo messaggi di commit chiari e descrittivi.
- Creiamo branch per nuove funzionalità o bugfix. - Creiamo branch per nuove funzionalità o bugfix.
- Sincronizziamo frequentemente il nostro repository locale con quello remoto. - Sincronizziamo frequentemente il nostro repository locale con quello remoto.
--- ---
@ -310,5 +347,7 @@ git branch -d <nome-branch>
## **11. Risorse aggiuntive** ## **11. Risorse aggiuntive**
- [Documentazione ufficiale di Git](https://git-scm.com/doc) - [Documentazione ufficiale di Git](https://git-scm.com/doc)
- [Guida interattiva Learn Git Branching](https://learngitbranching.js.org/) - [Guida interattiva Learn Git Branching](https://learngitbranching.js.org/)
- [GitHub Docs](https://docs.github.com/) - [GitHub Docs](https://docs.github.com/)

@ -6,7 +6,7 @@ author: Antonio De Lucreziis
tags: [astro, website] tags: [astro, website]
--- ---
In questa guida vedremo come creare una pagina Poisson moderna utilizzando Astro, un nuovo framework di sviluppo web statico. In questa guida vedremo come creare una pagina Poisson moderna utilizzando Astro, un nuovo framework di sviluppo web statico. Per prima cosa installeremo NodeJS sul nostro computer, poi creeremo un nuovo progetto Astro e infine dopo averlo generato, lo caricheremo su Poisson.
## Setup ## Setup
@ -35,7 +35,7 @@ cd nome-del-progetto
npm install npm install
``` ```
Se ad esempio volessimo usare un tema come [Astro Nano](https://github.com/markhorn-dev/astro-nano) possiamo fare così: Se ad esempio volessimo usare un tema come "[Astro Nano](https://github.com/markhorn-dev/astro-nano)" possiamo fare così:
```bash ```bash
git clone https://github.com/markhorn-dev/astro-nano sito-poisson git clone https://github.com/markhorn-dev/astro-nano sito-poisson
@ -62,8 +62,19 @@ Per vedere il nostro progetto in locale possiamo eseguire il comando:
npm run dev npm run dev
``` ```
A questo punto in base al tema scelto possiamo modificare i file dentro `src/pages` per cambiare il contenuto delle pagine. Molti temi sono preimpostati per scrivere contenuti in Markdown, ad esempio per il _template blog_ possiamo scrivere gli articoli per il nostro blog in `src/content/blog/$NOME_POST.md`. A questo punto in base al tema scelto possiamo modificare i file dentro `src/pages` per cambiare il contenuto delle pagine. Molti temi sono preimpostati per scrivere contenuti in Markdown, ad esempio per il _template blog_ possiamo scrivere gli articoli per il nostro blog in `src/content/blog/{nome_post}.md`.
## Deploy ## Appunti
Una volta creato il progetto possiamo caricare appunti e dispense nella cartella `/public` Una volta creato il progetto possiamo caricare appunti e dispense nella cartella `/public`
## Deploy
Per caricare il nostro sito su Poisson possiamo usare il comando `rsync`:
```bash
npm run build
rsync -avz dist/ username@poisson.phc.dm.unipi.it:public_html/
```
Dove `username` è il nostro username Poisson. Da notare che gli `/` alla fine di `dist/` e `public_html/` sono importanti per evitare di creare delle cartelle per errore.

@ -13,7 +13,9 @@ Poisson è un server autogestito dalla comunità studentesca di matematica, da s
Se non si è mai creato un account Poisson, è necessario inviare una richiesta via email a **macchinisti@lists.dm.unipi.it** includendo: Se non si è mai creato un account Poisson, è necessario inviare una richiesta via email a **macchinisti@lists.dm.unipi.it** includendo:
- Nome - Nome
- Cognome - Cognome
- Username di ateneo (quello associato alla propria email istituzionale) - Username di ateneo (quello associato alla propria email istituzionale)
Nella mail è sufficiente specificare che si desidera attivare un account Poisson. I "macchinisti" si occuperanno di attivare l'account il prima possibile. Nella mail è sufficiente specificare che si desidera attivare un account Poisson. I "macchinisti" si occuperanno di attivare l'account il prima possibile.
@ -33,6 +35,7 @@ Assicuriamoci di accedere con le credenziali di ateneo per recuperare username e
Per accedere a Poisson via SSH, è necessario: Per accedere a Poisson via SSH, è necessario:
1. Aprire un terminale (su Linux/Mac) o utilizzare un client SSH come PuTTY (su Windows). 1. Aprire un terminale (su Linux/Mac) o utilizzare un client SSH come PuTTY (su Windows).
2. Eseguire il comando: 2. Eseguire il comando:
```bash ```bash
@ -76,4 +79,4 @@ Dove `<username>` è il proprio username.
### Creazione di pagine web più complesse ### Creazione di pagine web più complesse
Per creare pagine web più complesse, suggeriamo di utilizzare il framework [Astro](https://astro.build/), che permette di creare siti web statici in modo semplice e veloce. A questo [link](<[2024-07-30-pagina-poisson-con-astro.md](https://phc.dm.unipi.it/)>) troviamo una guida su come iniziare a utilizzare Astro per creare la nostra pagina web e caricarla su Poisson. Per creare pagine web più complesse, suggeriamo di utilizzare il framework [Astro](https://astro.build/), che permette di creare siti web statici in modo semplice e veloce. [Abbiamo scritto una guida](/guide/pagina-poisson-con-astro) su come iniziare a utilizzare Astro per creare la nostra pagina web e caricarla su Poisson.

@ -9,7 +9,9 @@ tags: [poisson, password]
Se per qualche strano motivo hai dimenticato la tua password Poisson, niente paura! La procedura è super semplice: Se per qualche strano motivo hai dimenticato la tua password Poisson, niente paura! La procedura è super semplice:
1. Scrivi una mail a **macchinisti@lists.dm.unipi.it**. 1. Scrivi una mail a **macchinisti@lists.dm.unipi.it**.
2. Nella mail, specifica il tuo nome, cognome, username di ateneo (quello della tua email istituzionale) e se lo ricordi, anche il tuo username Poisson. 2. Nella mail, specifica il tuo nome, cognome, username di ateneo (quello della tua email istituzionale) e se lo ricordi, anche il tuo username Poisson.
3. Attendi pazientemente la risposta dei macchinisti, che ti resetteranno la password e ti invieranno una nuova via email. 3. Attendi pazientemente la risposta dei macchinisti, che ti resetteranno la password e ti invieranno una nuova via email.
E voilà, in un batter d'occhio sarai di nuovo pronto a entrare nel fantastico mondo di Poisson. E voilà, in un batter d'occhio sarai di nuovo pronto a entrare nel fantastico mondo di Poisson.

@ -31,9 +31,10 @@ const { title, description, thumbnail, pageTags } = Astro.props
<meta property="og:title" content={title ?? 'PHC'} /> <meta property="og:title" content={title ?? 'PHC'} />
<meta property="og:description" content={description ?? 'Sito web del PHC'} /> <meta property="og:description" content={description ?? 'Sito web del PHC'} />
<meta property="og:type" content="website" />
{thumbnail && <meta property="og:image" content={thumbnail} />} {thumbnail && <meta property="og:image" content={thumbnail} />}
<link rel="icon" type="image/png" sizes="512x512" href="/assets/icon.png" /> <link rel="icon" type="image/png" sizes="512x512" href="/favicon.svg" />
<script> <script>
import renderMathInElement from 'katex/contrib/auto-render' import renderMathInElement from 'katex/contrib/auto-render'

@ -1,13 +1,13 @@
--- ---
import { getCollection } from 'astro:content' import { getCollection } from 'astro:content'
import ArticleLayout from '../../layouts/ArticleLayout.astro' import ArticleLayout from '@/layouts/ArticleLayout.astro'
export async function getStaticPaths() { export async function getStaticPaths() {
const guides = await getCollection('guides') const guides = await getCollection('guides')
return guides.map(entry => ({ return guides.map(entry => ({
params: { id: entry.slug }, params: { id: entry.data.id },
props: { entry }, props: { entry },
})) }))
} }
@ -18,6 +18,20 @@ const { Content } = await entry.render()
<ArticleLayout {...entry.data} pageTags={['guida', entry.data.id, entry.data.series && 'series']}> <ArticleLayout {...entry.data} pageTags={['guida', entry.data.id, entry.data.series && 'series']}>
<h1>{entry.data.title}</h1> <h1>{entry.data.title}</h1>
{entry.data.series && <div class="series">Serie: {entry.data.series}</div>} {entry.data.series && <div class="series">Serie: {entry.data.series}</div>}
<Content /> <Content />
<div class="metadata">
<div class="metadata-item">
<strong>Autore</strong>
{entry.data.author}
</div>
<div class="metadata-item">
<strong>Tags</strong>
<div class="tags">
{entry.data.tags.map(tag => <a href={`/guide/tags/${tag}`}>#{tag}</a>)}
</div>
</div>
</div>
</ArticleLayout> </ArticleLayout>

@ -7,17 +7,19 @@ const guides = await getCollection('guides')
--- ---
<PageLayout pageTags="guide"> <PageLayout pageTags="guide">
<h1>Guide</h1> <h1>
<a href="/guide">Guide</a>
</h1>
<div class="card-list"> <div class="card-list">
{ {
guides.toReversed().map(guide => ( guides.toReversed().map(guide => (
<div class="card"> <div class="card">
<div class="title"> <div class="title">
<a href={`/guide/${guide.slug}`}>{guide.data.title}</a> <a href={`/guide/${guide.data.id}`}>{guide.data.title}</a>
</div> </div>
<div class="text">{guide.data.description}</div> <div class="text">{guide.data.description}</div>
<div class="tags"> <div class="tags">
{guide.data.tags.map(tag => ( {guide.data.tags.map((tag: string) => (
<a href={`/guide/tags/${tag}`}>#{tag}</a> <a href={`/guide/tags/${tag}`}>#{tag}</a>
))} ))}
</div> </div>

@ -9,7 +9,7 @@ export async function getStaticPaths() {
const tags: string[] = [] const tags: string[] = []
guides.forEach(post => { guides.forEach(post => {
post.data.tags.forEach(tag => { post.data.tags.forEach((tag: string) => {
tags.push(tag) tags.push(tag)
}) })
}) })
@ -34,17 +34,17 @@ const { tag, guides } = Astro.props
--- ---
<PageLayout pageTags="guide tag"> <PageLayout pageTags="guide tag">
<h1>Guide > #{tag}</h1> <h1><a href="/guide">Guide</a> > <a href={`/guide/tags/${tag}`}>#{tag}</a></h1>
<div class="card-list"> <div class="card-list">
{ {
guides.map(guide => ( guides.map(guide => (
<div class="card"> <div class="card">
<div class="title"> <div class="title">
<a href={`/guide/${guide.slug}`}>{guide.data.title}</a> <a href={`/guide/${guide.data.id}`}>{guide.data.title}</a>
</div> </div>
<div class="text">{guide.data.description}</div> <div class="text">{guide.data.description}</div>
<div class="tags"> <div class="tags">
{guide.data.tags.map(tag => ( {guide.data.tags.map((tag: string) => (
<a href={`/guide/tags/${tag}`}>#{tag}</a> <a href={`/guide/tags/${tag}`}>#{tag}</a>
))} ))}
</div> </div>

@ -7,7 +7,7 @@ const news = await getCollection('news')
--- ---
<PageLayout pageTags="notizie"> <PageLayout pageTags="notizie">
<h1>Notizie</h1> <h1><a href="/notizie">Notizie</a></h1>
<div class="card-list"> <div class="card-list">
{ {
news.map(newsItem => ( news.map(newsItem => (

@ -4,6 +4,8 @@ import BaseLayout from '../layouts/BaseLayout.astro'
import Header from '../components/Header.astro' import Header from '../components/Header.astro'
import Footer from '../components/Footer.astro' import Footer from '../components/Footer.astro'
import Timeline from '../components/Timeline.astro' import Timeline from '../components/Timeline.astro'
import imgPulizie from '@/assets/gallery/006-pulizie.jpg'
--- ---
<BaseLayout {...Astro.props} pageTags={'storia'}> <BaseLayout {...Astro.props} pageTags={'storia'}>
@ -18,11 +20,12 @@ import Timeline from '../components/Timeline.astro'
progetto. progetto.
</p> </p>
<img <img
class="small flat"
src="https://media.tenor.com/MRCIli40TYoAAAAj/under-construction90s-90s.gif" src="https://media.tenor.com/MRCIli40TYoAAAAj/under-construction90s-90s.gif"
alt="Work in progress" alt="Work in progress"
/> />
<p> <p>
Per delle note storiche un po' più dettagliate, si legga l'ottima pagine sul <a Per delle note storiche un po' più dettagliate, si legga l'ottima pagina sul <a
href="http://betti.dm.unipi.it/servizi/PHC.html">sito del dipartimento</a href="http://betti.dm.unipi.it/servizi/PHC.html">sito del dipartimento</a
>. >.
</p> </p>
@ -34,7 +37,7 @@ import Timeline from '../components/Timeline.astro'
Nel 2024, <strong>Luca Lombardo</strong> entra a far parte del PHC. Questo stesso anno vengono Nel 2024, <strong>Luca Lombardo</strong> entra a far parte del PHC. Questo stesso anno vengono
effettuate delle grandi pulizie nella stanza del PHC, come non si faceva dal lontano 2006. effettuate delle grandi pulizie nella stanza del PHC, come non si faceva dal lontano 2006.
</p> </p>
<img class="dropdown desktop-only" src="https://i.imgur.com/MA5q9dx.jpeg" alt="Logo" /> <img class="fill" src={imgPulizie.src} alt="pulizie phc" />
</Timeline> </Timeline>
<Timeline title="Tanti Francesco" year="2022"> <Timeline title="Tanti Francesco" year="2022">
<p> <p>
@ -70,7 +73,7 @@ import Timeline from '../components/Timeline.astro'
</p> </p>
<!-- TODO: Pensare a come mostrare questa immagine su mobile --> <!-- TODO: Pensare a come mostrare questa immagine su mobile -->
<img <img
class="dropdown desktop-only" class="fill"
src="https://web.archive.org/web/20060609003904im_/http://poisson.phc.unipi.it/logo_studenti.orig.png" src="https://web.archive.org/web/20060609003904im_/http://poisson.phc.unipi.it/logo_studenti.orig.png"
alt="Logo" alt="Logo"
/> />

@ -60,8 +60,8 @@ const RENDERER_FPS = 30
function setup() { function setup() {
console.log('Setting up circuits art...') console.log('Setting up circuits art...')
$canvas.width = $canvas.clientWidth $canvas.width = $canvas.clientWidth * window.devicePixelRatio
$canvas.height = $canvas.clientHeight $canvas.height = $canvas.clientHeight * window.devicePixelRatio
const g = $canvas.getContext('2d')! const g = $canvas.getContext('2d')!
const state: State = { const state: State = {
@ -75,14 +75,19 @@ function setup() {
const handle = window.setInterval(() => { const handle = window.setInterval(() => {
const time = new Date().getTime() - startTime.getTime() const time = new Date().getTime() - startTime.getTime()
update(state, g.canvas.width, g.canvas.height, time) update(
state,
g.canvas.width / window.devicePixelRatio,
g.canvas.height / window.devicePixelRatio,
time
)
render(g, state, time) render(g, state, time)
}, 1000 / RENDERER_FPS) }, 1000 / RENDERER_FPS)
renderer = { timer: handle } renderer = { timer: handle }
} }
function update(state: State, width: number, height: number, time: number) { function update(state: State, width: number, _height: number, _time: number) {
const w = (width / CELL_SIZE) | 0 const w = (width / CELL_SIZE) | 0
// const h = (height / CELL_SIZE) | 0 // const h = (height / CELL_SIZE) | 0
@ -166,14 +171,20 @@ const RENDER_CELL: Record<WireCell, (g: CanvasRenderingContext2D) => void> = {
}, },
} }
function render(g: CanvasRenderingContext2D, state: State, time: number) { function render(g: CanvasRenderingContext2D, state: State, _time: number) {
const WIDTH = g.canvas.width / window.devicePixelRatio
const HEIGHT = g.canvas.height / window.devicePixelRatio
g.clearRect(0, 0, g.canvas.width, g.canvas.height) g.clearRect(0, 0, g.canvas.width, g.canvas.height)
g.resetTransform() g.resetTransform()
g.scale(window.devicePixelRatio, window.devicePixelRatio)
g.scale(CELL_SIZE, CELL_SIZE) g.scale(CELL_SIZE, CELL_SIZE)
g.lineWidth = 3 / CELL_SIZE g.lineWidth = 3 / CELL_SIZE
const w = (g.canvas.width / CELL_SIZE) | 0 const w = (WIDTH / CELL_SIZE) | 0
const h = (g.canvas.height / CELL_SIZE) | 0 const h = (HEIGHT / CELL_SIZE) | 0
for (let y = 0; y <= h + 1; y++) { for (let y = 0; y <= h + 1; y++) {
for (let x = 0; x <= w + 1; x++) { for (let x = 0; x <= w + 1; x++) {
if (!state.grid.has([x, y])) continue if (!state.grid.has([x, y])) continue
@ -235,18 +246,6 @@ function randomChoice<T>(choices: T[]): T {
return choices[randomInt(0, choices.length - 1)] return choices[randomInt(0, choices.length - 1)]
} }
function randomWeightedChoice<T>(choices: [T, number][]) {
return
}
// 3 + 4 + 5 + 6
randomWeightedChoice([
['a', 3],
['b', 4],
['c', 5],
['d', 6],
])
const DIR_TO_VEC: Record<WireDirection, Point2> = { const DIR_TO_VEC: Record<WireDirection, Point2> = {
['down']: [0, 1], ['down']: [0, 1],
['down-left']: [-1, 1], ['down-left']: [-1, 1],
@ -277,14 +276,14 @@ const DIR_AVAILABLE_PREDICATE: Record<WireDirection, (pos: Point2, grid: Grid<Wi
function pruneDirections( function pruneDirections(
grid: Grid<WireCell>, grid: Grid<WireCell>,
position: Point2, position: Point2,
directions: WireDirection[], directions: WireDirection[]
): WireDirection[] { ): WireDirection[] {
return directions.filter(dir => DIR_AVAILABLE_PREDICATE[dir](position, grid)) return directions.filter(dir => DIR_AVAILABLE_PREDICATE[dir](position, grid))
} }
function generateWire( function generateWire(
grid: Grid<WireCell>, grid: Grid<WireCell>,
startingPoint: Point2, startingPoint: Point2
): { position: Point2; direction: WireCell }[] { ): { position: Point2; direction: WireCell }[] {
const segmentLength = Math.floor(1 - Math.random() ** 2) * 10 + 30 const segmentLength = Math.floor(1 - Math.random() ** 2) * 10 + 30
let currentPosition = startingPoint let currentPosition = startingPoint

@ -23,11 +23,7 @@
place-content: center; place-content: center;
font-size: 24px; font-size: 24px;
font-variation-settings: font-variation-settings: 'FILL' 0, 'wght' 300, 'GRAD' 0, 'opsz' 24;
'FILL' 0,
'wght' 300,
'GRAD' 0,
'opsz' 24;
max-width: 32px; max-width: 32px;
} }
@ -555,12 +551,6 @@
&.dimmed { &.dimmed {
color: color-mix(in srgb, var(--card-base-internal), #000 50%); color: color-mix(in srgb, var(--card-base-internal), #000 50%);
} }
img {
max-width: 4rem;
// non cambiare che ci sta l'immagine spastica quella nella storia
margin: 0 auto;
}
} }
& > .tags { & > .tags {
@ -616,12 +606,15 @@
display: grid; display: grid;
grid-auto-flow: row; grid-auto-flow: row;
width: 100%;
max-width: 100%; max-width: 100%;
gap: 2rem; gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr)); grid-template-columns: repeat(auto-fit, minmax(25rem, auto));
grid-auto-rows: auto; grid-auto-rows: auto;
justify-content: center;
& > .card { & > .card {
max-width: 25rem; max-width: 25rem;
} }

@ -462,6 +462,12 @@
} }
.notizie { .notizie {
h1 > a {
&:hover {
text-decoration: underline 3px solid;
}
}
main { main {
justify-self: center; justify-self: center;
@ -508,6 +514,12 @@
} }
.guide { .guide {
h1 > a {
&:hover {
text-decoration: underline 3px solid;
}
}
main { main {
justify-self: center; justify-self: center;
@ -531,6 +543,40 @@
margin-top: 3rem; margin-top: 3rem;
margin-bottom: 6rem; margin-bottom: 6rem;
position: relative;
.metadata {
position: absolute;
top: -2px;
left: calc(100% + 2rem);
width: 15rem;
display: grid;
grid-auto-flow: row;
gap: 1rem;
justify-items: start;
.metadata-item {
background: var(--card-base);
display: grid;
grid-template-rows: auto auto;
justify-items: start;
gap: 0.25rem;
padding: 0.75rem 1rem;
@include neo-brutalist-card($size: 3px);
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
}
}
@media screen and (max-width: $screen-desktop-min) { @media screen and (max-width: $screen-desktop-min) {
box-shadow: none; box-shadow: none;
border: none; border: none;
@ -538,6 +584,15 @@
max-width: none; max-width: none;
margin: 0 auto; margin: 0 auto;
.metadata {
position: static;
padding: 0;
width: auto;
margin: 0;
--card-base: color-mix(in lab, var(--guide-base), #fff 30%);
}
} }
} }
} }

@ -112,6 +112,40 @@
// margin-bottom: 1rem; // margin-bottom: 1rem;
// } // }
p[align='center'] {
margin: 1.5rem 0;
a {
// background: color-mix(in hsl, var(--card-base-internal, #ededed), #fff 20%);
background: hsl(from var(--card-base-internal, #ededed) h calc(s + 10) calc(l - 10));
padding: 0.5rem;
border-radius: 0.25rem;
box-shadow: 0.25rem 0.25rem 0 0 #333;
border: 2px solid #333;
}
}
img {
display: block;
margin: 0 auto;
@include neo-brutalist-card(2px);
&.fill {
width: 100%;
max-width: 20rem;
}
&.small {
max-width: 5rem;
}
&.flat {
border: none;
box-shadow: none;
}
}
p:first-child { p:first-child {
margin-top: 0; margin-top: 0;
} }
@ -160,6 +194,11 @@
ol, ol,
ul { ul {
margin-bottom: var(--paragraph-margin, 1rem); margin-bottom: var(--paragraph-margin, 1rem);
padding-left: 1.5rem;
p {
--paragraph-margin: 0.5rem;
}
} }
a, a,
@ -184,6 +223,14 @@
} }
} }
hr {
max-width: calc(100vw - 4rem);
width: 40ch;
margin: 3rem auto 2.75rem;
border: none;
border-top: 2px solid #0003;
}
@media screen and (max-width: $screen-desktop-min) { @media screen and (max-width: $screen-desktop-min) {
& > * { & > * {
margin: 0 0.75rem; margin: 0 0.75rem;

Loading…
Cancel
Save