diff --git a/internal/webserver/controller/document/controller.go b/internal/webserver/controller/document/controller.go index 2475f55..acb5865 100644 --- a/internal/webserver/controller/document/controller.go +++ b/internal/webserver/controller/document/controller.go @@ -24,9 +24,11 @@ type IdxReaderWriter interface { SameAuthors(slug string, quantity int) ([]index.Document, error) SameSeries(slug string, quantity int) ([]index.Document, error) RemoveFile(file string) error + Documents(IDs []string) (map[string]index.Document, error) } type highlightsRepository interface { + Highlights(userID int, page int, resultsPerPage int) (result.Paginated[[]string], error) Highlighted(userID int, doc index.Document) index.Document HighlightedPaginatedResult(userID int, results result.Paginated[[]index.Document]) result.Paginated[[]index.Document] } diff --git a/internal/webserver/controller/document/search.go b/internal/webserver/controller/document/search.go index 99effda..1ab944f 100644 --- a/internal/webserver/controller/document/search.go +++ b/internal/webserver/controller/document/search.go @@ -55,9 +55,29 @@ func (d *Controller) Search(c *fiber.Ctx) error { if err != nil { return fiber.ErrInternalServerError } + + highlights, err := d.hlRepository.Highlights(int(session.ID), page, 6) + if err != nil { + return fiber.ErrInternalServerError + } + + docs, err := d.idx.Documents(highlights.Hits()) + if err != nil { + return fiber.ErrInternalServerError + } + + docsSortedByHighlightedDate := make([]index.Document, len(docs)) + for i, path := range highlights.Hits() { + docsSortedByHighlightedDate[i] = docs[path] + docsSortedByHighlightedDate[i].Highlighted = true + } + return c.Render("index", fiber.Map{ - "Count": count, - "Title": "Coreander", - "Session": session, + "Count": count, + "Title": "Coreander", + "Session": session, + "Highlights": docsSortedByHighlightedDate, + "EmailSendingConfigured": emailSendingConfigured, + "EmailFrom": d.sender.From(), }, "layout") } diff --git a/internal/webserver/embedded/css/display.css b/internal/webserver/embedded/css/display.css index 9f507eb..3122a4b 100644 --- a/internal/webserver/embedded/css/display.css +++ b/internal/webserver/embedded/css/display.css @@ -75,7 +75,7 @@ a.collapse-control.collapsed:after { --bs-link-color: white; --bs-link-hover-color: white; --bs-link-color-rgb: 255, 255, 255; - --bs-link-hover-color-rgb: 139, 185, 254; + --bs-link-hover-color-rgb: 255, 255, 255; .pagination { --bs-pagination-active-bg: #ffffff; --bs-pagination-active-color: #000000; @@ -87,3 +87,7 @@ a.collapse-control.collapsed:after { background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } } + +.card-img-overlay a, .card-img-overlay p, .card-img-overlay h2, .card-img-overlay h3 { + color: rgba(255,255,255,0.8); +} diff --git a/internal/webserver/embedded/images/generic.jpg b/internal/webserver/embedded/images/generic.jpg index c7c6929..22fa6e4 100644 Binary files a/internal/webserver/embedded/images/generic.jpg and b/internal/webserver/embedded/images/generic.jpg differ diff --git a/internal/webserver/embedded/js/cover-loader.js b/internal/webserver/embedded/js/cover-loader.js new file mode 100644 index 0000000..a96364a --- /dev/null +++ b/internal/webserver/embedded/js/cover-loader.js @@ -0,0 +1,30 @@ +window.onload = function () { + let imgs = document.querySelectorAll('.cover'); + for (i = 0; i < imgs.length; i++) { + let img = imgs[i]; + + if (!img.getAttribute('data-src')) { + continue; + } + + img.addEventListener('error', function onError(e) { + this.setAttribute('src', '/images/generic.jpg'); + }); + + img.setAttribute('src', img.getAttribute('data-src')); + + img.addEventListener('load', (event) => { + if (img.getAttribute('src') == '/images/generic.jpg') { + return; + } + let cardTitle = img.nextElementSibling.getElementsByClassName('card-title')[0]; + let cardTitleLink = cardTitle.getElementsByTagName('a')[0] + if (cardTitleLink) { + cardTitleLink.text = ''; + } else { + cardTitle.innerHTML = '' + } + img.nextElementSibling.getElementsByClassName('card-text')[0].innerHTML = ''; + }); + } +} diff --git a/internal/webserver/embedded/translations/es.yml b/internal/webserver/embedded/translations/es.yml index c4bfcf3..091fbd9 100644 --- a/internal/webserver/embedded/translations/es.yml +++ b/internal/webserver/embedded/translations/es.yml @@ -75,8 +75,6 @@ "Request": "Solicitar" "A reset password request for Coreander has been received. You can proceed by clicking in the following link or pasting it in your browser": "Hemos recibido una petición para actualizar tu contraseña en Coreander. Si has sido tu, puedes continuar haciendo click en el siguiente enlace o pegándolo en tu navegador" "If you didn't request this, you can safely disregard this email.": "Si no has sido tu, puedes ignorar este correo." -"New password": "Nueva contraseña" -"Confirm new password": "Confirmar nueva contraseña" "We've received your password recovery request. If the address you introduced is registered in our system, you'll receive an email with further instructions in your inbox.": "Hemos recibido tu petición para recuperar tu contraseña. Si la dirección que has indicado está registrada en el sistema, recibiras un correo con indicaciones en tu bandeja de entrada." "Password recovery request": "Petición de recuperación de contraseña" "Set new password": "Introduce tu nueva contraseña" @@ -108,3 +106,4 @@ "Remove from highlights": "Quitar de destacados" "%d highlighted documents": "%d documentos destacados" "Method not allowed": "Método no permitido" +"Your highlights": "Tus destacados" diff --git a/internal/webserver/embedded/translations/fr.yml b/internal/webserver/embedded/translations/fr.yml index 7eea69c..79e2400 100644 --- a/internal/webserver/embedded/translations/fr.yml +++ b/internal/webserver/embedded/translations/fr.yml @@ -60,7 +60,7 @@ "Profile updated": "Profil mis à jour" "Current password": "Mot de passe actuel" "New password": "Nouveau mot de passe" -"Confirm new password": "Confirmar nueva contraseña" +"Confirm new password": "Confirmer le nouveau mot de passe" "Default send to email address": "Adresse e-mail d'envoi par défaut" "Please, fix the following issues": "S'il vous plaît, corrigez les problèmes suivants" "Delete user": "Supprimer l'utilisateur" @@ -75,8 +75,6 @@ "Request": "Solliciter" "A reset password request for Coreander has been received. You can proceed by clicking in the following link or pasting it in your browser": "Une demande de réinitialisation du mot de passe pour Coreander a été reçue. Vous pouvez continuer en cliquant sur le lien suivant ou en le collant dans votre navigateur" "If you didn't request this, you can safely disregard this email.": "Si vous ne l'avez pas demandé, vous pouvez ignorer cet e-mail en toute sécurité." -"New password": "Nouveau mot de passe" -"Confirm new password": "Confirmer le nouveau mot de passe" "We've received your password recovery request. If the address you introduced is registered in our system, you'll receive an email with further instructions in your inbox.": "Nous avons reçu votre demande de récupération de mot de passe. Si l'adresse que vous avez introduite est enregistrée dans notre système, vous recevrez un e-mail contenant des instructions supplémentaires dans votre boîte de réception." "Password recovery request": "Demande de récupération de mot de passe" "Set new password": "Définir un nouveau mot de passe" @@ -108,3 +106,4 @@ "Remove from highlights": "Retirer des favoris" "%d highlighted documents": "%d documents favoris" "Method not allowed": "Méthode Non Autorisée" +"Your highlights": "Vos favoris" diff --git a/internal/webserver/embedded/views/actions.js.html b/internal/webserver/embedded/views/actions.js.html index 8547bad..35d8b8d 100644 --- a/internal/webserver/embedded/views/actions.js.html +++ b/internal/webserver/embedded/views/actions.js.html @@ -78,16 +78,4 @@ console.log(error); }); } - - window.onload = function () { - let imgs = document.querySelectorAll('.cover'); - for (i = 0; i < imgs.length; i++) { - if (imgs[i].getAttribute('data-src')) { - imgs[i].addEventListener('error', function onError(e) { - this.setAttribute('src', '/images/generic.jpg'); - }); - imgs[i].setAttribute('src', imgs[i].getAttribute('data-src')); - } - } - } diff --git a/internal/webserver/embedded/views/document.html b/internal/webserver/embedded/views/document.html index 0d9ae9a..3f099f7 100644 --- a/internal/webserver/embedded/views/document.html +++ b/internal/webserver/embedded/views/document.html @@ -6,11 +6,22 @@
-
+
{{t $lang "\"%s\" cover" .Document.Title}} +
+

{{.Document.Title}}

+

+ {{if .Document.Authors}} + {{join .Document.Authors ", "}} + {{else}} + {{t $lang "Unknown author"}} + {{end}} +

+
+ - {{template "partials/related" dict "Lang" $lang "Related" .SameSeries}} +
+ {{range $i, $doc := .SameSeries}} +
+ {{template "partials/related" dict "Lang" $lang "Document" $doc}} +
+ {{end}} +
{{end}} @@ -152,7 +169,13 @@

{{t $lang "See all" }}

- {{template "partials/related" dict "Lang" $lang "Related" .SameAuthors}} +
+ {{range $i, $doc := .SameAuthors}} +
+ {{template "partials/related" dict "Lang" $lang "Document" $doc}} +
+ {{end}} +
{{end}} @@ -166,7 +189,13 @@

{{t $lang "Other documents with similar subjects"}}

{{t $lang "See all" }}
- {{template "partials/related" dict "Lang" $lang "Related" .SameSubjects}} +
+ {{range $i, $doc := .SameSubjects}} +
+ {{template "partials/related" dict "Lang" $lang "Document" $doc}} +
+ {{end}} +
{{end}}
@@ -177,3 +206,4 @@

{{t $lang "Other documents with similar subjects"}}

{{template "partials/delete-modal" .}} {{template "actions.js" dict "Lang" $lang}} + diff --git a/internal/webserver/embedded/views/index.html b/internal/webserver/embedded/views/index.html index 34c32b4..8f0e7ec 100644 --- a/internal/webserver/embedded/views/index.html +++ b/internal/webserver/embedded/views/index.html @@ -3,17 +3,55 @@ {{template "partials/searchbox" .}}

{{t .Lang "%d documents available" .Count}}

-
-

{{t .Lang "Search tips"}}

-

{{t .Lang "Use %s prefix in search box to search by authors only" `Authors:`}}

-

{{t .Lang "Use %s prefix in search box to search by title only" `Title:`}}

-

{{t .Lang "Use %s prefix in search box to search by series only" `Series:`}}

-

{{t .Lang "Use %s prefix in search box to search by subjects only" `Subjects:`}}

-

{{t .Lang "Enclose your search terms in double quotes to require all those terms and with the same order"}} -

-
+ {{if and (.Session) (ne .Session.Name "")}} +
+
+

{{t .Lang "Your highlights" }}

+
+ + +
+ {{$lang := .Lang}} + {{$emailSendingConfigured := .EmailSendingConfigured}} + {{$session := .Session}} + {{$emailFrom := .EmailFrom}} + + {{range $i, $doc := .Highlights}} +
+ {{template "partials/related" dict "Lang" $lang "Document" $doc}} +
+ +
+
+ {{end}} +
+
+ {{template "actions.js" dict "Lang" $lang}} + + {{else}} +
+

{{t .Lang "Search tips"}}

+

{{t .Lang "Use %s prefix in search box to search by authors only" `Authors:`}}

+

{{t .Lang "Use %s prefix in search box to search by title only" `Title:`}}

+

{{t .Lang "Use %s prefix in search box to search by series only" `Series:`}}

+

{{t .Lang "Use %s prefix in search box to search by subjects only" `Subjects:`}}

+

{{t .Lang "Enclose your search terms in double quotes to require all those terms and with the same order"}} +

+
+ {{end}}
diff --git a/internal/webserver/embedded/views/partials/actions.html b/internal/webserver/embedded/views/partials/actions.html index dcb5946..5a33cca 100644 --- a/internal/webserver/embedded/views/partials/actions.html +++ b/internal/webserver/embedded/views/partials/actions.html @@ -1,85 +1,79 @@ - +
+ - {{end}} - - + {{end}} + {{if eq .Session.Role 2}} + +
  • + + + +   {{t .Lang "Delete"}} {{basename .Document.ID}} +
  • + {{end}} + diff --git a/internal/webserver/embedded/views/partials/docs-list.html b/internal/webserver/embedded/views/partials/docs-list.html index 04bbe92..22c8d5b 100644 --- a/internal/webserver/embedded/views/partials/docs-list.html +++ b/internal/webserver/embedded/views/partials/docs-list.html @@ -8,10 +8,20 @@ {{if .Results}} {{range $i, $document := .Results.Hits}}
    -
    - {{t $lang "\"%s\" cover" $document.Title}} +
    + {{t $lang "\"%s\" cover" $document.Title}} +
    +
    {{$document.Title}}
    +

    + {{if $document.Authors}} + {{join $document.Authors ", "}} + {{else}} + {{t $lang "Unknown author"}} + {{end}} +

    +
    -
    +
    {{ if ne $document.Series "" }} {{$seriesTitle := t $lang "Search for more titles belonging to %s" @@ -25,8 +35,14 @@

    - {{ template "partials/actions" dict "Lang" $lang "Document" $document "EmailSendingConfigured" - $emailSendingConfigured "Index" $i "Session" $session "EmailFrom" $emailFrom}} +
    @@ -79,3 +95,4 @@
    {{t $lang "Unknown author"}}
    {{template "delete.js" dict "Lang" $lang}} {{template "actions.js" dict "Lang" $lang}} + diff --git a/internal/webserver/embedded/views/partials/related.html b/internal/webserver/embedded/views/partials/related.html index 097098d..7f05c3b 100644 --- a/internal/webserver/embedded/views/partials/related.html +++ b/internal/webserver/embedded/views/partials/related.html @@ -1,21 +1,13 @@ -{{$lang := .Lang}} - -
    - {{range $i, $doc := .Related}} -
    -
    - {{t $lang "\"%s\" cover" $doc.Title}} -
    -
    {{$doc.Title}}
    - {{if $doc.Authors}} +
    + {{t .Lang "\"%s\" cover" .Document.Title}} +
    +
    {{.Document.Title}}
    + {{if .Document.Authors}}

    - {{join $doc.Authors ", "}} + {{join .Document.Authors ", "}}

    - {{else}} -

    {{t $lang "Unknown author"}}

    - {{end}} -
    -
    + {{else}} +

    {{t .Lang "Unknown author"}}

    + {{end}}
    - {{end}}
    diff --git a/internal/webserver/embedded/views/partials/searchbox.html b/internal/webserver/embedded/views/partials/searchbox.html index 777c160..db5a5ff 100644 --- a/internal/webserver/embedded/views/partials/searchbox.html +++ b/internal/webserver/embedded/views/partials/searchbox.html @@ -3,7 +3,7 @@
    - +