diff --git a/apps/backend-functions/src/firestore/users/exercises/assess_life.ts b/apps/backend-functions/src/firestore/users/exercises/assess_life.ts index 7850635ac..3761c6305 100644 --- a/apps/backend-functions/src/firestore/users/exercises/assess_life.ts +++ b/apps/backend-functions/src/firestore/users/exercises/assess_life.ts @@ -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', @@ -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 })) @@ -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 } @@ -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(`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 diff --git a/apps/backend-functions/src/main.ts b/apps/backend-functions/src/main.ts index b097e8528..f1e00f80b 100644 --- a/apps/backend-functions/src/main.ts +++ b/apps/backend-functions/src/main.ts @@ -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' diff --git a/libs/exercises/src/lib/assess-life/assess-life.service.ts b/libs/exercises/src/lib/assess-life/assess-life.service.ts index 68d6915be..0e26d395e 100644 --- a/libs/exercises/src/lib/assess-life/assess-life.service.ts +++ b/libs/exercises/src/lib/assess-life/assess-life.service.ts @@ -90,7 +90,7 @@ export class AssessLifeEntryService extends FireSubCollection { 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) }) @@ -105,7 +105,7 @@ export class AssessLifeEntryService extends FireSubCollection { 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) }) diff --git a/libs/exercises/src/lib/assess-life/components/entry/assess-life-entry.component.html b/libs/exercises/src/lib/assess-life/components/entry/assess-life-entry.component.html index 9a210ff2c..ac59bc2fc 100644 --- a/libs/exercises/src/lib/assess-life/components/entry/assess-life-entry.component.html +++ b/libs/exercises/src/lib/assess-life/components/entry/assess-life-entry.component.html @@ -99,7 +99,7 @@ - + diff --git a/libs/exercises/src/lib/assess-life/components/prioritize-goals/prioritize-goals.component.ts b/libs/exercises/src/lib/assess-life/components/prioritize-goals/prioritize-goals.component.ts index a23efa7fe..876457ad1 100644 --- a/libs/exercises/src/lib/assess-life/components/prioritize-goals/prioritize-goals.component.ts +++ b/libs/exercises/src/lib/assess-life/components/prioritize-goals/prioritize-goals.component.ts @@ -1,5 +1,6 @@ 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' @@ -7,7 +8,6 @@ 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, @@ -37,39 +37,28 @@ export class PrioritizeGoalsComponent { })) ) + @Input() form?: FormArray> @Output() step = new EventEmitter<'next' | 'previous'>() constructor( private auth: AuthService, - private goalService: GoalService, - private stakeholderService: GoalStakeholderService + private goalService: GoalService ) {} doReorder(ev: CustomEvent, 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() } } \ No newline at end of file diff --git a/libs/exercises/src/lib/assess-life/forms/assess-life.form.ts b/libs/exercises/src/lib/assess-life/forms/assess-life.form.ts index 61fb70d71..5e7c948c6 100644 --- a/libs/exercises/src/lib/assess-life/forms/assess-life.form.ts +++ b/libs/exercises/src/lib/assess-life/forms/assess-life.form.ts @@ -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' @@ -21,6 +21,7 @@ function createAssessLifeFormControl(params?: Partial) { gratitude: new FormList(assessLife.gratitude), imagine: new ImagineForm(assessLife.imagine), learn: new LearnForm(assessLife.learn), + priorities: new FormArray>(assessLife.priorities.map(v => new FormControl(v, { nonNullable: true }))), proud: new FormList(assessLife.proud), timeManagement: new TimeManagementForm(assessLife.timeManagement), wheelOfLife: new WheelOfLifeForm(assessLife.wheelOfLife), @@ -42,6 +43,7 @@ export class AssessLifeForm extends FormGroup { 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> } get proud() { return this.get('proud')! as FormList } get timeManagement() { return this.get('timeManagement')! as TimeManagementForm } get wheelOfLife() { return this.get('wheelOfLife')! as WheelOfLifeForm } diff --git a/libs/model/src/lib/assess-life.ts b/libs/model/src/lib/assess-life.ts index e397701ac..c77ae2c1a 100644 --- a/libs/model/src/lib/assess-life.ts +++ b/libs/model/src/lib/assess-life.ts @@ -66,6 +66,7 @@ export interface AssessLifeEntry { imagine: AssessLifeImagine interval: AssessLifeInterval learn: Learn + priorities: string[] proud: ListEntries timeManagement: TimeManagement wheelOfLife: WheelOfLife @@ -86,6 +87,7 @@ export function createAssessLifeEntry(params: Partial = {}): 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)