These notes are now stale and reflect thoughts at a mid-way stage in updating to the revised version of book. So don't be mislead by detail. Retaining for troubleshooting purposes.
npm run dev
npm run build
Using vitest:
npm install -D vitest
npm install --save-dev @vue/test-utils
add to package.json scripts list:
"test:unit": "vitest run --environment jsdom"
Checking the typescript settings
the answer says update typescript, and node (both badly out of date, e.g. node was at 12, latest is 19.6.0)
And that fixed it.
Also install jsdom
npm install -D jsdom
npm install -D vitest-localstorage-mock
Edit vite.config.js as per install info at link
consider this
Or do this fix to use actual local storage.
if you get an error message about perf hooks, then ensure you are using the latest version of node (nvwm is recommended for managing node versions).
typical use case - prebooked session, and access for limited window.
How do we share that with a user? we can set sessionIDs and policies as URL params, e.g.
https://uoe.practable.io/book/?sid=some_session_id&pid=some_policy_id
- user cannot cancel sessionID bookings, because they might be shared in a group.
If that link is too clunky, we can always shorten it with a link shortener (e.g. using bitly or the university of edinburgh link shortener)
If we need to send multiples then we can do arrays .... need to check formatting. Some examples here and here.
but maybe ..
We can treat a one-off session as a user, if we book the session under a unique user name, e.g. a descriptive name including the date (soe-engdes1-23-feb-17-tues-1400-1500-spinner-00. Even though the system treats it as a user, we have the UI request this as a code to be typed in for a "session" and it gets all the bookings for that user as well. This user can be added to the localstorage to provide persistance if the machine is rebooted. Which identity does david use for the analytics?
We can have a single primary userID, to be used for analytics, and multiple "sessions". Users should be able to change their primary userID. The primary userID is what their bookings are made against.
All users are anonymous at present. There are persistent and epheremal user ids, so we can support staff pre-booking activities for students.
For example, hand out airport-style quick-reference codes which refer to a token containing a username and booking id code for a booking to borrow.
The booking is accessed as that user, but the persistent identity of the user remains intact for use with analytics.
Each instance has its own unique anonymous identity, generated by the book server.
You can change to another anonymous identity, e.g. to share the same account across multiple devices.
You can borrow a booking by entering a user-name and bookingID (can you do this in advance, or only at the time?)
Analytics server would still pick up the anonymous identity of the user
Allow users to change their user name, to transfer from another device. limit user names to the number of characters, letters and numbers that we expect from xid. show green or red depending on whether the format is met. run bad words filter Keep a history of user names so users can revert (e.g. if they make a mistake, and have bookings)
Allow users to put in an short code that retrieves user/booking combo from another server. An endpoint for this would be useful .... publish shortcodes on page so anyone can copy? put behind a button so shoulder surfing cannot be used to steal a booking?
Booking has to be set to shareable for this to work? I.e. students can protect their own bookings from being shared? Would need an endpoint for making the booking shareable or unsharable. What if it is made unsharable after being shared? The short code no longer works, and is not re-used... need to keep a list of stale short codes....
could use words for ease, but wordlists like '/usr/share/dict/words' have offensive words. scowl lists some words as offensive, but not nearly enough.
filtering with bad words list discussed here but this is incomplete.
EFF did this already although it still has some words I wouldn't want to see in a phrase given to students.
then
npm install -g vite
then npm run dev
<snip>
import { performance } from 'node:perf_hooks'
^
SyntaxError: Unexpected token {
<snip>
Looks like this perf hooks issue, solution proposed is
npm i --save-dev @types/node
and that fixed it.
Except that could not find global css or main.js
localhost/:8
GET http://localhost:3000/global.css net::ERR_ABORTED 404 (Not Found)
localhost/:10
GET http://localhost:3000/src/main.js net::ERR_ABORTED 404 (Not Found)
client.ts:16 [vite] connecting...
client.ts:53 [vite] connected.
oops ... main.js is now main.ts!
fix ... but then repeated reloads with errors, similar to this bad gateway for deps
<snip>
[vite] error while updating dependencies:
Error: ENOTEMPTY: directory not empty, rmdir '/home/tim/sources/bookjs/src/node_modules/.vite/deps'
<snip>
asdfasdf
rm -r
Also, env vars need changing to prefix VITE
To prevent accidentally leaking env variables to the client, only variables prefixed with VITE_ are exposed to your Vite-processed code. e.g. for the following env variables:
VITE_SOME_KEY=123
DB_PASSWORD=foobar
Only
VITE_SOME_KEYwill be exposed asimport.meta.env.VITE_SOME_KEYto your client source code, butDB_PASSWORDwill not.
changed all VUE_APP to VITE_APP, and now running fine locally on npm run dev with development env.vars pointing to the existing AWS server instantiation (for convenience in avoiding setting up local services).
Now try production build with base path and host on dev.practable.io/book ...
npm run build
Still got the base_path problem with css and js assets, being looked for at https://dev.practable.io/css/<name> and https://dev.practable.io/js/<name> so page is not loading, and can't check whether the routing etc is working yet.
base path for local dev server origin, base href
added base href, did not fix issue...
not sure about this router config as seems different, but apparently works
for all icons in project put this in css
.fa {
color : red;
}
stateDiagram-v2
[*] --> UserNameFromStorage
UserNameFromStorage --> LoginTokenFetch : OK
UserNameFromStorage --> UserNameFetch : Error
UserNameFetch --> UserNameAwaitResponse
UserNameAwaitResponse --> UserNameStore : OK
UserNameStore --> LoginTokenFetch
UserNameAwaitResponse --> UserNameWaitBackOff : Error
UserNameWaitBackOff --> UserNameFetch
LoginTokenFetch --> LoginTokenAwaitResponse
LoginTokenAwaitResponse --> StoreLoginToken : OK
LoginTokenAwaitResponse --> LoginTokenWaitBackOff : Error
LoginTokenWaitBackOff --> LoginTokenFetch
StoreLoginToken --> RefreshAwait
RefreshAwait --> LoginTokenFetch : RefreshRequested
RefreshAwait --> UserNameFromStorage : UserNameChanged
stateDiagram-v2
[*] --> RefreshLoginToken
GetGroups --> GetBookings
RefreshLoginToken --> GetGroups
GetBookings --> Wait
Wait --> RefreshLoginToken : RefreshRequested
Wait --> GetGroupDetails : GroupSelected
GetGroupDetails --> GetPolicies
GetPolicies --> Wait
Wait --> GetSlots : PolicySelected
GetSlots --> DisplaySuggestedBookingTimes
DisplaySuggestedBookingTimes --> Wait
Wait --> MakeBooking : TimeSelected
MakeBooking --> GetBookings : OK
Wait --> StartBooking : ClickOpen
StartBooking --> Wait
Wait --> CancelBooking : ClickCancel
CancelBooking --> GetBookings
stateDiagram-v2
[*] --> RefreshLoginToken
GetGroups --> Wait
RefreshLoginToken --> GetGroupsAndBookings
GetGroupsAndBookings --> Wait
GetBookings --> Wait
Wait --> RefreshLoginToken : RefreshRequested
Wait --> CheckGroupDetails : GroupSelected
CheckGroupDetails --> GetGroupDetails : Stale
CheckGroupDetails --> CheckSlotAvailabilities: Fresh
CheckSlotAvailabilities --> GetSlotAvailabilities : Stale
CheckSlotAvailabilities --> DisplaySuggestedBookingTimes : Fresh
GetGroupDetails --> GetPolicies
GetPolicies --> GetSlotAvailabilities
GetSlotAvailabilities--> CalculateSuggestedBookingTimes
CalculateSuggestedBookingTimes --> DisplaySuggestedBookingTimes
DisplaySuggestedBookingTimes --> Wait
Wait --> MakeBooking : TimeSelected
MakeBooking --> GetBookings : OK
Wait --> StartBooking : ClickOpen
StartBooking --> Wait
Wait --> CancelBooking : ClickCancel
CancelBooking --> GetBookings
Wait --> AddGroup
AddGroup --> GetGroups
Wait --> GetSlotAvailabilities : UserRequestedRefresh
stateDiagram-v2
[*] --> RefreshLoginToken
GetGroups --> Wait
RefreshLoginToken --> GetGroupsAndBookings
GetGroupsAndBookings --> Wait
GetBookings --> Wait
Wait --> RefreshLoginToken : ForceRefreshLogin
Wait --> GetBookings : ForceRefreshBookings
Wait --> CheckGroupDetails : GroupSelected
CheckGroupDetails --> GetGroupDetails : Stale
CheckGroupDetails --> CheckSlotAvailabilities: Fresh
CheckSlotAvailabilities --> GetSlotAvailabilities : Stale
CheckSlotAvailabilities --> Wait: Fresh
GetGroupDetails --> GetPolicies
GetPolicies --> GetSlotAvailabilities
GetSlotAvailabilities--> GetIndividualSlotAvailability
GetIndividualSlotAvailability --> CalculateSuggestedBookingTimes
CalculateSuggestedBookingTimes --> GetIndividualSlotAvailability : NextSlot
CalculateSuggestedBookingTimes --> Wait : Done
Wait --> MakeBooking : TimeSelected
MakeBooking --> GetBookings : OK
Wait --> StartBooking : ClickOpen
StartBooking --> Wait
Wait --> CancelBooking : ClickCancel
CancelBooking --> GetBookings
Wait --> AddGroup
AddGroup --> GetGroups
Wait --> GetGroupDetails : ForceRefreshGroupDetails
Wait --> GetIndividualSlotAvailability : ForceRefreshOneSlot
Wait --> GetSlotAvailabilities : ForceRefreshAll
RefreshMachine
stateDiagram-v2
[*] --> AwaitToken
AwaitToken --> Fetch : TokenRefreshed
Fetch --> Fresh : OK
Fetch --> AwaitToken : Unauthorised
Fetch --> Backoff : Error
Backoff --> Fetch : Timeout
Fresh --> Stale : Timeout
Fresh --> Fresh : Refresh (NOOP)
Stale --> Fetch : Refresh
KindRefreshMachine
stateDiagram-v2
[*] --> AwaitToken
AwaitToken --> Fetch : TokenRefreshed
Fetch --> Fresh : OK
Fetch --> AwaitToken : Unauthorised
Fetch --> Backoff : Error
Backoff --> Fetch : Timeout
Fresh --> Stale : Timeout
Fresh --> Fresh : KindRefresh (NOOP)
Stale --> Fetch : KindRefresh, ForceRefresh
Fresh --> Fetch : ForceRefresh
```