@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.
- package/eslint.config.mjs +5 -3
- package/index.ts +7 -1
- package/package.json +3 -2
- package/plateform.conf +1 -1
- package/src/App.vue +3 -7
- package/src/api/classicApi.ts +1 -1
- package/src/components/composable/player/usePlayerLive.ts +2 -2
- package/src/components/composable/player/usePlayerLogic.ts +2 -1
- package/src/components/composable/radio/usefetchRadioData.ts +29 -12
- package/src/components/composable/route/useSimplePageParam.ts +6 -1
- package/src/components/display/categories/CategoryChooser.vue +4 -0
- package/src/components/display/comments/CommentList.vue +1 -1
- package/src/components/display/emission/EmissionList.vue +2 -1
- package/src/components/display/emission/EmissionPresentationItem.vue +14 -6
- package/src/components/display/filter/AdvancedSearch.vue +2 -2
- package/src/components/display/filter/DateFilter.vue +15 -2
- package/src/components/display/live/RadioCurrently.vue +2 -5
- package/src/components/display/organisation/OrganisationChooserLight.vue +34 -36
- package/src/components/display/podcasts/PodcastPlayButton.vue +6 -1
- package/src/components/display/rubriques/RubriqueChooser.vue +24 -2
- package/src/components/display/rubriques/RubriqueList.vue +18 -0
- package/src/components/display/sharing/PlayerParameters.vue +0 -8
- package/src/components/display/sharing/SharePlayer.vue +0 -5
- package/src/components/display/sharing/SubscribeButtons.vue +4 -2
- package/src/components/form/ClassicCheckbox.vue +29 -4
- package/src/components/form/ClassicInputText.vue +14 -6
- package/src/components/form/ClassicMultiselect.vue +35 -7
- package/src/components/misc/ClassicAccordion.vue +4 -4
- package/src/components/misc/ClassicLazy.vue +25 -14
- package/src/components/misc/ClassicNav.vue +3 -0
- package/src/components/misc/ClassicSpinner.vue +1 -1
- package/src/components/misc/FooterSection.vue +18 -20
- package/src/components/misc/HomeDropdown.vue +3 -110
- package/src/components/misc/MobileMenu.vue +59 -64
- package/src/components/misc/TopBar.vue +2 -10
- package/src/components/misc/TopBarMainContent.vue +8 -12
- package/src/components/misc/UserButtonContent.vue +159 -0
- package/src/components/misc/modal/ClassicModal.vue +4 -0
- package/src/components/misc/player/PlayerCompact.vue +1 -0
- package/src/components/misc/player/PlayerComponent.vue +1 -0
- package/src/components/misc/player/elements/PlayerImage.vue +0 -1
- package/src/components/misc/player/elements/PlayerTitle.vue +3 -3
- package/src/components/misc/player/radio/RadioHistory.vue +3 -2
- package/src/components/misc/player/video/PlayerVideo.vue +2 -2
- package/src/components/pages/HomePage.vue +5 -4
- package/src/components/pages/PageLogout.vue +1 -6
- package/src/components/pages/PodcastPage.vue +0 -1
- package/src/components/pages/PodcastsPage.vue +1 -1
- package/src/components/pages/VideoPage.vue +5 -2
- package/src/helper/equals.ts +26 -0
- package/src/locale/de.ts +6 -5
- package/src/locale/en.ts +6 -5
- package/src/locale/es.ts +6 -5
- package/src/locale/fr.ts +6 -5
- package/src/locale/it.ts +6 -5
- package/src/locale/sl.ts +6 -5
- package/src/router/router.ts +10 -74
- package/src/router/utils.ts +112 -0
- package/src/stores/AuthStore.ts +5 -0
- package/src/stores/FilterStore.ts +126 -71
- package/src/stores/PlayerStore.ts +11 -1
- package/src/stores/class/conference/conference.ts +2 -0
- package/src/stores/class/general/player.ts +2 -2
- package/src/style/_variables.scss +6 -0
- package/src/style/general.scss +18 -1
- 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()
|
|
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="
|
|
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="
|
|
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 ? '':
|
|
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' +
|
|
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' +
|
|
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="
|
|
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="
|
|
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
|
-
<
|
|
11
|
-
label
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
24
|
-
|
|
23
|
+
alt=""
|
|
25
24
|
/>
|
|
26
|
-
<span
|
|
27
|
-
<
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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(
|
|
@@ -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
|
|
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
|
© Saooti 2025
|
|
11
14
|
</div>
|
|
12
|
-
<FooterGarSection
|
|
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 &&
|
|
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,
|
|
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
|
-
<
|
|
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
|
|
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
|
-
|
|
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() {
|