@saooti/octopus-sdk 41.0.14-SNAPSHOT → 41.0.14

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.
Files changed (66) hide show
  1. package/eslint.config.mjs +5 -3
  2. package/index.ts +7 -1
  3. package/package.json +3 -2
  4. package/plateform.conf +1 -1
  5. package/src/App.vue +3 -7
  6. package/src/api/classicApi.ts +1 -1
  7. package/src/components/composable/player/usePlayerLive.ts +2 -2
  8. package/src/components/composable/player/usePlayerLogic.ts +2 -1
  9. package/src/components/composable/radio/usefetchRadioData.ts +29 -12
  10. package/src/components/composable/route/useSimplePageParam.ts +6 -1
  11. package/src/components/display/categories/CategoryChooser.vue +4 -0
  12. package/src/components/display/comments/CommentList.vue +1 -1
  13. package/src/components/display/emission/EmissionList.vue +2 -1
  14. package/src/components/display/emission/EmissionPresentationItem.vue +14 -6
  15. package/src/components/display/filter/AdvancedSearch.vue +2 -2
  16. package/src/components/display/filter/DateFilter.vue +15 -2
  17. package/src/components/display/live/RadioCurrently.vue +2 -5
  18. package/src/components/display/organisation/OrganisationChooserLight.vue +34 -36
  19. package/src/components/display/podcasts/PodcastPlayButton.vue +6 -1
  20. package/src/components/display/rubriques/RubriqueChooser.vue +24 -2
  21. package/src/components/display/rubriques/RubriqueList.vue +18 -0
  22. package/src/components/display/sharing/PlayerParameters.vue +0 -8
  23. package/src/components/display/sharing/SharePlayer.vue +0 -5
  24. package/src/components/display/sharing/SubscribeButtons.vue +4 -2
  25. package/src/components/form/ClassicCheckbox.vue +29 -4
  26. package/src/components/form/ClassicInputText.vue +14 -6
  27. package/src/components/form/ClassicMultiselect.vue +35 -7
  28. package/src/components/misc/ClassicAccordion.vue +4 -4
  29. package/src/components/misc/ClassicLazy.vue +25 -14
  30. package/src/components/misc/ClassicNav.vue +3 -0
  31. package/src/components/misc/ClassicSpinner.vue +1 -1
  32. package/src/components/misc/FooterSection.vue +18 -20
  33. package/src/components/misc/HomeDropdown.vue +3 -110
  34. package/src/components/misc/MobileMenu.vue +59 -64
  35. package/src/components/misc/TopBar.vue +2 -10
  36. package/src/components/misc/TopBarMainContent.vue +8 -12
  37. package/src/components/misc/UserButtonContent.vue +159 -0
  38. package/src/components/misc/modal/ClassicModal.vue +4 -0
  39. package/src/components/misc/player/PlayerCompact.vue +1 -0
  40. package/src/components/misc/player/PlayerComponent.vue +1 -0
  41. package/src/components/misc/player/elements/PlayerImage.vue +0 -1
  42. package/src/components/misc/player/elements/PlayerTitle.vue +3 -3
  43. package/src/components/misc/player/radio/RadioHistory.vue +3 -2
  44. package/src/components/misc/player/video/PlayerVideo.vue +2 -2
  45. package/src/components/pages/HomePage.vue +5 -4
  46. package/src/components/pages/PageLogout.vue +1 -6
  47. package/src/components/pages/PodcastPage.vue +0 -1
  48. package/src/components/pages/PodcastsPage.vue +1 -1
  49. package/src/components/pages/VideoPage.vue +5 -2
  50. package/src/helper/equals.ts +26 -0
  51. package/src/locale/de.ts +6 -5
  52. package/src/locale/en.ts +6 -5
  53. package/src/locale/es.ts +6 -5
  54. package/src/locale/fr.ts +6 -5
  55. package/src/locale/it.ts +6 -5
  56. package/src/locale/sl.ts +6 -5
  57. package/src/router/router.ts +10 -74
  58. package/src/router/utils.ts +112 -0
  59. package/src/stores/AuthStore.ts +5 -0
  60. package/src/stores/FilterStore.ts +126 -71
  61. package/src/stores/PlayerStore.ts +11 -1
  62. package/src/stores/class/conference/conference.ts +2 -0
  63. package/src/stores/class/general/player.ts +2 -2
  64. package/src/style/_variables.scss +6 -0
  65. package/src/style/general.scss +18 -1
  66. package/src/helper/radio/radioHelper.ts +0 -15
@@ -36,12 +36,6 @@
36
36
  </div>
37
37
  </div>
38
38
  <ChooseEpisodesNumber v-else :episodes-number="episodesNumber" @update-number="emit('update:episodesNumber', $event)"/>
39
- <ClassicCheckbox
40
- :text-init="proceedReading"
41
- id-checkbox="proceed-reading-checkbox"
42
- :label="t('Proceed reading')"
43
- @update:text-init="emit('update:proceedReading', $event)"
44
- />
45
39
  </template>
46
40
  <ClassicCheckbox
47
41
  v-if="displayIsVisible"
@@ -104,7 +98,6 @@ const props = defineProps({
104
98
  displayArticleParam: { default: false, type: Boolean },
105
99
  displayIsVisible: { default: false, type: Boolean },
106
100
  displayInsertCode: { default: false, type: Boolean },
107
- proceedReading: { default: true, type: Boolean },
108
101
  displayArticle: { default: true, type: Boolean },
109
102
  displayTranscript: { default: true, type: Boolean },
110
103
  displayWave: { default: true, type: Boolean },
@@ -118,7 +111,6 @@ const props = defineProps({
118
111
  //Emits
119
112
  const emit = defineEmits([
120
113
  "episodeChoiceDisplay",
121
- "update:proceedReading",
122
114
  "update:isVisible",
123
115
  "update:episodesNumber",
124
116
  "update:displayArticle",
@@ -44,7 +44,6 @@
44
44
  v-model:display-article="displayArticle"
45
45
  v-model:display-transcript="displayTranscript"
46
46
  v-model:display-wave="displayWave"
47
- v-model:proceed-reading="proceedReading"
48
47
  v-model:is-visible="isVisible"
49
48
  v-model:player-auto-play="playerAutoPlay"
50
49
  v-model:episodes-number="episodesNumber"
@@ -125,7 +124,6 @@ const iFrameModel = ref("default");
125
124
  const isShareModal = ref(false);
126
125
  const color = ref("#40a372");
127
126
  const theme = ref("#000000");
128
- const proceedReading = ref(true);
129
127
  const episodeChoiceDisplay = ref("number");
130
128
  const episodesNumber = ref(3);
131
129
  const isVisible = ref(false);
@@ -341,9 +339,6 @@ function addUrlParameters(url: Array<string>) {
341
339
  url.push(
342
340
  `&color=${color.value.substring(1)}&theme=${theme.value.substring(1)}`,
343
341
  );
344
- if (!proceedReading.value) {
345
- url.push("&proceed=false");
346
- }
347
342
  if (!displayArticle.value && displayArticleParam.value) {
348
343
  url.push("&article=false");
349
344
  }
@@ -78,7 +78,7 @@ import RssIcon from "vue-material-design-icons/Rss.vue";
78
78
  import { useApiStore } from "../../../stores/ApiStore";
79
79
  import ClassicPopover from "../../misc/ClassicPopover.vue";
80
80
  import { Emission } from "@/stores/class/general/emission";
81
- import { computed, Ref, ref, useTemplateRef, watch } from "vue";
81
+ import { computed, onMounted, Ref, ref, useTemplateRef, watch } from "vue";
82
82
  import { useI18n } from "vue-i18n";
83
83
  type Link = {
84
84
  name: string;
@@ -204,7 +204,9 @@ const rssUrl = computed(() => {
204
204
 
205
205
 
206
206
  //Watch
207
- watch(()=>props.windowWidth, () =>resizeWindow(), {immediate: true});
207
+ watch(()=>props.windowWidth, () =>resizeWindow());
208
+
209
+ onMounted(()=>resizeWindow());
208
210
 
209
211
 
210
212
  //Methods
@@ -2,7 +2,7 @@
2
2
  <div class="d-flex flex-nowrap align-items-center octopus-form-item">
3
3
  <div :class="isSwitch ? 'octopus-form-switch me-2' : ''">
4
4
  <input
5
- :id="idCheckbox"
5
+ :id="computedIdCheckbox"
6
6
  :checked="textInit"
7
7
  type="checkbox"
8
8
  :disabled="isDisabled"
@@ -16,26 +16,35 @@
16
16
  v-if="isSwitch"
17
17
  class="slider btn-transparent"
18
18
  :title="label"
19
+ :disabled="isDisabled"
19
20
  @click="clickSlider"
20
21
  @keydown.space.prevent="clickSlider"
21
22
  />
22
23
  </div>
23
24
  <label
24
25
  class="c-hand"
25
- :class="[classLabel, displayLabel ? '' : 'd-none']"
26
- :for="idCheckbox"
27
- >{{ label }}</label
26
+ :class="[classLabel, displayLabel ? '' : 'd-none', isDisabled ? 'disabled' : '']"
27
+ :for="computedIdCheckbox"
28
28
  >
29
+ {{ label }}
30
+ </label>
29
31
  </div>
30
32
  </template>
31
33
 
32
34
  <script setup lang="ts">
35
+ import { computed, getCurrentInstance } from 'vue';
36
+
33
37
  //Props
34
38
  const props = defineProps({
39
+ /** The ID for the checkbox input */
35
40
  idCheckbox: { default: "", type: String },
41
+ /** The label to display with the checkbox */
36
42
  label: { default: "", type: String },
43
+ /** Disables input */
37
44
  isDisabled: { default: false, type: Boolean },
45
+ /** The value of the checkbox */
38
46
  textInit: { default: false, type: Boolean },
47
+ /** If true, displays a switch instead of a checkbox */
39
48
  isSwitch: { default: false, type: Boolean },
40
49
  displayLabel: { default: true, type: Boolean },
41
50
  classLabel: { default: "", type: String },
@@ -45,6 +54,11 @@ const props = defineProps({
45
54
  //Emits
46
55
  const emit = defineEmits(["update:textInit", "clickAction"]);
47
56
 
57
+ // Computed
58
+ const computedIdCheckbox = computed(() => {
59
+ return props.idCheckbox || 'checkbox-' + getCurrentInstance()?.uid;
60
+ });
61
+
48
62
  //Methods
49
63
  function emitClickAction(): void {
50
64
  emit("clickAction");
@@ -59,6 +73,12 @@ function clickSlider() {
59
73
 
60
74
  <style lang="scss">
61
75
  .octopus-app {
76
+
77
+ label.disabled {
78
+ color: var(--octopus-text-disabled);
79
+ cursor: default;
80
+ }
81
+
62
82
  .octopus-form-switch {
63
83
  position: relative;
64
84
  display: inline-block;
@@ -92,6 +112,11 @@ function clickSlider() {
92
112
  border-radius: 50%;
93
113
  }
94
114
 
115
+ .slider:disabled::before {
116
+ background-color: var(--octopus-text-disabled);
117
+ opacity: 0.6;
118
+ }
119
+
95
120
  input:checked + .slider {
96
121
  background-color: var(--octopus-primary);
97
122
  }
@@ -8,13 +8,14 @@
8
8
  <component
9
9
  :is="isWysiwyg? 'div': 'label'"
10
10
  :class="[classLabel, displayLabel ? '' : 'd-none']"
11
- :for="isWysiwyg ? '': inputId"
11
+ :for="isWysiwyg ? '': computedInputId"
12
12
  >{{ label }}
13
13
  <AsteriskIcon v-if="displayRequired" :size="10" class="ms-1 mb-2" :title="t('Mandatory input')"/>
14
14
  </component>
15
+ <slot name="afterTitle"/>
15
16
  <template v-if="popover">
16
17
  <button
17
- :id="'popover' + inputId"
18
+ :id="'popover' + computedInputId"
18
19
  :title="t('Help')"
19
20
  class="btn-transparent"
20
21
  >
@@ -22,7 +23,7 @@
22
23
  </button>
23
24
 
24
25
  <ClassicPopover
25
- :target="'popover' + inputId"
26
+ :target="'popover' + computedInputId"
26
27
  popover-class="popover-z-index"
27
28
  :relative-class="popoverRelativeClass"
28
29
  >
@@ -31,11 +32,13 @@
31
32
  <!-- eslint-enable -->
32
33
  </ClassicPopover>
33
34
  </template>
35
+ <slot name="afterHelp"/>
34
36
  </div>
37
+ <slot name="betweenTitleInput"/>
35
38
  <input
36
39
  v-if="!isWysiwyg && !isTextarea"
37
40
  v-show="showField"
38
- :id="inputId"
41
+ :id="computedInputId"
39
42
  ref="focusElement"
40
43
  v-model="textValue"
41
44
  :type="typeInput"
@@ -56,7 +59,7 @@
56
59
  <textarea
57
60
  v-else-if="isTextarea"
58
61
  v-show="showField"
59
- :id="inputId"
62
+ :id="computedInputId"
60
63
  ref="focusElement"
61
64
  v-model="textValue"
62
65
  :data-selenium="dataSelenium"
@@ -110,10 +113,11 @@
110
113
  </div>
111
114
  </div>
112
115
  </template>
116
+
113
117
  <script setup lang="ts">
114
118
  import AsteriskIcon from "vue-material-design-icons/Asterisk.vue";
115
119
  import HelpCircleIcon from "vue-material-design-icons/HelpCircle.vue";
116
- import { computed, defineAsyncComponent, onMounted, Ref, ref, useTemplateRef, watch } from "vue";
120
+ import { computed, defineAsyncComponent, onMounted, Ref, ref, useTemplateRef, watch, getCurrentInstance } from "vue";
117
121
  import { useI18n } from "vue-i18n";
118
122
  const ClassicPopover = defineAsyncComponent(
119
123
  () => import("../misc/ClassicPopover.vue"),
@@ -129,6 +133,7 @@ const ClassicEmojiPicker = defineAsyncComponent(
129
133
  const props = defineProps({
130
134
  inputId: { default: "", type: String },
131
135
  label: { default: "", type: String },
136
+ /** The input's value */
132
137
  textInit: { default: undefined, type: String },
133
138
  maxLength: { default: 0, type: Number },
134
139
  errorText: { default: "", type: String },
@@ -138,6 +143,7 @@ const props = defineProps({
138
143
  canBeNull: { default: false, type: Boolean },
139
144
  inputMaxLengthField: { default: undefined, type: Number },
140
145
  errorVariable: { default: true, type: Boolean },
146
+ /** Disable the text input */
141
147
  isDisable: { default: false, type: Boolean },
142
148
  indicText: { default: "", type: String },
143
149
  dataSelenium: { default: "", type: String },
@@ -168,6 +174,7 @@ const focusElementRef = useTemplateRef('focusElement');
168
174
  const { t } = useI18n();
169
175
 
170
176
  //Computed
177
+ const computedInputId = computed(() => props.inputId || 'input-' + getCurrentInstance()?.uid);
171
178
  const isError = computed(() => !valueTrimValid.value || !valueLengthValid.value || !valueRegexValid.value);
172
179
  const countValue = computed(() => {
173
180
  if (textValue.value) {
@@ -236,6 +243,7 @@ function addEmojiSelected(emoji: string) {
236
243
  textValue.value = (textValue.value ?? "") + emoji;
237
244
  }
238
245
  </script>
246
+
239
247
  <style lang="scss">
240
248
  .octopus-app .classic-input-text {
241
249
  .text-indic {
@@ -7,11 +7,31 @@
7
7
  }"
8
8
  :style="{ width: width, height: height }"
9
9
  >
10
- <label :class="displayLabel ? '' : 'd-none'" :for="id" class="form-label">{{
11
- label
12
- }}
13
- <AsteriskIcon v-if="displayRequired" :size="10" class="ms-1 mb-2" :title="t('Mandatory input')"/>
14
- </label>
10
+ <div class="d-flex align-items-center">
11
+ <label :class="displayLabel ? '' : 'd-none'" :for="id" class="form-label">{{
12
+ label
13
+ }}
14
+ <AsteriskIcon v-if="displayRequired" :size="10" class="ms-1 mb-2" :title="t('Mandatory input')"/>
15
+ </label>
16
+ <template v-if="popover">
17
+ <button
18
+ :id="'popover' + id"
19
+ :title="t('Help')"
20
+ class="btn-transparent"
21
+ >
22
+ <HelpCircleIcon :size="30" />
23
+ </button>
24
+ <ClassicPopover
25
+ :target="'popover' + id"
26
+ popover-class="popover-z-index"
27
+ :relative-class="popoverRelativeClass"
28
+ >
29
+ <!-- eslint-disable vue/no-v-html -->
30
+ <div v-html="popover" />
31
+ <!-- eslint-enable -->
32
+ </ClassicPopover>
33
+ </template>
34
+ </div>
15
35
  <vSelect
16
36
  v-model="optionSelected"
17
37
  :input-id="id"
@@ -77,12 +97,15 @@
77
97
  </template>
78
98
 
79
99
  <script setup lang="ts">
80
- import { computed, ref, Ref, watch } from "vue";
100
+ import { computed, defineAsyncComponent, ref, Ref, watch } from "vue";
81
101
  import { useI18n } from "vue-i18n";
82
102
  import AsteriskIcon from "vue-material-design-icons/Asterisk.vue";
83
103
  import ChevronDownIcon from "vue-material-design-icons/ChevronDown.vue";
84
104
  import vSelect from "vue-select";
85
-
105
+ import HelpCircleIcon from "vue-material-design-icons/HelpCircle.vue";
106
+ const ClassicPopover = defineAsyncComponent(
107
+ () => import("../misc/ClassicPopover.vue"),
108
+ );
86
109
 
87
110
  //Props
88
111
  const props = defineProps({
@@ -106,6 +129,8 @@ const props = defineProps({
106
129
  allowEmpty: { default: true, type: Boolean },
107
130
  textDanger :{ default: undefined, type: String },
108
131
  displayRequired: { default: false, type: Boolean },
132
+ popover: { default: undefined, type: String },
133
+ popoverRelativeClass: { default: undefined, type: String },
109
134
  })
110
135
 
111
136
  //Emits
@@ -214,6 +239,9 @@ defineExpose({
214
239
  height: 100%;
215
240
  }
216
241
 
242
+ .vs__search, .vs__search:focus{
243
+ border: var(--vs-selected-border-width) solid transparent;
244
+ }
217
245
  .vs__search:focus {
218
246
  min-width: 150px;
219
247
  }
@@ -20,11 +20,11 @@
20
20
  class="img-accordion"
21
21
  :src="imageUrl"
22
22
  aria-hidden="true"
23
- alt=""
24
-
23
+ alt=""
25
24
  />
26
- <span class="flex-grow-1">{{ title }}</span>
27
- <ChevronDownIcon :class="{ 'arrow-transform': isOpen }" />
25
+ <span>{{ title }}</span>
26
+ <slot name="afterTitle"/>
27
+ <ChevronDownIcon class="ms-auto" :class="{ 'arrow-transform': isOpen }" />
28
28
  </button>
29
29
  <div v-show="isOpen" class="body p-2">
30
30
  <slot />
@@ -4,9 +4,10 @@
4
4
  <slot v-else name="preview" />
5
5
  </div>
6
6
  </template>
7
+
7
8
  <script setup lang="ts">
8
9
  import { useIntersectionObserver } from "@vueuse/core";
9
- import { ref, nextTick, watch } from "vue";
10
+ import { ref, nextTick, watch, onMounted } from "vue";
10
11
 
11
12
  //Props
12
13
  const props = defineProps({
@@ -37,8 +38,8 @@ const { pause, resume } = useIntersectionObserver(
37
38
  if (isIntersecting) {
38
39
  // perhaps the user re-scrolled to a component that was set to unrender. In that case stop the unrendering timer
39
40
  clearTimeout(unrenderTimer);
40
- // if we're dealing underndering lets add a waiting period of 200ms before rendering. If a component enters the viewport and also leaves it within 200ms it will not render at all. This saves work and improves performance when user scrolls very fast
41
41
 
42
+ // if we're dealing underndering lets add a waiting period of 200ms before rendering. If a component enters the viewport and also leaves it within 200ms it will not render at all. This saves work and improves performance when user scrolls very fast
42
43
  renderTimer = setTimeout(
43
44
  () => {
44
45
  shouldRender.value = true;
@@ -46,6 +47,7 @@ const { pause, resume } = useIntersectionObserver(
46
47
  },
47
48
  props.unrender ? 200 : 0,
48
49
  );
50
+
49
51
  if (!props.unrender) {
50
52
  pause();
51
53
  }
@@ -64,18 +66,27 @@ const { pause, resume } = useIntersectionObserver(
64
66
  );
65
67
 
66
68
  //Logic
67
- setTimeout(() => {
68
- waitBeforeInit.value = false;
69
- }, props.initRenderDelay);
70
- if (props.renderOnIdle) {
71
- onIdle(() => {
72
- shouldRender.value = true;
73
- emit("isRender", true);
74
- if (!props.unrender) {
75
- pause();
76
- }
77
- });
78
- }
69
+ onMounted(() => {
70
+ if (props.initRenderDelay <= 0) {
71
+ // If there's no render delay, do not delay initialization
72
+ waitBeforeInit.value = false;
73
+ } else {
74
+ // Otherwise delay initialization
75
+ setTimeout(() => {
76
+ waitBeforeInit.value = false;
77
+ }, props.initRenderDelay);
78
+ }
79
+
80
+ if (props.renderOnIdle) {
81
+ onIdle(() => {
82
+ shouldRender.value = true;
83
+ emit("isRender", true);
84
+ if (!props.unrender) {
85
+ pause();
86
+ }
87
+ });
88
+ }
89
+ });
79
90
 
80
91
  //Watch
81
92
  watch(
@@ -1,3 +1,6 @@
1
+ <!--
2
+ Component to make a tab-based navigation
3
+ -->
1
4
  <template>
2
5
  <ul class="octopus-nav" :class="light ? 'light' : ''">
3
6
  <li
@@ -16,7 +16,7 @@ defineProps({
16
16
  --size-spinner: 3rem;
17
17
  --size-spinner-section: calc(var(--size-spinner) / 20);
18
18
  --half-size-spinner: calc(var(--size-spinner) / 2);
19
-
19
+
20
20
  color: #000000;
21
21
  display: inline-block;
22
22
  position: relative;
@@ -5,11 +5,17 @@
5
5
  role="contentinfo"
6
6
  class="d-flex align-items-center justify-content-between border-top mt-auto"
7
7
  >
8
- <div v-if="!state.generalParameters.podcastmaker" class="d-flex flex-column px-1">
8
+ <div
9
+ v-if="!state.generalParameters.podcastmaker"
10
+ class="d-flex flex-column px-1"
11
+ >
9
12
  <div class="text-dark my-1 special-select-align-magic-trick">
10
13
  &copy; Saooti 2025
11
14
  </div>
12
- <FooterGarSection v-if="authStore.isGarRole" :auth-orga-id="authStore.authOrgaId" />
15
+ <FooterGarSection
16
+ v-if="authStore.isGarRole"
17
+ :auth-orga-id="authStore.authOrgaId"
18
+ />
13
19
  <nav :aria-label="t('Site menu')">
14
20
  <ul class="p-0 m-0">
15
21
  <li
@@ -43,13 +49,11 @@
43
49
  class="my-1"
44
50
  />
45
51
  <OrganisationChooserLight
46
- v-if="!state.generalParameters.podcastmaker && organisationId && authenticated"
52
+ v-if="!state.generalParameters.podcastmaker && authenticated"
47
53
  page="footer"
48
54
  width="auto"
49
55
  class="my-1"
50
56
  :defaultanswer="t('No organisation filter')"
51
- :value="organisationId"
52
- :reset="reset"
53
57
  @selected="onOrganisationSelected"
54
58
  />
55
59
  </div>
@@ -83,7 +87,7 @@ import { useFilterStore } from "../../stores/FilterStore";
83
87
  import { useGeneralStore } from "../../stores/GeneralStore";
84
88
  import { useAuthStore } from "../../stores/AuthStore";
85
89
  import { Category } from "@/stores/class/general/category";
86
- import { computed, defineAsyncComponent, Ref, ref, watch } from "vue";
90
+ import { computed, defineAsyncComponent, ref, watch } from "vue";
87
91
  import { Organisation } from "@/stores/class/general/organisation";
88
92
  import { useI18n } from "vue-i18n";
89
93
  import { useRoute, useRouter } from "vue-router";
@@ -98,8 +102,6 @@ const { t, locale } = useI18n();
98
102
 
99
103
  //Data
100
104
  const language = ref(locale);
101
- const reset = ref(false);
102
- const organisationId: Ref<string | undefined> = ref(undefined);
103
105
 
104
106
  //Composables
105
107
  const generalStore = useGeneralStore();
@@ -127,15 +129,6 @@ const routerLinkSecondArray = computed(() => {
127
129
 
128
130
  //Watch
129
131
  watch(language, () => changeLanguage());
130
- watch(()=>filterStore.filterOrgaId, () => {
131
- if (filterStore.filterOrgaId) {
132
- organisationId.value = filterStore.filterOrgaId;
133
- } else {
134
- reset.value = !reset.value;
135
- }
136
- }, {immediate: true});
137
-
138
-
139
132
 
140
133
  //Methods
141
134
  function changeLanguage(): void {
@@ -164,15 +157,20 @@ function changeLanguage(): void {
164
157
  }
165
158
  });
166
159
  }
160
+
161
+ /**
162
+ * Select another organisation
163
+ * @param organisation The new organisation to focus on, or undefined to remove focus
164
+ */
167
165
  async function onOrganisationSelected( organisation: Organisation | undefined): Promise<void> {
166
+ // TODO use router utils
168
167
  if (organisation?.id) {
169
168
  router.push({
170
- query: { ...route.query, ...{ productor: organisation.id, o:undefined } },
169
+ query: { ...route.query, ...{ productor: organisation.id, o:undefined, displayAll: "false" } },
171
170
  });
172
171
  }else{
173
- organisationId.value = undefined;
174
172
  router.push({
175
- query: { ...route.query, ...{ productor: undefined } },
173
+ query: { ...route.query, ...{ productor: undefined, displayAll: "true" } },
176
174
  });
177
175
  }
178
176
  }
@@ -32,143 +32,36 @@
32
32
  :left-pos="true"
33
33
  :is-top-layer="true"
34
34
  >
35
- <nav :aria-label="t('User menu')">
36
- <ul class="p-0 m-0">
37
- <template v-if="!isAuthenticated">
38
- <li class="li-style-none">
39
- <a class="octopus-dropdown-item realLink" :href="pathLogin">
40
- {{ t("Login") }}
41
- </a>
42
- </li>
43
- <li class="li-style-none">
44
- <router-link
45
- v-if="!state.generalParameters.podcastmaker"
46
- class="octopus-dropdown-item"
47
- to="/main/pub/create"
48
- >
49
- {{ t("Create an account") }}
50
- </router-link>
51
- </li>
52
- </template>
53
- <template v-else>
54
- <li v-for="routerBack in routerBackoffice" :key="routerBack.path" class="li-style-none">
55
- <router-link
56
- v-if="!state.generalParameters.podcastmaker && routerBack.condition"
57
- :class="routerBack.class"
58
- :to="routerBack.path"
59
- >
60
- {{ routerBack.title }}
61
- </router-link>
62
- </li>
63
- <template v-if="helpLinks.length">
64
- <hr />
65
- <li v-for="helpLink in helpLinks" :key="helpLink.title" class="li-style-none">
66
- <a
67
- :href="helpLink.href"
68
- class="octopus-dropdown-item realLink"
69
- rel="noreferrer noopener"
70
- target="_blank"
71
- :title="t('New window', {text: helpLink.title})"
72
- >
73
- {{ helpLink.title }}
74
- <OpenInNewIcon class="ms-1" :size="15"/>
75
- </a>
76
- </li>
77
- </template>
78
- <hr />
79
- <li class="li-style-none">
80
- <a class="octopus-dropdown-item c-hand" href="/logout">
81
- {{ t("Logout") }}
82
- </a>
83
- </li>
84
- </template>
85
- <li class="li-style-none">
86
- <router-link
87
- v-if="!authStore.isGarRole"
88
- class="octopus-dropdown-item"
89
- to="/main/pub/contact"
90
- >
91
- {{ t("Contact") }}
92
- </router-link>
93
- </li>
94
- </ul>
95
- </nav>
35
+ <UserButtonContent :isEducation="isEducation" :navLabel="t('User menu')"/>
96
36
  </ClassicPopover>
97
37
  </div>
98
38
  </template>
99
39
 
100
40
  <script setup lang="ts">
101
- import OpenInNewIcon from "vue-material-design-icons/OpenInNew.vue";
41
+ import UserButtonContent from "./UserButtonContent.vue";
102
42
  import AppsIcon from "vue-material-design-icons/Apps.vue";
103
43
  import AccountIcon from "vue-material-design-icons/Account.vue";
104
44
  import DownloadIcon from "vue-material-design-icons/Download.vue";
105
- import { state } from "../../stores/ParamSdkStore";
106
45
  import ClassicPopover from "../misc/ClassicPopover.vue";
107
46
  import { useAuthStore } from "../../stores/AuthStore";
108
47
  import { computed } from "vue";
109
- import { useApiStore } from "../../stores/ApiStore";
110
48
  import { useI18n } from "vue-i18n";
111
49
  import { useRoute, useRouter } from "vue-router";
112
50
 
113
51
  //Props
114
- const props = defineProps({
52
+ defineProps({
115
53
  isEducation: { default: false, type: Boolean },
116
54
  mobileMenuDisplay: { default: false, type: Boolean },
117
- scrolled: { default: false, type: Boolean },
118
55
  })
119
56
 
120
57
  //Composables
121
58
  const { t } = useI18n();
122
59
  const authStore = useAuthStore();
123
- const apiStore = useApiStore();
124
60
  const route = useRoute();
125
61
  const router = useRouter();
126
62
 
127
63
  //Computed
128
- const isAuthenticated = computed(() => undefined !== authStore.authProfile?.userId);
129
64
  const isAuthenticatedWithOrga = computed(() => undefined !== authStore.authOrgaId);
130
- const pathLogin = computed(() => "/sso/login?redirect_url="+encodeURI(apiStore.frontendUrl + route.fullPath));
131
- const organisationsAvailable = computed(() => authStore.authProfile?.organisations ?? []);
132
- const helpLinks = computed(() => {
133
- if (authStore.isGarRole || props.isEducation) {
134
- return [];
135
- }
136
- return [
137
- { title:t("Help"), href: "https://help.octopus.saooti.com/Aide/"},
138
- { title: t("TutoMag"), href: "https://help.octopus.saooti.com/" },
139
- ];
140
- });
141
- const routerBackoffice = computed(() => {
142
- return [
143
- {
144
- title: t("My space"),
145
- class: "octopus-dropdown-item show-small-phone-flex",
146
- path: "/main/priv/backoffice",
147
- condition: isAuthenticatedWithOrga.value,
148
- },
149
- {
150
- title: t("Upload"),
151
- class: "octopus-dropdown-item show-small-phone-flex",
152
- path: "/main/priv/upload",
153
- condition: isAuthenticatedWithOrga.value && authStore.isRoleContribution,
154
- },
155
- {
156
- title: t("Edit my profile"),
157
- class: "octopus-dropdown-item",
158
- path: "/main/priv/edit/profile",
159
- condition: true,
160
- },
161
- {
162
- title: t("Edit my organisation"),
163
- class: "octopus-dropdown-item",
164
- path: "/main/priv/edit/organisation",
165
- condition:
166
- isAuthenticatedWithOrga.value &&
167
- (authStore.isRoleOrganisation || 1 < organisationsAvailable.value.length),
168
- },
169
- ];
170
- });
171
-
172
65
 
173
66
  //Methods
174
67
  function goToAdministration() {