Skip to content

Commit

Permalink
save goal priorities once and sync with stakeholder later
Browse files Browse the repository at this point in the history
  • Loading branch information
RemcoSimonides committed Oct 26, 2023
1 parent f6b7219 commit 214a3fd
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 35 deletions.
29 changes: 19 additions & 10 deletions apps/backend-functions/src/firestore/users/exercises/assess_life.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { arrayUnion, db, logger, onDocumentCreate, onDocumentUpdate } from '@strive/api/firebase'
import { AssessLifeEntry, AssessLifeInterval, AssessLifeSettings, Message, Personal, createAssessLifeEntry, createAssessLifeSettings, createDearFutureSelf, createMessage, getInterval } from '@strive/model'
import { arrayUnion, db, onDocumentCreate, onDocumentUpdate } from '@strive/api/firebase'
import { AssessLifeEntry, AssessLifeInterval, AssessLifeSettings, Message, Personal, Stakeholder, createAssessLifeEntry, createAssessLifeSettings, createDearFutureSelf, createMessage, getInterval } from '@strive/model'
import { getDocument, getDocumentSnap, toDate, unique } from '../../../shared/utils'
import { addMonths, addQuarters, addWeeks, addYears, differenceInDays, formatISO, isBefore, isEqual, startOfMonth, startOfQuarter, startOfWeek } from 'date-fns'
import { getNextDay, startOfAssessLifeYear } from '@strive/exercises/assess-life/utils/date.utils'
import { deleteScheduledTask, upsertScheduledTask } from 'apps/backend-functions/src/shared/scheduled-task/scheduled-task'
import { ScheduledTaskUserExerciseAssessLife, enumWorkerType } from 'apps/backend-functions/src/shared/scheduled-task/scheduled-task.interface'
import { deleteScheduledTask, upsertScheduledTask } from '../../../shared/scheduled-task/scheduled-task'
import { ScheduledTaskUserExerciseAssessLife, enumWorkerType } from '../../../shared/scheduled-task/scheduled-task.interface'
import { AES, enc } from 'crypto-js'

export const assessLifeSettingsCreatedHandler = onDocumentCreate(`Users/{uid}/Exercises/AssessLife`, 'assessLifeSettingsCreatedHandler',
Expand All @@ -21,8 +21,6 @@ async (snapshot, context) => {
export const assessLifeSettingsChangeHandler = onDocumentUpdate(`Users/{uid}/Exercises/AssessLife`, 'assessLifeChangeHandler',
async (snapshot, context) => {

logger.log('changed assess life settings')

const { uid } = context.params as { uid: string }
const before = createAssessLifeSettings(toDate({ ...snapshot.before.data(), id: snapshot.id }))
const after = createAssessLifeSettings(toDate({ ...snapshot.after.data(), id: snapshot.id }))
Expand Down Expand Up @@ -63,15 +61,14 @@ async (snapshot, context) => {
saveGratitude(uid, entry),
saveWheelOfLife(uid, entry),
saveDearFutureSelf(uid, entry),
saveImagine(uid, entry)
saveImagine(uid, entry),
savePriorities(uid, entry)
])

return promises

// TODO Sync goal priorities after submitting. And keep the goal priorities in the entry to see what the history was.
})

export const assessLifeEntryChangeHandler = onDocumentCreate(`Users/{uid}/Exercises/AssessLife/Entries/{entryId}`, 'assessLifeChangeHandler',
export const assessLifeEntryChangeHandler = onDocumentUpdate(`Users/{uid}/Exercises/AssessLife/Entries/{entryId}`, 'assessLifeChangeHandler',
async (snapshot, context) => {

const { uid } = context.params as { uid: string }
Expand All @@ -82,11 +79,23 @@ async (snapshot, context) => {
saveWheelOfLife(uid, after), // wheel of life can be overwritten everytime
// saveDearFutureSelf(uid, after), // unable to update dear future self as I don't know which message has been updated and just adding them isn't the solution
// saveImagine(uid, after) // unable to update imagine as I don't know which message has been updated and just adding them isn't the solution
savePriorities(uid, after)
])

return promises
})

async function savePriorities(uid: string, entry: AssessLifeEntry) {
const { priorities } = entry

const promises = priorities.map(goalId => getDocument<Stakeholder>(`Goals/${goalId}/GStakeholders/${uid}`))
const stakeholders = await Promise.all(promises)

return stakeholders.map((stakeholder, priority) => {
return db.doc(`Goals/${stakeholder.goalId}/GStakeholders/${uid}`).update({ priority })
})
}

async function saveGratitude(uid: string, entry: AssessLifeEntry) {
const items = entry.gratitude.entries.slice(0, 3)
if (!items.length) return
Expand Down
2 changes: 1 addition & 1 deletion apps/backend-functions/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export { scheduledFocusEmailRunner } from './pubsub/email/focus'
// firestorage
export { userSpectatorChangeHandler, userSpectatorCreatedHandler, userSpectatorDeleteHandler } from './firestore/users/user-spectators/user-spectator'
export { affirmationsCreatedHandler, affirmationsChangeHandler, affirmationsDeleteHandler } from './firestore/users/exercises/affirmation'
export { assessLifeSettingsCreatedHandler, assessLifeSettingsChangeHandler, assessLifeEntryCreatedHandler } from './firestore/users/exercises/assess_life'
export { assessLifeSettingsCreatedHandler, assessLifeSettingsChangeHandler, assessLifeEntryCreatedHandler, assessLifeEntryChangeHandler } from './firestore/users/exercises/assess_life'
export { dailyGratitudeCreatedHandler, dailyGratitudeChangedHandler, dailyGratitudeDeleteHandler } from './firestore/users/exercises/daily_gratitude'
export { dearFutureSelfCreatedHandler, dearFutureSelfChangedHandler, dearFutureSelfDeleteHandler } from './firestore/users/exercises/dear_future_self'
export { wheelOfLifeCreatedHandler, wheelOfLifeChangedHandler, wheelOfLifeDeleteHandler, wheelOfLifeEntryCreatedHandler } from './firestore/users/exercises/wheel_of_life'
Expand Down
4 changes: 2 additions & 2 deletions libs/exercises/src/lib/assess-life/assess-life.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class AssessLifeEntryService extends FireSubCollection<AssessLifeEntry> {
entries = entries.map(entry => {
Object.keys(entry).forEach(key => {
const typedKey = key as keyof AssessLifeEntry
const excludedProperties = ['id', 'createdAt', 'updatedAt', 'interval']
const excludedProperties = ['id', 'createdAt', 'updatedAt', 'interval', 'priorities']
if (excludedProperties.includes(key)) return
entry[typedKey] = _decrypt(entry[typedKey], encryptionKey)
})
Expand All @@ -105,7 +105,7 @@ export class AssessLifeEntryService extends FireSubCollection<AssessLifeEntry> {

Object.keys(entry).forEach(key => {
const typedKey = key as keyof AssessLifeEntry
const excludedProperties = ['id', 'createdAt', 'updatedAt', 'interval']
const excludedProperties = ['id', 'createdAt', 'updatedAt', 'interval', 'priorities']
if (excludedProperties.includes(key)) return
entry[typedKey] = _encrypt(entry[typedKey], encryptionKey)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
</ion-content>

<ion-content *ngSwitchCase="'prioritizeGoals'" class="ion-padding" [ngClass]="animatingSection()">
<strive-assess-life-prioritize-goals (step)="step($event)" />
<strive-assess-life-prioritize-goals [form]="form.priorities" (step)="step($event)" />
</ion-content>

<ion-content *ngSwitchCase="'imagine'" class="ion-padding" [ngClass]="animatingSection()">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core'
import { FormArray, FormControl } from '@angular/forms'
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'
import { IonicModule, ItemReorderEventDetail } from '@ionic/angular'
import { map, of, switchMap } from 'rxjs'
import { AuthService } from '@strive/auth/auth.service'
import { GoalService } from '@strive/goal/goal.service'
import { PageLoadingModule } from '@strive/ui/page-loading/page-loading.module'
import { StakeholderWithGoal } from '@strive/model'
import { ImageModule } from '@strive/media/directives/image.module'
import { GoalStakeholderService } from '@strive/stakeholder/stakeholder.service'

@Component({
standalone: true,
Expand Down Expand Up @@ -37,39 +37,28 @@ export class PrioritizeGoalsComponent {
}))
)

@Input() form?: FormArray<FormControl<string>>
@Output() step = new EventEmitter<'next' | 'previous'>()

constructor(
private auth: AuthService,
private goalService: GoalService,
private stakeholderService: GoalStakeholderService
private goalService: GoalService
) {}

doReorder(ev: CustomEvent<ItemReorderEventDetail>, stakeholders: StakeholderWithGoal[]) {
if (!this.auth.uid) return
if (!this.auth.uid || !this.form) return

const { from, to } = ev.detail
const element = stakeholders[from]
stakeholders.splice(from, 1)
stakeholders.splice(to, 0, element)

if (stakeholders.some(stakeholder => stakeholder.priority === -1)) {
// update all stakeholders
stakeholders.forEach((stakeholder, priority) => {
this.stakeholderService.update({ uid: this.auth.uid, priority }, { params: { goalId: stakeholder.goalId }})
})
const ids = stakeholders.map(stakeholder => stakeholder.goalId)

} else {
// only update the stakeholders that have been changed
const min = Math.min(from, to)
const max = Math.max(from, to)
const stakeholdersToUpdate = stakeholders.slice(min, max + 1)
this.form.clear()
ids.forEach(id => this.form?.push(new FormControl(id, { nonNullable: true })))
this.form?.markAsDirty()

stakeholdersToUpdate.forEach((stakeholder, index) => {
const priority = index + min
this.stakeholderService.update({ uid: this.auth.uid, priority }, { params: { goalId: stakeholder.goalId }})
})
}
ev.detail.complete()
}
}
4 changes: 3 additions & 1 deletion libs/exercises/src/lib/assess-life/forms/assess-life.form.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FormControl, FormGroup } from '@angular/forms'
import { FormArray, FormControl, FormGroup } from '@angular/forms'
import { AssessLifeEntry, createAssessLifeEntry } from '@strive/model'
import { TimeManagementForm } from '../components/time-management/time-management.form'
import { WheelOfLifeForm } from '../components/wheel-of-life/wheel-of-life.form'
Expand All @@ -21,6 +21,7 @@ function createAssessLifeFormControl(params?: Partial<AssessLifeEntry>) {
gratitude: new FormList(assessLife.gratitude),
imagine: new ImagineForm(assessLife.imagine),
learn: new LearnForm(assessLife.learn),
priorities: new FormArray<FormControl<string>>(assessLife.priorities.map(v => new FormControl(v, { nonNullable: true }))),
proud: new FormList(assessLife.proud),
timeManagement: new TimeManagementForm(assessLife.timeManagement),
wheelOfLife: new WheelOfLifeForm(assessLife.wheelOfLife),
Expand All @@ -42,6 +43,7 @@ export class AssessLifeForm extends FormGroup<AssessLifeFormControl> {
get gratitude() { return this.get('gratitude')! as FormList }
get imagine() { return this.get('imagine')! as ImagineForm }
get learn() { return this.get('learn')! as LearnForm }
get priorities() { return this.get('priorities')! as FormArray<FormControl<string>> }
get proud() { return this.get('proud')! as FormList }
get timeManagement() { return this.get('timeManagement')! as TimeManagementForm }
get wheelOfLife() { return this.get('wheelOfLife')! as WheelOfLifeForm }
Expand Down
2 changes: 2 additions & 0 deletions libs/model/src/lib/assess-life.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface AssessLifeEntry {
imagine: AssessLifeImagine
interval: AssessLifeInterval
learn: Learn
priorities: string[]
proud: ListEntries
timeManagement: TimeManagement
wheelOfLife: WheelOfLife
Expand All @@ -86,6 +87,7 @@ export function createAssessLifeEntry(params: Partial<AssessLifeEntry> = {}): As
gratitude: createListEntries(params?.gratitude),
imagine: createAssessLifeImagine(params?.imagine),
learn: createLearn(params?.learn),
priorities: params?.priorities ?? [],
proud: createListEntries(params?.proud),
timeManagement: createTimeManagement(params?.timeManagement),
wheelOfLife: createWheelOfLife(params?.wheelOfLife)
Expand Down

0 comments on commit 214a3fd

Please sign in to comment.