Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: go templ #100

Merged
merged 98 commits into from
Mar 8, 2024
Merged

Feat: go templ #100

merged 98 commits into from
Mar 8, 2024

Conversation

blackfyre
Copy link
Owner

@blackfyre blackfyre commented Feb 27, 2024

Summary by CodeRabbit

  • New Features
    • Introduced new templating for components, layouts, error pages, and static pages enhancing the user interface.
    • Added a feedback form for user input and a postcard editor for personalized digital postcards.
    • Enhanced navigation with a responsive top navigation bar.
    • Implemented a guestbook feature for user entries and a contributors page displaying GitHub contributors.
    • Improved artwork and artist pages with detailed information and search functionality.
    • Updated the home page to display content, artist count, and artwork count dynamically.
  • Bug Fixes
    • Corrected a typo in color variable names for consistent styling.
    • Adjusted event handling in JavaScript for better error and timeout management.
  • Documentation
    • Updated documentation to reflect changes in templating and component usage.
  • Refactor
    • Refactored handlers for artists, artworks, feedback, guestbook, and static pages to improve code structure and efficiency.
    • Updated utility functions for better error handling and pagination.
  • Style
    • Updated styles for navigation, feedback forms, and progress indicators for a more cohesive look and feel.
  • Chores
    • Updated Go version and added new tools and libraries for improved development workflow.
    • Enhanced .gitignore to exclude specific templating-generated files.
  • Tests
    • Deprecated certain functions in favor of new implementations for JSON-LD content generation and error handling.

@blackfyre blackfyre marked this pull request as ready for review March 8, 2024 05:39
@blackfyre blackfyre merged commit 353d112 into main Mar 8, 2024
1 of 2 checks passed
@blackfyre blackfyre deleted the feat/go-templ branch March 8, 2024 05:48
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 11

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 096a86c and 519676b.
Files ignored due to path filters (7)
  • Taskfile.yml is excluded by: !**/*.yml
  • assets/public/js/vendor/htmx.min.js is excluded by: !**/vendor/**, !**/*.min.js
  • docker-compose.yml is excluded by: !**/*.yml
  • go.mod is excluded by: !**/*.mod
  • go.sum is excluded by: !**/*.sum
  • package-lock.json is excluded by: !**/*.json
  • package.json is excluded by: !**/*.json
Files selected for processing (50)
  • .github/workflows/release.yml (1 hunks)
  • .gitignore (1 hunks)
  • .goreleaser.yaml (2 hunks)
  • .tool-versions (1 hunks)
  • .vscode/settings.json (1 hunks)
  • assets/public/js/vendor/.gitignore (1 hunks)
  • assets/templ/components/feedback.templ (1 hunks)
  • assets/templ/components/footer.templ (1 hunks)
  • assets/templ/components/image.templ (1 hunks)
  • assets/templ/components/nav.templ (1 hunks)
  • assets/templ/components/postcard.templ (1 hunks)
  • assets/templ/error_pages/not_found.templ (1 hunks)
  • assets/templ/error_pages/server_fault.templ (1 hunks)
  • assets/templ/layouts/layout.templ (1 hunks)
  • assets/templ/pages/artist.templ (1 hunks)
  • assets/templ/pages/artists.templ (1 hunks)
  • assets/templ/pages/artwork.templ (1 hunks)
  • assets/templ/pages/artworks.templ (1 hunks)
  • assets/templ/pages/contributors.templ (1 hunks)
  • assets/templ/pages/guestbook.templ (1 hunks)
  • assets/templ/pages/home.templ (1 hunks)
  • assets/templ/pages/postcard.templ (1 hunks)
  • assets/templ/pages/static.templ (1 hunks)
  • assets/templ/utils/utils.go (1 hunks)
  • esbuild.mjs (4 hunks)
  • handlers/artist.go (3 hunks)
  • handlers/artists.go (2 hunks)
  • handlers/artworks/main.go (4 hunks)
  • handlers/contributors.go (5 hunks)
  • handlers/feedback.go (3 hunks)
  • handlers/guestbook.go (2 hunks)
  • handlers/guestbook/main.go (1 hunks)
  • handlers/home.go (2 hunks)
  • handlers/musics.go (1 hunks)
  • handlers/postcard.go (5 hunks)
  • handlers/static.go (3 hunks)
  • handlers/utils.go (1 hunks)
  • models/artist.go (1 hunks)
  • models/guestbbok.go (2 hunks)
  • resources/css/_layout.scss (1 hunks)
  • resources/css/_variables.scss (1 hunks)
  • resources/css/style.scss (5 hunks)
  • resources/js/app.js (2 hunks)
  • utils/htmx.go (1 hunks)
  • utils/jsonld/main.go (4 hunks)
  • utils/jsonld/types.go (1 hunks)
  • utils/main.go (3 hunks)
  • utils/pagination.go (4 hunks)
  • utils/sitemap/main.go (3 hunks)
  • utils/url.go (1 hunks)
Files skipped from review due to trivial changes (4)
  • .gitignore
  • .tool-versions
  • assets/public/js/vendor/.gitignore
  • resources/css/_variables.scss
Additional comments: 78
.vscode/settings.json (1)
  • 1-27: The updates to .vscode/settings.json are well-aligned with the project's shift towards using the a-h/templ templating engine. These changes enhance the developer experience by properly configuring the development environment for the new templating approach. No issues or concerns were identified.
.goreleaser.yaml (1)
  • 1-6: The changes to .goreleaser.yaml, including the removal of npm ci and go mod tidy hooks and the replacement of node esbuild.mjs with templ generate, align well with the PR's objectives of integrating the a-h/templ templating engine and simplifying the build process. The adjustments to the build configuration and archive naming template are logical and raise no concerns.
assets/templ/pages/static.templ (1)
  • 1-35: The introduction of the StaticPage and StaticPageBlock templates for rendering static content using the a-h/templ templating engine is well-executed. The structure is clear, and the separation of concerns between the page and its content block is commendable. The use of layout and utility functions aligns with templating best practices.
assets/templ/error_pages/not_found.templ (1)
  • 1-27: The NotFoundPage and NotFoundBlock templates for rendering a 404 Not Found error page are well-designed, following the conventions of the a-h/templ templating engine. The use of a main layout and the inclusion of a user-friendly message and a link to return to the homepage enhance the user experience in the event of a 404 error. The structure and messaging are clear and effective.
assets/templ/error_pages/server_fault.templ (1)
  • 1-27: The ServerFaultPage and ServerFaultBlock templates for rendering a 500 Server Fault error page are well-designed, following the conventions of the a-h/templ templating engine. The structure and messaging are consistent with best practices for error handling in web applications, offering a clear explanation and a link to return to the homepage. The user-friendly design of the error page is commendable.
utils/htmx.go (1)
  • 10-18: It would be beneficial to document the expected structure of the data parameter in the SetHxTrigger function for clarity and future maintenance. Providing examples or a description of the expected keys and values can improve the maintainability of the code.
handlers/utils.go (1)
  • 33-33: The deprecation notice for the sendToastMessage function is clear and provides guidance on the preferred alternative. Consider adding more context, such as the timeline for removal or specific reasons for the deprecation, to give developers additional information.
assets/templ/pages/home.templ (3)
  • 8-12: The struct HomePage is well-defined and aligns with the expected data for rendering the home page.
  • 14-18: The HomePageWrapped function correctly wraps the home page content within the main layout. Good use of templating features.
  • 20-47: The HomePageContent function is well-structured and makes effective use of templating features to dynamically render content. Good job!
assets/templ/pages/artist.templ (2)
  • 9-14: The ArtistPage function correctly wraps the artist page content within the main layout. It effectively uses templating to inject artist-specific content.
  • 16-46: The ArtistBlock function is well-structured and makes effective use of templating features to dynamically render artist details and works. The use of @components.ImageGridComponent for rendering an image grid is a good practice.
assets/templ/pages/postcard.templ (3)
  • 8-16: The struct PostcardView is well-defined and aligns with the expected data for rendering the postcard page.
  • 18-22: The PostcardPage function correctly wraps the postcard page content within the main layout. It effectively uses templating to inject postcard-specific content.
  • 24-52: The PostcardBlock function is well-structured and makes effective use of templating features to dynamically render the postcard image and message. The use of @components.ImageBig for rendering a large image is a good practice.
.github/workflows/release.yml (4)
  • 28-28: The Go version is correctly updated to ">=1.22.0" as per the PR objectives. This ensures compatibility with the new templating engine and other project dependencies.
  • 30-31: The addition of the a-h/templ installation step is crucial for the new templating engine's functionality. This ensures that templ is available for generating static content during the build process.
  • 30-31: The addition of the a-h/templ installation step is crucial for the new templating engine's functionality. This ensures that templ is available for generating static content during the build process.
  • 30-31: The GoReleaser configuration is appropriately updated to align with the new build process, ensuring a streamlined release workflow.
assets/templ/components/footer.templ (1)
  • 3-42: The Footer function is well-structured and makes effective use of templating features to dynamically render footer content, including links and donation options. Good job!
assets/templ/pages/artwork.templ (3)
  • 9-17: The struct Artwork is well-defined and aligns with the expected data for rendering the artwork page, including embedded Image and Artist structs for comprehensive artwork details.
  • 19-23: The ArtworkPage function correctly wraps the artwork page content within the main layout. It effectively uses templating to inject artwork-specific content.
  • 25-63: The ArtworkBlock function is well-structured and makes effective use of templating features to dynamically render the artwork image, details, and a link for sending a postcard. The use of @components.ImageBig for rendering a large image is a good practice.
assets/templ/components/feedback.templ (1)
  • 3-67: The FeedbackForm function is well-structured and makes effective use of templating features to dynamically render the feedback form. The inclusion of honeypot fields for spam prevention is a good practice.
handlers/guestbook.go (1)
  • 61-69: The refactoring of the guestbook handlers to delegate functionality to the guestbook package improves modularity and maintainability. Good job on the clean separation of concerns.
models/artist.go (1)
  • 12-12: The addition of the Id field to the Artist struct is necessary for uniquely identifying artists in the database. This is a good practice for database design.
assets/templ/components/image.templ (1)
  • 16-26: The ImageBase function correctly defines a basic image figure with responsive sources and lazy loading. Good use of HTML5 and templating features.
assets/templ/pages/contributors.templ (1)
  • 8-31: The ContributorsPageDTO and GithubContributor structs are well-defined and align with the typical structure expected for handling contributors' data from GitHub. However, ensure that all fields in the GithubContributor struct are necessary for the application's functionality to avoid fetching and storing unnecessary data.
utils/sitemap/main.go (3)
  • 9-9: The addition of the import statement for github.com/blackfyre/wga/utils is appropriate for the functionality being implemented in this file. Ensure that the imported package is used effectively within the file.
  • 61-61: The modification to the Loc value in the generateArtistMap function to include both the artist's slug and ID in the URL is a good practice for SEO and user-friendly URLs. This change enhances the sitemap's usefulness by providing more descriptive URLs.
  • 110-110: Similarly, the modification in the generateArtworksMap function to include the artist's slug, ID, and the artwork's title and ID in the URL is beneficial for SEO and improves the clarity of the sitemap. This approach helps search engines and users understand the content of the links better.
assets/templ/pages/artists.templ (2)
  • 9-28: The Artist and ArtistsView structs are well-defined and provide a clear structure for representing artist data and the view model for the artists' page. This structured approach facilitates maintainability and readability of the code.
  • 30-133: The templated functions ArtistsPageFull, ArtistsPageBlock, artistsTable, and ArtistsSearchResults are correctly implemented using the a-h/templ engine. They effectively utilize loops, conditionals, and data binding to render dynamic content. However, ensure that the pagination and search functionality are thoroughly tested across different scenarios to ensure a smooth user experience.
handlers/contributors.go (4)
  • 4-11: The refactoring of import paths to use specific page-related assets and utilities is a good practice that enhances the modularity and clarity of the code. This change aligns with the project's shift towards a more component-based approach.
  • 1-21: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [18-40]

The getContributorsFromGithub function is well-implemented, with appropriate error handling and use of the GitHub API. However, consider adding rate limiting or caching mechanisms to avoid hitting GitHub API rate limits and to improve the performance of your application.

  • 63-69: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [66-75]

The readStoredContributors function provides a fallback mechanism to read contributors' data from a local file if the GitHub API call fails. This approach enhances the reliability of the application. Ensure that the contributors.json file is updated regularly to reflect the most current data.

  • 88-126: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [66-123]

In the registerContributors function, the use of the pages package for struct types and the enhanced error handling and rendering logic are commendable. However, ensure that the error messages provided to the user are user-friendly and that any sensitive information is not exposed.

utils/jsonld/types.go (1)
  • 3-80: The struct definitions for Person, Place, Occupation, VisualArtwork, and ImageObject are well-structured and align with the JSON-LD format for representing structured data on the web. The use of omitempty tags is appropriate for optional fields. Additionally, the functions for creating new instances of these structs (newPerson, newPlace, newOccupation, newVisualArtwork) are correctly implemented and ensure that the @context and @type fields are properly set. This approach enhances the maintainability and readability of the code.
esbuild.mjs (4)
  • 6-6: The addition of the copy import from "esbuild-plugin-copy" is a good practice for managing static assets more efficiently. This change allows for the direct copying of necessary files during the build process, reducing manual effort and potential errors.
  • 21-21: Updating the target option to include multiple browser targets ensures that the generated code is compatible with a wider range of browsers. This change improves the accessibility and user experience of your application across different environments.
  • 39-79: The modifications to the safelist and content paths for CSS purging are crucial for ensuring that necessary CSS classes are not removed during the build process. This change enhances the visual consistency of the application. However, ensure that the safelist is kept up-to-date as the project evolves to avoid styling issues.
  • 92-107: The addition of copy configurations for htmx library assets is a practical approach to managing external library dependencies. This ensures that the necessary files are included in the build output, facilitating easier deployment and usage of the htmx features within the application.
utils/jsonld/main.go (3)
  • 4-6: Renaming wgamodels to wgaModels improves the consistency and readability of the import aliases. This change aligns with Go naming conventions and enhances the maintainability of the code.
  • 16-17: Deprecating GenerateArtistJsonLdContent in favor of ArtistJsonLd is a good practice for evolving the codebase while maintaining backward compatibility. Ensure that the deprecated function is removed in future versions after updating all its usages.
  • 51-78: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [54-80]

The introduction of the ArtistJsonLd and ArtworkJsonLd functions for generating JSON-LD content is a significant improvement. These functions provide a more structured and type-safe way of generating structured data, enhancing the SEO and data handling of the application. Ensure that these functions are thoroughly tested with various input data to validate their correctness.

handlers/static.go (3)
  • 4-16: The addition of imports for new packages related to error and static pages rendering is appropriate for the functionality being implemented in this file. This change enhances the modularity and clarity of the code by separating concerns and utilizing specialized packages for specific tasks.
  • 42-62: The modified logic for handling static pages, including decorating the context with page information and setting response headers, is well-implemented. This approach provides a more structured and maintainable way of rendering static pages. However, ensure that the StaticPageDTO struct and the StaticPage templated function are correctly defined and used across the application.
  • 66-70: The addition of a new route for handling a 404 error page is a good practice for improving the user experience by providing a custom error page instead of a generic server error message. Ensure that the NotFoundPage templated function is correctly implemented and that the error page is styled consistently with the rest of the application.
handlers/feedback.go (1)
  • 7-7: Changing the import path to use github.com/blackfyre/wga/assets/templ/components for the feedback form component is a good practice that aligns with the project's shift towards a more component-based approach. This change enhances the modularity and maintainability of the code.
assets/templ/layouts/layout.templ (1)
  • 8-61: - The base layout template is well-structured and follows HTML5 standards.
  • Dynamic content such as title, description, OpenGraph, and Twitter tags are correctly fetched using utility functions.
  • External resources (CSS and JS files) are properly linked.
  • The use of hx-* attributes indicates integration with HTMX for AJAX capabilities, enhancing the interactivity of the web application without full page reloads.
  • Ensure that all external resources (e.g., Trix editor, animate.css) are available and compatible with the project's security and performance requirements.
assets/templ/components/postcard.templ (1)
  • 12-153: - The PostcardEditor component is well-structured, providing a user-friendly interface for creating postcards.
  • Form submission is handled via HTMX (hx-post), indicating asynchronous processing without a full page reload.
  • The use of hx-disabled-elt attribute on the form ensures that inputs are disabled during submission, preventing duplicate submissions.
  • The inclusion of hidden fields (hpt) for honey pot technique is a good practice for spam prevention. Ensure that server-side validation properly ignores these fields when processing form submissions.
  • Consider adding client-side validation for required fields to improve user experience and reduce server-side load.
  • The dynamic image source ({ p.Image }) and alt text ({ p.Title + " by " + p.AuthorName }) are correctly implemented, enhancing accessibility and SEO.
handlers/home.go (1)
  • 124-166: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [23-180]

  • The refactoring of the home page handler improves modularity and readability.
  • Database queries for welcome content, artist count, and artwork count are well-structured. Consider caching these values to improve performance, especially if they do not change frequently.
  • Error handling is consistent, using utils.ServerFaultError to return server errors. Ensure that this function logs the error and returns an appropriate HTTP status code to the client.
  • The use of tmplUtils.DecorateContext for setting page metadata (title, description, canonical URL) is a good practice for SEO.
  • The HX-Push-Url header manipulation ensures that the correct URL is displayed in the browser, which is important for SPA-like behavior with HTMX.
handlers/guestbook/main.go (3)
  • 39-68: - The EntriesHandler function correctly retrieves guestbook entries for a specified year and renders them using the GuestbookView template. The use of HTMX for dynamic content loading is consistent with modern web development practices.
  • The selection of the year through a dropdown menu with HTMX (hx-get) for filtering entries without a full page reload enhances user experience.
  • Error handling is consistent, using utils.ServerFaultError for server errors. Ensure that all possible errors during database queries are handled appropriately.
  • The dynamic construction of the fullUrl for canonical URL purposes is a good practice for SEO.
  • 71-83: - The StoreEntryViewHandler function serves the form for adding a new guestbook entry. The use of HTMX to load this form dynamically is a good practice for enhancing user experience by avoiding full page reloads.
  • Ensure that the form rendered by pages.GuestbookEntryForm() includes all necessary validations and error handling to provide feedback to the user in case of invalid input.
  • 86-151: - The StoreEntryHandler function handles the submission of new guestbook entries. The use of HTMX for asynchronous form submission is consistent with modern web development practices.
  • The honey pot technique implemented for spam prevention is a good practice. Ensure that server-side validation properly ignores these fields when processing form submissions.
  • Error handling during form submission and database interaction is well-implemented, providing user feedback through toast messages.
  • Consider adding server-side validation for the form fields to ensure data integrity and prevent SQL injection or other security vulnerabilities.
assets/templ/pages/artworks.templ (1)
  • 33-198: - The ArtworkSearchPage and its components (ArtworkSeachFilterBlock, ArtworkSearchResults, ArtworkSearchBlock) are well-structured, providing a comprehensive interface for searching artworks.
  • The use of HTMX (hx-get) for the search filter form submission enhances the user experience by dynamically loading search results without a full page reload.
  • Dynamic content rendering for search filters, results, and pagination is correctly implemented. Ensure that the pagination component correctly handles edge cases, such as a large number of pages.
  • Consider adding client-side validation for the search filters to improve user experience and reduce server-side load.
  • The commented-out imports (// "github.com/blackfyre/wga/assets/templ/utils", // "github.com/blackfyre/wga/assets/templ/components") should be removed if they are not needed to keep the code clean.
handlers/artists.go (1)
  • 23-180: - The processArtists function is well-structured, providing a clear flow for retrieving artist information based on search criteria and pagination, and rendering the view.
  • The use of JSON-LD for structured data is a good practice for SEO, enhancing the visibility of artist information in search engines.
  • Pagination is handled effectively, improving user experience by allowing users to navigate through artist listings easily.
  • Ensure that all external resources and dependencies (e.g., pages.ArtistsView, jsonld.Person) are correctly implemented and available.
  • Consider adding more detailed error messages for user feedback in case of failed operations, such as database queries or JSON-LD generation.
assets/templ/pages/guestbook.templ (1)
  • 18-205: - The guestbook templates (GuestbookPage, GuestbookBlock, GuestbookEntryForm, GuestbookEntries, GuestbookEntry) are well-structured, providing a comprehensive interface for viewing and adding guestbook entries.
  • The use of HTMX (hx-get, hx-post) for dynamic content loading and form submission enhances the user experience by avoiding full page reloads.
  • The implementation of the honey pot technique in the entry form is a good practice for spam prevention. Ensure that server-side validation properly ignores these fields when processing form submissions.
  • The use of Gravatar for displaying user avatars based on their email addresses is a nice touch, adding a personal element to the guestbook entries.
  • Consider adding client-side validation for the entry form to improve user experience and reduce server-side load.
resources/css/style.scss (5)
  • 21-23: The correction from wgaTorquise to wgaTurquoise for various navbar elements improves consistency and corrects a typographical error in the variable name. This change enhances readability and maintainability of the code.
  • 32-32: The addition of @import "../../node_modules/bulma-list/sass/bulma-list.sass"; introduces a new dependency on bulma-list. Ensure that this dependency is properly documented and included in the project's package management files to avoid build or runtime issues.
Verification successful

The addition of @import "../../node_modules/bulma-list/sass/bulma-list.sass"; has been properly documented and included in the project's package management files, as evidenced by the presence of bulma-list with version ^1.2.0 in the package.json dependencies.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Check if bulma-list is included in package.json dependencies
rg '"bulma-list":' package.json

Length of output: 60

* 176-181: The styling modifications for `figure`, specifically the `object-fit: cover;` property for `source` and `img` tags, ensure that images are properly scaled and cropped to fit their containers. This enhances the visual presentation of images across the site. * 193-193: The `.button.is-feedback` class styling positions the feedback button in a fixed location and rotates it for a unique presentation. Verify that this styling works as intended across different screen sizes and devices to ensure a consistent user experience. * 205-245: The `.progress-indicator` class and its child elements have been styled to create an indeterminate loading animation. This includes keyframes for the animation. Ensure that the animation performs smoothly across different browsers and that it aligns with the site's overall design language.
utils/main.go (4)
  • 5-5: The import of context is appropriate for the new error handling functions that utilize it for rendering error pages. This aligns with Go's standard practice of passing context to functions for request-scoped values, cancellation signals, and deadlines.
  • 306-313: The NotFoundError function correctly checks if the request is an HTMX request and renders the appropriate error block or page accordingly. This is a good practice for handling AJAX requests differently from standard requests, improving the user experience by providing feedback without a full page reload.
  • 315-321: Similarly, the ServerFaultError function follows the same pattern as NotFoundError for handling server errors. It's a good practice to have distinct functions for different types of errors, as it allows for more granular control over the response sent to the client.
  • 308-308: Using context.Background() in both NotFoundError and ServerFaultError functions is acceptable in this context since these functions are meant to render error pages and likely do not need to carry request-scoped data or cancellation signals. However, if there's any future need for request-scoped data or deadlines within these rendering operations, consider passing the request's context instead.

Also applies to: 317-317

handlers/postcard.go (5)
  • 4-12: The addition of imports for bytes, context, and specific subpackages (components, error_pages, pages) is appropriate for the refactored postcard handling logic. These imports support the new component-based approach and error handling improvements. The removal of godotenv suggests a shift away from environment variable management within this file, which is fine if configuration loading is handled elsewhere or no longer needed.
  • 54-60: Refactoring renderPostcardEditor to use components.PostcardEditor for rendering the postcard editor is a good practice. It aligns with the component-based approach, making the code more modular and maintainable. Ensure that all necessary data is correctly passed to the PostcardEditorDTO to render the editor accurately.
  • 24-24: Introducing registerPostcardHandlers to manage postcard-related routes is a positive change. It encapsulates the routing logic for postcards, making the codebase more organized and easier to navigate. This approach enhances modularity and maintainability.
  • 48-52: The improved error handling and logging within the postcard handlers are commendable. Logging errors and rendering appropriate error pages enhance the robustness of the application and improve the user experience by providing meaningful feedback during failures. Continue this practice across other parts of the application for consistency and reliability.

Also applies to: 63-64, 127-127

  • 105-135: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [82-132]

Implementing caching for postcard views using app.Store().Has(cacheKey) and app.Store().Set(cacheKey, cacheBuffer.String()) is an effective way to improve performance by reducing database queries and rendering times for frequently accessed content. Ensure that the cache is properly invalidated or updated when the underlying data changes to prevent serving stale content to users.

utils/pagination.go (4)
  • 90-104: Adding methods FirstPart, MiddlePart, LastPart to retrieve different parts of the pagination is a good practice. It allows for more flexible rendering of pagination links, especially in cases where the total number of pages is large. This approach enhances the usability of the pagination component by focusing on the most relevant pages to the user.
  • 105-113: The introduction of the generate method to dynamically generate pagination links based on the current state is a significant improvement. It smartly decides which parts of the pagination to display, ensuring that users always have access to relevant page links. This method enhances the scalability of the pagination component and improves user navigation.
  • 145-155: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [137-152]

The implementation of getUrlRange and getUrl for generating URLs within a specified range and constructing URLs based on page number is well-done. These methods provide the necessary flexibility for generating pagination links and ensure that the pagination component can adapt to various use cases. Pay attention to the TODO comments regarding parameter concatenation to ensure that all query parameters are correctly handled.

  • 183-230: The methods for generating different types of pagination link wrappers (GetActivePageWrapper, GetDisabledPageWrapper, GetAvailablePageWrapper) are well-implemented. They provide a clear and consistent way to render pagination links, enhancing the visual presentation and usability of the pagination component. Ensure that the HTML classes used align with the project's styling conventions.
resources/js/app.js (2)
  • 189-194: The workaround for the htmx issue by removing the disabled attribute from elements before history save is a clever temporary solution. However, it's important to track the progress of the htmx issue and remove this workaround once the issue is resolved to avoid potential side effects in the future.

Consider adding a comment with a link to the htmx issue tracker for easier tracking and future reference.

  • 268-270: The modifications to openDialog and closeDialog functions to use setTimeout for showing and closing dialogs with a delay improve the user experience by adding a smooth transition. However, ensure that this delay does not negatively impact the user's perception of the application's responsiveness. Testing with real users or gathering feedback could provide valuable insights.

Also applies to: 274-276

Comment on lines +165 to +187
document.body.addEventListener("htmx:swapError", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "An error occurred while processing your request.",
type: "is-danger",
});
});

document.body.addEventListener("htmx:targetError", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "An error occurred while processing your request.",
type: "is-danger",
});
});

document.body.addEventListener("htmx:timeout", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "The request timed out.",
type: "is-danger",
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of event listeners for htmx:swapError, htmx:targetError, and htmx:timeout events is a good practice for handling errors and timeouts gracefully. However, consider abstracting the error handling logic into a separate function to avoid code duplication and improve maintainability.

- document.body.addEventListener("htmx:swapError", function (evt) {
-   console.error(evt);
-   bulmaToast.toast({
-     message: "An error occurred while processing your request.",
-     type: "is-danger",
-   });
- });
- document.body.addEventListener("htmx:targetError", function (evt) {
-   console.error(evt);
-   bulmaToast.toast({
-     message: "An error occurred while processing your request.",
-     type: "is-danger",
-   });
- });
- document.body.addEventListener("htmx:timeout", function (evt) {
-   console.error(evt);
-   bulmaToast.toast({
-     message: "The request timed out.",
-     type: "is-danger",
-   });
- });
+ function handleHtmxError(evt, message) {
+   console.error(evt);
+   bulmaToast.toast({
+     message: message,
+     type: "is-danger",
+   });
+ }
+ document.body.addEventListener("htmx:swapError", (evt) => handleHtmxError(evt, "An error occurred while processing your request."));
+ document.body.addEventListener("htmx:targetError", (evt) => handleHtmxError(evt, "An error occurred while processing your request."));
+ document.body.addEventListener("htmx:timeout", (evt) => handleHtmxError(evt, "The request timed out."));

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
document.body.addEventListener("htmx:swapError", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "An error occurred while processing your request.",
type: "is-danger",
});
});
document.body.addEventListener("htmx:targetError", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "An error occurred while processing your request.",
type: "is-danger",
});
});
document.body.addEventListener("htmx:timeout", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "The request timed out.",
type: "is-danger",
});
});
function handleHtmxError(evt, message) {
console.error(evt);
bulmaToast.toast({
message: message,
type: "is-danger",
});
}
document.body.addEventListener("htmx:swapError", (evt) => handleHtmxError(evt, "An error occurred while processing your request."));
document.body.addEventListener("htmx:targetError", (evt) => handleHtmxError(evt, "An error occurred while processing your request."));
document.body.addEventListener("htmx:timeout", (evt) => handleHtmxError(evt, "The request timed out."));

Comment on lines 162 to 198
initCloner();
});

document.body.addEventListener("htmx:swapError", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "An error occurred while processing your request.",
type: "is-danger",
});
});

document.body.addEventListener("htmx:targetError", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "An error occurred while processing your request.",
type: "is-danger",
});
});

document.body.addEventListener("htmx:timeout", function (evt) {
console.error(evt);
bulmaToast.toast({
message: "The request timed out.",
type: "is-danger",
});
});

//! This is a workaround, has to be removed when htmx fixes the issue
addEventListener("htmx:beforeHistorySave", () => {
document
.querySelectorAll(":disabled")
.forEach((el) => (el.disabled = false));
});

document.addEventListener("trix-before-initialize", () => {
Trix.config.toolbar.getDefaultHTML = () => {
return `
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [240-240]

The use of insertAdjacentHTML in the initCloner function poses a potential security risk if the template variable contains user-controlled data, leading to Cross-Site Scripting (XSS) vulnerabilities. Ensure that the data used in template is properly sanitized or consider using safer alternatives to dynamically set HTML content.

- target.insertAdjacentHTML("beforeend", template);
+ // Ensure `template` is sanitized if it contains user-controlled data

Consider using a sanitization library like DOMPurify to sanitize HTML content before inserting it into the DOM.

},
closeDialog() {
wga.els.dialog.close();
wga.els.dialog.innerHTML = wga.els.dialogDefaultContent;
setTimeout(() => {
wga.els.dialog.innerHTML = wga.els.dialogDefaultContent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direct manipulation of innerHTML can lead to security vulnerabilities, such as Cross-Site Scripting (XSS), if user-controlled data is involved. Ensure that the content assigned to innerHTML is properly sanitized to prevent potential security risks.

- wga.els.dialog.innerHTML = wga.els.dialogDefaultContent;
+ // Ensure `wga.els.dialogDefaultContent` is sanitized if it contains user-controlled data

Consider using textContent for assigning non-HTML content or a sanitization library for HTML content.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
wga.els.dialog.innerHTML = wga.els.dialogDefaultContent;
// Ensure `wga.els.dialogDefaultContent` is sanitized if it contains user-controlled data

@@ -70,7 +70,7 @@ func registerMusicHandlers(app *pocketbase.PocketBase) {
isHtmx := utils.IsHtmxRequest(c)
cacheKey := "musics"

setUrl(c, "")
// setUrl(c, "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commenting out the setUrl(c, "") function call within registerMusicHandlers alters the behavior related to setting a URL in the context of music handlers. If this change is intentional and the functionality provided by setUrl is no longer required, consider removing the line entirely to avoid leaving commented-out code in the codebase, which can lead to confusion and clutter.

- // setUrl(c, "")

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// setUrl(c, "")

Comment on lines 87 to 116

const onEachSide int = 3

// FirstPart returns the first part of the pagination.
func (p *Pagination) FirstPart() []string {
return p.firstPart
}

// MiddlePart returns the middle part of the pagination.
func (p *Pagination) MiddlePart() []string {
return p.middlePart
}

// LastPart returns the last part of the pagination.
func (p *Pagination) LastPart() []string {
return p.lastPart
}

// generate generates the pagination links based on the current state of the Pagination object.
// It determines the range of pages to display based on the total number of pages and the current page.
// The generated links are stored in the Pagination object's firstPart, middlePart, and lastPart fields.
// If there are no pages to display, the method returns early.
// If the total number of pages is less than (onEachSide*2 + 6), the method generates links for all pages.
// Otherwise, the method generates links based on the current page's position relative to the window size.
// If the current page is within the first window, links are generated for the first window + 2 pages and the last 2 pages.
// If the current page is within the last window, links are generated for the first 2 pages and the last window + 2 pages.
// Otherwise, links are generated for the first 2 pages, the pages within the current page's window, and the last 2 pages.
func (p *Pagination) generate() {
if !p.HasPages() {
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [246-248]

The Render method effectively generates the HTML for the pagination component. However, be cautious with the use of template.HTML(html.UnescapeString(out.String())) as it could potentially introduce XSS vulnerabilities if user-controlled data can reach the template. Ensure that all data rendered through this method is properly sanitized or comes from trusted sources.

- return template.HTML(html.UnescapeString(out.String()))
+ // Ensure data is sanitized or from trusted sources before using template.HTML

Comment on lines +3 to +81
templ TopNav() {
<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" id="nav-logo" href="/" hx-get="/">
<img
src="/assets/images/logo.png"
loading="lazy"
width="318"
height="45"
alt="Web Gallery of Art"
title="Go to Home"
/>
</a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="top-navbar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="top-navbar" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/" hx-get="/">
Home
</a>
<a class="navbar-item" href="/artists" hx-get="/artists">
Artists
</a>
<a class="navbar-item" href="/artworks" hx-get="/artworks">
Artworks
</a>
<a class="navbar-item" href="/guestbook" hx-get="/guestbook" hx-trigger="guestbook-updated from:body">
Guestbook
</a>
<!--
<a class="navbar-item">
Tours
</a>
<a class="navbar-item is-hidden-touch" hx-on="click: ToggleDualMode()">
Dual mode
</a>
-->
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
More
</a>
<div class="navbar-dropdown">
<a
class="navbar-item"
href="/pages/privacy-policy"
hx-get="/pages/privacy-policy"
>
Privacy Policy
</a>
<!--
<a class="navbar-item">
Glossary
</a>
<a class="navbar-item">
Music
</a>
<a class="navbar-item">
Database
</a>
<a class="navbar-item">
Sources
</a>
<a class="navbar-item">
About Us
</a>
<a class="navbar-item">
Contact Us
</a>
-->
</div>
</div>
</div>
</div>
</nav>
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TopNav templated function is well-structured and makes effective use of HTMX attributes for dynamic content loading. However, ensure that the commented-out sections (lines 36-43 and 56-75) are intentionally left for future use or reference. If they are no longer needed, consider removing them to clean up the code.

- <!-- 
-            <a class="navbar-item">
-                Tours
-            </a>
-            <a class="navbar-item is-hidden-touch" hx-on="click: ToggleDualMode()">
-                Dual mode
-            </a>
-        -->
-                   <!--
-                    <a class="navbar-item">
-                        Glossary
-                    </a>
-                    <a class="navbar-item">
-                        Music
-                    </a>
-                    <a class="navbar-item">
-                        Database
-                    </a>
-                    <a class="navbar-item">
-                        Sources
-                    </a>
-                    <a class="navbar-item">
-                        About Us
-                    </a>
-                    <a class="navbar-item">
-                        Contact Us
-                    </a>
-                    -->

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
templ TopNav() {
<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" id="nav-logo" href="/" hx-get="/">
<img
src="/assets/images/logo.png"
loading="lazy"
width="318"
height="45"
alt="Web Gallery of Art"
title="Go to Home"
/>
</a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="top-navbar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="top-navbar" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/" hx-get="/">
Home
</a>
<a class="navbar-item" href="/artists" hx-get="/artists">
Artists
</a>
<a class="navbar-item" href="/artworks" hx-get="/artworks">
Artworks
</a>
<a class="navbar-item" href="/guestbook" hx-get="/guestbook" hx-trigger="guestbook-updated from:body">
Guestbook
</a>
<!--
<a class="navbar-item">
Tours
</a>
<a class="navbar-item is-hidden-touch" hx-on="click: ToggleDualMode()">
Dual mode
</a>
-->
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
More
</a>
<div class="navbar-dropdown">
<a
class="navbar-item"
href="/pages/privacy-policy"
hx-get="/pages/privacy-policy"
>
Privacy Policy
</a>
<!--
<a class="navbar-item">
Glossary
</a>
<a class="navbar-item">
Music
</a>
<a class="navbar-item">
Database
</a>
<a class="navbar-item">
Sources
</a>
<a class="navbar-item">
About Us
</a>
<a class="navbar-item">
Contact Us
</a>
-->
</div>
</div>
</div>
</div>
</nav>
}
templ TopNav() {
<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" id="nav-logo" href="/" hx-get="/">
<img
src="/assets/images/logo.png"
loading="lazy"
width="318"
height="45"
alt="Web Gallery of Art"
title="Go to Home"
/>
</a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="top-navbar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="top-navbar" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/" hx-get="/">
Home
</a>
<a class="navbar-item" href="/artists" hx-get="/artists">
Artists
</a>
<a class="navbar-item" href="/artworks" hx-get="/artworks">
Artworks
</a>
<a class="navbar-item" href="/guestbook" hx-get="/guestbook" hx-trigger="guestbook-updated from:body">
Guestbook
</a>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
More
</a>
<div class="navbar-dropdown">
<a
class="navbar-item"
href="/pages/privacy-policy"
hx-get="/pages/privacy-policy"
>
Privacy Policy
</a>
</div>
</div>
</div>
</div>
</nav>
}

Comment on lines +1 to +6
// .customBody {
// display: flex;
// flex-direction: column;
// justify-content: space-between;
// height: 100%;
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The styling for the .customBody class has been commented out. Consider the following actions:

  • If this class is no longer needed, it might be cleaner to remove the commented code entirely to keep the stylesheet maintainable.
  • If this is a temporary change, please add a comment explaining the reason for commenting it out and the conditions under which it should be re-enabled.

Comment on lines +21 to +25
// ExtractIdFromString extracts the ID from a string.
func ExtractIdFromString(s string) string {
parts := strings.Split(s, "-")
return parts[len(parts)-1]
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ExtractIdFromString function assumes the ID is always the last part of the string, which is a reasonable assumption given the context. However, consider the following improvements:

  • Error Handling: Add a check to ensure that the parts slice is not empty after the split operation to avoid potential runtime panics.
  • Documentation: It would be beneficial to document the assumption that the ID is expected to be the last part of the string for clarity and future maintenance.

Comment on lines +10 to +18
func SetHxTrigger(c echo.Context, data map[string]any) {
hd, err := json.Marshal(data)

if err != nil {
log.Fatalln(err)
}

c.Response().Header().Set("HX-Trigger", string(hd))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider replacing log.Fatalln(err) with structured logging in the SetHxTrigger function to avoid terminating the application on error. Structured logging would allow for better error handling and logging practices within a web application.

Comment on lines +24 to +33
func GuestbookQuery(dao *daos.Dao) *dbx.SelectQuery {
return dao.ModelQuery(&GuestbookEntry{})
}

func FindEntriesForYear(dao *daos.Dao, year string) ([]*GuestbookEntry, error) {
var entries []*GuestbookEntry

err := GuestbookQuery(dao).AndWhere(dbx.Like("created", year)).OrderBy("created DESC").All(&entries)

return entries, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of GuestbookQuery and FindEntriesForYear functions for querying guestbook entries is well-executed. To further enhance security, consider validating the year parameter in the FindEntriesForYear function to ensure it meets expected formats and values, thus preventing potential SQL injection or other security issues.

@blackfyre blackfyre mentioned this pull request Mar 11, 2024
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

Successfully merging this pull request may close these issues.

None yet

1 participant