Commit Graph

35 Commits

Author SHA1 Message Date
jordi fita mas 6ef551a846 Move top-level navigation bar inside body’s header
This is mostly to save on vertical space, since the header was almost
useless but took a lot of screen real estate.
2024-09-04 12:38:37 +02:00
jordi fita mas f95936c523 Split the tax details “mega dialog” into separate pages
I needed to place the payment accounts section somewhere, and the most
logical place seemed to be that dialog, where users can set up company
parameters.

However, that dialog was already saturated with related, but ultimately
independent forms, and adding the account section would make things
even worse, specially given that we need to be able to edit those
accounts in a separate page.

We agreed to separate that dialog into tabs, which means separate pages.
When i had everything in a separated page, then i did not know how to
actually share the code for the tabs, and decided that, for now, these
“tabs” would be items from the profile menu.  Same function, different
presentation.
2024-08-14 04:08:13 +02:00
jordi fita mas ad5bc271b6 Add the payments section
This actually should be the “payments and receivables” section, however
this is quite a mouthful; a “receivable” is a payment made **to** you,
therefore “payments” is ok.

In fact, there is still no receivables in there, as they should be in
a separate relation, to constraint them to invoices instead of expenses.
It will be done in a separate commit.

Since this section will be, in a sense, sort of simplified accounting,
i needed to introduce the “payment account” concept.  There is no way,
yet, for users to add them, because i have to revamp the “tax details”
section, but this commit started to grow too big already.

The same reasoning for the attachment payment slips as PDF to payment:
something i have to add, but not yet in this commit.
2024-08-10 04:34:07 +02:00
jordi fita mas b4b049aab9 Include numerusVersion to CSS and JavaScript’s URIs 2024-01-19 23:09:25 +01:00
jordi fita mas f15294c042 Use <small> to mark the application’s version up
I mistakenly thought that <small> was de inverse of the deprecated <big>
element, but apparently it is for small-print text and such, thus suited
for this case.
2024-01-19 22:59:06 +01:00
jordi fita mas 18b38f593c Add the application’s version on the footer
This is mostly to reassure people that we are running the same version
as published on numerus.cat.  Or at least, try.

Go 1.18 adds the info from git if the package is build from a git
repository, but this is not the case in OBS, so i instead relay on a
constant for the version number.  This constant is “updated” by Debian’s
rules, mostly due to the discussion in [0].

[0]: https://github.com/golang/go/issues/22706
2024-01-19 20:03:04 +01:00
jordi fita mas 31a655ae7f Add aria-current attribute to links in the top menu
This is mainly to be able to stylize them using CSS; the current style
i set i just a placeholder to check that it works as expected.

Most of these links needs to check for the URI’s prefix, because they
are links to a whole section, but the first link must check for the
exact match, otherwise it would match every other URI, as all of them
start with /company/{uuid}.

The server does not return the markup for the top navigation when usin
HTMx, though, hence i have to change the current class using JavaScript.

I am not sure if the correct value for aria-current is “page” when the
link is not for the actual page the user is currently in, like when is
in the new quote page, but it seems to be the most appropriate value
from the enumeration given in the specifications, except, perhaps, for
the “location” value, but i was unable to find any example of that value
anywhere.

Part of #89.
2023-11-13 14:42:27 +01:00
jordi fita mas e322ddd168 Add custom elements polyfill
I use customized built-in components, extended from any HTML elements
(e.g., HTMLDivElement), for product search, multiselect, and tags input
fields.  The idea is that people that without JavaScript could still use
the regular, non-customized, inputs.

It turns out, this does not work so well: the CSS assumes that
JavaScript is enabled, and web components supported by the browser. If
one of these fails, then the controls are unusable—the multiselect is
too short, and the tags field accepts invalid characters that the
backend does not validate until it fails with a database error.

We discovered this because Apple does not implement customized built-in
components[0], hence it does not use my JavaScript code and forms,
the expenses forms in particular, are almost useless.

The way to fix this is to replace the regular inputs with autonomous
web components, extended from HTMLElement, using JavaScript, because
it would only do so with JavaScript enabled, and the CSS style would
only apply to these components, not the regular input fields.

However, currently i do not have time to do the proper fix, and have
to use a polyfill for Safari to support customized built-in components.
Shame.

[0]: https://lists.w3.org/Archives/Public/public-webapps/2013OctDec/0801.html
2023-11-11 03:32:03 +01:00
jordi fita mas 998159d1d7 Add option to switch to another company
This is for users that belong to more than one company.  It is just a
page with links to the home of each company that the user belongs to.

Had to add a second company to the demo data to test it properly, even
though i already have unit tests for multicompany, but, you know….
2023-11-06 13:52:34 +01:00
jordi fita mas ae1e294144 Fix body class to show the filters without JavaScript
This class must match the one set by the “Filter” button so that when
there is no JavaScript filters forms are always visible.
2023-07-14 10:25:39 +02:00
jordi fita mas 58dd69773a Add aria-label to <summary> without text content
Using Orca or similar accessibility tools, it was not possible to
understand what these “menus” were intended for because they had only
icons without any alternative text, thus nothing to speak aloud with.
2023-07-06 11:49:36 +02:00
jordi fita mas eb845edf0a Change menu’s and profile icon
Eventually, we will allow people to upload their own profile images,
but until then we’ll use a “generic” profile icon instead of the closed
icon, that means nothing to users.

We wanted to have the same icon for that menu than for the Account item,
but the one we used until now did not look inside the round button for
the menu, thus we changed the two.

Related to #55.
2023-07-02 19:49:03 +02:00
jordi fita mas 9931796744 Add HTTP controller and view to add quotes
It still does not support quotes without contact or payment.
2023-06-07 16:35:31 +02:00
jordi fita mas 992bbf32a9 Toggle filters forms
I tried this already when i started adding filters, but i tried to use
AlpineJS for that, and could not because it would reset the context each
time i submitted the filters, due to HTMx replacing the whole content.

I realized that the only thing i need is some “flag” to show and hide
the form with CSS.  I do not even need AlpineJS for that, but i used it
anyway because then i can use the x-cloak thing to hidde the toggle
button for users with JavaScript disabled.

Similarly, the body by default has that “flag” set in the markup, and is
removed when AlpineJS is initialized, thus if JavaScript is disabled the
filters form is shown nevertheless.
2023-05-24 12:13:09 +02:00
jordi fita mas 55d650bd62 Add expenses’ index and add form 2023-05-03 12:46:25 +02:00
jordi fita mas 19bcfc29e8 Update HTMx version to 1.9.2
I was hit with a couple of bugs: hx-on not properly de-initializing,
with a workaround in 43fffb68 and properly fixed with version 1.9.2;
and elements with naked hx-trigger did not work with hx-boost, as i do
for the tag inline form, fixed in 1.9.1.

The other bug fixed in 1.9.1, play well with other libraries that also
use the window.onpopstate, did not affect me, i believe.
2023-04-29 16:20:13 +02:00
jordi fita mas b10f0dcb3f Update HTMx to version 1.9.0
I mainly did it for the new hx-on attribute, to click the update
button on recompute, but it does not seem to work as i think it does.
Anyway, there are some fixed bugs.

From the release announcement[0]:

## New Features

  * Support for view transitions, based on the experimental View
    Transitions API currently available in Chrome 111+ and coming to
    other browsers soon.
  * Support for “naked” hx-trigger attributes, where an hx-trigger is
    present on an element that does not have an hx-get, etc. defined on
    it. Instead, it will trigger the new htmx:triggered event, which
    can be responded to via your preferred scripting solution.
  * Support for generalized inline event handling via the new hx-on
    attribute, which addresses the shortcoming of limited onevent
    properties attributes in HTML.

## Improvements & Bug fixes

  * A memory leak fix by @croxton

[0]: https://htmx.org/posts/2023-04-11-htmx-1-9-0-is-released/
2023-04-26 14:30:40 +02:00
jordi fita mas 7e8ec539ff Add a SnackBar to show HTMx errors
We do not have any design yet for errors and other notifications, so i
followed material design, for now, since we already kind of use their
input fields design.

This time i decided to use AlpineJS because there is not that much HTML
code, and the transitioning is way easier to do in AlpineJS than it
would be with plain JavaScript—not to mention the bugs i would
introduce.
2023-03-25 01:56:26 +01:00
jordi fita mas 41ce5af2ed Boost the main navigation links with HTMx
I am not sure if, at the end, all pages that now use
mustRenderAppTemplate will be replaced with mustRenderMainTemplate,
but for now i keep them separate to know which routes are already
“boosted”.
2023-03-23 10:55:02 +01:00
jordi fita mas b1e3afc48b Show the tax details form in a dialog using HTMx 2023-03-21 11:58:54 +01:00
jordi fita mas 9e757cb9f4 Show the profile form in a dialog using HTMx
Had to split the actual page content and the breadcrumbs because they
do not belong in a dialog.  However, i had to change all templates to
do that.
2023-03-20 13:09:52 +01:00
jordi fita mas 2dde25c862 Reimplement the multiselect as a custom element
What i really set off on was to refactor the multiselect’s x-data
context to a separate JavaScript file.

I did not see the need at first, thinking that it would not matter
because it was used only in a template and i was not duplicating the
code in my files.  However, i then realized that having the context
in the template means the visitor has to download it each and every time
it accesses a form with a multiselect, even if nothing changed, and,
worse, it would download it multiple times if there were many
multiselect controls.

It makes more sense to put all that into a file that the browser would
only download and parse once, if the proper caching is set.

Once i realized that, it was a shame that AlpineJS has no way to do
the same for the HTML structure[0], for the exact same reasons: not
wanting to download many times the same extra <template> and other
markup required to build the control for JavaScript users.  And then i
remembered that this is supposed to be custom element’s main selling
point.

At first i tried to create a shadow DOW to replace the <select> with
the same <div> and <ul> that i used with Alpine, but it turns out that
<select> is not one of the allowed elements that can have a shadow root
attached[0].

Therefore, i changed the custom element to extend the <div> for the
<select> and <label> instead—the same element that had the x-init
context—, but i would have to define or include all the styles inside
the shadow DOM, and bring the lang attribute, for it to look like it
did before.   Out with the shadow DOM, and modify the <div>’s contents
instead.

At this point the code was so far removed from the declarative way that
AlpineJS promotes that i did not see much value on using it, except for
its reactivity.   But, given that this is such a small component, at the
end decided to write it all in plain JavaScript.

It is more code, at least looking only at the code i had to write, but
i love how i only have to add an is="numerus-multiselect" attribute to
HTML for it to work.

[0]: https://github.com/alpinejs/alpine/discussions/1205
[1]: https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow
2023-03-17 14:55:12 +01:00
jordi fita mas f93d557aa9 Move the multiselect “component” to the select-field template
I had in the product edit page only because it was easier to test there
while i was developing it, but it is something that should be done for
all select[multiple], of course.

I removed the whole x-cloak thing because i am not sure what would
happen if i do something wrong and Alpine can not initialize the
multiselect; probably show nothing to the user.  Now it shows the
native select a fraction of a second, but if i fuck it up at least the
user can still use the app.
2023-03-15 11:44:18 +01:00
jordi fita mas 5702f0d198 Start “improving” the user interface with AlpineJS: tax selector
It is a shitty component, but i do not have more time today to do it
better.
2023-03-14 18:07:38 +01:00
jordi fita mas f3b841473f Add the context menu with the duplicate option
As per the design document.
2023-03-08 11:54:06 +01:00
jordi fita mas 039bf3abbd Add the “menu” to change invoice statuses 2023-03-07 11:52:09 +01:00
jordi fita mas 5c15b9de20 Add the bare-bones form for invoices 2023-02-11 22:16:48 +01:00
jordi fita mas e9cc331ee0 Add products section
There is still some issues with the price field, because for now it is
in cents, but do not have time now to fix that.
2023-02-04 11:32:39 +01:00
jordi fita mas 917db31227 Add cross-request forgery detection
I use the ten first digits of the cookie’s hash, that i believe it is
not a problem, has the advantage of not expiring until the user logs
out, and using a per user session token is explicitly allowed by
OWASP[0].

[0]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern
2023-02-02 11:39:34 +01:00
jordi fita mas 75fd12bf1c Rename Customer to Contact
That section is intended for both customers and suppliers, collectively
called “contacts”.
2023-02-01 10:14:26 +01:00
jordi fita mas e0abf98bb1 Add custom function to get the current locale from templates
This is just to set the correct `lang` attribute on the HTML, so that
text readers can do its job and the `(optional)` suffix of labels gets
the correct ”translation”.
2023-01-31 15:45:51 +01:00
jordi fita mas 89256d5b4c Add nav link to dashboard 2023-01-31 13:29:56 +01:00
jordi fita mas 3117c9a268 Rename #profilemenu to #profile-menu, for consistency 2023-01-31 13:25:57 +01:00
jordi fita mas 9aee33511a Move page titles to their respective templates
I have been thinking about that, and it does not make that much sense to
have the titles in the Go source anymore: most of them are static text
that i have to remember to set in the controller each time, and when
the time come i have to face a dynamic title i am sure i will manage
with only the template capabilities—worst comes worst, i can always
define a function.

On the other hand, there is no way i can define a template without its
title and i know that everytime that template is used, no matter what
controller rendered it, it will always have that title.
2023-01-31 13:07:17 +01:00
jordi fita mas 1a7b9f6bdd Rename extension of templates to .gohtml
Apparently, there are tools that only know how to use that extensions
when referring to Go templates.
2023-01-30 16:48:21 +01:00