From 2ea66184902ca59270d83e459967a8c07caded82 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Tue, 19 Nov 2024 21:03:26 +0300
Subject: [PATCH 001/113] all: smoother november challenge (fixes #7741)(fixes
 #7748) (#7751)

Co-authored-by: Axel Lo <54468493+RheuX@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |   6 +-
 src/app/community/community.component.ts      |  60 ++++++--
 .../courses-step-view.component.ts            |   8 +
 src/app/dashboard/dashboard.component.html    |   3 -
 src/app/dashboard/dashboard.component.ts      |   8 -
 src/app/exams/exams-view.component.ts         |  21 ++-
 src/app/home/home.component.html              |   4 +-
 src/app/home/home.component.ts                |  15 +-
 .../notifications.component.html              |   6 +-
 .../notifications/notifications.component.ts  |  17 ++-
 src/app/shared/database/pouch-auth.service.ts |  11 +-
 .../dialogs-announcement.component.html       |  92 ++++++-----
 .../dialogs-announcement.component.scss       |  32 +++-
 .../dialogs/dialogs-announcement.component.ts | 143 ++++++++++++------
 .../dialogs/dialogs-chat-share.component.ts   |  16 +-
 .../shared/dialogs/planet-dialogs.module.ts   |   8 +-
 .../shared/user-challenge-status.service.ts   |  41 +++++
 17 files changed, 353 insertions(+), 138 deletions(-)
 create mode 100644 src/app/shared/user-challenge-status.service.ts

diff --git a/package.json b/package.json
index 091f07f3e8..d4f944db42 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.50",
+  "version": "0.15.51",
   "myplanet": {
-    "latest": "v0.20.97",
-    "min": "v0.19.97"
+    "latest": "v0.20.99",
+    "min": "v0.19.99"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/community/community.component.ts b/src/app/community/community.component.ts
index 836222c18a..82d186ac52 100644
--- a/src/app/community/community.component.ts
+++ b/src/app/community/community.component.ts
@@ -8,7 +8,6 @@ import { DialogsLoadingService } from '../shared/dialogs/dialogs-loading.service
 import { MatDialog } from '@angular/material/dialog';
 import { CommunityLinkDialogComponent } from './community-link-dialog.component';
 import { TeamsService } from '../teams/teams.service';
-import { DialogsAnnouncementComponent } from '../shared/dialogs/dialogs-announcement.component';
 import { DialogsPromptComponent } from '../shared/dialogs/dialogs-prompt.component';
 import { CouchService } from '../shared/couchdb.service';
 import { PlanetMessageService } from '../shared/planet-message.service';
@@ -20,6 +19,13 @@ import { CustomValidators } from '../validators/custom-validators';
 import { environment } from '../../environments/environment';
 import { planetAndParentId } from '../manager-dashboard/reports/reports.utils';
 import { DeviceInfoService, DeviceType } from '../shared/device-info.service';
+import {
+  DialogsAnnouncementComponent,
+  DialogsAnnouncementSuccessComponent,
+  includedCodes,
+  challengePeriod
+} from '../shared/dialogs/dialogs-announcement.component';
+import { UserChallengeStatusService } from '../shared/user-challenge-status.service';
 
 @Component({
   selector: 'planet-community',
@@ -49,7 +55,6 @@ export class CommunityComponent implements OnInit, OnDestroy {
   resizeCalendar: any = false;
   deviceType: DeviceType;
   deviceTypes = DeviceType;
-  challengeActive: boolean;
   isLoading: boolean;
 
   constructor(
@@ -64,7 +69,8 @@ export class CommunityComponent implements OnInit, OnDestroy {
     private planetMessageService: PlanetMessageService,
     private userService: UserService,
     private usersService: UsersService,
-    private deviceInfoService: DeviceInfoService
+    private userStatusService: UserChallengeStatusService,
+    private deviceInfoService: DeviceInfoService,
   ) {
     this.deviceType = this.deviceInfoService.getDeviceType();
   }
@@ -101,22 +107,31 @@ export class CommunityComponent implements OnInit, OnDestroy {
   }
 
   communityChallenge() {
-    const includedCodes = [ 'guatemala', 'san.pablo', 'xela', 'embakasi', 'uriur' ];
-    this.challengeActive = includedCodes.includes(this.configuration.code) &&
-    ((new Date() > new Date(2024, 9, 31)) && (new Date() < new Date(2024, 11, 1)));
-    const popupShown = localStorage.getItem('announcementPopupShown');
+    const challengeActive = includedCodes.includes(this.configuration.code) && challengePeriod;
 
-    if (this.challengeActive && !popupShown) {
-      this.openAnnouncementDialog();
-      localStorage.setItem('announcementPopupShown', 'true');
+    if (challengeActive) {
+      const dialogRef = this.dialog.open(DialogsAnnouncementComponent, {
+        width: '50vw',
+        maxHeight: '100vh'
+      });
+      dialogRef.afterClosed().subscribe(() => {
+        if (!this.userStatusService.getCompleteChallenge()) {
+          this.sendChallengeNotification(this.user).subscribe();
+        }
+      });
     }
   }
 
-  openAnnouncementDialog() {
-    this.dialog.open(DialogsAnnouncementComponent, {
-      width: '50vw',
-      maxHeight: '100vh'
-    });
+  sendChallengeNotification(user) {
+    const data = {
+      'user': user._id,
+      'message': `El reto está en`,
+      'type': 'challenges',
+      'priority': 1,
+      'status': 'unread',
+      'time': this.couchService.datePlaceholder
+    };
+    return this.couchService.updateDocument('notifications', data);
   }
 
   getCommunityData() {
@@ -193,7 +208,20 @@ export class CommunityComponent implements OnInit, OnDestroy {
         return this.couchService.updateDocument('notifications/_bulk_docs', { docs });
       }),
       finalize(() => this.dialogsLoadingService.stop())
-    ).subscribe(() => this.dialogsFormService.closeDialogsForm());
+    ).subscribe(() => {
+      this.dialogsFormService.closeDialogsForm();
+      if (
+        this.userStatusService.getStatus('joinedCourse') &&
+        this.userStatusService.getStatus('surveyComplete') &&
+        !this.userStatusService.getStatus('hasPost')
+      ) {
+        this.dialog.open(DialogsAnnouncementSuccessComponent, {
+          width: '50vw',
+          maxHeight: '100vh'
+        });
+        this.userStatusService.updateStatus('hasPost', true);
+      }
+    });
   }
 
   sendNotifications(user, currentUser) {
diff --git a/src/app/courses/step-view-courses/courses-step-view.component.ts b/src/app/courses/step-view-courses/courses-step-view.component.ts
index 7ea1ff1026..eb4b692921 100644
--- a/src/app/courses/step-view-courses/courses-step-view.component.ts
+++ b/src/app/courses/step-view-courses/courses-step-view.component.ts
@@ -11,6 +11,7 @@ import { ResourcesService } from '../../resources/resources.service';
 import { DialogsSubmissionsComponent } from '../../shared/dialogs/dialogs-submissions.component';
 import { StateService } from '../../shared/state.service';
 import { ChatService } from '../../shared/chat.service';
+import { DialogsAnnouncementComponent, includedCodes, challengeCourseId, challengePeriod } from '../../shared/dialogs/dialogs-announcement.component';
 
 @Component({
   templateUrl: './courses-step-view.component.html',
@@ -141,6 +142,13 @@ export class CoursesStepViewComponent implements OnInit, OnDestroy {
 
   backToCourseDetail() {
     this.router.navigate([ '../../' ], { relativeTo: this.route });
+    // Challenge option only
+    if (includedCodes.includes(this.stateService.configuration.code) && challengePeriod && this.courseId === challengeCourseId) {
+      this.dialog.open(DialogsAnnouncementComponent, {
+        width: '50vw',
+        maxHeight: '100vh'
+      });
+    }
   }
 
   setResourceUrl(resourceUrl: string) {
diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html
index b385727c58..292b296d2b 100644
--- a/src/app/dashboard/dashboard.component.html
+++ b/src/app/dashboard/dashboard.component.html
@@ -21,9 +21,6 @@ <h1 class="mat-title">
         </mat-icon>
       </span>
     </div>
-    <div class="cursor-pointer" (click)="openChallengeView()" matTooltip="challenge">
-      <mat-icon>stars</mat-icon>
-    </div>
   </div>
 </mat-card>
 <planet-dashboard-tile
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts
index 7f19748be9..e6ccedd30d 100644
--- a/src/app/dashboard/dashboard.component.ts
+++ b/src/app/dashboard/dashboard.component.ts
@@ -15,7 +15,6 @@ import { CoursesService } from '../courses/courses.service';
 import { CoursesViewDetailDialogComponent } from '../courses/view-courses/courses-view-detail.component';
 import { foundations, foundationIcons } from '../courses/constants';
 import { CertificationsService } from '../manager-dashboard/certifications/certifications.service';
-import { DialogsAnnouncementComponent } from '../shared/dialogs/dialogs-announcement.component';
 
 @Component({
   templateUrl: './dashboard.component.html',
@@ -212,11 +211,4 @@ export class DashboardComponent implements OnInit, OnDestroy {
     this.badgeGroups = [ ...foundations, 'none' ].filter(group => this.badgesCourses[group] && this.badgesCourses[group].length);
   }
 
-  openChallengeView() {
-    this.dialog.open(DialogsAnnouncementComponent, {
-      width: '50vw',
-      maxHeight: '100vh'
-    });
-  }
-
 }
diff --git a/src/app/exams/exams-view.component.ts b/src/app/exams/exams-view.component.ts
index 54e3a67e75..244c0df035 100644
--- a/src/app/exams/exams-view.component.ts
+++ b/src/app/exams/exams-view.component.ts
@@ -10,6 +10,9 @@ import { FormControl, AbstractControl } from '@angular/forms';
 import { CustomValidators } from '../validators/custom-validators';
 import { Exam, ExamQuestion } from './exams.model';
 import { PlanetMessageService } from '../shared/planet-message.service';
+import { DialogsAnnouncementComponent, includedCodes, challengeCourseId, challengePeriod } from '../shared/dialogs/dialogs-announcement.component';
+import { StateService } from '../shared/state.service';
+import { MatDialog } from '@angular/material/dialog';
 
 @Component({
   selector: 'planet-exams-view',
@@ -45,6 +48,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
   unansweredQuestions: number[];
   isComplete = false;
   comment: string;
+  courseId: string;
 
   constructor(
     private router: Router,
@@ -53,7 +57,9 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
     private submissionsService: SubmissionsService,
     private userService: UserService,
     private couchService: CouchService,
-    private planetMessageService: PlanetMessageService
+    private planetMessageService: PlanetMessageService,
+    private dialog: MatDialog,
+    private stateService: StateService,
   ) { }
 
   ngOnInit() {
@@ -77,6 +83,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
         return;
       }
       this.setExam(params);
+      this.courseId = params.get('id');
     });
   }
 
@@ -133,6 +140,18 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
         this.spinnerOn = false;
       } else {
         this.routeToNext(nextClicked ? this.questionNum : nextQuestion, previousStatus);
+        // Challenge option only
+        if (
+          isFinish &&
+          includedCodes.includes(this.stateService.configuration.code) &&
+          challengePeriod &&
+          this.courseId === challengeCourseId
+          ) {
+          this.dialog.open(DialogsAnnouncementComponent, {
+            width: '50vw',
+            maxHeight: '100vh'
+          });
+        }
       }
     });
   }
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index 5cdc488552..8e1f338f34 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -72,12 +72,12 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
     <mat-menu #notificationMenu="matMenu" [overlapTrigger]="false" class="notification-menu">
       <div class="notification-items">
         <a mat-menu-item (click)="readAllNotification()" i18n>Mark all as Read</a>
-        <a [routerLink]="!notification.link ? '/notifications' : notification.link !== '/' ? [ notification.link, notification.linkParams || {} ] : '/'"
+        <a [routerLink]="notification.type !== 'challenges' ? (!notification.link ? '/notifications' : notification.link !== '/' ? [notification.link, notification.linkParams || {}] : '/') : null"
           class="menu-item-notification"
           [ngClass]="{'primary-text-color':notification.status==='unread'}"
           mat-menu-item
           *ngFor="let notification of notifications"
-          (click)="readNotification(notification)">
+          (click)="notification.type === 'challenges' ? openAnnouncementDialog(notification) : readNotification(notification)">
           <p [innerHTML]="notification.message"><p>
           <p *ngIf="notification.time > 0" class="small">{{notification.time | date: 'mediumDate'}}</p>
           <mat-divider></mat-divider>
diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts
index 0930ac29e9..967025d4d8 100644
--- a/src/app/home/home.component.ts
+++ b/src/app/home/home.component.ts
@@ -12,6 +12,8 @@ import { PouchAuthService } from '../shared/database/pouch-auth.service';
 import { StateService } from '../shared/state.service';
 import { DeviceInfoService } from '../shared/device-info.service';
 import { NotificationsService } from '../notifications/notifications.service';
+import { DialogsAnnouncementComponent, includedCodes, challengePeriod } from '../shared/dialogs/dialogs-announcement.component';
+import { MatDialog } from '@angular/material/dialog';
 
 @Component({
   templateUrl: './home.component.html',
@@ -60,13 +62,14 @@ export class HomeComponent implements OnInit, DoCheck, AfterViewChecked, OnDestr
   private onDestroy$ = new Subject<void>();
 
   constructor(
+    private dialog: MatDialog,
     private couchService: CouchService,
     private router: Router,
     private userService: UserService,
     private pouchAuthService: PouchAuthService,
     private stateService: StateService,
     private deviceInfoService: DeviceInfoService,
-    private notificationsService: NotificationsService
+    private notificationsService: NotificationsService,
   ) {
     this.userService.userChange$.pipe(takeUntil(this.onDestroy$))
       .subscribe(() => {
@@ -229,4 +232,14 @@ export class HomeComponent implements OnInit, DoCheck, AfterViewChecked, OnDestr
     }
   }
 
+  openAnnouncementDialog(notification) {
+    this.readNotification(notification);
+    const challengeActive = includedCodes.includes(this.configuration.code) && challengePeriod;
+    if (challengeActive) {
+      this.dialog.open(DialogsAnnouncementComponent, {
+        width: '50vw',
+        maxHeight: '100vh'
+      });
+    }
+  }
 }
diff --git a/src/app/notifications/notifications.component.html b/src/app/notifications/notifications.component.html
index 8e7cb1b3f5..14635947b7 100644
--- a/src/app/notifications/notifications.component.html
+++ b/src/app/notifications/notifications.component.html
@@ -23,8 +23,10 @@
               </a>
             </ng-container>
             <ng-template #noLink>
-              <span [innerHTML]="element.message"></span>
-              <span *ngIf="element.time > 0" class="mat-caption margin-lr-8">{{element.time | date: 'medium'}}</span>
+              <a (click)="element.type === 'challenges' && openAnnouncementDialog()">
+                <span [innerHTML]="element.message"></span>
+                <span *ngIf="element.time > 0" class="mat-caption margin-lr-8">{{element.time | date: 'medium'}}</span>
+              </a>
             </ng-template>
           </p>
         </mat-cell>
diff --git a/src/app/notifications/notifications.component.ts b/src/app/notifications/notifications.component.ts
index 41420256fd..0dec83f4c4 100644
--- a/src/app/notifications/notifications.component.ts
+++ b/src/app/notifications/notifications.component.ts
@@ -8,7 +8,10 @@ import { Subject } from 'rxjs';
 
 import { MatPaginator } from '@angular/material/paginator';
 import { MatTableDataSource } from '@angular/material/table';
+import { MatDialog } from '@angular/material/dialog';
 import { NotificationsService } from './notifications.service';
+import { DialogsAnnouncementComponent, includedCodes, challengePeriod } from '../shared/dialogs/dialogs-announcement.component';
+import { StateService } from '../shared/state.service';
 
 @Component({
   templateUrl: './notifications.component.html',
@@ -25,9 +28,11 @@ export class NotificationsComponent implements OnInit, AfterViewInit {
   anyUnread = true;
 
   constructor(
+    private dialog: MatDialog,
+    private stateService: StateService,
+    private notificationsService: NotificationsService,
     private couchService: CouchService,
     private userService: UserService,
-    private notificationsService: NotificationsService
   ) {
     this.userService.notificationStateChange$.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
       this.getNotifications();
@@ -88,4 +93,14 @@ export class NotificationsComponent implements OnInit, AfterViewInit {
   readAllNotification() {
     this.notificationsService.setNotificationsAsRead(this.notifications.data);
   }
+
+  openAnnouncementDialog() {
+    const challengeActive = includedCodes.includes(this.stateService.configuration.code) && challengePeriod;
+    if (challengeActive) {
+      this.dialog.open(DialogsAnnouncementComponent, {
+        width: '50vw',
+        maxHeight: '100vh'
+      });
+    }
+  }
 }
diff --git a/src/app/shared/database/pouch-auth.service.ts b/src/app/shared/database/pouch-auth.service.ts
index 363357ca5e..f1f5dddd96 100644
--- a/src/app/shared/database/pouch-auth.service.ts
+++ b/src/app/shared/database/pouch-auth.service.ts
@@ -1,8 +1,9 @@
 import { Injectable } from '@angular/core';
 import { from, throwError, Observable, forkJoin } from 'rxjs';
-import { catchError, switchMap, tap } from 'rxjs/operators';
+import { catchError, switchMap } from 'rxjs/operators';
 import { PouchService } from './pouch.service';
 import { CouchService } from '../couchdb.service';
+import { UserChallengeStatusService } from '../user-challenge-status.service';
 
 interface SessionInfo {
   userCtx: {
@@ -18,7 +19,8 @@ export class PouchAuthService {
 
   constructor(
     private pouchService: PouchService,
-    private couchService: CouchService
+    private couchService: CouchService,
+    private userStatusService: UserChallengeStatusService
   ) {
     this.authDB = this.pouchService.getAuthDB();
   }
@@ -32,10 +34,6 @@ export class PouchAuthService {
   login(username, password) {
     this.pouchService.configureDBs();
     return from(this.authDB.logIn(username, password)).pipe(
-      tap(() => {
-        // Reset the popup flag on successful login
-        localStorage.removeItem('announcementPopupShown');
-      }),
       catchError(this.handleError)
     );
   }
@@ -48,6 +46,7 @@ export class PouchAuthService {
   }
 
   logout() {
+    this.userStatusService.resetStatus();
     return from(this.authDB.logOut()).pipe(
       switchMap(() => forkJoin(this.pouchService.deconfigureDBs())),
       catchError(this.handleError)
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.html b/src/app/shared/dialogs/dialogs-announcement.component.html
index 7cb42a2d72..4998d47191 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.html
+++ b/src/app/shared/dialogs/dialogs-announcement.component.html
@@ -5,48 +5,64 @@
     class="announcement-banner"
   />
 
-  <div class="steps-container">
-    <div class="step">
-      <mat-icon color="primary">
-        {{ userStatus.joinedCourse ? 'check_circle' : 'radio_button_unchecked' }}
-      </mat-icon>
-      <span>Únete al curso <a href="/courses/view/{{ courseId }}">Reto de noviembre</a>.</span>
-      <a *ngIf="!userStatus.joinedCourse" mat-button mat-raised-button color="primary" type="button" (click)="joinCourse()">
-        Únete
-      </a>
-    </div>
-
-    <div class="step">
-      <mat-icon color="primary">
-        {{ userStatus.surveyComplete ? 'check_circle' : 'radio_button_unchecked' }}
-      </mat-icon>
-      <span>¡Encuesta finalizada!</span>
-      <a *ngIf="userStatus.joinedCourse && !userStatus.surveyComplete" mat-button mat-raised-button color="primary" type="button" (click)="doSurvey()">
-        Encuesta
-      </a>
+  <div class="thermometer-container">
+    <div class="thermometer">
+      <div class="thermometer-bar" [style.width.%]="getGoalPercentage()">
+        <div
+          class="thermometer-label"
+          [ngClass]="{ outside: getGoalPercentage() < 8 }"
+        >
+          {{ "$" + getTotalMoneyEarned() }}
+        </div>
+      </div>
     </div>
+  </div>
+  <hr>
 
-    <div class="step">
-      <mat-icon color="primary">
-        {{ userStatus.hasPost ? 'check_circle' : 'radio_button_unchecked' }}
-      </mat-icon>
-      <span>Comparte tu opinión en Nuestras Voces.</span>
-      <a *ngIf="userStatus.joinedCourse && userStatus.surveyComplete && !userStatus.hasPost" mat-button mat-raised-button color="primary" type="button" (click)="postVoice()">
-        Voces
-      </a>
-    </div>
+  <div *ngIf="isLoading; else content">
+    <mat-spinner></mat-spinner>
   </div>
 
-  <div class="thermometer-container">
-  <div class="thermometer">
-    <div class="thermometer-bar" [style.width.%]="getGoalPercentage()">
-      <div class="thermometer-label" [ngClass]="{'outside': getGoalPercentage() < 8}">
-        {{ getGoalPercentage() | number:'1.0-2' }}% ({{ '$'+ groupSummary?.length }})
+  <ng-template #content>
+    <div class="steps-container">
+      <div class="step">
+        <mat-icon color="primary">
+          {{ getStatus('joinedCourse') ? 'check_circle' : 'radio_button_unchecked' }}
+        </mat-icon>
+        <span>Únete al curso Reto noviembre.</span>
+        <a *ngIf="!getStatus('joinedCourse')" mat-button mat-raised-button color="primary" type="button" (click)="joinCourse()">
+          Unirse
+        </a>
+      </div>
+
+      <div class="step">
+        <mat-icon color="primary">
+          {{ getStatus('surveyComplete') ? 'check_circle' : 'radio_button_unchecked' }}
+        </mat-icon>
+        <span>¡Encuesta finalizada!</span>
+        <a *ngIf="getStatus('joinedCourse') && !getStatus('surveyComplete')" mat-button mat-raised-button color="primary" type="button" (click)="doSurvey()">
+          Encuesta
+        </a>
+      </div>
+
+      <div class="step">
+        <mat-icon color="primary">
+          {{ getStatus('hasPost') ? 'check_circle' : 'radio_button_unchecked' }}
+        </mat-icon>
+        <span>Comparte tu opinión en Nuestras Voces. <br><span>{{getStatus('amountEarned')}} de 5 Voces diarias</span> </span>
+        <a *ngIf="getStatus('joinedCourse') && getStatus('surveyComplete') && !getStatus('hasPost'); else dailyVoices" mat-button mat-raised-button color="primary" type="button" (click)="chatNShare()">
+          Chatea y comparte
+        </a>
+        <ng-template #dailyVoices>
+          <div class="daily-voces-dots">
+            <div
+              *ngFor="let dot of [0, 1, 2, 3, 4]; let i = index"
+              class="dot"
+              [ngClass]="{ completed: i < getStatus('amountEarned') }"
+            ></div>
+          </div>
+        </ng-template>
       </div>
     </div>
-  </div>
-  <div class="thermometer-goal">
-    <span>$0</span>
-    <span>$500</span>
-  </div>
+  </ng-template>
 </div>
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.scss b/src/app/shared/dialogs/dialogs-announcement.component.scss
index aec859b3d2..f3d53594ca 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.scss
+++ b/src/app/shared/dialogs/dialogs-announcement.component.scss
@@ -42,9 +42,9 @@
 
 .thermometer {
   width: 100%;
-  height: 30px;
+  height: 40px;
   background-color: #e0e0e0;
-  border-radius: 15px;
+  border-radius: 20px;
   overflow: hidden;
   position: relative;
   margin-bottom: 10px;
@@ -60,8 +60,8 @@
 }
 
 .thermometer-label {
-  color: white;
-  font-size: 12px;
+  color: black;
+  font-size: 1.5rem;
   padding: 2px;
   border-radius: 3px;
 }
@@ -71,9 +71,25 @@
   left: 0.5rem;
 }
 
-.thermometer-goal {
+.success-msg {
+  font-size: 1.5rem;
+  font-weight: bold;
+  margin-top: 20px;
+}
+
+.daily-voces-dots {
   display: flex;
-  justify-content: space-between;
-  width: 100%;
-  font-size: 14px;
+  gap: 8px;
+  margin-top: 8px;
+}
+
+.dot {
+  width: 12px;
+  height: 12px;
+  border-radius: 50%;
+  background-color: lightgray;
+}
+
+.dot.completed {
+  background-color: $primary;
 }
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.ts b/src/app/shared/dialogs/dialogs-announcement.component.ts
index f1b141548c..9f45a636d3 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.ts
+++ b/src/app/shared/dialogs/dialogs-announcement.component.ts
@@ -11,8 +11,28 @@ import { NewsService } from '../../news/news.service';
 import { StateService } from '../state.service';
 import { SubmissionsService } from '../../submissions/submissions.service';
 import { UserService } from '../user.service';
+import { UserChallengeStatusService } from '../user-challenge-status.service';
 import { planetAndParentId } from '../../manager-dashboard/reports/reports.utils';
 
+export const includedCodes = [ 'guatemala', 'san.pablo', 'xela', 'ollonde', 'okuro', 'uriur', 'mutugi', 'vi' ];
+export const challengeCourseId = '9517e3b45a5bb63e69bb8f269216974d';
+export const challengePeriod = (new Date() > new Date(2024, 9, 31)) && (new Date() < new Date(2024, 11, 1));
+
+@Component({
+  template: `
+    <div class="announcement-container">
+      <img
+        src="https://res.cloudinary.com/mutugiii/image/upload/v1730395098/challenge_horizontal_new_tnco4v.jpg"
+        alt="Issues Challenge"
+        class="announcement-banner"
+      />
+      <p class="success-msg">¡Felicidades reto completado!</p>
+    </div>
+  `,
+  styleUrls: [ './dialogs-announcement.component.scss' ]
+})
+export class DialogsAnnouncementSuccessComponent { }
+
 @Component({
   templateUrl: './dialogs-announcement.component.html',
   styleUrls: [ './dialogs-announcement.component.scss' ]
@@ -23,17 +43,13 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   currentUserName = this.userService.get().name;
   configuration = this.stateService.configuration;
   teamId = planetAndParentId(this.stateService.configuration);
-  submissionsSet = new Set();
+  submissions = [];
   groupSummary = [];
   enrolledMembers: any;
-  courseId = '9517e3b45a5bb63e69bb8f269216974d';
+  courseId = challengeCourseId;
   startDate = new Date(2024, 9, 31);
   endDate = new Date(2024, 11, 1);
-  userStatus = {
-    joinedCourse: false,
-    surveyComplete: false,
-    hasPost: false,
-  };
+  isLoading = true;
 
   constructor(
     public dialogRef: MatDialogRef<DialogsAnnouncementComponent>,
@@ -43,15 +59,16 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     private newsService: NewsService,
     private stateService: StateService,
     private submissionsService: SubmissionsService,
-    private userService: UserService
+    private userService: UserService,
+    private userStatusService: UserChallengeStatusService
   ) {}
 
   ngOnInit() {
-    const includedCodes = [ 'guatemala', 'san.pablo', 'xela', 'embakasi', 'uriur' ];
-
     if (includedCodes.includes(this.configuration.code)) {
       this.configuration = this.stateService.configuration;
       this.initializeData();
+    } else {
+      this.isLoading = false;
     }
   }
 
@@ -82,21 +99,52 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   joinCourse() {
     const courseTitle = this.coursesService.getCourseNameFromId(this.courseId);
     this.coursesService.courseResignAdmission(this.courseId, 'admission', courseTitle).subscribe((res) => {
-      this.router.navigate([ '/courses/view', this.courseId ]);
+      this.router.navigate([ `/courses/view/${this.courseId}/step/1` ]);
     }, (error) => ((error)));
     this.dialogRef.close();
   }
 
   doSurvey() {
-    this.router.navigate([ `/courses/view/${this.courseId}/step/3` ]);
+    this.router.navigate([ `/courses/view/${this.courseId}/step/3/exam`, {
+      id: this.courseId,
+      stepNum: 3,
+      questionNum: 1,
+      type: 'survey',
+      preview: 'false',
+      examId: '83fe016d8a983de6f7112e761c014545'
+    } ]);
     this.dialogRef.close();
   }
 
-  postVoice() {
-    this.router.navigate([ '/' ]);
+  chatNShare() {
+    this.router.navigate([ '/chat' ]);
     this.dialogRef.close();
   }
 
+  hasCompletedSurvey(userName: string) {
+    return this.submissions.some(submission => submission.name === userName && submission.status === 'complete');
+  }
+
+  hasSubmittedVoice(news: any[], userName: string) {
+    const uniqueDays = new Set<string>();
+
+    news.forEach(post => {
+      if (
+      post.doc.user.name === userName &&
+      post.doc.time > this.startDate &&
+      post.doc.time < this.endDate &&
+      !post.doc.replyTo
+      ) {
+        uniqueDays.add(new Date(post.doc.time).toDateString());
+      }
+    });
+    return Math.min(uniqueDays.size, 5);
+  }
+
+  hasEnrolledCourse(member) {
+    return member.courseIds.includes(this.courseId);
+  }
+
   fetchEnrolled() {
     this.couchService.findAll('shelf', {
       selector: { courseIds: { $elemMatch: { $eq: this.courseId } } },
@@ -111,24 +159,6 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     });
   }
 
-  hasCompletedSurvey(userName: string) {
-    return this.submissionsSet.has(userName);
-  }
-
-  hasSubmittedVoice(news: any[], userName: string) {
-    return news.some(post => {
-      return (
-      post.doc.user.name === userName &&
-      post.doc.time > this.startDate &&
-      post.doc.time < this.endDate
-      );
-    });
-  }
-
-  hasEnrolledCourse(member) {
-    return member.courseIds.includes(this.courseId);
-  }
-
   fetchCourseAndNews() {
     this.newsService.newsUpdated$.pipe(
       takeUntil(this.onDestroy$)
@@ -147,33 +177,58 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
         this.submissionsService.getSubmissions(findDocuments({ type: 'survey' }))
         .subscribe((submissions: any[]) => {
           const filteredSubmissions = submissions.filter(submission => submission.parentId.includes(this.courseId));
-          this.submissionsSet = new Set(filteredSubmissions.map(submission => submission.user.name));
+          this.submissions = filteredSubmissions.map(submission => ({
+            name: submission.user.name,
+            status: submission.status,
+            time: submission.lastUpdateTime
+          }));
+
 
           // Group Summary
           this.enrolledMembers.forEach((member) => {
-            const hasCompletedSurvey = this.hasCompletedSurvey(member.name);
-            const hasPosted = this.hasSubmittedVoice(news, member.name);
             const hasJoinedCourse = this.hasEnrolledCourse(member);
-
-            if (hasCompletedSurvey && hasPosted && hasJoinedCourse) {
-              this.groupSummary.push(member);
+            const hasCompletedSurvey = this.hasCompletedSurvey(member.name);
+            const hasPosted = this.hasSubmittedVoice(news, member.name) > 0;
+            const userAmount = this.hasSubmittedVoice(news, member.name);
+
+            if (hasCompletedSurvey && hasPosted && hasJoinedCourse && userAmount > 0) {
+              if (!this.groupSummary.some(m => m.name === member.name)) {
+                this.groupSummary.push({
+                  ...member,
+                  amountEarned: userAmount
+                });
+              }
             }
           });
 
           // Individual stats
-          this.userStatus.surveyComplete = this.hasCompletedSurvey(this.currentUserName);
-          this.userStatus.hasPost = this.hasSubmittedVoice(news, this.currentUserName);
+          this.userStatusService.updateStatus('surveyComplete', this.hasCompletedSurvey(this.currentUserName));
+          this.userStatusService.updateStatus('hasPost', this.hasSubmittedVoice(news, this.currentUserName) > 0);
+          this.userStatusService.updateStatus('amountEarned', this.hasSubmittedVoice(news, this.currentUserName));
           this.enrolledMembers.some(member => {
             if (member.name === this.currentUserName) {
-              this.userStatus.joinedCourse = this.hasEnrolledCourse(member);
+              this.userStatusService.updateStatus('joinedCourse', this.hasEnrolledCourse(member));
             }
           });
-        });
-      });
+          this.isLoading = false;
+        }, () => this.isLoading = false);
+      }, () => this.isLoading = false);
+  }
+
+  getTotalMoneyEarned(): number {
+    return this.groupSummary.reduce((total, member) => {
+      const amount = Number(member.amountEarned);
+      return total + (isNaN(amount) ? 0 : amount);
+    }, 0);
   }
 
   getGoalPercentage(): number {
     const goal = 500;
-    return (this.groupSummary?.length / goal) * 100;
+    const totalMoneyEarned = this.getTotalMoneyEarned();
+    return (totalMoneyEarned / goal) * 100;
+  }
+
+  getStatus(key: string) {
+    return this.userStatusService.getStatus(key);
   }
 }
diff --git a/src/app/shared/dialogs/dialogs-chat-share.component.ts b/src/app/shared/dialogs/dialogs-chat-share.component.ts
index d6599a1955..a968fb1b39 100644
--- a/src/app/shared/dialogs/dialogs-chat-share.component.ts
+++ b/src/app/shared/dialogs/dialogs-chat-share.component.ts
@@ -1,7 +1,7 @@
 import { Component, Inject, OnInit, ViewChild } from '@angular/core';
 import { MatStepper } from '@angular/material/stepper';
 import { FormBuilder, FormGroup } from '@angular/forms';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog';
 import { forkJoin } from 'rxjs';
 import { switchMap, map } from 'rxjs/operators';
 
@@ -10,6 +10,8 @@ import { CouchService } from '../../shared/couchdb.service';
 import { NewsService } from '../../news/news.service';
 import { TeamsService } from '../../teams/teams.service';
 import { UserService } from '../../shared/user.service';
+import { UserChallengeStatusService } from '../user-challenge-status.service';
+import { DialogsAnnouncementSuccessComponent } from '../../shared/dialogs/dialogs-announcement.component';
 
 @Component({
   templateUrl: './dialogs-chat-share.component.html',
@@ -44,6 +46,8 @@ export class DialogsChatShareComponent implements OnInit {
     private newsService: NewsService,
     private teamsService: TeamsService,
     private userService: UserService,
+    private dialog: MatDialog,
+    private userStatusService: UserChallengeStatusService,
   ) {
     this.conversation = data || this.conversation;
   }
@@ -139,6 +143,16 @@ export class DialogsChatShareComponent implements OnInit {
     }
     this.conversation.chat = true;
     this.newsService.shareNews(this.conversation, null, $localize`Chat has been successfully shared to community`).subscribe(() => {});
+    if (
+      this.userStatusService.getStatus('joinedCourse') &&
+      this.userStatusService.getStatus('surveyComplete') &&
+      !this.userStatusService.getStatus('hasPost')
+    ) {
+      this.dialog.open(DialogsAnnouncementSuccessComponent, {
+        width: '50vw',
+        maxHeight: '100vh'
+      });
+    }
   }
 
 }
diff --git a/src/app/shared/dialogs/planet-dialogs.module.ts b/src/app/shared/dialogs/planet-dialogs.module.ts
index 0a7f384566..c0f9a4f63b 100644
--- a/src/app/shared/dialogs/planet-dialogs.module.ts
+++ b/src/app/shared/dialogs/planet-dialogs.module.ts
@@ -16,7 +16,7 @@ import { SharedComponentsModule } from '../shared-components.module';
 import { SyncDirective } from '../../manager-dashboard/sync.directive';
 import { DialogsImagesComponent } from './dialogs-images.component';
 import { DialogsVideoComponent } from './dialogs-video.component';
-import { DialogsAnnouncementComponent } from './dialogs-announcement.component';
+import { DialogsAnnouncementComponent, DialogsAnnouncementSuccessComponent } from './dialogs-announcement.component';
 import { DialogsRatingsComponent, DialogsRatingsDirective } from './dialogs-ratings.component';
 
 
@@ -41,8 +41,7 @@ import { DialogsRatingsComponent, DialogsRatingsDirective } from './dialogs-rati
     DialogsRatingsComponent,
     DialogsRatingsDirective,
     ChangePasswordDirective,
-    SyncDirective,
-    DialogsAnnouncementComponent,
+    SyncDirective
   ],
   declarations: [
     DialogsFormComponent,
@@ -57,7 +56,8 @@ import { DialogsRatingsComponent, DialogsRatingsDirective } from './dialogs-rati
     DialogsRatingsDirective,
     ChangePasswordDirective,
     SyncDirective,
-    DialogsAnnouncementComponent
+    DialogsAnnouncementComponent,
+    DialogsAnnouncementSuccessComponent
   ],
   providers: [
     DialogsFormService,
diff --git a/src/app/shared/user-challenge-status.service.ts b/src/app/shared/user-challenge-status.service.ts
new file mode 100644
index 0000000000..5d00649880
--- /dev/null
+++ b/src/app/shared/user-challenge-status.service.ts
@@ -0,0 +1,41 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+    providedIn: 'root'
+})
+export class UserChallengeStatusService {
+  userStatus = {
+    joinedCourse: false,
+    surveyComplete: false,
+    hasPost: false,
+    amountEarned: 0
+  };
+
+  updateStatus(key: string, value: boolean | number) {
+    this.userStatus[key] = value;
+  }
+
+  getCompleteChallenge(): boolean {
+    const complete = Object.values(this.userStatus).every(
+      (value, index) => index !== 3 && value === true
+    );
+    return complete;
+  }
+
+  getStatus(key: string): boolean| number {
+    return this.userStatus[key];
+  }
+
+  printStatus(): any {
+    return this.userStatus;
+  }
+
+  resetStatus() {
+    this.userStatus = {
+      joinedCourse: false,
+      surveyComplete: false,
+      hasPost: false,
+      amountEarned: 0
+    };
+  }
+}

From 937d33ecc3d41f95a7971ec9fb039ab04de2b0c1 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Tue, 19 Nov 2024 11:28:51 -0800
Subject: [PATCH 002/113] courses: smoother steps loading (fixes #7779) (#7781)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |   2 +-
 .../courses-step-view.component.html          |   7 +-
 .../courses-step-view.component.ts            |   2 +
 src/app/exams/exams-view.component.html       | 173 +++++++++---------
 src/app/exams/exams-view.component.ts         |   4 +
 5 files changed, 103 insertions(+), 85 deletions(-)

diff --git a/package.json b/package.json
index d4f944db42..baafe4868b 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.51",
+  "version": "0.15.52",
   "myplanet": {
     "latest": "v0.20.99",
     "min": "v0.19.99"
diff --git a/src/app/courses/step-view-courses/courses-step-view.component.html b/src/app/courses/step-view-courses/courses-step-view.component.html
index 9bff90643b..a08a3a2267 100644
--- a/src/app/courses/step-view-courses/courses-step-view.component.html
+++ b/src/app/courses/step-view-courses/courses-step-view.component.html
@@ -93,6 +93,11 @@ <h3 class="margin-lr-3 ellipsis-title"><ng-container i18n>Step</ng-container> {{
     </ng-template>
   </div>
   <ng-template #emptyRecord>
-    <div class="view-container view-full-height" i18n>No description provided.</div>
+    <div class="view-container view-full-height" i18n>
+      <ng-container *ngIf="isLoading; else noContent">
+        Loading Content...
+      </ng-container>
+      <ng-template #noContent>No description provided.</ng-template>
+    </div>
   </ng-template>
 </div>
diff --git a/src/app/courses/step-view-courses/courses-step-view.component.ts b/src/app/courses/step-view-courses/courses-step-view.component.ts
index eb4b692921..b06c03cff3 100644
--- a/src/app/courses/step-view-courses/courses-step-view.component.ts
+++ b/src/app/courses/step-view-courses/courses-step-view.component.ts
@@ -39,6 +39,7 @@ export class CoursesStepViewComponent implements OnInit, OnDestroy {
   isGridView = true;
   showChat = false;
   isOpenai = false;
+  isLoading = true;
   @ViewChild(MatMenuTrigger) previewButton: MatMenuTrigger;
 
   constructor(
@@ -125,6 +126,7 @@ export class CoursesStepViewComponent implements OnInit, OnDestroy {
         user: this.userService.get(),
         type: 'exam' });
     }
+    this.isLoading = false;
   }
 
   initResources(resources) {
diff --git a/src/app/exams/exams-view.component.html b/src/app/exams/exams-view.component.html
index fd36232ec8..55aa920eae 100644
--- a/src/app/exams/exams-view.component.html
+++ b/src/app/exams/exams-view.component.html
@@ -16,91 +16,98 @@
     <button mat-icon-button [disabled]="questionNum === maxQuestions" (click)="nextQuestion({ nextClicked: true })" [planetSubmit]="spinnerOn"><mat-icon>navigate_next</mat-icon></button>
   </mat-toolbar>
   <div class="view-container" [ngClass]="{ 'view-full-height': !isDialog }">
-    <td-markdown [content]="question?.body"></td-markdown>
-    <div [ngSwitch]="mode">
-      <ng-container *ngSwitchCase="'take'">
-        <ng-container [ngSwitch]="question?.type">
-          <mat-form-field class="full-width" *ngSwitchCase="'input'">
-            <input matInput i18n-placeholder placeholder="Enter answer here" [formControl]="answer">
-          </mat-form-field>
-          <mat-form-field *ngSwitchCase="'textarea'" class="full-width mat-form-field-type-no-underline">
-            <planet-markdown-textbox [formControl]="answer"></planet-markdown-textbox>
-          </mat-form-field>
-          <mat-radio-group *ngSwitchCase="'select'" class="question-list" [formControl]="answer">
-            <mat-radio-button [value]="option" *ngFor="let option of question?.choices">
-              <span class="multiple-choice-text">{{option.text}}</span>
-            </mat-radio-button>
-          </mat-radio-group>
-          <div *ngSwitchCase="'selectMultiple'" class="question-list">
-            <span class="mat-caption" i18n>
-              {examType, select, survey {You can choose one or more answers.} exam {There are one or more correct answers. Please choose all correct answers.}}
-            </span>
-            <mat-checkbox *ngFor="let option of question?.choices" [value]="option" (change)="setAnswer($event, option)" [checked]="checkboxState[option.id]">
-              <span class="multiple-choice-text">{{option.text}}</span>
-            </mat-checkbox>
-          </div>
+    <ng-container *ngIf="!isLoading; else LoadingContent">
+      <td-markdown [content]="question?.body"></td-markdown>
+      <div [ngSwitch]="mode">
+        <ng-container *ngSwitchCase="'take'">
+          <ng-container [ngSwitch]="question?.type">
+            <mat-form-field class="full-width" *ngSwitchCase="'input'">
+              <input matInput i18n-placeholder placeholder="Enter answer here" [formControl]="answer">
+            </mat-form-field>
+            <mat-form-field *ngSwitchCase="'textarea'" class="full-width mat-form-field-type-no-underline">
+              <planet-markdown-textbox [formControl]="answer"></planet-markdown-textbox>
+            </mat-form-field>
+            <mat-radio-group *ngSwitchCase="'select'" class="question-list" [formControl]="answer">
+              <mat-radio-button [value]="option" *ngFor="let option of question?.choices">
+                <span class="multiple-choice-text">{{option.text}}</span>
+              </mat-radio-button>
+            </mat-radio-group>
+            <div *ngSwitchCase="'selectMultiple'" class="question-list">
+              <span class="mat-caption" i18n>
+                {examType, select, survey {You can choose one or more answers.} exam {There are one or more correct answers. Please choose all correct answers.}}
+              </span>
+              <mat-checkbox *ngFor="let option of question?.choices" [value]="option" (change)="setAnswer($event, option)" [checked]="checkboxState[option.id]">
+                <span class="multiple-choice-text">{{option.text}}</span>
+              </mat-checkbox>
+            </div>
+          </ng-container>
         </ng-container>
-      </ng-container>
-      <ng-container *ngSwitchCase="'grade'">
-        <p><b i18n>Submitted answer:</b></p>
-        <td-markdown [content]="answer?.value?.text || answer?.value"></td-markdown>
-        <mat-radio-group [(ngModel)]="grade" [disabled]="question?.type === 'select' || question?.type === 'selectMultiple'">
-          <mat-radio-button [value]="1" class="planet-radio-button" i18n>Correct</mat-radio-button>
-          <mat-radio-button [value]="0" class="planet-radio-button" i18n>Incorrect</mat-radio-button>
-        </mat-radio-group>
-        <mat-form-field class="full-width mat-form-field-type-no-underline">
-          <planet-markdown-textbox class="full-width" i18n-placeholder placeholder="Comment" [(ngModel)]="comment"></planet-markdown-textbox>
-        </mat-form-field>
-      </ng-container>
-      <ng-container *ngSwitchCase="'view'">
-        <p><b i18n>Response:</b></p>
-        <td-markdown [content]="answer?.value?.text || answer?.value"></td-markdown>
-        <ng-container *ngIf="grade>=0">
-          <p><b i18n>Grade:</b></p>
-          <p *ngIf="grade===1" i18n>Correct</p>
-          <p *ngIf="grade===0" i18n>Incorrect</p>
+        <ng-container *ngSwitchCase="'grade'">
+          <p><b i18n>Submitted answer:</b></p>
+          <td-markdown [content]="answer?.value?.text || answer?.value"></td-markdown>
+          <mat-radio-group [(ngModel)]="grade" [disabled]="question?.type === 'select' || question?.type === 'selectMultiple'">
+            <mat-radio-button [value]="1" class="planet-radio-button" i18n>Correct</mat-radio-button>
+            <mat-radio-button [value]="0" class="planet-radio-button" i18n>Incorrect</mat-radio-button>
+          </mat-radio-group>
+          <mat-form-field class="full-width mat-form-field-type-no-underline">
+            <planet-markdown-textbox class="full-width" i18n-placeholder placeholder="Comment" [(ngModel)]="comment"></planet-markdown-textbox>
+          </mat-form-field>
         </ng-container>
-        <ng-container *ngIf="comment">
-          <p><b i18n>Feedback:</b></p>
-          <td-markdown [content]="comment"></td-markdown>
+        <ng-container *ngSwitchCase="'view'">
+          <p><b i18n>Response:</b></p>
+          <td-markdown [content]="answer?.value?.text || answer?.value"></td-markdown>
+          <ng-container *ngIf="grade>=0">
+            <p><b i18n>Grade:</b></p>
+            <p *ngIf="grade===1" i18n>Correct</p>
+            <p *ngIf="grade===0" i18n>Incorrect</p>
+          </ng-container>
+          <ng-container *ngIf="comment">
+            <p><b i18n>Feedback:</b></p>
+            <td-markdown [content]="comment"></td-markdown>
+          </ng-container>
         </ng-container>
-      </ng-container>
-    </div>
-    <div class="v-align-center action-buttons">
-      <button
-        *ngIf="mode !== 'view'"
-        mat-raised-button
-        color="primary"
-        (click)="nextQuestion()"
-        [planetSubmit]="spinnerOn"
-        [disabled]="!answer.valid || grade === undefined || grade === null">
-        <ng-container i18n>Submit Answer</ng-container>
-      </button>
-      <button
-        *ngIf="mode === 'take'"
-        mat-raised-button
-        color="accent"
-        (click)="nextQuestion({ isFinish: true })"
-        [disabled]="!isComplete || !answer.valid || grade === undefined || grade === null"
-        i18n>
-        {examType, select, survey {Finish Survey} exam {Finish Test}}
-      </button>
-      <span class="v-align-center small" [ngSwitch]="statusMessage">
-        <div *ngSwitchCase="'incorrect'" class="warn-text-color">
-          <mat-icon>error</mat-icon><span i18n>Incorrect answer, please try again</span>
-        </div>
-        <div *ngSwitchCase="'complete'" class="primary-text-color">
-          <mat-icon>check_circle</mat-icon>
-          <span>
-            <ng-container i18n>{examType, select, survey {Survey is complete.} exam {Test is complete.}}</ng-container>
-            {{' '}}
-            <ng-container i18n *ngIf="previewMode; else finishExam">You can close the preview.</ng-container>
-            <ng-template #finishExam>
-              <ng-container i18n>{examType, select, survey {Click Finish Survey to submit for review.} exam {Click Finish Test to submit for review.}}</ng-container>
-            </ng-template>
-          </span>
-        </div>
-      </span>
-    </div>
+      </div>
+      <div class="v-align-center action-buttons">
+        <button
+          *ngIf="mode !== 'view'"
+          mat-raised-button
+          color="primary"
+          (click)="nextQuestion()"
+          [planetSubmit]="spinnerOn"
+          [disabled]="!answer.valid || grade === undefined || grade === null">
+          <ng-container i18n>Submit Answer</ng-container>
+        </button>
+        <button
+          *ngIf="mode === 'take'"
+          mat-raised-button
+          color="accent"
+          (click)="nextQuestion({ isFinish: true })"
+          [disabled]="!isComplete || !answer.valid || grade === undefined || grade === null"
+          i18n>
+          {examType, select, survey {Finish Survey} exam {Finish Test}}
+        </button>
+        <span class="v-align-center small" [ngSwitch]="statusMessage">
+          <div *ngSwitchCase="'incorrect'" class="warn-text-color">
+            <mat-icon>error</mat-icon><span i18n>Incorrect answer, please try again</span>
+          </div>
+          <div *ngSwitchCase="'complete'" class="primary-text-color">
+            <mat-icon>check_circle</mat-icon>
+            <span>
+              <ng-container i18n>{examType, select, survey {Survey is complete.} exam {Test is complete.}}</ng-container>
+              {{' '}}
+              <ng-container i18n *ngIf="previewMode; else finishExam">You can close the preview.</ng-container>
+              <ng-template #finishExam>
+                <ng-container i18n>{examType, select, survey {Click Finish Survey to submit for review.} exam {Click Finish Test to submit for review.}}</ng-container>
+              </ng-template>
+            </span>
+          </div>
+        </span>
+      </div>
+    </ng-container>
+    <ng-template #LoadingContent>
+      <div i18n>
+        Loading content...
+      </div>
+    </ng-template>
   </div>
 </div>
diff --git a/src/app/exams/exams-view.component.ts b/src/app/exams/exams-view.component.ts
index 244c0df035..563efc7bc5 100644
--- a/src/app/exams/exams-view.component.ts
+++ b/src/app/exams/exams-view.component.ts
@@ -48,6 +48,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
   unansweredQuestions: number[];
   isComplete = false;
   comment: string;
+  isLoading = true;
   courseId: string;
 
   constructor(
@@ -126,6 +127,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
       this.updatedOn = this.submission.lastUpdateTime;
       this.setViewAnswerText(this.submission.answers[this.questionNum - 1]);
     }
+    this.isLoading = false;
   }
 
   nextQuestion({ nextClicked = false, isFinish = false }: { nextClicked?: boolean, isFinish?: boolean } = {}) {
@@ -196,6 +198,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
   }
 
   goBack() {
+    this.isLoading = false;
     this.router.navigate([ '../',
       this.mode === 'take' ? {} :
       { type: this.mode === 'grade' ? 'exam' : 'survey' }
@@ -232,6 +235,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
       const type = this.examType;
       const takingExam = exam ? exam : step[type];
       this.setTakingExam(takingExam, takingExam._id + '@' + course._id, type);
+      this.isLoading = false;
     });
   }
 

From 3d2f3aabbf9ff5b3f2a0eb11f7fd2842b56de977 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Tue, 19 Nov 2024 11:34:53 -0800
Subject: [PATCH 003/113] resources: smoother collection tags (fixes #5776)
 (#7778)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                     |  2 +-
 .../forms/planet-tag-input-dialog.component.ts   | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index baafe4868b..98c1229c3d 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.52",
+  "version": "0.15.53",
   "myplanet": {
     "latest": "v0.20.99",
     "min": "v0.19.99"
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.ts b/src/app/shared/forms/planet-tag-input-dialog.component.ts
index 6c335053c1..fdff521c14 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.ts
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.ts
@@ -203,6 +203,7 @@ export class PlanetTagInputDialogComponent {
         this.data.initTags();
         this.deleteDialog.close();
         this.planetMessageService.showMessage($localize`Tag deleted: ${tag.name}`);
+        this.resetValidationAndCheck(this.addTagForm);
       },
       onError: (error) => this.planetMessageService.showAlert($localize`There was a problem deleting this tag.`)
     };
@@ -230,6 +231,21 @@ export class PlanetTagInputDialogComponent {
     );
   }
 
+  resetValidationAndCheck(form: FormGroup) {
+    Object.keys(form.controls).forEach(key => {
+      const control = form.get(key);
+      control?.clearValidators();
+
+      if (key === 'name') {
+        control?.setValidators(this.tagNameSyncValidator());
+        control?.setAsyncValidators(ac => this.tagNameAsyncValidator(ac));
+      }
+
+      control?.markAsUntouched();
+      control?.updateValueAndValidity();
+    });
+  }
+
   toggleSubcollection(event, tagId) {
     event.stopPropagation();
     const newState = !this.subcollectionIsOpen.get(tagId);

From ed1bb2d10d085e21f86c29f80f28b54e519af65d Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 19 Nov 2024 14:38:43 -0500
Subject: [PATCH 004/113] mylife: smoother achievements (fixes #7782) (#7783)

Co-authored-by: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                       |  2 +-
 .../users-achievements.component.html              |  4 ++--
 .../users-achievements/users-achievements.scss     | 14 +++++++++++++-
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 98c1229c3d..a691fc9ad5 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.53",
+  "version": "0.15.54",
   "myplanet": {
     "latest": "v0.20.99",
     "min": "v0.19.99"
diff --git a/src/app/users/users-achievements/users-achievements.component.html b/src/app/users/users-achievements/users-achievements.component.html
index 8988c3abc6..ff40b83dad 100644
--- a/src/app/users/users-achievements/users-achievements.component.html
+++ b/src/app/users/users-achievements/users-achievements.component.html
@@ -39,7 +39,7 @@ <h3 i18n>My Goals</h3>
       <ng-container *planetBeta>
         <div *ngIf="certifications.length > 0">
           <h3 i18n>My Certifications</h3>
-          <mat-list>
+          <mat-list class="certs-list">
             <mat-list-item *ngFor="let certification of certifications">
               {{certification.name}}
             </mat-list-item>
@@ -79,7 +79,7 @@ <h3 i18n>My Achievements</h3>
       </div>
       <div *ngIf="achievements.references.length > 0">
         <h3 i18n>My References</h3>
-        <mat-list>
+        <mat-list class="references-list">
           <mat-list-item class="mat-list-item-word-wrap" *ngFor="let reference of achievements.references">
             <h4 mat-line>{{reference.name}}</h4>
             <p mat-line *ngIf="reference?.relationship"><ng-container i18n>Relationship:</ng-container> {{reference.relationship}}</p>
diff --git a/src/app/users/users-achievements/users-achievements.scss b/src/app/users/users-achievements/users-achievements.scss
index f99e871f44..17470dd780 100644
--- a/src/app/users/users-achievements/users-achievements.scss
+++ b/src/app/users/users-achievements/users-achievements.scss
@@ -5,6 +5,18 @@
   margin: 0 auto;
   text-align: center;
 
+  .references-list {
+    display: flex;
+    justify-content: center;
+    text-align: center;
+  }
+
+  .certs-list .mat-list-item{
+    display: flex;
+    justify-content: center;
+    text-align: center;
+  }
+
   & mat-list, & ul, & ol {
     text-align: left;
   }
@@ -105,4 +117,4 @@
   .center-text div {
     margin: 0 auto;
   }
-}
\ No newline at end of file
+}

From fc1c01b9cc40be11e3171f508e9649fb79ffde22 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Tue, 19 Nov 2024 11:44:19 -0800
Subject: [PATCH 005/113] teams: smoother voices creation (fixes #4800) (#7793)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                      | 2 +-
 src/app/shared/forms/planet-markdown-textbox.scss | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index a691fc9ad5..482d6f2ca5 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.54",
+  "version": "0.15.55",
   "myplanet": {
     "latest": "v0.20.99",
     "min": "v0.19.99"
diff --git a/src/app/shared/forms/planet-markdown-textbox.scss b/src/app/shared/forms/planet-markdown-textbox.scss
index cac82c94c1..9ef7201751 100644
--- a/src/app/shared/forms/planet-markdown-textbox.scss
+++ b/src/app/shared/forms/planet-markdown-textbox.scss
@@ -36,6 +36,7 @@ planet-markdown-textbox {
   }
 
   .editor-statusbar {
+    opacity: 0;
     margin-bottom: -2.75em;
   }
 

From 99b77d1ff36d5bace127591ea6fbca7aafc4c8e4 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 20 Nov 2024 12:57:50 -0800
Subject: [PATCH 006/113] dashboard: complete profile reminder (fixes #7758)
 (#7765)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                               |  6 ++--
 src/app/dashboard/dashboard.component.html |  6 ++++
 src/app/dashboard/dashboard.component.ts   | 33 +++++++++++++++-----
 src/app/dashboard/dashboard.scss           | 36 +++++++++++++++++++++-
 src/app/shared/user.service.ts             | 10 ++++++
 5 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/package.json b/package.json
index 482d6f2ca5..f54ab96bcf 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.55",
+  "version": "0.15.56",
   "myplanet": {
-    "latest": "v0.20.99",
-    "min": "v0.19.99"
+    "latest": "v0.21.2",
+    "min": "v0.20.2"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html
index 292b296d2b..942932614c 100644
--- a/src/app/dashboard/dashboard.component.html
+++ b/src/app/dashboard/dashboard.component.html
@@ -1,3 +1,9 @@
+<div *ngIf="showBanner" class="alert">
+  <a [routerLink]="['/users/update', user.name]">
+    <span class="banner-text" i18n>Please complete your profile to enjoy full features!</span>
+  </a>
+  <span class="closebtn" (click)="closeBanner()">&times;</span>
+</div>
 <mat-card class="horizontal">
   <img [src]="profileImg">
   <div class="dashboard-name">
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts
index e6ccedd30d..5b462ae6c1 100644
--- a/src/app/dashboard/dashboard.component.ts
+++ b/src/app/dashboard/dashboard.component.ts
@@ -22,8 +22,9 @@ import { CertificationsService } from '../manager-dashboard/certifications/certi
 })
 export class DashboardComponent implements OnInit, OnDestroy {
 
+  user = this.userService.get();
   data = { resources: [], courses: [], meetups: [], myTeams: [] };
-  urlPrefix = environment.couchAddress + '/_users/org.couchdb.user:' + this.userService.get().name + '/';
+  urlPrefix = environment.couchAddress + '/_users/org.couchdb.user:' + this.user.name + '/';
   displayName: string;
   roles: string[];
   planetName: string;
@@ -37,6 +38,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
   examsCount = 0;
   leaderIds = [];
   onDestroy$ = new Subject<void>();
+  showBanner = false;
 
   myLifeItems: any[] = [
     { firstLine: $localize`my`, title: $localize`Submissions`, link: 'submissions', authorization: 'leader,manager',
@@ -57,7 +59,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
     private certificationsService: CertificationsService,
     private dialog: MatDialog
   ) {
-    const currRoles = this.userService.get().roles;
+    const currRoles = this.user.roles;
     this.roles = currRoles.reduce(dedupeShelfReduce, currRoles.length ? [ 'learner' ] : [ 'Inactive' ]);
     this.userService.shelfChange$.pipe()
       .subscribe(() => {
@@ -74,13 +76,12 @@ export class DashboardComponent implements OnInit, OnDestroy {
   }
 
   ngOnInit() {
-    const user = this.userService.get();
-    this.displayName = user.firstName !== undefined ? user.firstName + ' ' + user.lastName : user.name;
+    this.displayName = this.user.firstName !== undefined ? this.user.firstName + ' ' + this.user.lastName : this.user.name;
     this.planetName = this.stateService.configuration.name;
     this.getSurveys();
     this.getExams();
     this.initDashboard();
-    this.couchService.findAll('login_activities', findDocuments({ 'user': this.userService.get().name }, [ 'user' ], [], 1000))
+    this.couchService.findAll('login_activities', findDocuments({ 'user': this.user.name }, [ 'user' ], [], 1000))
       .pipe(
         catchError(() => {
           return of([]);
@@ -88,6 +89,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
       ).subscribe((res: any) => {
         this.visits = res.length;
       });
+    this.reminderBanner();
   }
 
   ngOnDestroy() {
@@ -132,7 +134,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
   getTeamMembership() {
     const configuration = this.stateService.configuration;
     return this.couchService.findAll(
-      'teams', findDocuments({ userPlanetCode: configuration.code, userId: this.userService.get()._id, docType: 'membership' })
+      'teams', findDocuments({ userPlanetCode: configuration.code, userId: this.user._id, docType: 'membership' })
     ).pipe(
       switchMap((memberships) => forkJoin([
         of(memberships),
@@ -147,7 +149,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
   }
 
   get profileImg() {
-    const attachments = this.userService.get()._attachments;
+    const attachments = this.user._attachments;
     if (attachments) {
       return this.urlPrefix + Object.keys(attachments)[0];
     }
@@ -170,7 +172,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
   }
 
   getSurveys() {
-    this.getSubmissions('survey', 'pending', this.userService.get().name).subscribe((surveys) => {
+    this.getSubmissions('survey', 'pending', this.user.name).subscribe((surveys) => {
       this.surveysCount = dedupeObjectArray(surveys, [ 'parentId' ]).length;
       this.myLifeItems = this.myLifeItems.map(item => item.link === 'mySurveys' ? { ...item, badge: this.surveysCount } : item);
     });
@@ -211,4 +213,19 @@ export class DashboardComponent implements OnInit, OnDestroy {
     this.badgeGroups = [ ...foundations, 'none' ].filter(group => this.badgesCourses[group] && this.badgesCourses[group].length);
   }
 
+  reminderBanner() {
+    this.userService.isProfileComplete();
+    combineLatest([
+      this.userService.profileBanner,
+      this.userService.profileComplete$
+    ]).pipe(takeUntil(this.onDestroy$)).subscribe(([ profileBanner, profileComplete ]) => {
+      this.showBanner = profileBanner && !profileComplete;
+    });
+  }
+
+  closeBanner() {
+    this.userService.profileBanner.next(false);
+    this.showBanner = false;
+  }
+
 }
diff --git a/src/app/dashboard/dashboard.scss b/src/app/dashboard/dashboard.scss
index 5640f7923b..2f1edbe817 100644
--- a/src/app/dashboard/dashboard.scss
+++ b/src/app/dashboard/dashboard.scss
@@ -93,7 +93,41 @@ $top-row-height: calc(#{$dashboard-tile-width} + 0.5rem);
     p {
       margin: 0;
     }
-
   }
+}
+
+.alert {
+  position: fixed;
+  top: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+  width: 90%;
+  padding: 20px;
+  background-color: #fdee7f;
+  color: rgb(0, 0, 0);
+  text-align: center;
+  border-radius: 8px;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
+  z-index: 1000;
+}
+
+.banner-text {
+  display: block;
+  margin: 0 2rem;
+}
+
+.closebtn {
+  position: absolute;
+  right: 15px;
+  top: 50%;
+  transform: translateY(-50%);
+  color: rgb(126, 126, 126);
+  font-weight: bold;
+  font-size: 22px;
+  cursor: pointer;
+  transition: 0.5s;
+}
 
+.closebtn:hover {
+  color: rgb(0, 0, 0);
 }
diff --git a/src/app/shared/user.service.ts b/src/app/shared/user.service.ts
index 091f8208d5..172de224c9 100644
--- a/src/app/shared/user.service.ts
+++ b/src/app/shared/user.service.ts
@@ -46,6 +46,10 @@ export class UserService {
   userLogout$ = this.userLogout.asObservable();
   private notificationStateChange = new Subject<void>();
   notificationStateChange$ = this.notificationStateChange.asObservable();
+  profileComplete = new BehaviorSubject<boolean>(false);
+  profileComplete$ = this.profileComplete.asObservable();
+  profileBanner = new BehaviorSubject<boolean>(true);
+  profileBanner$ = this.profileBanner.asObservable();
   minBirthDate = new Date(1900, 0, 1);
 
 
@@ -295,4 +299,10 @@ export class UserService {
     })));
   }
 
+  isProfileComplete() {
+    const isComplete = !!(this.user.firstName && this.user.lastName && this.user.email && this.user.birthDate &&
+      this.user.gender && this.user.language && this.user.phoneNumber && this.user.level);
+    this.profileComplete.next(isComplete);
+  }
+
 }

From 1c7b9554a41184426e3840119ffb66618ef22f50 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 20 Nov 2024 16:09:11 -0500
Subject: [PATCH 007/113] courses: smoother resuming (fixes #2716) (#7794)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                          |  2 +-
 src/app/exams/exams-view.component.ts | 20 ++++++++++++++++----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index f54ab96bcf..d9305172f8 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.56",
+  "version": "0.15.57",
   "myplanet": {
     "latest": "v0.21.2",
     "min": "v0.20.2"
diff --git a/src/app/exams/exams-view.component.ts b/src/app/exams/exams-view.component.ts
index 563efc7bc5..380bcb1937 100644
--- a/src/app/exams/exams-view.component.ts
+++ b/src/app/exams/exams-view.component.ts
@@ -48,6 +48,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
   unansweredQuestions: number[];
   isComplete = false;
   comment: string;
+  initialLoad = true;
   isLoading = true;
   courseId: string;
 
@@ -133,7 +134,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
   nextQuestion({ nextClicked = false, isFinish = false }: { nextClicked?: boolean, isFinish?: boolean } = {}) {
     const { correctAnswer, obs }: { correctAnswer?: boolean | undefined, obs: any } = this.createAnswerObservable(isFinish);
     const previousStatus = this.previewMode ? 'preview' : this.submissionsService.submission.status;
-    // Only navigate away from page until after successful post (ensures DB is updated for submission list)
+// Only navigate away from page until after successful post (ensures DB is updated for submission list)
     obs.subscribe(({ nextQuestion }) => {
       if (correctAnswer === false) {
         this.statusMessage = 'incorrect';
@@ -141,7 +142,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
         this.question.choices.forEach(choice => this.checkboxState[choice.id] = false);
         this.spinnerOn = false;
       } else {
-        this.routeToNext(nextClicked ? this.questionNum : nextQuestion, previousStatus);
+        this.routeToNext(nextQuestion, previousStatus);
         // Challenge option only
         if (
           isFinish &&
@@ -255,6 +256,17 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
         this.grade = (ans && ans.grade !== undefined) ? ans.grade : this.grade;
         this.comment = ans && ans.gradeComment;
       }
+      if (this.initialLoad && this.mode === 'take' && this.unansweredQuestions.length > 0) {
+        const nextUnansweredQuestion = this.unansweredQuestions[0];
+        if (this.questionNum !== nextUnansweredQuestion) {
+          this.questionNum = nextUnansweredQuestion;
+          this.router.navigate([ {
+            ...this.route.snapshot.params,
+            questionNum: this.questionNum
+          } ], { relativeTo: this.route });
+        }
+        this.initialLoad = false;
+      }
       if (this.mode === 'take' && this.isNewQuestion) {
         this.setAnswerForRetake(ans);
       } else if (this.mode !== 'take') {
@@ -262,8 +274,8 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
       }
       this.isNewQuestion = false;
       this.isComplete = this.unansweredQuestions && this.unansweredQuestions.every(number => this.questionNum === number);
-    });
-  }
+  });
+}
 
   setAnswer(event, option) {
     this.answer.setValue(Array.isArray(this.answer.value) ? this.answer.value : []);

From 544d562b5ea1080a43add7d4be31f4d5e22f28dd Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Fri, 22 Nov 2024 00:17:18 +0300
Subject: [PATCH 008/113] all: smoother challenge validation (fixes #7822)
 (#7824)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                      |  2 +-
 .../dialogs/dialogs-announcement.component.html   |  4 ++--
 .../dialogs/dialogs-announcement.component.ts     | 15 +++++++++------
 src/app/shared/user-challenge-status.service.ts   |  4 ++--
 4 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/package.json b/package.json
index d9305172f8..882b45a62b 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.57",
+  "version": "0.15.58",
   "myplanet": {
     "latest": "v0.21.2",
     "min": "v0.20.2"
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.html b/src/app/shared/dialogs/dialogs-announcement.component.html
index 4998d47191..f06747ea37 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.html
+++ b/src/app/shared/dialogs/dialogs-announcement.component.html
@@ -49,7 +49,7 @@
         <mat-icon color="primary">
           {{ getStatus('hasPost') ? 'check_circle' : 'radio_button_unchecked' }}
         </mat-icon>
-        <span>Comparte tu opinión en Nuestras Voces. <br><span>{{getStatus('amountEarned')}} de 5 Voces diarias</span> </span>
+        <span>Comparte tu opinión en Nuestras Voces. <br><span>{{getStatus('userPosts')}} de 5 Voces diarias</span> </span>
         <a *ngIf="getStatus('joinedCourse') && getStatus('surveyComplete') && !getStatus('hasPost'); else dailyVoices" mat-button mat-raised-button color="primary" type="button" (click)="chatNShare()">
           Chatea y comparte
         </a>
@@ -58,7 +58,7 @@
             <div
               *ngFor="let dot of [0, 1, 2, 3, 4]; let i = index"
               class="dot"
-              [ngClass]="{ completed: i < getStatus('amountEarned') }"
+              [ngClass]="{ completed: i < getStatus('userPosts') }"
             ></div>
           </div>
         </ng-template>
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.ts b/src/app/shared/dialogs/dialogs-announcement.component.ts
index 9f45a636d3..780fe1caf3 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.ts
+++ b/src/app/shared/dialogs/dialogs-announcement.component.ts
@@ -50,6 +50,8 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   startDate = new Date(2024, 9, 31);
   endDate = new Date(2024, 11, 1);
   isLoading = true;
+  submissionValue = 5;
+  goal = 500;
 
   constructor(
     public dialogRef: MatDialogRef<DialogsAnnouncementComponent>,
@@ -195,7 +197,7 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
               if (!this.groupSummary.some(m => m.name === member.name)) {
                 this.groupSummary.push({
                   ...member,
-                  amountEarned: userAmount
+                  userPosts: userAmount
                 });
               }
             }
@@ -204,7 +206,7 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
           // Individual stats
           this.userStatusService.updateStatus('surveyComplete', this.hasCompletedSurvey(this.currentUserName));
           this.userStatusService.updateStatus('hasPost', this.hasSubmittedVoice(news, this.currentUserName) > 0);
-          this.userStatusService.updateStatus('amountEarned', this.hasSubmittedVoice(news, this.currentUserName));
+          this.userStatusService.updateStatus('userPosts', this.hasSubmittedVoice(news, this.currentUserName));
           this.enrolledMembers.some(member => {
             if (member.name === this.currentUserName) {
               this.userStatusService.updateStatus('joinedCourse', this.hasEnrolledCourse(member));
@@ -216,16 +218,17 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   }
 
   getTotalMoneyEarned(): number {
-    return this.groupSummary.reduce((total, member) => {
-      const amount = Number(member.amountEarned);
+    const totalEarned = this.groupSummary.reduce((total, member) => {
+      const amount = Number(member.userPosts * this.submissionValue);
       return total + (isNaN(amount) ? 0 : amount);
     }, 0);
+
+    return Math.min(totalEarned, this.goal);
   }
 
   getGoalPercentage(): number {
-    const goal = 500;
     const totalMoneyEarned = this.getTotalMoneyEarned();
-    return (totalMoneyEarned / goal) * 100;
+    return (totalMoneyEarned / this.goal) * 100;
   }
 
   getStatus(key: string) {
diff --git a/src/app/shared/user-challenge-status.service.ts b/src/app/shared/user-challenge-status.service.ts
index 5d00649880..7825124d62 100644
--- a/src/app/shared/user-challenge-status.service.ts
+++ b/src/app/shared/user-challenge-status.service.ts
@@ -8,7 +8,7 @@ export class UserChallengeStatusService {
     joinedCourse: false,
     surveyComplete: false,
     hasPost: false,
-    amountEarned: 0
+    userPosts: 0
   };
 
   updateStatus(key: string, value: boolean | number) {
@@ -35,7 +35,7 @@ export class UserChallengeStatusService {
       joinedCourse: false,
       surveyComplete: false,
       hasPost: false,
-      amountEarned: 0
+      userPosts: 0
     };
   }
 }

From a8da2c713c4eca364dc69d6a06ca7e320f17406e Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:27:56 -0500
Subject: [PATCH 009/113] courses: smoother menu entries (fixes #4019) (#7790)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                           | 6 +++---
 src/app/courses/courses.component.html | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 882b45a62b..146e4f48c9 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.58",
+  "version": "0.15.59",
   "myplanet": {
-    "latest": "v0.21.2",
-    "min": "v0.20.2"
+    "latest": "v0.21.4",
+    "min": "v0.20.4"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/courses.component.html b/src/app/courses/courses.component.html
index 23a4ab5adb..840bcd8da2 100644
--- a/src/app/courses/courses.component.html
+++ b/src/app/courses/courses.component.html
@@ -180,8 +180,8 @@ <h3 class="header">
               <span i18n>Feedback</span>
             </a>
             <a mat-menu-item *ngIf="element.canManage" (click)="updateCourse(element.doc)">
-              <mat-icon>folder</mat-icon>
-              <span i18n>Manage</span>
+              <mat-icon>edit</mat-icon>
+              <span i18n>Edit Course</span>
             </a>
             <a mat-menu-item [routerLink]="['/courses/view', element._id]">
               <mat-icon>visibility</mat-icon>

From 4770eaa2d0d64158ce06bf7543d2e2282432fcab Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:32:16 -0500
Subject: [PATCH 010/113] dashboard: smoother avatar linking (fixes #4532)
 (#7792)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                               |  2 +-
 src/app/dashboard/dashboard.component.html | 52 +++++++++++++---------
 src/app/dashboard/dashboard.component.ts   |  3 +-
 3 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/package.json b/package.json
index 146e4f48c9..d0f090ef0f 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.59",
+  "version": "0.15.60",
   "myplanet": {
     "latest": "v0.21.4",
     "min": "v0.20.4"
diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html
index 942932614c..ffa7443106 100644
--- a/src/app/dashboard/dashboard.component.html
+++ b/src/app/dashboard/dashboard.component.html
@@ -4,28 +4,38 @@
   </a>
   <span class="closebtn" (click)="closeBanner()">&times;</span>
 </div>
-<mat-card class="horizontal">
-  <img [src]="profileImg">
-  <div class="dashboard-name">
-    <h1 class="mat-title">{{displayName}}  ({{visits | number}})</h1>
-    <h1 class="mat-title">
-      <span class="mat-subheading-2"><ng-container *ngFor="let role of roles; last as last">
-        <planet-role [role]="role"></planet-role><span *ngIf="!last">, </span>
-      </ng-container></span>
-    </h1>
-  </div>
-  <div class="date">
-    <p>{{dateNow | date:'longDate'}}</p>
+<mat-card class="horizontal" style="display: flex; flex-direction: row; justify-content: space-between; align-items: flex-start;">
+  <div style="display: flex; align-items: flex-start;">
+    <a [routerLink]="['/users/profile', user.name]" class="profile-link">
+      <img [src]="profileImg" class="profile-avatar">
+    </a>
+    <div class="dashboard-name" style="margin-left: 16px;">
+      <a [routerLink]="['/users/profile', user.name]" class="profile-link">
+        <h1 class="mat-title">{{displayName}} ({{visits | number}})</h1>
+      </a>
+      <h1 class="mat-title">
+        <span class="mat-subheading-2">
+          <ng-container *ngFor="let role of roles; last as last">
+            <planet-role [role]="role"></planet-role><span *ngIf="!last">, </span>
+          </ng-container>
+        </span>
+      </h1>
+    </div>
   </div>
-  <div class="badges">
-    <div *ngFor="let badgeGroup of badgeGroups">
-      <span *ngFor="let course of badgesCourses[badgeGroup]" class="cursor-pointer" (click)="openCourseView(course)" [matTooltip]="course.doc.courseTitle">
-        <mat-icon
-          [ngClass]="{ 'primary-text-color': course.inCertification, 'grey-text-color': !course.inCertification }"
-          fontSet="fa"
-          [fontIcon]="badgeIcons[badgeGroup]">
-        </mat-icon>
-      </span>
+  <div style="display: flex; flex-direction: column; align-items: flex-end;">
+    <div class="date" style="text-align: right;">
+      <p>{{dateNow | date:'longDate'}}</p>
+    </div>
+    <div class="badges" style="display: flex; flex-wrap: wrap; justify-content: flex-end; max-width: 100%; margin-top: 8px;">
+      <div *ngFor="let badgeGroup of badgeGroups" style="margin-right: 4px;">
+        <span *ngFor="let course of badgesCourses[badgeGroup]" class="cursor-pointer" (click)="openCourseView(course)" [matTooltip]="course.doc.courseTitle">
+          <mat-icon
+            [ngClass]="{ 'primary-text-color': course.inCertification, 'grey-text-color': !course.inCertification }"
+            fontSet="fa"
+            [fontIcon]="badgeIcons[badgeGroup]">
+          </mat-icon>
+        </span>
+      </div>
     </div>
   </div>
 </mat-card>
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts
index 5b462ae6c1..97ff21b988 100644
--- a/src/app/dashboard/dashboard.component.ts
+++ b/src/app/dashboard/dashboard.component.ts
@@ -76,7 +76,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
   }
 
   ngOnInit() {
-    this.displayName = this.user.firstName !== undefined ? this.user.firstName + ' ' + this.user.lastName : this.user.name;
+    this.displayName = this.user.firstName !== undefined ? `${this.user.firstName} ${this.user.lastName}` : this.user.name;
     this.planetName = this.stateService.configuration.name;
     this.getSurveys();
     this.getExams();
@@ -84,6 +84,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
     this.couchService.findAll('login_activities', findDocuments({ 'user': this.user.name }, [ 'user' ], [], 1000))
       .pipe(
         catchError(() => {
+          console.warn('Error fetching login activities');
           return of([]);
         })
       ).subscribe((res: any) => {

From 2f111054f2724ddbb2dd68d5b3a90a90e801da21 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:45:48 -0500
Subject: [PATCH 011/113] all: smoother feedback buttons (fixes #7825) (#7810)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 src/app/feedback/feedback-view.component.html | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index d0f090ef0f..2aefa95510 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.60",
+  "version": "0.15.61",
   "myplanet": {
     "latest": "v0.21.4",
     "min": "v0.20.4"
diff --git a/src/app/feedback/feedback-view.component.html b/src/app/feedback/feedback-view.component.html
index 865515231c..412e2f6189 100644
--- a/src/app/feedback/feedback-view.component.html
+++ b/src/app/feedback/feedback-view.component.html
@@ -32,13 +32,13 @@
         </a>
       </ng-template>
       <span class="toolbar-fill"></span>
-      <a *ngIf="feedback?.state" [routerLink]="['/', feedback.state, 'view', feedback.item]" mat-icon-button>
+      <a *ngIf="feedback?.state" [routerLink]="['/', feedback.state, 'view', feedback.item]" mat-raised-button color="accent">
         <ng-container [ngSwitch]="feedback.state">
-          <mat-icon *ngSwitchCase="'resources'" svgIcon="myLibrary"></mat-icon>
-          <mat-icon *ngSwitchCase="'courses'" svgIcon="myCourses"></mat-icon>
-          <mat-icon *ngSwitchCase="'meetups'" svgIcon="myMeetups"></mat-icon>
-          <mat-icon *ngSwitchCase="'teams'" svgIcon="myTeams"></mat-icon>
-          <mat-icon *ngSwitchCase="'enterprises'">business</mat-icon>
+          <span *ngSwitchCase="'resources'" i18n>Go to Resource</span>
+          <span *ngSwitchCase="'courses'" i18n>Go to Course</span>
+          <span *ngSwitchCase="'meetups'" i18n>Go to Meetup</span>
+          <span *ngSwitchCase="'teams'" i18n>Go to Team</span>
+          <span *ngSwitchCase="'enterprises'" i18n>Go to Enterprise</span>
         </ng-container>
       </a>
     </mat-toolbar-row>

From c59e1a390c80f8a7f5f3ce2faec0697a1d31dada Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 21 Nov 2024 17:04:17 -0500
Subject: [PATCH 012/113] courses: add participants export (fixes #7815)
 (#7817)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../courses-enroll.component.html             |  3 +++
 .../courses-enroll.component.ts               | 22 ++++++++++++++++++-
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 2aefa95510..dec870e481 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.61",
+  "version": "0.15.62",
   "myplanet": {
     "latest": "v0.21.4",
     "min": "v0.20.4"
diff --git a/src/app/courses/enroll-courses/courses-enroll.component.html b/src/app/courses/enroll-courses/courses-enroll.component.html
index cf50e4eaea..fab9af1283 100644
--- a/src/app/courses/enroll-courses/courses-enroll.component.html
+++ b/src/app/courses/enroll-courses/courses-enroll.component.html
@@ -8,6 +8,9 @@
   <mat-toolbar class="primary-color font-size-1">
     {{ course }}
     <span class="toolbar-fill"></span>
+    <button mat-raised-button color="accent" (click)="exportCSV()">
+      Export
+    </button>
   </mat-toolbar>
 
   <ng-container *ngIf="!emptyData; else notFoundMessage">
diff --git a/src/app/courses/enroll-courses/courses-enroll.component.ts b/src/app/courses/enroll-courses/courses-enroll.component.ts
index b9527d4ea5..dbcb54e23d 100644
--- a/src/app/courses/enroll-courses/courses-enroll.component.ts
+++ b/src/app/courses/enroll-courses/courses-enroll.component.ts
@@ -9,6 +9,7 @@ import { TableState } from '../../users/users-table.component';
 import { StateService } from '../../shared/state.service';
 import { ManagerService } from '../../manager-dashboard/manager.service';
 import { attachNamesToPlanets } from '../../manager-dashboard/reports/reports.utils';
+import { CsvService } from '../../shared/csv.service';
 
 
 @Component({
@@ -37,7 +38,8 @@ export class CoursesEnrollComponent {
     private usersService: UsersService,
     private coursesService: CoursesService,
     private stateService: StateService,
-    private managerService: ManagerService
+    private managerService: ManagerService,
+    private csvService: CsvService
   ) {
     this.coursesService.requestCourses();
     this.usersService.requestUserData();
@@ -83,4 +85,22 @@ export class CoursesEnrollComponent {
     this.emptyData = this.members.length === 0;
   }
 
+  exportCSV() {
+    // Prepare CSV data
+    const csvData = this.members.map((user: any) => {
+      return {
+        username: user.doc.name,
+        dateStarted: user.activityDates.createdDate
+          ? new Date(user.activityDates.createdDate).toLocaleDateString()
+          : 'N/A',
+        mostRecentActivity: user.activityDates.updatedDate
+          ? new Date(user.activityDates.updatedDate).toLocaleDateString()
+          : 'N/A',
+      };
+    });
+    this.csvService.exportCSV({
+      data: csvData,
+      title: `Course Enrollment Data - ${this.course}`,
+    });
+  }
 }

From 09259c0f7beb8b699529a786bce9c8512afd4efe Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Fri, 22 Nov 2024 12:21:41 -0800
Subject: [PATCH 013/113] chat: smoother share (fixes #7812) (#7828)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                           |  6 +++---
 src/app/chat/chat-sidebar/chat-sidebar.component.ts    | 10 +++++++---
 src/app/shared/dialogs/dialogs-chat-share.component.ts |  6 +++++-
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index dec870e481..637989c306 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.62",
+  "version": "0.15.63",
   "myplanet": {
-    "latest": "v0.21.4",
-    "min": "v0.20.4"
+    "latest": "v0.21.7",
+    "min": "v0.20.7"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.component.ts b/src/app/chat/chat-sidebar/chat-sidebar.component.ts
index b41dd7a11b..1e72876eb1 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.component.ts
+++ b/src/app/chat/chat-sidebar/chat-sidebar.component.ts
@@ -211,14 +211,18 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
   }
 
   openShareDialog(conversation) {
-    this.dialog.open(DialogsChatShareComponent, {
+    const dialogRef = this.dialog.open(DialogsChatShareComponent, {
       width: '50vw',
       maxHeight: '90vh',
       data: {
         news: conversation,
       }
     });
-    this.updateConversation(conversation, null, true);
-  }
 
+    dialogRef.afterClosed().subscribe((result) => {
+      if (result) {
+        this.updateConversation(conversation, null, true);
+      }
+    });
+  }
 }
diff --git a/src/app/shared/dialogs/dialogs-chat-share.component.ts b/src/app/shared/dialogs/dialogs-chat-share.component.ts
index a968fb1b39..9a5c65d82a 100644
--- a/src/app/shared/dialogs/dialogs-chat-share.component.ts
+++ b/src/app/shared/dialogs/dialogs-chat-share.component.ts
@@ -124,7 +124,6 @@ export class DialogsChatShareComponent implements OnInit {
       })
     ).subscribe((membersData) => {
       this.conversation.chat = true;
-
       this.newsService.postNews({
         viewIn: [ { '_id': linkId, section: 'teams', public: false } ],
         messageType: teamType,
@@ -134,6 +133,7 @@ export class DialogsChatShareComponent implements OnInit {
         switchMap(() => this.sendNotifications('message', membersData, teamType)),
       ).subscribe();
     });
+    this.interact();
   }
 
   shareWithCommunity() {
@@ -142,6 +142,7 @@ export class DialogsChatShareComponent implements OnInit {
       this.conversation.message = message ? { text: message, images: [] } : { text: '</br>', images: [] };
     }
     this.conversation.chat = true;
+    this.interact();
     this.newsService.shareNews(this.conversation, null, $localize`Chat has been successfully shared to community`).subscribe(() => {});
     if (
       this.userStatusService.getStatus('joinedCourse') &&
@@ -155,4 +156,7 @@ export class DialogsChatShareComponent implements OnInit {
     }
   }
 
+  interact() {
+    this.dialogRef.close({  interacted: true });
+  }
 }

From 914d7f6e2f277d7cdb57f9c21a871ab1e1ef35ed Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Fri, 22 Nov 2024 12:41:32 -0800
Subject: [PATCH 014/113] chat: smoother provider switching (fixes #7638)(fixes
 #7809) (#7814)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../chat-sidebar/chat-sidebar.component.ts    | 36 +++++++++++++++++--
 .../chat/chat-window/chat-window.component.ts |  1 +
 src/app/chat/chat.component.ts                | 11 ++++++
 src/app/shared/chat.service.ts                | 11 +++++-
 5 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 637989c306..eece41d638 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.63",
+  "version": "0.15.64",
   "myplanet": {
     "latest": "v0.21.7",
     "min": "v0.20.7"
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.component.ts b/src/app/chat/chat-sidebar/chat-sidebar.component.ts
index 1e72876eb1..6170dd0b7b 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.component.ts
+++ b/src/app/chat/chat-sidebar/chat-sidebar.component.ts
@@ -4,7 +4,7 @@ import { MatDialog } from '@angular/material/dialog';
 import { Subject } from 'rxjs';
 import { takeUntil } from 'rxjs/operators';
 
-import { Conversation } from '../chat.model';
+import { Conversation, AIProvider } from '../chat.model';
 import { ChatService } from '../../shared/chat.service';
 import { CouchService } from '../../shared/couchdb.service';
 import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
@@ -33,6 +33,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
   selectedConversation: Conversation;
   lastRenderedConversation: number;
   isEditing: boolean;
+  provider: AIProvider;
   fullTextSearch = false;
   searchType: 'questions' | 'responses';
   overlayOpen = false;
@@ -56,6 +57,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
     this.titleSearch = '';
     this.getChatHistory();
     this.subscribeToNewChats();
+    this.subscribeToAIService();
   }
 
   ngOnDestroy() {
@@ -74,11 +76,36 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
       .subscribe(() => this.getChatHistory());
   }
 
+  subscribeToAIService() {
+    this.chatService.toggleAIService$
+      .pipe(takeUntil(this.onDestroy$))
+      .subscribe((aiService => {
+        this.provider = {
+          name: aiService
+        };
+        this.hasProviderChanged();
+      }));
+  }
+
   newChat() {
     this.chatService.sendNewChatSelectedSignal();
+    this.chatService.setChatAIProvider(undefined);
     this.selectedConversation = null;
   }
 
+  hasProviderChanged() {
+    const currentProvider = this.chatService.getChatAIProvider();
+    if (!currentProvider) {
+      // That means it's a brand-new chat
+      return;
+    }
+    if (currentProvider.name === this.provider.name) {
+      // That means the same model is still being used
+      return;
+    }
+    this.newChat();
+  }
+
   toggleEditTitle() {
     this.isEditing = !this.isEditing;
   }
@@ -94,7 +121,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
         title: title !== undefined && title !== null ? title : conversation.title,
         shared: shared,
         updatedDate: this.couchService.datePlaceholder
-     }
+      }
     ).subscribe((data) => {
       this.getChatHistory();
       return data;
@@ -141,6 +168,11 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
 
   selectConversation(conversation, index: number) {
     this.selectedConversation = conversation;
+    const aiProvider: AIProvider = {
+      name: this.selectedConversation['aiProvider'],
+    };
+    this.chatService.setChatAIProvider(aiProvider);
+    const currentProvider = this.chatService.getChatAIProvider();
     this.chatService.setSelectedConversationId({
       '_id': conversation?._id,
       '_rev': conversation?._rev
diff --git a/src/app/chat/chat-window/chat-window.component.ts b/src/app/chat/chat-window/chat-window.component.ts
index 3927ca3ea5..cbeb6908d7 100644
--- a/src/app/chat/chat-window/chat-window.component.ts
+++ b/src/app/chat/chat-window/chat-window.component.ts
@@ -205,6 +205,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
     const content = this.promptForm.get('prompt').value;
     this.data = { ...this.data, content, aiProvider: this.provider };
 
+    this.chatService.setChatAIProvider(this.data.aiProvider);
     this.setSelectedConversation();
 
     if (this.context) {
diff --git a/src/app/chat/chat.component.ts b/src/app/chat/chat.component.ts
index 6aed46a070..4660ab9615 100644
--- a/src/app/chat/chat.component.ts
+++ b/src/app/chat/chat.component.ts
@@ -27,6 +27,17 @@ export class ChatComponent implements OnInit {
       this.displayToggle = this.aiServices.length > 0;
       this.chatService.toggleAIServiceSignal(this.activeService);
     });
+    this.subscribeToAIService();
+  }
+
+  subscribeToAIService() {
+    this.chatService.currentChatAIProvider$
+      .subscribe((aiService => {
+        if (aiService) {
+          this.activeService = aiService.name;
+          this.toggleAIService();
+        }
+      }));
   }
 
   goBack(): void {
diff --git a/src/app/shared/chat.service.ts b/src/app/shared/chat.service.ts
index 387be33bb8..fa95048284 100644
--- a/src/app/shared/chat.service.ts
+++ b/src/app/shared/chat.service.ts
@@ -23,13 +23,14 @@ import { AIServices, AIProvider } from '../chat/chat.model';
   private toggleAIService = new Subject<string>();
   private selectedConversationIdSubject = new BehaviorSubject<object | null>(null);
   private aiProvidersSubject = new BehaviorSubject<Array<AIProvider>>([]);
+  private currentChatAIProvider = new BehaviorSubject<AIProvider>(undefined);
 
   newChatAdded$ = this.newChatAdded.asObservable();
   newChatSelected$ = this.newChatSelected.asObservable();
   toggleAIService$ = this.toggleAIService.asObservable();
   aiProviders$ = this.aiProvidersSubject.asObservable();
   selectedConversationId$: Observable<object | null> = this.selectedConversationIdSubject.asObservable();
-
+  currentChatAIProvider$: Observable<AIProvider> = this.currentChatAIProvider.asObservable();
 
   constructor(
     private httpClient: HttpClient,
@@ -123,6 +124,14 @@ import { AIServices, AIProvider } from '../chat/chat.model';
     this.toggleAIService.next(aiService);
   }
 
+  setChatAIProvider(aiProvider: AIProvider) {
+    this.currentChatAIProvider.next(aiProvider);
+  }
+
+  getChatAIProvider(): AIProvider {
+    return this.currentChatAIProvider.getValue();
+  }
+
   setSelectedConversationId(conversationId: object) {
     this.selectedConversationIdSubject.next(conversationId);
   }

From c57e52983ebed1022b0bac89f08d0981f9653a5c Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Fri, 22 Nov 2024 12:55:34 -0800
Subject: [PATCH 015/113] courses: smoother steps loading (fixes #7780) (#7808)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                             | 2 +-
 .../step-view-courses/courses-step-view.component.ts     | 9 ++++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index eece41d638..68545c356e 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.64",
+  "version": "0.15.65",
   "myplanet": {
     "latest": "v0.21.7",
     "min": "v0.20.7"
diff --git a/src/app/courses/step-view-courses/courses-step-view.component.ts b/src/app/courses/step-view-courses/courses-step-view.component.ts
index b06c03cff3..f380e36a80 100644
--- a/src/app/courses/step-view-courses/courses-step-view.component.ts
+++ b/src/app/courses/step-view-courses/courses-step-view.component.ts
@@ -137,11 +137,18 @@ export class CoursesStepViewComponent implements OnInit, OnDestroy {
 
   // direction = -1 for previous, 1 for next
   changeStep(direction) {
+    this.isLoading = true;
     this.router.navigate([ '../' + (this.stepNum + direction) ], { relativeTo: this.route });
-    this.resource = undefined;
+    this.resetCourseStep();
     this.countActivity = true;
   }
 
+  resetCourseStep() {
+    this.resource = undefined;
+    this.stepDetail = { stepTitle: '', description: '', resources: [] };
+    this.attempts = 0;
+  }
+
   backToCourseDetail() {
     this.router.navigate([ '../../' ], { relativeTo: this.route });
     // Challenge option only

From 0e1277f6216a818de40f0b64580f6d6e43947e90 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Mon, 25 Nov 2024 13:05:32 -0800
Subject: [PATCH 016/113] all: smoother challenge chat select (fixes #7813)
 (#7832)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                        | 6 +++---
 src/app/chat/chat-sidebar/chat-sidebar.component.ts | 7 +++++--
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 68545c356e..5b51b545a3 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.65",
+  "version": "0.15.66",
   "myplanet": {
-    "latest": "v0.21.7",
-    "min": "v0.20.7"
+    "latest": "v0.21.10",
+    "min": "v0.20.10"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.component.ts b/src/app/chat/chat-sidebar/chat-sidebar.component.ts
index 6170dd0b7b..ad0c43b8c8 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.component.ts
+++ b/src/app/chat/chat-sidebar/chat-sidebar.component.ts
@@ -73,7 +73,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
   subscribeToNewChats() {
     this.chatService.newChatAdded$
       .pipe(takeUntil(this.onDestroy$))
-      .subscribe(() => this.getChatHistory());
+      .subscribe(() => this.getChatHistory(true));
   }
 
   subscribeToAIService() {
@@ -146,7 +146,7 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
     });
   }
 
-  getChatHistory() {
+  getChatHistory(newChat: boolean = false) {
     this.chatService
       .findConversations([], [ this.userService.get().name ])
       .subscribe(
@@ -160,6 +160,9 @@ export class ChatSidebarComponent implements OnInit, OnDestroy {
               return dateB - dateA;
             });
           this.filteredConversations = [ ...this.conversations ];
+          if (newChat) {
+            this.selectConversation(this.filteredConversations[0], 0);
+          }
           this.initializeFormGroups();
         },
         (error) => console.log(error)

From f1b77c2dc9cb7605bb898c904fe3c95b10bb5928 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 25 Nov 2024 16:11:22 -0500
Subject: [PATCH 017/113] mylife: smoother myhealth form (fixes #7833) (#7834)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       | 2 +-
 src/app/health/health.constants.ts | 2 +-
 src/app/shared/label.component.ts  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 5b51b545a3..1f18c138f9 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.66",
+  "version": "0.15.67",
   "myplanet": {
     "latest": "v0.21.10",
     "min": "v0.20.10"
diff --git a/src/app/health/health.constants.ts b/src/app/health/health.constants.ts
index 1f37311ee3..3f4bb4192e 100644
--- a/src/app/health/health.constants.ts
+++ b/src/app/health/health.constants.ts
@@ -10,7 +10,7 @@ export const conditions = [
   $localize`FGM`,
   $localize`HIV/AIDS`,
   $localize`Influenza`,
-  $localize`Ischaemic heat disease`,
+  $localize`Ischaemic heart disease`,
   $localize`Malaria`,
   $localize`Malnutrition`,
   $localize`Measles`,
diff --git a/src/app/shared/label.component.ts b/src/app/shared/label.component.ts
index 97a7359d54..ec9f10b1dd 100644
--- a/src/app/shared/label.component.ts
+++ b/src/app/shared/label.component.ts
@@ -25,7 +25,7 @@ import { Component, Input } from '@angular/core';
       Epilepsy {Epilepsy}
       FGM {FGM}
       Influenza {Influenza}
-      Ischaemic heat disease {Ischaemic heat disease}
+      Ischaemic heart disease {Ischaemic heart disease}
       Malaria {Malaria}
       Malnutrition {Malnutrition}
       Measles {Measles}

From efb22c1f4a90deeb33647eed71693e9b40e4a28d Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 26 Nov 2024 15:40:19 -0500
Subject: [PATCH 018/113] teams: smoother joining (fixes #4530) (#7837)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     | 6 +++---
 src/app/teams/teams.component.ts | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 1f18c138f9..b5ac785138 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.67",
+  "version": "0.15.68",
   "myplanet": {
-    "latest": "v0.21.10",
-    "min": "v0.20.10"
+    "latest": "v0.21.11",
+    "min": "v0.20.11"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/teams/teams.component.ts b/src/app/teams/teams.component.ts
index 00093e4cfe..719df2ab02 100644
--- a/src/app/teams/teams.component.ts
+++ b/src/app/teams/teams.component.ts
@@ -269,7 +269,7 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       finalize(() => this.dialogsLoadingService.stop())
     ).subscribe(() => {
       this.teams.data = this.teamList(this.teams.data);
-      this.planetMessageService.showMessage($localize`Request to join team sent`);
+      this.planetMessageService.showMessage($localize`Request to join ${team.name} sent`);
     });
   }
 

From 5401d9d96f120c79bd1b4f9b768a433c94baa7be Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 26 Nov 2024 15:45:33 -0500
Subject: [PATCH 019/113] mylife: smoother myachievements (fixes #7639) (#7806)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../users-achievements.component.html         | 17 ++++++--
 .../users-achievements.component.ts           | 10 +++++
 .../users-achievements.scss                   | 41 +++++++++++++++++--
 4 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index b5ac785138..b6581862d0 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.68",
+  "version": "0.15.69",
   "myplanet": {
     "latest": "v0.21.11",
     "min": "v0.20.11"
diff --git a/src/app/users/users-achievements/users-achievements.component.html b/src/app/users/users-achievements/users-achievements.component.html
index ff40b83dad..4f2f70d554 100644
--- a/src/app/users/users-achievements/users-achievements.component.html
+++ b/src/app/users/users-achievements/users-achievements.component.html
@@ -23,19 +23,25 @@
   </mat-toolbar>
   <div class="view-container">
     <div *ngIf="achievements !== undefined" class="achievements-container">
-      <h2>{{user.firstName}} {{user.middleName}} {{user.lastName}}</h2>
-      <div>
-        <ng-container *ngIf="user.birthDate"><span i18n>Birthdate: {{' ' + (user.birthDate | date: medium) + ' '}}</span></ng-container><br/><br/>
-        <span *ngIf="user.birthplace" i18n>Birthplace: {{' ' + user.birthplace}} </span>
+      <div class="user-info">
+        <img class="profile-image" [src]="profileImg">
+        <h2>{{user.firstName}} {{user.middleName}} {{user.lastName}}</h2>
+        <div class="birth-info">
+          <ng-container *ngIf="user.birthDate"><span i18n>Birthdate: {{' ' + (user.birthDate | date: medium) + ' '}}</span></ng-container><br/><br/>
+          <span *ngIf="user.birthplace" i18n>Birthplace: {{' ' + user.birthplace}} </span>
+        </div>
       </div>
+      <mat-divider></mat-divider>
       <div *ngIf="achievements.purpose">
         <h3 i18n>My Purpose</h3>
         <td-markdown [content]="achievements.purpose"></td-markdown>
       </div>
+      <mat-divider></mat-divider>
       <div *ngIf="achievements.goals">
         <h3 i18n>My Goals</h3>
         <td-markdown [content]="achievements.goals"></td-markdown>
       </div>
+      <mat-divider></mat-divider>
       <ng-container *planetBeta>
         <div *ngIf="certifications.length > 0">
           <h3 i18n>My Certifications</h3>
@@ -46,6 +52,7 @@ <h3 i18n>My Certifications</h3>
           </mat-list>
         </div>
       </ng-container>
+      <mat-divider></mat-divider>
       <div *ngIf="achievements?.links?.length > 0">
         <h3 i18n>My Links</h3>
         <mat-list>
@@ -55,6 +62,7 @@ <h4 mat-line>{{link.title}}:</h4>
           </mat-list-item>
         </mat-list>
       </div>
+      <mat-divider></mat-divider>
       <div *ngIf="achievements.achievementsHeader || achievements.achievements.length > 0">
         <h3 i18n>My Achievements</h3>
         <td-markdown [content]="achievements.achievementsHeader"></td-markdown>
@@ -77,6 +85,7 @@ <h3 i18n>My Achievements</h3>
           </mat-list-item>
         </mat-list>
       </div>
+      <mat-divider></mat-divider>
       <div *ngIf="achievements.references.length > 0">
         <h3 i18n>My References</h3>
         <mat-list class="references-list">
diff --git a/src/app/users/users-achievements/users-achievements.component.ts b/src/app/users/users-achievements/users-achievements.component.ts
index aef47056e6..de990a2643 100644
--- a/src/app/users/users-achievements/users-achievements.component.ts
+++ b/src/app/users/users-achievements/users-achievements.component.ts
@@ -9,6 +9,7 @@ import { catchError, auditTime } from 'rxjs/operators';
 import { throwError, combineLatest } from 'rxjs';
 import { StateService } from '../../shared/state.service';
 import { CoursesService } from '../../courses/courses.service';
+import { environment } from '../../../environments/environment';
 import { CertificationsService } from '../../manager-dashboard/certifications/certifications.service';
 
 const pdfMake = require('pdfmake/build/pdfmake');
@@ -25,6 +26,7 @@ export class UsersAchievementsComponent implements OnInit {
   achievements: any;
   achievementNotFound = false;
   ownAchievements = false;
+  urlPrefix = environment.couchAddress + '/_users/org.couchdb.user:' + this.userService.get().name + '/';
   openAchievementIndex = -1;
   certifications: any[] = [];
 
@@ -103,6 +105,14 @@ export class UsersAchievementsComponent implements OnInit {
     return achievement.description.length > 0;
   }
 
+  get profileImg() {
+    const attachments = this.userService.get()._attachments;
+    if (attachments) {
+      return this.urlPrefix + Object.keys(attachments)[0];
+    }
+    return 'assets/image.png';
+  }
+
   setCertifications(courses = [], progress = [], certifications = []) {
     this.certifications = certifications.filter(certification => {
       const certificateCourses = courses
diff --git a/src/app/users/users-achievements/users-achievements.scss b/src/app/users/users-achievements/users-achievements.scss
index 17470dd780..c280f57f51 100644
--- a/src/app/users/users-achievements/users-achievements.scss
+++ b/src/app/users/users-achievements/users-achievements.scss
@@ -1,9 +1,8 @@
 @import '../../variables';
 
 .achievements-container {
-  max-width: 800px;
+  max-width: 95%;
   margin: 0 auto;
-  text-align: center;
 
   .references-list {
     display: flex;
@@ -21,6 +20,41 @@
     text-align: left;
   }
 
+  mat-divider {
+    margin-top: 1rem;
+    background-color: $primary;
+  }
+
+  .profile-image{
+    max-width: 15vh;
+    border-radius: 50%;
+    width: 100px;
+    height: 100px;
+  }
+
+  .user-info {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    text-align: center;
+    margin-bottom: 2rem;
+   }
+
+   .birth-info {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    gap: 1rem;
+   }
+
+   .logo {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin: 2rem;
+   }
+
   .mat-list-base .mat-list-item {
     &.mat-list-item-word-wrap {
       height: initial;
@@ -56,7 +90,6 @@
         margin-right: 0;
       }
     }
-
   }
 
   .styled-link {
@@ -100,7 +133,7 @@
     gap: 0.2rem;
     width: 100%;
   }
-  
+
   .auto-adjust-buttons a {
     flex-grow: 1;
     text-align: center;

From d484314eab4488c04dff8ef445d2c11f516d5807 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 27 Nov 2024 15:59:24 -0500
Subject: [PATCH 020/113] courses: smoother submissions toolbar (fixes #7631) 
 (#7649)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  6 +-
 src/app/submissions/submission.component.scss | 46 ++++++-----
 .../submissions/submissions.component.html    | 77 ++++++++++++-------
 src/app/submissions/submissions.component.ts  | 18 ++++-
 4 files changed, 92 insertions(+), 55 deletions(-)

diff --git a/package.json b/package.json
index b6581862d0..828eca331c 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.69",
+  "version": "0.15.70",
   "myplanet": {
-    "latest": "v0.21.11",
-    "min": "v0.20.11"
+    "latest": "v0.21.12",
+    "min": "v0.20.12"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/submissions/submission.component.scss b/src/app/submissions/submission.component.scss
index 2cef47733b..6f1c2635b9 100644
--- a/src/app/submissions/submission.component.scss
+++ b/src/app/submissions/submission.component.scss
@@ -1,21 +1,25 @@
-@import "../variables";
-
-.mat-column-name {
-  max-width: 25vw;
-}
-.mat-column-stepNum {
-  max-width: 90px;
-}
-
-@media (max-width: $screen-sm) {
-  .responsive-table {
-    display: block;
-    width: 100%;
-    overflow-x: auto;
-  }
-
-  mat-header-cell,
-  mat-cell {
-    min-width: 130px;
-  }
-}
+@import "../variables";
+
+.mat-column-name {
+  max-width: 25vw;
+}
+.mat-column-stepNum {
+  max-width: 90px;
+}
+
+@media (max-width: $screen-sm) {
+  .responsive-table {
+    display: block;
+    width: 100%;
+    overflow-x: auto;
+  }
+
+  mat-header-cell,
+  mat-cell {
+    min-width: 130px;
+  }
+
+  .status-dropdown {
+    max-width: 100px;
+  }
+}
diff --git a/src/app/submissions/submissions.component.html b/src/app/submissions/submissions.component.html
index 0f6bcfd33d..2a977bab28 100644
--- a/src/app/submissions/submissions.component.html
+++ b/src/app/submissions/submissions.component.html
@@ -1,36 +1,57 @@
-
 <mat-toolbar *ngIf="!isDialog">
-  <button mat-icon-button (click)="goBack()">
-    <mat-icon>arrow_back</mat-icon>
-  </button>
-  <span i18n>{mode, select, survey {mySurveys} grade {Submissions}}</span>
-  <span class="toolbar-fill"></span>
-  <ng-container *ngIf="this.mode !== 'survey'">
-    <mat-form-field class="font-size-1 margin-lr-3">
-      <mat-select i18n-placeholder placeholder="Status" [value]="filter.status || 'All'" (selectionChange)="onFilterChange($event.value, 'status')">
-        <mat-option i18n value="All">All</mat-option>
-        <ng-container *ngFor="let option of statusOptions">
-          <mat-option *ngIf="this.filter.type !== 'survey' || option.text !== 'Not Graded'" [value]="option.value">{{option.text}}</mat-option>
-        </ng-container>
-      </mat-select>
-    </mat-form-field>
-    <mat-button-toggle-group
-      class="margin-lr-5 font-size-1"
-      (change)="onFilterChange($event.value, 'type')"
-      #filterGroup="matButtonToggleGroup">
-      <mat-button-toggle value="exam" [checked]="this.filter.type === 'exam'" i18n>
-        Tests
-      </mat-button-toggle>
-      <mat-button-toggle value="survey" [checked]="this.filter.type === 'survey'" i18n>
-        Surveys
-      </mat-button-toggle>
-    </mat-button-toggle-group>
-  </ng-container>
+  <mat-toolbar-row>
+    <button mat-icon-button (click)="goBack()">
+      <mat-icon>arrow_back</mat-icon>
+    </button>
+    <span i18n>{mode, select, survey {mySurveys} grade {Submissions}}</span>
+    <span class="toolbar-fill"></span>
+    <ng-container *ngIf="!isMobile">
+      <ng-container *ngTemplateOutlet="filterDropdown"></ng-container>
+      <ng-container *ngTemplateOutlet="filterToggleGroup"></ng-container>
+      <ng-container *ngTemplateOutlet="filterSearch"></ng-container>
+    </ng-container>
+    <button mat-icon-button *ngIf="isMobile" (click)="showFiltersRow = !showFiltersRow">
+      <mat-icon>filter_list</mat-icon>
+    </button>
+  </mat-toolbar-row>
+  <mat-toolbar-row *ngIf="showFiltersRow && isMobile">
+    <ng-container *ngTemplateOutlet="filterDropdown"></ng-container>
+    <ng-container *ngTemplateOutlet="filterToggleGroup"></ng-container>
+  </mat-toolbar-row>
+  <mat-toolbar-row *ngIf="showFiltersRow && isMobile">
+    <ng-container *ngTemplateOutlet="filterSearch"></ng-container>
+  </mat-toolbar-row>
+</mat-toolbar>
+
+<ng-template #filterDropdown>
+  <mat-form-field class="font-size-1 margin-lr-3 status-dropdown">
+    <mat-select i18n-placeholder placeholder="Status" [value]="filter.status || 'All'" (selectionChange)="onFilterChange($event.value, 'status')">
+      <mat-option i18n value="All">All</mat-option>
+      <ng-container *ngFor="let option of statusOptions">
+        <mat-option *ngIf="this.filter.type !== 'survey' || option.text !== 'Not Graded'" [value]="option.value">{{option.text}}</mat-option>
+      </ng-container>
+    </mat-select>
+  </mat-form-field>
+</ng-template>
+<ng-template #filterToggleGroup>
+  <mat-button-toggle-group
+    class="margin-lr-5 font-size-1"
+    (change)="onFilterChange($event.value, 'type')"
+    #filterGroup="matButtonToggleGroup">
+    <mat-button-toggle value="exam" [checked]="this.filter.type === 'exam'" i18n>
+      Tests
+    </mat-button-toggle>
+    <mat-button-toggle value="survey" [checked]="this.filter.type === 'survey'" i18n>
+      Surveys
+    </mat-button-toggle>
+  </mat-button-toggle-group>
+</ng-template>
+<ng-template #filterSearch>
   <mat-icon>search</mat-icon>
   <mat-form-field class="font-size-1">
     <input matInput (keyup)="applyFilter($event.target.value)" i18n-placeholder placeholder="Type name to search...">
   </mat-form-field>
-</mat-toolbar>
+</ng-template>
 
 <div class="primary-link-hover" [ngClass]="{ 'space-container': !isDialog }">
   <div class="view-container view-table responsive-table" [ngClass]="{ 'view-full-height no-toolbar': !isDialog }" *ngIf="!emptyData; else notFoundMessage">
diff --git a/src/app/submissions/submissions.component.ts b/src/app/submissions/submissions.component.ts
index c178b3eda5..1752a06fc5 100644
--- a/src/app/submissions/submissions.component.ts
+++ b/src/app/submissions/submissions.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, ViewChild, AfterViewChecked, OnDestroy, Input, Output, EventEmitter } from '@angular/core';
+import { Component, OnInit, HostListener, ViewChild, AfterViewChecked, OnDestroy, Input, Output, EventEmitter } from '@angular/core';
 import { MatPaginator } from '@angular/material/paginator';
 import { MatSort } from '@angular/material/sort';
 import { MatTableDataSource } from '@angular/material/table';
@@ -11,7 +11,7 @@ import { UserService } from '../shared/user.service';
 import { findDocuments } from '../shared/mangoQueries';
 import { DialogsLoadingService } from '../shared/dialogs/dialogs-loading.service';
 import { CoursesService } from '../courses/courses.service';
-
+import { DeviceInfoService, DeviceType } from '../shared/device-info.service';
 const columnsByFilterAndMode = {
   exam: {
     grade: [ 'name', 'courseTitle', 'stepNum', 'status', 'grade', 'user', 'lastUpdateTime', 'gradeTime' ]
@@ -38,6 +38,9 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
   @ViewChild(MatPaginator) paginator: MatPaginator;
   @ViewChild(MatSort) sort: MatSort;
   initTable = true;
+  isMobile: boolean;
+  deviceType: DeviceType;
+  showFiltersRow = false;
   statusOptions: any = [
     { text: $localize`Pending`, value: 'pending' },
     { text: $localize`Not Graded`, value: 'requires grading' },
@@ -56,9 +59,12 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
     private submissionsService: SubmissionsService,
     private userService: UserService,
     private coursesService: CoursesService,
-    private dialogsLoadingService: DialogsLoadingService
+    private dialogsLoadingService: DialogsLoadingService,
+    private deviceInfoService: DeviceInfoService,
   ) {
     this.dialogsLoadingService.start();
+    this.deviceType = this.deviceInfoService.getDeviceType();
+    this.isMobile = this.deviceType === DeviceType.MOBILE;
   }
 
   ngOnInit() {
@@ -97,6 +103,12 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
     this.setupTable();
   }
 
+  @HostListener('window:resize') onResize() {
+    this.deviceType = this.deviceInfoService.getDeviceType();
+    this.isMobile = this.deviceType === DeviceType.MOBILE;
+    this.showFiltersRow = false;
+  }
+
   ngAfterViewChecked() {
     if (this.initTable === true) {
       this.submissions.paginator = this.paginator;

From e13d0b082df27662a75dca8b0c120f83ef0412c9 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Wed, 27 Nov 2024 16:04:55 -0500
Subject: [PATCH 021/113] courses: smoother details creation date (fixes #7839)
 (#7840)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                    | 2 +-
 src/app/courses/view-courses/courses-view-detail.component.html | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 828eca331c..e7ae8c7daa 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.70",
+  "version": "0.15.71",
   "myplanet": {
     "latest": "v0.21.12",
     "min": "v0.20.12"
diff --git a/src/app/courses/view-courses/courses-view-detail.component.html b/src/app/courses/view-courses/courses-view-detail.component.html
index c0f14d6783..f96641a797 100644
--- a/src/app/courses/view-courses/courses-view-detail.component.html
+++ b/src/app/courses/view-courses/courses-view-detail.component.html
@@ -3,6 +3,7 @@
 <p><b i18n>Grade Level:</b> <planet-language-label [options]="gradeOptions" [label]="courseDetail?.gradeLevel"></planet-language-label></p>
 <p *ngIf="courseDetail?.languageOfInstruction"><b i18n>Language of Instruction:</b> <planet-language-label [options]="languageOptions" [label]="courseDetail?.languageOfInstruction || 'N/A'"></planet-language-label></p>
 <p *ngIf="courseDetail?.creatorDoc"><b i18n>Creator:</b> {{courseDetail?.creatorDoc?.fullName}} </p>
+<p><b i18n>Created on:</b> {{(courseDetail?.createdDate | date: 'mediumDate') || 'N/A'}}</p>
 <p *ngIf="courseDetail?.sourcePlanet !== planetConfiguration.code && courseDetail?.sourcePlanet"><b i18n>Source:</b> {{courseDetail?.sourcePlanet}}</p>
 <p><b i18n>Description:</b></p>
 <planet-markdown [content]="courseDetail?.description" [imageSource]="imageSource" class="img-resize"></planet-markdown>

From 0839125dbbfddad8b047c00438a2c4ea92aab80a Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 27 Nov 2024 16:17:29 -0500
Subject: [PATCH 022/113] chat: smoother input autofocus (fixes #7836) (#7844)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                    |  2 +-
 .../chat/chat-window/chat-window.component.html |  2 +-
 .../chat/chat-window/chat-window.component.ts   | 17 ++++++++++++++---
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index e7ae8c7daa..90a532ee57 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.71",
+  "version": "0.15.72",
   "myplanet": {
     "latest": "v0.21.12",
     "min": "v0.20.12"
diff --git a/src/app/chat/chat-window/chat-window.component.html b/src/app/chat/chat-window/chat-window.component.html
index 3c06a04609..97496763a1 100644
--- a/src/app/chat/chat-window/chat-window.component.html
+++ b/src/app/chat/chat-window/chat-window.component.html
@@ -11,7 +11,7 @@
       <mat-form-field class="full-width mat-form-field-type-no-underline">
         <mat-label i18n>Chat</mat-label>
         <div class="textarea-container">
-          <textarea matInput [formControl]="promptForm.controls.prompt" rows="5" placeholder="Send a message" i18n-placeholder></textarea>
+          <textarea #chatInput matInput [formControl]="promptForm.controls.prompt" rows="5" placeholder="Send a message" i18n-placeholder></textarea>
           <button
             mat-icon-button
             [planetSubmit]="promptForm.valid && spinnerOn"
diff --git a/src/app/chat/chat-window/chat-window.component.ts b/src/app/chat/chat-window/chat-window.component.ts
index cbeb6908d7..85cdf7ce7d 100644
--- a/src/app/chat/chat-window/chat-window.component.ts
+++ b/src/app/chat/chat-window/chat-window.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef, Input } from '@angular/core';
+import { Component, OnInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef, Input, AfterViewInit } from '@angular/core';
 import { FormBuilder, FormGroup } from '@angular/forms';
 import { Subject } from 'rxjs';
 import { takeUntil } from 'rxjs/operators';
@@ -15,7 +15,7 @@ import { StateService } from '../../shared/state.service';
   templateUrl: './chat-window.component.html',
   styleUrls: [ './chat-window.scss' ],
 })
-export class ChatWindowComponent implements OnInit, OnDestroy {
+export class ChatWindowComponent implements OnInit, OnDestroy, AfterViewInit {
   private onDestroy$ = new Subject<void>();
   spinnerOn = true;
   streaming: boolean;
@@ -34,8 +34,8 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
     context: '',
   };
   providers: AIProvider[] = [];
-
   @Input() context: any;
+  @ViewChild('chatInput') chatInput: ElementRef;
   @ViewChild('chat') chatContainer: ElementRef;
 
   constructor(
@@ -57,6 +57,10 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
     });
   }
 
+  ngAfterViewInit() {
+    this.focusInput();
+  }
+
   ngOnDestroy() {
     this.onDestroy$.next();
     this.onDestroy$.complete();
@@ -69,6 +73,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
       .subscribe(() => {
         this.selectedConversationId = null;
         this.conversations = [];
+        this.focusInput();
       }, error => {
         console.error('Error subscribing to newChatSelected$', error);
       });
@@ -80,6 +85,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
       .subscribe((conversationId) => {
         this.selectedConversationId = conversationId;
         this.fetchConversation(this.selectedConversationId?._id);
+        this.focusInput();
       }, error => {
         console.error('Error subscribing to selectedConversationId$', error);
       });
@@ -92,6 +98,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
         this.provider = {
           name: aiService
         };
+        this.focusInput();
       }));
   }
 
@@ -234,4 +241,8 @@ export class ChatWindowComponent implements OnInit, OnDestroy {
       );
     }
   }
+
+  focusInput() {
+    this.chatInput?.nativeElement.focus();
+  }
 }

From 2919c7ef1d2a803b1e700123fb09c51f366e3b83 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 2 Dec 2024 15:39:34 -0500
Subject: [PATCH 023/113] dashboard: smoother calendar recurrence (fixes #7859)
 (#7863)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                             | 6 +++---
 src/app/meetups/view-meetups/meetups-view.component.html | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 90a532ee57..12134b5179 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.72",
+  "version": "0.15.73",
   "myplanet": {
-    "latest": "v0.21.12",
-    "min": "v0.20.12"
+    "latest": "v0.21.20",
+    "min": "v0.20.20"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/meetups/view-meetups/meetups-view.component.html b/src/app/meetups/view-meetups/meetups-view.component.html
index 6f4fd2b735..cbdded6dd5 100644
--- a/src/app/meetups/view-meetups/meetups-view.component.html
+++ b/src/app/meetups/view-meetups/meetups-view.component.html
@@ -36,7 +36,7 @@ <h3 class="margin-lr-3 ellipsis-title">{{meetupDetail?.title}}</h3>
       <p *ngIf="meetupDetail?.deadline"><b i18n>Deadline:</b> {{meetupDetail?.deadline | date: 'fullDate'}} {{meetupDetail?.deadline | date: 'shortTime'}}</p>
       <p *ngIf="meetupDetail?.completedTime"><b i18n>Completed On:</b> {{meetupDetail?.completedTime | date: 'fullDate'}} {{meetupDetail?.completedTime | date: 'shortTime'}}</p>
       <p *ngIf="meetupDetail?.startTime || meetupDetail?.endTime" i18n><b>Time:</b> {{meetupDetail?.startTime}} {{ meetupDetail?.endTime ? '-' : '' }} {{meetupDetail?.endTime}}</p>
-      <p *ngIf="meetupDetail?.recurring"><b i18n>Recurring:</b> {{meetupDetail?.recurring | titlecase}}</p>
+      <p *ngIf="meetupDetail?.recurring && meetupDetail?.recurring !== 'none'"><b i18n>Recurring:</b> {{meetupDetail?.recurring | titlecase}} for {{ meetupDetail?.recurringNumber }} {{ meetupDetail?.recurring === 'daily' ? 'days' : 'weeks' }}</p>
       <p *ngIf="meetupDetail?.recurring === 'weekly'"><b i18n>Recurring Days: </b><span *ngFor="let day of meetupDetail?.day; let isLast= last">{{day}}{{isLast ? '' : ', '}}</span></p>
       <p *ngIf="meetupDetail?.meetupLocation"><b i18n>Location:</b> {{meetupDetail?.meetupLocation}}</p>
       <p *ngIf="meetupDetail?.assignee"><b i18n>Assigned to:</b><a class="cursor-pointer" (click)="openProfile(meetupDetail?.assignee?.name, meetupDetail?.assignee?.userPlanetCode)">{{' ' + meetupDetail?.assignee?.name}}</a></p>

From 28628eea25dd07a0d434a75b10aff27f925ea348 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Mon, 2 Dec 2024 15:46:06 -0500
Subject: [PATCH 024/113] teams: smoother deletion snackbar (fixes #7852)
 (#7853)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     | 2 +-
 src/app/teams/teams.component.ts | 7 ++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 12134b5179..a2d94c1c61 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.73",
+  "version": "0.15.74",
   "myplanet": {
     "latest": "v0.21.20",
     "min": "v0.20.20"
diff --git a/src/app/teams/teams.component.ts b/src/app/teams/teams.component.ts
index 719df2ab02..19ca325108 100644
--- a/src/app/teams/teams.component.ts
+++ b/src/app/teams/teams.component.ts
@@ -238,7 +238,12 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       request: this.teamsService.archiveTeam(team)().pipe(switchMap(() => this.teamsService.deleteCommunityLink(team))),
       onNext: () => {
         this.deleteDialog.close();
-        this.planetMessageService.showMessage($localize`You have deleted a team.`);
+        if (this.mode == 'enterprise'){
+          this.planetMessageService.showMessage($localize`You have deleted an ${toProperCase(this.mode)}.`);
+        }
+        else{
+          this.planetMessageService.showMessage($localize`You have deleted a ${toProperCase(this.mode)}.`);
+        }
         this.removeTeamFromTable(team);
       },
       onError: () => this.planetMessageService.showAlert($localize`There was a problem deleting this team.`)

From 4159fd4a2b26c7fd0159e88e97b5f5e9fe77eb6c Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Mon, 2 Dec 2024 15:51:48 -0500
Subject: [PATCH 025/113] enterprises: smoother list checkmark (fixes #5231)
 (#7848)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       | 2 +-
 src/app/teams/teams.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index a2d94c1c61..ae08e36115 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.74",
+  "version": "0.15.75",
   "myplanet": {
     "latest": "v0.21.20",
     "min": "v0.20.20"
diff --git a/src/app/teams/teams.component.html b/src/app/teams/teams.component.html
index eff232045c..c523f72a3f 100644
--- a/src/app/teams/teams.component.html
+++ b/src/app/teams/teams.component.html
@@ -45,7 +45,7 @@
         <mat-cell *matCellDef="let element">
           <h3>
             {{element.doc.name}}
-            <mat-icon class="margin-lr-3" i18n-title title="Joined Team" [inline]="true" *ngIf="element.userStatus=='member'">check</mat-icon>
+            <mat-icon class="margin-lr-3" i18n-title title="{{ mode === 'enterprise' ? 'Joined Enterprise' : 'Joined Team' }}" [inline]="true" *ngIf="element.userStatus=='member'">check</mat-icon>
           </h3>
         </mat-cell>
       </ng-container>

From d453e65835e44fbdfe555187bb2cd5ffaeab3caa Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Mon, 2 Dec 2024 15:55:44 -0500
Subject: [PATCH 026/113] teams: smoother document deletion (fixes #4956)
 (#7847)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                         | 2 +-
 src/app/shared/dialogs/dialogs-prompt.component.html | 1 +
 src/app/teams/teams-view.component.html              | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index ae08e36115..63fb90bfb6 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.75",
+  "version": "0.15.76",
   "myplanet": {
     "latest": "v0.21.20",
     "min": "v0.20.20"
diff --git a/src/app/shared/dialogs/dialogs-prompt.component.html b/src/app/shared/dialogs/dialogs-prompt.component.html
index 78b9e9f782..0157aec2be 100644
--- a/src/app/shared/dialogs/dialogs-prompt.component.html
+++ b/src/app/shared/dialogs/dialogs-prompt.component.html
@@ -7,6 +7,7 @@
         nation {nation}
         course {course}
         resource {resource}
+        document {document}
         meetup {meetup}
         user {member}
         change {change}
diff --git a/src/app/teams/teams-view.component.html b/src/app/teams/teams-view.component.html
index b4b7caa6f8..9f2796632d 100644
--- a/src/app/teams/teams-view.component.html
+++ b/src/app/teams/teams-view.component.html
@@ -171,7 +171,7 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
                   <mat-icon>more_vert</mat-icon>
                 </button>
                 <mat-menu #resourceMenu="matMenu">
-                  <button mat-menu-item (click)="openDialogPrompt(resource, 'resource', { changeType: 'remove', type: 'resource' })">
+                  <button mat-menu-item (click)="openDialogPrompt(resource, 'resource', { changeType: 'remove', type: 'document' })">
                     <mat-icon>clear</mat-icon>
                     <span i18n>Remove</span>
                   </button>

From d8fae2a43299442e564b37a63237a46b8f863934 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 3 Dec 2024 15:35:23 -0500
Subject: [PATCH 027/113] courses: smoother steps icons (fixes #7870) (#7876)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                   | 6 +++---
 src/app/courses/view-courses/courses-view.scss | 8 ++++++++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 63fb90bfb6..e296fe9cb5 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.76",
+  "version": "0.15.77",
   "myplanet": {
-    "latest": "v0.21.20",
-    "min": "v0.20.20"
+    "latest": "v0.21.24",
+    "min": "v0.20.24"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/view-courses/courses-view.scss b/src/app/courses/view-courses/courses-view.scss
index ca04a3bff8..5b8d6caa87 100644
--- a/src/app/courses/view-courses/courses-view.scss
+++ b/src/app/courses/view-courses/courses-view.scss
@@ -26,6 +26,14 @@
     grid-column-gap: 0;
   }
 
+  .mat-expansion-panel-header-description {
+    justify-content: flex-end;
+  }
+
+  .mat-expansion-panel-header-description planet-course-icon {
+    margin-left: 8px;
+  }
+
   @media (max-width: $screen-sm) {
     .course-container {
       grid-template-columns: 1fr;

From 39f16f9446f482d5991794da959d1a52c7ddf367 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Tue, 3 Dec 2024 23:57:05 +0300
Subject: [PATCH 028/113] all: december challenge (fixes #7838) (#7850)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |   2 +-
 .../dialogs-announcement.component.html       |  36 +++--
 .../dialogs/dialogs-announcement.component.ts | 149 ++++++++++++------
 .../shared/user-challenge-status.service.ts   |  42 +++--
 src/app/teams/teams.component.ts              |   5 +-
 5 files changed, 152 insertions(+), 82 deletions(-)

diff --git a/package.json b/package.json
index e296fe9cb5..8ae4bd2fb2 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.77",
+  "version": "0.15.78",
   "myplanet": {
     "latest": "v0.21.24",
     "min": "v0.20.24"
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.html b/src/app/shared/dialogs/dialogs-announcement.component.html
index f06747ea37..4754422790 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.html
+++ b/src/app/shared/dialogs/dialogs-announcement.component.html
@@ -1,6 +1,6 @@
 <div class="announcement-container">
   <img
-    src="https://res.cloudinary.com/mutugiii/image/upload/v1730395098/challenge_horizontal_new_tnco4v.jpg"
+    src="https://res.cloudinary.com/mutugiii/image/upload/v1733224910/dec_challenge_svcbi3.jpg"
     alt="Issues Challenge"
     class="announcement-banner"
   />
@@ -12,7 +12,7 @@
           class="thermometer-label"
           [ngClass]="{ outside: getGoalPercentage() < 8 }"
         >
-          {{ "$" + getTotalMoneyEarned() }}
+          ${{ getGroupMoneyEarned() }} / ${{ goal }}
         </div>
       </div>
     </div>
@@ -29,28 +29,18 @@
         <mat-icon color="primary">
           {{ getStatus('joinedCourse') ? 'check_circle' : 'radio_button_unchecked' }}
         </mat-icon>
-        <span>Únete al curso Reto noviembre.</span>
+        <span>Únete al curso Curso Planet & myPlanet. [${{courseStepValue}}]</span>
         <a *ngIf="!getStatus('joinedCourse')" mat-button mat-raised-button color="primary" type="button" (click)="joinCourse()">
           Unirse
         </a>
       </div>
 
-      <div class="step">
-        <mat-icon color="primary">
-          {{ getStatus('surveyComplete') ? 'check_circle' : 'radio_button_unchecked' }}
-        </mat-icon>
-        <span>¡Encuesta finalizada!</span>
-        <a *ngIf="getStatus('joinedCourse') && !getStatus('surveyComplete')" mat-button mat-raised-button color="primary" type="button" (click)="doSurvey()">
-          Encuesta
-        </a>
-      </div>
-
       <div class="step">
         <mat-icon color="primary">
           {{ getStatus('hasPost') ? 'check_circle' : 'radio_button_unchecked' }}
         </mat-icon>
-        <span>Comparte tu opinión en Nuestras Voces. <br><span>{{getStatus('userPosts')}} de 5 Voces diarias</span> </span>
-        <a *ngIf="getStatus('joinedCourse') && getStatus('surveyComplete') && !getStatus('hasPost'); else dailyVoices" mat-button mat-raised-button color="primary" type="button" (click)="chatNShare()">
+        <span>Comparte tu opinión en Nuestras Voces. [${{postStepValue}}/voz]<br><span>{{getPosts()}} de 5 Voces diarias</span> </span>
+        <a *ngIf="getStatus('joinedCourse') && !getStatus('hasPost'); else dailyVoices" mat-button mat-raised-button color="primary" type="button" (click)="shareVoice()">
           Chatea y comparte
         </a>
         <ng-template #dailyVoices>
@@ -58,11 +48,25 @@
             <div
               *ngFor="let dot of [0, 1, 2, 3, 4]; let i = index"
               class="dot"
-              [ngClass]="{ completed: i < getStatus('userPosts') }"
+              [ngClass]="{ completed: i < getPosts() }"
             ></div>
           </div>
         </ng-template>
       </div>
+
+      <div class="step">
+        <mat-icon color="primary">
+          {{ getStatus('surveyComplete') ? 'check_circle' : 'radio_button_unchecked' }}
+        </mat-icon>
+        <span>¡Encuesta finalizada! [${{surveyStepValue}}]</span>
+        <a *ngIf="getStatus('joinedCourse') && getStatus('hasPost') && !getStatus('surveyComplete')" mat-button mat-raised-button color="primary" type="button" (click)="doSurvey()">
+          Encuesta
+        </a>
+      </div>
+
+      <div>
+        <span>Mis ganancias: <b>${{getIndividualMoneyEarned()}}</b> / $11</span>
+      </div>
     </div>
   </ng-template>
 </div>
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.ts b/src/app/shared/dialogs/dialogs-announcement.component.ts
index 780fe1caf3..ec17b7215b 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.ts
+++ b/src/app/shared/dialogs/dialogs-announcement.component.ts
@@ -11,18 +11,20 @@ import { NewsService } from '../../news/news.service';
 import { StateService } from '../state.service';
 import { SubmissionsService } from '../../submissions/submissions.service';
 import { UserService } from '../user.service';
+import { UsersService } from '../../users/users.service';
 import { UserChallengeStatusService } from '../user-challenge-status.service';
 import { planetAndParentId } from '../../manager-dashboard/reports/reports.utils';
 
-export const includedCodes = [ 'guatemala', 'san.pablo', 'xela', 'ollonde', 'okuro', 'uriur', 'mutugi', 'vi' ];
-export const challengeCourseId = '9517e3b45a5bb63e69bb8f269216974d';
-export const challengePeriod = (new Date() > new Date(2024, 9, 31)) && (new Date() < new Date(2024, 11, 1));
+export const includedCodes = [ 'guatemala', 'san.pablo', 'xela', 'okuro', 'uriur', 'mutugi', 'vi' ];
+export const challengeCourseId = '4e6b78800b6ad18b4e8b0e1e38a98cac';
+export const examId = '4e6b78800b6ad18b4e8b0e1e38b382ab';
+export const challengePeriod = (new Date() > new Date(2024, 10, 31)) && (new Date() < new Date(2024, 12, 1));
 
 @Component({
   template: `
     <div class="announcement-container">
       <img
-        src="https://res.cloudinary.com/mutugiii/image/upload/v1730395098/challenge_horizontal_new_tnco4v.jpg"
+        src="https://res.cloudinary.com/mutugiii/image/upload/v1733224910/dec_challenge_svcbi3.jpg"
         alt="Issues Challenge"
         class="announcement-banner"
       />
@@ -45,12 +47,15 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   teamId = planetAndParentId(this.stateService.configuration);
   submissions = [];
   groupSummary = [];
+  members: any;
   enrolledMembers: any;
   courseId = challengeCourseId;
-  startDate = new Date(2024, 9, 31);
-  endDate = new Date(2024, 11, 1);
+  startDate = new Date(2024, 10, 31);
+  endDate = new Date(2024, 12, 1);
   isLoading = true;
-  submissionValue = 5;
+  postStepValue = 2;
+  courseStepValue = 0;
+  surveyStepValue = 1;
   goal = 500;
 
   constructor(
@@ -62,6 +67,7 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     private stateService: StateService,
     private submissionsService: SubmissionsService,
     private userService: UserService,
+    private usersService: UsersService,
     private userStatusService: UserChallengeStatusService
   ) {}
 
@@ -94,8 +100,9 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
       },
       viewId: this.teamId
     });
+    this.fetchMembers();
     this.fetchCourseAndNews();
-    this.fetchEnrolled();
+    this.fetchEnrolledMembers();
   }
 
   joinCourse() {
@@ -107,27 +114,27 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   }
 
   doSurvey() {
-    this.router.navigate([ `/courses/view/${this.courseId}/step/3/exam`, {
+    this.router.navigate([ `/courses/view/${this.courseId}/step/5/exam`, {
       id: this.courseId,
-      stepNum: 3,
+      stepNum: 5,
       questionNum: 1,
       type: 'survey',
       preview: 'false',
-      examId: '83fe016d8a983de6f7112e761c014545'
+      examId: examId
     } ]);
     this.dialogRef.close();
   }
 
-  chatNShare() {
-    this.router.navigate([ '/chat' ]);
+  shareVoice() {
+    this.router.navigate([ '/' ]);
     this.dialogRef.close();
   }
 
-  hasCompletedSurvey(userName: string) {
+  hasCompletedSurvey(userName: string): boolean {
     return this.submissions.some(submission => submission.name === userName && submission.status === 'complete');
   }
 
-  hasSubmittedVoice(news: any[], userName: string) {
+  hasSubmittedVoice(news: any[], userName: string): number {
     const uniqueDays = new Set<string>();
 
     news.forEach(post => {
@@ -143,11 +150,27 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     return Math.min(uniqueDays.size, 5);
   }
 
-  hasEnrolledCourse(member) {
-    return member.courseIds.includes(this.courseId);
+  hasEnrolledCourse(member: any): boolean {
+    return this.enrolledMembers.some(
+      (enrolledMember) =>
+        enrolledMember._id === member._id &&
+        enrolledMember.courseIds?.includes(this.courseId)
+    );
   }
 
-  fetchEnrolled() {
+  fetchMembers() {
+    this.usersService.getAllUsers().subscribe((users: any) => {
+      this.members = users.map((member: any) => {
+        const [ , memberName ] = member?._id.split(':');
+        return {
+          ...member,
+          name: memberName,
+        };
+      });
+    });
+  }
+
+  fetchEnrolledMembers() {
     this.couchService.findAll('shelf', {
       selector: { courseIds: { $elemMatch: { $eq: this.courseId } } },
     }).subscribe((members) => {
@@ -161,6 +184,43 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     });
   }
 
+  fetchGroupSummary(news) {
+    this.members.forEach((member) => {
+      const hasJoinedCourse = this.hasEnrolledCourse(member);
+      const hasCompletedSurvey = this.hasCompletedSurvey(member.name);
+      const userPosts = this.hasSubmittedVoice(news, member.name);
+
+      if (!this.groupSummary.some(m => m.name === member.name)) {
+        this.groupSummary.push({
+          ...member,
+          userPosts,
+          courseAmount: hasJoinedCourse ? this.courseStepValue : 0,
+          surveyAmount: hasCompletedSurvey ? this.surveyStepValue : 0
+        });
+      }
+    });
+  }
+
+  fetchIndividualSummary(news) {
+    this.userStatusService.updateStatus('surveyComplete', {
+      status: this.hasCompletedSurvey(this.currentUserName),
+      amount: this.surveyStepValue
+    });
+    this.userStatusService.updateStatus('hasPost', {
+      status: this.hasSubmittedVoice(news, this.currentUserName) > 0,
+      amount: this.postStepValue
+    });
+    this.userStatusService.updateStatus('userPosts', this.hasSubmittedVoice(news, this.currentUserName));
+    this.members.some(member => {
+      if (member.name === this.currentUserName) {
+        this.userStatusService.updateStatus('joinedCourse', {
+          status: this.hasEnrolledCourse(member),
+          amount: this.courseStepValue
+        });
+      }
+    });
+  }
+
   fetchCourseAndNews() {
     this.newsService.newsUpdated$.pipe(
       takeUntil(this.onDestroy$)
@@ -175,7 +235,6 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
           ) || {}
         ).public,
         }));
-
         this.submissionsService.getSubmissions(findDocuments({ type: 'survey' }))
         .subscribe((submissions: any[]) => {
           const filteredSubmissions = submissions.filter(submission => submission.parentId.includes(this.courseId));
@@ -184,54 +243,40 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
             status: submission.status,
             time: submission.lastUpdateTime
           }));
-
-
-          // Group Summary
-          this.enrolledMembers.forEach((member) => {
-            const hasJoinedCourse = this.hasEnrolledCourse(member);
-            const hasCompletedSurvey = this.hasCompletedSurvey(member.name);
-            const hasPosted = this.hasSubmittedVoice(news, member.name) > 0;
-            const userAmount = this.hasSubmittedVoice(news, member.name);
-
-            if (hasCompletedSurvey && hasPosted && hasJoinedCourse && userAmount > 0) {
-              if (!this.groupSummary.some(m => m.name === member.name)) {
-                this.groupSummary.push({
-                  ...member,
-                  userPosts: userAmount
-                });
-              }
-            }
-          });
-
-          // Individual stats
-          this.userStatusService.updateStatus('surveyComplete', this.hasCompletedSurvey(this.currentUserName));
-          this.userStatusService.updateStatus('hasPost', this.hasSubmittedVoice(news, this.currentUserName) > 0);
-          this.userStatusService.updateStatus('userPosts', this.hasSubmittedVoice(news, this.currentUserName));
-          this.enrolledMembers.some(member => {
-            if (member.name === this.currentUserName) {
-              this.userStatusService.updateStatus('joinedCourse', this.hasEnrolledCourse(member));
-            }
-          });
+          this.fetchGroupSummary(news);
+          this.fetchIndividualSummary(news);
           this.isLoading = false;
         }, () => this.isLoading = false);
       }, () => this.isLoading = false);
   }
 
-  getTotalMoneyEarned(): number {
+  getIndividualMoneyEarned(): number {
+    const userStatus = this.userStatusService.printStatus();
+    const postsEarnings = Number(userStatus.userPosts) * this.postStepValue;
+    const courseAmount = userStatus.joinedCourse.status ? userStatus.joinedCourse.amount : 0;
+    const surveyAmount = userStatus.surveyComplete.status ? userStatus.surveyComplete.amount : 0;
+    return postsEarnings + courseAmount + surveyAmount;
+  }
+
+  getGroupMoneyEarned(): number {
     const totalEarned = this.groupSummary.reduce((total, member) => {
-      const amount = Number(member.userPosts * this.submissionValue);
-      return total + (isNaN(amount) ? 0 : amount);
+      const postAmount = Number(member.userPosts * this.postStepValue);
+      const stepAmounts = member.courseAmount + member.surveyAmount;
+      return total + (isNaN(postAmount) ? 0 : postAmount) + (isNaN(stepAmounts) ? 0 : stepAmounts);
     }, 0);
-
     return Math.min(totalEarned, this.goal);
   }
 
   getGoalPercentage(): number {
-    const totalMoneyEarned = this.getTotalMoneyEarned();
+    const totalMoneyEarned = this.getGroupMoneyEarned();
     return (totalMoneyEarned / this.goal) * 100;
   }
 
   getStatus(key: string) {
     return this.userStatusService.getStatus(key);
   }
+
+  getPosts() {
+    return this.userStatusService.getPosts();
+  }
 }
diff --git a/src/app/shared/user-challenge-status.service.ts b/src/app/shared/user-challenge-status.service.ts
index 7825124d62..d779831e4d 100644
--- a/src/app/shared/user-challenge-status.service.ts
+++ b/src/app/shared/user-challenge-status.service.ts
@@ -5,25 +5,38 @@ import { Injectable } from '@angular/core';
 })
 export class UserChallengeStatusService {
   userStatus = {
-    joinedCourse: false,
-    surveyComplete: false,
-    hasPost: false,
+    joinedCourse: {
+      status: false,
+      amount: 0
+    },
+    surveyComplete: {
+      status: false,
+      amount: 0
+    },
+    hasPost: {
+      status: false,
+      amount: 0
+    },
     userPosts: 0
   };
 
-  updateStatus(key: string, value: boolean | number) {
+  updateStatus(key: string, value: Object | number) {
     this.userStatus[key] = value;
   }
 
   getCompleteChallenge(): boolean {
     const complete = Object.values(this.userStatus).every(
-      (value, index) => index !== 3 && value === true
+      (value, index) => typeof value === 'object' && 'status' in value && value.status === true
     );
     return complete;
   }
 
-  getStatus(key: string): boolean| number {
-    return this.userStatus[key];
+  getPosts(): number {
+    return this.userStatus.userPosts;
+  }
+
+  getStatus(key: string): boolean {
+    return this.userStatus[key].status;
   }
 
   printStatus(): any {
@@ -32,9 +45,18 @@ export class UserChallengeStatusService {
 
   resetStatus() {
     this.userStatus = {
-      joinedCourse: false,
-      surveyComplete: false,
-      hasPost: false,
+      joinedCourse: {
+        status: false,
+        amount: 0
+      },
+      surveyComplete: {
+        status: false,
+        amount: 0
+      },
+      hasPost: {
+        status: false,
+        amount: 0
+      },
       userPosts: 0
     };
   }
diff --git a/src/app/teams/teams.component.ts b/src/app/teams/teams.component.ts
index 19ca325108..7a39a9ab93 100644
--- a/src/app/teams/teams.component.ts
+++ b/src/app/teams/teams.component.ts
@@ -238,10 +238,9 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       request: this.teamsService.archiveTeam(team)().pipe(switchMap(() => this.teamsService.deleteCommunityLink(team))),
       onNext: () => {
         this.deleteDialog.close();
-        if (this.mode == 'enterprise'){
+        if (this.mode === 'enterprise') {
           this.planetMessageService.showMessage($localize`You have deleted an ${toProperCase(this.mode)}.`);
-        }
-        else{
+        } else {
           this.planetMessageService.showMessage($localize`You have deleted a ${toProperCase(this.mode)}.`);
         }
         this.removeTeamFromTable(team);

From 1e377ed3f270022014e1ba8f80ccc48c0068491e Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 4 Dec 2024 12:32:00 -0800
Subject: [PATCH 029/113] surveys: smoother sorting (fixes #7802) (#7875)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                 | 6 +++---
 src/app/submissions/submissions.component.ts | 7 +++----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index 8ae4bd2fb2..8c95148d31 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.78",
+  "version": "0.15.79",
   "myplanet": {
-    "latest": "v0.21.24",
-    "min": "v0.20.24"
+    "latest": "v0.21.27",
+    "min": "v0.20.27"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/submissions/submissions.component.ts b/src/app/submissions/submissions.component.ts
index 1752a06fc5..7c1bd8f946 100644
--- a/src/app/submissions/submissions.component.ts
+++ b/src/app/submissions/submissions.component.ts
@@ -37,7 +37,6 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
   onDestroy$ = new Subject<void>();
   @ViewChild(MatPaginator) paginator: MatPaginator;
   @ViewChild(MatSort) sort: MatSort;
-  initTable = true;
   isMobile: boolean;
   deviceType: DeviceType;
   showFiltersRow = false;
@@ -110,10 +109,9 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
   }
 
   ngAfterViewChecked() {
-    if (this.initTable === true) {
+    if (this.sort && this.paginator && !this.submissions.paginator && !this.submissions.sort) {
       this.submissions.paginator = this.paginator;
       this.submissions.sort = this.sort;
-      this.initTable = false;
     }
   }
 
@@ -166,8 +164,9 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
     // Force filter to update by setting it to a space if empty
     this.submissions.filter = this.submissions.filter || ' ';
     this.emptyData = !this.submissions.filteredData.length;
-    this.initTable = !this.emptyData;
     this.displayedColumns = columnsByFilterAndMode[this.filter.type][this.mode] || this.displayedColumns;
+    this.submissions.paginator = undefined;
+    this.submissions.sort = undefined;
   }
 
   dropdownsFill() {

From 101078b5a09c175d052906e440ff7df648ab6acf Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 4 Dec 2024 12:44:39 -0800
Subject: [PATCH 030/113] chat: smoother textbox size (fixes #7874) (#7881)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                              | 2 +-
 src/app/chat/chat-window/chat-window.scss | 7 ++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 8c95148d31..36553c32d5 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.79",
+  "version": "0.15.80",
   "myplanet": {
     "latest": "v0.21.27",
     "min": "v0.20.27"
diff --git a/src/app/chat/chat-window/chat-window.scss b/src/app/chat/chat-window/chat-window.scss
index 4a31686b10..d395950bd5 100644
--- a/src/app/chat/chat-window/chat-window.scss
+++ b/src/app/chat/chat-window/chat-window.scss
@@ -27,9 +27,14 @@
   border-radius: 5px;
 }
 
+.textarea-container textarea {
+  resize: none;
+  height: 100px;
+}
+
 .textarea-container button {
   position: absolute;
-  top: 50%;
+  top: 70%;
   right: 8px;
   transform: translateY(-50%);
 }

From f3d6b62eccd9ddfe9d02334c20dfbbcfb04aa515 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Wed, 4 Dec 2024 16:02:50 -0500
Subject: [PATCH 031/113] courses: smoother steps titles (fixes #7867) (#7873)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                            | 2 +-
 src/app/courses/add-courses/courses-step.component.html | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 36553c32d5..f728fb8f3a 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.80",
+  "version": "0.15.81",
   "myplanet": {
     "latest": "v0.21.27",
     "min": "v0.20.27"
diff --git a/src/app/courses/add-courses/courses-step.component.html b/src/app/courses/add-courses/courses-step.component.html
index a5e1111b91..94db40f307 100644
--- a/src/app/courses/add-courses/courses-step.component.html
+++ b/src/app/courses/add-courses/courses-step.component.html
@@ -1,6 +1,6 @@
 <planet-step-list [steps]="steps" (stepsChange)="stepsMoved($event)" [nameProp]="'stepTitle'" (stepClicked)="stepClick($event)">
   <planet-step-list-item *ngFor="let step of steps; index as i; first as isFirst; last as isLast">
-    <span i18n>{{step.stepTitle || 'Step ' + (i+1)}}</span>
+    <span i18n>{{(step.stepTitle || 'Step ' + (i+1)) | slice:0:50}}{{(step.stepTitle || 'Step ' + (i+1)).length > 50 ? '...' : ''}}</span>
     <planet-course-icon *ngIf="step?.exam?.questions.length" [icon]="'assignment'"></planet-course-icon>
     <planet-course-icon *ngIf="step?.resources?.length" [icon]="'attach_file'"></planet-course-icon>
     <planet-course-icon *ngIf="step?.survey?.questions.length" [icon]="'description'"></planet-course-icon>
@@ -13,7 +13,7 @@
   <div planetStepListForm>
     <form [formGroup]="stepForm">
       <mat-form-field class="full-width">
-        <input matInput i18n-placeholder placeholder="Step title" formControlName="stepTitle">
+        <input matInput i18n-placeholder placeholder="Step title" maxlength="200" formControlName="stepTitle">
       </mat-form-field>
       <mat-form-field class="full-width mat-form-field-type-no-underline">
         <planet-markdown-textbox class="full-width" i18n-placeholder placeholder="Description" [formControl]="stepForm.controls.description" imageGroup="community"></planet-markdown-textbox>

From f3f04992496fc037ff44f84ae3ed70ef6647b9f0 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 5 Dec 2024 16:36:38 -0500
Subject: [PATCH 032/113] courses: smoother progress navigation (fixes #7769)
 (#7773)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  6 +-
 .../courses-progress-leader.component.html    | 62 +++++++++++--------
 .../courses-progress-leader.component.ts      | 18 ++++--
 3 files changed, 53 insertions(+), 33 deletions(-)

diff --git a/package.json b/package.json
index f728fb8f3a..05e6afc14e 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.81",
+  "version": "0.15.82",
   "myplanet": {
-    "latest": "v0.21.27",
-    "min": "v0.20.27"
+    "latest": "v0.21.28",
+    "min": "v0.20.28"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/progress-courses/courses-progress-leader.component.html b/src/app/courses/progress-courses/courses-progress-leader.component.html
index e978628454..0cff81fd1f 100644
--- a/src/app/courses/progress-courses/courses-progress-leader.component.html
+++ b/src/app/courses/progress-courses/courses-progress-leader.component.html
@@ -1,31 +1,43 @@
 <mat-toolbar>
   <a mat-icon-button (click)="navigateBack()"><mat-icon>arrow_back</mat-icon></a>
+  <span>
+    <ng-container *ngIf="selectedStep === undefined" i18n>Course Progress</ng-container>
+    <ng-container *ngIf="selectedStep !== undefined" i18n>Test Progress</ng-container>
+  </span>
 </mat-toolbar>
 
-<div class="space-container">
-  <mat-toolbar class="primary-color font-size-1 action-buttons">
-    <span>
-      {{headingStart ? headingStart + ' ' : ''}}
-      <ng-container *ngIf="selectedStep === undefined" i18n>Course Progress</ng-container>
-      <ng-container *ngIf="selectedStep !== undefined" i18n>Test Progress</ng-container>
-    </span>
+<mat-toolbar class="primary-color font-size-1">
+  <span><h3 class="margin-lr-3 ellipsis-title">{{ headingStart }}</h3></span>
+  <ng-container *ngIf="deviceType === deviceTypes.DESKTOP">
     <span class="toolbar-fill"></span>
-    <planet-selector *ngIf="planetCodes.length > 1" [planetCodes]="planetCodes" (selectionChange)="planetSelectionChange($event)"></planet-selector>
-    <mat-form-field *ngIf="submittedExamSteps?.length > 1">
-      <mat-select i18n-placeholder placeholder="View Test Progress" [value]="selectedStep" (selectionChange)="onStepChange($event.value)">
-        <mat-option *ngFor="let step of submittedExamSteps" [value]="step" i18n>
-          {{ step.stepTitle || 'Step ' + (step.index + 1) }}
-        </mat-option>
-      </mat-select>
-    </mat-form-field>
-    <button mat-raised-button color="accent" class="margin-lr-3" *ngIf="selectedStep !== undefined" (click)="resetToFullCourse()" i18n>Show full course</button>
-    <button *ngIf="chartData?.length" class="margin-lr-10" color="accent" mat-raised-button i18n (click)="exportChartData()">
-      Export
-    </button>
-  </mat-toolbar>
-  <div class="view-container view-full-height">
-    <planet-courses-progress-chart *ngIf="chartData?.length; else noProgress" [label]="chartLabel" [inputs]="chartData" [height]="yAxisLength" [showAvatar]="true" (clickAction)="memberClick($event)" (changeData)="changeData($event)">
-    </planet-courses-progress-chart>
-    <ng-template #noProgress i18n>No Progress record available</ng-template>
-  </div>
+    <ng-container *ngTemplateOutlet="filterSelectors"></ng-container>
+    <ng-container *ngTemplateOutlet="actionButtons"></ng-container>
+  </ng-container>
+  <ng-container *ngIf="deviceType !== deviceTypes.DESKTOP">
+    <span class="toolbar-fill"></span>
+    <button class="menu" *ngIf="chartData?.length" mat-icon-button [matMenuTriggerFor]="actionsMenu"><mat-icon>more_vert</mat-icon></button>
+    <mat-menu #actionsMenu="matMenu" class="actions-menu">
+      <ng-container *ngTemplateOutlet="filterSelectors"></ng-container>
+      <ng-container *ngTemplateOutlet="actionButtons"></ng-container>
+    </mat-menu>
+  </ng-container>
+</mat-toolbar>
+<ng-template #filterSelectors>
+  <planet-selector *ngIf="planetCodes.length > 1" [planetCodes]="planetCodes" (selectionChange)="planetSelectionChange($event)"></planet-selector>
+  <mat-form-field *ngIf="submittedExamSteps?.length > 1" class="margin-lr-3">
+    <mat-select i18n-placeholder placeholder="View Test Progress" [value]="selectedStep" (selectionChange)="onStepChange($event.value)">
+      <mat-option *ngFor="let step of submittedExamSteps" [value]="step" i18n>
+        {{ step.stepTitle || 'Step ' + (step.index + 1) }}
+      </mat-option>
+    </mat-select>
+  </mat-form-field>
+</ng-template>
+<ng-template #actionButtons>
+  <button mat-raised-button color="accent" *ngIf="selectedStep !== undefined" (click)="resetToFullCourse()" class="margin-lr-3" i18n>Show full course</button>
+  <button mat-raised-button color="accent" *ngIf="chartData?.length" (click)="exportChartData()" class="margin-lr-3" i18n>Export</button>
+</ng-template>
+<div class="view-container view-full-height">
+  <planet-courses-progress-chart *ngIf="chartData?.length; else noProgress" [label]="chartLabel" [inputs]="chartData" [height]="yAxisLength" [showAvatar]="true" (clickAction)="memberClick($event)" (changeData)="changeData($event)">
+  </planet-courses-progress-chart>
+  <ng-template #noProgress i18n>No Progress record available</ng-template>
 </div>
diff --git a/src/app/courses/progress-courses/courses-progress-leader.component.ts b/src/app/courses/progress-courses/courses-progress-leader.component.ts
index 8ab04286f6..c6a36c59d9 100644
--- a/src/app/courses/progress-courses/courses-progress-leader.component.ts
+++ b/src/app/courses/progress-courses/courses-progress-leader.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, OnDestroy } from '@angular/core';
+import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
 import { Router, ActivatedRoute, ParamMap } from '@angular/router';
 import { MatDialog } from '@angular/material/dialog';
 import { Subject } from 'rxjs';
@@ -10,15 +10,14 @@ import { dedupeObjectArray } from '../../shared/utils';
 import { DialogsLoadingService } from '../../shared/dialogs/dialogs-loading.service';
 import { findDocuments } from '../../shared/mangoQueries';
 import { UserProfileDialogComponent } from '../../users/users-profile/users-profile-dialog.component';
+import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
 
 @Component({
-  templateUrl: 'courses-progress-leader.component.html',
-  styleUrls: [ 'courses-progress.scss' ]
+  templateUrl: 'courses-progress-leader.component.html'
 })
 export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
 
   course: any;
-  // Need to define this variable for template which is shared with CoursesProgressLearner
   headingStart = '';
   chartLabel = $localize`Steps`;
   selectedStep: any;
@@ -32,6 +31,8 @@ export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
   submittedExamSteps: any[] = [];
   planetCodes: string[] = [];
   selectedPlanetCode: string;
+  deviceType: DeviceType;
+  deviceTypes = DeviceType;
 
   constructor(
     private router: Router,
@@ -40,9 +41,11 @@ export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
     private submissionsService: SubmissionsService,
     private csvService: CsvService,
     private dialogsLoadingService: DialogsLoadingService,
-    private dialog: MatDialog
+    private dialog: MatDialog,
+    private deviceInfoService: DeviceInfoService
   ) {
     this.dialogsLoadingService.start();
+    this.deviceType = this.deviceInfoService.getDeviceType();
   }
 
   ngOnInit() {
@@ -66,6 +69,11 @@ export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
     this.onDestroy$.complete();
   }
 
+  @HostListener('window:resize')
+  onResize() {
+    this.deviceType = this.deviceInfoService.getDeviceType();
+  }
+
   setProgress(course) {
     this.coursesService.findProgress([ course._id ], { allUsers: true }).subscribe((progress) => {
       this.progress = progress;

From cf3f47c67775fa579345e1d7b36ded73b641759e Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Thu, 5 Dec 2024 14:05:10 -0800
Subject: [PATCH 033/113] courses: smoother steps preview title (fixes #7868)
 (#7879)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../view-courses/courses-view.component.html  |  2 +-
 .../courses/view-courses/courses-view.scss    | 26 ++++++++++++++++---
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 05e6afc14e..5a3593831e 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.82",
+  "version": "0.15.83",
   "myplanet": {
     "latest": "v0.21.28",
     "min": "v0.20.28"
diff --git a/src/app/courses/view-courses/courses-view.component.html b/src/app/courses/view-courses/courses-view.component.html
index b6eedb7993..3e33f0bd70 100644
--- a/src/app/courses/view-courses/courses-view.component.html
+++ b/src/app/courses/view-courses/courses-view.component.html
@@ -65,7 +65,7 @@ <h3 class="margin-lr-3 ellipsis-title">{{courseDetail.courseTitle}}</h3>
         <ng-container *ngFor="let step of courseDetail.steps; let stepNum = index; trackBy: trackBySteps">
           <mat-expansion-panel hideToggle="true" (opened)="setStepButtonStatus(step, stepNum)">
             <mat-expansion-panel-header>
-              <mat-panel-title i18n>
+              <mat-panel-title class="step-title" i18n>
                 {{step.stepTitle || 'Step ' + (stepNum + 1)}}
               </mat-panel-title>
               <mat-panel-description>
diff --git a/src/app/courses/view-courses/courses-view.scss b/src/app/courses/view-courses/courses-view.scss
index 5b8d6caa87..5db279dfb1 100644
--- a/src/app/courses/view-courses/courses-view.scss
+++ b/src/app/courses/view-courses/courses-view.scss
@@ -47,10 +47,30 @@
       grid-template-columns: 1fr;
       grid-template-rows: 0 1fr;
     } 
+    
+  }
+}
 
-    .course-detail, .course-view {
-      overflow: visible;
-    }
+mat-expansion-panel-header {
+  display: flex;
+  justify-content: space-between;
+}
+
+mat-panel-title {
+  display: block;
+}
+
+.step-title {
+  max-width: 150ch;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+
+  @media (max-width: $screen-md) {
+    max-width: 90ch;
   }
 
+  @media (max-width: $screen-sm) {
+    max-width: 45ch;
+  }
 }

From af73fc9a664f976abd2b9ffd1a8735827998c6c9 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Fri, 6 Dec 2024 23:37:07 +0300
Subject: [PATCH 034/113] all: smoother empty tables (fixes #7882) (#7883)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                          |  6 +++---
 src/app/courses/courses.component.html                |  9 ++++-----
 src/app/courses/courses.component.ts                  |  3 ---
 .../enroll-courses/courses-enroll.component.html      |  7 +------
 .../enroll-courses/courses-enroll.component.ts        |  2 --
 src/app/feedback/feedback.component.html              | 11 +++++------
 src/app/feedback/feedback.component.ts                |  2 --
 src/app/health/health-list.component.html             |  7 +------
 src/app/health/health-list.component.ts               |  2 --
 .../certifications/certifications.component.html      |  8 ++++----
 .../certifications/certifications.component.ts        |  2 --
 .../manager-dashboard/manager-fetch.component.html    |  8 ++++----
 src/app/manager-dashboard/manager-fetch.component.ts  |  2 --
 src/app/meetups/meetups.component.html                |  8 ++++----
 src/app/meetups/meetups.component.ts                  |  2 --
 src/app/notifications/notifications.component.html    |  8 ++++----
 src/app/notifications/notifications.component.ts      |  2 --
 src/app/resources/resources.component.html            |  8 ++++----
 src/app/resources/resources.component.ts              |  3 ---
 src/app/submissions/submissions.component.html        |  8 ++++----
 src/app/submissions/submissions.component.ts          |  3 ---
 src/app/surveys/surveys.component.html                | 10 +++++-----
 src/app/surveys/surveys.component.ts                  |  2 --
 src/app/teams/teams.component.html                    |  8 ++++----
 src/app/teams/teams.component.ts                      |  2 --
 src/app/users/users-table.component.html              |  3 +++
 src/app/users/users.component.html                    |  7 +------
 src/app/users/users.component.ts                      |  1 -
 28 files changed, 51 insertions(+), 93 deletions(-)

diff --git a/package.json b/package.json
index 5a3593831e..cd6d82b9d9 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.83",
+  "version": "0.15.84",
   "myplanet": {
-    "latest": "v0.21.28",
-    "min": "v0.20.28"
+    "latest": "v0.21.29",
+    "min": "v0.20.29"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/courses.component.html b/src/app/courses/courses.component.html
index 840bcd8da2..554f750401 100644
--- a/src/app/courses/courses.component.html
+++ b/src/app/courses/courses.component.html
@@ -104,7 +104,7 @@
     </ng-container>
   </ng-template>
 
-  <div [ngClass]="{ 'view-container view-full-height view-table': !isForm }" *ngIf="!emptyData; else notFoundMessage">
+  <div [ngClass]="{ 'view-container view-full-height view-table': !isForm }">
     <mat-table #table [dataSource]="courses" matSort [matSortDisableClear]="true" [trackBy]="trackById">
       <ng-container matColumnDef="select">
         <mat-header-cell *matHeaderCellDef>
@@ -231,15 +231,14 @@ <h3 class="header">
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
       <mat-row *matRowDef="let row; columns: displayedColumns;" [ngClass]="{highlight:selection.isSelected(row._id)}"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Course Found</div></td>
+      </tr>
     </mat-table>
-
     <mat-paginator #paginator
       [pageSize]="50"
       [pageSizeOptions]="[5, 10, 20, 50, 100, 200]"
       (page)="onPaginateChange($event)">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Course Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/courses/courses.component.ts b/src/app/courses/courses.component.ts
index 51f489444e..f036d867cb 100644
--- a/src/app/courses/courses.component.ts
+++ b/src/app/courses/courses.component.ts
@@ -88,7 +88,6 @@ export class CoursesComponent implements OnInit, OnChanges, AfterViewInit, OnDes
   userShelf: any = [];
   private onDestroy$ = new Subject<void>();
   planetType = this.planetConfiguration.planetType;
-  emptyData = false;
   isAuthorized = false;
   tagFilter = new FormControl([]);
   tagFilterValue = [];
@@ -158,7 +157,6 @@ export class CoursesComponent implements OnInit, OnChanges, AfterViewInit, OnDes
       this.userShelf = this.userService.shelf;
       this.courses.data = this.setupList(courses, this.userShelf.courseIds)
         .filter((course: any) => this.excludeIds.indexOf(course._id) === -1);
-      this.emptyData = !this.courses.data.length;
       this.dialogsLoadingService.stop();
     });
     this.selection.changed.subscribe(({ source }) => {
@@ -335,7 +333,6 @@ export class CoursesComponent implements OnInit, OnChanges, AfterViewInit, OnDes
 
   removeFilteredFromSelection() {
     this.selection.deselect(...selectedOutOfFilter(this.courses.filteredData, this.selection, this.paginator));
-    this.emptyData = this.courses.filteredData.length === 0;
   }
 
   onSearchChange({ items, category }) {
diff --git a/src/app/courses/enroll-courses/courses-enroll.component.html b/src/app/courses/enroll-courses/courses-enroll.component.html
index fab9af1283..e05788bd80 100644
--- a/src/app/courses/enroll-courses/courses-enroll.component.html
+++ b/src/app/courses/enroll-courses/courses-enroll.component.html
@@ -13,10 +13,5 @@
     </button>
   </mat-toolbar>
 
-  <ng-container *ngIf="!emptyData; else notFoundMessage">
-    <planet-users-table [users]="members" [(tableState)]="tableState" [displayedColumns]="userTableColumns" [shouldOpenProfileDialog]="true" containerClass="view-container view-full-height view-table"></planet-users-table>
-  </ng-container>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No User Found</div>
-  </ng-template>
+  <planet-users-table [users]="members" [(tableState)]="tableState" [displayedColumns]="userTableColumns" [shouldOpenProfileDialog]="true" containerClass="view-container view-full-height view-table"></planet-users-table>
 </div>
diff --git a/src/app/courses/enroll-courses/courses-enroll.component.ts b/src/app/courses/enroll-courses/courses-enroll.component.ts
index dbcb54e23d..79fc7e7319 100644
--- a/src/app/courses/enroll-courses/courses-enroll.component.ts
+++ b/src/app/courses/enroll-courses/courses-enroll.component.ts
@@ -22,7 +22,6 @@ export class CoursesEnrollComponent {
   course: any;
   members: any[] = [];
   tableState = new TableState();
-  emptyData = false;
   userTableColumns = [
     'profile',
     'name',
@@ -82,7 +81,6 @@ export class CoursesEnrollComponent {
         ),
         planet: planets.find(planet => planet.doc.code === user.doc.planetCode)
       })).filter(doc => doc.planet !== undefined && (doc.activityDates.createdDate || shelfUsers.find((u: any) => u._id === doc._id)));
-    this.emptyData = this.members.length === 0;
   }
 
   exportCSV() {
diff --git a/src/app/feedback/feedback.component.html b/src/app/feedback/feedback.component.html
index f98b6ffdc2..3990964b1d 100644
--- a/src/app/feedback/feedback.component.html
+++ b/src/app/feedback/feedback.component.html
@@ -63,7 +63,7 @@
     </mat-toolbar-row>
   </mat-toolbar>
 
-  <div class="view-container view-full-height view-table" *ngIf="!emptyData; else notFoundMessage">
+  <div class="view-container view-full-height view-table">
     <mat-table #table [dataSource]="feedback" matSort [matSortDisableClear]="true">
       <!-- Title Column -->
       <ng-container matColumnDef="title">
@@ -148,12 +148,11 @@
         </mat-cell>
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
-      <mat-row *matRowDef="let row; columns: displayedColumns" class="cursor-pointer" [routerLink]="['view', row._id]">
-      </mat-row>
+      <mat-row *matRowDef="let row; columns: displayedColumns" class="cursor-pointer" [routerLink]="['view', row._id]"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Feedback Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator [pageSize]="50" [pageSizeOptions]="[5, 10, 20, 50, 100, 200]" i18n></mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Feedback Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/feedback/feedback.component.ts b/src/app/feedback/feedback.component.ts
index d7ac201d0c..494792b1d6 100644
--- a/src/app/feedback/feedback.component.ts
+++ b/src/app/feedback/feedback.component.ts
@@ -53,7 +53,6 @@ export class FeedbackComponent implements OnInit, AfterViewInit, OnDestroy {
   @ViewChild(MatSort) sort: MatSort;
   user: any = {};
   private onDestroy$ = new Subject<void>();
-  emptyData = false;
   users = [];
   deviceType: DeviceType;
   deviceTypes: typeof DeviceType = DeviceType;
@@ -115,7 +114,6 @@ export class FeedbackComponent implements OnInit, AfterViewInit, OnDestroy {
     const selector = !this.user.isUserAdmin ? { 'owner': this.user.name } : { '_id': { '$gt': null } };
     this.couchService.findAll(this.dbName, findDocuments(selector, 0, [ { 'openTime': 'desc' } ])).subscribe((feedbackData: any[]) => {
       this.feedback.data = feedbackData.map(feedback => ({ ...feedback, user: this.users.find(u => u.doc.name === feedback.owner) }));
-      this.emptyData = !this.feedback.data.length;
       this.dialogsLoadingService.stop();
     }, (error) => this.message = $localize`There is a problem of getting data.`);
   }
diff --git a/src/app/health/health-list.component.html b/src/app/health/health-list.component.html
index 4cbda7cc81..1ed73b87bd 100644
--- a/src/app/health/health-list.component.html
+++ b/src/app/health/health-list.component.html
@@ -10,10 +10,5 @@
 </mat-toolbar>
 
 <div class="space-container">
-  <ng-container *ngIf="!emptyData; else notFoundMessage">
-    <planet-users-table #table [users]="users" [search]="searchValue" [filter]="{}" [(tableState)]="tableState" [displayedColumns]="displayedColumns" containerClass="view-container view-full-height no-toolbar view-table" (tableDataChange)="tableDataChange($event)"></planet-users-table>
-  </ng-container>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No User Found</div>
-  </ng-template>
+  <planet-users-table #table [users]="users" [search]="searchValue" [filter]="{}" [(tableState)]="tableState" [displayedColumns]="displayedColumns" containerClass="view-container view-full-height no-toolbar view-table" (tableDataChange)="tableDataChange($event)"></planet-users-table>
 </div>
diff --git a/src/app/health/health-list.component.ts b/src/app/health/health-list.component.ts
index 0cc6a03bc5..7b23924d05 100644
--- a/src/app/health/health-list.component.ts
+++ b/src/app/health/health-list.component.ts
@@ -16,7 +16,6 @@ export class HealthListComponent implements OnInit, OnDestroy {
   users: any[] = [];
   displayedColumns = [ 'profile', 'name', 'contact', 'birthDate', 'lastVisit' ];
   tableState = new TableState();
-  emptyData = true;
   healthRequests: string[] = [];
 
   constructor(
@@ -29,7 +28,6 @@ export class HealthListComponent implements OnInit, OnDestroy {
   ngOnInit() {
     this.usersService.usersListener().pipe(takeUntil(this.onDestroy$)).subscribe(users => {
       this.users = users;
-      this.emptyData = this.users.length === 0;
     });
     this.usersService.requestUserData();
   }
diff --git a/src/app/manager-dashboard/certifications/certifications.component.html b/src/app/manager-dashboard/certifications/certifications.component.html
index 3b77224266..2795550906 100644
--- a/src/app/manager-dashboard/certifications/certifications.component.html
+++ b/src/app/manager-dashboard/certifications/certifications.component.html
@@ -15,7 +15,7 @@
   <mat-toolbar class="primary-color font-size-1">
     <a i18n mat-mini-fab routerLink="add"><mat-icon>add</mat-icon></a>
   </mat-toolbar>
-  <div *ngIf="!emptyData; else notFoundMessage" class="view-container view-full-height view-table">
+  <div class="view-container view-full-height view-table">
     <mat-table #table [dataSource]="certifications" matSort [matSortDisableClear]="true">
       <ng-container matColumnDef="name">
         <mat-header-cell i18n *matHeaderCellDef mat-sort-header="name">Certification Name</mat-header-cell>
@@ -34,13 +34,13 @@
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
       <mat-row class="cursor-pointer" *matRowDef="let row; columns: displayedColumns;" [routerLink]="[ 'view/' + row._id ]"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div i18n class="view-container" i18n>No Certifications Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator
       [pageSize]="50"
       [pageSizeOptions]="[5, 10, 20, 50, 100, 200]">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div i18n class="view-container" i18n>No Certifications Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/manager-dashboard/certifications/certifications.component.ts b/src/app/manager-dashboard/certifications/certifications.component.ts
index d2e0a06ef4..c1bccf735a 100644
--- a/src/app/manager-dashboard/certifications/certifications.component.ts
+++ b/src/app/manager-dashboard/certifications/certifications.component.ts
@@ -13,7 +13,6 @@ export class CertificationsComponent implements OnInit, AfterViewInit {
 
   certifications = new MatTableDataSource();
   selection = new SelectionModel(true, []);
-  emptyData = false;
   displayedColumns = [
     'name',
     'action'
@@ -54,7 +53,6 @@ export class CertificationsComponent implements OnInit, AfterViewInit {
   getCertifications() {
     this.certificationsService.getCertifications().subscribe((certifications: any) => {
       this.certifications.data = certifications;
-      this.emptyData = !this.certifications.data.length;
     });
   }
 
diff --git a/src/app/manager-dashboard/manager-fetch.component.html b/src/app/manager-dashboard/manager-fetch.component.html
index e8870be32b..285a4fdb5c 100644
--- a/src/app/manager-dashboard/manager-fetch.component.html
+++ b/src/app/manager-dashboard/manager-fetch.component.html
@@ -11,7 +11,7 @@
     </button>
   </mat-toolbar>
 
-  <div class="view-container view-full-height view-table" *ngIf="!emptyData; else notFoundMessage">
+  <div class="view-container view-full-height view-table">
     <mat-table #table [dataSource]="pushedItems" matSort>
       <ng-container matColumnDef="select">
         <mat-header-cell *matHeaderCellDef>
@@ -41,6 +41,9 @@
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
       <mat-row *matRowDef="let row; columns: displayedColumns;" class="cursor-pointer" [ngClass]="{highlight:selection.isSelected(row._id)}" (click)="selection.toggle(row._id)"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Record Found</div></td>
+      </tr>
     </mat-table>
 
     <mat-paginator #paginator
@@ -49,7 +52,4 @@
       (page)="onPaginateChange($event)">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Record Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/manager-dashboard/manager-fetch.component.ts b/src/app/manager-dashboard/manager-fetch.component.ts
index 6d02ce7757..b2dde6d9c0 100644
--- a/src/app/manager-dashboard/manager-fetch.component.ts
+++ b/src/app/manager-dashboard/manager-fetch.component.ts
@@ -32,7 +32,6 @@ export class ManagerFetchComponent implements OnInit, AfterViewInit {
   planetConfiguration = this.stateService.configuration;
   displayedColumns = [ 'select', 'item', 'date' ];
   pushedItems = new MatTableDataSource();
-  emptyData = false;
 
   constructor(
     private couchService: CouchService,
@@ -46,7 +45,6 @@ export class ManagerFetchComponent implements OnInit, AfterViewInit {
   ngOnInit() {
     this.managerService.getPushedList().subscribe((pushedList: any) => {
       this.pushedItems.data = pushedList;
-      this.emptyData = !this.pushedItems.data.length;
     });
   }
 
diff --git a/src/app/meetups/meetups.component.html b/src/app/meetups/meetups.component.html
index f797434d05..36d84e5b81 100644
--- a/src/app/meetups/meetups.component.html
+++ b/src/app/meetups/meetups.component.html
@@ -34,7 +34,7 @@
     </ng-container>
   </mat-toolbar>
 
-  <div class="view-container view-full-height view-table" *ngIf="!emptyData; else notFoundMessage">
+  <div class="view-container view-full-height view-table">
     <mat-table #table [dataSource]="meetups" matSort [matSortDisableClear]="true">
       <ng-container matColumnDef="select">
         <mat-header-cell *matHeaderCellDef>
@@ -103,6 +103,9 @@ <h3 class="header">
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns" class="hide"></mat-header-row>
       <mat-row *matRowDef="let row; columns: displayedColumns;" [ngClass]="{highlight:selection.isSelected(row._id)}"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Meetups Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator
       [pageSize]="50"
@@ -110,7 +113,4 @@ <h3 class="header">
       (page)="onPaginateChange($event)">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Meetups Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/meetups/meetups.component.ts b/src/app/meetups/meetups.component.ts
index 3bc929eee7..33210263a6 100644
--- a/src/app/meetups/meetups.component.ts
+++ b/src/app/meetups/meetups.component.ts
@@ -43,7 +43,6 @@ export class MeetupsComponent implements OnInit, AfterViewInit, OnDestroy {
   getOpts = this.parent ? { domain: this.stateService.configuration.parentDomain } : {};
   pageEvent: PageEvent;
   currentUser = this.userService.get();
-  emptyData = false;
   selectedNotJoined = 0;
   selectedJoined = 0;
   isAuthorized = false;
@@ -69,7 +68,6 @@ export class MeetupsComponent implements OnInit, AfterViewInit, OnDestroy {
       // Sort in descending createdDate order, so the new meetup can be shown on the top
       meetups.sort((a, b) => b.createdDate - a.createdDate);
       this.meetups.data = meetups;
-      this.emptyData = !this.meetups.data.length;
       this.dialogsLoadingService.stop();
     });
     this.meetupService.updateMeetups({ opts: this.getOpts });
diff --git a/src/app/notifications/notifications.component.html b/src/app/notifications/notifications.component.html
index 14635947b7..3788896032 100644
--- a/src/app/notifications/notifications.component.html
+++ b/src/app/notifications/notifications.component.html
@@ -11,7 +11,7 @@
       </mat-select>
     </mat-form-field>
   </mat-toolbar>
-  <ng-container *ngIf="!emptyData; else notFoundMessage">
+  <ng-container>
     <mat-table #table [dataSource]="notifications">
       <ng-container matColumnDef="message">
         <mat-cell *matCellDef="let element" (click)="readNotification(element)">
@@ -37,13 +37,13 @@
         </mat-cell>
       </ng-container>
       <mat-row *matRowDef="let row; columns: displayedColumns;" ></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Notification Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator
       [pageSize]="50"
       [pageSizeOptions]="[5, 10, 20, 50, 100, 200]">
     </mat-paginator>
   </ng-container>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Notification Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/notifications/notifications.component.ts b/src/app/notifications/notifications.component.ts
index 0dec83f4c4..19198b770b 100644
--- a/src/app/notifications/notifications.component.ts
+++ b/src/app/notifications/notifications.component.ts
@@ -22,7 +22,6 @@ export class NotificationsComponent implements OnInit, AfterViewInit {
   notifications = new MatTableDataSource<any>();
   displayedColumns = [ 'message', 'read' ];
   private onDestroy$ = new Subject<void>();
-  emptyData = false;
   notificationStatus = [ 'All', 'Read', 'Unread' ];
   filter = { 'status': '' };
   anyUnread = true;
@@ -65,7 +64,6 @@ export class NotificationsComponent implements OnInit, AfterViewInit {
     .subscribe(notifications => {
        this.notifications.data = notifications;
        this.anyUnread = this.notifications.data.some(notification => notification.status === 'unread');
-       this.emptyData = !this.notifications.data.length;
     }, (err) => console.log(err.error.reason));
   }
 
diff --git a/src/app/resources/resources.component.html b/src/app/resources/resources.component.html
index 50375e431e..7d8ad39798 100644
--- a/src/app/resources/resources.component.html
+++ b/src/app/resources/resources.component.html
@@ -103,7 +103,7 @@
     </mat-menu>
   </ng-template>
 
-  <div class="view-container view-full-height view-table" [ngClass]="{'view-with-search':showFilters}" *ngIf="!emptyData; else notFoundMessage">
+  <div class="view-container view-full-height view-table" [ngClass]="{'view-with-search':showFilters}">
     <mat-table #table [dataSource]="resources" [matSortActive]="initialSort" matSortDirection="desc" matSort [matSortDisableClear]="true" [trackBy]="trackById">
       <ng-container matColumnDef="select">
         <mat-header-cell *matHeaderCellDef>
@@ -208,6 +208,9 @@ <h3 class="header">
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns" class="hide"></mat-header-row>
       <mat-row *matRowDef="let row; columns: displayedColumns;" [ngClass]="{highlight:selection.isSelected(row._id)}"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Resource Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator
       [pageSize]="50"
@@ -215,7 +218,4 @@ <h3 class="header">
       (page)="onPaginateChange($event)">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Resource Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/resources/resources.component.ts b/src/app/resources/resources.component.ts
index 27a9975646..91cae48c56 100644
--- a/src/app/resources/resources.component.ts
+++ b/src/app/resources/resources.component.ts
@@ -71,7 +71,6 @@ export class ResourcesComponent implements OnInit, AfterViewInit, OnDestroy {
     this.removeFilteredFromSelection();
   }
   myView = this.route.snapshot.data.view;
-  emptyData = false;
   selectedNotAdded = 0;
   selectedAdded = 0;
   selectedSync = [];
@@ -138,7 +137,6 @@ export class ResourcesComponent implements OnInit, AfterViewInit, OnDestroy {
             (resource.doc.private === true && (resource.doc.privateFor || {}).users === this.userService.get()._id) :
             resource.doc.private !== true)
       );
-      this.emptyData = !this.resources.data.length;
       this.resources.paginator = this.paginator;
       this.dialogsLoadingService.stop();
     });
@@ -168,7 +166,6 @@ export class ResourcesComponent implements OnInit, AfterViewInit, OnDestroy {
 
   removeFilteredFromSelection() {
     this.selection.deselect(...selectedOutOfFilter(this.resources.filteredData, this.selection, this.paginator));
-    this.emptyData = this.resources.filteredData.length === 0;
   }
 
 
diff --git a/src/app/submissions/submissions.component.html b/src/app/submissions/submissions.component.html
index 2a977bab28..950e0b2fbf 100644
--- a/src/app/submissions/submissions.component.html
+++ b/src/app/submissions/submissions.component.html
@@ -54,7 +54,7 @@
 </ng-template>
 
 <div class="primary-link-hover" [ngClass]="{ 'space-container': !isDialog }">
-  <div class="view-container view-table responsive-table" [ngClass]="{ 'view-full-height no-toolbar': !isDialog }" *ngIf="!emptyData; else notFoundMessage">
+  <div class="view-container view-table responsive-table" [ngClass]="{ 'view-full-height no-toolbar': !isDialog }">
     <mat-table #table [dataSource]="submissions" matSort [matSortDisableClear]="true">
       <ng-container matColumnDef="name">
         <mat-header-cell *matHeaderCellDef mat-sort-header="name" i18n>Name</mat-header-cell>
@@ -103,13 +103,13 @@
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns" class="hide"></mat-header-row>
       <mat-row *matRowDef="let row; columns: displayedColumns;" (click)="submissionAction(row)" [ngClass]="{'cursor-pointer': row.status!=='pending' || mode === 'survey'}"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Record Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator
       [pageSize]="50"
       [pageSizeOptions]="[5, 10, 20, 50, 100, 200]">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No Record Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/submissions/submissions.component.ts b/src/app/submissions/submissions.component.ts
index 7c1bd8f946..dbc3a39ed9 100644
--- a/src/app/submissions/submissions.component.ts
+++ b/src/app/submissions/submissions.component.ts
@@ -46,7 +46,6 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
     { text: $localize`Completed`, value: 'complete' }
   ];
   mode = 'grade';
-  emptyData = false;
   filter = {
     type: 'exam',
     status: 'requires grading'
@@ -96,7 +95,6 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
       }));
       this.dialogsLoadingService.stop();
       this.applyFilter('');
-      this.emptyData = !this.submissions.filteredData.length;
     });
     this.submissionsService.updateSubmissions({ query: this.submissionQuery() });
     this.setupTable();
@@ -163,7 +161,6 @@ export class SubmissionsComponent implements OnInit, AfterViewChecked, OnDestroy
     this.filter[field] = filterValue === 'All' ? '' : filterValue;
     // Force filter to update by setting it to a space if empty
     this.submissions.filter = this.submissions.filter || ' ';
-    this.emptyData = !this.submissions.filteredData.length;
     this.displayedColumns = columnsByFilterAndMode[this.filter.type][this.mode] || this.displayedColumns;
     this.submissions.paginator = undefined;
     this.submissions.sort = undefined;
diff --git a/src/app/surveys/surveys.component.html b/src/app/surveys/surveys.component.html
index 37ac02a856..cd3302a9bd 100644
--- a/src/app/surveys/surveys.component.html
+++ b/src/app/surveys/surveys.component.html
@@ -17,13 +17,13 @@
     </button>
     <span class="toolbar-fill"></span>
     <ng-container *planetAuthorizedRoles="'manager'">
-      <button mat-button (click)="deleteSelected()" [disabled]="!selection.selected.length" *ngIf="!emptyData">
+      <button mat-button (click)="deleteSelected()" [disabled]="!selection.selected.length">
         <mat-icon aria-hidden="true" class="margin-lr-3">delete_forever</mat-icon><span i18n>Delete</span>
         <span *ngIf="selection?.selected?.length"> ({{selection?.selected?.length}})</span>
       </button>
     </ng-container>
   </mat-toolbar>
-  <div class="view-container view-full-height view-table" *ngIf="!emptyData; else notFoundMessage">
+  <div class="view-container view-full-height view-table">
     <mat-table #table [dataSource]="surveys" matSort matSortActive="createdDate" matSortDirection="desc" [matSortDisableClear]="true">
       <ng-container matColumnDef="select">
         <mat-header-cell *matHeaderCellDef>
@@ -81,6 +81,9 @@
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
       <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No Survey Found</div></td>
+      </tr>
     </mat-table>
     <mat-paginator #paginator
       [pageSize]="50"
@@ -88,7 +91,4 @@
       (page)="onPaginateChange($event)">
     </mat-paginator>
     </div>
-    <ng-template #notFoundMessage>
-      <div class="view-container" i18n>No Survey Found</div>
-    </ng-template>
 </div>
diff --git a/src/app/surveys/surveys.component.ts b/src/app/surveys/surveys.component.ts
index 78ed9b4b0c..8df508e2fc 100644
--- a/src/app/surveys/surveys.component.ts
+++ b/src/app/surveys/surveys.component.ts
@@ -39,7 +39,6 @@ export class SurveysComponent implements OnInit, AfterViewInit, OnDestroy {
   dialogRef: MatDialogRef<DialogsAddTableComponent>;
   private onDestroy$ = new Subject<void>();
   readonly dbName = 'exams';
-  emptyData = false;
   isAuthorized = false;
   deleteDialog: any;
   message = '';
@@ -82,7 +81,6 @@ export class SurveysComponent implements OnInit, AfterViewInit, OnDestroy {
         ...this.createParentSurveys(submissions)
       ];
       this.surveys.data = this.surveys.data.map((data: any) => ({ ...data, courseTitle: data.course ? data.course.courseTitle : '' }));
-      this.emptyData = !this.surveys.data.length;
       this.dialogsLoadingService.stop();
     });
     this.couchService.checkAuthorization(this.dbName).subscribe((isAuthorized) => this.isAuthorized = isAuthorized);
diff --git a/src/app/teams/teams.component.html b/src/app/teams/teams.component.html
index c523f72a3f..033295d432 100644
--- a/src/app/teams/teams.component.html
+++ b/src/app/teams/teams.component.html
@@ -38,7 +38,7 @@
     </ng-container>
   </mat-toolbar>
 
-  <div class="primary-link-hover" *ngIf="!emptyData; else notFoundMessage" [ngClass]="{'view-container view-table view-full-height':!isDialog}">
+  <div class="primary-link-hover" [ngClass]="{'view-container view-table view-full-height':!isDialog}">
     <mat-table #table [dataSource]="teams" matSortActive="visitLog.visitCount" matSortDirection="desc" matSort [matSortDisableClear]="true">
       <ng-container matColumnDef="doc.name">
         <mat-header-cell *matHeaderCellDef mat-sort-header="doc.name" i18n>Name</mat-header-cell>
@@ -116,6 +116,9 @@ <h3>
       </ng-container>
       <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
       <mat-row (click)="teamClick(row.doc._id, row.doc.teamType)" *matRowDef="let row; columns: displayedColumns;"></mat-row>
+      <tr class="mat-row" *matNoDataRow>
+        <td><div class="view-container" i18n>No { mode, select, team {Teams} enterprise {Enterprises} } Found</div></td>
+      </tr>
     </mat-table>
     <div *ngIf="userNotInShelf" i18n style="text-align: center;">
       Oops ... Error: no full access in Teams and Enterprises (data missing) ... please contact the manager of this site
@@ -125,7 +128,4 @@ <h3>
       [pageSizeOptions]="[5, 10, 20, 50, 100, 200]">
     </mat-paginator>
   </div>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No { mode, select, team {Teams} enterprise {Enterprises} } Found</div>
-  </ng-template>
 </div>
diff --git a/src/app/teams/teams.component.ts b/src/app/teams/teams.component.ts
index 7a39a9ab93..758e5d7fd2 100644
--- a/src/app/teams/teams.component.ts
+++ b/src/app/teams/teams.component.ts
@@ -33,7 +33,6 @@ export class TeamsComponent implements OnInit, AfterViewInit {
   userMembership: any[] = [];
   teamActivities: any[] = [];
   dbName = 'teams';
-  emptyData = false;
   user = this.userService.get();
   isAuthorized = false;
   planetType = this.stateService.configuration.planetType;
@@ -123,7 +122,6 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       )) {
         this.userService.addImageForReplication(true).subscribe(() => {});
       }
-      this.emptyData = !this.teams.data.length;
       this.dialogsLoadingService.stop();
     }, (error) => {
       if (this.userNotInShelf) {
diff --git a/src/app/users/users-table.component.html b/src/app/users/users-table.component.html
index 6a6b009457..613bf4c617 100644
--- a/src/app/users/users-table.component.html
+++ b/src/app/users/users-table.component.html
@@ -136,6 +136,9 @@
     </ng-container>
     <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
     <mat-row [ngClass]="{'cursor-pointer':!isDialog}" *matRowDef= "let row; columns: displayedColumns;" (click)="gotoProfileView(row.doc.name)" [ngClass]="{highlight:isSelected(row.doc)}"></mat-row>
+    <tr class="mat-row" *matNoDataRow>
+      <td><div class="view-container" i18n>No User Found</div></td>
+    </tr>
   </mat-table>
   <mat-paginator #paginator
     [pageSize]="50"
diff --git a/src/app/users/users.component.html b/src/app/users/users.component.html
index 754f62e9a6..62da847bea 100644
--- a/src/app/users/users.component.html
+++ b/src/app/users/users.component.html
@@ -82,10 +82,5 @@
     </div>
   </mat-toolbar>
 
-  <ng-container *ngIf="!emptyData; else notFoundMessage">
-    <planet-users-table #table [users]="users" [search]="searchValue" [filter]="filter" [(tableState)]="tableState" containerClass="view-container view-full-height view-table" [isDialog]="isDialog"></planet-users-table>
-  </ng-container>
-  <ng-template #notFoundMessage>
-    <div class="view-container" i18n>No User Found</div>
-  </ng-template>
+  <planet-users-table #table [users]="users" [search]="searchValue" [filter]="filter" [(tableState)]="tableState" containerClass="view-container view-full-height view-table" [isDialog]="isDialog"></planet-users-table>
 </div>
diff --git a/src/app/users/users.component.ts b/src/app/users/users.component.ts
index 5023c17003..688b602736 100644
--- a/src/app/users/users.component.ts
+++ b/src/app/users/users.component.ts
@@ -46,7 +46,6 @@ export class UsersComponent implements OnInit, OnDestroy {
   filteredRole: string;
   userShelf = this.userService.shelf;
   private onDestroy$ = new Subject<void>();
-  emptyData = false;
   private searchChange = new Subject<string>();
   configuration = this.stateService.configuration;
   tableState = new TableState();

From 7298f8b8362f4d690e4eb10f32811624cbe4ef95 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Fri, 6 Dec 2024 12:45:49 -0800
Subject: [PATCH 035/113] surveys: smoother loading (fixes #7877) (#7903)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                          | 2 +-
 src/app/exams/exams-view.component.ts | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index cd6d82b9d9..9dc4a39345 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.84",
+  "version": "0.15.85",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/exams/exams-view.component.ts b/src/app/exams/exams-view.component.ts
index 380bcb1937..04cd67d8c1 100644
--- a/src/app/exams/exams-view.component.ts
+++ b/src/app/exams/exams-view.component.ts
@@ -274,6 +274,7 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
       }
       this.isNewQuestion = false;
       this.isComplete = this.unansweredQuestions && this.unansweredQuestions.every(number => this.questionNum === number);
+      this.isLoading = false;
   });
 }
 

From 6d3a25023fa7e8bab2cbeaa7fcb89e0e39360f56 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Fri, 6 Dec 2024 15:54:42 -0500
Subject: [PATCH 036/113] teams: smoother delete message (fixes #7885) (#7899)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     | 2 +-
 src/app/teams/teams.component.ts | 7 ++-----
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index 9dc4a39345..3d2849eef3 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.85",
+  "version": "0.15.86",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/teams/teams.component.ts b/src/app/teams/teams.component.ts
index 758e5d7fd2..9fdb471b82 100644
--- a/src/app/teams/teams.component.ts
+++ b/src/app/teams/teams.component.ts
@@ -236,11 +236,8 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       request: this.teamsService.archiveTeam(team)().pipe(switchMap(() => this.teamsService.deleteCommunityLink(team))),
       onNext: () => {
         this.deleteDialog.close();
-        if (this.mode === 'enterprise') {
-          this.planetMessageService.showMessage($localize`You have deleted an ${toProperCase(this.mode)}.`);
-        } else {
-          this.planetMessageService.showMessage($localize`You have deleted a ${toProperCase(this.mode)}.`);
-        }
+        const entityType = this.mode === 'enterprise' ? 'enterprise' : 'team';
+        this.planetMessageService.showMessage($localize`You have deleted ${entityType} ${team.name}.`);
         this.removeTeamFromTable(team);
       },
       onError: () => this.planetMessageService.showAlert($localize`There was a problem deleting this team.`)

From f65801e19eff46948cd7fcfa5f8b45798d005216 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Sat, 7 Dec 2024 00:00:53 +0300
Subject: [PATCH 037/113] courses: smoother filter list (fixes #7880) (#7901)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                   | 2 +-
 src/app/courses/search-courses/courses-search.component.ts     | 3 ++-
 .../resources/search-resources/resources-search.component.ts   | 3 ++-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 3d2849eef3..f41223f140 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.86",
+  "version": "0.15.87",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/courses/search-courses/courses-search.component.ts b/src/app/courses/search-courses/courses-search.component.ts
index f48e0e80fc..96479f0486 100644
--- a/src/app/courses/search-courses/courses-search.component.ts
+++ b/src/app/courses/search-courses/courses-search.component.ts
@@ -25,7 +25,7 @@ import { MatSelectionList } from '@angular/material/list';
     </span>
     <mat-selection-list (selectionChange)="selectionChange($event)">
       <mat-list-option *ngFor="let item of items" [value]="item.value" [selected]="isSelected(item)" checkboxPosition="before">
-        {{item.label}}
+        {{item?.label || 'N/A'}}
       </mat-list-option>
     </mat-selection-list>
   `,
@@ -116,6 +116,7 @@ export class CoursesSearchComponent implements OnInit, OnChanges {
       items: data.reduce((list, { doc }) => list.concat(doc[category.label]), []).reduce(dedupeShelfReduce, []).filter(item => item)
         .filter(item => typeof item === 'string' && item.trim() !== '')
         .sort((a, b) => a.toLowerCase() > b.toLowerCase() ? 1 : -1).map(item => category.options.find(opt => opt.value === item))
+        .filter(item => item)
     });
   }
 
diff --git a/src/app/resources/search-resources/resources-search.component.ts b/src/app/resources/search-resources/resources-search.component.ts
index 81faad4cb0..560dac1e3d 100644
--- a/src/app/resources/search-resources/resources-search.component.ts
+++ b/src/app/resources/search-resources/resources-search.component.ts
@@ -26,7 +26,7 @@ import { MatSelectionList } from '@angular/material/list';
     </span>
     <mat-selection-list (selectionChange)="selectionChange($event)">
       <mat-list-option *ngFor="let item of items" [value]="item.value" [selected]="isSelected(item)" checkboxPosition="before">
-        {{item.label}}
+        {{item?.label || 'N/A'}}
       </mat-list-option>
     </mat-selection-list>
   `,
@@ -117,6 +117,7 @@ export class ResourcesSearchComponent implements OnInit, OnChanges {
       category: category.label,
       items: data.reduce((list, { doc }) => list.concat(doc[category.label]), []).reduce(dedupeShelfReduce, []).filter(item => item)
         .sort((a, b) => a.toLowerCase() > b.toLowerCase() ? 1 : -1).map(item => category.options.find(opt => opt.value === item))
+        .filter(item => item)
     });
   }
 

From 7c83d31fba218c0c1358b6905342f216715f0911 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 6 Dec 2024 16:10:43 -0500
Subject: [PATCH 038/113] resources: smoother buttons (fixes #7889) (#7897)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                               | 2 +-
 src/app/resources/resources.component.html | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index f41223f140..4c6a833d45 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.87",
+  "version": "0.15.88",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/resources/resources.component.html b/src/app/resources/resources.component.html
index 7d8ad39798..61657b0ac4 100644
--- a/src/app/resources/resources.component.html
+++ b/src/app/resources/resources.component.html
@@ -174,8 +174,8 @@ <h3 class="header">
             </ng-container>
             <ng-container *ngIf="element.canManage && myView !== 'myPersonals'">
               <a mat-menu-item (click)="updateResource(element)">
-                <mat-icon>folder</mat-icon>
-                <span i18n>Manage</span>
+                <mat-icon>edit</mat-icon>
+                <span i18n>Edit Resource</span>
               </a>
               <button mat-menu-item (click)="deleteClick(element)">
                 <mat-icon>delete_forever</mat-icon>

From b1459c1549185c0b6db388122e348b1020cd608a Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 9 Dec 2024 15:19:21 -0500
Subject: [PATCH 039/113] enterprises: smoother csv exports (fixes #7887)(fixes
 #7888) (#7898)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                   |  2 +-
 src/app/teams/teams-reports.component.ts       | 14 ++++++++++++--
 src/app/teams/teams-view-finances.component.ts |  9 ++++++---
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index 4c6a833d45..a3ca0208ae 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.88",
+  "version": "0.15.89",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/teams/teams-reports.component.ts b/src/app/teams/teams-reports.component.ts
index a9a658cb85..f7cccabeba 100644
--- a/src/app/teams/teams-reports.component.ts
+++ b/src/app/teams/teams-reports.component.ts
@@ -11,6 +11,7 @@ import { DialogsPromptComponent } from '../shared/dialogs/dialogs-prompt.compone
 import { tap } from 'rxjs/operators';
 import { convertUtcDate } from './teams.utils';
 import { CsvService } from '../shared/csv.service';
+import { StateService } from '../shared/state.service';
 
 @Component({
   selector: 'planet-teams-reports',
@@ -25,6 +26,8 @@ export class TeamsReportsComponent implements DoCheck {
   @Output() reportsChanged = new EventEmitter<void>();
   columns = 4;
   minColumnWidth = 300;
+  configuration: any = {};
+  planetName: any;
 
   constructor(
     private couchService: CouchService,
@@ -33,7 +36,8 @@ export class TeamsReportsComponent implements DoCheck {
     private dialogsLoadingService: DialogsLoadingService,
     private teamsService: TeamsService,
     private csvService: CsvService,
-    private elementRef: ElementRef
+    private elementRef: ElementRef,
+    private stateService: StateService,
   ) {}
 
   ngDoCheck() {
@@ -161,7 +165,13 @@ export class TeamsReportsComponent implements DoCheck {
       'Profit/Loss': report.sales + report.otherIncome - report.wages - report.otherExpenses,
       'Ending Balance': report.beginningBalance + report.sales + report.otherIncome - report.wages - report.otherExpenses
     }));
-    this.csvService.exportCSV({ data: exportData, title: $localize`${this.team.name} Financial Report Summary` });
+    const planetName = this.stateService.configuration.name || 'Unnamed';
+    const entityLabel = this.configuration.planetType === 'nation' ? 'Nation' : 'Community';
+    const titleName = this.team.name || `${entityLabel} ${planetName}`;
+    this.csvService.exportCSV({
+      data: exportData,
+      title: $localize`Financial Summary for ${titleName}`
+    });
   }
 
 }
diff --git a/src/app/teams/teams-view-finances.component.ts b/src/app/teams/teams-view-finances.component.ts
index dcd9d68500..797173a57f 100644
--- a/src/app/teams/teams-view-finances.component.ts
+++ b/src/app/teams/teams-view-finances.component.ts
@@ -34,7 +34,8 @@ export class TeamsViewFinancesComponent implements OnInit, OnChanges {
   emptyTable = true;
   showBalanceWarning = false;
   curCode = this.stateService.configuration.currency || {};
-
+  configuration: any = {};
+  planetName: any;
   constructor(
     private csvService: CsvService,
     private couchService: CouchService,
@@ -198,10 +199,12 @@ export class TeamsViewFinancesComponent implements OnInit, OnChanges {
       debit: row.debit,
       balance: row.balance
     }));
-
+    const planetName = this.stateService.configuration.name || 'Unnamed';
+    const entityLabel = this.configuration.planetType === 'nation' ? 'Nation' : 'Community';
+    const titleName = this.team.name || `${entityLabel} ${planetName}`;
     this.csvService.exportCSV({
       data: updatedData,
-      title: $localize`Financial Transactions for ${this.team.name} Enterprise`
+      title: $localize`Financial Transactions for ${titleName}`
     });
   }
 

From b5502335e4bbfd0a5a8e898cf7d625ee63a8f964 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Mon, 9 Dec 2024 15:24:53 -0500
Subject: [PATCH 040/113] dashboard: smoother drag and drop (fixes #7886)
 (#7902)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                    | 2 +-
 src/app/dashboard/dashboard-tile.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index a3ca0208ae..26544e38e9 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.89",
+  "version": "0.15.90",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/dashboard/dashboard-tile.component.html b/src/app/dashboard/dashboard-tile.component.html
index a66844b4f9..6cda7acb0e 100644
--- a/src/app/dashboard/dashboard-tile.component.html
+++ b/src/app/dashboard/dashboard-tile.component.html
@@ -25,7 +25,7 @@
             #dashboardTile
           >
             <p [matBadge]="item.badge" [matBadgeHidden]="item.badge===0" matBadgeOverlap="false">{{item.firstLine}}</p>
-            <p class="dashboard-text" [ngStyle]="{ '-webkit-line-clamp': tileLines }">{{item.title}}</p>
+            <p class="dashboard-text" [ngStyle]="{ '-webkit-line-clamp': tileLines }">{{item.title | slice:0:80}}</p>
             <button mat-icon-button class="delete-item" (click)="removeFromShelf($event, item)" *ngIf="cardType!=='myLife' && !item?.canRemove">
               <mat-icon i18n-matTooltip [matTooltip]="'Remove from ' + cardTitle" [inline]="true">clear</mat-icon>
             </button>

From 54c9b79fcd16860747d869337ff6d668d985b6c9 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Mon, 9 Dec 2024 15:29:36 -0500
Subject: [PATCH 041/113] courses: smoother toolbar (fixes #7878) (#7904)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                             | 2 +-
 src/app/courses/view-courses/courses-view.component.html | 2 +-
 src/app/courses/view-courses/courses-view.scss           | 4 ++++
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 26544e38e9..8e475f7603 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.90",
+  "version": "0.15.91",
   "myplanet": {
     "latest": "v0.21.29",
     "min": "v0.20.29"
diff --git a/src/app/courses/view-courses/courses-view.component.html b/src/app/courses/view-courses/courses-view.component.html
index 3e33f0bd70..208a55281d 100644
--- a/src/app/courses/view-courses/courses-view.component.html
+++ b/src/app/courses/view-courses/courses-view.component.html
@@ -49,7 +49,7 @@ <h3 class="margin-lr-3 ellipsis-title">{{courseDetail.courseTitle}}</h3>
           Leave
         </button>
       </ng-container>
-      <button mat-raised-button color="accent" (click)="viewStep()" i18n [disabled]="!courseDetail?.steps?.length">View Step</button>
+      <button class="view-step-button" mat-raised-button color="accent" (click)="viewStep()" i18n [disabled]="!courseDetail?.steps?.length">View Step</button>
    </ng-template>
 
   <div class="view-container view-full-height">
diff --git a/src/app/courses/view-courses/courses-view.scss b/src/app/courses/view-courses/courses-view.scss
index 5db279dfb1..810af1acae 100644
--- a/src/app/courses/view-courses/courses-view.scss
+++ b/src/app/courses/view-courses/courses-view.scss
@@ -34,6 +34,10 @@
     margin-left: 8px;
   }
 
+  .view-step-button{
+    flex-shrink: 0;
+  }
+
   @media (max-width: $screen-sm) {
     .course-container {
       grid-template-columns: 1fr;

From e078d848d40aa9392864c4b52c0dbf4ea4562b7c Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 10 Dec 2024 14:47:37 -0500
Subject: [PATCH 042/113] teams: smoother list (fixes #6546) (#7864)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json             |  6 +++---
 src/app/teams/teams.scss | 11 +++++------
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index 8e475f7603..c0f250749e 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.91",
+  "version": "0.15.92",
   "myplanet": {
-    "latest": "v0.21.29",
-    "min": "v0.20.29"
+    "latest": "v0.21.32",
+    "min": "v0.20.32"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/teams/teams.scss b/src/app/teams/teams.scss
index 50f96491f6..0e6a2cfae0 100644
--- a/src/app/teams/teams.scss
+++ b/src/app/teams/teams.scss
@@ -1,23 +1,22 @@
 @import "../variables.scss";
 
 :host {
-  /* Column Widths */
   .mat-column-doc-teamType {
     max-width: 150px;
     padding-right: 0.5rem;
   }
 
   .mat-column-visitLog-visitCount {
+    justify-content: center;
     max-width: 80px;
-    padding-right: 0.5rem;
-  }
-  .mat-column-visitLog-lastVisit {
-    max-width: 180px;
-    padding-right: 0.5rem;
+    padding-right: 1rem;
+    margin-right: 1rem
   }
+
   mat-row {
     cursor: pointer;
   }
+
   .button-container {
     display: flex;
     flex-direction: row;

From e5aae0c5a4d81ceb0cb103010e33ad689e71cdb7 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 10 Dec 2024 14:54:06 -0500
Subject: [PATCH 043/113] enterprises: smoother report dialog (fixes #6946)
 (#7908)

Co-authored-by: Sahil <sahilvunnam423@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                      | 2 +-
 src/app/teams/teams-reports-dialog.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index c0f250749e..b0d8bcb3fe 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.92",
+  "version": "0.15.93",
   "myplanet": {
     "latest": "v0.21.32",
     "min": "v0.20.32"
diff --git a/src/app/teams/teams-reports-dialog.component.html b/src/app/teams/teams-reports-dialog.component.html
index 408eb3fd1a..e2d00fd271 100644
--- a/src/app/teams/teams-reports-dialog.component.html
+++ b/src/app/teams/teams-reports-dialog.component.html
@@ -6,5 +6,5 @@ <h3>{{teamName}} <ng-container i18n>Financial Report</ng-container></h3>
   <planet-teams-reports-detail [report]="report" [showSummary]="true"></planet-teams-reports-detail>
 </mat-dialog-content>
 <mat-dialog-actions>
-  <button mat-raised-button color="primary" mat-dialog-close i18n>Close</button>
+  <button mat-raised-button mat-dialog-close i18n>Close</button>
 </mat-dialog-actions>

From ec6de361b960e5ab15fffab7dd15b2a3828475e1 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 10 Dec 2024 14:59:13 -0500
Subject: [PATCH 044/113] courses: smoother progress title (fixes #7906)
 (#7909)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                  | 2 +-
 .../progress-courses/courses-progress-leader.component.html   | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index b0d8bcb3fe..45ca1ecc2f 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.93",
+  "version": "0.15.94",
   "myplanet": {
     "latest": "v0.21.32",
     "min": "v0.20.32"
diff --git a/src/app/courses/progress-courses/courses-progress-leader.component.html b/src/app/courses/progress-courses/courses-progress-leader.component.html
index 0cff81fd1f..6a189f4016 100644
--- a/src/app/courses/progress-courses/courses-progress-leader.component.html
+++ b/src/app/courses/progress-courses/courses-progress-leader.component.html
@@ -7,7 +7,9 @@
 </mat-toolbar>
 
 <mat-toolbar class="primary-color font-size-1">
-  <span><h3 class="margin-lr-3 ellipsis-title">{{ headingStart }}</h3></span>
+  <h3 class="ellipsis-title margin-lr-3">
+    {{ headingStart | slice:0:140 }}
+  </h3>
   <ng-container *ngIf="deviceType === deviceTypes.DESKTOP">
     <span class="toolbar-fill"></span>
     <ng-container *ngTemplateOutlet="filterSelectors"></ng-container>

From 4e4763a393edcf86d617c6460d2ac334665e272a Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 11 Dec 2024 13:02:07 -0800
Subject: [PATCH 045/113] courses: smoother ratings (fixes #7726) (#7737)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                   |  6 +++---
 .../courses-view-detail.component.ts           |  2 --
 .../forms/planet-rating-stars.component.ts     | 11 ++++++++++-
 .../shared/forms/planet-rating.component.html  |  3 ++-
 .../shared/forms/planet-rating.component.ts    | 18 ++++++++++++++++++
 5 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index 45ca1ecc2f..38dc830819 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.94",
+  "version": "0.15.95",
   "myplanet": {
-    "latest": "v0.21.32",
-    "min": "v0.20.32"
+    "latest": "v0.21.34",
+    "min": "v0.20.34"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/view-courses/courses-view-detail.component.ts b/src/app/courses/view-courses/courses-view-detail.component.ts
index cc3be81e73..f601c8857b 100644
--- a/src/app/courses/view-courses/courses-view-detail.component.ts
+++ b/src/app/courses/view-courses/courses-view-detail.component.ts
@@ -29,7 +29,6 @@ export class CoursesViewDetailComponent implements OnChanges {
   ngOnChanges() {
     this.imageSource = this.parent === true ? 'parent' : 'local';
   }
-
 }
 
 @Component({
@@ -68,5 +67,4 @@ export class CoursesViewDetailDialogComponent implements OnInit {
   routeToCourses(courseId) {
     this.router.navigate([ '../../courses/view/', courseId ], { relativeTo: this.route });
   }
-
 }
diff --git a/src/app/shared/forms/planet-rating-stars.component.ts b/src/app/shared/forms/planet-rating-stars.component.ts
index 7d8a3346eb..9dfdb78834 100644
--- a/src/app/shared/forms/planet-rating-stars.component.ts
+++ b/src/app/shared/forms/planet-rating-stars.component.ts
@@ -3,6 +3,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
 import { MatFormFieldControl } from '@angular/material/form-field';
 import { Subject } from 'rxjs';
 import { ControlValueAccessor, NgControl } from '@angular/forms';
+import { UserService } from '../user.service';
 
 @Component({
   selector: 'planet-rating-stars',
@@ -51,11 +52,14 @@ export class PlanetRatingStarsComponent implements MatFormFieldControl<number>,
     this.onChange(rating);
     this.stateChanges.next();
   }
+  @Input() isEnrolled: (id: any, type: any) => boolean;
+  @Input() itemId: (id: any) => void;
+  @Input() type: string;
   private _value = 0;
 
   onChange(_: any) {}
 
-  constructor(@Optional() @Self() public ngControl: NgControl) {
+  constructor(@Optional() @Self() public ngControl: NgControl, private userService: UserService) {
     if (this.ngControl) {
       this.ngControl.valueAccessor = this;
     }
@@ -101,6 +105,11 @@ export class PlanetRatingStarsComponent implements MatFormFieldControl<number>,
   }
 
   onStarClick(rating: number): void {
+    if (this.isEnrolled) {
+      if (!this.isEnrolled(this.itemId, this.type)) {
+        return;
+      }
+    }
     this.writeValue(rating);
   }
 
diff --git a/src/app/shared/forms/planet-rating.component.html b/src/app/shared/forms/planet-rating.component.html
index 4bd0e0133e..06f04a5efb 100644
--- a/src/app/shared/forms/planet-rating.component.html
+++ b/src/app/shared/forms/planet-rating.component.html
@@ -14,7 +14,8 @@
 
   <div class="your-rating" *ngIf="!parent">
     <form [formGroup]="rateForm" novalidate>
-      <planet-rating-stars (click)="onStarClick()" formControlName="rate" [disabled]="disabled"></planet-rating-stars>
+      <planet-rating-stars (click)="onStarClick()" formControlName="rate" [disabled]="disabled" [isEnrolled]="isEnrolled" [itemId]="item._id" [type]="ratingType">
+      </planet-rating-stars>
     </form>
   </div>
 
diff --git a/src/app/shared/forms/planet-rating.component.ts b/src/app/shared/forms/planet-rating.component.ts
index eaaa7b2109..9e2a9e15c0 100644
--- a/src/app/shared/forms/planet-rating.component.ts
+++ b/src/app/shared/forms/planet-rating.component.ts
@@ -45,6 +45,7 @@ export class PlanetRatingComponent implements OnChanges {
   popupForm: FormGroup;
   isPopupOpen = false;
   stackedBarData = [];
+  enrolled = true;
   get rateFormField() {
     return { rate: this.rating.userRating.rate || 0 };
   }
@@ -83,7 +84,24 @@ export class PlanetRatingComponent implements OnChanges {
     this.popupForm.setValue(Object.assign({}, this.rateFormField, this.commentField));
   }
 
+  isEnrolled(id: any, type: any): boolean {
+    const idType = type === 'course' ? 'courseIds' : 'resourceIds';
+    const { inShelf } = this.userService.countInShelf([ id ], idType);
+    return inShelf;
+  }
+
   onStarClick(form = this.rateForm) {
+    if (!this.isEnrolled(this.item._id, this.ratingType)) {
+      if (this.ratingType === 'course') {
+        this.planetMessage.showMessage($localize`Please join the ${this.ratingType} before rating!`);
+      } else {
+        this.planetMessage.showMessage($localize`Please add the ${this.ratingType} to your library before rating!`);
+      }
+      this.enrolled = false;
+      return;
+    }
+
+    this.enrolled = true;
     if (this.disabled || form.controls.rate.value === 0) {
       return;
     }

From b71b1ff2fc620be7c65a17f45003d833577e2d1d Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 11 Dec 2024 13:11:25 -0800
Subject: [PATCH 046/113] manager: smoother reports subheading (fixes #4418)
 (#7914)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../reports/reports-detail.component.html     | 34 +++++++++----------
 .../reports/reports-detail.scss               |  4 +++
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/package.json b/package.json
index 38dc830819..0e5ba002f4 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.95",
+  "version": "0.15.96",
   "myplanet": {
     "latest": "v0.21.34",
     "min": "v0.20.34"
diff --git a/src/app/manager-dashboard/reports/reports-detail.component.html b/src/app/manager-dashboard/reports/reports-detail.component.html
index 97026c3c21..2d65d55362 100644
--- a/src/app/manager-dashboard/reports/reports-detail.component.html
+++ b/src/app/manager-dashboard/reports/reports-detail.component.html
@@ -77,7 +77,7 @@
           <div>
             <h1 class="mat-title" i18n>Members</h1>
             <mat-grid-list cols="2" rowHeight="2rem">
-              <mat-grid-tile class="label" i18n>Total Members</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Total Members</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalUsers}}</mat-grid-tile>
               <mat-grid-tile class="label">
                 <mat-icon>subdirectory_arrow_right</mat-icon>
@@ -94,10 +94,10 @@ <h1 class="mat-title" i18n>Members</h1>
                 <span i18n>Did not specify</span>
               </mat-grid-tile>
               <mat-grid-tile>{{reports?.usersByGender?.didNotSpecify || 0}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Total Visits</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Total Visits</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalMemberVisits}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Members by Visits</mat-grid-tile>
-              <mat-grid-tile i18n>Total Visits by Member</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Members by Visits</mat-grid-tile>
+              <mat-grid-tile i18n class="subheading">Total Visits by Member</mat-grid-tile>
               <ng-container *ngIf="!reports?.visits || reports?.visits.length === 0">
                 <mat-grid-tile colspan="2" i18n>There are no visits</mat-grid-tile>
               </ng-container>
@@ -113,12 +113,12 @@ <h1 class="mat-title" i18n>Members</h1>
           <div>
             <h1 class="mat-title" i18n>Resources</h1>
             <mat-grid-list cols="2" rowHeight="2rem">
-              <mat-grid-tile class="label" i18n>Total Resources</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Total Resources</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalResources}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Total Views</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Total Views</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalResourceViews}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Most Visited</mat-grid-tile>
-              <mat-grid-tile i18n>Total Visits by Resource</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Most Visited</mat-grid-tile>
+              <mat-grid-tile class="subheading" i18n>Total Visits by Resource</mat-grid-tile>
               <ng-container *ngIf="!reports?.resources || reports?.resources.length === 0">
                 <mat-grid-tile colspan="2" i18n>No resources have been visited</mat-grid-tile>
               </ng-container>
@@ -129,8 +129,8 @@ <h1 class="mat-title" i18n>Resources</h1>
                 </mat-grid-tile>
                 <mat-grid-tile>{{resource.count}}</mat-grid-tile>
               </ng-container>
-              <mat-grid-tile class="label" i18n>Highest Rated</mat-grid-tile>
-              <mat-grid-tile i18n>Average Rating</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Highest Rated</mat-grid-tile>
+              <mat-grid-tile class="subheading" i18n>Average Rating</mat-grid-tile>
               <ng-container *ngIf="!reports?.resourceRatings || reports?.resourceRatings.length === 0">
                 <mat-grid-tile colspan="2" i18n>There are no resource ratings</mat-grid-tile>
               </ng-container>
@@ -146,14 +146,14 @@ <h1 class="mat-title" i18n>Resources</h1>
           <div>
             <h1 class="mat-title" i18n>Courses</h1>
             <mat-grid-list cols="2" rowHeight="2rem">
-              <mat-grid-tile class="label" i18n>Total Courses</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Total Courses</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalCourses}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Total Views</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Total Views</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalCourseViews}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Steps Completed</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Steps Completed</mat-grid-tile>
               <mat-grid-tile>{{reports?.totalStepCompleted}}</mat-grid-tile>
-              <mat-grid-tile class="label" i18n>Most Visited</mat-grid-tile>
-              <mat-grid-tile i18n>Total Visits by Course</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Most Visited</mat-grid-tile>
+              <mat-grid-tile class="subheading" i18n>Total Visits by Course</mat-grid-tile>
               <ng-container *ngIf="!reports?.courses || reports?.courses.length === 0">
                 <mat-grid-tile colspan="2" i18n>No courses have been visited</mat-grid-tile>
               </ng-container>
@@ -164,8 +164,8 @@ <h1 class="mat-title" i18n>Courses</h1>
                 </mat-grid-tile>
                 <mat-grid-tile>{{course.count}}</mat-grid-tile>
               </ng-container>
-              <mat-grid-tile class="label" i18n>Highest Rated</mat-grid-tile>
-              <mat-grid-tile i18n>Average Rating</mat-grid-tile>
+              <mat-grid-tile class="subheading label" i18n>Highest Rated</mat-grid-tile>
+              <mat-grid-tile class="subheading" i18n>Average Rating</mat-grid-tile>
               <ng-container *ngIf="!reports?.courseRatings || reports?.courseRatings.length === 0">
                 <mat-grid-tile colspan="2" i18n>There are no course ratings</mat-grid-tile>
               </ng-container>
diff --git a/src/app/manager-dashboard/reports/reports-detail.scss b/src/app/manager-dashboard/reports/reports-detail.scss
index 1ed5d76211..9931af899f 100644
--- a/src/app/manager-dashboard/reports/reports-detail.scss
+++ b/src/app/manager-dashboard/reports/reports-detail.scss
@@ -11,6 +11,10 @@ mat-toolbar mat-form-field {
   line-height: 3.7em
 }
 
+.subheading {
+  font-weight: bold;
+}
+
 .manager-reports-detail {
   mat-grid-tile.label figure {
     justify-content: start;

From 297cd4d655083df969c6a4c1b29ade5fb8d04e2c Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 11 Dec 2024 13:18:21 -0800
Subject: [PATCH 047/113] manager: initial chat reports (fixes #7896) (#7916)

Co-authored-by: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                      |  2 +-
 .../reports/reports-detail.component.html         |  1 +
 .../reports/reports-detail.component.ts           | 15 +++++++++++++++
 .../manager-dashboard/reports/reports.service.ts  | 13 +++++++++++++
 .../manager-dashboard/reports/reports.utils.ts    |  3 ++-
 5 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 0e5ba002f4..e480c6539f 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.96",
+  "version": "0.15.97",
   "myplanet": {
     "latest": "v0.21.34",
     "min": "v0.20.34"
diff --git a/src/app/manager-dashboard/reports/reports-detail.component.html b/src/app/manager-dashboard/reports/reports-detail.component.html
index 2d65d55362..fcf29da727 100644
--- a/src/app/manager-dashboard/reports/reports-detail.component.html
+++ b/src/app/manager-dashboard/reports/reports-detail.component.html
@@ -73,6 +73,7 @@
         <canvas id="resourceViewChart"></canvas>
         <canvas id="courseViewChart"></canvas>
         <canvas id="stepCompletedChart"></canvas>
+        <canvas id="chatUsageChart"></canvas>
         <div class="reports-table-container">
           <div>
             <h1 class="mat-title" i18n>Members</h1>
diff --git a/src/app/manager-dashboard/reports/reports-detail.component.ts b/src/app/manager-dashboard/reports/reports-detail.component.ts
index 8f60740a01..87375f3d14 100644
--- a/src/app/manager-dashboard/reports/reports-detail.component.ts
+++ b/src/app/manager-dashboard/reports/reports-detail.component.ts
@@ -51,6 +51,7 @@ export class ReportsDetailComponent implements OnInit, OnDestroy {
     completions: new ReportsDetailData('time'),
     steps: new ReportsDetailData('time')
   };
+  chatActivities = new ReportsDetailData('createdDate');
   today: Date;
   minDate: Date;
   ratings = { total: new ReportsDetailData('time'), resources: [], courses: [] };
@@ -121,6 +122,7 @@ export class ReportsDetailComponent implements OnInit, OnDestroy {
       this.getDocVisits('courseActivities');
       this.getPlanetCounts(local);
       this.getTeams();
+      this.getChatUsage();
       this.dialogsLoadingService.stop();
     });
   }
@@ -165,6 +167,8 @@ export class ReportsDetailComponent implements OnInit, OnDestroy {
         )
       )
     ));
+    this.chatActivities.filter(this.filter);
+    this.setChatUsage();
   }
 
   getLoginActivities() {
@@ -278,6 +282,17 @@ export class ReportsDetailComponent implements OnInit, OnDestroy {
     });
   }
 
+  getChatUsage() {
+    this.activityService.getChatHistory().subscribe((data) => {
+      this.chatActivities.data = data;
+    });
+  }
+
+  setChatUsage() {
+    const { byMonth } = this.activityService.groupChatUsage(this.chatActivities.filteredData);
+    this.setChart({ ...this.setGenderDatasets(byMonth), chartName: 'chatUsageChart' });
+  }
+
   getTeamMembers(team: any) {
     if (team === 'All') {
       return of([]);
diff --git a/src/app/manager-dashboard/reports/reports.service.ts b/src/app/manager-dashboard/reports/reports.service.ts
index 6d0b54e61d..21241d2947 100644
--- a/src/app/manager-dashboard/reports/reports.service.ts
+++ b/src/app/manager-dashboard/reports/reports.service.ts
@@ -262,6 +262,19 @@ export class ReportsService {
     }));
   }
 
+  getChatHistory() {
+    return this.couchService.get('chat_history/_all_docs', { params: { include_docs: 'true' } })
+    .pipe(
+      map((data: any) => data.rows.map((row: any) => row.doc))
+    );
+  }
+
+  groupChatUsage(chats: any) {
+    return ({
+      byMonth: this.groupByMonth(this.appendGender(chats), 'createdDate', '_id')
+    });
+  }
+
   groupStepCompletion(steps: any[]) {
     return ({
       byMonth: this.groupByMonth(this.appendGender(steps), 'time', 'userId')
diff --git a/src/app/manager-dashboard/reports/reports.utils.ts b/src/app/manager-dashboard/reports/reports.utils.ts
index b2c743330f..464b09aa85 100644
--- a/src/app/manager-dashboard/reports/reports.utils.ts
+++ b/src/app/manager-dashboard/reports/reports.utils.ts
@@ -83,7 +83,8 @@ export const titleOfChartName = (chartName: string) => {
     courseViewChart: $localize`Course Views by Month`,
     visitChart: $localize`Total Member Visits by Month`,
     uniqueVisitChart: $localize`Unique Member Visits by Month`,
-    stepCompletedChart: $localize`Steps Completed by Month`
+    stepCompletedChart: $localize`Steps Completed by Month`,
+    chatUsageChart: $localize`Chats Created by Month`
   };
   return chartNames[chartName];
 };

From ea374622b250cc56880a84240647de94205d2ccb Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 12 Dec 2024 18:42:54 -0500
Subject: [PATCH 048/113] courses: smoother titles (fixes #7664) (#7922)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                           | 6 +++---
 src/app/courses/courses.component.html | 5 +++--
 src/app/courses/courses.scss           | 4 ++++
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index e480c6539f..c57a6351fd 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.97",
+  "version": "0.15.98",
   "myplanet": {
-    "latest": "v0.21.34",
-    "min": "v0.20.34"
+    "latest": "v0.21.35",
+    "min": "v0.20.35"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/courses.component.html b/src/app/courses/courses.component.html
index 554f750401..586eb3df19 100644
--- a/src/app/courses/courses.component.html
+++ b/src/app/courses/courses.component.html
@@ -131,8 +131,9 @@ <h3 class="header">
             </ng-container>
             <ng-container *ngTemplateOutlet="headerText"></ng-container>
             <ng-template #headerText>
-              <a *ngIf="!isDialog && !isForm; else newTabLink" [routerLink]="['view', element._id]">{{ element.doc.courseTitle.length > 180 ? element.doc.courseTitle.slice(0, 180) + '...' : element.doc.courseTitle }}</a>
-              <ng-template #newTabLink><a class="cursor-pointer" (click)="openCourseViewDialog(element._id)">{{ element.doc.courseTitle.length > 180 ? element.doc.courseTitle.slice(0, 180) + '...' : element.doc.courseTitle }}</a></ng-template>
+              <a *ngIf="!isDialog && !isForm; else newTabLink" [routerLink]="['view', element._id]" class="break-word">{{ element.doc.courseTitle.length > 180 ? element.doc.courseTitle.slice(0, 180) + '...' : element.doc.courseTitle }}</a>
+            <ng-template #newTabLink><a class="cursor-pointer break-word" (click)="openCourseViewDialog(element._id)">{{ element.doc.courseTitle.length > 180 ? element.doc.courseTitle.slice(0, 180) + '...' : element.doc.courseTitle }}</a>
+            </ng-template>
               <span *ngIf="!parent && !isDialog" [ngClass]="{ 'cursor-pointer': !isForm }">
                 <mat-icon class="margin-lr-3" i18n-matTooltip matTooltip="In myCourses" [inline]="true" *ngIf="element.admission" (click)="courseToggle(element._id, 'resign')">bookmark</mat-icon>
                 <mat-icon class="margin-lr-3" i18n-matTooltip matTooltip="Not in myCourses" [inline]="true" *ngIf="!element.admission && element.doc.steps.length" (click)="courseToggle(element._id, 'admission')">bookmark_border</mat-icon>
diff --git a/src/app/courses/courses.scss b/src/app/courses/courses.scss
index 6ec414dfe1..efe18f5943 100644
--- a/src/app/courses/courses.scss
+++ b/src/app/courses/courses.scss
@@ -55,6 +55,10 @@ $label-height: 1rem;
   height: $toolbar-height;
 }
 
+.break-word {
+  word-break: break-word;
+}
+
 @media(max-width: $screen-md) {
   .mat-column-info {
     max-width: 120px;

From 0f4a9ca715aab737fd8703cdde7184fdf54861bc Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 12 Dec 2024 18:45:52 -0500
Subject: [PATCH 049/113] dashboard: smoother tiles (fixes #7924) (#7926)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                    | 2 +-
 src/app/dashboard/dashboard-tile.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index c57a6351fd..dfdb51b2c3 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.98",
+  "version": "0.15.99",
   "myplanet": {
     "latest": "v0.21.35",
     "min": "v0.20.35"
diff --git a/src/app/dashboard/dashboard-tile.component.html b/src/app/dashboard/dashboard-tile.component.html
index 6cda7acb0e..9941b3c936 100644
--- a/src/app/dashboard/dashboard-tile.component.html
+++ b/src/app/dashboard/dashboard-tile.component.html
@@ -25,7 +25,7 @@
             #dashboardTile
           >
             <p [matBadge]="item.badge" [matBadgeHidden]="item.badge===0" matBadgeOverlap="false">{{item.firstLine}}</p>
-            <p class="dashboard-text" [ngStyle]="{ '-webkit-line-clamp': tileLines }">{{item.title | slice:0:80}}</p>
+            <p class="dashboard-text" [ngStyle]="{ '-webkit-line-clamp': tileLines,'word-wrap': 'break-word' }">{{item.title | slice:0:80}}</p>
             <button mat-icon-button class="delete-item" (click)="removeFromShelf($event, item)" *ngIf="cardType!=='myLife' && !item?.canRemove">
               <mat-icon i18n-matTooltip [matTooltip]="'Remove from ' + cardTitle" [inline]="true">clear</mat-icon>
             </button>

From 6e18f46b98e81df8d85c847b6d5f870746531abd Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Fri, 13 Dec 2024 23:55:37 +0300
Subject: [PATCH 050/113] manager: smoother myplanet logs (fixes #7634)(fixes
 #7816) (#7913)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  6 +--
 src/app/home/home-router.module.ts            |  2 -
 src/app/home/home.module.ts                   |  2 +-
 .../manager-dashboard-router.module.ts        |  2 +
 .../manager-dashboard.component.html          |  1 +
 .../reports}/logs-myplanet.component.html     |  9 +++-
 .../reports}/logs-myplanet.component.ts       | 47 ++++++++++++++---
 .../reports/reports-myplanet.component.html   |  6 +++
 .../reports/reports-myplanet.component.ts     | 52 ++++++++++++++++++-
 9 files changed, 112 insertions(+), 15 deletions(-)
 rename src/app/{logs-myplanet => manager-dashboard/reports}/logs-myplanet.component.html (76%)
 rename src/app/{logs-myplanet => manager-dashboard/reports}/logs-myplanet.component.ts (58%)

diff --git a/package.json b/package.json
index dfdb51b2c3..2d26be0a9e 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.15.99",
+  "version": "0.16.0",
   "myplanet": {
-    "latest": "v0.21.35",
-    "min": "v0.20.35"
+    "latest": "v0.21.40",
+    "min": "v0.20.40"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/home/home-router.module.ts b/src/app/home/home-router.module.ts
index 7a4e71a88f..8eda6e64d8 100644
--- a/src/app/home/home-router.module.ts
+++ b/src/app/home/home-router.module.ts
@@ -6,7 +6,6 @@ import { NotificationsComponent } from '../notifications/notifications.component
 import { UpgradeComponent } from '../upgrade/upgrade.component';
 import { UsersAchievementsComponent } from '../users/users-achievements/users-achievements.component';
 import { UsersAchievementsUpdateComponent } from '../users/users-achievements/users-achievements-update.component';
-import { LogsMyPlanetComponent } from '../logs-myplanet/logs-myplanet.component';
 import { TeamsViewComponent } from '../teams/teams-view.component';
 import { HealthListComponent } from '../health/health-list.component';
 import { CommunityComponent } from '../community/community.component';
@@ -35,7 +34,6 @@ const routes: Routes = [
       { path: 'upgrade/myplanet', component: UpgradeComponent, data: { myPlanet: true } },
       { path: 'teams', loadChildren: () => import('../teams/teams.module').then(m => m.TeamsModule) },
       { path: 'enterprises', loadChildren: () => import('../teams/teams.module').then(m => m.TeamsModule), data: { mode: 'enterprise' } },
-      { path: 'logs/myplanet', component: LogsMyPlanetComponent },
       { path: 'health', component: HealthListComponent },
       { path: 'health/profile/:id', loadChildren: () => import('../health/health.module').then(m => m.HealthModule) },
       { path: 'nation', component: TeamsViewComponent, data: { mode: 'services' } },
diff --git a/src/app/home/home.module.ts b/src/app/home/home.module.ts
index cc9c52acae..8ee5378d75 100644
--- a/src/app/home/home.module.ts
+++ b/src/app/home/home.module.ts
@@ -17,7 +17,7 @@ import { UpgradeComponent } from '../upgrade/upgrade.component';
 import { SharedComponentsModule } from '../shared/shared-components.module';
 import { UsersAchievementsModule } from '../users/users-achievements/users-achievements.module';
 import { NewsModule } from '../news/news.module';
-import { LogsMyPlanetComponent } from '../logs-myplanet/logs-myplanet.component';
+import { LogsMyPlanetComponent } from '../manager-dashboard/reports/logs-myplanet.component';
 import { TeamsModule } from '../teams/teams.module';
 import { CommunityComponent } from '../community/community.component';
 import { PlanetCalendarModule } from '../shared/calendar.module';
diff --git a/src/app/manager-dashboard/manager-dashboard-router.module.ts b/src/app/manager-dashboard/manager-dashboard-router.module.ts
index 9249544115..c5b7fd16e4 100644
--- a/src/app/manager-dashboard/manager-dashboard-router.module.ts
+++ b/src/app/manager-dashboard/manager-dashboard-router.module.ts
@@ -10,6 +10,7 @@ import { ReportsDetailComponent } from './reports/reports-detail.component';
 import { ReportsPendingComponent } from './reports/reports-pending.component';
 import { ReportsMyPlanetComponent } from './reports/reports-myplanet.component';
 import { RequestsComponent } from './requests/requests.component';
+import { LogsMyPlanetComponent } from './reports/logs-myplanet.component';
 
 const routes: Routes = [
   { path: '', component: ManagerDashboardComponent },
@@ -27,6 +28,7 @@ const routes: Routes = [
   { path: 'reports/detail', component: ReportsDetailComponent },
   { path: 'reports/pending', component: ReportsPendingComponent },
   { path: 'reports/myplanet', component: ReportsMyPlanetComponent },
+  { path: 'logs/myplanet', component: LogsMyPlanetComponent },
   { path: 'requests', component: RequestsComponent }
 ];
 
diff --git a/src/app/manager-dashboard/manager-dashboard.component.html b/src/app/manager-dashboard/manager-dashboard.component.html
index c31840c7e0..85d2f7bb5b 100644
--- a/src/app/manager-dashboard/manager-dashboard.component.html
+++ b/src/app/manager-dashboard/manager-dashboard.component.html
@@ -10,6 +10,7 @@
   </ng-container>
   <a *ngIf="planetType !== 'community' || isHub" [routerLink]="['reports', isHub ? { 'hubId': planetConfiguration._id } : {}]" i18n mat-raised-button>Reports</a>
   <a [routerLink]="['reports', 'myplanet', isHub ? { 'hubId': planetConfiguration._id } : {}]" i18n mat-raised-button>myPlanet Reports</a>
+  <a [routerLink]="['logs', 'myplanet', isHub ? { 'hubId': planetConfiguration._id } : {}]" i18n mat-raised-button>myPlanet Logs</a>
   <ng-container *planetAuthorizedRoles="'manager'">
     <a [routerLink]="['surveys']" mat-raised-button i18n>Surveys</a>
     <button *ngIf="planetType !== center && showResendConfiguration"
diff --git a/src/app/logs-myplanet/logs-myplanet.component.html b/src/app/manager-dashboard/reports/logs-myplanet.component.html
similarity index 76%
rename from src/app/logs-myplanet/logs-myplanet.component.html
rename to src/app/manager-dashboard/reports/logs-myplanet.component.html
index 01822b8053..5b0f0318b4 100644
--- a/src/app/logs-myplanet/logs-myplanet.component.html
+++ b/src/app/manager-dashboard/reports/logs-myplanet.component.html
@@ -1,5 +1,5 @@
 <mat-toolbar>
-    <button class="btnBack" mat-icon-button routerLink="/">
+    <button class="btnBack" mat-icon-button routerLink="/manager">
       <mat-icon>arrow_back</mat-icon>
     </button>
     <span i18n>Logs</span>
@@ -13,6 +13,10 @@
   <mat-toolbar>
     <mat-toolbar-row class="primary-color font-size-1">
       <span i18n>myPlanet</span>
+      <span class="toolbar-fill"></span>
+      <button mat-raised-button color="accent" (click)="exportAll()">
+        Export All
+      </button>
     </mat-toolbar-row>
   </mat-toolbar>
   <div class="view-container view-full-height">
@@ -22,6 +26,9 @@
           <mat-panel-title>{{planet.nameDoc?.name || planet.doc?.name}} ({{planet.children.length}})</mat-panel-title>
         </mat-expansion-panel-header>
         <planet-myplanet-table dataType="logs" [data]="planet.children"></planet-myplanet-table>
+        <button mat-raised-button color="accent" (click)="exportSingle(planet)" style="margin-right: 2rem;">
+          Export
+        </button>
       </mat-expansion-panel>
     </ng-container>
     <ng-container *ngIf="isEmpty">
diff --git a/src/app/logs-myplanet/logs-myplanet.component.ts b/src/app/manager-dashboard/reports/logs-myplanet.component.ts
similarity index 58%
rename from src/app/logs-myplanet/logs-myplanet.component.ts
rename to src/app/manager-dashboard/reports/logs-myplanet.component.ts
index c71a58706a..4e6443c94c 100644
--- a/src/app/logs-myplanet/logs-myplanet.component.ts
+++ b/src/app/manager-dashboard/reports/logs-myplanet.component.ts
@@ -1,12 +1,12 @@
 import { Component, OnInit } from '@angular/core';
-import { CouchService } from '../shared/couchdb.service';
+import { CouchService } from '../../shared/couchdb.service';
 import { forkJoin } from 'rxjs';
-import { StateService } from '../shared/state.service';
-import { PlanetMessageService } from '../shared/planet-message.service';
-import { ManagerService } from '../manager-dashboard/manager.service';
-import { filterSpecificFields } from '../shared/table-helpers';
-import { attachNamesToPlanets, areNoChildren } from '../manager-dashboard/reports/reports.utils';
-
+import { StateService } from '../../shared/state.service';
+import { PlanetMessageService } from '../../shared/planet-message.service';
+import { ManagerService } from '../manager.service';
+import { filterSpecificFields } from '../../shared/table-helpers';
+import { attachNamesToPlanets, areNoChildren } from './reports.utils';
+import { CsvService } from '../../shared/csv.service';
 
 @Component({
   templateUrl: './logs-myplanet.component.html'
@@ -23,6 +23,7 @@ export class LogsMyPlanetComponent implements OnInit {
   }
 
   constructor(
+    private csvService: CsvService,
     private couchService: CouchService,
     private stateService: StateService,
     private planetMessageService: PlanetMessageService,
@@ -64,4 +65,36 @@ export class LogsMyPlanetComponent implements OnInit {
     }, (error) => this.planetMessageService.showAlert($localize`There was a problem getting myPlanet activity.`));
   }
 
+  private mapToCsvData(children: any[], planetName?: string): any[] {
+    return children.map((data: any) => ({
+      ...(planetName ? { 'Planet Name': planetName } : {}),
+      'ID': data.androidId,
+      'Name': data.deviceName || data.customDeviceName,
+      'Type': data.type,
+      'Time': new Date(Number(data.time)),
+      'Version': data.version,
+      'Error':  data.error || 'N/A',
+    }));
+  }
+
+  exportAll(): void {
+    const csvData: any[] = this.apklogs.flatMap((planet: any) => {
+      return this.mapToCsvData(planet.children, planet.name);
+    });
+
+    this.csvService.exportCSV({
+      data: csvData,
+      title: 'myPlanet Logs',
+    });
+  }
+
+  exportSingle(planet: any): void {
+    const csvData = this.mapToCsvData(planet.children);
+
+    this.csvService.exportCSV({
+      data: csvData,
+      title: `myPlanet Logs for ${planet.name}`,
+    });
+  }
+
 }
diff --git a/src/app/manager-dashboard/reports/reports-myplanet.component.html b/src/app/manager-dashboard/reports/reports-myplanet.component.html
index e581313d35..8f10c8ea16 100755
--- a/src/app/manager-dashboard/reports/reports-myplanet.component.html
+++ b/src/app/manager-dashboard/reports/reports-myplanet.component.html
@@ -29,6 +29,9 @@
     <mat-toolbar-row class="primary-color font-size-1">
       <span i18n>myPlanet on { planetType, select, center {Nations} other {Communities} }</span>
       <span class="toolbar-fill"></span>
+      <button mat-raised-button color="accent" (click)="exportAll()">
+        Export All
+      </button>
     </mat-toolbar-row>
   </mat-toolbar>
   <div class="view-container view-full-height">
@@ -38,6 +41,9 @@
           <mat-panel-title>{{planet.nameDoc?.name || planet.doc?.name}} ({{planet.children.length}})</mat-panel-title>
         </mat-expansion-panel-header>
         <planet-myplanet-table [data]="planet.children"></planet-myplanet-table>
+        <button mat-raised-button color="accent" (click)="exportSingle(planet)" style="margin-right: 2rem;">
+          Export
+        </button>
       </mat-expansion-panel>
     </ng-container>
     <ng-container *ngIf="isEmpty">
diff --git a/src/app/manager-dashboard/reports/reports-myplanet.component.ts b/src/app/manager-dashboard/reports/reports-myplanet.component.ts
index 8e4dc06efb..134c0e2255 100755
--- a/src/app/manager-dashboard/reports/reports-myplanet.component.ts
+++ b/src/app/manager-dashboard/reports/reports-myplanet.component.ts
@@ -11,6 +11,7 @@ import { ActivatedRoute } from '@angular/router';
 import { switchMap, map } from 'rxjs/operators';
 import { findDocuments } from '../../shared/mangoQueries';
 import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
+import { CsvService } from '../../shared/csv.service';
 
 @Component({
   templateUrl: './reports-myplanet.component.html'
@@ -33,13 +34,14 @@ export class ReportsMyPlanetComponent implements OnInit {
   hub = { spokes: [] };
 
   constructor(
+    private csvService: CsvService,
     private couchService: CouchService,
     private stateService: StateService,
     private planetMessageService: PlanetMessageService,
     private managerService: ManagerService,
     private reportsService: ReportsService,
     private route: ActivatedRoute,
-    private deviceInfoService: DeviceInfoService,
+    private deviceInfoService: DeviceInfoService
   ) {
     this.deviceType = this.deviceInfoService.getDeviceType();
     this.isMobile = this.deviceType === DeviceType.MOBILE;
@@ -112,4 +114,52 @@ export class ReportsMyPlanetComponent implements OnInit {
     );
   }
 
+  private formatTotalTime(totalMilliseconds: number): string {
+    if (!totalMilliseconds || totalMilliseconds === 0) {
+        return '00:00:00';
+    }
+    const totalSeconds = Math.floor(totalMilliseconds / 1000);
+    const hours = Math.floor(totalSeconds / 3600);
+    const minutes = Math.floor((totalSeconds % 3600) / 60);
+    const seconds = totalSeconds % 60;
+
+    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
+  }
+
+  private mapToCsvData(children: any[], planetName?: string): any[] {
+    return children.map((data: any) => ({
+      ...(planetName ? { 'Planet Name': planetName } : {}),
+      'ID': data.androidId.toString() || data.uniqueAndroidId.toString(),
+      'Name': data.deviceName || data.customDeviceName,
+      'Last Synced': data.time && data.time !== 0 ?
+      new Date(data.time).toDateString() :
+      data.last_synced && data.last_synced !== 0 ?
+      new Date(data.last_synced).toDateString() :
+      'N/A',
+      'Version': data.versionName,
+      'No of Visits': data.count,
+      'Used Time': this.formatTotalTime(data.totalUsedTime),
+    }));
+  }
+
+  exportAll(): void {
+    const csvData: any[] = this.planets.flatMap((planet: any) => {
+      return this.mapToCsvData(planet.children, planet.name);
+    });
+
+    this.csvService.exportCSV({
+      data: csvData,
+      title: 'myPlanet Reports',
+    });
+  }
+
+  exportSingle(planet: any): void {
+    const csvData = this.mapToCsvData(planet.children);
+
+    this.csvService.exportCSV({
+      data: csvData,
+      title: `myPlanet Reports for ${planet.name}`,
+    });
+  }
+
 }

From 6a2f4ece25258e817d9c18003a49e002d7f02a55 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 13 Dec 2024 16:11:57 -0500
Subject: [PATCH 051/113] teams: smoother calendar recursions (fixes #7858)
 (#7862)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../add-meetups/meetups-add.component.html    |  7 +-
 .../add-meetups/meetups-add.component.ts      | 75 ++++++++++++-------
 src/app/shared/calendar.component.ts          | 15 ++--
 src/app/validators/custom-validators.ts       | 11 +++
 5 files changed, 72 insertions(+), 38 deletions(-)

diff --git a/package.json b/package.json
index 2d26be0a9e..625d9ddf90 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.0",
+  "version": "0.16.1",
   "myplanet": {
     "latest": "v0.21.40",
     "min": "v0.20.40"
diff --git a/src/app/meetups/add-meetups/meetups-add.component.html b/src/app/meetups/add-meetups/meetups-add.component.html
index cca2895936..f44c7ed018 100644
--- a/src/app/meetups/add-meetups/meetups-add.component.html
+++ b/src/app/meetups/add-meetups/meetups-add.component.html
@@ -53,8 +53,11 @@
           <mat-error><planet-form-error-messages [control]="meetupForm.controls.recurring"></planet-form-error-messages></mat-error>
         </mat-radio-group>
       </div>
-      <div *ngIf="meetupForm.controls.recurring.value==='weekly'" class="full-width">
-        <mat-checkbox (change)="onDayChange(day, $event.checked)" *ngFor="let day of days" class="margin-lr" [checked]="isClassDay(day)">{{day}}</mat-checkbox>
+      <div *ngIf="meetupForm.controls.recurring.value === 'weekly'" class="full-width">
+          <mat-checkbox (change)="onDayChange(day, $event.checked)" *ngFor="let day of days"  class="margin-lr" [checked]="meetupForm.controls.day.value.includes(day)"> {{ day }}</mat-checkbox>
+          <mat-error *ngIf="meetupForm.controls.day.hasError('noDaysSelected')">
+            <span i18n>Please select at least one day.</span>
+          </mat-error>
       </div>
       <ng-container *ngIf="meetupForm.controls.recurring.value==='weekly' || meetupForm.controls.recurring.value==='daily'">
         <mat-form-field>
diff --git a/src/app/meetups/add-meetups/meetups-add.component.ts b/src/app/meetups/add-meetups/meetups-add.component.ts
index 9b26da9cee..9b22185699 100644
--- a/src/app/meetups/add-meetups/meetups-add.component.ts
+++ b/src/app/meetups/add-meetups/meetups-add.component.ts
@@ -103,22 +103,24 @@ export class MeetupsAddComponent implements OnInit {
     }, {
       validators: CustomValidators.meetupTimeValidator()
     });
-  }
+}
 
-  onSubmit() {
-    if (!this.meetupForm.valid) {
-      showFormErrors(this.meetupForm.controls);
-      return;
-    }
-    this.meetupForm.value.startTime = this.changeTimeFormat(this.meetupForm.value.startTime);
-    this.meetupForm.value.endTime = this.changeTimeFormat(this.meetupForm.value.endTime);
-    const meetup = { ...this.meetupForm.value, link: this.link, sync: this.sync };
-    if (this.pageType === 'Update') {
+onSubmit() {
+  if (!this.meetupForm.valid) {
+    showFormErrors(this.meetupForm.controls);
+    return;
+  }
+  const dayFormArray = this.meetupForm.get('day') as FormArray;
+  dayFormArray.updateValueAndValidity();
+  this.meetupForm.value.startTime = this.changeTimeFormat(this.meetupForm.value.startTime);
+  this.meetupForm.value.endTime = this.changeTimeFormat(this.meetupForm.value.endTime);
+  const meetup = { ...this.meetupForm.value, link: this.link, sync: this.sync };
+  if (this.pageType === 'Update') {
       this.updateMeetup(meetup);
     } else {
       this.addMeetup(meetup);
-    }
   }
+}
 
   changeTimeFormat(time: string): string {
     if (time && time.length < 5) {
@@ -174,35 +176,50 @@ export class MeetupsAddComponent implements OnInit {
     }
   }
 
-  isClassDay(day) {
-    return this.meetupFrequency.includes(day) ? true : false;
-  }
-
   onDayChange(day: string, isChecked: boolean) {
     const dayFormArray = <FormArray>this.meetupForm.controls.day;
     if (isChecked) {
       // add to day array if checked
       dayFormArray.push(new FormControl(day));
     } else {
-      // remove from day array if unchecked
-      const index = dayFormArray.controls.findIndex(x => x.value === day);
-      dayFormArray.removeAt(index);
+        // remove from day array if unchecked
+        const index = dayFormArray.controls.findIndex(x => x.value === day);
+        if (index >= 0) {
+            dayFormArray.removeAt(index);
+        }
     }
-  }
+    dayFormArray.updateValueAndValidity();
+}
 
-  toggleDaily(val, showCheckbox) {
-    // empty the array
-    this.meetupForm.setControl('day', this.fb.array([]));
-    switch (val) {
+toggleDaily(val: string, showCheckbox: boolean) {
+  const dayFormArray = this.meetupForm.get('day') as FormArray;
+  dayFormArray.clear();
+  dayFormArray.clearValidators();
+
+  switch (val) {
+      // add all days to the array if the course is daily
       case 'daily':
-        // add all days to the array if the course is daily
-        this.meetupForm.setControl('day', this.fb.array(this.days));
-        break;
+          this.days.forEach((day) => {
+              dayFormArray.push(new FormControl(day));
+          });
+          break;
       case 'weekly':
-        this.meetupForm.setControl('day', this.fb.array(this.meetupFrequency));
-        break;
-    }
+          dayFormArray.setValidators(CustomValidators.atLeastOneDaySelected());
+          const startDate = this.meetupForm.controls.startDate.value;
+          if (startDate) {
+              const startDateObj = new Date(startDate);
+              const dayOfWeek = this.days[startDateObj.getDay()];
+              if (dayOfWeek) {
+                  dayFormArray.push(new FormControl(dayOfWeek));
+              }
+          }
+          break;
+
+      default:
+          break;
   }
+  dayFormArray.updateValueAndValidity();
+}
 
   meetupChangeNotifications(users, meetupInfo, meetupId) {
     return { docs: users.map((user) => ({
diff --git a/src/app/shared/calendar.component.ts b/src/app/shared/calendar.component.ts
index 31cc504025..a45d582a21 100644
--- a/src/app/shared/calendar.component.ts
+++ b/src/app/shared/calendar.component.ts
@@ -171,13 +171,16 @@ export class PlanetCalendarComponent implements OnInit, OnChanges {
   }
 
   openAddEventDialog(event) {
-    let meetup;
-    if (event?.start) {
-      meetup = {
-        startDate: event?.start,
-        endDate: this.adjustEndDate(event?.end)
-      };
+    const today = new Date();
+    const meetup = event?.start
+    ? {
+      startDate: event.start,
+      endDate: this.adjustEndDate(event.end),
     }
+  : {
+      startDate: today,
+      endDate: today,
+    };
     this.dialog.open(DialogsAddMeetupsComponent, {
       data: { meetup: meetup, link: this.link, sync: this.sync, onMeetupsChange: this.onMeetupsChange.bind(this), editable: this.editable }
     });
diff --git a/src/app/validators/custom-validators.ts b/src/app/validators/custom-validators.ts
index c3c9311230..da950a37c8 100755
--- a/src/app/validators/custom-validators.ts
+++ b/src/app/validators/custom-validators.ts
@@ -255,4 +255,15 @@ export class CustomValidators {
     });
   }
 
+  static atLeastOneDaySelected(): ValidatorFn {
+    return (control: AbstractControl): ValidationErrors | null => {
+        if (!control.parent) { return null; }
+        const recurringControl = control.parent.get('recurring');
+        if (!recurringControl || recurringControl.value !== 'weekly') {
+            return null;
+        }
+        const selectedDays = control.value;
+        return selectedDays && selectedDays.length > 0 ? null : { noDaysSelected: true };
+    };
+  }
 }

From 432e29325b7056bdd34f0002a4791e19f1af815f Mon Sep 17 00:00:00 2001
From: sahilvunnam <118228103+sahilvunnam@users.noreply.github.com>
Date: Fri, 13 Dec 2024 13:23:30 -0800
Subject: [PATCH 052/113] resources: smoother collections display (fixes #7772)
 (#7776)

Co-authored-by: Axel Lorens <axelnlorens@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                | 2 +-
 src/app/shared/forms/planet-tag-input-dialog.component.html | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 625d9ddf90..aaa098482b 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.1",
+  "version": "0.16.2",
   "myplanet": {
     "latest": "v0.21.40",
     "min": "v0.20.40"
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.html b/src/app/shared/forms/planet-tag-input-dialog.component.html
index 150940285e..eeb210d37a 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.html
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.html
@@ -54,8 +54,10 @@
   <mat-nav-list *ngIf="!selectMany">
     <mat-list-item (click)="selectOne('')" i18n>All</mat-list-item>
     <ng-container *ngFor="let tag of tags">
-      <mat-list-item (click)="tag.subTags.length === 0 ? selectOne(tag._id || tag.name) : toggleSubcollection($event,tag._id)" [ngClass]="{ 'mat-body-2': tag.subTags.length > 0 }">
-        {{tag.name + ' (' + (tag.count || 0) + ')'}}
+      <mat-list-item class="tag-text" (click)="tag.subTags.length === 0 ? selectOne(tag._id || tag.name) : toggleSubcollection($event, tag._id)" 
+        [ngClass]="{ 'mat-body-2': tag.subTags.length > 0 }"
+      >
+        {{ (tag.name + ' (' + (tag.count || 0) + ')') | slice:0:30 }}{{ (tag.name.length + tag.count.toString().length > 30) ? '...' : '' }}
         <planet-tag-input-toggle-icon *ngIf="tag.subTags.length > 0" [isOpen]="subcollectionIsOpen.get(tag._id)"></planet-tag-input-toggle-icon>
         <span class="toolbar-fill"></span>
         <button mat-stroked-button *ngIf="isUserAdmin" (click)="editTagClick($event,tag)" i18n>Edit</button>

From 6d7e593461a19e44880828f03b5e58cc98712eb3 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 16 Dec 2024 15:56:59 -0500
Subject: [PATCH 053/113] courses: smoother progress export (fixes #7811)
 (#7912)

Co-authored-by: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../courses-progress-leader.component.ts      | 43 ++++++++++++++-----
 2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/package.json b/package.json
index aaa098482b..e97348854d 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.2",
+  "version": "0.16.3",
   "myplanet": {
     "latest": "v0.21.40",
     "min": "v0.20.40"
diff --git a/src/app/courses/progress-courses/courses-progress-leader.component.ts b/src/app/courses/progress-courses/courses-progress-leader.component.ts
index c6a36c59d9..2a9faa7947 100644
--- a/src/app/courses/progress-courses/courses-progress-leader.component.ts
+++ b/src/app/courses/progress-courses/courses-progress-leader.component.ts
@@ -10,6 +10,7 @@ import { dedupeObjectArray } from '../../shared/utils';
 import { DialogsLoadingService } from '../../shared/dialogs/dialogs-loading.service';
 import { findDocuments } from '../../shared/mangoQueries';
 import { UserProfileDialogComponent } from '../../users/users-profile/users-profile-dialog.component';
+import { StateService } from '../../shared/state.service';
 import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
 
 @Component({
@@ -31,6 +32,7 @@ export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
   submittedExamSteps: any[] = [];
   planetCodes: string[] = [];
   selectedPlanetCode: string;
+  configuration: any = {};
   deviceType: DeviceType;
   deviceTypes = DeviceType;
 
@@ -42,6 +44,7 @@ export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
     private csvService: CsvService,
     private dialogsLoadingService: DialogsLoadingService,
     private dialog: MatDialog,
+    private stateService: StateService,
     private deviceInfoService: DeviceInfoService
   ) {
     this.dialogsLoadingService.start();
@@ -221,23 +224,41 @@ export class CoursesProgressLeaderComponent implements OnInit, OnDestroy {
   }
 
   structureChartData(data) {
-    const dataArr = [];
-    data.forEach(element => {
-      const dataDict = {};
-      dataDict['Username'] = element.label;
-      for (let i = 0; i < element.items.length; i++) {
-        dataDict[`Step ${(i + 1)}`] = element.items[i].number;
-      }
+    return data.map(element => {
+      let successfulSteps = 0;
+      let totalSteps = 0;
+      let totalErrors = 0;
+      const steps = {};
 
-      dataArr.push(dataDict);
+      element.items.forEach((item, index) => {
+        const stepErrors = item.number || 0;
+        totalSteps++;
+        if (stepErrors === 0) {
+          successfulSteps++;
+        }
+        totalErrors += stepErrors;
+        steps[`Step ${(index + 1)}`] = stepErrors;
+      });
+
+      return {
+        'Username': element.label,
+        'Success Percentage': `${((successfulSteps / totalSteps) * 100).toFixed(2)}%`,
+        'Total Errors': totalErrors,
+        ...steps
+      };
     });
-    return dataArr;
   }
 
   exportChartData() {
+    const planetName = this.stateService.configuration.name;
+    const courseTitle = this.course.courseTitle;
+    const entityLabel = this.configuration.planetType === 'nation' ? 'Nation' : 'Community';
+    const title = $localize`${courseTitle} Course Progress for ${entityLabel} ${planetName}`;
+
+    const structuredData = this.structureChartData(this.chartData);
     this.csvService.exportCSV({
-      data:  this.structureChartData(this.chartData),
-      title: $localize`Course Progress Data`
+      data: structuredData,
+      title: title
     });
   }
 

From dad08fdd8b65b27eab3c50dd2ec694363e0160b4 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 16 Dec 2024 16:14:48 -0500
Subject: [PATCH 054/113] resources: smoother navigation (fixes #7927) (#7929)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                | 2 +-
 .../resources/view-resources/resources-view.component.html  | 6 +++---
 src/app/resources/view-resources/resources-view.scss        | 4 ++++
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index e97348854d..e5e7f9ef39 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.3",
+  "version": "0.16.4",
   "myplanet": {
     "latest": "v0.21.40",
     "min": "v0.20.40"
diff --git a/src/app/resources/view-resources/resources-view.component.html b/src/app/resources/view-resources/resources-view.component.html
index cedf7e1f91..9c040b3a7f 100644
--- a/src/app/resources/view-resources/resources-view.component.html
+++ b/src/app/resources/view-resources/resources-view.component.html
@@ -43,11 +43,11 @@
 
   <ng-template #actionButtons>
     <ng-container *ngIf="!parent">
-      <a mat-raised-button *ngIf="resource.doc?._attachments" [href]="resourceSrc" target="_blank" color="accent" i18n>Open in new tab</a>
-      <button mat-raised-button color="accent" (click)="libraryToggle(resource._id, 'add')" i18n class="margin-lr-3" *ngIf="!isUserEnrolled">
+      <a mat-raised-button *ngIf="resource.doc?._attachments" [href]="resourceSrc" target="_blank" color="accent" i18n class = "toolbar-button margin-lr-3">Open in new tab</a>
+      <button mat-raised-button color="accent" (click)="libraryToggle(resource._id, 'add')" i18n class="toolbar-button margin-lr-3" *ngIf="!isUserEnrolled">
         Add to myLibrary
       </button>
-      <button mat-raised-button color="accent" (click)="libraryToggle(resource._id, 'remove')" i18n class="margin-lr-3" *ngIf="isUserEnrolled">
+      <button mat-raised-button color="accent" (click)="libraryToggle(resource._id, 'remove')" i18n class="toolbar-button margin-lr-3" *ngIf="isUserEnrolled">
         Remove from myLibrary
       </button>
     </ng-container>
diff --git a/src/app/resources/view-resources/resources-view.scss b/src/app/resources/view-resources/resources-view.scss
index 937c77f616..e33ad07cb0 100644
--- a/src/app/resources/view-resources/resources-view.scss
+++ b/src/app/resources/view-resources/resources-view.scss
@@ -34,6 +34,10 @@
       max-height: 60vh;
     }
   }
+  
+  .toolbar-button {
+    flex-shrink: 0;
+  }
 
   @media (max-width: $screen-sm) {
     .view-container {

From 56d4b398b9c8fd2732e60eb5ad926a5351f12c45 Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Mon, 16 Dec 2024 13:22:56 -0800
Subject: [PATCH 055/113] chat: smoother ux (fixes #7915) (#7931)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../chat/chat-window/chat-window.component.ts | 22 +++++++++++++++----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index e5e7f9ef39..6cfbdb5399 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.4",
+  "version": "0.16.5",
   "myplanet": {
     "latest": "v0.21.40",
     "min": "v0.20.40"
diff --git a/src/app/chat/chat-window/chat-window.component.ts b/src/app/chat/chat-window/chat-window.component.ts
index 85cdf7ce7d..2b987c78cf 100644
--- a/src/app/chat/chat-window/chat-window.component.ts
+++ b/src/app/chat/chat-window/chat-window.component.ts
@@ -1,7 +1,7 @@
 import { Component, OnInit, OnDestroy, ViewChild, ElementRef, ChangeDetectorRef, Input, AfterViewInit } from '@angular/core';
 import { FormBuilder, FormGroup } from '@angular/forms';
 import { Subject } from 'rxjs';
-import { takeUntil } from 'rxjs/operators';
+import { filter, takeUntil } from 'rxjs/operators';
 
 import { CustomValidators } from '../../validators/custom-validators';
 import { ConversationForm, AIProvider } from '../chat.model';
@@ -20,6 +20,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy, AfterViewInit {
   spinnerOn = true;
   streaming: boolean;
   disabled = false;
+  clearChat = true;
   provider: AIProvider;
   conversations: any[] = [];
   selectedConversationId: any;
@@ -71,8 +72,7 @@ export class ChatWindowComponent implements OnInit, OnDestroy, AfterViewInit {
     this.chatService.newChatSelected$
       .pipe(takeUntil(this.onDestroy$))
       .subscribe(() => {
-        this.selectedConversationId = null;
-        this.conversations = [];
+        this.resetConversation();
         this.focusInput();
       }, error => {
         console.error('Error subscribing to newChatSelected$', error);
@@ -81,7 +81,16 @@ export class ChatWindowComponent implements OnInit, OnDestroy, AfterViewInit {
 
   subscribeToSelectedConversation() {
     this.chatService.selectedConversationId$
-      .pipe(takeUntil(this.onDestroy$))
+      .pipe(
+        takeUntil(this.onDestroy$),
+        filter(() => {
+          if (this.clearChat) {
+            this.clearChat = false;
+            return false;
+          }
+          return true;
+        })
+      )
       .subscribe((conversationId) => {
         this.selectedConversationId = conversationId;
         this.fetchConversation(this.selectedConversationId?._id);
@@ -102,6 +111,11 @@ export class ChatWindowComponent implements OnInit, OnDestroy, AfterViewInit {
       }));
   }
 
+  resetConversation() {
+    this.conversations = [];
+    this.selectedConversationId = null;
+  }
+
   createForm() {
     this.promptForm = this.formBuilder.group({
       prompt: [ '', CustomValidators.required ],

From 7f741bd80e263546966dca3e06d49e686d9c8f5f Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 17 Dec 2024 15:19:21 -0500
Subject: [PATCH 056/113] courses: smoother snackbar (fixes #7934) (#7935)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       | 6 +++---
 src/app/courses/courses.service.ts | 6 ++++--
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index 6cfbdb5399..be624f1aa5 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.5",
+  "version": "0.16.6",
   "myplanet": {
-    "latest": "v0.21.40",
-    "min": "v0.20.40"
+    "latest": "v0.21.42",
+    "min": "v0.20.42"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/courses.service.ts b/src/app/courses/courses.service.ts
index 072e656893..78866f6d07 100644
--- a/src/app/courses/courses.service.ts
+++ b/src/app/courses/courses.service.ts
@@ -203,6 +203,7 @@ export class CoursesService {
 
   courseResignAdmission(courseId, type, courseTitle?) {
     const title = courseTitle ? courseTitle : this.getCourseNameFromId(courseId);
+    const truncatedTitle = title.length > 180 ? `${title.slice(0, 180)}...` : title;
     const courseIds: any = [ ...this.userService.shelf.courseIds ];
     if (type === 'resign') {
       const myCourseIndex = courseIds.indexOf(courseId);
@@ -211,8 +212,9 @@ export class CoursesService {
       courseIds.push(courseId);
     }
     return this.userService.updateShelf(courseIds, 'courseIds').pipe(map((res) => {
-      const admissionMessage = type === 'resign' ? $localize`${title} successfully removed from myCourses` :
-        $localize`${title} added to your dashboard`;
+      const admissionMessage = type === 'resign'
+        ? $localize`${truncatedTitle} successfully removed from myCourses`
+        : $localize`${truncatedTitle} added to your dashboard`;
       this.planetMessageService.showMessage(admissionMessage);
       return res;
     }));

From 555417caa55b973268f3dfa01dbee13c0e7743cb Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 17 Dec 2024 15:24:29 -0500
Subject: [PATCH 057/113] courses: smoother progress navigation (fixes
 #7911)(fixes #7936) (#7938)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                               | 2 +-
 .../progress-courses/courses-progress-chart.component.html | 2 +-
 .../courses-progress-learner.component.html                | 2 +-
 .../progress-courses/courses-progress-learner.component.ts | 7 +++++++
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index be624f1aa5..7c07e2bd36 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.6",
+  "version": "0.16.7",
   "myplanet": {
     "latest": "v0.21.42",
     "min": "v0.20.42"
diff --git a/src/app/courses/progress-courses/courses-progress-chart.component.html b/src/app/courses/progress-courses/courses-progress-chart.component.html
index fb3711547f..1b5508212b 100644
--- a/src/app/courses/progress-courses/courses-progress-chart.component.html
+++ b/src/app/courses/progress-courses/courses-progress-chart.component.html
@@ -41,6 +41,6 @@
   <div class="errors" *ngFor="let set of sets">
     <div>{{set.total}}</div>
     <planet-avatar *ngIf="showAvatar" class="cursor-pointer" (click)="labelClick(set)" [username]="set.label" [planetCode]="set.planetCode" imgClass="profile-image-large"></planet-avatar>
-    <div class="wrap-content cursor-pointer" (click)="labelClick(set)" i18n-matTooltip [matTooltip]="set.label?.length > 3 ? set.label : null "><p>{{set.label}}</p></div>
+    <div class="wrap-content cursor-pointer" (click)="labelClick(set)" i18n-matTooltip [matTooltip]="set.label && set.label.length > 3 ? (set.label.length > 180 ? (set.label | slice:0:180) + '...' : set.label) : null"><p>{{set.label}}</p></div>
   </div>
 </div>
diff --git a/src/app/courses/progress-courses/courses-progress-learner.component.html b/src/app/courses/progress-courses/courses-progress-learner.component.html
index e46c021040..1258573afe 100644
--- a/src/app/courses/progress-courses/courses-progress-learner.component.html
+++ b/src/app/courses/progress-courses/courses-progress-learner.component.html
@@ -7,7 +7,7 @@
     <span i18n>Courses: myProgress</span>
   </mat-toolbar>
   <div class="view-container view-full-height">
-    <planet-courses-progress-chart *ngIf="chartData?.length; else noProgress" [inputs]="chartData" [height]="yAxisLength" [showTotals]="false" (changeData)="changeData($event)">
+    <planet-courses-progress-chart *ngIf="chartData?.length; else noProgress" [inputs]="chartData" [height]="yAxisLength" [showTotals]="false" (clickAction)="handleCourseClick($event)" (changeData)="changeData($event)">
     </planet-courses-progress-chart>
     <ng-template #noProgress i18n>No Progress record available</ng-template>
   </div>
diff --git a/src/app/courses/progress-courses/courses-progress-learner.component.ts b/src/app/courses/progress-courses/courses-progress-learner.component.ts
index 9c59bab079..c030e26b8e 100644
--- a/src/app/courses/progress-courses/courses-progress-learner.component.ts
+++ b/src/app/courses/progress-courses/courses-progress-learner.component.ts
@@ -62,6 +62,7 @@ export class CoursesProgressLearnerComponent implements OnInit, OnDestroy {
   createChartData(courses = [], submissions) {
     return courses.map((course: any) => ({
       label: course.doc.courseTitle,
+      courseId: course._id,
       items: this.courseBySteps(
         course,
         submissions.filter(submission => submission.parentId.indexOf(course._id) > -1)
@@ -106,4 +107,10 @@ export class CoursesProgressLearnerComponent implements OnInit, OnDestroy {
 
   changeData(event) {}
 
+  handleCourseClick(event: any) {
+    if (event.courseId) {
+      this.router.navigate([ '/courses', 'view', event.courseId ]);
+    }
+  }
+
 }

From 8c8a9551d87237398fcbc6d643ea6dafcb58740d Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Tue, 17 Dec 2024 13:01:19 -0800
Subject: [PATCH 058/113] courses: smoother multiple choice (fixes #7939)
 (#7946)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                          |  2 +-
 src/app/exams/exams-view.component.ts | 30 ++++++++++++++++++++-------
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index 7c07e2bd36..6899ed7369 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.7",
+  "version": "0.16.8",
   "myplanet": {
     "latest": "v0.21.42",
     "min": "v0.20.42"
diff --git a/src/app/exams/exams-view.component.ts b/src/app/exams/exams-view.component.ts
index 04cd67d8c1..c9b70fe540 100644
--- a/src/app/exams/exams-view.component.ts
+++ b/src/app/exams/exams-view.component.ts
@@ -279,13 +279,22 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
 }
 
   setAnswer(event, option) {
-    this.answer.setValue(Array.isArray(this.answer.value) ? this.answer.value : []);
-    const value = this.answer.value;
-    if (event.checked === true) {
-      value.push(option);
-    } else if (event.checked === false) {
-      value.splice(value.indexOf(option), 1);
+    const value = this.answer.value || [];
+
+
+    if (event.checked) {
+      if (!value.includes(option)) {
+        value.push(option);
+      }
+    } else {
+      const index = value.indexOf(option);
+      if (index > -1) {
+        value.splice(index, 1);
+      }
     }
+
+    this.answer.setValue(value);
+    this.answer.updateValueAndValidity();
     this.checkboxState[option.id] = event.checked;
   }
 
@@ -343,9 +352,14 @@ export class ExamsViewComponent implements OnInit, OnDestroy {
 
   answerValidator(ac: AbstractControl) {
     if (typeof ac.value === 'string') {
-      return CustomValidators.required(ac);
+      return ac.value.trim() ? null : { required: true };
     }
-    return ac.value !== null ? null : { required: true };
+
+    if (Array.isArray(ac.value)) {
+      return ac.value.length > 0 ? null : { required: true };
+    }
+
+    return ac.value !== null && ac.value !== undefined ? null : { required: true };
   }
 
   setViewAnswerText(answer: any) {

From 6e06cff4299d0e568a410ae154b7d6c7b5f927b4 Mon Sep 17 00:00:00 2001
From: sahilvunnam <118228103+sahilvunnam@users.noreply.github.com>
Date: Tue, 17 Dec 2024 13:26:57 -0800
Subject: [PATCH 059/113] community: smoother calendar legend (fixes #6572)
 (#7770)

Co-authored-by: Axel Lorens <axelnlorens@gmail.com>
Co-authored-by: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                               |  2 +-
 src/app/community/community.component.html |  2 +-
 src/app/community/community.scss           | 23 +++++++++++++++++++++-
 src/app/shared/calendar.component.ts       | 15 ++++++++++++++
 src/app/teams/teams-view.component.html    |  2 +-
 5 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 6899ed7369..78a26d8913 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.8",
+  "version": "0.16.9",
   "myplanet": {
     "latest": "v0.21.42",
     "min": "v0.20.42"
diff --git a/src/app/community/community.component.html b/src/app/community/community.component.html
index e8416ebb39..aec7227687 100644
--- a/src/app/community/community.component.html
+++ b/src/app/community/community.component.html
@@ -72,7 +72,7 @@ <h3 style="text-align: right; margin-right: 0.5rem;">
           <planet-teams-reports [reports]="reports" [editable]="isCommunityLeader && !planetCode" [team]="team" (reportsChanged)="dataChanged()"></planet-teams-reports>
         </mat-tab>
         <mat-tab i18n-label label="Calendar" *ngIf="deviceType !== deviceTypes.DESKTOP">
-          <planet-calendar [resizeCalendar]="resizeCalendar" [link]="{ teams: teamId }" [sync]="{ type: 'sync', planetCode: planetCode || configuration.code }"></planet-calendar>
+          <planet-calendar [resizeCalendar]="resizeCalendar" [type]="'community'" [link]="{ teams: teamId }" [sync]="{ type: 'sync', planetCode: planetCode || configuration.code }"></planet-calendar>
         </mat-tab>
       </mat-tab-group>
     </div>
diff --git a/src/app/community/community.scss b/src/app/community/community.scss
index 293fb05afe..3d8e70b249 100644
--- a/src/app/community/community.scss
+++ b/src/app/community/community.scss
@@ -35,6 +35,27 @@ planet-calendar {
   overflow-y: auto;
 }
 
+.calendar-legend {
+  padding-top: 10px;
+  text-align: right;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.calendar-legend .legend-item {
+  display: inline-flex;
+  align-items: center;
+}
+
+.calendar-legend .legend-color {
+  width: 20px;
+  height: 20px;
+  margin-right: 10px;
+  border-radius: 4px;
+}
+
 .card-grid {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
@@ -60,6 +81,6 @@ mat-tab-group, mat-tab {
   padding-top: 0.5rem;
 }
 
-.toggle-button{
+.toggle-button {
   margin-bottom: 1rem;
 }
diff --git a/src/app/shared/calendar.component.ts b/src/app/shared/calendar.component.ts
index a45d582a21..80a05b48b9 100644
--- a/src/app/shared/calendar.component.ts
+++ b/src/app/shared/calendar.component.ts
@@ -16,6 +16,14 @@ import { addDateAndTime, styleVariables } from './utils';
   selector: 'planet-calendar',
   template: `
     <full-calendar #calendar [options]="calendarOptions"></full-calendar>
+    <div class="calendar-legend" *ngIf="showLegend">
+      <div *ngFor="let legend of eventLegend">
+        <div class="legend-item" *ngIf="!legend.type || legend.type === type">
+          <div class="legend-color" [style.backgroundColor]="legend.color"></div>
+          <span>{{ legend.label }}</span>
+        </div>
+      </div>
+    </div>
   `
 })
 export class PlanetCalendarComponent implements OnInit, OnChanges {
@@ -25,6 +33,7 @@ export class PlanetCalendarComponent implements OnInit, OnChanges {
   @Input() link: any = {};
   @Input() sync: { type: 'local' | 'sync', planetCode: string };
   @Input() editable = true;
+  @Input() type = '';
 
   @Input() header?: any = {
     left: 'title',
@@ -47,6 +56,12 @@ export class PlanetCalendarComponent implements OnInit, OnChanges {
   dbName = 'meetups';
   meetups: any[] = [];
   tasks: any[] = [];
+  showLegend = true;
+  eventLegend = [
+    { color: styleVariables.primary, label: 'Event' },
+    { color: 'orange', label: 'Uncompleted Task', type: 'team' },
+    { color: 'grey', label: 'Completed Task', type: 'team' }
+  ];
 
   calendarOptions: CalendarOptions = {
     initialView: 'dayGridMonth',
diff --git a/src/app/teams/teams-view.component.html b/src/app/teams/teams-view.component.html
index 9f2796632d..2a651303e3 100644
--- a/src/app/teams/teams-view.component.html
+++ b/src/app/teams/teams-view.component.html
@@ -131,7 +131,7 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
           <ng-template mat-tab-label>
             <ng-container i18n>Calendar</ng-container>
           </ng-template>
-          <planet-calendar *ngIf="calendarTab.isActive" [link]="{ teams: teamId }" [sync]="{ type: team.teamType, planetCode: team.teamPlanetCode }" [editable]="userStatus === 'member'"></planet-calendar>
+          <planet-calendar *ngIf="calendarTab.isActive" [type]="'team'" [link]="{ teams: teamId }" [sync]="{ type: team.teamType, planetCode: team.teamPlanetCode }" [editable]="userStatus === 'member'"></planet-calendar>
         </mat-tab>
         <mat-tab *ngIf="mode!=='team'">
           <ng-template mat-tab-label>

From 119bef26411fb230d95f11a7ea1ed14d9f0ac1df Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Tue, 17 Dec 2024 13:31:21 -0800
Subject: [PATCH 060/113] resources: smoother collections (fixes #7928) (#7932)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 .../planet-tag-selected-input.component.ts    | 23 ++++++++++++++++---
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 78a26d8913..6896556574 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.9",
+  "version": "0.16.10",
   "myplanet": {
     "latest": "v0.21.42",
     "min": "v0.20.42"
diff --git a/src/app/shared/forms/planet-tag-selected-input.component.ts b/src/app/shared/forms/planet-tag-selected-input.component.ts
index 11f37d8f21..afc3d4308d 100644
--- a/src/app/shared/forms/planet-tag-selected-input.component.ts
+++ b/src/app/shared/forms/planet-tag-selected-input.component.ts
@@ -1,11 +1,13 @@
-import { Component, Input, OnChanges } from '@angular/core';
+import { Component, Input, OnChanges, HostListener } from '@angular/core';
 import { TagsService } from './tags.service';
+import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
 
 @Component({
   template: `
     <span [ngSwitch]="selectedIds.length" class="small margin-lr-5">
       <span *ngSwitchCase="0" i18n>No collections selected</span>
-      <span *ngSwitchCase="1"><span i18n>Selected:</span>{{' ' + tooltipLabels}}</span>
+      <span *ngSwitchCase="1"><span i18n>Selected:</span>
+        {{ truncatedTooltip }}
       <span *ngSwitchDefault [matTooltip]="tooltipLabels" i18n>Hover to see selected collections</span>
     </span>
   `,
@@ -17,18 +19,33 @@ export class PlanetTagSelectedInputComponent implements OnChanges {
   @Input() allTags: any[] = [];
 
   tooltipLabels = '';
+  deviceType: DeviceType;
+  deviceTypes: typeof DeviceType = DeviceType;
 
   constructor(
-    private tagsService: TagsService
+    private tagsService: TagsService,
+    private deviceInfoService: DeviceInfoService
   ) {}
 
   ngOnChanges() {
     this.setTooltipLabels(this.selectedIds, this.allTags);
   }
 
+  @HostListener('window:resize') OnResize() {
+      this.deviceType = this.deviceInfoService.getDeviceType();
+    }
+
   setTooltipLabels(selectedIds, allTags) {
     const tagsNames = selectedIds.map((tag: any) => this.tagsService.findTag(tag, allTags).name);
     this.tooltipLabels = tagsNames.join(', ');
   }
 
+  get truncatedTooltip(): string {
+    const maxLength = this.deviceType === this.deviceTypes.DESKTOP ? 50 :
+                      this.deviceType === this.deviceTypes.TABLET ? 35 : 20;
+    return this.tooltipLabels.length > maxLength
+      ? this.tooltipLabels.slice(0, maxLength) + '...'
+      : this.tooltipLabels;
+  }
+
 }

From bab2894c6b9dae28954bf022d8314e1fbc4dbd8b Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 18 Dec 2024 12:40:21 -0800
Subject: [PATCH 061/113] resources: smoother subcollections (fixes #7948)
 (#7958)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  6 +++---
 .../planet-tag-input-dialog.component.html    |  2 +-
 .../planet-tag-input-dialog.component.ts      | 19 +++++++++++++++++--
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index 6896556574..50e223ccfd 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.10",
+  "version": "0.16.11",
   "myplanet": {
-    "latest": "v0.21.42",
-    "min": "v0.20.42"
+    "latest": "v0.21.43",
+    "min": "v0.20.43"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.html b/src/app/shared/forms/planet-tag-input-dialog.component.html
index eeb210d37a..b26ea2446b 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.html
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.html
@@ -68,7 +68,7 @@
       <ng-container *ngIf="subcollectionIsOpen.get(tag._id)">
         <mat-list-item *ngFor="let subTag of tag.subTags" (click)="selectOne(subTag._id || subTag.name)">
           <mat-icon>subdirectory_arrow_right</mat-icon>
-          {{subTag.name + ' (' + (subTag.count || 0) + ')'}}
+          {{ truncateTagName(subTag) }}
           <span class="toolbar-fill"></span>
           <button mat-stroked-button *ngIf="isUserAdmin" (click)="editTagClick($event,subTag)" i18n>Edit</button>
           <button mat-stroked-button *ngIf="isUserAdmin" (click)="deleteTag($event,subTag)" i18n>Delete</button>
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.ts b/src/app/shared/forms/planet-tag-input-dialog.component.ts
index fdff521c14..9b86062c86 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.ts
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject, Input } from '@angular/core';
+import { Component, Inject, Input, HostListener } from '@angular/core';
 import { FormGroup, FormBuilder } from '@angular/forms';
 import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog';
 import { TagsService } from './tags.service';
@@ -6,6 +6,7 @@ import { PlanetMessageService } from '../planet-message.service';
 import { ValidatorService } from '../../validators/validator.service';
 import { DialogsFormService } from '../dialogs/dialogs-form.service';
 import { UserService } from '../user.service';
+import { DeviceInfoService, DeviceType } from '../../shared/device-info.service';
 import { CustomValidators } from '../../validators/custom-validators';
 import { mapToArray, isInMap } from '../utils';
 import { DialogsLoadingService } from '../../shared/dialogs/dialogs-loading.service';
@@ -52,6 +53,8 @@ export class PlanetTagInputDialogComponent {
   get okClickValue() {
     return { wasOkClicked: true, indeterminate: this.indeterminate ? mapToArray(this.indeterminate, true) : [] };
   }
+  deviceType: DeviceType;
+  deviceTypes: typeof DeviceType = DeviceType;
 
   constructor(
     public dialogRef: MatDialogRef<PlanetTagInputDialogComponent>,
@@ -63,7 +66,8 @@ export class PlanetTagInputDialogComponent {
     private dialogsFormService: DialogsFormService,
     private userService: UserService,
     private dialogsLoadingService: DialogsLoadingService,
-    private dialog: MatDialog
+    private dialog: MatDialog,
+    private deviceInfoService: DeviceInfoService,
   ) {
     this.dataInit();
     // April 17, 2019: Removing selectMany toggle, but may revisit later
@@ -80,8 +84,13 @@ export class PlanetTagInputDialogComponent {
       attachedTo: [ [] ]
     });
     this.isUserAdmin = this.userService.get().isUserAdmin;
+    this.deviceType = this.deviceInfoService.getDeviceType();
   }
 
+  @HostListener('window:resize') OnResize() {
+      this.deviceType = this.deviceInfoService.getDeviceType();
+    }
+
   dataInit() {
     this.tags = this.filterTags(this.filterValue);
     this.mode = this.data.mode;
@@ -268,6 +277,12 @@ export class PlanetTagInputDialogComponent {
     return checkValue(this.selected.entries());
   }
 
+  truncateTagName(subTag: { name: string; count?: number }, maxLength: number): string {
+    if (this.deviceType === this.deviceTypes.DESKTOP) { maxLength = 50; } else { maxLength = 25; }
+    const truncatedName = subTag.name.length > maxLength ? subTag.name.slice(0, maxLength) + '...' : subTag.name;
+    return `${truncatedName} (${subTag.count || 0})`;
+  }
+
 }
 
 @Component({

From d0784fdc92f960b4984cd35be1d7b945fbb0fae7 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 18 Dec 2024 15:49:48 -0500
Subject: [PATCH 062/113] courses: smoother exam preview header (fixes #7949)
 (#7951)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                            | 2 +-
 src/app/exams/exams-view.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 50e223ccfd..0741a48c4a 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.11",
+  "version": "0.16.12",
   "myplanet": {
     "latest": "v0.21.43",
     "min": "v0.20.43"
diff --git a/src/app/exams/exams-view.component.html b/src/app/exams/exams-view.component.html
index 55aa920eae..2f63d20bcb 100644
--- a/src/app/exams/exams-view.component.html
+++ b/src/app/exams/exams-view.component.html
@@ -9,7 +9,7 @@
     <span class="ellipsis-title">{{title ? title + ': ' : ''}}</span>
     <span>
       <ng-container i18n>Question</ng-container>{{' ' + questionNum + ' '}}<ng-container i18n>of</ng-container>{{' ' + maxQuestions }}
-      <span i18n *ngIf="mode === 'grade' || mode === 'view'"> By{{' ' + submittedBy}}</span><span i18n *ngIf="!submittedBy">Unknown</span><span i18n> on {{(updatedOn | date: 'short') || '--'}}</span>
+      <span i18n *ngIf="mode === 'grade' || mode === 'view'"> by{{' ' + submittedBy}}</span><span i18n *ngIf="!submittedBy">(Preview)</span><span *ngIf="updatedOn" i18n> on {{updatedOn | date: 'short'}}</span>
     </span>
     <span class="toolbar-fill"></span>
     <button mat-icon-button [disabled]="questionNum === 1" (click)="moveQuestion(-1)" [planetSubmit]="spinnerOn"><mat-icon>navigate_before</mat-icon></button>

From 9a65a043591172f04eb61df40f80ec11373343d9 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 18 Dec 2024 16:11:04 -0500
Subject: [PATCH 063/113] all: smoother dialog prompts (fixes #7945) (#7947)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                         | 2 +-
 src/app/shared/dialogs/dialogs-prompt.component.html | 2 +-
 src/app/shared/dialogs/dialogs-prompt.component.ts   | 9 ++++++++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 0741a48c4a..579a25e4e4 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.12",
+  "version": "0.16.13",
   "myplanet": {
     "latest": "v0.21.43",
     "min": "v0.20.43"
diff --git a/src/app/shared/dialogs/dialogs-prompt.component.html b/src/app/shared/dialogs/dialogs-prompt.component.html
index 0157aec2be..3c67eab8ba 100644
--- a/src/app/shared/dialogs/dialogs-prompt.component.html
+++ b/src/app/shared/dialogs/dialogs-prompt.component.html
@@ -31,7 +31,7 @@
     }
   </p>
   <p [innerHTML]=data.extraMessage></p>
-  <b>{{data.displayName}}</b>
+  <b class = break-word>{{data.displayName | slice:0:140}}<span *ngIf="data.displayName.length > 140">...</span></b>
   <b *ngIf="data.displayDates">{{data.displayDates.startDate | date : 'mediumDate' : isDateUtc ? '+0000' : undefined }} - {{data.displayDates.endDate | date: 'mediumDate' : isDateUtc ? '+0000' : undefined }}</b>
   <ng-container *ngFor="let label of labels; last as last">
     <p><b><planet-label [label]="label.field"></planet-label>: {{label.value}}</b></p>
diff --git a/src/app/shared/dialogs/dialogs-prompt.component.ts b/src/app/shared/dialogs/dialogs-prompt.component.ts
index 2d5fb6460b..3ee85901d6 100644
--- a/src/app/shared/dialogs/dialogs-prompt.component.ts
+++ b/src/app/shared/dialogs/dialogs-prompt.component.ts
@@ -16,7 +16,14 @@ import { timer, throwError } from 'rxjs';
 import { catchError, switchMap } from 'rxjs/operators';
 
 @Component({
-  templateUrl: './dialogs-prompt.component.html'
+  templateUrl: './dialogs-prompt.component.html',
+  styles: [ `
+    .break-word {
+      word-wrap: break-word;
+      white-space: normal;
+      word-break: break-word;
+    }
+  ` ]
 })
 export class DialogsPromptComponent {
 

From 20469f7bf3dbfdc1dd295af38d0ec52405163abd Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Thu, 19 Dec 2024 15:46:51 -0500
Subject: [PATCH 064/113] teams: smoother title overflow (fixes #7964) (#7967)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                            |  6 +++---
 src/app/teams/teams-view.component.html | 12 ++++++------
 src/app/teams/teams-view.scss           |  4 ++++
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/package.json b/package.json
index 579a25e4e4..07782eaab9 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.13",
+  "version": "0.16.14",
   "myplanet": {
-    "latest": "v0.21.43",
-    "min": "v0.20.43"
+    "latest": "v0.21.45",
+    "min": "v0.20.45"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/teams/teams-view.component.html b/src/app/teams/teams-view.component.html
index 2a651303e3..4f2a7d5b8b 100644
--- a/src/app/teams/teams-view.component.html
+++ b/src/app/teams/teams-view.component.html
@@ -43,26 +43,26 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
   <ng-template #actionButtons>
     <ng-container [ngSwitch]="userStatus" *ngIf="user.isUserAdmin || user.roles.length">
       <ng-container *ngSwitchCase="'member'">
-        <button *ngIf="mode!=='services'" mat-stroked-button mat-button class="margin-lr-3" (click)="openInviteMemberDialog()" i18n [disabled]="disableAddingMembers">
+        <button *ngIf="mode!=='services'" mat-stroked-button mat-button class=" toolbar-button margin-lr-3" (click)="openInviteMemberDialog()" i18n [disabled]="disableAddingMembers">
           Add Members
         </button>
-        <button mat-raised-button color="accent" class="margin-lr-3" (click)="openResourcesDialog()" i18n>
+        <button mat-raised-button color="accent" class="toolbar-button margin-lr-3" (click)="openResourcesDialog()" i18n>
           { mode, select, team {Add Resources} enterprise {Add Documents} services {Add Documents} }
         </button>
-        <button mat-raised-button color="accent" class="margin-lr-3" (click)="openCourseDialog()" i18n>
+        <button mat-raised-button color="accent" class="toolbar-button margin-lr-3" (click)="openCourseDialog()" i18n>
           Add Courses
         </button>
         <ng-container *ngIf="!isUserLeader && mode !== 'services'">
-          <button mat-raised-button color="accent" class="margin-lr-3" (click)="openDialogPrompt(team, 'leave', { changeType: 'leave', type: 'team' })" i18n>Leave</button>
+          <button mat-raised-button color="accent" class="toolbar-button margin-lr-3" (click)="openDialogPrompt(team, 'leave', { changeType: 'leave', type: 'team' })" i18n>Leave</button>
         </ng-container>
       </ng-container>
-      <button mat-raised-button color="accent" *ngSwitchCase="'unrelated'" class="margin-lr-3" (click)="changeMembership('request')">
+      <button mat-raised-button color="accent" *ngSwitchCase="'unrelated'" class="toolbar-button margin-lr-3" (click)="changeMembership('request')">
         <ng-container *ngIf="mode!=='services'" i18n>Request to Join</ng-container>
       </button>
       <mat-chip-list *ngSwitchCase="'requesting'"><mat-chip color="accent" class="chip-no-style" selected i18n>Request pending</mat-chip></mat-chip-list>
     </ng-container>
     <ng-container *ngIf="mode!=='services'">
-      <button *planetAuthorizedRoles="''" mat-raised-button color="accent" class="margin-lr-3" (click)="openDialogPrompt(team, 'archive', { changeType: 'delete', type: 'team' })" i18n>Delete</button>
+      <button *planetAuthorizedRoles="''" mat-raised-button color="accent" class=" toolbar-button margin-lr-3" (click)="openDialogPrompt(team, 'archive', { changeType: 'delete', type: 'team' })" i18n>Delete</button>
     </ng-container>
   </ng-template>
 
diff --git a/src/app/teams/teams-view.scss b/src/app/teams/teams-view.scss
index 0603a3c8b9..91ff662210 100644
--- a/src/app/teams/teams-view.scss
+++ b/src/app/teams/teams-view.scss
@@ -32,4 +32,8 @@
     margin: 0;
   }
 
+  .toolbar-button{
+    flex-shrink: 0;
+  }
+
 }

From 186062232bdbb518b65e2ebe2946cbcddcaed7d4 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 19 Dec 2024 15:52:58 -0500
Subject: [PATCH 065/113] community: smoother calendar event deletion (fixes
 #5401) (#7960)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       | 2 +-
 src/app/meetups/meetups.service.ts | 6 +++++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 07782eaab9..c2b460adae 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.14",
+  "version": "0.16.15",
   "myplanet": {
     "latest": "v0.21.45",
     "min": "v0.20.45"
diff --git a/src/app/meetups/meetups.service.ts b/src/app/meetups/meetups.service.ts
index d71c0333ab..c7fa5773ee 100644
--- a/src/app/meetups/meetups.service.ts
+++ b/src/app/meetups/meetups.service.ts
@@ -96,13 +96,17 @@ export class MeetupService {
   openDeleteDialog(meetups: any[] | any, callback) {
     const isMany = meetups.length > 1;
     const displayName = isMany ? '' : (meetups[0] || meetups).title;
+    const recurringInfo = (meetups[0] || meetups).recurring && (meetups[0] || meetups).recurring !== 'none' && (meetups[0] || meetups).recurringNumber
+      ? `(Recurs ${ (meetups[0] || meetups).recurring} for ${ (meetups[0] || meetups).recurringNumber } ${ (meetups[0] || meetups).recurring === 'daily' ? 'days' : 'weeks' })`
+      : '';
     this.deleteDialog = this.dialog.open(DialogsPromptComponent, {
       data: {
         okClick: this.deleteMeetups([ meetups ].flat(), displayName, callback),
         changeType: 'delete',
         type: 'event',
         amount: isMany ? 'many' : 'single',
-        displayName
+        displayName,
+        extraMessage: recurringInfo
       }
     });
   }

From ad4790af4162dd1f044ab916d675855203685575 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Thu, 19 Dec 2024 16:00:50 -0500
Subject: [PATCH 066/113] resources: smoother collections scrolling (fixes
 #6280) (#7943)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                              | 2 +-
 src/app/shared/forms/planet-tag-input-dialog.component.ts | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c2b460adae..9687570aa6 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.15",
+  "version": "0.16.16",
   "myplanet": {
     "latest": "v0.21.45",
     "min": "v0.20.45"
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.ts b/src/app/shared/forms/planet-tag-input-dialog.component.ts
index 9b86062c86..8c549c019e 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.ts
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.ts
@@ -15,6 +15,14 @@ import { DialogsPromptComponent } from '../../shared/dialogs/dialogs-prompt.comp
 @Component({
   'templateUrl': 'planet-tag-input-dialog.component.html',
   'styles': [ `
+    :host {
+      display: block;
+      overflow: hidden;
+    }
+    :host mat-dialog-content {
+      overflow-y: auto;
+      max-height: calc(100vh - 100px); 
+    }
     :host .mat-list-option span {
       font-weight: inherit;
     }

From 5dbc0bd327f43f2d110c78021c3e378a0a86d83a Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 19 Dec 2024 16:05:07 -0500
Subject: [PATCH 067/113] resources: smoother snackbar (fixes #7954)(fixes
 #7955) (#7956)

Co-authored-by: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                           | 2 +-
 src/app/courses/courses.service.ts     | 3 ++-
 src/app/resources/resources.service.ts | 7 ++++++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 9687570aa6..139d7817c6 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.16",
+  "version": "0.16.17",
   "myplanet": {
     "latest": "v0.21.45",
     "min": "v0.20.45"
diff --git a/src/app/courses/courses.service.ts b/src/app/courses/courses.service.ts
index 78866f6d07..2c69e183be 100644
--- a/src/app/courses/courses.service.ts
+++ b/src/app/courses/courses.service.ts
@@ -227,7 +227,8 @@ export class CoursesService {
   courseAdmissionMany(courseIds, type) {
     return this.userService.changeShelf(courseIds, 'courseIds', type).pipe(map(({ shelf, countChanged }) => {
       const prefix = countChanged > 1 ? $localize`${countChanged} courses` : this.getCourseNameFromId(courseIds[courseIds.length - 1]);
-      const message = type === 'remove' ? $localize`${prefix} successfully removed from myCourses` : $localize`${prefix} added to your dashboard`;
+      const message = type === 'remove' ? $localize`${prefix} successfully removed from myCourses` :
+        $localize`${prefix} added to myCourses`;
       this.planetMessageService.showMessage(message);
       return shelf;
     }));
diff --git a/src/app/resources/resources.service.ts b/src/app/resources/resources.service.ts
index ea00aa17de..aac7f085eb 100644
--- a/src/app/resources/resources.service.ts
+++ b/src/app/resources/resources.service.ts
@@ -90,8 +90,13 @@ export class ResourcesService {
 
   libraryAddRemove(resourceIds, type) {
     return this.userService.changeShelf(resourceIds, 'resourceIds', type).pipe(map(({ shelf, countChanged }) => {
+      const resource = this.resources.local.find(r => r._id === resourceIds[0]);
+      const resourceTitle = resource ? resource.doc.title : '';
       const message = type === 'remove' ?
-        countChanged + $localize` Resources successfully removed from myLibrary` : countChanged + $localize` Resources added to your dashboard`;
+        (countChanged === 1 ? $localize`${resourceTitle} successfully removed from myLibrary` :
+          `${countChanged} ${$localize`Resources`} successfully removed from myLibrary`) :
+        (countChanged === 1 ? $localize`${resourceTitle} added to myLibrary` :
+          `${countChanged} ${$localize`Resources`} added to myLibrary`);
       this.planetMessageService.showMessage(message);
       return shelf;
     }));

From e92959c964be3b7797284552d5bd11f118f05eb0 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:15:13 -0500
Subject: [PATCH 068/113] chat: smoother placeholder text (#7973) (#7974)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                          | 6 +++---
 src/app/chat/chat-sidebar/chat-sidebar.component.html | 2 +-
 src/app/chat/chat-sidebar/chat-sidebar.scss           | 4 ++++
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 139d7817c6..d2b03ae947 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.17",
+  "version": "0.16.18",
   "myplanet": {
-    "latest": "v0.21.45",
-    "min": "v0.20.45"
+    "latest": "v0.21.51",
+    "min": "v0.20.51"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.component.html b/src/app/chat/chat-sidebar/chat-sidebar.component.html
index 14625e5cee..10bd193118 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.component.html
+++ b/src/app/chat/chat-sidebar/chat-sidebar.component.html
@@ -69,7 +69,7 @@
       </ul>
     </ng-container>
     <ng-template #noChats>
-      <div i18n>No previous conversations.</div>
+      <div class="no-chats-message" i18n>No previous conversations.</div>
     </ng-template>
   </mat-drawer>
 
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.scss b/src/app/chat/chat-sidebar/chat-sidebar.scss
index e974ca4f80..4ef09f2260 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.scss
+++ b/src/app/chat/chat-sidebar/chat-sidebar.scss
@@ -77,6 +77,10 @@ li:hover {
   margin: 0;
 }
 
+.no-chats-message {
+  margin-left: 4px;
+}
+
 @media only screen and (max-width: $screen-md) {
   .expand-button {
     top: 10px;

From 3698db5ecc3f09252ce58ef48f5ede92a6aba300 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:21:30 -0500
Subject: [PATCH 069/113] teams: smoother resources titles (fixes #7978)
 (#7981)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                  | 2 +-
 src/app/teams/teams-view.scss | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index d2b03ae947..f6a5235790 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.18",
+  "version": "0.16.19",
   "myplanet": {
     "latest": "v0.21.51",
     "min": "v0.20.51"
diff --git a/src/app/teams/teams-view.scss b/src/app/teams/teams-view.scss
index 91ff662210..a5b4639e48 100644
--- a/src/app/teams/teams-view.scss
+++ b/src/app/teams/teams-view.scss
@@ -32,6 +32,14 @@
     margin: 0;
   }
 
+  .mat-subheading-2 b {
+    display: inline-block;
+    max-width: 100%;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
   .toolbar-button{
     flex-shrink: 0;
   }

From 97fc1bbb2ff60aa92a6df6778ff8d02b980fd7b6 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 20 Dec 2024 16:43:10 -0500
Subject: [PATCH 070/113] all: smoother navigation tooltips (fixes #7979)
 (#7984)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     | 2 +-
 src/app/home/home.component.html | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index f6a5235790..3620c97dce 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.19",
+  "version": "0.16.20",
   "myplanet": {
     "latest": "v0.21.51",
     "min": "v0.20.51"
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index 8e1f338f34..6296f3e295 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -44,8 +44,8 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
     </ng-container>
     <span *ngIf="layout === 'classic' && !forceModern">
       <button mat-icon-button routerLink="/chat" i18n-title title="Chat"><mat-icon>chat_bubble_outline</mat-icon></button>
-      <button mat-icon-button planetFeedback i18n-title title="Feedback"><mat-icon>feedback_outline</mat-icon></button>
-      <button mat-icon-button routerLink="/feedback" i18n-title title="Messages"><mat-icon>mail_outline</mat-icon></button>
+      <button mat-icon-button planetFeedback i18n-title title="Submit Feedback"><mat-icon>feedback_outline</mat-icon></button>
+      <button mat-icon-button routerLink="/feedback" i18n-title title="Review Feedback"><mat-icon>mail_outline</mat-icon></button>
       <ng-container *planetAuthorizedRoles>
         <button mat-icon-button planetSync i18n-title title="Sync" *ngIf="onlineStatus === 'accepted'"><mat-icon svgIcon="feedback"></mat-icon></button>
       </ng-container>

From c52e42d538384cb618870ac475f3546ddfef5f4c Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 23 Dec 2024 16:23:03 -0500
Subject: [PATCH 071/113] resources: smoother collections labels (fixes #7983)
 (#7988)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     | 6 +++---
 src/app/courses/courses.scss     | 8 ++++++++
 src/app/resources/resources.scss | 8 ++++++++
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 3620c97dce..b0371a0bb6 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.20",
+  "version": "0.16.21",
   "myplanet": {
-    "latest": "v0.21.51",
-    "min": "v0.20.51"
+    "latest": "v0.21.55",
+    "min": "v0.20.55"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/courses/courses.scss b/src/app/courses/courses.scss
index efe18f5943..e13f0980d8 100644
--- a/src/app/courses/courses.scss
+++ b/src/app/courses/courses.scss
@@ -59,6 +59,14 @@ $label-height: 1rem;
   word-break: break-word;
 }
 
+.tags-list mat-chip {
+  max-width: 200px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  display: inline-block;
+}
+
 @media(max-width: $screen-md) {
   .mat-column-info {
     max-width: 120px;
diff --git a/src/app/resources/resources.scss b/src/app/resources/resources.scss
index b73f711a42..1de20c3419 100644
--- a/src/app/resources/resources.scss
+++ b/src/app/resources/resources.scss
@@ -56,6 +56,14 @@ $label-height: 1rem;
   justify-content: center;
 }
 
+.tags-list mat-chip {
+  max-width: 200px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  display: inline-block;
+}
+
 @media(max-width: $screen-md) {
   .resources-list {
     .mat-column-createdDate {

From a8297efcfb19c70baaa858711ea9334baf6f1f9d Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Fri, 27 Dec 2024 13:10:35 -0500
Subject: [PATCH 072/113] resources: smoother create (fixes #7798) (#7801)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                   | 2 +-
 src/app/resources/resources-add.component.html | 2 +-
 src/app/resources/resources-add.scss           | 6 ++++++
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index b0371a0bb6..8e33f77734 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.21",
+  "version": "0.16.22",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/resources/resources-add.component.html b/src/app/resources/resources-add.component.html
index 3ac3c770a9..f5978236eb 100644
--- a/src/app/resources/resources-add.component.html
+++ b/src/app/resources/resources-add.component.html
@@ -86,7 +86,7 @@
           </mat-autocomplete>
           <mat-error><planet-form-error-messages [control]="resourceForm.controls.openWhichFile"></planet-form-error-messages></mat-error>
         </mat-form-field>
-        <div class="inner-gaps by-column full-width">
+        <div class="file-upload inner-gaps by-column full-width">
           <label i18n>File Upload:</label>
           <planet-file-input (fileChange)="bindFile($event)"></planet-file-input>
           <label i18n class="warn-text-color" *ngIf="resourceForm?.errors?.fileTooBig">File size cannot exceed more than 512 MB</label>
diff --git a/src/app/resources/resources-add.scss b/src/app/resources/resources-add.scss
index 4f4a5cb9ac..b93107fbbd 100644
--- a/src/app/resources/resources-add.scss
+++ b/src/app/resources/resources-add.scss
@@ -22,5 +22,11 @@
     .form-container {
       width: auto;
     }
+
+    .file-upload {
+      display: flex;
+      flex-direction: column;
+    }
+
   }
 }

From f0368b87f2fbc724d6dcb90b852bfd2691442296 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Fri, 27 Dec 2024 13:21:00 -0500
Subject: [PATCH 073/113] teams: smoother tasks deadlines (fixes #5377) (#7842)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       |  2 +-
 src/app/tasks/tasks.component.html |  3 ++-
 src/app/tasks/tasks.component.ts   | 20 ++++++++++++++++++++
 src/app/tasks/tasks.scss           |  8 ++++++++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 8e33f77734..67bedc05bf 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.22",
+  "version": "0.16.23",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/tasks/tasks.component.html b/src/app/tasks/tasks.component.html
index 73ad09a824..16522e4336 100644
--- a/src/app/tasks/tasks.component.html
+++ b/src/app/tasks/tasks.component.html
@@ -15,7 +15,8 @@
   <button mat-list-item *ngFor="let task of filteredTasks; trackBy: trackById" (click)="openTaskDetail(task)" [disabled]="!editable">
     <mat-checkbox [checked]="task.completed" [disabled]="!editable" (change)="toggleTaskComplete(task)" (click)="$event.stopPropagation()"></mat-checkbox>
     <p matLine>{{task.title}}</p>
-    <p matLine><ng-container i18n>Deadline:</ng-container> {{task.deadline | date}} {{task.deadline | date: 'shortTime'}}</p>
+    <p matLine [ngClass]="{'deadline-soon': isTaskDueSoon(task),
+    'deadline-passed': isTaskOverdue(task)}"><ng-container i18n>Deadline:</ng-container> {{task.deadline | date}} {{task.deadline | date: 'shortTime'}}</p>
     <p matLine *ngIf="task.completed"><ng-container i18n>Completed:</ng-container> {{task.completedTime | date}} {{task.completedTime | date: 'shortTime'}}</p>
     <img (click)="openMemberDialog(task.assignee); $event.stopPropagation()" matTooltip="{{task.assignee | assigneeName}}" *ngIf="task.assignee" matListAvatar [src]="
       task.assignee.attachmentDoc ?
diff --git a/src/app/tasks/tasks.component.ts b/src/app/tasks/tasks.component.ts
index 9c7b7f64c7..2e22cd2544 100644
--- a/src/app/tasks/tasks.component.ts
+++ b/src/app/tasks/tasks.component.ts
@@ -72,6 +72,26 @@ export class TasksComponent implements OnInit {
     });
   }
 
+  isTaskDueSoon(task): boolean {
+    if (!task || task.completed || !task.deadline) return false;
+  
+    const now = new Date();
+    const deadline = new Date(task.deadline);
+    const twentyFourHoursFromNow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
+  
+    const isWithinNextDay = deadline <= twentyFourHoursFromNow && deadline > now;
+  
+    return isWithinNextDay;
+  }
+
+  isTaskOverdue(task): boolean {
+    if (task.completed || !task.deadline) return false;
+    
+    const now = new Date();
+    const deadline = new Date(task.deadline);
+    return deadline < now;
+  }
+
   openAddDialog(additionalFields, task: any = {}, onSuccess = (res) => {}) {
     const { fields, formGroup } = this.tasksService.addDialogForm(task);
     this.dialogsFormService.openDialogsForm(task.title ? $localize`Edit Task` : $localize`Add Task`, fields, formGroup, {
diff --git a/src/app/tasks/tasks.scss b/src/app/tasks/tasks.scss
index 65c5ece91c..14e3ba9115 100644
--- a/src/app/tasks/tasks.scss
+++ b/src/app/tasks/tasks.scss
@@ -19,6 +19,14 @@ planet-tasks {
     }
   }
 
+  .deadline-soon{
+    color: #F6BE00
+  }
+
+  .deadline-passed{
+    color: red
+  }
+
   mat-button-toggle-group {
     font-size: 14px;
 

From fe5d6d0cc55dcc3b8c559b0f6400ecb7d3dc96d2 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Fri, 27 Dec 2024 13:25:32 -0500
Subject: [PATCH 074/113] mylife: smoother achievements certifications (fixes
 #7975) (#7995)

Co-authored-by: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                           |  2 +-
 .../users-achievements.component.html                  |  2 +-
 .../users/users-achievements/users-achievements.scss   | 10 ++++++----
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index 67bedc05bf..81dd2eb708 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.23",
+  "version": "0.16.24",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/users/users-achievements/users-achievements.component.html b/src/app/users/users-achievements/users-achievements.component.html
index 4f2f70d554..55b80d2471 100644
--- a/src/app/users/users-achievements/users-achievements.component.html
+++ b/src/app/users/users-achievements/users-achievements.component.html
@@ -47,7 +47,7 @@ <h3 i18n>My Goals</h3>
           <h3 i18n>My Certifications</h3>
           <mat-list class="certs-list">
             <mat-list-item *ngFor="let certification of certifications">
-              {{certification.name}}
+              <span class="cert-item">{{certification.name}}</span>
             </mat-list-item>
           </mat-list>
         </div>
diff --git a/src/app/users/users-achievements/users-achievements.scss b/src/app/users/users-achievements/users-achievements.scss
index c280f57f51..782c8baf52 100644
--- a/src/app/users/users-achievements/users-achievements.scss
+++ b/src/app/users/users-achievements/users-achievements.scss
@@ -10,10 +10,12 @@
     text-align: center;
   }
 
-  .certs-list .mat-list-item{
-    display: flex;
-    justify-content: center;
-    text-align: center;
+  .certs-list {
+    .cert-item {
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+    }
   }
 
   & mat-list, & ul, & ol {

From 017ca20e07de624e8f147d2402d328157cdd3ef4 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Fri, 27 Dec 2024 13:32:43 -0500
Subject: [PATCH 075/113] mylife: smoother achievements spacing (fixes #7996)
 (#7997)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                        |  2 +-
 src/app/meetups/meetups.service.ts                  | 13 ++++++++++---
 .../forms/planet-tag-input-dialog.component.ts      |  2 +-
 .../users-achievements.component.html               |  2 +-
 .../users-achievements/users-achievements.scss      |  5 +++++
 5 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index 81dd2eb708..2b601c30ff 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.24",
+  "version": "0.16.25",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/meetups/meetups.service.ts b/src/app/meetups/meetups.service.ts
index c7fa5773ee..d1f1f37820 100644
--- a/src/app/meetups/meetups.service.ts
+++ b/src/app/meetups/meetups.service.ts
@@ -96,9 +96,16 @@ export class MeetupService {
   openDeleteDialog(meetups: any[] | any, callback) {
     const isMany = meetups.length > 1;
     const displayName = isMany ? '' : (meetups[0] || meetups).title;
-    const recurringInfo = (meetups[0] || meetups).recurring && (meetups[0] || meetups).recurring !== 'none' && (meetups[0] || meetups).recurringNumber
-      ? `(Recurs ${ (meetups[0] || meetups).recurring} for ${ (meetups[0] || meetups).recurringNumber } ${ (meetups[0] || meetups).recurring === 'daily' ? 'days' : 'weeks' })`
-      : '';
+    const recurringInfo =
+      (meetups[0] || meetups).recurring &&
+      (meetups[0] || meetups).recurring !== 'none' &&
+      (meetups[0] || meetups).recurringNumber
+        ? `(Recurs ${(meetups[0] || meetups).recurring} for ${
+            (meetups[0] || meetups).recurringNumber
+          } ${
+            (meetups[0] || meetups).recurring === 'daily' ? 'days' : 'weeks'
+          })`
+        : '';
     this.deleteDialog = this.dialog.open(DialogsPromptComponent, {
       data: {
         okClick: this.deleteMeetups([ meetups ].flat(), displayName, callback),
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.ts b/src/app/shared/forms/planet-tag-input-dialog.component.ts
index 8c549c019e..1e26049b29 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.ts
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.ts
@@ -21,7 +21,7 @@ import { DialogsPromptComponent } from '../../shared/dialogs/dialogs-prompt.comp
     }
     :host mat-dialog-content {
       overflow-y: auto;
-      max-height: calc(100vh - 100px); 
+      max-height: calc(100vh - 100px);
     }
     :host .mat-list-option span {
       font-weight: inherit;
diff --git a/src/app/users/users-achievements/users-achievements.component.html b/src/app/users/users-achievements/users-achievements.component.html
index 55b80d2471..d6d29168eb 100644
--- a/src/app/users/users-achievements/users-achievements.component.html
+++ b/src/app/users/users-achievements/users-achievements.component.html
@@ -57,7 +57,7 @@ <h3 i18n>My Certifications</h3>
         <h3 i18n>My Links</h3>
         <mat-list>
           <mat-list-item class="mat-list-item-word-wrap" *ngFor="let link of achievements.links">
-            <h4 mat-line>{{link.title}}:</h4>
+            <h4 class="link-title" mat-line>{{link.title}}:</h4>
             <a href="{{link.url}}" target="_blank" class="styled-link"> {{link.url}} </a>
           </mat-list-item>
         </mat-list>
diff --git a/src/app/users/users-achievements/users-achievements.scss b/src/app/users/users-achievements/users-achievements.scss
index 782c8baf52..27a8894a54 100644
--- a/src/app/users/users-achievements/users-achievements.scss
+++ b/src/app/users/users-achievements/users-achievements.scss
@@ -78,6 +78,7 @@
         grid-area: txt;
         display: flex;
         align-items: center;
+        max-width: 75%;
       }
 
       .achievement-date {
@@ -94,6 +95,10 @@
     }
   }
 
+  .link-title {
+    max-width: 75%;
+  }
+
   .styled-link {
     color: #007bff;
     text-decoration: none;

From d62c5aace38bcba7a432ff268d555eb6f9412d4d Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 30 Dec 2024 14:15:12 -0500
Subject: [PATCH 076/113] dashboard: smoother icon colors (fixes #7993) (#7999)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                          | 2 +-
 src/app/dashboard/dashboard-tile.scss | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 2b601c30ff..9557fb14cf 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.25",
+  "version": "0.16.26",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/dashboard/dashboard-tile.scss b/src/app/dashboard/dashboard-tile.scss
index 63e24d4bdb..ca1765f696 100644
--- a/src/app/dashboard/dashboard-tile.scss
+++ b/src/app/dashboard/dashboard-tile.scss
@@ -25,7 +25,7 @@
         flex-wrap: wrap;
         font-size: 1.25rem;
       }
-
+      color: #fff;
     }
 
     .right-tile {

From ecda72027aecc5c59ecc709b1a00fc2ced52008b Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 30 Dec 2024 14:18:58 -0500
Subject: [PATCH 077/113] chat: smoother full search (fixes #8004) (#8009)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                         |  2 +-
 .../chat/chat-sidebar/chat-sidebar.component.html    |  2 +-
 src/app/chat/chat-sidebar/chat-sidebar.scss          |  4 ++++
 src/app/tasks/tasks.component.ts                     | 12 ++++++------
 4 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index 9557fb14cf..bf145e9684 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.26",
+  "version": "0.16.27",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.component.html b/src/app/chat/chat-sidebar/chat-sidebar.component.html
index 10bd193118..e95768a217 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.component.html
+++ b/src/app/chat/chat-sidebar/chat-sidebar.component.html
@@ -13,8 +13,8 @@
       <button mat-icon-button color="primary" (click)="resetFilter()" [disabled]="!titleSearch && !searchType" matTooltip="Clear search" i18n-matTooltip [matTooltipDisabled]="!titleSearch && !searchType">
         <mat-icon>delete</mat-icon>
       </button><br>
-      <span style="font-size: small; font-style: italic;" i18n>Full Conversation Search </span>
       <mat-checkbox [checked]="fullTextSearch" (change)="toggleSearchType()"></mat-checkbox>
+      <span style="font-size: small; font-style: italic;" i18n>Full Conversation Search </span>
       <button style="text-align: end;" mat-icon-button (mouseenter)="toggleOverlay()" (mouseleave)="toggleOverlay()" cdkOverlayOrigin #trigger="cdkOverlayOrigin">
         <mat-icon>help_outline</mat-icon>
       </button>
diff --git a/src/app/chat/chat-sidebar/chat-sidebar.scss b/src/app/chat/chat-sidebar/chat-sidebar.scss
index 4ef09f2260..f76ee91517 100644
--- a/src/app/chat/chat-sidebar/chat-sidebar.scss
+++ b/src/app/chat/chat-sidebar/chat-sidebar.scss
@@ -81,6 +81,10 @@ li:hover {
   margin-left: 4px;
 }
 
+.mat-checkbox {
+  margin-right: 4px;
+}
+
 @media only screen and (max-width: $screen-md) {
   .expand-button {
     top: 10px;
diff --git a/src/app/tasks/tasks.component.ts b/src/app/tasks/tasks.component.ts
index 2e22cd2544..111d2bff72 100644
--- a/src/app/tasks/tasks.component.ts
+++ b/src/app/tasks/tasks.component.ts
@@ -73,20 +73,20 @@ export class TasksComponent implements OnInit {
   }
 
   isTaskDueSoon(task): boolean {
-    if (!task || task.completed || !task.deadline) return false;
-  
+    if (!task || task.completed || !task.deadline) { return false; }
+
     const now = new Date();
     const deadline = new Date(task.deadline);
     const twentyFourHoursFromNow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
-  
+
     const isWithinNextDay = deadline <= twentyFourHoursFromNow && deadline > now;
-  
+
     return isWithinNextDay;
   }
 
   isTaskOverdue(task): boolean {
-    if (task.completed || !task.deadline) return false;
-    
+    if (task.completed || !task.deadline) { return false; }
+
     const now = new Date();
     const deadline = new Date(task.deadline);
     return deadline < now;

From 653ff59f18808262ddb3601a201ddd6a3f8b0d45 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 30 Dec 2024 14:23:15 -0500
Subject: [PATCH 078/113] mylife: smoother myhealth toolbar (fixes #8008)
 (#8010)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                         | 2 +-
 src/app/health/health.component.html | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index bf145e9684..e2f415cd88 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.27",
+  "version": "0.16.28",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/health/health.component.html b/src/app/health/health.component.html
index cc68e701dd..b1591cf81e 100644
--- a/src/app/health/health.component.html
+++ b/src/app/health/health.component.html
@@ -6,6 +6,7 @@
 
 <div class="space-container">
   <mat-toolbar class="primary-color font-size-1 action-buttons">
+    <span class="toolbar-fill"></span>
     <a mat-raised-button color="accent" i18n [routerLink]="['update']" *ngIf="isOwnUser">Update Details</a>
     <a mat-raised-button color="accent" i18n [routerLink]="['event', { id: userDetail._id }]">Add Examination</a>
     <span *ngIf="userDetail.firstName === undefined"><ng-container i18n>Member login:</ng-container> {{userDetail.name}}</span>

From 783cd87d7a7c05ee578dff36f6f17d2253abed45 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 30 Dec 2024 14:26:37 -0500
Subject: [PATCH 079/113] mylife: smoother myhealth countdown (fixes #8007)
 (#8011)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                      | 2 +-
 src/app/health/health-event-dialog.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index e2f415cd88..f350927b22 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.28",
+  "version": "0.16.29",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/health/health-event-dialog.component.html b/src/app/health/health-event-dialog.component.html
index 8b594d91f9..5879b833db 100644
--- a/src/app/health/health-event-dialog.component.html
+++ b/src/app/health/health-event-dialog.component.html
@@ -27,6 +27,6 @@ <h4 class="primary-text-color" *ngIf="hasConditionAndTreatment" i18n>Other Notes
 <mat-dialog-actions>
   <button type="button" mat-raised-button mat-dialog-close i18n>Close</button>
   <button type="button" color="primary" mat-dialog-close (click)="editExam(event)" *ngIf="canUpdate" mat-raised-button>
-    <span i18n>Edit</span> <ng-container *ngIf="minutes">({{ minutes }}:{{ seconds }})</ng-container>
+    <span i18n>Edit <ng-container *ngIf="minutes">({{ minutes }}:{{ seconds }})</ng-container></span> 
   </button>
 </mat-dialog-actions>

From bb694afee9648045049d1e0653bb4a5e28c15e6d Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 30 Dec 2024 14:31:33 -0500
Subject: [PATCH 080/113] community: smoother leaders tiles (fixes #8005)
 (#8015)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     | 2 +-
 src/app/community/community.scss | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index f350927b22..368c5ece47 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.29",
+  "version": "0.16.30",
   "myplanet": {
     "latest": "v0.21.55",
     "min": "v0.20.55"
diff --git a/src/app/community/community.scss b/src/app/community/community.scss
index 3d8e70b249..5f6aa4a2ff 100644
--- a/src/app/community/community.scss
+++ b/src/app/community/community.scss
@@ -66,6 +66,7 @@ planet-calendar {
     top: -0.25rem;
     right: -0.25rem;
   }
+  word-break: break-word;
 }
 
 mat-tab-group, mat-tab {

From d0302de4744c8f982c1aa285653b10e49ba334dd Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 2 Jan 2025 14:44:53 -0500
Subject: [PATCH 081/113] manager: smoother myplanet pin (fixes #7920) (#8023)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                               | 6 +++---
 src/app/manager-dashboard/manager-dashboard.component.html | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index 368c5ece47..6b4c903c21 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.30",
+  "version": "0.16.31",
   "myplanet": {
-    "latest": "v0.21.55",
-    "min": "v0.20.55"
+    "latest": "v0.21.58",
+    "min": "v0.20.58"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/manager-dashboard/manager-dashboard.component.html b/src/app/manager-dashboard/manager-dashboard.component.html
index 85d2f7bb5b..0103f5a15b 100644
--- a/src/app/manager-dashboard/manager-dashboard.component.html
+++ b/src/app/manager-dashboard/manager-dashboard.component.html
@@ -75,7 +75,7 @@ <h3 i18n *ngIf="showParentList">{{ planetType === 'community' ? 'Nation' : 'Cent
         <p *ngSwitchDefault i18n><b>Your request has not yet been accepted by { planetType, select, community {nation} nation {center}}</b></p>
       </ng-container>
     </div>
-    <div *ngIf="pin"><span i18n>Your tablet pin number is:</span> <b class="pinClass">{{ ' ' + pin + ' ' }}</b>
+    <div *ngIf="pin"><span i18n>myPlanet Server pin:</span> <b class="pinClass">{{ ' ' + pin + ' ' }}</b>
       <button mat-raised-button i18n (click)="resetPin()">Reset Pin</button>
     </div>
   </ng-container>

From 8c546a9e4bce148b2101b6358edff9294b07ed76 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Thu, 2 Jan 2025 22:50:33 +0300
Subject: [PATCH 082/113] all: smoother december challenge (fixes #8024)
 (#8026)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                               | 2 +-
 src/app/shared/dialogs/dialogs-announcement.component.scss | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 6b4c903c21..5f747c5ecf 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.31",
+  "version": "0.16.32",
   "myplanet": {
     "latest": "v0.21.58",
     "min": "v0.20.58"
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.scss b/src/app/shared/dialogs/dialogs-announcement.component.scss
index f3d53594ca..fd1a6d80aa 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.scss
+++ b/src/app/shared/dialogs/dialogs-announcement.component.scss
@@ -55,8 +55,9 @@
   background-color: $primary;
   transition: width 0.5s;
   display: flex;
-  justify-content: center;
   align-items: center;
+  white-space: nowrap;
+  padding: 0 10px;
 }
 
 .thermometer-label {

From 30bf903a64ec3ed0653eb80d103dc1123e731e8e Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 2 Jan 2025 14:56:37 -0500
Subject: [PATCH 083/113] teams: smoother voices deletion (fixes #8016)(fixes
 #8017) (#8019)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                         | 2 +-
 src/app/news/news-list.component.ts                  | 5 +++--
 src/app/news/news.service.ts                         | 6 +++---
 src/app/shared/dialogs/dialogs-prompt.component.html | 1 +
 4 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index 5f747c5ecf..a8122962bd 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.32",
+  "version": "0.16.33",
   "myplanet": {
     "latest": "v0.21.58",
     "min": "v0.20.58"
diff --git a/src/app/news/news-list.component.ts b/src/app/news/news-list.component.ts
index 61d3ea892a..fb0b0cf5bd 100644
--- a/src/app/news/news-list.component.ts
+++ b/src/app/news/news-list.component.ts
@@ -115,7 +115,8 @@ export class NewsListComponent implements OnChanges {
       data: {
         okClick: this.deleteNews(news),
         changeType: 'delete',
-        type: 'news'
+        type: 'news',
+        displayName: news.message
       }
     });
   }
@@ -134,7 +135,7 @@ export class NewsListComponent implements OnChanges {
         this.deleteDialog.close();
       },
       onError: (error) => {
-        this.planetMessageService.showAlert($localize`There was a problem deleting this news.`);
+        this.planetMessageService.showAlert($localize`There was a problem deleting this message.`);
       }
     };
   }
diff --git a/src/app/news/news.service.ts b/src/app/news/news.service.ts
index 32bfcab631..de318dab2c 100644
--- a/src/app/news/news.service.ts
+++ b/src/app/news/news.service.ts
@@ -54,7 +54,7 @@ export class NewsService {
     return ((item.viewIn || []).find(view => view._id === viewId) || {}).sharedDate;
   }
 
-  postNews(post, successMessage = $localize`Thank you for submitting your news`, isMessageEdit = true) {
+  postNews(post, successMessage = $localize`Thank you for submitting your message`, isMessageEdit = true) {
     const { configuration } = this.stateService;
     const message = typeof post.message === 'string' ? post.message : post.message.text;
     const images = this.createImagesArray(post, message);
@@ -76,7 +76,7 @@ export class NewsService {
   }
 
   deleteNews(post) {
-    return this.postNews({ ...post, _deleted: true }, $localize`Post deleted`);
+    return this.postNews({ ...post, _deleted: true }, $localize`Message deleted`);
   }
 
   createImagesArray(post, message) {
@@ -90,7 +90,7 @@ export class NewsService {
     return this.couchService.bulkDocs(this.dbName, replies.map(reply => ({ ...reply.doc, replyTo: newReplyToId })));
   }
 
-  shareNews(news, planets?: any[], successMessage = $localize`News has been successfully shared`) {
+  shareNews(news, planets?: any[], successMessage = $localize`Message has been successfully shared`) {
     const viewInObject = (planet) => (
       { '_id': `${planet.code}@${planet.parentCode}`, section: 'community', sharedDate: this.couchService.datePlaceholder }
     );
diff --git a/src/app/shared/dialogs/dialogs-prompt.component.html b/src/app/shared/dialogs/dialogs-prompt.component.html
index 3c67eab8ba..456c4b973f 100644
--- a/src/app/shared/dialogs/dialogs-prompt.component.html
+++ b/src/app/shared/dialogs/dialogs-prompt.component.html
@@ -17,6 +17,7 @@
         event {event}
         transaction {transaction}
         link {link}
+        news {message}
         report {report}}?
       }
       many

From dfd9e5da88c006dfacb4a10d3d1fa021535c54ee Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 3 Jan 2025 15:18:50 -0500
Subject: [PATCH 084/113] manager: smoother members buttons (fixes #8003)
 (#8018)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                             |  6 +++---
 src/app/users/users-table.component.html |  4 ++--
 src/app/users/users-table.scss           | 14 +++++++++++---
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index a8122962bd..dcb3d2269a 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.33",
+  "version": "0.16.34",
   "myplanet": {
-    "latest": "v0.21.58",
-    "min": "v0.20.58"
+    "latest": "v0.21.62",
+    "min": "v0.20.62"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/users/users-table.component.html b/src/app/users/users-table.component.html
index 613bf4c617..f49f5f43bd 100644
--- a/src/app/users/users-table.component.html
+++ b/src/app/users/users-table.component.html
@@ -127,10 +127,10 @@
               <label *ngIf="!isMobile"> Demote </label>
             </button>
           </span>
-          <a class="visibility-cell" (click)="gotoProfileView(element.doc.name)" mat-raised-button color="primary" i18n>
+          <button (click)="gotoProfileView(element.doc.name)" mat-raised-button color="primary" i18n>
             <mat-icon>visibility</mat-icon>
             <label *ngIf="!isMobile"> View Profile </label>
-          </a>
+          </button>
         </div>
       </mat-cell>
     </ng-container>
diff --git a/src/app/users/users-table.scss b/src/app/users/users-table.scss
index dc3458c0cd..68bc3af1fb 100644
--- a/src/app/users/users-table.scss
+++ b/src/app/users/users-table.scss
@@ -23,6 +23,15 @@ button-container {
   justify-content: center;
 }
 
+.mat-cell button, .mat-cell div button[mat-raised-button] {
+  width: 150px;
+  text-align: center;
+  padding: 8px 12px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
 @media(max-width: $screen-md) {
   .mat-column-visitCount, .mat-column-joinDate, .mat-column-lastLogin {
     max-width: 70px;
@@ -30,8 +39,7 @@ button-container {
 }
 
 @media (max-width: $screen-sm) {
-  mat-cell button, .visibility-cell {
-    min-width: 0;
-    padding: 0 3px;
+  .mat-cell button, .mat-cell div button[mat-raised-button] {
+    width: 50px;
   }
 }

From c0c6167075478d321f4be56113284b4c463fed47 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Fri, 3 Jan 2025 15:35:56 -0500
Subject: [PATCH 085/113] resources: smoother list titles (fixes #8030) (#8031)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     |  2 +-
 src/app/resources/resources.scss | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index dcb3d2269a..c64a0b38d6 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.34",
+  "version": "0.16.35",
   "myplanet": {
     "latest": "v0.21.62",
     "min": "v0.20.62"
diff --git a/src/app/resources/resources.scss b/src/app/resources/resources.scss
index 1de20c3419..5e803920cf 100644
--- a/src/app/resources/resources.scss
+++ b/src/app/resources/resources.scss
@@ -44,6 +44,19 @@ $label-height: 1rem;
   }
 }
 
+.list-content-menu {
+  &.list-content-menu-auto {
+    .header {
+      word-break: break-word;
+      max-width: 100%;
+      
+      a {
+        display: inline-block;
+      }
+    }
+  }
+}
+
 .ellipsis-menu {
   text-align: center;
 }

From c6797c0a0bf401aaade3119ab32eaa5d75a47e52 Mon Sep 17 00:00:00 2001
From: sahilvunnam <118228103+sahilvunnam@users.noreply.github.com>
Date: Tue, 7 Jan 2025 12:27:53 -0800
Subject: [PATCH 086/113] mylife: smoother myachievements (fixes #6429) (#7753)

Co-authored-by: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  6 ++--
 .../users-achievements-update.component.html  |  5 +--
 .../users-achievements-update.component.ts    | 35 +++++++++++--------
 3 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/package.json b/package.json
index c64a0b38d6..b183cd06fc 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.35",
+  "version": "0.16.36",
   "myplanet": {
-    "latest": "v0.21.62",
-    "min": "v0.20.62"
+    "latest": "v0.21.74",
+    "min": "v0.20.74"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/users/users-achievements/users-achievements-update.component.html b/src/app/users/users-achievements/users-achievements-update.component.html
index 2240d819ae..7147bde432 100644
--- a/src/app/users/users-achievements/users-achievements-update.component.html
+++ b/src/app/users/users-achievements/users-achievements-update.component.html
@@ -1,6 +1,7 @@
 <mat-toolbar>
   <button mat-icon-button (click)="goBack()"><mat-icon>arrow_back</mat-icon></button>
-  <span i18n>Edit Achievements</span>
+  <span *ngIf="achievementNotFound" i18n>Add Achievements</span>
+  <span *ngIf="!achievementNotFound" i18n>Edit Achievements</span>
 </mat-toolbar>
 
 <div class="planet-users-achievements-update space-container">
@@ -91,7 +92,7 @@
       </form>
     </div>
     <div class="achievement-button">
-      <button type="button" (click)="onSubmit()" mat-raised-button [planetSubmit]="editForm.valid && profileForm.valid" color="primary" i18n>Update</button>
+      <button type="button" (click)="onSubmit()" mat-raised-button [planetSubmit]="editForm.valid && profileForm.valid" color="primary" i18n>Submit</button>
       <button type="button" mat-raised-button color="warn" (click)="goBack()" i18n>Cancel</button>
     </div>
   </div>
diff --git a/src/app/users/users-achievements/users-achievements-update.component.ts b/src/app/users/users-achievements/users-achievements-update.component.ts
index 162823a75d..0b6c8fd501 100644
--- a/src/app/users/users-achievements/users-achievements-update.component.ts
+++ b/src/app/users/users-achievements/users-achievements-update.component.ts
@@ -20,11 +20,11 @@ import { showFormErrors } from '../../shared/table-helpers';
   encapsulation: ViewEncapsulation.None
 })
 export class UsersAchievementsUpdateComponent implements OnInit, OnDestroy {
-
   user = this.userService.get();
   configuration = this.stateService.configuration;
   docInfo = { '_id': this.user._id + '@' + this.configuration.code, '_rev': undefined };
   readonly dbName = 'achievements';
+  achievementNotFound = false;
   editForm: FormGroup;
   profileForm: FormGroup;
   private onDestroy$ = new Subject<void>();
@@ -59,20 +59,25 @@ export class UsersAchievementsUpdateComponent implements OnInit, OnDestroy {
   ngOnInit() {
     this.profileForm.patchValue(this.user);
     this.usersAchievementsService.getAchievements(this.docInfo._id)
-    .pipe(catchError(() => this.usersAchievementsService.getAchievements(this.user._id)))
-    .subscribe((achievements) => {
-      this.editForm.patchValue(achievements);
-      this.editForm.controls.achievements = this.fb.array(achievements.achievements || []);
-      this.editForm.controls.references = this.fb.array(achievements.references || []);
-      this.editForm.controls.links = this.fb.array(achievements.links || []);
-      // Keeping older otherInfo property so we don't lose this info on database
-      this.editForm.controls.otherInfo = this.fb.array(achievements.otherInfo || []);
-      if (this.docInfo._id === achievements._id) {
-        this.docInfo._rev = achievements._rev;
-      }
-    }, (error) => {
-      console.log(error);
-    });
+      .pipe(
+        catchError(() => this.usersAchievementsService.getAchievements(this.user._id))
+      )
+      .subscribe((achievements) => {
+        this.editForm.patchValue(achievements);
+        this.editForm.controls.achievements = this.fb.array(achievements.achievements || []);
+        this.editForm.controls.references = this.fb.array(achievements.references || []);
+        this.editForm.controls.links = this.fb.array(achievements.links || []);
+        // Keeping older otherInfo property so we don't lose this info on database
+        this.editForm.controls.otherInfo = this.fb.array(achievements.otherInfo || []);
+
+        if (this.docInfo._id === achievements._id) {
+          this.docInfo._rev = achievements._rev;
+        }
+      }, (error) => {
+        console.log(error);
+        this.achievementNotFound = true;
+      });
+
     this.planetStepListService.stepMoveClick$.pipe(takeUntil(this.onDestroy$)).subscribe(
       () => this.editForm.controls.dateSortOrder.setValue('none')
     );

From b8681b79e003deed233d22e0723899bc73043912 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 7 Jan 2025 15:32:29 -0500
Subject: [PATCH 087/113] teams: smoother list titles (fixes #8028) (#8029)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       | 2 +-
 src/app/teams/teams.component.html | 4 ++--
 src/app/teams/teams.scss           | 5 +++++
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index b183cd06fc..9b3b0d3d23 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.36",
+  "version": "0.16.37",
   "myplanet": {
     "latest": "v0.21.74",
     "min": "v0.20.74"
diff --git a/src/app/teams/teams.component.html b/src/app/teams/teams.component.html
index 033295d432..b2f889b592 100644
--- a/src/app/teams/teams.component.html
+++ b/src/app/teams/teams.component.html
@@ -43,8 +43,8 @@
       <ng-container matColumnDef="doc.name">
         <mat-header-cell *matHeaderCellDef mat-sort-header="doc.name" i18n>Name</mat-header-cell>
         <mat-cell *matCellDef="let element">
-          <h3>
-            {{element.doc.name}}
+          <h3 class="team-name">
+            {{element.doc.name.length > 200 ? element.doc.name.slice(0, 200) + '...': element.doc.name }}
             <mat-icon class="margin-lr-3" i18n-title title="{{ mode === 'enterprise' ? 'Joined Enterprise' : 'Joined Team' }}" [inline]="true" *ngIf="element.userStatus=='member'">check</mat-icon>
           </h3>
         </mat-cell>
diff --git a/src/app/teams/teams.scss b/src/app/teams/teams.scss
index 0e6a2cfae0..04b1fac865 100644
--- a/src/app/teams/teams.scss
+++ b/src/app/teams/teams.scss
@@ -26,6 +26,11 @@
     justify-content: center;
   }
 
+  .team-name{
+    max-width: 95%;
+    overflow: hidden;
+  }
+
   @media screen and (max-width: #{$screen-sm}) {
     mat-cell button {
       min-width: 0;

From 773fca5a7429f1a4187b3ad5e6832fc34385ff6c Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Tue, 7 Jan 2025 15:43:23 -0500
Subject: [PATCH 088/113] mylife: smoother myachievements view (fixes #8040)
 (#8041)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                         |  2 +-
 .../users-achievements.component.html                | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/package.json b/package.json
index 9b3b0d3d23..d5109497cb 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.37",
+  "version": "0.16.38",
   "myplanet": {
     "latest": "v0.21.74",
     "min": "v0.20.74"
diff --git a/src/app/users/users-achievements/users-achievements.component.html b/src/app/users/users-achievements/users-achievements.component.html
index d6d29168eb..1ccb50c49a 100644
--- a/src/app/users/users-achievements/users-achievements.component.html
+++ b/src/app/users/users-achievements/users-achievements.component.html
@@ -31,19 +31,19 @@ <h2>{{user.firstName}} {{user.middleName}} {{user.lastName}}</h2>
           <span *ngIf="user.birthplace" i18n>Birthplace: {{' ' + user.birthplace}} </span>
         </div>
       </div>
-      <mat-divider></mat-divider>
       <div *ngIf="achievements.purpose">
+        <mat-divider></mat-divider>
         <h3 i18n>My Purpose</h3>
         <td-markdown [content]="achievements.purpose"></td-markdown>
       </div>
-      <mat-divider></mat-divider>
       <div *ngIf="achievements.goals">
+        <mat-divider></mat-divider>
         <h3 i18n>My Goals</h3>
         <td-markdown [content]="achievements.goals"></td-markdown>
       </div>
-      <mat-divider></mat-divider>
       <ng-container *planetBeta>
         <div *ngIf="certifications.length > 0">
+          <mat-divider></mat-divider>
           <h3 i18n>My Certifications</h3>
           <mat-list class="certs-list">
             <mat-list-item *ngFor="let certification of certifications">
@@ -52,8 +52,8 @@ <h3 i18n>My Certifications</h3>
           </mat-list>
         </div>
       </ng-container>
-      <mat-divider></mat-divider>
       <div *ngIf="achievements?.links?.length > 0">
+        <mat-divider></mat-divider>
         <h3 i18n>My Links</h3>
         <mat-list>
           <mat-list-item class="mat-list-item-word-wrap" *ngFor="let link of achievements.links">
@@ -62,8 +62,8 @@ <h4 class="link-title" mat-line>{{link.title}}:</h4>
           </mat-list-item>
         </mat-list>
       </div>
-      <mat-divider></mat-divider>
       <div *ngIf="achievements.achievementsHeader || achievements.achievements.length > 0">
+        <mat-divider></mat-divider>
         <h3 i18n>My Achievements</h3>
         <td-markdown [content]="achievements.achievementsHeader"></td-markdown>
         <mat-list>
@@ -85,8 +85,8 @@ <h3 i18n>My Achievements</h3>
           </mat-list-item>
         </mat-list>
       </div>
-      <mat-divider></mat-divider>
       <div *ngIf="achievements.references.length > 0">
+        <mat-divider></mat-divider>
         <h3 i18n>My References</h3>
         <mat-list class="references-list">
           <mat-list-item class="mat-list-item-word-wrap" *ngFor="let reference of achievements.references">

From b768259f48f398ba77c2c49695bd917e404c91ec Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Wed, 8 Jan 2025 00:00:28 +0300
Subject: [PATCH 089/113] all: extend december challenge (fixes #8044) (#8046)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                             | 2 +-
 src/app/shared/dialogs/dialogs-announcement.component.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index d5109497cb..1c8eb63673 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.38",
+  "version": "0.16.39",
   "myplanet": {
     "latest": "v0.21.74",
     "min": "v0.20.74"
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.ts b/src/app/shared/dialogs/dialogs-announcement.component.ts
index ec17b7215b..0651bfcbee 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.ts
+++ b/src/app/shared/dialogs/dialogs-announcement.component.ts
@@ -18,7 +18,7 @@ import { planetAndParentId } from '../../manager-dashboard/reports/reports.utils
 export const includedCodes = [ 'guatemala', 'san.pablo', 'xela', 'okuro', 'uriur', 'mutugi', 'vi' ];
 export const challengeCourseId = '4e6b78800b6ad18b4e8b0e1e38a98cac';
 export const examId = '4e6b78800b6ad18b4e8b0e1e38b382ab';
-export const challengePeriod = (new Date() > new Date(2024, 10, 31)) && (new Date() < new Date(2024, 12, 1));
+export const challengePeriod = (new Date() > new Date(2024, 10, 31)) && (new Date() < new Date(2025, 0, 16));
 
 @Component({
   template: `

From d5aee9fa9d29589835ef9c20f6af06f1435697d4 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 7 Jan 2025 16:13:56 -0500
Subject: [PATCH 090/113] mylife: smoother myhealth exams (fixes #8035) (#8045)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json               | 2 +-
 src/app/health/health.scss | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 1c8eb63673..cf7b6f7bdb 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.39",
+  "version": "0.16.40",
   "myplanet": {
     "latest": "v0.21.74",
     "min": "v0.20.74"
diff --git a/src/app/health/health.scss b/src/app/health/health.scss
index 08c79a7c97..cab22985ca 100644
--- a/src/app/health/health.scss
+++ b/src/app/health/health.scss
@@ -68,3 +68,7 @@ mat-table {
     min-width: 110px;
   }
 }
+
+mat-header-cell div .header-date {
+  min-height: 1.7rem;
+}

From ad1261401ff595454dbba2400e000daae626f7a0 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 7 Jan 2025 16:26:31 -0500
Subject: [PATCH 091/113] mylife: smoother myhealth emergency contact (fixes
 #8034) (#8049)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                         | 2 +-
 src/app/health/health.component.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index cf7b6f7bdb..0e2c23a02f 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.40",
+  "version": "0.16.41",
   "myplanet": {
     "latest": "v0.21.74",
     "min": "v0.20.74"
diff --git a/src/app/health/health.component.html b/src/app/health/health.component.html
index b1591cf81e..8f236c079b 100644
--- a/src/app/health/health.component.html
+++ b/src/app/health/health.component.html
@@ -57,7 +57,7 @@ <h4 class="primary-text-color" i18n>Birthplace</h4>
           </div>
           <mat-divider></mat-divider>
         </div>
-        <div>
+        <div class="full-width">
           <div>
             <h4 class="primary-text-color" i18n>Emergency Contact</h4>
             <p><b i18n>Name: </b>{{healthDetail?.emergencyContactName || 'N/A'}}</p>

From 8470fc3ed525cbc507c64debe0437def46749931 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Thu, 9 Jan 2025 13:52:01 +0300
Subject: [PATCH 092/113] dashboard: smoother challenge initial load (fixes
 #7917) (#7933)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |   6 +--
 .../dialogs-announcement.component.html       |   2 +-
 .../dialogs/dialogs-announcement.component.ts |  36 ++++++++++--------
 src/assets/challenge/dec challenge.jpeg       | Bin 0 -> 192227 bytes
 4 files changed, 24 insertions(+), 20 deletions(-)
 create mode 100644 src/assets/challenge/dec challenge.jpeg

diff --git a/package.json b/package.json
index 0e2c23a02f..767ee0823b 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.41",
+  "version": "0.16.42",
   "myplanet": {
-    "latest": "v0.21.74",
-    "min": "v0.20.74"
+    "latest": "v0.21.75",
+    "min": "v0.20.75"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.html b/src/app/shared/dialogs/dialogs-announcement.component.html
index 4754422790..79ad83396a 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.html
+++ b/src/app/shared/dialogs/dialogs-announcement.component.html
@@ -1,6 +1,6 @@
 <div class="announcement-container">
   <img
-    src="https://res.cloudinary.com/mutugiii/image/upload/v1733224910/dec_challenge_svcbi3.jpg"
+    src="assets/challenge/dec challenge.jpeg"
     alt="Issues Challenge"
     class="announcement-banner"
   />
diff --git a/src/app/shared/dialogs/dialogs-announcement.component.ts b/src/app/shared/dialogs/dialogs-announcement.component.ts
index 0651bfcbee..93cbade868 100644
--- a/src/app/shared/dialogs/dialogs-announcement.component.ts
+++ b/src/app/shared/dialogs/dialogs-announcement.component.ts
@@ -1,8 +1,8 @@
 import { Component, OnDestroy, OnInit } from '@angular/core';
 import { MatDialogRef } from '@angular/material/dialog';
 import { Router } from '@angular/router';
-import { Subject } from 'rxjs';
-import { takeUntil } from 'rxjs/operators';
+import { Subject, of, Observable } from 'rxjs';
+import { takeUntil, catchError, map, switchMap } from 'rxjs/operators';
 
 import { findDocuments } from '../../shared/mangoQueries';
 import { CouchService } from '../couchdb.service';
@@ -11,7 +11,6 @@ import { NewsService } from '../../news/news.service';
 import { StateService } from '../state.service';
 import { SubmissionsService } from '../../submissions/submissions.service';
 import { UserService } from '../user.service';
-import { UsersService } from '../../users/users.service';
 import { UserChallengeStatusService } from '../user-challenge-status.service';
 import { planetAndParentId } from '../../manager-dashboard/reports/reports.utils';
 
@@ -24,7 +23,7 @@ export const challengePeriod = (new Date() > new Date(2024, 10, 31)) && (new Dat
   template: `
     <div class="announcement-container">
       <img
-        src="https://res.cloudinary.com/mutugiii/image/upload/v1733224910/dec_challenge_svcbi3.jpg"
+        src="assets/challenge/dec challenge.jpeg"
         alt="Issues Challenge"
         class="announcement-banner"
       />
@@ -67,7 +66,6 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     private stateService: StateService,
     private submissionsService: SubmissionsService,
     private userService: UserService,
-    private usersService: UsersService,
     private userStatusService: UserChallengeStatusService
   ) {}
 
@@ -90,6 +88,7 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
   }
 
   initializeData() {
+    this.fetchMembers().subscribe(members => { this.members = members; });
     this.coursesService.requestCourses();
     this.newsService.requestNews({
       selectors: {
@@ -100,7 +99,6 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
       },
       viewId: this.teamId
     });
-    this.fetchMembers();
     this.fetchCourseAndNews();
     this.fetchEnrolledMembers();
   }
@@ -158,16 +156,22 @@ export class DialogsAnnouncementComponent implements OnInit, OnDestroy {
     );
   }
 
-  fetchMembers() {
-    this.usersService.getAllUsers().subscribe((users: any) => {
-      this.members = users.map((member: any) => {
-        const [ , memberName ] = member?._id.split(':');
-        return {
-          ...member,
-          name: memberName,
-        };
-      });
-    });
+  fetchMembers(): Observable<any[]> {
+    return this.couchService.findAll('login_activities', findDocuments({
+      type: 'login',
+      loginTime: { $gte: this.startDate.getTime() }
+    }, [ 'user' ])).pipe(
+      catchError(() => of([])),
+      map((res: any[]) => Array.from(new Set(res.map(doc => doc.user)))),
+      switchMap(uniqueUsers => {
+        if (uniqueUsers.length === 0) { return of([]); }
+        return this.couchService.findAll(
+          '_users',
+          findDocuments({ name: { $in: uniqueUsers } }, [ '_id', 'name' ])
+        );
+      }),
+      catchError(() => of([]))
+    );
   }
 
   fetchEnrolledMembers() {
diff --git a/src/assets/challenge/dec challenge.jpeg b/src/assets/challenge/dec challenge.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..944b8beae6aa8478ea1a7cb8eb06a6d0d1f67c9c
GIT binary patch
literal 192227
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
AT>t<8

literal 0
HcmV?d00001


From 154cf6901447982c7d0ad77495971cc162a0ad56 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 9 Jan 2025 06:02:07 -0500
Subject: [PATCH 093/113] mylife: smoother myhealth exams (fixes #8050) (#8051)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                         | 2 +-
 src/app/health/health.component.html | 2 +-
 src/app/health/health.scss           | 6 +++++-
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index 767ee0823b..8b8e755e3f 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.42",
+  "version": "0.16.43",
   "myplanet": {
     "latest": "v0.21.75",
     "min": "v0.20.75"
diff --git a/src/app/health/health.component.html b/src/app/health/health.component.html
index 8f236c079b..397e14bef8 100644
--- a/src/app/health/health.component.html
+++ b/src/app/health/health.component.html
@@ -82,7 +82,7 @@ <h4 class="primary-text-color" i18n>Notes</h4>
         </div>
       </div>
       <ng-container *ngIf="events.length > 0">
-        <h4 class="full-width" i18n>Examinations</h4>
+        <h3 class="full-width examinations-header" i18n>Examinations</h3>
         <div class="full-width table-container" #examsTable>
           <mat-table [dataSource]="eventTable" *ngIf="events.length > 0">
             <ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column" [sticky]="column === 'label'">
diff --git a/src/app/health/health.scss b/src/app/health/health.scss
index cab22985ca..bc02abb366 100644
--- a/src/app/health/health.scss
+++ b/src/app/health/health.scss
@@ -69,6 +69,10 @@ mat-table {
   }
 }
 
+.examinations-header {
+  text-align: center;
+}
+
 mat-header-cell div .header-date {
   min-height: 1.7rem;
-}
+}
\ No newline at end of file

From e8550ad79fc8f8fad782f83437ac41cea5492f47 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:19:27 +0300
Subject: [PATCH 094/113] teams: add surveys (fixes #7944) (#7957)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                  |  2 +-
 src/app/exams/exams-add.component.ts          |  4 ++++
 src/app/home/home.module.ts                   |  4 +++-
 .../submissions/submissions.component.html    |  2 +-
 src/app/surveys/surveys.component.html        |  8 ++++----
 src/app/surveys/surveys.component.ts          | 19 ++++++++++++++++---
 src/app/surveys/surveys.module.ts             |  1 +
 src/app/teams/teams-router.module.ts          |  4 ++++
 src/app/teams/teams-view.component.html       |  6 +++++-
 src/app/teams/teams.module.ts                 |  2 ++
 10 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/package.json b/package.json
index 8b8e755e3f..d3e93eabe9 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.43",
+  "version": "0.16.44",
   "myplanet": {
     "latest": "v0.21.75",
     "min": "v0.20.75"
diff --git a/src/app/exams/exams-add.component.ts b/src/app/exams/exams-add.component.ts
index d3f786937e..abf7c6d3e9 100644
--- a/src/app/exams/exams-add.component.ts
+++ b/src/app/exams/exams-add.component.ts
@@ -37,6 +37,7 @@ export class ExamsAddComponent implements OnInit {
   pageType: 'Add' | 'Update' | 'Copy' = 'Add';
   courseName = '';
   examType: 'exam' | 'survey' = <'exam' | 'survey'>this.route.snapshot.paramMap.get('type') || 'exam';
+  teamId = this.route.parent?.snapshot.paramMap.get('teamId') || null;
   successMessage = this.examType === 'survey' ? $localize`New survey added` : $localize`New test added`;
   steps = [];
   showFormError = false;
@@ -120,6 +121,9 @@ export class ExamsAddComponent implements OnInit {
 
   onSubmit(reRoute = false) {
     if (this.examForm.valid) {
+      if (this.teamId) {
+        this.examForm.value.teamId = this.teamId;
+      }
       this.showFormError = false;
       this.addExam(Object.assign({}, this.examForm.value, this.documentInfo), reRoute);
     } else {
diff --git a/src/app/home/home.module.ts b/src/app/home/home.module.ts
index 8ee5378d75..5611dc04be 100644
--- a/src/app/home/home.module.ts
+++ b/src/app/home/home.module.ts
@@ -27,6 +27,7 @@ import { UsersModule } from '../users/users.module';
 import { PlanetComponent } from './planet.component';
 import { CoursesViewDetailModule } from '../courses/view-courses/courses-view-detail.module';
 import { ChatModule } from '../chat/chat.module';
+import { SurveysModule } from '../surveys/surveys.module';
 
 @NgModule({
   imports: [
@@ -46,7 +47,8 @@ import { ChatModule } from '../chat/chat.module';
     PlanetCalendarModule,
     UsersModule,
     CoursesViewDetailModule,
-    ChatModule
+    ChatModule,
+    SurveysModule
   ],
   declarations: [
     HomeComponent,
diff --git a/src/app/submissions/submissions.component.html b/src/app/submissions/submissions.component.html
index 950e0b2fbf..cd9fd16f52 100644
--- a/src/app/submissions/submissions.component.html
+++ b/src/app/submissions/submissions.component.html
@@ -62,7 +62,7 @@
       </ng-container>
       <ng-container matColumnDef="courseTitle">
         <mat-header-cell *matHeaderCellDef mat-sort-header="courseTitle" i18n>Course Name</mat-header-cell>
-        <mat-cell *matCellDef="let element">{{element.courseTitle}}</mat-cell>
+        <mat-cell *matCellDef="let element">{{element.courseTitle || element.parent.courseTitle}}</mat-cell>
       </ng-container>
       <ng-container matColumnDef="stepNum">
         <mat-header-cell *matHeaderCellDef mat-sort-header="stepNum" i18n>Course Step</mat-header-cell>
diff --git a/src/app/surveys/surveys.component.html b/src/app/surveys/surveys.component.html
index cd3302a9bd..a94b93f4ed 100644
--- a/src/app/surveys/surveys.component.html
+++ b/src/app/surveys/surveys.component.html
@@ -1,4 +1,4 @@
-<mat-toolbar>
+<mat-toolbar *ngIf="!teamId">
   <button mat-icon-button (click)="goBack()">
     <mat-icon>arrow_back</mat-icon>
   </button>
@@ -11,7 +11,7 @@
 </mat-toolbar>
 
 <div class="space-container primary-link-hover">
-  <mat-toolbar class="primary-color font-size-1">
+  <mat-toolbar *ngIf="!teamId" class="primary-color font-size-1">
     <button mat-mini-fab (click)="routeToEditSurvey('add')" *ngIf="isAuthorized" >
       <mat-icon>add</mat-icon>
     </button>
@@ -61,8 +61,8 @@
         <mat-header-cell *matHeaderCellDef i18n>Action</mat-header-cell>
         <mat-cell *matCellDef="let element">
           <ng-container *ngIf="!element.parent === true">
-            <button mat-raised-button color="primary" (click)="routeToEditSurvey('update', element._id)" i18n><mat-icon>edit</mat-icon> Edit</button>
-            <button mat-raised-button color="primary" [disabled]="!element.questions.length" (click)="openSendSurveyDialog(element)" i18n><mat-icon>send</mat-icon> Send</button>
+            <button mat-raised-button color="primary" *ngIf="!teamId" (click)="routeToEditSurvey('update', element._id)" i18n><mat-icon>edit</mat-icon> Edit</button>
+            <button mat-raised-button color="primary" *ngIf="!teamId && !routeTeamId" [disabled]="!element.questions.length" (click)="openSendSurveyDialog(element)" i18n><mat-icon>send</mat-icon> Send</button>
             <button mat-raised-button color="primary" [disabled]="!element.questions.length" (click)="recordSurvey(element)"
               i18n-matTooltip matTooltip="Record survey information from a person who is not a member of {{configuration.name}}" i18n>
               <mat-icon>fiber_manual_record</mat-icon> Record
diff --git a/src/app/surveys/surveys.component.ts b/src/app/surveys/surveys.component.ts
index 8df508e2fc..5079e926d3 100644
--- a/src/app/surveys/surveys.component.ts
+++ b/src/app/surveys/surveys.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
+import { Component, OnInit, ViewChild, AfterViewInit, OnDestroy, Input } from '@angular/core';
 import { Router, ActivatedRoute } from '@angular/router';
 import { FormGroup } from '@angular/forms';
 import { MatDialog, MatDialogRef } from '@angular/material/dialog';
@@ -25,6 +25,7 @@ import { DialogsFormService } from '../shared/dialogs/dialogs-form.service';
 import { DialogsAddTableComponent } from '../shared/dialogs/dialogs-add-table.component';
 
 @Component({
+  selector: 'planet-surveys',
   templateUrl: './surveys.component.html',
   styleUrls: [ './surveys.component.scss' ]
 })
@@ -44,6 +45,8 @@ export class SurveysComponent implements OnInit, AfterViewInit, OnDestroy {
   message = '';
   configuration = this.stateService.configuration;
   parentCount = 0;
+  routeTeamId = this.route.parent?.snapshot.paramMap.get('teamId') || null;
+  @Input() teamId?: string;
 
   constructor(
     private couchService: CouchService,
@@ -79,7 +82,17 @@ export class SurveysComponent implements OnInit, AfterViewInit, OnDestroy {
           }).length
         })),
         ...this.createParentSurveys(submissions)
-      ];
+      ].filter(survey => {
+        if (this.routeTeamId) {
+          return survey.teamId === this.routeTeamId;
+        }
+
+        if (this.teamId) {
+          return survey.teamId === this.teamId;
+        } else {
+          return true;
+        }
+      });
       this.surveys.data = this.surveys.data.map((data: any) => ({ ...data, courseTitle: data.course ? data.course.courseTitle : '' }));
       this.dialogsLoadingService.stop();
     });
@@ -245,7 +258,7 @@ export class SurveysComponent implements OnInit, AfterViewInit, OnDestroy {
   recordSurvey(survey: any) {
     this.submissionsService.createSubmission(survey, 'survey').subscribe((res: any) => {
       this.router.navigate([
-        'dispense',
+        this.teamId ? 'surveys/dispense' : 'dispense',
         { questionNum: 1, submissionId: res.id, status: 'pending', mode: 'take' }
       ], { relativeTo: this.route });
     });
diff --git a/src/app/surveys/surveys.module.ts b/src/app/surveys/surveys.module.ts
index c9594d40bb..35294a277a 100644
--- a/src/app/surveys/surveys.module.ts
+++ b/src/app/surveys/surveys.module.ts
@@ -23,6 +23,7 @@ import { SharedComponentsModule } from '../shared/shared-components.module';
     SurveysRouterModule,
     SharedComponentsModule
   ],
+  exports: [ SurveysComponent ],
   declarations: [
     SurveysComponent
   ]
diff --git a/src/app/teams/teams-router.module.ts b/src/app/teams/teams-router.module.ts
index b686e4f9bc..ba8a036766 100644
--- a/src/app/teams/teams-router.module.ts
+++ b/src/app/teams/teams-router.module.ts
@@ -6,6 +6,10 @@ import { TeamsViewComponent } from './teams-view.component';
 const routes: Routes = [
   { path: '', component: TeamsComponent },
   { path: 'view/:teamId', component: TeamsViewComponent },
+  {
+    path: 'view/:teamId/surveys',
+    loadChildren: () => import('../surveys/surveys.module').then(m => m.SurveysModule)
+  },
   { path: 'users', loadChildren: () => import('../users/users.module').then(m => m.UsersModule) },
 ];
 @NgModule({
diff --git a/src/app/teams/teams-view.component.html b/src/app/teams/teams-view.component.html
index 4f2a7d5b8b..ce128346a2 100644
--- a/src/app/teams/teams-view.component.html
+++ b/src/app/teams/teams-view.component.html
@@ -43,6 +43,7 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
   <ng-template #actionButtons>
     <ng-container [ngSwitch]="userStatus" *ngIf="user.isUserAdmin || user.roles.length">
       <ng-container *ngSwitchCase="'member'">
+        <a class="margin-lr-3" [routerLink]="['surveys']" mat-stroked-button mat-button i18n>Manage Surveys</a>
         <button *ngIf="mode!=='services'" mat-stroked-button mat-button class=" toolbar-button margin-lr-3" (click)="openInviteMemberDialog()" i18n [disabled]="disableAddingMembers">
           Add Members
         </button>
@@ -184,7 +185,7 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
             </div>
           </ng-template>
         </mat-tab>
-        <mat-tab label="Courses">
+        <mat-tab i18n-label label="Courses">
           <ng-template mat-tab-label>
             <ng-container i18n>Courses</ng-container> ({{team?.courses?.length || 0}})
           </ng-template>
@@ -211,6 +212,9 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
             </div>
           </ng-template>
         </mat-tab>
+        <mat-tab i18n-label label="Surveys">
+          <planet-surveys [teamId]="teamId"></planet-surveys>
+        </mat-tab>
         <mat-tab *ngIf="mode!=='services'" #applicantTab>
           <ng-template mat-tab-label>
             <ng-container i18n>{ mode, select, team {Join Requests} enterprise {Applicants} }</ng-container> ({{requests.length}})
diff --git a/src/app/teams/teams.module.ts b/src/app/teams/teams.module.ts
index 11b2614760..c77877f90b 100644
--- a/src/app/teams/teams.module.ts
+++ b/src/app/teams/teams.module.ts
@@ -18,6 +18,7 @@ import { TeamsMemberComponent } from './teams-member.component';
 import { TeamsReportsComponent } from './teams-reports.component';
 import { TeamsReportsDialogComponent } from './teams-reports-dialog.component';
 import { TeamsReportsDetailComponent } from './teams-reports-detail.component';
+import { SurveysModule } from '../surveys/surveys.module';
 
 @NgModule({
   exports: [ TeamsViewComponent, TeamsComponent, TeamsViewFinancesComponent, TeamsMemberComponent, TeamsReportsComponent ],
@@ -34,6 +35,7 @@ import { TeamsReportsDetailComponent } from './teams-reports-detail.component';
     SharedComponentsModule,
     PlanetCalendarModule,
     FormsModule,
+    SurveysModule
   ],
   declarations: [
     TeamsComponent,

From eb56a011cf928be7b62acbf40338f00a8e47c318 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:32:04 +0300
Subject: [PATCH 095/113] all: activate alternative login (fixes #8047) (#8048)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                         | 2 +-
 src/app/home/home-router.module.ts   | 4 ++--
 src/app/shared/auth-guard.service.ts | 9 +++++++++
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/package.json b/package.json
index d3e93eabe9..cd96df184f 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.44",
+  "version": "0.16.45",
   "myplanet": {
     "latest": "v0.21.75",
     "min": "v0.20.75"
diff --git a/src/app/home/home-router.module.ts b/src/app/home/home-router.module.ts
index 8eda6e64d8..bf3a53ac97 100644
--- a/src/app/home/home-router.module.ts
+++ b/src/app/home/home-router.module.ts
@@ -73,8 +73,8 @@ const routes: Routes = [
       }
     ]
   },
-  { path: 'landing', component: LandingComponent },
-  { path: 'landing', loadChildren: () => import('../landing/landing.module').then(m => m.LandingModule) }
+  { path: 'landing', component: LandingComponent, data: { requiresAuth: false } },
+  { path: 'landing', loadChildren: () => import('../landing/landing.module').then(m => m.LandingModule), data: { requiresAuth: false } }
 ];
 
 @NgModule({
diff --git a/src/app/shared/auth-guard.service.ts b/src/app/shared/auth-guard.service.ts
index c19ec8debe..5461ff3422 100644
--- a/src/app/shared/auth-guard.service.ts
+++ b/src/app/shared/auth-guard.service.ts
@@ -45,6 +45,15 @@ export class AuthService {
   // For main app (which requires login).  Uses canActivateChild to check on every route
   // change if session has expired
   canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
+    let currentRoute: ActivatedRouteSnapshot | null = route;
+
+    while (currentRoute) {
+      if (currentRoute.data && currentRoute.data.requiresAuth === false) {
+        return of(true);
+      }
+      currentRoute = currentRoute.parent;
+    }
+
     return this.checkUser(state.url);
   }
 

From 7fa7fa68ae2e2c62e17c8882368f3e98ad937d44 Mon Sep 17 00:00:00 2001
From: Gavin Porter <112116086+Gavinp14@users.noreply.github.com>
Date: Thu, 9 Jan 2025 16:31:50 -0500
Subject: [PATCH 096/113] mylife: smoother achievements resume (fixes #8062)
 (#8063)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                | 6 +++---
 .../users-achievements/users-achievements.component.ts      | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index cd96df184f..9d3b250457 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.45",
+  "version": "0.16.46",
   "myplanet": {
-    "latest": "v0.21.75",
-    "min": "v0.20.75"
+    "latest": "v0.21.81",
+    "min": "v0.20.81"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/users/users-achievements/users-achievements.component.ts b/src/app/users/users-achievements/users-achievements.component.ts
index de990a2643..4c420cea89 100644
--- a/src/app/users/users-achievements/users-achievements.component.ts
+++ b/src/app/users/users-achievements/users-achievements.component.ts
@@ -133,8 +133,8 @@ export class UsersAchievementsComponent implements OnInit {
       {
         text: `
           ${this.user.firstName} ${this.user.middleName ? this.user.middleName : ''} ${this.user.lastName}
-          ${formattedBirthDate ? $localize`Birthplace: ${formattedBirthDate}` : ''}
-          ${this.user.Birthplace ? $localize`Birthdate: ${this.user.Birthplace}` : ''}
+          ${formattedBirthDate ? $localize`Birthdate: ${formattedBirthDate}` : ''}
+          ${this.user.birthplace ? $localize`Birthplace: ${this.user.birthplace}` : ''}
           `,
         alignment: 'center',
       },

From 5d179559e6dba7dee9646f7dc69bac9fdfddfba2 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 9 Jan 2025 16:44:35 -0500
Subject: [PATCH 097/113] mylife: smoother myhealth dialog (fixes #8064)
 (#8065)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                             | 2 +-
 src/app/health/health-event.component.ts | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 9d3b250457..cb86d48517 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.46",
+  "version": "0.16.47",
   "myplanet": {
     "latest": "v0.21.81",
     "min": "v0.20.81"
diff --git a/src/app/health/health-event.component.ts b/src/app/health/health-event.component.ts
index 832e826095..7f44e4c4b7 100644
--- a/src/app/health/health-event.component.ts
+++ b/src/app/health/health-event.component.ts
@@ -116,6 +116,7 @@ export class HealthEventComponent implements OnInit {
             this.goBack();
           }
         },
+        displayName: '',
         showMainParagraph: false,
         extraMessage: $localize`The value(s) of the following are not in the normal range. Click <b>Cancel</b> to fix or click <b>OK</b> to submit.`,
         showLabels: invalidFields

From 736dc853041ed5382c23a44d8e42bba61e3b62d4 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 9 Jan 2025 16:53:24 -0500
Subject: [PATCH 098/113] courses: smoother finish button (fixes #8059) (#8067)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                  | 2 +-
 .../step-view-courses/courses-step-view.component.html        | 2 +-
 src/app/courses/step-view-courses/courses-step-view.scss      | 4 ++++
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index cb86d48517..a3fbcf8a19 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.47",
+  "version": "0.16.48",
   "myplanet": {
     "latest": "v0.21.81",
     "min": "v0.20.81"
diff --git a/src/app/courses/step-view-courses/courses-step-view.component.html b/src/app/courses/step-view-courses/courses-step-view.component.html
index a08a3a2267..d785b55e7f 100644
--- a/src/app/courses/step-view-courses/courses-step-view.component.html
+++ b/src/app/courses/step-view-courses/courses-step-view.component.html
@@ -66,7 +66,7 @@ <h3 class="margin-lr-3 ellipsis-title"><ng-container i18n>Step</ng-container> {{
       <span>{{stepNum}}/{{maxStep}}</span>
       <button mat-icon-button *ngIf="maxStep !== 1" [disabled]="stepNum === 1" (click)="changeStep(-1)"><mat-icon>navigate_before</mat-icon></button>
       <button mat-icon-button *ngIf="stepNum !== maxStep"  [disabled]="stepNum === maxStep || (!parent && stepDetail?.exam?.questions.length > 0 && !attempts)" (click)="changeStep(1)"><mat-icon>navigate_next</mat-icon></button>
-      <button mat-raised-button *ngIf="stepNum === maxStep && maxStep !== 1" [disabled]="!parent && stepDetail?.exam?.questions.length > 0 && !attempts" (click)="backToCourseDetail()" i18n>Finish</button>
+      <button mat-raised-button class="finish-button" *ngIf="stepNum === maxStep" [disabled]="!parent && stepDetail?.exam?.questions.length > 0 && !attempts" (click)="backToCourseDetail()" i18n>Finish</button>
     </div>
   </mat-toolbar>
   <div class="view-container view-full-height" [ngClass]="{'grid-view': showChat, 'flex-view': !isGridView && !showChat}" *ngIf="stepDetail?.description || resource?._attachments; else emptyRecord">
diff --git a/src/app/courses/step-view-courses/courses-step-view.scss b/src/app/courses/step-view-courses/courses-step-view.scss
index 77862610d5..052748fcf0 100644
--- a/src/app/courses/step-view-courses/courses-step-view.scss
+++ b/src/app/courses/step-view-courses/courses-step-view.scss
@@ -56,4 +56,8 @@
     text-overflow: ellipsis;
   }
 
+  .finish-button {
+    margin-left: 10px;
+  }
+
 }

From 1c0f87c0e9b48460072b30cd83951051607e0b5e Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Thu, 9 Jan 2025 16:58:43 -0500
Subject: [PATCH 099/113] teams: smoother list buttons (fixes #8054) (#8066)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json             |  2 +-
 src/app/teams/teams.scss | 20 +++++++++++++++++++-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index a3fbcf8a19..c6e522a4c7 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.48",
+  "version": "0.16.49",
   "myplanet": {
     "latest": "v0.21.81",
     "min": "v0.20.81"
diff --git a/src/app/teams/teams.scss b/src/app/teams/teams.scss
index 04b1fac865..0af5144e31 100644
--- a/src/app/teams/teams.scss
+++ b/src/app/teams/teams.scss
@@ -31,10 +31,28 @@
     overflow: hidden;
   }
 
-  @media screen and (max-width: #{$screen-sm}) {
+  .mat-cell button, .mat-cell div button[mat-raised-button] {
+    width: 150px;
+    text-align: center;
+    padding: 8px 12px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  @media (max-width: $screen-sm) {
     mat-cell button {
       min-width: 0;
       padding: 0 3px;
     }
+
+    .mat-cell button, .mat-cell div button[mat-raised-button] {
+      width: 50px;
+    }
+
+    .button-container {
+      flex-direction: column;
+      align-items: flex-start;
+    }
   }
 }

From 19a772aa449d875600d4f80483db930f7cf0e941 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Fri, 10 Jan 2025 15:41:26 -0500
Subject: [PATCH 100/113] all: smoother navigation icons (fixes #7980) (#7982)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                     |  6 ++---
 src/app/home/home.component.html | 29 ++++++++++++-----------
 src/assets/icons/logout.svg      | 40 ++++++++++----------------------
 3 files changed, 31 insertions(+), 44 deletions(-)

diff --git a/package.json b/package.json
index c6e522a4c7..b8694a9665 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.49",
+  "version": "0.16.50",
   "myplanet": {
-    "latest": "v0.21.81",
-    "min": "v0.20.81"
+    "latest": "v0.21.88",
+    "min": "v0.20.88"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index 6296f3e295..4a3e34eca7 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -49,7 +49,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
       <ng-container *planetAuthorizedRoles>
         <button mat-icon-button planetSync i18n-title title="Sync" *ngIf="onlineStatus === 'accepted'"><mat-icon svgIcon="feedback"></mat-icon></button>
       </ng-container>
-      <button mat-icon-button routerLink="/manager" i18n-title title="Manager Settings" *planetAuthorizedRoles="'manager,monitor'"><mat-icon svgIcon="usersettings"></mat-icon></button>
+      <button mat-icon-button routerLink="/manager" i18n-title title="Manager Settings" *planetAuthorizedRoles="'manager,monitor'"><mat-icon>settings</mat-icon></button>
       <planet-language></planet-language>
     </span>
     <ng-container *planetAuthorizedRoles="'learner'">
@@ -109,7 +109,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
               planetPulsateIcon
               i18n-title title="Community"
               [routerLinkActiveOptions]="{exact:true}">
-              <mat-icon svgIcon="home"></mat-icon>
+              <mat-icon>home</mat-icon>
               <label i18n>Community</label>
             </a>
           </li>
@@ -119,7 +119,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
               planetPulsateIcon
               i18n-title title="Nation"
               [routerLinkActiveOptions]="{exact:true}">
-              <mat-icon svgIcon="home"></mat-icon>
+              <mat-icon>library_books</mat-icon>
               <label i18n>Nation</label>
             </a>
           </li>
@@ -129,7 +129,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
             routerLinkActive="active"
             planetPulsateIcon
             i18n-title title="Dashboard">
-            <mat-icon>turned_in_not</mat-icon>
+            <mat-icon>dashboard</mat-icon>
             <label i18n>myDashboard</label>
           </a>
         </li>
@@ -138,7 +138,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
             routerLinkActive="active"
             planetPulsateIcon
             i18n-title title="Library">
-            <mat-icon svgIcon="myLibrary"></mat-icon>
+            <mat-icon>folder</mat-icon>
             <label i18n>Library</label>
           </a>
         </li>
@@ -147,7 +147,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
             routerLinkActive="active"
             planetPulsateIcon
             i18n-title title="Courses">
-            <mat-icon svgIcon="myCourses"></mat-icon>
+            <mat-icon>school</mat-icon>
             <label i18n>Courses</label>
           </a>
         </li>
@@ -156,7 +156,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
             routerLinkActive="active"
             planetPulsateIcon
             i18n-title title="Teams">
-            <mat-icon svgIcon="myTeams"></mat-icon>
+            <mat-icon>groups</mat-icon>
             <label i18n>Teams</label>
           </a>
         </li>
@@ -165,7 +165,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
             routerLinkActive="active"
             planetPulsateIcon
             i18n-title title="Enterprises">
-            <mat-icon>business</mat-icon>
+            <mat-icon>work</mat-icon>
             <label i18n>Enterprises</label>
           </a>
         </li>
@@ -187,7 +187,7 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
       <ul class="bottom-nav">
         <li>
           <a mat-button routerLink="/chat" i18n-title title="Chat">
-            <mat-icon>chat_bubble_outline</mat-icon>
+            <mat-icon>question_answer</mat-icon>
             <label i18n>Chat</label>
           </a>
         </li>
@@ -199,20 +199,23 @@ <h1><ng-container>Planet</ng-container> {{planetName}}</h1>
         </li>
         <li>
           <a mat-button routerLink="/feedback" i18n-title title="Messages">
-            <mat-icon>mail_outline</mat-icon>
+            <mat-icon>mail</mat-icon>
             <label i18n>Messages</label>
           </a>
         </li>
         <ng-container *planetAuthorizedRoles="'manager,monitor'">
           <li>
             <a mat-button routerLink="/manager" i18n-title title="Manager Settings">
-              <mat-icon svgIcon="usersettings"></mat-icon>
+              <mat-icon>settings</mat-icon>
               <label i18n>Manager Settings</label>
             </a>
           </li>
         </ng-container>
-        <li style="text-align: center;">
-          <planet-language [iconOnly]="layout === 'modern' || forceModern"></planet-language>
+        <li>
+          <a mat-button (click)="openLanguageDialog()" i18n-title title="Change Language">
+            <mat-icon>translate</mat-icon>
+            <label *ngIf="sidenavState === 'open'" i18n>Language</label>
+          </a>
         </li>
         <ng-container *planetAuthorizedRoles>
           <li *ngIf="onlineStatus === 'accepted'">
diff --git a/src/assets/icons/logout.svg b/src/assets/icons/logout.svg
index 2464672fc3..185a3d42c9 100644
--- a/src/assets/icons/logout.svg
+++ b/src/assets/icons/logout.svg
@@ -1,28 +1,12 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 viewBox="0 0 511.989 511.989" style="enable-background:new 0 0 511.989 511.989;" xml:space="preserve">
-<g>
-	<g>
-		<g>
-			<path d="M110.933,221.782c-4.71,0-8.533,3.823-8.533,8.533v51.2c0,4.71,3.823,8.533,8.533,8.533s8.533-3.823,8.533-8.533v-51.2
-				C119.467,225.605,115.644,221.782,110.933,221.782z"/>
-			<path d="M111.855,2.304L31.172,34.586C8.448,43,0,54.418,0,76.715v358.477c0,22.298,8.448,33.715,30.959,42.061l81.058,32.427
-				c4.011,1.519,8.038,2.287,11.981,2.287c17.152,0,29.602-14.336,29.602-34.091V34.049C153.6,9.78,134.246-6.126,111.855,2.304z
-				 M136.533,477.876c0,10.18-5.035,17.024-12.535,17.024c-1.869,0-3.883-0.401-5.803-1.118L37.103,461.33
-				c-16.102-5.965-20.036-11.102-20.036-26.138V76.715c0-15.036,3.934-20.164,20.241-26.206l80.725-32.29
-				c2.082-0.785,4.087-1.186,5.956-1.186c7.501,0,12.544,6.835,12.544,17.016V477.876z"/>
-			<path d="M178.133,51.115h120.533c14.114,0,25.6,11.486,25.6,25.6v128c0,4.71,3.814,8.533,8.533,8.533
-				c4.719,0,8.533-3.823,8.533-8.533v-128c0-23.526-19.14-42.667-42.667-42.667H178.133c-4.71,0-8.533,3.823-8.533,8.533
-				S173.423,51.115,178.133,51.115z"/>
-			<path d="M332.8,298.582c-4.719,0-8.533,3.823-8.533,8.533v128c0,14.114-11.486,25.6-25.6,25.6H179.2
-				c-4.71,0-8.533,3.823-8.533,8.533s3.823,8.533,8.533,8.533h119.467c23.526,0,42.667-19.14,42.667-42.667v-128
-				C341.333,302.405,337.519,298.582,332.8,298.582z"/>
-			<path d="M511.343,252.655c-0.435-1.05-1.058-1.988-1.852-2.782l-85.325-85.333c-3.337-3.336-8.73-3.336-12.066,0
-				c-3.337,3.337-3.337,8.73,0,12.066l70.767,70.775H196.267c-4.71,0-8.533,3.823-8.533,8.533c0,4.71,3.823,8.533,8.533,8.533
-				h286.601L412.1,335.215c-3.337,3.337-3.337,8.73,0,12.066c1.664,1.664,3.849,2.5,6.033,2.5c2.185,0,4.369-0.836,6.033-2.5
-				l85.325-85.325c0.794-0.794,1.417-1.732,1.852-2.782C512.205,257.093,512.205,254.738,511.343,252.655z"/>
-		</g>
-	</g>
-</g>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Uploaded to: SVG Find, www.svgrepo.com, Generator: SVG Find Mixer Tools -->
+<svg width="800px" height="800px" version="1.1" viewBox="144 144 512 512" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+  <clipPath id="a">
+   <path d="m148.09 148.09h503.81v503.81h-503.81z"/>
+  </clipPath>
+ </defs>
+ <g clip-path="url(#a)">
+  <path d="m649.6 405.56-70.848 70.848v0.003906c-1.4766 1.4766-3.4805 2.3047-5.5664 2.3047-2.0898 0-4.0898-0.82812-5.5664-2.3047l-23.617-23.617c-1.4766-1.4766-2.3047-3.4766-2.3047-5.5664 0-2.0859 0.82813-4.0898 2.3047-5.5664l18.051-18.051h-130.56c-4.3477 0-7.875-3.5234-7.875-7.8711v-31.488c0-4.3477 3.5273-7.8711 7.875-7.8711h130.56l-18.051-18.051c-1.4766-1.4766-2.3047-3.4766-2.3047-5.5664 0-2.0859 0.82813-4.0898 2.3047-5.5664l23.617-23.617v0.003907c1.4766-1.4766 3.4766-2.3086 5.5664-2.3086 2.0859 0 4.0898 0.83203 5.5664 2.3086l70.848 70.848c1.4766 1.4766 2.3047 3.4766 2.3047 5.5664 0 2.0859-0.82812 4.0898-2.3047 5.5625zm-241.73 10.18v-31.488c0.019531-6.2578 2.5117-12.254 6.9375-16.68 4.4258-4.4219 10.422-6.918 16.68-6.9375h78.719v-157.44c-0.011719-4.3438-3.5312-7.8594-7.8711-7.875h-149.57v409.35h149.57c4.3398-0.011719 7.8594-3.5312 7.8711-7.8711v-157.44h-78.719c-6.2578-0.019531-12.254-2.5117-16.68-6.9375-4.4258-4.4258-6.918-10.422-6.9375-16.68zm-125.95-23.617c-3.1836 0-6.0547 1.918-7.2734 4.8594s-0.54297 6.3281 1.707 8.582c2.25 2.25 5.6367 2.9219 8.5781 1.7031 2.9414-1.2148 4.8594-4.0859 4.8594-7.2695-0.003906-4.3477-3.5234-7.8711-7.8711-7.875zm55.105-236.16v488.07c0 2.5273-1.2109 4.9023-3.2617 6.3828-2.0469 1.4805-4.6797 1.8867-7.0781 1.0938l-173.18-57.203-0.003906 0.003906c-3.2266-1.0664-5.4023-4.082-5.4023-7.4805v-373.66c0-3.3984 2.1758-6.4141 5.4023-7.4766l173.18-57.203h0.003906c2.3984-0.79297 5.0312-0.38672 7.0781 1.0977 2.0508 1.4805 3.2617 3.8516 3.2617 6.3789zm-31.488 244.04c0-6.2656-2.4883-12.273-6.918-16.699-4.4297-4.4297-10.438-6.918-16.699-6.918s-12.27 2.4883-16.699 6.918c-4.4297 4.4258-6.918 10.434-6.918 16.699 0 6.2617 2.4883 12.27 6.918 16.699 4.4297 4.4258 10.438 6.9141 16.699 6.9141 6.2617-0.003906 12.266-2.4961 16.691-6.9219 4.4258-4.4297 6.918-10.43 6.9258-16.691z"/>
+ </g>
+</svg>
\ No newline at end of file

From f118bc306f881aeaf441335dd505e2a6c194210b Mon Sep 17 00:00:00 2001
From: sahilvunnam <118228103+sahilvunnam@users.noreply.github.com>
Date: Fri, 10 Jan 2025 12:53:51 -0800
Subject: [PATCH 101/113] enterprises: smoother report titles (fixes #6917)
 (#7743)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                               | 2 +-
 src/app/teams/teams-reports.component.html | 4 ++--
 src/app/teams/teams-reports.component.ts   | 7 +++++--
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/package.json b/package.json
index b8694a9665..a4168c9a9e 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.50",
+  "version": "0.16.51",
   "myplanet": {
     "latest": "v0.21.88",
     "min": "v0.20.88"
diff --git a/src/app/teams/teams-reports.component.html b/src/app/teams/teams-reports.component.html
index 4c6f9d79b1..f22a7cfd42 100644
--- a/src/app/teams/teams-reports.component.html
+++ b/src/app/teams/teams-reports.component.html
@@ -1,5 +1,5 @@
 <div class="fixed action-buttons" *ngIf="editable">
-  <button mat-raised-button color="primary" i18n (click)="openAddReportDialog()">Add Report</button>
+  <button mat-raised-button color="primary" i18n (click)="openAddReportDialog(false)">Add Report</button>
   <button mat-raised-button color="accent" i18n *ngIf="reports && reports.length > 0" (click)="exportReports()">
     Export as CSV
   </button>
@@ -20,7 +20,7 @@
       <mat-card-footer class="action-buttons margin-lr-10">
         <ng-container *ngIf="editable">
           <button mat-icon-button (click)="$event.stopPropagation(); openDeleteReportDialog(report)"><mat-icon>delete</mat-icon></button>
-          <button mat-icon-button (click)="$event.stopPropagation(); openAddReportDialog(report)"><mat-icon>edit</mat-icon></button>
+          <button mat-icon-button (click)="$event.stopPropagation(); openAddReportDialog(report, true)"><mat-icon>edit</mat-icon></button>
         </ng-container>
         <button mat-button i18n>View Report</button>
       </mat-card-footer>
diff --git a/src/app/teams/teams-reports.component.ts b/src/app/teams/teams-reports.component.ts
index f7cccabeba..c56c4013f9 100644
--- a/src/app/teams/teams-reports.component.ts
+++ b/src/app/teams/teams-reports.component.ts
@@ -51,13 +51,16 @@ export class TeamsReportsComponent implements DoCheck {
     }
   }
 
-  openAddReportDialog(oldReport = {}) {
+  openAddReportDialog(oldReport = {}, isEdit: boolean) {
+    const actionType = isEdit ? 'Edit' : 'Add';
+    const dialogTitle = $localize`${actionType} Report`;
+
     this.couchService.currentTime().subscribe((time: number) => {
       const currentDate = new Date(time);
       const lastMonthStart = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1);
       const lastMonthEnd = currentDate.setDate(0);
       this.dialogsFormService.openDialogsForm(
-        $localize`Add Report`,
+        dialogTitle,
         [
           { name: 'startDate', placeholder: $localize`Start Date`, type: 'date', required: true },
           { name: 'endDate', placeholder: $localize`End Date`, type: 'date', required: true },

From 9541b0ea165fbdd8de1df935c49baf2d0731a91c Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Sat, 11 Jan 2025 00:07:40 +0300
Subject: [PATCH 102/113] mylife: smoother achievements view (fixes #8060)
 (#8061)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                    | 2 +-
 .../users/users-achievements/users-achievements.component.ts    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index a4168c9a9e..ed9ffb55b3 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.51",
+  "version": "0.16.52",
   "myplanet": {
     "latest": "v0.21.88",
     "min": "v0.20.88"
diff --git a/src/app/users/users-achievements/users-achievements.component.ts b/src/app/users/users-achievements/users-achievements.component.ts
index 4c420cea89..63001b25dd 100644
--- a/src/app/users/users-achievements/users-achievements.component.ts
+++ b/src/app/users/users-achievements/users-achievements.component.ts
@@ -177,7 +177,7 @@ export class UsersAchievementsComponent implements OnInit {
         ...this.achievements.achievements.map((achievement) => {
           return [
             { text: achievement.title, bold: true, margin: [ 20, 5 ] },
-            { text: format(new Date(achievement.date), 'MMM d, y'), marginLeft: 40 },
+            { text: achievement.date ? format(new Date(achievement?.date), 'MMM d, y') : '', marginLeft: 40 },
             { text: achievement.link, marginLeft: 40 },
             { text: achievement.description, marginLeft: 40 },
           ];

From 8c2492ae73021239de3c02378b2578b9be98f2ea Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 13 Jan 2025 16:03:09 -0500
Subject: [PATCH 103/113] teams: smoother toolbar buttons (fixes #8077) (#8079)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                            | 6 +++---
 src/app/teams/teams-view.component.html | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index ed9ffb55b3..63f4b379f6 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.52",
+  "version": "0.16.53",
   "myplanet": {
-    "latest": "v0.21.88",
-    "min": "v0.20.88"
+    "latest": "v0.21.96",
+    "min": "v0.20.96"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/teams/teams-view.component.html b/src/app/teams/teams-view.component.html
index ce128346a2..171eadc7c1 100644
--- a/src/app/teams/teams-view.component.html
+++ b/src/app/teams/teams-view.component.html
@@ -43,7 +43,7 @@ <h3 *ngIf="mode==='services'" class="margin-lr-3 ellipsis-title">{{configuration
   <ng-template #actionButtons>
     <ng-container [ngSwitch]="userStatus" *ngIf="user.isUserAdmin || user.roles.length">
       <ng-container *ngSwitchCase="'member'">
-        <a class="margin-lr-3" [routerLink]="['surveys']" mat-stroked-button mat-button i18n>Manage Surveys</a>
+        <a class="toolbar-button margin-lr-3" [routerLink]="['surveys']" mat-stroked-button mat-button i18n>Manage Surveys</a>
         <button *ngIf="mode!=='services'" mat-stroked-button mat-button class=" toolbar-button margin-lr-3" (click)="openInviteMemberDialog()" i18n [disabled]="disableAddingMembers">
           Add Members
         </button>

From cbcb75f6a77f07890c18f49302612ba2d58c9786 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Mon, 13 Jan 2025 16:16:57 -0500
Subject: [PATCH 104/113] resources: smoother collections dialog (fixes #8058)
 (#8080)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                              | 2 +-
 src/app/shared/forms/planet-tag-input-dialog.component.ts | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 63f4b379f6..583e14b096 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.53",
+  "version": "0.16.54",
   "myplanet": {
     "latest": "v0.21.96",
     "min": "v0.20.96"
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.ts b/src/app/shared/forms/planet-tag-input-dialog.component.ts
index 1e26049b29..418fdbbf44 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.ts
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.ts
@@ -22,6 +22,7 @@ import { DialogsPromptComponent } from '../../shared/dialogs/dialogs-prompt.comp
     :host mat-dialog-content {
       overflow-y: auto;
       max-height: calc(100vh - 100px);
+      width: 600px;
     }
     :host .mat-list-option span {
       font-weight: inherit;
@@ -35,6 +36,9 @@ import { DialogsPromptComponent } from '../../shared/dialogs/dialogs-prompt.comp
     :host mat-dialog-actions {
       padding: 0;
     }
+    button[mat-stroked-button] {
+      min-width: 64px;
+    }
   ` ]
 })
 export class PlanetTagInputDialogComponent {

From 3db52efa85e7734e0ed3ed1ea5f15d1fad2bcae9 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Tue, 14 Jan 2025 00:43:21 +0300
Subject: [PATCH 105/113] mylife: smoother myhealth access (fixes #8068)
 (#8069)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                         |  2 +-
 src/app/home/home-router.module.ts   |  4 ++--
 src/app/shared/auth-guard.service.ts | 14 +++++++++-----
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index 583e14b096..d5c756aa8a 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.54",
+  "version": "0.16.55",
   "myplanet": {
     "latest": "v0.21.96",
     "min": "v0.20.96"
diff --git a/src/app/home/home-router.module.ts b/src/app/home/home-router.module.ts
index bf3a53ac97..28a7f2105f 100644
--- a/src/app/home/home-router.module.ts
+++ b/src/app/home/home-router.module.ts
@@ -34,8 +34,8 @@ const routes: Routes = [
       { path: 'upgrade/myplanet', component: UpgradeComponent, data: { myPlanet: true } },
       { path: 'teams', loadChildren: () => import('../teams/teams.module').then(m => m.TeamsModule) },
       { path: 'enterprises', loadChildren: () => import('../teams/teams.module').then(m => m.TeamsModule), data: { mode: 'enterprise' } },
-      { path: 'health', component: HealthListComponent },
-      { path: 'health/profile/:id', loadChildren: () => import('../health/health.module').then(m => m.HealthModule) },
+      { path: 'health', component: HealthListComponent, data: { roles: [ '_admin', 'health' ] } },
+      { path: 'health/profile/:id', loadChildren: () => import('../health/health.module').then(m => m.HealthModule), data: { roles: [ '_admin', 'health' ] } },
       { path: 'nation', component: TeamsViewComponent, data: { mode: 'services' } },
       { path: 'earth', component: TeamsViewComponent, data: { mode: 'services' } },
       { path: myDashboardRoute, component: DashboardComponent },
diff --git a/src/app/shared/auth-guard.service.ts b/src/app/shared/auth-guard.service.ts
index 5461ff3422..91272411ab 100644
--- a/src/app/shared/auth-guard.service.ts
+++ b/src/app/shared/auth-guard.service.ts
@@ -22,12 +22,17 @@ export class AuthService {
     return this.pouchAuthService.getSessionInfo();
   }
 
-  private checkUser(url: any): Observable<boolean> {
+  private checkUser(url: any, roles: any[]): Observable<boolean> {
     return this.getSession$().pipe(
       switchMap((sessionInfo) => {
         if (sessionInfo.userCtx.name) {
           // If user already matches one on the user service, do not make additional call to CouchDB
-          if (sessionInfo.userCtx.name === this.userService.get().name) {
+          const user = this.userService.get();
+          if (sessionInfo.userCtx.name === user.name) {
+            if (roles.length > 0) {
+              const hasRole = roles.some(role => user.roles.includes(role));
+              return hasRole ? of(true) : of(false);
+            }
             return of(true);
           }
           this.stateService.requestBaseData();
@@ -46,15 +51,14 @@ export class AuthService {
   // change if session has expired
   canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
     let currentRoute: ActivatedRouteSnapshot | null = route;
-
+    const roles: Array<string> = currentRoute.data?.roles ?? [];
     while (currentRoute) {
       if (currentRoute.data && currentRoute.data.requiresAuth === false) {
         return of(true);
       }
       currentRoute = currentRoute.parent;
     }
-
-    return this.checkUser(state.url);
+    return this.checkUser(state.url, roles);
   }
 
   // For login route will redirect to main app if there is an active session

From 2ace99efe82eae88a78376d600e382ab759edf0a Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 14 Jan 2025 15:45:06 -0500
Subject: [PATCH 106/113] teams: smoother resources handling (fixes #8072)
 (#8078)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                          |  6 +++---
 .../dialogs/dialogs-add-resources.component.html      |  2 +-
 .../shared/dialogs/dialogs-add-resources.component.ts | 11 +++++++++--
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/package.json b/package.json
index d5c756aa8a..f2cbdad6a1 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.55",
+  "version": "0.16.56",
   "myplanet": {
-    "latest": "v0.21.96",
-    "min": "v0.20.96"
+    "latest": "v0.21.99",
+    "min": "v0.20.99"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/shared/dialogs/dialogs-add-resources.component.html b/src/app/shared/dialogs/dialogs-add-resources.component.html
index b56c029b15..fa189446c6 100644
--- a/src/app/shared/dialogs/dialogs-add-resources.component.html
+++ b/src/app/shared/dialogs/dialogs-add-resources.component.html
@@ -10,5 +10,5 @@
     <span class="margin-lr-8" i18n>OR</span>
   </ng-container>
   <button mat-raised-button mat-dialog-close i18n>Cancel</button>
-  <button color="primary" mat-raised-button [disabled]="okDisabled" (click)="ok()" i18n>OK</button>
+  <button color="primary" mat-raised-button [disabled]="okDisabled || isSubmitting" (click)="ok()" i18n>OK</button>
 </mat-dialog-actions>
diff --git a/src/app/shared/dialogs/dialogs-add-resources.component.ts b/src/app/shared/dialogs/dialogs-add-resources.component.ts
index 2e5ae0fbb0..d17aa4c862 100644
--- a/src/app/shared/dialogs/dialogs-add-resources.component.ts
+++ b/src/app/shared/dialogs/dialogs-add-resources.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject, ViewChild, AfterViewInit } from '@angular/core';
+import { Component, Inject, ViewChild, AfterViewInit, ChangeDetectorRef } from '@angular/core';
 import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 import { ResourcesComponent } from '../../resources/resources.component';
 import { ResourcesAddComponent } from '../../resources/resources-add.component';
@@ -16,11 +16,13 @@ export class DialogsAddResourcesComponent implements AfterViewInit {
   okDisabled = true;
   updateResource = false;
   existingResource: any = {};
+  isSubmitting = false;
 
   constructor(
     public dialogRef: MatDialogRef<DialogsAddResourcesComponent>,
     @Inject(MAT_DIALOG_DATA) public data: any,
-    private dialogsLoadingService: DialogsLoadingService
+    private dialogsLoadingService: DialogsLoadingService,
+    private cdr: ChangeDetectorRef
   ) {
     this.linkInfo = this.data.db ? { [this.data.db]: this.data.linkId } : undefined;
     if (this.data.resource) {
@@ -32,9 +34,14 @@ export class DialogsAddResourcesComponent implements AfterViewInit {
 
   ngAfterViewInit() {
     this.initOkDisableChange();
+    this.cdr.detectChanges();
   }
 
   ok() {
+    if (this.isSubmitting) {
+      return;
+    }
+    this.isSubmitting = true;
     this.dialogsLoadingService.start();
     switch (this.view) {
       case 'resources':

From 46473e7869b83da7fdb2ae1b7730eb21c132a77e Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 14 Jan 2025 15:54:55 -0500
Subject: [PATCH 107/113] teams: smoother voices titles (fixes #8086)(fixes
 #8087) (#8089)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                              | 2 +-
 src/app/news/news-list.component.ts                       | 2 +-
 src/app/shared/forms/planet-tag-input-dialog.component.ts | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index f2cbdad6a1..7bca8d8ea5 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.56",
+  "version": "0.16.57",
   "myplanet": {
     "latest": "v0.21.99",
     "min": "v0.20.99"
diff --git a/src/app/news/news-list.component.ts b/src/app/news/news-list.component.ts
index fb0b0cf5bd..daf1bf1d2c 100644
--- a/src/app/news/news-list.component.ts
+++ b/src/app/news/news-list.component.ts
@@ -22,7 +22,7 @@ import { dedupeShelfReduce } from '../shared/utils';
 export class NewsListComponent implements OnChanges {
 
   @Input() items: any[] = [];
-  @Input() editSuccessMessage = $localize`News has been updated successfully.`;
+  @Input() editSuccessMessage = $localize`Message updated successfully.`;
   @Input() viewableBy = 'community';
   @Input() viewableId: string;
   @Input() editable = true;
diff --git a/src/app/shared/forms/planet-tag-input-dialog.component.ts b/src/app/shared/forms/planet-tag-input-dialog.component.ts
index 418fdbbf44..35d967fb7d 100644
--- a/src/app/shared/forms/planet-tag-input-dialog.component.ts
+++ b/src/app/shared/forms/planet-tag-input-dialog.component.ts
@@ -223,10 +223,10 @@ export class PlanetTagInputDialogComponent {
       onNext: (data) => {
         this.data.initTags();
         this.deleteDialog.close();
-        this.planetMessageService.showMessage($localize`Tag deleted: ${tag.name}`);
+        this.planetMessageService.showMessage($localize`Collection deleted: ${tag.name}`);
         this.resetValidationAndCheck(this.addTagForm);
       },
-      onError: (error) => this.planetMessageService.showAlert($localize`There was a problem deleting this tag.`)
+      onError: (error) => this.planetMessageService.showAlert($localize`There was a problem deleting this collection.`)
     };
   }
 

From 5c195345034fc454ffd53711ee00ff38678ae48b Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Tue, 14 Jan 2025 15:59:33 -0500
Subject: [PATCH 108/113] enterprises: smoother delete dialog (fixes #8083)
 (#8091)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                    |  2 +-
 .../dialogs/dialogs-prompt.component.html       |  1 +
 src/app/teams/teams.component.ts                | 17 ++++++++++-------
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/package.json b/package.json
index 7bca8d8ea5..bc9b22e5d6 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.57",
+  "version": "0.16.58",
   "myplanet": {
     "latest": "v0.21.99",
     "min": "v0.20.99"
diff --git a/src/app/shared/dialogs/dialogs-prompt.component.html b/src/app/shared/dialogs/dialogs-prompt.component.html
index 456c4b973f..88b1c2e754 100644
--- a/src/app/shared/dialogs/dialogs-prompt.component.html
+++ b/src/app/shared/dialogs/dialogs-prompt.component.html
@@ -12,6 +12,7 @@
         user {member}
         change {change}
         team {team}
+        enterprise {enterprise}
         task {task}
         certification {certification}
         event {event}
diff --git a/src/app/teams/teams.component.ts b/src/app/teams/teams.component.ts
index 9fdb471b82..db0f006ed1 100644
--- a/src/app/teams/teams.component.ts
+++ b/src/app/teams/teams.component.ts
@@ -195,7 +195,8 @@ export class TeamsComponent implements OnInit, AfterViewInit {
     this.teamsService.addTeamDialog(this.user._id, this.mode, { ...team, teamType }).subscribe(() => {
       this.getTeams();
       const action = $localize`${team._id ? 'updated' : 'created'}`;
-      const msg = $localize`${toProperCase(this.mode)} ${action} successfully`;
+      const entityType = this.mode === 'enterprise' ? 'Enterprise' : 'Team';
+      const msg = $localize`${entityType} ${action} successfully`;
       this.planetMessageService.showMessage(msg);
     });
   }
@@ -220,12 +221,13 @@ export class TeamsComponent implements OnInit, AfterViewInit {
           onNext: () => {
             this.leaveDialog.close();
             this.teams.data = this.teamList(this.teams.data);
-            const msg = 'left';
-            this.planetMessageService.showMessage($localize`You have ${msg} ${team.name}`);
+            const entityType = this.mode === 'enterprise' ? 'enterprise' : 'team';
+            const msg = $localize`You have left ${entityType} ${team.name}`;
+            this.planetMessageService.showMessage(msg);
           },
         },
         changeType: 'leave',
-        type: 'team',
+        type: this.mode === 'enterprise' ? 'enterprise' : 'team',
         displayName: team.name
       }
     });
@@ -240,7 +242,7 @@ export class TeamsComponent implements OnInit, AfterViewInit {
         this.planetMessageService.showMessage($localize`You have deleted ${entityType} ${team.name}.`);
         this.removeTeamFromTable(team);
       },
-      onError: () => this.planetMessageService.showAlert($localize`There was a problem deleting this team.`)
+      onError: () => this.planetMessageService.showAlert($localize`There was a problem deleting this ${this.mode === 'enterprise' ? 'enterprise' : 'team'}.`)
     };
   }
 
@@ -249,7 +251,7 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       data: {
         okClick: this.archiveTeam(team),
         changeType: 'delete',
-        type: 'team',
+        type: this.mode === 'enterprise' ? 'enterprise' : 'team',
         displayName: team.name
       }
     });
@@ -268,7 +270,8 @@ export class TeamsComponent implements OnInit, AfterViewInit {
       finalize(() => this.dialogsLoadingService.stop())
     ).subscribe(() => {
       this.teams.data = this.teamList(this.teams.data);
-      this.planetMessageService.showMessage($localize`Request to join ${team.name} sent`);
+      const entityType = this.mode === 'enterprise' ? 'enterprise' : 'team';
+      this.planetMessageService.showMessage($localize`Request to join ${entityType} ${team.name} sent`);
     });
   }
 

From 107f00ee3943d1f92f7ba0957d7f9f1bed2e069d Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 15 Jan 2025 16:00:20 -0500
Subject: [PATCH 109/113] teams: smoother reports dialogs (fixes #8084)(fixes
 #8085) (#8090)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                             |  6 +++---
 src/app/teams/teams-reports.component.ts | 12 +++++++++++-
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index bc9b22e5d6..04dd957c1e 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.58",
+  "version": "0.16.59",
   "myplanet": {
-    "latest": "v0.21.99",
-    "min": "v0.20.99"
+    "latest": "v0.22.7",
+    "min": "v0.21.7"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/teams/teams-reports.component.ts b/src/app/teams/teams-reports.component.ts
index c56c4013f9..95b136ade9 100644
--- a/src/app/teams/teams-reports.component.ts
+++ b/src/app/teams/teams-reports.component.ts
@@ -12,6 +12,7 @@ import { tap } from 'rxjs/operators';
 import { convertUtcDate } from './teams.utils';
 import { CsvService } from '../shared/csv.service';
 import { StateService } from '../shared/state.service';
+import { PlanetMessageService } from '../shared/planet-message.service';
 
 @Component({
   selector: 'planet-teams-reports',
@@ -38,6 +39,7 @@ export class TeamsReportsComponent implements DoCheck {
     private csvService: CsvService,
     private elementRef: ElementRef,
     private stateService: StateService,
+    private planetMessageService: PlanetMessageService,
   ) {}
 
   ngDoCheck() {
@@ -76,6 +78,8 @@ export class TeamsReportsComponent implements DoCheck {
           disableIfInvalid: true,
           onSubmit: (newReport) => this.updateReport(oldReport, newReport).subscribe(() => {
             this.dialogsFormService.closeDialogsForm();
+            const action = isEdit ? 'edited' : 'added';
+            this.planetMessageService.showMessage(`Report ${action}`);
           })
         }
       );
@@ -87,11 +91,17 @@ export class TeamsReportsComponent implements DoCheck {
       data: {
         changeType: 'delete',
         type: 'report',
-        displayDates: report,
+        displayName: `${$localize`Report from`} ${new Date(report.startDate).toLocaleDateString('en-US', { timeZone: 'UTC' })} ${$localize`to`} ${new Date(report.endDate).toLocaleDateString('en-US', { timeZone: 'UTC' })}`,
         okClick: {
           request: this.updateReport(report),
           onNext: () => {
+            this.planetMessageService.showMessage('Report deleted');
+            this.dialogsLoadingService.stop();
             deleteDialog.close();
+          },
+          onError: () => {
+            this.planetMessageService.showAlert('There was a problem deleting the report.');
+            this.dialogsLoadingService.stop();
           }
         },
         isDateUtc: true

From 8af64363d579e2132406171cce9d5cb5745d7d8e Mon Sep 17 00:00:00 2001
From: Axel Lo <54468493+RheuX@users.noreply.github.com>
Date: Wed, 15 Jan 2025 13:07:06 -0800
Subject: [PATCH 110/113] teams: smoother calendar legend (fixes #8093) (#8094)

Co-authored-by: mutugiii <mutugimutuma@gmail.com>
Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                           |  2 +-
 src/app/community/community.scss       | 21 ---------------------
 src/app/shared/calendar.component.scss | 20 ++++++++++++++++++++
 src/app/shared/calendar.component.ts   |  1 +
 4 files changed, 22 insertions(+), 22 deletions(-)
 create mode 100644 src/app/shared/calendar.component.scss

diff --git a/package.json b/package.json
index 04dd957c1e..311fe6f150 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.59",
+  "version": "0.16.60",
   "myplanet": {
     "latest": "v0.22.7",
     "min": "v0.21.7"
diff --git a/src/app/community/community.scss b/src/app/community/community.scss
index 5f6aa4a2ff..c0e0e1c264 100644
--- a/src/app/community/community.scss
+++ b/src/app/community/community.scss
@@ -35,27 +35,6 @@ planet-calendar {
   overflow-y: auto;
 }
 
-.calendar-legend {
-  padding-top: 10px;
-  text-align: right;
-  display: flex;
-  flex-wrap: wrap;
-  justify-content: flex-end;
-  gap: 10px;
-}
-
-.calendar-legend .legend-item {
-  display: inline-flex;
-  align-items: center;
-}
-
-.calendar-legend .legend-color {
-  width: 20px;
-  height: 20px;
-  margin-right: 10px;
-  border-radius: 4px;
-}
-
 .card-grid {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
diff --git a/src/app/shared/calendar.component.scss b/src/app/shared/calendar.component.scss
new file mode 100644
index 0000000000..cb56cbab92
--- /dev/null
+++ b/src/app/shared/calendar.component.scss
@@ -0,0 +1,20 @@
+.calendar-legend {
+  padding-top: 10px;
+  text-align: right;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+.calendar-legend .legend-item {
+  display: inline-flex;
+  align-items: center;
+}
+
+.calendar-legend .legend-color {
+  width: 20px;
+  height: 20px;
+  margin-right: 10px;
+  border-radius: 4px;
+}
diff --git a/src/app/shared/calendar.component.ts b/src/app/shared/calendar.component.ts
index 80a05b48b9..4c1abc1148 100644
--- a/src/app/shared/calendar.component.ts
+++ b/src/app/shared/calendar.component.ts
@@ -14,6 +14,7 @@ import { addDateAndTime, styleVariables } from './utils';
 
 @Component({
   selector: 'planet-calendar',
+  styleUrls: [ './calendar.component.scss' ],
   template: `
     <full-calendar #calendar [options]="calendarOptions"></full-calendar>
     <div class="calendar-legend" *ngIf="showLegend">

From 2162bf2478e308429088aec3279606abc83382f5 Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Thu, 16 Jan 2025 00:12:28 +0300
Subject: [PATCH 111/113] mylife: smoother achievements sharing (fixes #8082)
 (#8095)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                           |  2 +-
 .../users-achievements.component.html                  |  7 +++++--
 .../users-achievements/users-achievements.component.ts | 10 +++++++++-
 .../users-achievements/users-achievements.module.ts    |  3 ++-
 .../users/users-profile/users-profile.component.html   | 10 ----------
 src/app/users/users-router.module.ts                   |  2 +-
 6 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/package.json b/package.json
index 311fe6f150..459e02c8dc 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.60",
+  "version": "0.16.61",
   "myplanet": {
     "latest": "v0.22.7",
     "min": "v0.21.7"
diff --git a/src/app/users/users-achievements/users-achievements.component.html b/src/app/users/users-achievements/users-achievements.component.html
index 1ccb50c49a..e4f34d8301 100644
--- a/src/app/users/users-achievements/users-achievements.component.html
+++ b/src/app/users/users-achievements/users-achievements.component.html
@@ -1,4 +1,4 @@
-<mat-toolbar>
+<mat-toolbar *ngIf="!publicView">
   <button mat-icon-button (click)="goBack()"><mat-icon>arrow_back</mat-icon></button>
   <span i18n>Achievements</span>
   <span class="toolbar-fill"></span>
@@ -19,6 +19,9 @@
         <span *ngIf="achievementNotFound" i18n>Add Achievements</span>
         <span *ngIf="!achievementNotFound" i18n>Edit Achievements</span>
       </a>
+      <button mat-icon-button matTooltip="Copy Achievements Link" i18n-matTooltip (click)="copyLink()">
+        <mat-icon>link</mat-icon>
+      </button>
     </div>
   </mat-toolbar>
   <div class="view-container">
@@ -26,7 +29,7 @@
       <div class="user-info">
         <img class="profile-image" [src]="profileImg">
         <h2>{{user.firstName}} {{user.middleName}} {{user.lastName}}</h2>
-        <div class="birth-info">
+        <div class="birth-info" *ngIf="!publicView">
           <ng-container *ngIf="user.birthDate"><span i18n>Birthdate: {{' ' + (user.birthDate | date: medium) + ' '}}</span></ng-container><br/><br/>
           <span *ngIf="user.birthplace" i18n>Birthplace: {{' ' + user.birthplace}} </span>
         </div>
diff --git a/src/app/users/users-achievements/users-achievements.component.ts b/src/app/users/users-achievements/users-achievements.component.ts
index 63001b25dd..34d9258e02 100644
--- a/src/app/users/users-achievements/users-achievements.component.ts
+++ b/src/app/users/users-achievements/users-achievements.component.ts
@@ -1,6 +1,7 @@
 import { format } from 'date-fns';
 import { Component, OnInit, ViewEncapsulation } from '@angular/core';
 import { Router, ActivatedRoute, ParamMap } from '@angular/router';
+import { Clipboard } from '@angular/cdk/clipboard';
 import { CouchService } from '../../shared/couchdb.service';
 import { UserService } from '../../shared/user.service';
 import { PlanetMessageService } from '../../shared/planet-message.service';
@@ -29,6 +30,7 @@ export class UsersAchievementsComponent implements OnInit {
   urlPrefix = environment.couchAddress + '/_users/org.couchdb.user:' + this.userService.get().name + '/';
   openAchievementIndex = -1;
   certifications: any[] = [];
+  publicView = this.route.snapshot.data.requiresAuth === false;
 
   constructor(
     private couchService: CouchService,
@@ -39,7 +41,8 @@ export class UsersAchievementsComponent implements OnInit {
     private usersAchievementsService: UsersAchievementsService,
     private stateService: StateService,
     private coursesService: CoursesService,
-    private certificationsService: CertificationsService
+    private certificationsService: CertificationsService,
+    private clipboard: Clipboard
   ) { }
 
   ngOnInit() {
@@ -122,6 +125,11 @@ export class UsersAchievementsComponent implements OnInit {
     });
   }
 
+  copyLink() {
+    const link = `${window.location.origin}/profile/${this.user.name}/achievements;planet=${this.stateService.configuration.code}`;
+    this.clipboard.copy(link);
+  }
+
   generatePDF() {
     const formattedBirthDate = format(new Date(this.user.birthDate), 'MMM d, y');
     let contentArray = [
diff --git a/src/app/users/users-achievements/users-achievements.module.ts b/src/app/users/users-achievements/users-achievements.module.ts
index 62cc595f77..aad8ee2ae1 100644
--- a/src/app/users/users-achievements/users-achievements.module.ts
+++ b/src/app/users/users-achievements/users-achievements.module.ts
@@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { RouterModule } from '@angular/router';
+import { ClipboardModule } from '@angular/cdk/clipboard';
 import { MaterialModule } from '../../shared/material.module';
 import { PlanetFormsModule } from '../../shared/forms/planet-forms.module';
 import { SharedComponentsModule } from '../../shared/shared-components.module';
@@ -10,7 +11,7 @@ import { UsersAchievementsUpdateComponent } from './users-achievements-update.co
 
 @NgModule({
   imports: [
-    CommonModule, FormsModule, ReactiveFormsModule, RouterModule, MaterialModule, PlanetFormsModule, SharedComponentsModule
+    CommonModule, FormsModule, ReactiveFormsModule, RouterModule, MaterialModule, PlanetFormsModule, SharedComponentsModule, ClipboardModule
   ],
   exports: [
     UsersAchievementsUpdateComponent,
diff --git a/src/app/users/users-profile/users-profile.component.html b/src/app/users/users-profile/users-profile.component.html
index 03f2f084a0..610f5ef41d 100644
--- a/src/app/users/users-profile/users-profile.component.html
+++ b/src/app/users/users-profile/users-profile.component.html
@@ -1,13 +1,3 @@
-<mat-toolbar *ngIf="!isDialog">
-  <mat-toolbar-row>
-    <button mat-icon-button (click)="goBack()">
-      <mat-icon>arrow_back</mat-icon>
-    </button>
-    <span i18n>Member Profile</span>
-    <span class="toolbar-fill"></span>
-  </mat-toolbar-row>
-</mat-toolbar>
-
 <div class="space-container">
   <mat-toolbar class="primary-color font-size-1">
     <span>{{userDetail.name}}</span>
diff --git a/src/app/users/users-router.module.ts b/src/app/users/users-router.module.ts
index 23185ce4ed..0a864c1e97 100644
--- a/src/app/users/users-router.module.ts
+++ b/src/app/users/users-router.module.ts
@@ -13,7 +13,7 @@ const routes: Routes = [
   { path: 'delete/request', component: UsersArchiveComponent },
   { path: 'profile/:name', component: UsersProfileComponent },
   { path: 'update/:name', component: UsersUpdateComponent },
-  { path: 'profile/:name/achievements', component: UsersAchievementsComponent },
+  { path: 'profile/:name/achievements', component: UsersAchievementsComponent, data: { requiresAuth: false } },
   { path: 'profile/:name/achievements/update', component: UsersAchievementsUpdateComponent },
   { path: 'submission', component: UsersUpdateComponent, data: { submission: true } }
 ];

From 8dea8ae90778da5aeef0a34d6260783ae85d81d4 Mon Sep 17 00:00:00 2001
From: Jesse Washburn <142361664+jessewashburn@users.noreply.github.com>
Date: Wed, 15 Jan 2025 16:17:27 -0500
Subject: [PATCH 112/113] mylife: smoother achievements links (fixes #8071)
 (#8098)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                                                    | 2 +-
 .../users-achievements/users-achievements-update.component.ts   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 459e02c8dc..db18039cfb 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.61",
+  "version": "0.16.62",
   "myplanet": {
     "latest": "v0.22.7",
     "min": "v0.21.7"
diff --git a/src/app/users/users-achievements/users-achievements-update.component.ts b/src/app/users/users-achievements/users-achievements-update.component.ts
index 0b6c8fd501..b994f5542d 100644
--- a/src/app/users/users-achievements/users-achievements-update.component.ts
+++ b/src/app/users/users-achievements/users-achievements-update.component.ts
@@ -133,7 +133,7 @@ export class UsersAchievementsUpdateComponent implements OnInit, OnDestroy {
         ...achievement,
         title: [ achievement.title, CustomValidators.required ],
         description: [ achievement.description ],
-        link: [ achievement.link, [], CustomValidators.validLink ],
+        link: [ achievement.link ],
         date: [ achievement.date, null, ac => this.validatorService.notDateInFuture$(ac) ]
       }),
       { onSubmit: (formValue, formGroup) => {

From df8e748d1e17397de155bfc84baa353c229388bb Mon Sep 17 00:00:00 2001
From: Mutugi <48474421+Mutugiii@users.noreply.github.com>
Date: Thu, 16 Jan 2025 23:44:45 +0300
Subject: [PATCH 113/113] manager: smoother rights check (fixes #8105) (#8106)

Co-authored-by: dogi <dogi@users.noreply.github.com>
---
 package.json                       | 6 +++---
 src/app/home/home-router.module.ts | 6 +++++-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json
index db18039cfb..2d6e744a6f 100755
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
 {
   "name": "planet",
   "license": "AGPL-3.0",
-  "version": "0.16.62",
+  "version": "0.16.63",
   "myplanet": {
-    "latest": "v0.22.7",
-    "min": "v0.21.7"
+    "latest": "v0.22.13",
+    "min": "v0.21.13"
   },
   "scripts": {
     "ng": "ng",
diff --git a/src/app/home/home-router.module.ts b/src/app/home/home-router.module.ts
index 28a7f2105f..00a9d12816 100644
--- a/src/app/home/home-router.module.ts
+++ b/src/app/home/home-router.module.ts
@@ -23,7 +23,11 @@ const routes: Routes = [
       { path: '', component: CommunityComponent },
       { path: 'community/:code', component: CommunityComponent },
       { path: 'users', loadChildren: () => import('../users/users.module').then(m => m.UsersModule) },
-      { path: 'manager', loadChildren: () => import('../manager-dashboard/manager-dashboard.module').then(m => m.ManagerDashboardModule) },
+      {
+        path: 'manager',
+        loadChildren: () => import('../manager-dashboard/manager-dashboard.module').then(m => m.ManagerDashboardModule),
+        data: { roles: [ '_admin' ] }
+      },
       { path: 'courses', loadChildren: () => import('../courses/courses.module').then(m => m.CoursesModule) },
       { path: 'feedback', loadChildren: () => import('../feedback/feedback.module').then(m => m.FeedbackModule) },
       { path: 'resources', loadChildren: () => import('../resources/resources.module').then(m => m.ResourcesModule) },