@saooti/octopus-sdk 37.0.42 → 37.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "37.0.42",
3
+ "version": "37.0.44",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -23,9 +23,9 @@
23
23
  "@tiptap/vue-3": "^2.1.11",
24
24
  "@vue/cli": "^5.0.8",
25
25
  "@vue/compat": "^3.3.4",
26
- "@vuepic/vue-datepicker": "^6.1.0",
26
+ "@vuepic/vue-datepicker": "^7.0.0",
27
27
  "autoprefixer": "^10.4.16",
28
- "axios": "^1.5.0",
28
+ "axios": "^1.5.1",
29
29
  "dayjs": "^1.11.10",
30
30
  "eslint-config-prettier": "^9.0.0",
31
31
  "eslint-plugin-prettier": "^5.0.0",
@@ -37,29 +37,29 @@
37
37
  "qrcode.vue": "^3.4.1",
38
38
  "sass": "^1.68.0",
39
39
  "sonarqube-scanner": "^3.1.0",
40
- "swiper": "^10.3.0",
40
+ "swiper": "^10.3.1",
41
41
  "video.js": "^7.21.5",
42
42
  "videojs-contrib-quality-levels": "^2.2.1",
43
43
  "videojs-hls-quality-selector": "^1.1.4",
44
44
  "vite": "^4.4.9",
45
45
  "vue": "^3.3.4",
46
- "vue-i18n": "^9.4.1",
46
+ "vue-i18n": "^9.5.0",
47
47
  "vue-recaptcha": "^2.0.3",
48
- "vue-router": "^4.2.4",
48
+ "vue-router": "^4.2.5",
49
49
  "vue-select": "^4.0.0-beta.6",
50
50
  "vue3-lazyload": "^0.3.8",
51
51
  "vue3-swatches": "^1.2.3"
52
52
  },
53
53
  "devDependencies": {
54
- "@types/videojs-contrib-quality-levels": "^2.0.1",
55
- "@types/videojs-hls-quality-selector": "^1.1.0",
56
- "@types/vue-select": "^3.16.2",
57
- "@typescript-eslint/eslint-plugin": "^6.7.2",
58
- "@typescript-eslint/parser": "^6.7.2",
54
+ "@types/videojs-contrib-quality-levels": "^2.0.2",
55
+ "@types/videojs-hls-quality-selector": "^1.1.1",
56
+ "@types/vue-select": "^3.16.3",
57
+ "@typescript-eslint/eslint-plugin": "^6.7.3",
58
+ "@typescript-eslint/parser": "^6.7.3",
59
59
  "@vitejs/plugin-vue": "^4.3.4",
60
60
  "@vue/compiler-sfc": "^3.3.4",
61
- "@vue/eslint-config-typescript": "^11.0.3",
62
- "eslint": "^8.49.0",
61
+ "@vue/eslint-config-typescript": "^12.0.0",
62
+ "eslint": "^8.50.0",
63
63
  "eslint-plugin-vue": "^9.15.1",
64
64
  "typescript": "^5.1.6"
65
65
  },
@@ -257,7 +257,7 @@ export default defineComponent({
257
257
  });
258
258
  this.saveOrganisation = this.organisation;
259
259
  if (0 === this.rubriquageData.length) return;
260
-
260
+
261
261
  if (initArrayFilter && this.rubriquageData[0].rubriquageId) {
262
262
  this.arrayFilter.push({
263
263
  rubriquageId: this.rubriquageData[0].rubriquageId,
@@ -265,18 +265,20 @@ export default defineComponent({
265
265
  nameRubriquage: this.rubriquageData[0].title,
266
266
  nameRubrique: "",
267
267
  });
268
- }else{
268
+ } else {
269
269
  const arrayFilterToUpdate = [];
270
- for(const filter of this.arrayFilter){
271
- const rubriquageExist = this.rubriquageData.find( (element) => element.rubriquageId === filter.rubriquageId);
272
- if(rubriquageExist){
270
+ for (const filter of this.arrayFilter) {
271
+ const rubriquageExist = this.rubriquageData.find(
272
+ (element) => element.rubriquageId === filter.rubriquageId,
273
+ );
274
+ if (rubriquageExist) {
273
275
  arrayFilterToUpdate.push(filter);
274
276
  }
275
277
  }
276
- if(arrayFilterToUpdate.length !== this.arrayFilter.length){
278
+ if (arrayFilterToUpdate.length !== this.arrayFilter.length) {
277
279
  this.arrayFilter = arrayFilterToUpdate;
280
+ this.$emit("warning");
278
281
  }
279
- this.$emit('warning');
280
282
  }
281
283
  },
282
284
  resetRubriqueFilter(): void {
@@ -17,7 +17,13 @@
17
17
  <button class="image-play-button" @click="playRadio">
18
18
  <div class="multiple-play-buttons-container">
19
19
  <div v-if="!playingRadio" :title="$t('Play')" class="saooti-play" />
20
- <div v-else class="bloc-paddle" :class="playingRadio && 'PLAYING' === playerStatus ? 'play-animation' : ''">
20
+ <div
21
+ v-else
22
+ class="bloc-paddle"
23
+ :class="
24
+ playingRadio && 'PLAYING' === playerStatus ? 'play-animation' : ''
25
+ "
26
+ >
21
27
  <span class="paddle1" />
22
28
  <span class="paddle2" />
23
29
  <span class="paddle3" />
@@ -28,10 +28,10 @@
28
28
  <div v-if="isRecordedInLive" class="live-image-status recording-bg">
29
29
  {{ $t("Recorded in live") }}
30
30
  </div>
31
- <PodcastPlayButton
31
+ <PodcastPlayButton
32
32
  :podcast="podcast"
33
- :hidePlay="hidePlay"
34
- :fetchConference="fetchConference"
33
+ :hide-play="hidePlay"
34
+ :fetch-conference="fetchConference"
35
35
  />
36
36
  <div
37
37
  v-if="displayDescription && isMobile"
@@ -52,8 +52,8 @@ import imageProxy from "../../mixins/imageProxy";
52
52
  import { defineComponent } from "vue";
53
53
  export default defineComponent({
54
54
  name: "PodcastImage",
55
- components:{
56
- PodcastPlayButton
55
+ components: {
56
+ PodcastPlayButton,
57
57
  },
58
58
  mixins: [imageProxy],
59
59
  props: {
@@ -94,26 +94,25 @@ export default defineComponent({
94
94
  );
95
95
  },
96
96
  statusText(): string {
97
- if (!this.fetchConference) return '';
97
+ if (!this.fetchConference) return "";
98
98
  switch (this.fetchConference.status) {
99
- case 'PLANNED':
100
- return this.$t('live in few time');
101
- case 'PENDING':
102
- if (this.isAnimatorLive) return this.$t('Open studio');
103
- return this.$t('live upcoming');
104
- case 'RECORDING':
105
- return this.$t('In live');
106
- case 'DEBRIEFING':
107
- /* if (!this.isAnimatorLive) return ''; */
108
- if ('READY_TO_RECORD' === this.podcast.processingStatus)
109
- return this.$t('Not recording');
110
- return this.$t('Debriefing');
111
- case 'ERROR':
112
- return this.$t('In error');
113
- case 'PUBLISHING':
114
- return this.$t('Publishing');
99
+ case "PLANNED":
100
+ return this.$t("live in few time");
101
+ case "PENDING":
102
+ if (this.isAnimatorLive) return this.$t("Open studio");
103
+ return this.$t("live upcoming");
104
+ case "RECORDING":
105
+ return this.$t("In live");
106
+ case "DEBRIEFING":
107
+ if ("READY_TO_RECORD" === this.podcast.processingStatus)
108
+ return this.$t("Not recording");
109
+ return this.$t("Debriefing");
110
+ case "ERROR":
111
+ return this.$t("In error");
112
+ case "PUBLISHING":
113
+ return this.$t("Publishing");
115
114
  default:
116
- return '';
115
+ return "";
117
116
  }
118
117
  },
119
118
  },
@@ -7,7 +7,9 @@
7
7
  >
8
8
  <PodcastImage
9
9
  :podcast="podcast"
10
- :hide-play="hoverDesc && 0 !== description.length && podcastItemDescription"
10
+ :hide-play="
11
+ hoverDesc && 0 !== description.length && podcastItemDescription
12
+ "
11
13
  :display-description="0 !== description.length && podcastItemDescription"
12
14
  :arrow-direction="arrowDirection"
13
15
  :fetch-conference="fetchConference"
@@ -185,7 +185,7 @@ export default defineComponent({
185
185
  ? this.authProfile?.userId
186
186
  : undefined,
187
187
  includeStatus: ["READY", "PROCESSING"],
188
- withVideo: this.withVideo
188
+ withVideo: this.withVideo,
189
189
  };
190
190
  try {
191
191
  const data = await octopusApi.fetchDataWithParams<{
@@ -1,21 +1,25 @@
1
1
  <template>
2
- <button
2
+ <button
3
3
  v-if="!hidePlay || recordingLive"
4
4
  class="image-play-button"
5
5
  :class="classicPodcastPlay ? '' : 'transparent-background'"
6
- @mouseenter="hoverType='audio'"
7
- @mouseleave="hoverType=''"
6
+ @mouseenter="hoverType = 'audio'"
7
+ @mouseleave="hoverType = ''"
8
8
  @click="play(false)"
9
9
  >
10
10
  <div
11
11
  class="multiple-play-buttons-container"
12
12
  :class="[
13
- hoverType ? 'hover-type-'+hoverType : '',
13
+ hoverType ? 'hover-type-' + hoverType : '',
14
14
  isVideoPodcast ? 'has-video' : '',
15
15
  ]"
16
16
  >
17
17
  <template v-if="!isLiveToBeRecorded">
18
- <div v-if="!playingPodcast || (playingPodcast && playerVideo)" :title="$t('Play')" class="saooti-play me-1" />
18
+ <div
19
+ v-if="!playingPodcast || (playingPodcast && playerVideo)"
20
+ :title="$t('Play')"
21
+ class="saooti-play me-1"
22
+ />
19
23
  <div
20
24
  v-if="playingPodcast"
21
25
  :class="'PLAYING' === playerStatus ? 'play-animation' : ''"
@@ -29,11 +33,11 @@
29
33
  v-if="isVideoPodcast && !playerVideo"
30
34
  :title="$t('Video')"
31
35
  class="btn-transparent d-flex align-items-center saooti-play-video"
32
- @mouseenter="hoverType='video'"
33
- @mouseleave="hoverType='audio'"
36
+ @mouseenter="hoverType = 'video'"
37
+ @mouseleave="hoverType = 'audio'"
34
38
  @click.stop="play(true)"
35
39
  />
36
- <div
40
+ <div
37
41
  v-if="!classicPodcastPlay"
38
42
  class="special-icon-play-button"
39
43
  :class="iconName"
@@ -42,7 +46,12 @@
42
46
  {{ durationString }}
43
47
  </div>
44
48
  </template>
45
- <div v-else :title="textVisible" class="big-icon-error" :class="iconName" />
49
+ <div
50
+ v-else
51
+ :title="textVisible"
52
+ class="big-icon-error"
53
+ :class="iconName"
54
+ />
46
55
  </div>
47
56
  <div v-if="!classicPodcastPlay" class="live-image-status bg-dark">
48
57
  {{ textVisible }}
@@ -81,35 +90,50 @@ export default defineComponent({
81
90
  ]),
82
91
  isVideoPodcast(): boolean {
83
92
  return (
84
- (this.fetchConference?.videoProfile?.includes("video_") && "READY_TO_RECORD" === this.podcast.processingStatus) ||
93
+ (this.fetchConference?.videoProfile?.includes("video_") &&
94
+ "READY_TO_RECORD" === this.podcast.processingStatus) ||
85
95
  undefined !== this.podcast.video?.videoId
86
96
  );
87
97
  },
88
- playingLive(): boolean{
89
- return undefined!==this.fetchConference && "null" !== this.fetchConference.toString() &&
90
- this.playerLive?.conferenceId === this.fetchConference.conferenceId;
98
+ playingLive(): boolean {
99
+ return (
100
+ undefined !== this.fetchConference &&
101
+ "null" !== this.fetchConference.toString() &&
102
+ this.playerLive?.conferenceId === this.fetchConference.conferenceId
103
+ );
91
104
  },
92
105
  playingPodcast() {
93
- return this.playerPodcast?.podcastId === this.podcast.podcastId || this.playingLive;
106
+ return (
107
+ this.playerPodcast?.podcastId === this.podcast.podcastId ||
108
+ this.playingLive
109
+ );
94
110
  },
95
111
  isLiveToBeRecorded(): boolean {
96
112
  return undefined === this.fetchConference && this.isLiveReadyToRecord;
97
113
  },
98
114
  isLiveReadyToRecord(): boolean {
99
- return undefined !== this.podcast?.conferenceId && 0 !== this.podcast.conferenceId &&
100
- "READY_TO_RECORD" === this.podcast.processingStatus;
115
+ return (
116
+ undefined !== this.podcast?.conferenceId &&
117
+ 0 !== this.podcast.conferenceId &&
118
+ "READY_TO_RECORD" === this.podcast.processingStatus
119
+ );
101
120
  },
102
- isLiveValidAndVisible():boolean{
103
- return undefined !== this.podcast && false !== this.podcast.valid &&
104
- undefined !== this.podcast.availability.visibility && this.podcast.availability.visibility;
121
+ isLiveValidAndVisible(): boolean {
122
+ return (
123
+ undefined !== this.podcast &&
124
+ false !== this.podcast.valid &&
125
+ undefined !== this.podcast.availability.visibility &&
126
+ this.podcast.availability.visibility
127
+ );
105
128
  },
106
129
  classicPodcastPlay(): boolean {
107
130
  return (
108
131
  this.isLiveValidAndVisible &&
109
132
  !this.isLiveToBeRecorded &&
110
133
  ("READY_TO_RECORD" === this.podcast.processingStatus ||
111
- "READY" === this.podcast.processingStatus ||
112
- ("PROCESSING" === this.podcast.processingStatus && !(state.generalParameters.authenticated as boolean)))
134
+ "READY" === this.podcast.processingStatus ||
135
+ ("PROCESSING" === this.podcast.processingStatus &&
136
+ !(state.generalParameters.authenticated as boolean)))
113
137
  );
114
138
  },
115
139
  iconName(): string {
@@ -219,7 +243,7 @@ export default defineComponent({
219
243
  .big-icon-error {
220
244
  font-size: 1.5rem;
221
245
  }
222
- .special-icon-play-button{
246
+ .special-icon-play-button {
223
247
  width: 30px;
224
248
  height: 30px;
225
249
  background-color: #ffd663;
@@ -234,7 +258,7 @@ export default defineComponent({
234
258
  align-items: center;
235
259
  justify-content: center;
236
260
  }
237
- .has-video .special-icon-play-button{
261
+ .has-video .special-icon-play-button {
238
262
  left: 7.4rem;
239
263
  }
240
264
  }
@@ -220,7 +220,8 @@ export default defineComponent({
220
220
  if ("video" === this.iFrameModel) {
221
221
  return (
222
222
  "https://www.ultimedia.com/deliver/generic/iframe/mdtk/01009833/zone/1/showtitle/1/src/" +
223
- this.podcast?.video?.videoId + "/sound/true"
223
+ this.podcast?.video?.videoId +
224
+ "/sound/true"
224
225
  );
225
226
  }
226
227
  let url = [""];
@@ -49,7 +49,14 @@ export default defineComponent({
49
49
  useTeleport: { default: false, type: Boolean },
50
50
  templateClass: { default: undefined, type: String },
51
51
  readonly: { default: false, type: Boolean },
52
- maxTime:{default: null, type: Object as () => { hours?: number | string; minutes?: number | string; seconds?: number | string }}
52
+ maxTime: {
53
+ default: null,
54
+ type: Object as () => {
55
+ hours?: number | string;
56
+ minutes?: number | string;
57
+ seconds?: number | string;
58
+ },
59
+ },
53
60
  },
54
61
 
55
62
  emits: ["updateDate", "update:date"],
@@ -119,14 +119,15 @@ export default defineComponent({
119
119
  }
120
120
  const rectElement = (e.target as HTMLElement).getBoundingClientRect();
121
121
  (this.$refs.popover as HTMLElement).style.display = "block";
122
- if(this.leftPos){
123
- this.posX = rectElement.right -
122
+ if (this.leftPos) {
123
+ this.posX =
124
+ rectElement.right -
124
125
  parentRight -
125
126
  (this.$refs.popover as HTMLElement).clientWidth;
126
- }else{
127
+ } else {
127
128
  this.posX = rectElement.left - parentLeft;
128
129
  }
129
- this.posX = Math.max(0, this.posX);
130
+ this.posX = Math.max(0, this.posX);
130
131
  const yPosParent = this.topPos ? rectElement.top : rectElement.bottom;
131
132
  const yGap = this.topPos
132
133
  ? -5 - (this.$refs.popover as HTMLElement).clientHeight
@@ -1,7 +1,11 @@
1
1
  <template>
2
- <div :id="idModal" class="octopus-modal" :class="onlyHeader? 'octopus-only-header-modal':''">
3
- <div class="octopus-modal-backdrop"/>
4
- <div class="octopus-modal-dialog" >
2
+ <div
3
+ :id="idModal"
4
+ class="octopus-modal"
5
+ :class="onlyHeader ? 'octopus-only-header-modal' : ''"
6
+ >
7
+ <div class="octopus-modal-backdrop" />
8
+ <div class="octopus-modal-dialog">
5
9
  <div class="octopus-modal-content">
6
10
  <div class="octopus-modal-header">
7
11
  <h5 cclass="octopus-modal-title">
@@ -11,8 +15,8 @@
11
15
  <button
12
16
  v-if="canBeReduced"
13
17
  class="btn-transparent text-light"
14
- :class="onlyHeader? 'saooti-down':'saooti-up'"
15
- :title="onlyHeader? $t('Enlarge'):$t('Reduce')"
18
+ :class="onlyHeader ? 'saooti-down' : 'saooti-up'"
19
+ :title="onlyHeader ? $t('Enlarge') : $t('Reduce')"
16
20
  @click="onlyHeader = !onlyHeader"
17
21
  />
18
22
  <button
@@ -274,7 +274,7 @@ export default defineComponent({
274
274
  ${this.emissionName}${this.description}`,
275
275
  ];
276
276
  html.push(
277
- `</table>
277
+ `</table>
278
278
  <table width='100%' style="width:100%;background:#f3f3f3;font-family: Arial, sans-serif;font-size: 12px;line-height: 20px;">
279
279
  <tr style="font-family: Arial, sans-serif;font-size: 12px;line-height: 20px;background: #f3f3f3;vertical-align: middle;padding: 15px 10px;display: flex; align-items:center; flex-wrap:wrap">
280
280
  <td><a href="${this.shareUrl}">
@@ -283,7 +283,7 @@ export default defineComponent({
283
283
  <td style="margin-left:10px"><a style="color: #000;text-decoration: none; margin-right:8px" href="${this.shareUrl}">${this.shareText}</a></td>
284
284
  ${this.articleHtml}
285
285
  </tr>
286
- </table>${this.participantsName}`
286
+ </table>${this.participantsName}`,
287
287
  );
288
288
  return html.join("");
289
289
  },
@@ -26,12 +26,12 @@ import { defineComponent } from "vue";
26
26
  export default defineComponent({
27
27
  name: "PlayerVideo",
28
28
  components: {
29
- SnackBar
29
+ SnackBar,
30
30
  },
31
31
 
32
32
  computed: {
33
33
  ...mapState(usePlayerStore, ["playerPodcast", "playerVideo"]),
34
- videoId(): string|undefined{
34
+ videoId(): string | undefined {
35
35
  return this.playerPodcast?.video?.videoId;
36
36
  },
37
37
  srcVideo(): string {
@@ -51,12 +51,12 @@ export default defineComponent({
51
51
  }, */
52
52
  },
53
53
  mounted() {
54
- if(undefined===this.videoId){
54
+ if (undefined === this.videoId) {
55
55
  (this.$refs.snackbar as InstanceType<typeof SnackBar>).open(
56
56
  this.$t("Podcast play error"),
57
57
  );
58
58
  }
59
-
59
+
60
60
  /* this.goFullScreen(); */
61
61
  },
62
62
  methods: {
@@ -25,11 +25,11 @@ if (!videojs.getPlugin("hlsQualitySelector")) {
25
25
  import { defineComponent } from "vue";
26
26
  export default defineComponent({
27
27
  name: "PlayerVideoHls",
28
+ mixins: [playerLogicProgress],
28
29
 
29
30
  props: {
30
31
  hlsUrl: { default: "", type: String },
31
32
  },
32
- mixins: [playerLogicProgress],
33
33
  emits: ["changeValid"],
34
34
  data() {
35
35
  return {
@@ -90,11 +90,11 @@ export default defineComponent({
90
90
  },
91
91
 
92
92
  methods: {
93
- ...mapActions(usePlayerStore, ["playerUpdateSeekTime"]),
93
+ ...mapActions(usePlayerStore, ["playerUpdateSeekTime"]),
94
94
  definedStalledTimeout() {
95
95
  this.isPaused = false;
96
96
  this.stalledTimout = setTimeout(() => {
97
- if(this.isPaused){
97
+ if (this.isPaused) {
98
98
  return;
99
99
  }
100
100
  this.videoClean();
@@ -125,19 +125,19 @@ export default defineComponent({
125
125
  this.errorPlay = this.$t("Podcast play error");
126
126
  }
127
127
  });
128
- this.player.on('seeking', () => {
129
- this.playerUpdateSeekTime(this.player?.currentTime()??0);
128
+ this.player.on("seeking", () => {
129
+ this.playerUpdateSeekTime(this.player?.currentTime() ?? 0);
130
130
  });
131
- this.player.on('pause', () => {
132
- this.isPaused=true;
131
+ this.player.on("pause", () => {
132
+ this.isPaused = true;
133
133
  });
134
134
  this.player.on("timeupdate", () => {
135
135
  clearTimeout(this.stalledTimout);
136
136
  this.definedStalledTimeout();
137
137
  this.onTimeUpdateVideo();
138
138
  });
139
- this.player.on('seeking', () => {
140
- this.playerUpdateSeekTime(this.player?.currentTime()??0);
139
+ this.player.on("seeking", () => {
140
+ this.playerUpdateSeekTime(this.player?.currentTime() ?? 0);
141
141
  });
142
142
  },
143
143
  async playLiveIos(): Promise<void> {
@@ -164,7 +164,7 @@ export default defineComponent({
164
164
  this.onTimeUpdateVideo();
165
165
  };
166
166
  this.videoElement.onpause = async () => {
167
- this.isPaused=true;
167
+ this.isPaused = true;
168
168
  };
169
169
  this.videoElement.onseeking = async () => {
170
170
  this.playerUpdateSeekTime(this.videoElement.currentTime);
@@ -200,11 +200,14 @@ export default defineComponent({
200
200
  this.endListeningProgress();
201
201
  },
202
202
  onTimeUpdateVideo(): void {
203
- if (!this.downloadId) { return;}
204
- const currentTime = this.player?.currentTime() ?? this.videoElement.currentTime;
203
+ if (!this.downloadId) {
204
+ return;
205
+ }
206
+ const currentTime =
207
+ this.player?.currentTime() ?? this.videoElement.currentTime;
205
208
  this.onTimeUpdateProgress(currentTime);
206
209
  },
207
- },
210
+ },
208
211
  });
209
212
  </script>
210
213
 
@@ -100,9 +100,9 @@ export default defineComponent({
100
100
  organisation(): string | undefined {
101
101
  return this.organisationId ? this.organisationId : this.filterOrgaId;
102
102
  },
103
- withVideo(): boolean|undefined{
104
- return false===this.onlyVideo ? undefined : true;
105
- }
103
+ withVideo(): boolean | undefined {
104
+ return false === this.onlyVideo ? undefined : true;
105
+ },
106
106
  },
107
107
  watch: {
108
108
  organisationId(): void {
@@ -42,7 +42,7 @@ export const useAuthStore = defineStore("AuthStore", {
42
42
  isGarRole(): string | undefined {
43
43
  return this.authProfile?.attributes?.["GAR"] as
44
44
  | string
45
- | undefined; /* return "ELEVE"; */ /*CHEF_ETABLISSEMENT, ENSEIGNANT, ELEVE, undefined */
45
+ | undefined; /*CHEF_ETABLISSEMENT, ENSEIGNANT, ELEVE, undefined */
46
46
  },
47
47
  isGarStudent(): boolean {
48
48
  return "ELEVE" === this.isGarRole;