Skip to content

Commit

Permalink
fix: debug the ShareLinkResolver
Browse files Browse the repository at this point in the history
  • Loading branch information
czabaj committed Jul 25, 2023
1 parent 50a50a3 commit 75ae203
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 42 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"dependencies": {
"@nobleai/rescript-rxjs": "https://github.com/czabaj/rescript-rxjs#a85312969a9cddba8d4cc3cd11d9c947512f8a05",
"@nobleai/rescript-rxjs": "https://github.com/czabaj/rescript-rxjs#73a625653408bd262ac481847108ede30a99442e",
"@oddbird/popover-polyfill": "^0.2.2",
"@rescript/core": "^0.4.0",
"@rescript/react": "^0.11.0",
Expand Down
24 changes: 16 additions & 8 deletions src/backend/Db.res
Original file line number Diff line number Diff line change
Expand Up @@ -451,9 +451,7 @@ module Place = {
->Firebase.WriteBatch.set(
personDoc,
{
account: Js.Null.return(userId),
createdAt: now,
name: personName,
transactions: [],
},
{},
Expand Down Expand Up @@ -541,9 +539,7 @@ module Person = {
let now = Firebase.Timestamp.now()
let personDoc = Firebase.seedDoc(placePersonsCollection(firestore, placeId))
let newPerson: FirestoreModels.person = {
account: Null.null,
createdAt: now,
name: personName,
transactions: [],
}
let newPersonsAllRecord = {
Expand Down Expand Up @@ -630,7 +626,8 @@ module Person = {
module PersonsIndex = {
let allEntriesSortedRx = (firestore, ~placeId) => {
let personsIndexRef = personsIndexConverted(firestore, placeId)
Rxfire.docData(personsIndexRef)->Rxjs.pipe(
Rxfire.docData(personsIndexRef)->Rxjs.pipe2(
Rxjs.keepSome,
Rxjs.map((personsIndex: personsIndexConverted, _) => {
let personsAllEntries = personsIndex.all->Js.Dict.entries
personsAllEntries->Array.sort(((_, a), (_, b)) => {
Expand Down Expand Up @@ -658,6 +655,11 @@ module ShareLink = {
Firebase.doc(firestore, ~path=`shareLinks/${linkId}`)
}

let delete = (firestore, ~linkId) => {
let shareLinkDocument = document(firestore, linkId)
Firebase.deleteDoc(shareLinkDocument)
}

let upsert = async (firestore, ~placeId, ~personId, ~role) => {
if role === FirestoreModels.Owner {
Exn.raiseError("Changing owner is currently not supported")
Expand Down Expand Up @@ -695,10 +697,16 @@ module ShareLink = {
Exn.raiseError("Share link does not exist")
}
let {place, person, role} = shareLinkSnapshot.data(. {})
let placeIndexDocument = personsIndexDocument(firestore, place)
let placeIndexDocument = personsIndexConverted(firestore, place)
let placeIndex = (await transaction->Transaction.get(placeIndexDocument)).data(. {})
let personTuple = placeIndex.all->Js.Dict.get(person)->Option.getExn
let personRecord = personsAllTupleToRecord(. personTuple)
let userAlreadyInPlace =
placeIndex.all
->Dict.valuesToArray
->Array.some(p => p.userId->Null.mapWithDefault(false, id => id === userId))
if userAlreadyInPlace {
Exn.raiseError("User already in place")
}
let personRecord = placeIndex.all->Js.Dict.get(person)->Option.getExn
if personRecord.userId !== Null.null {
Exn.raiseError("Person already has a connected user account")
}
Expand Down
7 changes: 1 addition & 6 deletions src/backend/FirestoreModels.gen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,7 @@ export type keg = {
};

// tslint:disable-next-line:interface-over-type-literal
export type person = {
readonly account: (null | string);
readonly createdAt: Firebase_Timestamp_t;
readonly name: personName;
readonly transactions: financialTransaction[]
};
export type person = { readonly createdAt: Firebase_Timestamp_t; readonly transactions: financialTransaction[] };

// tslint:disable-next-line:interface-over-type-literal
export type role = $$role;
Expand Down
2 changes: 0 additions & 2 deletions src/backend/FirestoreModels.res
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ and keg = {
}
@genType
and person = {
account: Js.null<string>,
createdAt: Firebase.Timestamp.t,
name: personName,
transactions: array<financialTransaction>,
}

Expand Down
2 changes: 1 addition & 1 deletion src/backend/Rxfire.res
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ external doc: Firebase.documentReference<'a> => Rxjs.t<
external docData: (
Firebase.documentReference<'a>,
@as(json`{ "idField": "uid" }`) _,
) => Rxjs.t<Rxjs.foreign, Rxjs.void, 'a> = "docData"
) => Rxjs.t<Rxjs.foreign, Rxjs.void, option<'a>> = "docData"

@module("rxfire/firestore")
external snapToData: (Firebase.documentSnapshot<'a>, @as(json`{ "idField": "uid" }`) _) => 'a =
Expand Down
3 changes: 3 additions & 0 deletions src/pages/Place/Place.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
.list li > div:first-child {
margin-inline-end: auto;
}
.list li[aria-current="true"] > div:first-child {
font-weight: var(--font-weight-semibold);
}

.listEmpty {
padding-block: 0.5rem;
Expand Down
24 changes: 18 additions & 6 deletions src/pages/Place/Place.res
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module ActivePersonListItem = {
let make = (
~activeCheckbox: option<React.element>,
~consumptions: array<Db.userConsumption>,
~isCurrent,
~onAddConsumption,
~personName,
) => {
Expand Down Expand Up @@ -75,7 +76,7 @@ module ActivePersonListItem = {
None
}, [consumptionsStr])

<li ref={ReactDOM.Ref.domRef(listItemEl)}>
<li ariaCurrent={isCurrent ? #"true" : #"false"} ref={ReactDOM.Ref.domRef(listItemEl)}>
<div> {React.string(personName)} </div>
{switch activeCheckbox {
| Some(node) => node
Expand All @@ -101,10 +102,10 @@ type dialogState =

type userConsumption = {milliliters: int, timestamp: float}

let pageDataRx = (firestore, placeId) => {
let pageDataRx = (auth, firestore, placeId) => {
open Rxjs
let placeRef = Db.placeDocument(firestore, placeId)
let placeRx = Rxfire.docData(placeRef)
let placeRx = Rxfire.docData(placeRef)->pipe(keepSome)
let tapsWithKegsRx = placeRx->pipe2(
distinctUntilChanged((prev: FirestoreModels.place, curr) => prev.taps == curr.taps),
mergeMap((place: FirestoreModels.place) => {
Expand Down Expand Up @@ -196,21 +197,24 @@ let pageDataRx = (firestore, placeId) => {
(all, active, inactive)
}),
)
combineLatest5(
let currentUserRx = Rxfire.user(auth)->pipe(keepMap(Null.toOption))
combineLatest6(
placeRx,
personsAllRx,
tapsWithKegsRx,
unfinishedConsumptionsByUserRx,
recentConsumptionsByUserRx,
currentUserRx,
)
}

@react.component
let make = (~placeId) => {
let auth = Reactfire.useAuth()
let firestore = Reactfire.useFirestore()
let pageDataStatus = Reactfire.useObservable(
~observableId=`Page_Place_${placeId}`,
~source=pageDataRx(firestore, placeId),
~source=pageDataRx(auth, firestore, placeId),
)
let (dialogState, setDialog) = React.useState(() => Hidden)
let hideDialog = _ => setDialog(_ => Hidden)
Expand All @@ -224,6 +228,7 @@ let make = (~placeId) => {
tapsWithKegs,
unfinishedConsumptionsByUser,
recentConsumptionsByUser,
currentUser,
) =>
<FormattedCurrency.Provider value={place.currency}>
<div className={`${Styles.page.narrow} ${classes.root}`}>
Expand Down Expand Up @@ -264,6 +269,9 @@ let make = (~placeId) => {
/>
)}
consumptions={consumptions}
isCurrent={person.userId->Null.mapWithDefault(false, userId =>
userId === currentUser.uid
)}
key={personId}
onAddConsumption={() => {
setDialog(_ => AddConsumption({personId, person}))
Expand Down Expand Up @@ -315,7 +323,11 @@ let make = (~placeId) => {
->Array.map(inactivePerson => {
let (personId, person) = inactivePerson
let recentActivityDate = person.recentActivityAt->Firebase.Timestamp.toDate
<li key={personId}>
let isCurrent =
person.userId->Null.mapWithDefault(false, userId =>
userId === currentUser.uid
)
<li ariaCurrent={isCurrent ? #"true" : #"false"} key={personId}>
<div>
{React.string(`${person.name} `)}
<time dateTime={recentActivityDate->Js.Date.toISOString}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/PlacePersonsSetting/PlacePersonsSetting.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type dialogState =
let pageDataRx = (firestore, placeId) => {
open Rxjs
let placeRef = Db.placeDocument(firestore, placeId)
let placeRx = Rxfire.docData(placeRef)
let placeRx = Rxfire.docData(placeRef)->pipe(keepSome)
let allChargedKegsRx = Db.allChargedKegsRx(firestore, placeId)
let unfinishedConsumptionsByUserRx = allChargedKegsRx->pipe(
map((chargedKegs, _) => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/PlaceSetting/PlaceSetting.res
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
let pageDataRx = (firestore, placeId) => {
open Rxjs
let placeRef = Db.placeDocument(firestore, placeId)
let placeRx = Rxfire.docData(placeRef)
let placeRx = Rxfire.docData(placeRef)->pipe(keepSome)
let personsAllRx = Db.PersonsIndex.allEntriesSortedRx(firestore, ~placeId)
let chargedKegsRx = Db.allChargedKegsRx(firestore, placeId)
combineLatest3(placeRx, personsAllRx, chargedKegsRx)
Expand Down
54 changes: 40 additions & 14 deletions src/pages/ShareLinkResolver/ShareLinkResolver.res
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,62 @@ module Pure = {
}
}

let pageDataRx = (firestore, ~linkId) => {
let redirectToPlace = placeId => {
RescriptReactRouter.replace(`/misto/${placeId}`)
}

let pageDataRx = (auth, firestore, ~linkId) => {
open Rxjs
Rxfire.docData(Db.ShareLink.document(firestore, linkId))->pipe(
mergeMap((shareLink: FirestoreModels.shareLink) => {
Rxfire.docData(Db.placeDocument(firestore, shareLink.place))->pipe(
map((place, _) => (shareLink, place)),
)
let currentUserRx = Rxfire.user(auth)->pipe(keepMap(Null.toOption))
let shareLinkRx = Rxfire.docData(Db.ShareLink.document(firestore, linkId))
let shareLinkPlaceRx = shareLinkRx->pipe(
switchMap((maybeShareLink: option<FirestoreModels.shareLink>) => {
switch maybeShareLink {
| None => return(None)
| Some(shareLink) => Rxfire.docData(Db.placeDocument(firestore, shareLink.place))
}
}),
)
combineLatest2(currentUserRx, shareLinkPlaceRx)
->pipe2(
first(),
tap(((currentUser, maybeShareLinkPlace): (Firebase.User.t, option<FirestoreModels.place>)) => {
switch maybeShareLinkPlace {
| None => ()
| Some(shareLinkPlace) => {
let userAlreadyInPlace = shareLinkPlace.users->Dict.get(currentUser.uid)->Option.isSome
if userAlreadyInPlace {
Db.ShareLink.delete(firestore, ~linkId)->ignore
redirectToPlace(Db.getUid(shareLinkPlace))
}
}
}
}),
)
->subscribeFn(_ => ())
->ignore
combineLatest3(currentUserRx, shareLinkRx, shareLinkPlaceRx)
}

@react.component
let make = (~linkId) => {
let auth = Reactfire.useAuth()
let firestore = Reactfire.useFirestore()
let pageDataStatus = Reactfire.useObservable(
~observableId=`page_ShareLinkResolver_${linkId}`,
~source=pageDataRx(firestore, ~linkId),
~source=pageDataRx(auth, firestore, ~linkId),
)
let {currentUser} = Reactfire.useAuth()
switch (pageDataStatus.data, currentUser->Null.toOption) {
| (Some(data), Some({uid: userId})) =>

switch pageDataStatus.data {
| Some((currentUser, Some(shareLink), Some(shareLinkPlace))) =>
let (acceptInviteState, acceptInviteSend) = ReactUpdate.useReducer(Ready, (action, state) => {
switch (action, state) {
| (Run, Error(_)) // allow retry
| (Run, Ready) =>
ReactUpdate.UpdateWithSideEffects(
Pending,
({send}) => {
Db.ShareLink.acceptInvitation(firestore, ~linkId, ~userId)
Db.ShareLink.acceptInvitation(firestore, ~linkId, ~userId=currentUser.uid)
->Promise.then(() => {
send(Resolved)
Promise.resolve()
Expand All @@ -103,8 +130,7 @@ let make = (~linkId) => {
ReactUpdate.UpdateWithSideEffects(
Success,
_ => {
let shareLink = data->fst
RescriptReactRouter.replace(`/misto/${shareLink.place}`)
redirectToPlace(shareLink.place)
None
},
)
Expand All @@ -113,7 +139,7 @@ let make = (~linkId) => {
}
})
<Pure
data=pageDataStatus.data
data=Some(shareLink, shareLinkPlace)
loading={acceptInviteState == Pending}
onAccept={_ => acceptInviteSend(Run)}
/>
Expand Down
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2375,9 +2375,9 @@
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz#ea6d23ade78a325f7a52750aab1526b02b628c29"
integrity sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==

"@nobleai/rescript-rxjs@https://github.com/czabaj/rescript-rxjs#a85312969a9cddba8d4cc3cd11d9c947512f8a05":
"@nobleai/rescript-rxjs@https://github.com/czabaj/rescript-rxjs#73a625653408bd262ac481847108ede30a99442e":
version "7.5.9"
resolved "https://github.com/czabaj/rescript-rxjs#a85312969a9cddba8d4cc3cd11d9c947512f8a05"
resolved "https://github.com/czabaj/rescript-rxjs#73a625653408bd262ac481847108ede30a99442e"

"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
Expand Down

0 comments on commit 75ae203

Please sign in to comment.