A Windows desktop application for tracking daily work activities, built with .NET MAUI Blazor Hybrid and SQL Server. Designed for software teams: log work sessions, associate them with clients and software versions, track SVN/Git changesets, and manage deployments across frozen environments (test/production).
WorkActivityTracker Γ¨ un'applicazione desktop Windows per il tracciamento delle attivitΓ lavorative giornaliere. Costruita con .NET MAUI Blazor Hybrid, utilizza una WebView interna per renderizzare un'interfaccia Bootstrap 5.
L'applicazione permette a uno o piΓΉ utenti (identificati dal login Windows) di registrare le proprie attivitΓ , associarle a clienti e versioni software, tracciare i changeset SVN/Git coinvolti e gestire il riporto delle modifiche sui congelati (ambienti di test/collaudo/produzione).
Griglia delle attivitΓ con filtri per anno/mese/giorno e form di inserimento/modifica con editor Note, Changeset, congelati e barra di stato in fondo.
Modale per inviare segnalazioni agli altri utenti, con griglia riepilogativa, filtri per stato e utente, e funzionalitΓ di risposta.
Modale per gestire una base di conoscenza personale: lista appunti con tag, editor ricco con toolbar di formattazione e filtro per tag.
Modale per la gestione dei TODO: griglia con stato, prioritΓ e scadenza, form per aggiungere nuovi elementi e integrazione con il rilevamento TODO nelle attivitΓ .
Modale di ricerca full-text su tutti i campi delle attivitΓ , con anteprima del dettaglio e possibilitΓ di selezionare direttamente l'attivitΓ trovata.
- Visual Studio 2022 (17.8+) con workload:
- Sviluppo .NET Multi-platform App UI (.NET MAUI)
- Sviluppo ASP.NET e Web
- .NET 10 SDK con workload MAUI:
dotnet workload install maui - SQL Server (Express, Developer o Standard)
- Esegui
Database/CreateDatabase.sqlin SSMS per creare il database iniziale - Applica in ordine tutti gli script
MigrateToVX.Y.sqlfino all'ultimo disponibile - Crea il file
appsettings.jsonnella root del progetto (non Γ¨ incluso nel repository) e configura la connection string:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=NOME_SERVER;Initial Catalog=WorkActivityTracker;Integrated Security=True;TrustServerCertificate=True"
},
"AppSettings": {
"AppName": "Work Activity Tracker",
"Version": "4.4",
"MostraModalitaAdmin": true,
"PrivacyMode": false
}
}Da Visual Studio: apri WorkActivityTracker.csproj, seleziona Windows Machine, premi F5.
Ogni attivitΓ registrata contiene:
| Campo | Tipo | Descrizione |
|---|---|---|
TipoAttivita |
string | Lavoro / Permesso / Ferie |
Data |
DateTime | Data dell'attivitΓ |
Descrizione |
string | Titolo breve obbligatorio (in grassetto) |
OreLavorate |
decimal | Ore dedicate (step 0.5) |
Cliente |
FK | Cliente associato |
Versione |
string | Versione software sviluppata (es: 3.2.61) |
UrlTicket |
string | URL ticket, CR, backlog (multiriga) |
Vedere |
string | Riferimenti esterni (email, Teams, ecc.) |
CartellaDocumentazione |
string | Path cartella locale con doc |
Note |
HTML | Descrizione dettagliata del lavoro (con grassetto) |
TestoCheckIn |
string | Testo del messaggio di check-in SCM (in grassetto) |
ChangesetCoinvolti |
HTML | Elenco changeset/commit coinvolti (con grassetto) |
NumeroTicket |
string | Numero/i del ticket (separati da virgola se piΓΉ di uno) |
UrlPatchRilasci |
string | URL patch/pacchetto nei rilasci (NVARCHAR(MAX), puΓ² contenere piΓΉ URL) |
AmbientiSelezionatiIds |
List<int> | Congelati su cui Γ¨ riportata la modifica |
AmbientiRilascioNomi |
string? | Nomi ambienti rilascio separati da virgola (solo lettura, per griglia) |
Per i tipi Permesso e Ferie, vengono mostrati solo i campi Data, Ore, Descrizione e Note; gli altri campi vengono nascosti nell'interfaccia.
- Tabella con scroll verticale (max-height 300px) con sticky header.
- Filtri: Anno / Mese / Giorno + ricerca testuale full-text + checkbox "Solo TODO".
- All'avvio: Anno e Mese impostati al mese corrente, Giorno = "Tutti".
- Bottone "π Oggi" accanto al filtro Giorno: imposta automaticamente Anno/Mese/Giorno alla data odierna.
- Combo Giorno con nomi ed emoji: quando Anno e Mese sono selezionati, ogni opzione mostra il numero + il giorno della settimana abbreviato in italiano (es. "1 - lun"). Vengono nascosti i giorni non validi per il mese selezionato. Emoji prefisso: π’ per il giorno odierno (ha la precedenza), π per sabato e domenica.
- Rilevamento TODO preciso: regex
(?<![a-zA-Z])TODO(?![a-zA-Z])(word boundary, case-insensitive). - Evidenziazione TODO: riga rossa se TODO Γ¨ in Descrizione, Note, ChangesetCoinvolti, UrlTicket.
- Riga selezionata: colore giallo vivace (
#ffe066). Se riga TODO+selezionata: arancione. - Riga totale ore: footer con la somma delle ore delle attivitΓ visibili, allineata sotto la colonna Ore.
- Colonna Ambienti: mostra i nomi degli ambienti di rilascio compilati, separati da virgola (es. "Test, Produzione"), senza numero di versione. Calcolato da una query batch in
ActivityService.GetActivitiesAsync()e salvato inWorkActivityDto.AmbientiRilascioNomi. Vuota se nessun ambiente Γ¨ stato associato. - Colonna Patch: mostra β verde se il campo "URL Patch/Pacchetto nei rilasci" (
UrlPatchRilasci) Γ¨ compilato. - Colonna Azioni: pulsanti Copia (π), Esporta TXT (πΎ), Duplica (π), Elimina (ποΈ).
- π Copia: genera testo plain dell'attivitΓ (HTML stripped) e lo copia negli appunti.
- πΎ Esporta TXT: salva il dettaglio dell'attivitΓ come file
.txtnella cartellaExport/. - π Duplica: copia tutti i campi tranne la data (incluso NumeroTicket).
- ποΈ Elimina: mostra una modale Blazor custom centrata per la conferma.
- Pulsanti export sotto la griglia (visibili se ci sono attivitΓ ):
- π Esporta XLSX: esporta la griglia visualizzata in Excel (
ElencoAttivitΓ Al[timestamp].xlsx). - π Esporta dettagli TXT: esporta tutte le attivitΓ visibili in un TXT (
DettaglioTutteLeAttivitΓ _[dal]_[al]_[timestamp].txt). - π Apri Export: apre la cartella
Export/in Esplora Risorse.
- π Esporta XLSX: esporta la griglia visualizzata in Excel (
- Dopo il salvataggio, l'attivitΓ appena salvata rimane selezionata nella griglia.
La testata (header blu) contiene bottoni rapidi Nuova / Salva (Ctrl+S) / Annulla replicati in piccolo. I bottoni principali sono anche nel footer del form.
Shortcut Ctrl+S: salva l'attivitΓ corrente in qualsiasi momento (registrato via registraCtrlS JS + [JSInvokable] SalvaViaShortcut()).
Il campo Cliente ha un bottone βοΈ che apre la modale ClientiEditorModal per gestire la lista clienti (con log delle modifiche in Clienti_Log).
Visibili nel form solo quando TipoAttivita == Lavoro e il cliente selezionato Γ¨ diverso da "Sviluppo". Comprendono 3 coppie (Tipo ambiente / Versione) disposte orizzontalmente:
- Tipo ambiente:
<input list>con<datalist>alimentato daTipiAmbientiRilascio(es. Test, QualitΓ , Pre-produzione, Produzione). - Versione:
<input list>con<datalist>alimentato daVersioniRilascio(es. 3.2.50, 4.1.10). - I valori nuovi digitati vengono aggiunti automaticamente ai rispettivi lookup al salvataggio (
EnsureTipoExistsAsync,EnsureVersioneExistsAsync). - Dati persistiti in
AttivitaAmbientiRilascio(conPosizione1-3). Caricati inSelezionaAttivita()tramiteAmbientiRilascioService.GetAmbientiRilascioAsync(). - Il DTO
WorkActivityDto.AmbientiRilasciocontiene sempre 3 coppieAmbienteRilascioDto(Posizione, TipoAmbiente, Versione). Il campoAmbientiRilascioNomi(string?) Γ¨ calcolato daActivityService.GetActivitiesAsync()per la colonna della griglia.
Campo contenteditable (non textarea) con toolbar di editing:
- β₯ β / β€ β: indentazione destra/sinistra delle righe selezionate.
- G (Grassetto): applica/rimuove bold con
document.execCommand('bold'). - A giallo / A arancione / A verde: evidenziatura del testo selezionato (hiliteColor).
- S barrato / S sottolineato: formattazione barrato e sottolineato.
- A rosso: colora il testo in rosso.
- β: rimuove tutta la formattazione (bold, colore, highlight, sottolineato, ecc.).
- β / π / βΆ: Undo / Storico versioni / Redo (overlay in basso a destra dell'editor, sopra le scrollbar).
- β: rimuove le righe vuote dal contenuto dell'editor.
- TODO: sostituisce ogni occorrenza di "TODO" (parola isolata) con
--, preservando tutta la formattazione HTML. - Altezza: min 120px, max 300px con scroll verticale.
- Font: Segoe UI,
white-space: pre-wrap. - Bordo rosso se il campo contiene TODO.
- Salva/carica HTML (
innerHTML) per persistere il grassetto nel database. - La sincronizzazione avviene via
noteEditorHelper(JS):setContent,getHtml,getText,indent,rimuoviRigheVuote.
La sezione "Modifica riportata sui congelati" mostra una tabella checkbox con:
- Sviluppo (riga virtuale): versione di sviluppo corrente.
- Ambienti dal DB: Codice, Versione, Data congelamento.
Quando si spunta un congelato: viene aggiunto automaticamente un blocco nell'editor Changeset (se non giΓ presente):
NomeCongelato (Versione):
Changeset XXX: [Testo del check-in]
div con contenteditable="true" con toolbar di editing:
- β₯ β / β€ β: indentazione (cursore rimane sulla stessa riga dopo l'operazione).
- G (Grassetto): applica/rimuove bold.
- A giallo / A arancione / A verde: evidenziatura del testo selezionato (hiliteColor).
- S barrato / S sottolineato: formattazione barrato e sottolineato.
- A rosso: colora il testo in rosso.
- β: rimuove tutta la formattazione (bold, colore, highlight, sottolineato, ecc.).
- β / π / βΆ: Undo / Storico versioni / Redo (overlay in basso a destra dell'editor, sopra le scrollbar).
- β: rimuove le righe vuote dal contenuto dell'editor.
- TODO: sostituisce ogni occorrenza di "TODO" (parola isolata) con
--, preservando tutta la formattazione HTML. - Altezza: min 200px, max 350px, scroll verticale e orizzontale.
- Font monospace (Consolas),
white-space: pre. - Salva/carica HTML (
innerHTML) per persistere il grassetto. - Sincronizzazione via
changesetEditorHelper(JS):setContent,getHtml,getText,indent,rimuoviRigheVuote. AggiungiBloccoCongelato(): usaHtmlToPlainText()per i confronti stringa, poi appende il nuovo blocco come HTML (<strong>heading</strong><br>Changeset XXX: testo) preservando la formattazione esistente.
Modale separata per gestire TODO personali. Ogni TODO: Titolo, Descrizione, Data inserimento, Urgenza (1-5), Completato. Badge con contatore nel pulsante in alto.
Modale per note rapide con sistema di tag (Titolo, Descrizione, Tag multi-valore). Badge con contatore nel pulsante in alto.
Modale ClientiEditorModal aperta dal pulsante βοΈ accanto al campo Cliente:
- CRUD completo: aggiungi, modifica, disattiva cliente.
- Ogni modifica Γ¨ tracciata in
Clienti_Log: NomeUtente, AzioneSvolta (Nuovo/Modifica/Elimina), VecchioValore, NuovoValore, Timestamp.
Modale CongelatiEditorModal aperta dal pulsante "βοΈ Modifica lista" sotto la tabella congelati. Log in Ambienti_Log.
- Campi: Codice, Versione, Data Congelamento, Data Dismissione, Attivo.
- π Esporta MD: esporta la griglia in formato Markdown (tabella GFM) nella cartella
Export/(Congelati_[timestamp].md). - Data Dismissione: obbligatoria quando la checkbox "Attivo" viene deselezionata; il form mostra un errore di validazione se mancante. Mostrata come colonna nella griglia.
- Il log
Ambienti_LogincludeDataDismissionenei campiVecchioValoreeNuovoValoreper tracciabilitΓ completa.
Ricerca full-text su tutte le attivitΓ (senza filtri data) con griglia risultati, navigazione frecce, evidenziazione rossa, selezione attivitΓ nel form.
Pulsante "π Segnala" nella barra superiore (sempre visibile, indipendente dalla modalitΓ admin), apre la modale SegnalazioniModal:
- Form invio: combo utente (auto-seleziona utente corrente) + textarea + bottone "Invia Segnalazione".
- Griglia segnalazioni: Utente, Testo (troncato), Data, Stato con badge colorati. Pulsante "π¬ Rispondi" sempre visibile (anche per chi ha originato la segnalazione).
- Dettaglio segnalazione selezionata: testo formattato readonly con Utente, Data, Testo, Stato, storico risposte.
- Form risposta: textarea + combo stato + bottone "Invia Risposta".
- Stati disponibili: In attesa di risposta, Risposta, Richiesta accettata, Richiesta rifiutata, Modifica proposta accettata, Risolto.
Attivabile tramite checkbox (configurabile in appsettings.json con MostraModalitaAdmin):
- Mostra le attivitΓ di tutti gli utenti (eccetto quelli con
PrivacyMode: true). - Impedisce la modifica di attivitΓ altrui.
Quando si tenta di chiudere la finestra con il form in modifica, viene mostrato un dialogo di conferma. Implementato via UnsavedChangesService (singleton) + AppWindow.Closing (WinUI nativo) in App.xaml.cs.
- File salvati nella sottocartella
Export/nella directory dell'eseguibile (creata automaticamente). - Naming convention:
ElencoAttivitΓ Al[yyyyMMdd_HHmmss].xlsx,DettaglioTutteLeAttivitΓ _[dal]_[al]_[timestamp].txt,DettaglioAttivitΓ _[data]_[descrizione]_[timestamp].txt. - I campi HTML (Note, ChangesetCoinvolti) vengono convertiti in testo plain via
HtmlToPlainText()prima dell'export. - L'ultimo file esportato viene mostrato nella barra di stato.
- XLSX generato con ClosedXML (pacchetto NuGet 0.102.2).
Barra fissa in fondo alla finestra:
- πΎ Ultimo salvataggio: orario HH:mm:ss dell'ultimo salvataggio riuscito.
- π€ Export: nome dell'ultimo file esportato (con tooltip percorso completo).
- π ModalitΓ Admin attiva: badge in admin mode.
- π Privacy attiva: badge se
PrivacyMode: true. - Versione app: numero da
appsettings.json.
ProprietΓ booleana PrivacyMode in appsettings.json. Se true: le attivitΓ dell'utente non sono visibili ad altri utenti in modalitΓ Admin. Nessuna UI per modificarla.
La colonna Cart. Doc. Γ¨ stata aggiunta alla griglia delle attivitΓ (tra "Patch" e "Azioni").
Mostra l'icona π verde quando il campo CartellaDocumentazione Γ¨ compilato; il tooltip riporta il percorso completo. Se il campo Γ¨ vuoto la cella Γ¨ vuota.
Ogni volta che un'attivitΓ viene salvata, il contenuto HTML dei campi Note e ChangesetCoinvolti viene registrato nella tabella EditorHistory (storico infinito, associato all'utente e all'attivitΓ ).
Tre pulsanti sono posizionati come overlay nell'angolo in basso a destra di ciascuna textarea editor (non nella toolbar):
| Pulsante | Azione |
|---|---|
| β | Torna alla versione precedente salvata (Undo) |
| π | Apre la modale EditorHistoryModal con la lista completa delle versioni |
| β | Avanza alla versione successiva salvata (Redo) |
I pulsanti sono disabilitati finchΓ© l'attivitΓ non Γ¨ stata salvata almeno una volta. Il campo viene registrato nello storico solo se non Γ¨ vuoto (verifica tramite HtmlToPlainText) e solo se il contenuto Γ¨ diverso dall'ultimo salvataggio (evita duplicati consecutivi in EditorHistory).
Logica navigazione:
- Indice
-1= contenuto corrente non ancora salvato (stato iniziale). - Al primo Undo: il contenuto corrente viene memorizzato in memoria, viene caricata la lista storico da DB e viene mostrata la versione 0 (piΓΉ recente).
- Undo successivi: incrementa l'indice (va a versioni piΓΉ vecchie, fino all'ultima).
- Redo da indice 0: ripristina il contenuto memorizzato (torna all'indice -1).
- Redo da indice >0: decrementa l'indice (torna a versioni piΓΉ recenti).
- Il cache storico viene azzerato ad ogni salvataggio e quando si seleziona un'altra attivitΓ .
Modale EditorHistoryModal.razor:
- Griglia con data salvataggio (
dd/MM/yyyy HH:mm:ss) e anteprima testo (primi 100 caratteri, HTML strippato). - Riga selezionata evidenziata in giallo (
table-warning). - Pulsanti β β per navigare le righe con contatore "N di Totale".
- Div di anteprima dettagliato con HTML renderizzato (readonly).
- Bottoni "Annulla" (chiude senza modifiche) e "β Seleziona" (chiude e applica la versione all'editor).
Utenti β Utenti identificati da WindowsUsername
Clienti β Clienti (Es: Sviluppo, Cattolica, Aviva)
Clienti_Log β Log modifiche alla lista clienti
Ambienti β Congelati (Codice, Versione/Descrizione, DataCongelamento, DataDismissione)
Ambienti_Log β Log modifiche agli ambienti/congelati
Attivita β AttivitΓ lavorative principali
AttivitaAmbienti β Relazione N:N tra Attivita e Ambienti
TodoItems β Elementi TODO List per utente
Appunti β Appunti/Knowledge Base per utente
AppuntiTags β Tag associati agli appunti
Segnalazioni β Segnalazioni bug / richieste di modifica
Segnalazioni_Risposte β Risposte alle segnalazioni
TipiAmbientiRilascio β Lookup tipi di ambiente (Test, QualitΓ , Produzione, ecc.) (v4.1)
VersioniRilascio β Lookup versioni di rilascio (v4.1)
AttivitaAmbientiRilascio β Relazione N:N tra Attivita e ambienti di rilascio (v4.1)
TipiAttivita β Tipi attivitΓ configurabili (Lavoro/Permesso/Ferie + custom) (v4.2)
TipiAttivita_Log β Log modifiche ai tipi attivitΓ (v4.2)
EventiCalendario β Eventi del calendario con scadenza e stato risolto (v4.2)
EditorHistory β Storico versioni HTML dei campi Note e ChangesetCoinvolti (v4.5)
Valori del campo TipoAttivita (NVARCHAR(20)):
Lavoroβ attivitΓ lavorativa (default)Permessoβ assenza per permessoFerieβ assenza per ferie
UI (Blazor Razor)
β @inject / EventCallback
Service Layer (ActivityService, ClienteService, SegnalazioneService, ...)
β IDbContextFactory<AppDbContext>
EF Core DbContext
β SQL Server Provider
SQL Server Database
- Single Page Application:
Components/Pages/Home.razor(~2700 righe). - Modali come componenti Blazor separati in
Components/. - JS Interop: script in
wwwroot/index.htmlper gli editor contenteditable e Ctrl+S. - Nessuna EF Migration: aggiornamenti schema tramite script SQL manuali in
Database/. - HTML storage: i campi
NoteeChangesetCoinvoltisalvano HTML nel DB per persistere il grassetto.HtmlToPlainText()viene chiamato per export, clipboard e confronti stringa.
| Servizio | Lifetime | Scopo |
|---|---|---|
ActivityService |
Scoped | CRUD attivitΓ |
UserService |
Scoped | Gestione utente Windows |
AmbienteService |
Scoped | CRUD congelati + log |
ClienteService |
Scoped | CRUD clienti + log |
TodoService |
Scoped | CRUD TODO List |
AppuntiService |
Scoped | CRUD Appunti/Knowledge Base |
SegnalazioneService |
Scoped | CRUD segnalazioni + risposte |
AppConfigService |
Singleton | Lettura appsettings.json |
UnsavedChangesService |
Singleton | Stato modifiche non salvate (chiusura app) |
AmbientiRilascioService |
Scoped | CRUD tipi ambienti e versioni di rilascio (v4.1) |
TipiAttivitaService |
Scoped | CRUD tipi attivitΓ dinamici (v4.2) |
CalendarioService |
Scoped | CRUD eventi calendario + eventi imminenti (v4.2) |
EditorHistoryService |
Scoped | Salvataggio e recupero storico versioni editor Note/Changeset (v4.5) |
| Funzione/Helper | Scopo |
|---|---|
registraCtrlS(dotNetRef) |
Registra Ctrl+S globale con callback a [JSInvokable] SalvaViaShortcut() |
eseguiBold(el) |
Applica/rimuove grassetto con document.execCommand('bold') |
changesetEditorHelper.setContent(el, val) |
Imposta contenuto (rileva HTML vs plain text) |
changesetEditorHelper.getHtml(el) |
Restituisce innerHTML per salvataggio DB |
changesetEditorHelper.getText(el) |
Restituisce innerText per operazioni stringa C# |
changesetEditorHelper.indent(el, right) |
Indenta le righe selezionate (β₯/β€), cursore stabile |
noteEditorHelper.setContent(el, val) |
Imposta contenuto Note (rileva HTML vs plain text) |
noteEditorHelper.getHtml(el) |
Restituisce innerHTML per salvataggio DB |
noteEditorHelper.getText(el) |
Restituisce innerText |
noteEditorHelper.indent(el, right) |
Indenta le righe selezionate nelle Note |
sostituisciTodoNeiNodi(el) |
Traversa i text node dell'editor e sostituisce TODO (parola isolata) con --, preservando HTML |
copyToClipboard(text) |
Copia testo negli appunti con fallback execCommand per MAUI |
Gli script SQL si trovano in Database/ e vanno eseguiti in ordine:
| File | Contenuto |
|---|---|
CreateDatabase.sql |
Schema iniziale completo |
MigrateToV3.sql |
Prima migrazione |
MigrateToV3.2.sql |
Aggiunta congelati |
MigrateToV3.3.sql |
Aggiunta log congelati |
MigrateToV3.4.sql |
Aggiunta TodoItems |
MigrateToV3.5.sql |
Aggiunta URL Patch Rilasci |
MigrateToV3.6.sql |
Aggiunta CartDoc, TODO Titolo, Data congelamento |
MigrateToV3.7.sql |
Aggiunta Appunti/AppuntiTags |
MigrateToV3.8.sql |
Aggiunta TipoAttivita (Lavoro/Permesso/Ferie) |
MigrateToV3.9.sql |
Aggiunta PrivacyMode in Utenti; VecchioValore+NuovoValore in Ambienti_Log |
MigrateToV4.0.sql |
Aggiunta Clienti_Log, Segnalazioni, Segnalazioni_Risposte |
MigrateToV4.1.sql |
Aggiunta TipiAmbientiRilascio, VersioniRilascio, AttivitaAmbientiRilascio + log |
MigrateToV4.2.sql |
Aggiunta TipiAttivita, TipiAttivita_Log, EventiCalendario |
MigrateToV4.3.sql |
Aggiunta NumeroTicket in Attivita |
MigrateToV4.4.sql |
UrlPatchRilasci β NVARCHAR(MAX); aggiunta DataDismissione in Ambienti |
@bindin Blazor crea dipendenza bidirezionale. I campicontenteditable(Note, Changeset) non usano@bind: il valore viene sincronizzato via JS interop su@onblure prima del salvataggio.noteEditorNeedsUpdateechangesetEditorNeedsUpdate: flag che forzano l'aggiornamento degli editor inOnAfterRenderAsync, solo quando non sono in focus.HtmlToPlainText(): helper statico che stripa i tag HTML e decodifica entitΓ di base. Usato in:ContieneTodo(),CampoHaTodo(),AggiungiBloccoCongelato(),GeneraTestoAttivita(),GeneraTestoAttivitaPlain().AggiungiBloccoCongelato(): prima di confrontare le righe del testo Changeset, chiamaHtmlToPlainText()perchΓ© il campo ora puΓ² contenere HTML.- L'eliminazione usa
ConfermaEliminaAttivita()β modale custom centrata βConfermaElimina(). - La versione di sviluppo successiva Γ¨ calcolata automaticamente dal primo ambiente (+1 al patch).
- Il filtro "Solo TODO" Γ¨ applicato sia alla lista principale che alla lista per la ricerca avanzata.
UnsavedChangesService: singleton condiviso tra il layer MAUI (App.xaml.cs) e il layer Blazor (Home.razor).App.xaml.csintercettaAppWindow.Closing(cancellabile), controlla il servizio e mostraDisplayAlert.DotNetObjectReference<Home>per il callback Ctrl+S: creato inOnAfterRenderAsyncal first render, disposto inDispose()(il componente implementaIDisposable).- Export XLSX usa ClosedXML (
ClosedXML0.102.2 nel.csproj). I file vengono salvati inExport/nella directory dell'eseguibile.
- π Griglia β colonna "Cart. Doc.": icona π verde nella griglia quando il campo
CartellaDocumentazioneΓ¨ compilato; tooltip con il percorso completo - π Storico versioni editor Note e Changeset: ogni salvataggio registra una voce nella nuova tabella
EditorHistory(solo se il campo non Γ¨ vuoto e il contenuto Γ¨ cambiato rispetto all'ultimo salvataggio); pulsanti β π β come overlay nell'angolo in basso a destra di ciascuna textarea per navigare lo storico (Undo/Redo basato su versioni salvate) e aprire la modale di navigazioneEditorHistoryModal - π
EditorHistoryModal: nuova modale con griglia versioni (data + anteprima), navigazione ββ, anteprima HTML dettagliata e azione "β Seleziona" per ripristinare la versione scelta nell'editor - π Nuovo servizio:
EditorHistoryService - π Nuova migrazione DB:
MigrateToV4.5.sql
- π Griglia β colonna "Ambienti": mostra i nomi degli ambienti di rilascio compilati (es. "Test, Produzione"), senza versione; calcolato tramite query batch in
ActivityService.GetActivitiesAsync()e salvato inWorkActivityDto.AmbientiRilascioNomi - π Griglia β colonna "Patch": indicatore β verde se
UrlPatchRilasciΓ¨ compilato - π Combo Giorno β emoji weekend/oggi: prefisso π per sabato e domenica, π’ per il giorno corrente (ha la precedenza sul weekend)
- π§ Fix editor Changeset β formattazione preservata:
SincronizzaTestoEditorAsync()ora salva HTML (non plain text);AggiungiBloccoCongelato()appende il nuovo blocco come HTML preservando bold/highlight/colori esistenti;ToggleAmbienteaggiorna correttamente il DOM editor dopo l'aggiunta del blocco - π§ Fix Tab/indent in editor: la funzione
indentJS ora filtra i text node e BR quando il cursore Γ¨ su contenuto BR-based, evitando il bug"undefined"nell'innerHTML - π§ Fix rimuoviRigheVuote: rimossa la modalitΓ selezione (causa corruzione HTML con
extractContents); la funzione opera sempre sull'intero editor - π§ Fix URL Patch errore DB: rimosso
[MaxLength(500)]daUrlPatchRilasciβ oraNVARCHAR(MAX)per supportare URL multipli lunghi - π§ Fix Duplica attivitΓ :
NumeroTicketora viene copiato correttamente inDuplicaAttivita() - π Combo Giorno con nomi: quando Anno e Mese sono selezionati, la combo mostra il numero del giorno + il nome abbreviato italiano (es. "1 - lun"); i giorni non validi per il mese sono nascosti
- π Bottone TODOβ"--": aggiunto in tutte e 4 le toolbar (sopra/sotto Note, sopra/sotto Changeset); sostituisce le occorrenze di TODO (parola isolata) con
--preservando la formattazione HTML; funzione JSsostituisciTodoNeiNodi(el)che opera sui text node - π Data Dismissione nei Congelati: nuovo campo
DataDismissione(obbligatorio quandoAttivo = false); colonna nella griglia, campo nel form con validazione; incluso nel logAmbienti_Log(VecchioValore/NuovoValore) - π Nuova migrazione DB:
MigrateToV4.4.sql
- π NumeroTicket: nuovo campo
NVARCHAR(200)affiancato al campo URL Ticket nel form; tooltip "Inserire il numero del ticket, usare la virgola se sono piΓΉ di uno"; incluso nella ricerca full-text; copiato correttamente da "Duplica attivitΓ " - π§ VisibilitΓ campi per tipo attivitΓ : URL Ticket, Numero Ticket, Cartella Documentazione e Vedere ora visibili anche per i tipi personalizzati (custom); nascosti solo per Permesso e Ferie
- π GetTipoBadge(): badge grigio
π {tipo}per i tipi personalizzati (usaHtmlEncodeper sicurezza)
- π Tipi AttivitΓ dinamici: nuova tabella
TipiAttivita+TipiAttivita_Log; dropdown caricato da DB viaTipiAttivitaService; pulsante βοΈ accanto alla combo apreTipiAttivitaEditorModal;EnsureTipiBaseAsync()garantisce Lavoro/Permesso/Ferie all'avvio; i tipi base non possono essere rinominati nΓ© eliminati - π Calendario eventi: nuova tabella
EventiCalendario; servizioCalendarioService; icona π accanto al campo Data apreCalendarioModal(griglia mensile con navigazione e form evento); barra colorata in cima alla pagina mostra l'evento piΓΉ urgente non risolto (verde/arancione/rosso/grigio per distanza in giorni) - π Popup errore DB:
MostraMessaggioConPopup()in Home.razor mostra modale con OK per errori critici (connessione all'avvio, salvataggio) - π Nuove tabelle DB:
TipiAttivita,TipiAttivita_Log,EventiCalendario - π Nuovi servizi:
TipiAttivitaService,CalendarioService
- π Ambienti di rilascio: nel form (visibili quando cliente β "Sviluppo") compaiono 3 coppie (Tipo ambiente / Versione) con
<input list>e autocompletamento; i valori nuovi vengono aggiunti automaticamente ai lookup al salvataggio - π Colonna Ambienti in griglia: mostra i nomi degli ambienti di rilascio compilati, separati da virgola (es. "Test, Produzione"), senza versione
- π Colonna Patch in griglia: indicatore β verde se
UrlPatchRilasciΓ¨ compilato - π Nuove tabelle DB:
TipiAmbientiRilascio,VersioniRilascio,AttivitaAmbientiRilascio+ log per entrambe - π Nuovo servizio:
AmbientiRilascioService
- π Editor Note con indent + bold: "Descrizione dettagliata lavoro svolto" convertita da
textareaacontenteditable divcon toolbar (β₯β, β€β, G grassetto) - π Bold nel Changeset editor: aggiunto bottone G alla toolbar esistente
- π HTML storage: Note e ChangesetCoinvolti salvano HTML nel DB per persistere il grassetto.
HtmlToPlainText()per export/clipboard/confronti - π Ctrl+S: shortcut globale per salvare (tooltip aggiornato su entrambi i bottoni Salva)
- π Bottone "π Oggi": accanto al filtro Giorno, imposta la data odierna e ricarica
- π Editor Clienti: pulsante βοΈ accanto al campo Cliente apre modale CRUD con log in
Clienti_Log - π "Elenco Changeset e lista files coinvolti": label rinominata da "Elenco Changeset coinvolti"
- π Export XLSX: esporta la griglia visualizzata in Excel (ClosedXML)
- π Export TXT dettagli: esporta tutte le attivitΓ visibili in un file TXT
- π Export TXT per riga: bottone πΎ in ogni riga della griglia per esportare la singola attivitΓ
- π Apri Export: pulsante per aprire la cartella Export in Esplora Risorse
- π Avviso chiusura: dialogo se ci sono modifiche non salvate (WinUI
AppWindow.Closing+UnsavedChangesService) - π Segnalazioni: pulsante "π Segnala" sempre visibile, modale con invio segnalazioni, griglia, risposte e cambio stato
- π Barra di stato: aggiunto nome dell'ultimo file esportato
- π Nuove tabelle DB:
Clienti_Log,Segnalazioni,Segnalazioni_Risposte - π Nuovi servizi:
ClienteService,SegnalazioneService,UnsavedChangesService
- π PrivacyMode: campo
PrivacyMode(BIT) aggiunto a tabellaUtenti; sincronizzato al login dall'appsettings.json - π Ambienti_Log: aggiunto
VecchioValoreeNuovoValore(NVARCHAR MAX) per tracciare i valori prima/dopo la modifica - π Admin mode: filtra utenti con
PrivacyMode = true(tranne l'utente corrente)
- π TipoAttivita: campo Lavoro/Permesso/Ferie
- π Per Permesso e Ferie vengono nascosti i campi non pertinenti (Cliente, Versione, Ticket, Congelati, Changeset)
- π Etichette e placeholder adattate al tipo selezionato
- π Appunti (Knowledge Base personale): modale con CRUD, tag, ricerca con evidenziazione, navigazione frecce, modalitΓ admin
- π Nuove tabelle:
Appunti,AppuntiTags - π§ "Dettagli ricerca" β "Ricerca avanzata" (sempre attivo)
- π TODO List: campo Titolo, data inserimento editabile
- π Congelati: colonna "Data Cong." nella tabella + Editor Congelati (modale CRUD)
- π TracciabilitΓ congelati: tabella
Ambienti_Log - π MostraModalitaAdmin: configurabile in
appsettings.json
- π Nuovo campo "URL Patch/Pacchetto nei rilasci" (multiriga, ricercabile)
- π Filtro "Visualizza solo TODO" con badge "Filtro attivo"
- π TODO List: modale con urgenza 1-5, CRUD, completamento, isolamento per utente
- π Cliente "Sviluppo" auto-selezionato per nuove attivitΓ
- π Nuovo campo "Testo del check-in" con pulsante β¬οΈπ per copiarlo in Descrizione
- π Auto-compilazione blocchi Changeset alla selezione congelati
- π Ricerca avanzata: auto-scroll + navigazione occorrenze (Precedente/Prossimo)
- π Connection string in
appsettings.json - π Font form 13px
- π Regex TODO word boundary + evidenziazione righe + badge
- π Pulsante Duplica (π) nella griglia
- π Auto-completamento versione di sviluppo (+1 patch)
- Campo "URL Ticket" multilinea, cartella documentazione con folder picker
- Congelati con tabella Nome/Versione; "Elenco Changeset coinvolti" (contenteditable)
- Modale ricerca avanzata con evidenziazione e selezione diretta
- Changeset coinvolti, ModalitΓ Admin, filtri inizializzati a oggi, ricerca estesa
- Prima versione con funzionalitΓ base
WorkActivityTracker/
βββ appsettings.json # Connection string + config (NON in repo)
βββ Components/
β βββ Pages/
β β βββ Home.razor # Pagina principale (~2700 righe)
β βββ SearchModal.razor # Ricerca avanzata
β βββ TodoListModal.razor # TODO List
β βββ AppuntiModal.razor # Appunti / Knowledge Base
β βββ CongelatiEditorModal.razor # Editor congelati
β βββ ClientiEditorModal.razor # Editor clienti (v4.0)
β βββ SegnalazioniModal.razor # Segnalazioni bug/richieste (v4.0)
β βββ TipiAttivitaEditorModal.razor # Editor tipi attivitΓ dinamici (v4.2)
β βββ CalendarioModal.razor # Calendario eventi (v4.2)
β βββ _Imports.razor
β βββ Routes.razor
βββ Data/
β βββ AppDbContext.cs # EF Core DbContext
βββ Database/
β βββ CreateDatabase.sql
β βββ MigrateToV3.sql ... MigrateToV3.9.sql
β βββ MigrateToV4.0.sql # (v4.0) Clienti_Log, Segnalazioni, Segnalazioni_Risposte
β βββ MigrateToV4.1.sql # (v4.1) AmbientiRilascio
β βββ MigrateToV4.2.sql # (v4.2) TipiAttivita, EventiCalendario
β βββ MigrateToV4.3.sql # (v4.3) NumeroTicket
β βββ MigrateToV4.4.sql # (v4.4) UrlPatchRilasci β MAX, DataDismissione in Ambienti
βββ Models/
β βββ WorkActivity.cs # Tutti i modelli EF Core + DTO + static classes
βββ Services/
β βββ ActivityService.cs
β βββ AmbienteService.cs
β βββ AppConfigService.cs
β βββ AppuntiService.cs
β βββ ClienteService.cs # (v4.0) CRUD clienti + Clienti_Log
β βββ SegnalazioneService.cs # (v4.0) CRUD segnalazioni + risposte
β βββ TodoService.cs
β βββ UnsavedChangesService.cs # (v4.0) Singleton flag modifiche non salvate
β βββ UserService.cs
β βββ AmbientiRilascioService.cs # (v4.1) CRUD tipi ambienti + versioni rilascio
β βββ TipiAttivitaService.cs # (v4.2) CRUD tipi attivitΓ dinamici
β βββ CalendarioService.cs # (v4.2) CRUD eventi calendario
βββ wwwroot/
β βββ css/app.css # Stili custom (font 13px, TODO, editor toolbar)
β βββ index.html # Entry point HTML + script JS custom
βββ App.xaml.cs # Finestra MAUI + avviso chiusura (v4.0)
βββ MauiProgram.cs # Composizione DI
βββ WorkActivityTracker.csproj # ClosedXML 0.102.2 (v4.0)
Le segnalazioni di bug e le richieste di nuove funzionalitΓ sono benvenute tramite le Issues di GitHub.
Per contribuire al codice:
- Fai un fork del repository
- Crea un branch per la tua modifica (
git checkout -b feature/nome-funzionalita) - Esegui il commit delle modifiche
- Apri una Pull Request descrivendo cosa hai cambiato e perchΓ©
Prima di proporre modifiche strutturali al database, consulta la sezione Script di Migrazione Database: le migration sono manuali (script SQL in Database/), non usa EF Migrations.
Distribuito sotto licenza MIT. Consulta il file LICENSE per i dettagli.