150 lines
6.2 KiB
Markdown
150 lines
6.2 KiB
Markdown
---
|
|
name: elixforms-project-architecture
|
|
description: >
|
|
Architettura e struttura del progetto elixForms Custom Pages.
|
|
Descrive il monorepo, la libreria common condivisa, il pattern delle pagine autonome
|
|
e tutte le convenzioni di naming, configurazione e build.
|
|
Attiva questa skill quando lavori su qualsiasi parte del progetto,
|
|
crei nuove pagine, modifichi l'architettura o devi capire come è organizzato il codice.
|
|
---
|
|
|
|
# Architettura del Progetto elixForms Custom Pages
|
|
|
|
## Panoramica
|
|
|
|
Questo progetto è un **monorepo** per la creazione di pagine web React custom destinate alla piattaforma **elixForms** dell'Università di Parma (UniPR). Ogni pagina è un micro-progetto indipendente che produce un **singolo file JS bundle** contenente React, Bootstrap Italia e il codice custom, da pubblicare su un server remoto.
|
|
|
|
## Struttura del Workspace
|
|
|
|
```
|
|
elixforms-custom-pages/ ← Root del workspace (VS Code)
|
|
├── .vscode/ ← Configurazioni VS Code (launch, tasks)
|
|
├── docs/ ← Documentazione (PDF manuali)
|
|
└── react/ ← Root del monorepo React
|
|
├── package.json ← Dipendenze condivise (React, ReactDOM)
|
|
├── tsconfig.base.json ← Configurazione TypeScript base condivisa
|
|
├── .gitignore
|
|
├── common/ ← Libreria condivisa di componenti ElixForms
|
|
│ ├── package.json
|
|
│ ├── tsconfig.json ← Estende tsconfig.base, composite: true
|
|
│ └── src/
|
|
│ ├── ElixFormsComponent.tsx
|
|
│ ├── ElixFormsComponentAbstract.tsx
|
|
│ ├── ElixFormsElement.tsx
|
|
│ ├── ElixFormsTypes.tsx
|
|
│ ├── ElixFormsComponent.module.scss
|
|
│ ├── IElixFormsComponentProperties.ts
|
|
│ ├── IElixFormsComponentFormState.tsx
|
|
│ ├── IElixFormsComponentCustomFormFieldFactory.ts
|
|
│ └── QueryParamHelper.tsx
|
|
└── scelta-carriera/ ← Esempio di pagina custom (micro-progetto)
|
|
├── package.json
|
|
├── tsconfig.json ← Estende tsconfig.base
|
|
├── vite.config.js
|
|
├── eslint.config.js
|
|
├── index.html
|
|
└── src/
|
|
├── main.jsx ← Entry point React
|
|
├── App.jsx ← Componente principale della pagina
|
|
├── App.css ← CSS (importa CSS remoti di elixForms)
|
|
├── index.css ← CSS globale (attualmente commentato)
|
|
├── global.d.ts ← Dichiarazioni di tipo per moduli
|
|
└── assets/ ← Immagini e risorse statiche
|
|
```
|
|
|
|
## Pattern Architetturale: Micro-Progetto per Pagina
|
|
|
|
Ogni pagina (es. `scelta-carriera/`) è un progetto Vite completamente autonomo che:
|
|
|
|
1. **Importa dalla libreria `common/`** tramite alias `@common` configurato in `vite.config.js`
|
|
2. **Ha le proprie dipendenze** nel suo `package.json` (solo devDependencies e plugin Vite)
|
|
3. **Condivide le dipendenze runtime** (React, ReactDOM) dal `package.json` root di `react/`
|
|
4. **Produce un singolo file JS** tramite la configurazione Rollup in `vite.config.js`
|
|
5. **Estende il tsconfig base** per avere configurazione TypeScript coerente
|
|
|
|
## Dipendenze Condivise (react/package.json)
|
|
|
|
Le dipendenze runtime sono hoisted al livello `react/`:
|
|
- `react` ^19.2.7
|
|
- `react-dom` ^19.2.5
|
|
|
|
## Configurazione TypeScript
|
|
|
|
### Base (tsconfig.base.json)
|
|
- `module`: ESNext
|
|
- `target`: ES2022
|
|
- `moduleResolution`: bundler
|
|
- `jsx`: react-jsx
|
|
- `strict`: true
|
|
- Path alias: `@common/*` → `./common/*`
|
|
|
|
### Common (common/tsconfig.json)
|
|
- `composite`: true (per project references)
|
|
- `declaration`: true, `declarationMap`: true
|
|
|
|
### Pagine (scelta-carriera/tsconfig.json)
|
|
- `extends`: `../tsconfig.base.json`
|
|
- `references`: `../common`
|
|
- `allowJs`: true, `checkJs`: true (supporto misto JSX/TSX)
|
|
|
|
## Configurazione Build (Vite)
|
|
|
|
Ogni pagina usa questa configurazione per generare un **singolo bundle JS**:
|
|
|
|
```js
|
|
// Plugin chiave
|
|
react() // Supporto React JSX
|
|
cssInjectedByJsPlugin() // CSS iniettato nel JS (no file .css separati)
|
|
|
|
// Build options
|
|
cssCodeSplit: false
|
|
rollupOptions.input: 'src/main.jsx'
|
|
rollupOptions.output:
|
|
codeSplitting: false
|
|
manualChunks: undefined
|
|
entryFileNames: '<nome-pagina>.js' // Nome descrittivo (es. 'scelta-carriera.js')
|
|
assetFileNames: '[name].[ext]'
|
|
sourcemap: true
|
|
```
|
|
|
|
## Resolve Alias
|
|
|
|
```js
|
|
resolve.alias: {
|
|
"@common": path.resolve(__dirname, "../common")
|
|
}
|
|
server.fs.allow: [".."] // Permette import da common/
|
|
```
|
|
|
|
## CSS Strategy
|
|
|
|
Le pagine caricano CSS dal server remoto elixForms tramite `@import url(...)` in `App.css`:
|
|
- CSS da `console-unipr.elixforms.it` per il design system dell'università
|
|
- I componenti Bootstrap Italia usano classi HTML e CSS del design system UniPR
|
|
- SCSS modules sono usati in `common/` per stili dei componenti condivisi
|
|
- `sass-embedded` è installato come devDependency per supporto SCSS
|
|
|
|
## Integrazione con elixForms
|
|
|
|
La pagina custom interagisce con la piattaforma elixForms tramite:
|
|
1. **Query parameters**: Parametri obbligatori passati nell'URL (es. `RWE2_MODULE_ID`, `RWE2_REQUEST_ID`, `crc`, etc.)
|
|
2. **Form POST**: Il form fa submit a `https://procedure.unipr.it/rwe2/ComeBackToElixAndSave`
|
|
3. **Hidden inputs**: I parametri query vengono inseriti come campi hidden nel form
|
|
4. **Encoding**: `acceptCharset="ISO-8859-1"` per compatibilità con il backend
|
|
|
|
## Convenzioni di Naming
|
|
|
|
- **Cartelle pagina**: kebab-case (es. `scelta-carriera`)
|
|
- **Package name**: `@elixforms/<nome-pagina>` (es. `@elixforms/scelta-carriera`)
|
|
- **Bundle output**: `<nome-pagina>.js` (es. `scelta-carriera.js`)
|
|
- **Componenti React**: PascalCase
|
|
- **File sorgente**: I file correnti sono `.jsx` ma il progetto ha pieno supporto TypeScript (`.tsx`)
|
|
- **Tipo moduli**: `"type": "module"` nelle pagine
|
|
|
|
## Ambiente di Sviluppo
|
|
|
|
- **Dev server**: `npm run dev` (Vite HMR)
|
|
- **Build**: `npm run build` → output in `dist/`
|
|
- **Debug VS Code**: Configurazioni in `.vscode/launch.json` per avviare Vite + Chrome
|
|
- **Lint**: ESLint con plugin react-hooks e react-refresh
|