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

[NO-ISSUE] feat: allow to query multiple users (freebusy) #26

Merged
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
805f4e2
refactor: adapt/update js client
GuillaumeDecMeetsMore Jul 11, 2024
941e65f
chore: update justfile
GuillaumeDecMeetsMore Jul 11, 2024
d2234a7
ci: adapt JS client lib's CI
GuillaumeDecMeetsMore Jul 11, 2024
446f130
test: start adding integration tests for our use cases
GuillaumeDecMeetsMore Jul 11, 2024
0a4f16c
ci: fix actions/setup-node usage for pnpm
GuillaumeDecMeetsMore Jul 11, 2024
1f0bd04
ci: update actions + install pnpm
GuillaumeDecMeetsMore Jul 11, 2024
b1df0f7
ci: remove cache on actions/setup-node as it's pretty fast
GuillaumeDecMeetsMore Jul 11, 2024
cee3d0f
Merge branch 'guillaume/ci/adapt-js-client-ci' into guillaume/test/ad…
GuillaumeDecMeetsMore Jul 11, 2024
a08ea16
Merge branch 'master' into guillaume/test/add-integration-test-for-ou…
GuillaumeDecMeetsMore Jul 16, 2024
8bac479
test: add more tests to integration tests
GuillaumeDecMeetsMore Jul 17, 2024
10439cb
Merge branch 'master' into guillaume/test/add-integration-test-for-ou…
GuillaumeDecMeetsMore Jul 18, 2024
6800201
refactor: rename file + adapt requirements' tests
GuillaumeDecMeetsMore Jul 22, 2024
e556c34
feat(users): allow to provide external userId (uuid)
GuillaumeDecMeetsMore Jul 18, 2024
a08d635
chore: fix formatting
GuillaumeDecMeetsMore Jul 18, 2024
4626cf1
test(requirements): provide userUuid
GuillaumeDecMeetsMore Jul 22, 2024
6d1bf21
feat(js lib): add format + lint biome + fixes
GuillaumeDecMeetsMore Jul 22, 2024
47d560a
refactor: convert unix timestamps to datetimes
GuillaumeDecMeetsMore Jul 24, 2024
1e9d5af
Merge branch 'master' into guillaume/feat/user-allow-to-provide-exter…
GuillaumeDecMeetsMore Jul 25, 2024
0e37677
Merge branch 'guillaume/feat/user-allow-to-provide-external-user-uuid…
GuillaumeDecMeetsMore Jul 25, 2024
a56b001
Merge branch 'guillaume/feat/add-format-lint-via-biome' into guillaum…
GuillaumeDecMeetsMore Jul 25, 2024
515f73e
Merge branch 'master' into guillaume/refactor/convert-unix-timestamps…
GuillaumeDecMeetsMore Jul 25, 2024
8d0f7bd
fix: format & lint
GuillaumeDecMeetsMore Jul 25, 2024
dc66f27
Merge branch 'master' into guillaume/refactor/convert-unix-timestamps…
GuillaumeDecMeetsMore Jul 25, 2024
dc6757e
Merge branch 'master' into guillaume/refactor/convert-unix-timestamps…
GuillaumeDecMeetsMore Jul 26, 2024
f420558
fix: missing imports
GuillaumeDecMeetsMore Jul 26, 2024
11749f3
fix: format
GuillaumeDecMeetsMore Jul 26, 2024
57a181b
fix: make client lib return Dates
GuillaumeDecMeetsMore Jul 29, 2024
bd43e72
chore: add js docs to client lib
GuillaumeDecMeetsMore Jul 25, 2024
8f1bd7f
chore: add more JSDocs
GuillaumeDecMeetsMore Jul 25, 2024
ee5164a
feat: allow to query multiple calendars + allow to query on name + al…
GuillaumeDecMeetsMore Jul 29, 2024
c14dfc5
chore: remove debug logs
GuillaumeDecMeetsMore Jul 29, 2024
804da1c
feat: add query freebusy on multiple users + fix metadata
GuillaumeDecMeetsMore Jul 30, 2024
0f55a28
refactor: extract convertEventDates & convertInstanceDates
GuillaumeDecMeetsMore Jul 30, 2024
3861c55
chore: remove comment
GuillaumeDecMeetsMore Jul 30, 2024
72147a9
Merge branch 'guillaume/refactor/convert-unix-timestamps-to-datetimes…
GuillaumeDecMeetsMore Jul 30, 2024
9bdd463
Merge branch 'master' into guillaume/feat/add-js-docs-client-lib
GuillaumeDecMeetsMore Jul 30, 2024
5ff58a4
chore: add more comments
GuillaumeDecMeetsMore Jul 30, 2024
ba6229a
refactor: rework result of "freebusy of multiple users"
GuillaumeDecMeetsMore Jul 31, 2024
7f0b094
fix: client lib multiple freebusy
GuillaumeDecMeetsMore Jul 31, 2024
af390af
Merge branch 'guillaume/feat/add-js-docs-client-lib' into guillaume/f…
GuillaumeDecMeetsMore Jul 31, 2024
821a881
chore: remove duplicate requirements
GuillaumeDecMeetsMore Jul 31, 2024
1b8e859
Merge branch 'master' into guillaume/feat/allow-to-query-free-busy-mu…
GuillaumeDecMeetsMore Aug 5, 2024
9693b49
refactor: change multipleFreeBusy URL path
GuillaumeDecMeetsMore Aug 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export DATABASE_URL := "postgresql://postgres:postgres@localhost:45432/nettuscheduler"
export RUST_BACKTRACE := "1"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Print backtrace in case of error


# Install minimal tools
install_tools:
Expand Down
4 changes: 2 additions & 2 deletions scheduler/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion scheduler/clients/javascript/lib/accountClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type CreateAccountResponse = {
type CreateAccountRequest = {
/**
* Code to use for creating the account
* This code is unique on the backend and is required for "admin" requests such as this one
* This code is unique on the backend and is required for "admin" requests such as this one
* If not provided at startup via "CREATE_ACCOUNT_SECRET_CODE" environment variable
* Then the backend will generate one for you and log it
* @example "jXtS54fVjZlvJsRA" (auto-generated)
Expand Down
2 changes: 1 addition & 1 deletion scheduler/clients/javascript/lib/calendarClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type {
OutlookCalendarAccessRole,
} from './domain/calendar'
import { type APIResponse, NettuBaseClient } from './baseClient'
import type { Metadata } from './domain/metadata'
import type {
CalendarEvent,
CalendarEventInstance,
Expand All @@ -15,6 +14,7 @@ import type {
} from './domain'
import type { Timespan } from './eventClient'
import { convertInstanceDates } from './helpers/datesConverters'
import { Metadata } from './domain/metadata'

/**
* Request for creating a calendar
Expand Down
2 changes: 1 addition & 1 deletion scheduler/clients/javascript/lib/domain/account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UUID } from "./utilities"
import { UUID } from './utilities'

/**
* Account domain model
Expand Down
2 changes: 1 addition & 1 deletion scheduler/clients/javascript/lib/domain/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface Calendar {
timezone: string
}
/**
* Possible metadata
* Possible metadata
*/
metadata: Metadata
}
Expand Down
2 changes: 1 addition & 1 deletion scheduler/clients/javascript/lib/domain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export {
} from './service'
export { Permissions } from './permissions'
export { User } from './user'
export { UUID} from './utilities'
export { UUID } from './utilities'
4 changes: 1 addition & 3 deletions scheduler/clients/javascript/lib/domain/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@


/**
* UUID type
* @format uuid (v4) - `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`
* @example "d3b3b3b3-3b3b-4b3b-b3b3-b3b3b3b3b3b3"
*/
export type UUID = string
export type UUID = string
86 changes: 77 additions & 9 deletions scheduler/clients/javascript/lib/userClient.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { CalendarEventInstance } from './domain/calendarEvent'
import { NettuBaseClient } from './baseClient'
import { APIResponse, NettuBaseClient } from './baseClient'
import type { Metadata } from './domain/metadata'
import type { User } from './domain/user'
import type { IntegrationProvider, UUID } from '.'
import { convertInstanceDates } from './helpers/datesConverters'

/**
* Request to get a user's freebusy
Expand All @@ -27,14 +28,34 @@ type GetUserFeebusyReq = {
calendarIds?: string[]
}

/**
* Request to get multiple users' freebusy status
*/
type GetMultipleUsersFeebusyReq = {
/**
* List of user ids to check for freebusy
*/
userIds: UUID[]
/**
* Start time of the period to check for freebusy
* @format Date in UTC

Choose a reason for hiding this comment

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

I assume you've thought of this so maybe just catch me up, but:

my expectation as a user of the client would be that I'd be able to query with timezone information, this seems like the main place someone would make a mistake there.

Is there a reason why this expects UTC?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I have started looking into a bit more in #28, following the article that Derek shared, but it's a bit more complex than expected (I need to invest more time).

Ideally, I would like (at least) the JS SDK, the Rust SDK and the API to accept any timezone.
The API could still only handle only UTC datetimes internally. In the PR above, I've tried to have timezones everywhere (so, never convert to UTC, but it became quite complex so I decided to focus on the other requirements as this one is not blocking per se

Choose a reason for hiding this comment

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

Good for me, we might need to revisit the API design later though.

The reason I ask is you're going to immediately have this problem I think since we're operating in Tokyo timezone.

*/
startTime: Date
/**
* End time of the period to check for freebusy
* @format Date in UTC
*/
endTime: Date
}

/**
* Response when getting a user's freebusy
*/
type GetUserFeebusyResponse = {
/**
* List of busy instances
* List of busy instances per user_id
*/
busy: CalendarEventInstance[]
[key: string]: CalendarEventInstance[]

Choose a reason for hiding this comment

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

[nit] Shouldn't this be key: UUID

Choose a reason for hiding this comment

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

@GuillaumeDecMeetsMore minor nit, otherwise LGTM.

}

/**
Expand Down Expand Up @@ -117,12 +138,59 @@ export class NettuUserClient extends NettuBaseClient {
return this.delete<UserResponse>(`/user/${userId}`)
}

public freebusy(userId: UUID, req: GetUserFeebusyReq) {
return this.get<GetUserFeebusyResponse>(`/user/${userId}/freebusy`, {
startTime: req.startTime.toISOString(),
endTime: req.endTime.toISOString(),
calendarIds: req.calendarIds,
})
public async freebusy(
userId: UUID,
req: GetUserFeebusyReq
): Promise<APIResponse<GetUserFeebusyResponse>> {
const res = await this.get<GetUserFeebusyResponse>(
`/user/${userId}/freebusy`,
{
startTime: req.startTime.toISOString(),
endTime: req.endTime.toISOString(),
calendarIds: req.calendarIds?.join(','),
}
)

if (!res.data) {
return res
}

return {
res: res.res,
status: res.status,
data: {
busy: res.data.busy.map(convertInstanceDates),
},
}
Comment on lines +158 to +164
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fix, it should retun Dates and not strings

}

public async freebusyMultipleUsers(
req: GetMultipleUsersFeebusyReq
): Promise<APIResponse<GetUserFeebusyResponse>> {
const res = await this.post<GetUserFeebusyResponse>(
'/user/multipleFreebusy',
GuillaumeDecMeetsMore marked this conversation as resolved.
Show resolved Hide resolved
{
userIds: req.userIds,
startTime: req.startTime.toISOString(),
endTime: req.endTime.toISOString(),
}
)

if (!res.data) {
return res
}

return {
res: res.res,
status: res.status,
data: Object.keys(res.data).reduce((acc, key) => {
if (!res?.data?.[key]) {
return acc
}
acc[key] = res.data[key].map(convertInstanceDates)
return acc
}, {} as GetUserFeebusyResponse),
}
}

public oauth(userId: UUID, code: string, provider: IntegrationProvider) {
Expand Down
Loading