La parte server di questo sito è realizzata in Dart (senza Flutter), utilizzando la libreria shelf.
In aggiunta, utilizza due componenti importanti, che ho sviluppato ad hoc per questo tipo di applicazione:
Ecco per esempio il codice che prepara, utilizzando dart_bsx, la scheda di questa pagina, che comprende l'indice a sinistra e il contenuto dell'articolo a destra:
BsxTag _bookCard(String bookTitle, Toc toc, String articleTitle,
String articleHtml) {
var tocWithStyle = toc
..withBsBgColor(BsColor.light)
..withBsPadding(size: 1, side: BsSide.y)
..withBsPadding(size: 2, side: BsSide.x);
var tocCol = GridCol()
..addTag(tocWithStyle)
..withColSize(size: BsSize.medium, width: 4);
var articleCol = GridCol()
..withClass('book-page')
..addTags([H4(articleTitle), Text(articleHtml)])
..withColSize(size: BsSize.medium, width: 8);
var bookRow = GridRow.fromCols([tocCol, articleCol])
..withColCount(count: 1)
..withColCount(count: 2, size: BsSize.medium);
final bookContent = Div()
..withClass('container-fluid')
..addTag(bookRow);
final cardHeader = CardHeader()..addTag(H4(bookTitle));
final cardBody = CardBody()
..addTag(bookContent)
..withBsMargin(size: 1, side: BsSide.bottom);
return Card()
..addItems([cardHeader, cardBody])
..withBsMargin(size: 2, side: BsSide.top)
..withBsShadow(BsShadow.small);
}
Anche il sito trekking-etc.it è realizzato con le stesse tecnologie, anzi ne sfrutta più ampiamente le funzionalità, offrendo contenuti più ricchi e complessi. Ecco per esempio come viene utilizzato etc_db per reperire tutti gli elementi necessari a comporre la pagina di un articolo:
// Retrieve the main article.
var mainArticle = await _db.retrieveObjOfType(articleId, 'article',
lang: lang) as EtcArticleObj?;
if (mainArticle == null) return PageResult.notFound();
if (mainArticle.hasRedirect)
return PageResult.redirect(redirectUrl(mainArticle));
await _db.iconizeObj(mainArticle);
// Retrieve the relevant children.
final children = await _db.retrieveChildrenOfTypes(mainArticle,
['article', 'image', 'seo'], lang: lang);
// Extract the articles; sort or shuffle them.
var articles = children.whereTypeIs('article').cast<EtcArticleObj>();
if (shuffleArticles) {
articles = articles.shuffled();
} else {
articles = articles.sorted();
}
await _db.iconizeObjs(articles);
// Prepare full SEO stuff.
final seo = children.whereTypeIs('seo').firstOrNull as EtcSeoObj?;
final seoTags = await _view.articleSeoTags(mainArticle, seo, view);
// Retrieve the carousel images.
final carouselImages = children.whereTypeIs('image')
.cast<EtcImageObj>()
.where((image) => image.role == 'carousel')
.shuffled();
// Retrieve the bread-crumb items.
final ancestors = (await _db.retrieveAncestors(mainArticle,
lang: lang)).where((obj) => obj.type != 'folder');
Il codice è straordinariamente auto-esplicativo, e richiede pochi commenti, ben distribuiti, per permettere una successiva manutenzione.
Giorgio Barchiesi
Albo degli Ingegneri Sez. A, N. 4027 della Prov. di Trento
P.IVA 02370260222, C.F. BRC GRG 58L26 C794R
Copyright © 2015-2024 Giorgio Barchiesi - Tutti i diritti riservati