diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c41c391..682eae9f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
#### Bug fixes
* **(guided-tour)** : correction problème de chargement des traductions du tour guidé sur certains périphériques
* **(statistics)** : suppression de l'utilisation du DeviceId pour le suivi des statistiques d'usage comme préconisé dans le RGPD. Utilisation d'une UID générée automatiquement par le client à la place.
-* **(widgets)**: les widgets tiennent désormais compte de l'ionicon ou bien des icônes SVG renseignées du côté du CMS et les affichent à côté du titre de la Widget
+* **(widgets)**: les widgets tiennent désormais compte de l'Ionicon ou bien des icônes SVG renseignées du côté du CMS et les affichent à côté du titre de la Widget
+
+#### New features
+* **(schedule)** : Il est désormais possible de choisir entre 2 affichages pour la widget des prochains cours à venir :
+ * Liste verticale (list)
+ * Slider horizontal (slider)
### Backend
#### Bug fixes
diff --git a/dev/user-frontend-ionic/projects/schedule/README.md b/dev/user-frontend-ionic/projects/schedule/README.md
index daecdddd..a532a2ee 100644
--- a/dev/user-frontend-ionic/projects/schedule/README.md
+++ b/dev/user-frontend-ionic/projects/schedule/README.md
@@ -2,36 +2,33 @@
Module permettant l'affichage des emplois du temps de l'utilisateur.
-## Widgets
-- `next-events` : Widget qui affiche les prochains évènements de l'emploi du temps.
-
## Configuration
-Exemple dans `app.module.ts` :
+Exemple dans `environment.ts` :
```typescript
- @NgModule({
- declarations: [AppComponent],
- imports: [
- ScheduleModule.forRoot({
- nextEventsWidget: {
- numberOfEventsLimit: 2,
- numberOfDaysLimit: 7
- },
- previousWeeksInCache: 1,
- nextWeeksInCache: 2,
- managerRoles: ['role_1', 'role_2']
- })
- ]
- })
+ScheduleModule.forRoot({
+ nextEventsWidget: {
+ numberOfEventsLimit: 2,
+ numberOfDaysLimit: 7,
+ display: 'slider'
+ },
+ previousWeeksInCache: 1,
+ nextWeeksInCache: 2,
+ managerRoles: ['role_1', 'role_2']
+})
```
-### Configuration du widget "mes prochains cours"
-- `nextEventsWidget.numberOfEventsLimit` : nombre maximum des prochains évènements à afficher.
-- `nextEventsWidget.numberOfDaysLimit` : limite maximale du nombre de jours suivants le jour courant dans lesquels chercher les prochains évènements.
-
### Configuration du cache
- `previousWeeksInCache` : Le nombre de semaines précédentes à sauvegarder en cache.
- `nextEventsWidget.numberOfDaysLimit` : Le nombre de semaines suivant à sauvegarder en cache.
### Configuration des gestionnaires d'emploi du temps
- `managerRoles` : Liste des rôles permettant d'identifier l'utilisateur comme étant gestionnaire d'emploi du temps et lui permettant ainsi d'accéder à l'affichage d'un EDT pour une autre personne
+
+## Widgets
+- `next-events` : Widget qui affiche les prochains évènements de l'emploi du temps.
+
+### Configuration du widget "mes prochains cours"
+- `nextEventsWidget.numberOfEventsLimit` : nombre maximum des prochains évènements à afficher.
+- `nextEventsWidget.numberOfDaysLimit` : limite maximale du nombre de jours suivants le jour courant dans lesquels chercher les prochains évènements.
+- `nextEventsWidget.display` : ("list" | "slider") : choix de la vue, en liste ou en ligne
diff --git a/dev/user-frontend-ionic/projects/schedule/src/lib/schedule.config.ts b/dev/user-frontend-ionic/projects/schedule/src/lib/schedule.config.ts
index 14a5e306..3dab8af8 100644
--- a/dev/user-frontend-ionic/projects/schedule/src/lib/schedule.config.ts
+++ b/dev/user-frontend-ionic/projects/schedule/src/lib/schedule.config.ts
@@ -42,6 +42,7 @@ import { InjectionToken } from '@angular/core';
interface NextEventsWidgetConfig {
numberOfEventsLimit: number;
numberOfDaysLimit: number;
+ display: "list" | "slider";
}
export interface ScheduleModuleConfig {
diff --git a/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.html b/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.html
index c57cd776..e60198db 100644
--- a/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.html
+++ b/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.html
@@ -37,65 +37,147 @@
~ termes.
-->
-
-
-
-
-
-
-
-
- {{ "SCHEDULE.WIDGET.NEXT_EVENTS.NO_EVENTS" | translate }}
-
+
+
+
+
+
+
+
-
-
-
- {{ event.startDateTime | completeLocalDate }}
-
-
-
-
-
-
-
-
-
- {{event.startDateTime | localHour}} - {{event.endDateTime | localHour}}
-
-
-
-
-
-
- {{event.course.label}}
-
-
-
- {{room.label}} - {{room.building}}
+
+
+
+
+
+ {{ "SCHEDULE.WIDGET.NEXT_EVENTS.NO_EVENTS" | translate }}
+
+
+
+
+
+
+
+
+
+ {{ event.startDateTime | completeLocalDate }}
+
+
+
+
+
+
+
+
+
+
+ {{event.startDateTime | localHour}} - {{event.endDateTime | localHour}}
+
+
+
+
+
+
+ {{event.course.label}}
+
+
+
+
+
+
+ {{room.label}} - {{room.building}}
+
+
+
+
+
+
+
+
+ {{teacher.displayname}}
+
+
+
+
+
+
+
+
+ {{ event.course.url | truncate:35 }}
+
+
+
-
-
- {{teacher.displayname}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ "SCHEDULE.WIDGET.NEXT_EVENTS.NO_EVENTS" | translate }}
+
+
+
+
+
+
+
+
+ {{event.startDateTime | localHour}} - {{event.endDateTime | localHour}}
+
+
+ {{completeLocalDate | slice: 0:completeLocalDate.indexOf(' ')}}
+ {{completeLocalDate | slice: completeLocalDate.indexOf(' ')}}
+
+
+
+ {{event.course.label}}
+
+
+
+ {{room.label}} - {{room.building}}
+
+
+
+ {{teacher.displayname}}
+
+
+
+
+
+ {{event.teachers[0].displayname}} (+ {{event.teachers.length - 1}} {{ "SCHEDULE.WIDGET.NEXT_EVENTS.LIMIT_TEACHERS" | translate }})
+
+
-
- {{ event.course.url | truncate:35 }}
+
+ {{ event.course.url | truncate:35 }}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.ts b/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.ts
index 446c1f27..2b8b5bb5 100644
--- a/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.ts
+++ b/dev/user-frontend-ionic/projects/schedule/src/lib/widgets/next-events/next-events.component.ts
@@ -37,13 +37,14 @@
* termes.
*/
-import { AfterViewInit, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core';
+import { AfterViewInit, ChangeDetectorRef, Component, Inject, Input, OnDestroy, TemplateRef, ViewChild } from '@angular/core';
import { CompleteLocalDatePipe, ThemeService } from '@multi/shared';
import { Observable, Subscription } from 'rxjs';
import { finalize, map, take } from 'rxjs/operators';
import { Event } from '../../schedule.repository';
import { ScheduleService } from '../../schedule.service';
import { NextEventsService } from './next-events.service';
+import { SCHEDULE_CONFIG, ScheduleModuleConfig } from '../../schedule.config';
@Component({
selector: 'app-schedule-widget-next-events',
@@ -53,6 +54,8 @@ import { NextEventsService } from './next-events.service';
export class NextEventsComponent implements OnDestroy, AfterViewInit {
@Input() widgetColor: string;
+ @ViewChild('list') list: TemplateRef;
+ @ViewChild('slider') slider: TemplateRef;
public isLoading = false;
public nextEvents$: Observable;
@@ -65,7 +68,8 @@ export class NextEventsComponent implements OnDestroy, AfterViewInit {
private scheduleService: ScheduleService,
private completeLocalDatePipe: CompleteLocalDatePipe,
private themeService: ThemeService,
- private changeDetectorRef: ChangeDetectorRef
+ private changeDetectorRef: ChangeDetectorRef,
+ @Inject(SCHEDULE_CONFIG) private config: ScheduleModuleConfig
) {
this.nextEvents$ = this.nextEventsService.getNextEvents$().pipe();
@@ -111,5 +115,9 @@ export class NextEventsComponent implements OnDestroy, AfterViewInit {
ngOnDestroy() {
this.nextEventsSubscription.unsubscribe();
}
+
+ getTemplateRef(): TemplateRef {
+ return this[this?.config.nextEventsWidget.display];
+ }
}
diff --git a/dev/user-frontend-ionic/src/environments/environment.ts.dist b/dev/user-frontend-ionic/src/environments/environment.ts.dist
index a4ba19f7..85a833ab 100644
--- a/dev/user-frontend-ionic/src/environments/environment.ts.dist
+++ b/dev/user-frontend-ionic/src/environments/environment.ts.dist
@@ -108,7 +108,8 @@ export const environment: any = {
ScheduleModule.forRoot({
nextEventsWidget: {
numberOfEventsLimit: 2,
- numberOfDaysLimit: 7
+ numberOfDaysLimit: 7,
+ display: 'list'
},
previousWeeksInCache: 1,
nextWeeksInCache: 2,
diff --git a/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/en.json b/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/en.json
index 363668e0..f3d21886 100644
--- a/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/en.json
+++ b/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/en.json
@@ -42,7 +42,8 @@
},
"WIDGET": {
"NEXT_EVENTS": {
- "NO_EVENTS": "No courses soon"
+ "NO_EVENTS": "No courses soon",
+ "LIMIT_TEACHERS": "others"
}
}
}
diff --git a/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/fr.json b/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/fr.json
index ab6357f4..3a060340 100644
--- a/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/fr.json
+++ b/dev/user-frontend-ionic/src/theme/app-theme-dist/i18n/schedule/fr.json
@@ -42,7 +42,8 @@
},
"WIDGET": {
"NEXT_EVENTS": {
- "NO_EVENTS": "Pas de cours prochainement"
+ "NO_EVENTS": "Pas de cours prochainement",
+ "LIMIT_TEACHERS": "autres"
}
}
}
diff --git a/dev/user-frontend-ionic/src/theme/app-theme-dist/styles/schedule/next-events.component.scss b/dev/user-frontend-ionic/src/theme/app-theme-dist/styles/schedule/next-events.component.scss
index fd105f35..34b93e9a 100644
--- a/dev/user-frontend-ionic/src/theme/app-theme-dist/styles/schedule/next-events.component.scss
+++ b/dev/user-frontend-ionic/src/theme/app-theme-dist/styles/schedule/next-events.component.scss
@@ -37,79 +37,195 @@
* termes.
*/
-ion-card {
- overflow: visible;
- box-shadow: var(--app-border-no-box-shadow);
- border-radius: var(--app-border-no-radius);
- margin-top: 0px !important;
- margin-bottom: 0px !important;
- background: transparent;
-}
+.next-events-list-style {
-.last-card {
- padding-bottom: 0.8rem !important;
-}
+ ion-card {
+ overflow: visible;
+ box-shadow: var(--app-border-no-box-shadow);
+ border-radius: var(--app-border-no-radius);
+ margin-top: 0 !important;
+ margin-bottom: 0 !important;
+ background: transparent;
+ }
-.events-container {
-padding-left: 1rem !important;
-padding-bottom: 0rem !important;
-}
+ .last-card {
+ padding-bottom: 0.8rem !important;
+ }
-.dashed-line{
- position: absolute;
- top: 0.77rem;
- left: 0rem;
- width: 2rem;
- height: 100%;
-
- background-image: linear-gradient(rgb(255, 255, 255) 43%, rgba(255, 255, 255, 0) 0%);
- background-position: left;
- background-size: 0.13rem 0.9rem;
- background-repeat: repeat-y;
- overflow: visible;
- z-index: 10 !important;
-}
+ .events-container {
+ padding-left: 1rem !important;
+ padding-bottom: 0 !important;
+ }
-.event-day {
- position: relative;
- padding-bottom: 0.5rem !important;
- padding-top: 0.5rem !important;
- padding-left: 0rem !important;
- z-index: 12;
-}
+ .dashed-line{
+ position: absolute;
+ top: 0.77rem;
+ left: 0;
+ width: 2rem;
+ height: 100%;
+ background-image: linear-gradient(rgb(255, 255, 255) 43%, rgba(255, 255, 255, 0) 0%);
+ background-position: left;
+ background-size: 0.13rem 0.9rem;
+ background-repeat: repeat-y;
+ overflow: visible;
+ z-index: 10 !important;
+ }
-ion-card-header {
- padding-top: 0px;
- padding-left: 1.2rem;
- padding-bottom: 0px;
-}
+ .event-day {
+ position: relative;
+ padding-bottom: 0.5rem !important;
+ padding-top: 0.5rem !important;
+ padding-left: 0 !important;
+ z-index: 12;
+ }
-ion-card-content {
- padding-left: 2.3rem;
-}
+ ion-card-header {
+ padding-top: 0;
+ padding-left: 1.2rem;
+ padding-bottom: 0;
+ }
-.circle-top-left {
- position: absolute;
- top: 0.30rem;
- left: -0.18rem;
- width: 0.5rem;
- height: 0.5rem;
- background-color: var(--ion-color-dark-contrast);
- border-radius: 50%;
-}
+ ion-card-content {
+ padding-left: 2.3rem;
+ }
-.card-labels {
- margin-right: 0.6rem;
-}
+ .circle-top-left {
+ position: absolute;
+ top: 0.30rem;
+ left: -0.18rem;
+ width: 0.5rem;
+ height: 0.5rem;
+ background-color: var(--ion-color-dark-contrast);
+ border-radius: 50%;
+ }
-.card-labels-icons {
- margin-right: 0.3rem;
-}
+ .card-labels {
+ margin-right: 0.6rem;
+ }
+ .card-labels-icons {
+ margin-right: 0.3rem;
+ }
+
+ .light-font-color {
+ color: var(--app-font-color-for-dark-background-from-cms) !important;
+ }
+
+ .dark-font-color {
+ color: var(--app-font-color-for-light-background-from-cms) !important;
+ }
-.light-font-color{
- color: var(--app-font-color-for-dark-background-from-cms) !important;
}
-.dark-font-color{
- color: var(--app-font-color-for-light-background-from-cms) !important;
+.next-events-slider-style {
+ display: block;
+
+ ion-card {
+ scroll-snap-align: center;
+ }
+
+ ion-card.slider-theme-color {
+ box-shadow: var(--app-border-no-box-shadow);
+ //border: var(--app-border-width-7) solid var(--app-border-color-primary);
+ background-color: var(--ion-color-tertiary);
+ }
+
+ ion-card-content {
+ padding: 0.7rem 0;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .empty-container {
+ padding-left: 1rem !important;
+ padding-bottom: 0 !important;
+ }
+
+ .events-container {
+ padding: .5rem 0 0;
+ display: grid;
+ gap: 1rem;
+ grid-auto-flow: column;
+ grid-template-columns: 10px;
+ grid-auto-columns: 85%;
+ overflow-x: auto;
+ scrollbar-width: none;
+ scroll-snap-type: x mandatory;
+ overscroll-behavior-x: contain;
+
+ &::-webkit-scrollbar {
+ display: none;
+ }
+
+ &::before,
+ &::after {
+ content: '';
+ width: 10px;
+ }
+
+ .event-day-hour {
+ display: flex;
+ flex-direction: row;
+ border-left-width: 4px;
+ border-left-style: solid;
+ align-items: center;
+ flex-wrap: nowrap;
+
+ .hour {
+ padding-left: 1rem;
+ display: block;
+ }
+
+ .day {
+ padding-left: 1rem;
+ display: block;
+
+ ion-text {
+ display: block;
+ }
+ }
+ }
+ }
+
+ .card-labels {
+ margin-right: 0.6rem;
+ }
+
+ .card-labels-icons {
+ margin-right: 0.3rem;
+ }
+
+ .event-label {
+ padding: 1rem 1rem 0;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ }
+
+ .event-additional {
+ display: flex;
+ padding: 0.2rem 0.5rem 0.2rem 2rem;
+ justify-content: flex-start;
+ flex-wrap: wrap;
+ flex-grow: 2;
+ align-items: center;
+
+ ion-row:last-child {
+ margin-right: 0;
+ }
+ }
+
+ .slider-font-color{
+ color: var(--app-font-fix-light-color) !important;
+ }
+
+ .light-font-color {
+ color: var(--app-font-color-for-dark-background-from-cms) !important;
+ }
+
+ .dark-font-color {
+ color: var(--app-font-color-for-light-background-from-cms) !important;
+ }
+
}