The hour headers indicate the time on the left line of the cell, this
makes them confusing to read. Shift the displayed hour to be in the
middle of the left line of the cell so that it is clear which line is
the start of which hour.
Start component names with the kind of element it creates on the page
(button, input, table, card, etc), then follow it with an hierarchy like
set of parts describing what part of the system it operates on.
This makes related components stick together in the directory listing of
components and auto-complete work better.
Instead of constructing a new DateTime object and seeing if it
succeeded, validate the client's timezone selection using the
Info.normalizeZone utility function. This prevents throwing an
unexpected error creating the DateTime object after the change
in e100555 to throw on invalid dates.
Use the ClientSchedule data structure for deserialising and tracking
edit state on the client instead of trying to directly deal with the
ApiSchedule type which is not build for ease of edits or rendering.
Implement tracking of time slots along with editing and restoration of
singularly edited time slots. This provides a simpler interface to work
with when rendering tables of time slots that can be edited than
directly manipulating events and shifts containing an array of slots.
To determine if the entity received from the server is the same as the
entity the client has the equals method is use. To avoid problems with
clients that have incorrect clocks the timestamp is overriden with the
server's time when the entities are saved on the server.
This means that the entities received back from the server when the
client saves will have different timestamps than what the client set.
Ignore the updatedAt timestamp when comparing entities for equality so
that the update logic correctly replaces entities that only differ by
the update timestamp.
If the event/shift that a location/role was referencing had been marked
for deletion the sanity check would incorrectly refuse to delete the
event/role. Fix by ignoring deleted events/shifts.
Add utility methods to more easily edit the fields of a single entity in
the schedule, along with a modification flag and is modified utility to
check for changes having been made.
The Vue Ref system and assiated proxies does not work with the native
EcmaScript private fields, replace them with the TypeScript access
modifiers which are regular fields under the hood.
Write the logic of keeping track of location modifications and applying
updates from the server into the ClientSchedule class. This should
serve as the foundation for replacing the prototype in-component update
logic which have turned into an unmaintainable spagetti.
When the object passed to defineNuxtConfig contains logic for enable
devtools option the Nuxtr plugin annoyingly shows an endlessly spinning
orb on the statusline.
Rename and refactor the types passed over the API to be based on an
entity that's either living or a tombstone. A living entity has a
deleted property that's either undefined or false, while a tombstone
has a deleted property set to true. All entities have a numeric id
and an updatedAt timestamp.
To sync entities, an array of replacements are passed around. Living
entities are replaced with tombstones when they're deleted. And
tombstones are replaced with living entities when restored.
Start the work of clearly distingushing client side types, server side
types and types shared over the API by renaming "AccountSession" and
"Session" names used on the server to "ServerSession".
The EventCard logic assume interestedIds not being present means the
account can't set events as interested. Fix this logic by checking if
the account is valid instead and always have interestedIds present on
the account store.
An account refers to the user the active session is logged in as. As
such it doesn't make sense outside of the /auth API paths that deals
with the current authenticated user. Move /api/account to
/api/auth/account to reflect this.
The authenticated middleware runs before the page content is rendered.
This means that it'll run before the session is fetched in app.vue on
pages that are protected by it on the first load. Fetch the session in
the middleware so that it doesn't act before the session is initalized.
Some functions in luxon default to the system's locale while other
functions default to "en-US". Explicitly set the locale everywhere
the luxon objects are created to avoid possible mismatches and
unexpected behaviour should the system's locale be different.
Replace the convoluted useAccountSession composable with a pinia store
that in addition allows for the consolidation of all session related
functions to grouped into one module.
If a session is refreshed when accessed through /api/auth/session during
a SSR then the Set-Cookie header was lost. Pass this along to the
client in this case to keep the session alive.
Putting secrets into environment variables is problematic due to them
being inherited by sub-processes, the ease as which these can be
leaked in logs, and the lack of support for loading secrets into
environment variables by systems such as systemd and docker.
Change the loading of secrets to be done by loading the content of a
file specified by an environment variable.
If a cookie is signed for one purpose, but the server also uses a
differently named signed cookie name for another purpose, then it's
possible for a malicious client to substitute the value of one signed
cookie with the value of another and have it pass the signature check.
Include the name of the cookie when computing the signature so that no
cookies signed for example for "user_session" can be used as a value for
a hypothetical "admin_session" cookie.
Use the useRuntimeConfig interface to read vapid details on the server
side. This is a more portale way to deal with loading data from the
environment in Nuxt.js.
The access permissions in Forgejo does not allow making packages
of a user private, the only options are hide the user completely
or make packages public. Do a workaround for this by pushing to
a private org.