From fe6910a5877ad039e2d6cf95efc10a62c0762871 Mon Sep 17 00:00:00 2001 From: Julien Lepiller Date: Fri, 9 Oct 2020 00:32:56 +0200 Subject: [PATCH] website: Add community page. * website/apps/media/templates/community.scm: New file. * website/apps/media/builder.scm: Add community builder. * website/apps/base/templates/components.scm: Add it to the menu. * website/apps/media/templates/components.scm: Add resource->shtml. * website/apps/media/types.scm: New resource data type. * website/apps/media/data.scm: Add community resources. * website/static/base/css/index.css: Add css for new classes. * website/static/media/css/community.css: New file. * website/static/media/img/community/carl-dong-bitcoin-security.webp: New file. --- website/apps/base/templates/components.scm | 3 +- website/apps/media/builder.scm | 16 ++++- website/apps/media/data.scm | 49 ++++++++++++++ website/apps/media/templates/community.scm | 34 ++++++++++ website/apps/media/templates/components.scm | 24 ++++++- website/apps/media/types.scm | 63 +++++++++++++++++- website/static/base/css/index.css | 12 ++++ website/static/media/css/community.css | 13 ++++ .../community/carl-dong-bitcoin-security.webp | Bin 0 -> 13952 bytes 9 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 website/apps/media/templates/community.scm create mode 100644 website/static/media/css/community.css create mode 100644 website/static/media/img/community/carl-dong-bitcoin-security.webp diff --git a/website/apps/base/templates/components.scm b/website/apps/base/templates/components.scm index 44d410e..7482503 100644 --- a/website/apps/base/templates/components.scm +++ b/website/apps/base/templates/components.scm @@ -413,7 +413,8 @@ manual. #:items (list (C_ "website menu" (menu-item #:label "Videos" #:active-item active-item #:url (guix-url "videos/"))) - (C_ "website menu" (menu-item #:label "Screenshots" #:active-item active-item #:url (guix-url "screenshots/"))))) + (C_ "website menu" (menu-item #:label "Screenshots" #:active-item active-item #:url (guix-url "screenshots/"))) + (C_ "website menu" (menu-item #:label "Community Resources" #:active-item active-item #:url (guix-url "community/"))))) ,(C_ "website menu" (menu-item #:label "Donate" #:active-item active-item #:url (guix-url "donate/"))) diff --git a/website/apps/media/builder.scm b/website/apps/media/builder.scm index 53378e6..c4cb17b 100644 --- a/website/apps/media/builder.scm +++ b/website/apps/media/builder.scm @@ -1,11 +1,13 @@ ;;; GNU Guix web site ;;; Copyright © 2019 Florian Pelz +;;; Copyright © 2020 Julien Lepiller ;;; Initially written by sirgazil who waives all ;;; copyright interest on this file. (define-module (apps media builder) #:use-module (apps aux system) #:use-module (apps media data) + #:use-module (apps media templates community) #:use-module (apps media templates screenshot) #:use-module (apps media templates screenshots-overview) #:use-module (apps media templates video) @@ -17,6 +19,7 @@ #:use-module (apps aux web) #:use-module (apps media utils) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-19) #:export (builder)) @@ -41,7 +44,8 @@ A list of page objects that represent the web resources of the application. See Haunt objects for more information." (flatten - (list (screenshots-overview-builder) + (list (community-builder) + (screenshots-overview-builder) (screenshots-builder) (videos-builder) (video-list-builder)))) @@ -51,6 +55,16 @@ ;;; Helper builders. ;;; +(define (community-builder) + "Return a Haunt page representing the community resources page." + (make-page "community/index.html" + (community-t (sort resources + (lambda (a b) + (time>=? + (date->time-utc (resource-date a)) + (date->time-utc (resource-date b)))))) + sxml->html)) + (define (screenshots-builder) "Return a list of Haunt pages representing screenshot pages." (map diff --git a/website/apps/media/data.scm b/website/apps/media/data.scm index 76af25d..89f7a8c 100644 --- a/website/apps/media/data.scm +++ b/website/apps/media/data.scm @@ -1,5 +1,6 @@ ;;; GNU Guix web site ;;; Copyright © 2019 Florian Pelz +;;; Copyright © 2020 Julien Lepiller ;;; Initially written by sirgazil who waives all ;;; copyright interest on this file. @@ -9,6 +10,7 @@ #:use-module (apps media types) #:use-module (srfi srfi-19) #:export (playlists + resources screenshots)) @@ -85,6 +87,53 @@ distribution.")) #:last-updated (string->date "2020-03-28T16:00:00" "~Y-~m-~dT~H:~M:~S"))))) +(define resources + (list + (resource + #:title (C_ "community resource title" "Everyday use of Guix") + #:link "https://media.marusich.info/everyday-use-of-gnu-guix-chris-marusich-seagl-2018.webm" + #:type 'video + #:language (G_ "English") + #:author "Chris Marushich" + #:date (string->date "2018-10-10" "~Y-~m-~d")) + (resource + #:title (C_ "community resource title" "Bitcoin Build System Security") + #:link "https://www.youtube.com/watch?v=I2iShmUTEl8" + #:type 'video + #:language (G_ "English") + #:preview (guix-url "static/media/img/community/carl-dong-bitcoin-security.webp") + #:author "Carl Dong" + #:date (string->date "2019-06-08" "~Y-~m-~d")) + (resource + #:title (C_ "community resource title" "Reproducible System Administration with GNU Guix") + #:link "https://replay.jres.org/videos/watch/c77b3a44-b75f-4c10-9f39-8fb55ae096d7" + #:type 'video + #:language (G_ "French") + #:author "Julien Lepiller" + #:date (string->date "2019-12-04" "~Y-~m-~d")) + (resource + #:title (C_ "community resource title" "Au-delà des conteneurs : environnements logiciels reproductibles avec GNU Guix") + #:link "https://webcast.in2p3.fr/video/au-dela-des-conteneurs-environnements-logiciels-reproductibles-avec-gnu-guix-1" + #:type 'video + #:language (G_ "French") + #:author "Ludovic Courtès" + #:date (string->date "2019-05-23" "~Y-~m-~d")) + (resource + #:title (C_ "community resource title" "Code Staging in GNU Guix") + #:link "https://arxiv.org/abs/1709.00833" + #:type 'article + #:language (G_ "English") + #:author "Ludovic Courtès" + #:date (string->date "2017-09-04" "~Y-~m-~d")) + (resource + #:title (C_ "community resource title" "Guix: A most advanced operating system") + #:link "https://ambrevar.xyz/guix-advance/index.html" + #:type 'blog + #:language (G_ "English") + #:author "Pierre Neidhardt" + #:date (string->date "2019-01-14" "~Y-~m-~d")))) + + (define screenshots (list (screenshot diff --git a/website/apps/media/templates/community.scm b/website/apps/media/templates/community.scm new file mode 100644 index 0000000..6cd51a0 --- /dev/null +++ b/website/apps/media/templates/community.scm @@ -0,0 +1,34 @@ +;;; GNU Guix web site +;;; Copyright © 2020 Julien Lepiller +;;; Initially written by sirgazil who waives all +;;; copyright interest on this file. + +(define-module (apps media templates community) + #:use-module (apps base templates theme) + #:use-module (apps base utils) + #:use-module (apps i18n) + #:use-module (apps media templates components) + #:export (community-t)) + +(define (community-t community-resources) + "Return an SHTML page for all COMMUNITY-RESOURCES." + (theme + #:title (C_ "webpage title" '("Community")) + #:description (G_ "Links to resources created by the community") + #:keywords + (string-split ;TRANSLATORS: |-separated list of webpage keywords + (G_ "GNU|Linux|Unix|Free software|Libre software|Operating \ +system|GNU Hurd|GNU Guix package manager|GNU Guile|Guile \ +Scheme|Transactional upgrades|Functional package \ +management|Reproducibility") #\|) + #:active-menu-item (C_ "website menu" "Media") + #:css (list (guix-url "static/base/css/index.css") + (guix-url "static/base/css/item-preview.css") + (guix-url "static/media/css/community.css")) + #:content + `(main + (section + (@ (class "page")) + (div + (@ (class "resource-box")) + ,@(map resource->shtml community-resources)))))) diff --git a/website/apps/media/templates/components.scm b/website/apps/media/templates/components.scm index d928d23..85574ee 100644 --- a/website/apps/media/templates/components.scm +++ b/website/apps/media/templates/components.scm @@ -1,5 +1,6 @@ ;;; GNU Guix web site ;;; Copyright © 2019 Florian Pelz +;;; Copyright © 2020 Julien Lepiller ;;; Initially written by sirgazil who waives all ;;; copyright interest on this file. @@ -14,7 +15,8 @@ #:use-module (apps media types) #:use-module (apps media utils) #:use-module (srfi srfi-19) - #:export (screenshot->shtml + #:export (resource->shtml + screenshot->shtml screenshots-box video->shtml video-content @@ -25,6 +27,26 @@ ;;; Components. ;;; +(define (resource->shtml resource) + `(a + (@ (class "community-preview item-preview") + (href ,(resource-link resource))) + (div + (@ (class "community-image")) + (div + (img + (@ (class "responsive-image") + (src ,(or (resource-preview resource) + (case (resource-type resource) + ((video) (guix-url "static/base/img/videos-icon.png")) + ((article blog) (guix-url "static/base/img/manual-icon.png"))))) + (alt ""))))) + (h3 ,(resource-title resource)) + (p + ,(G_ `(" published " ,(date->string (resource-date resource) "~b ~d, ~Y") + " by " ,(resource-author resource) + " in " ,(resource-language resource)))))) + (define (screenshot->shtml shot) "Return an SHTML representation of the given screenshot object. diff --git a/website/apps/media/types.scm b/website/apps/media/types.scm index 50c0989..ab54af8 100644 --- a/website/apps/media/types.scm +++ b/website/apps/media/types.scm @@ -5,7 +5,16 @@ (define-module (apps media types) #:use-module (srfi srfi-9) - #:export (screenshot + #:export (resource + resource? + resource-author + resource-date + resource-language + resource-link + resource-preview + resource-title + resource-type + screenshot screenshot? screenshot-caption screenshot-image @@ -32,6 +41,58 @@ ;;; Data types. ;;; +;;; Resource (record type) +;;; ---------------------- +;;; +;;; A community resource object represents a link to a resource created outside +;;; of the Guix project, that talks about Guix. +;;; +;;; Objects of this type can be created with the "resource" precodure (see +;;; Helper procedures below). +;;; +;;; Fields: +;;; +;;; title (string) +;;; The title of the resource +;;; +;;; link (string) +;;; The link to the resource +;;; +;;; author (string) +;;; The name of the author +;;; +;;; date (date) +;;; The date of publication +;;; +;;; preview (string) +;;; A URL to a small size image that represents the resource, or `#f' if +;;; it cannot be represented by an image. +;;; +;;; language (string) +;;; The name of the language in which the resource is written or spoken. +;;; +;;; type (symbol) +;;; The type of the resource, which can be one of: +;;; - 'article: a scientific or journalistic publication +;;; - 'blog: a blog post +;;; - 'video: a video presentation +(define-record-type + (make-resource title link author date preview language type) + resource? + (title resource-title) + (link resource-link) + (author resource-author) + (date resource-date) + (preview resource-preview) + (language resource-language) + (type resource-type)) + +;;; Helper procedures. + +(define* (resource #:key title link author date preview language type) + "Return a object with the given attributes." + (make-resource title link author date preview language type)) + ;;; Screenshot (record type) ;;; ------------------------ ;;; diff --git a/website/static/base/css/index.css b/website/static/base/css/index.css index ea52a6d..707091b 100644 --- a/website/static/base/css/index.css +++ b/website/static/base/css/index.css @@ -66,6 +66,18 @@ h3 { color: #E6E6E6; } +.resource-box { + padding: 40px 10px 0px 10px; + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.community-preview { + max-width: 270px; + padding: 0.5em; +} + .screenshots-box { padding: 40px 0px 0px 0px; } diff --git a/website/static/media/css/community.css b/website/static/media/css/community.css new file mode 100644 index 0000000..54de8d7 --- /dev/null +++ b/website/static/media/css/community.css @@ -0,0 +1,13 @@ +.community-image { + width: 180px; + height: 180px; + display: flex; + margin: auto; + flex-direction: row; + align-items: center; +} + +.community-image img { + max-width: 180px; + max-height: 180px; +} diff --git a/website/static/media/img/community/carl-dong-bitcoin-security.webp b/website/static/media/img/community/carl-dong-bitcoin-security.webp new file mode 100644 index 0000000000000000000000000000000000000000..017c00dd5c4b76614102b50a6bdb2f6887145a07 GIT binary patch literal 13952 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