@saooti/octopus-sdk 41.5.4 → 41.5.5
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/CHANGELOG.md +13 -0
- package/package.json +1 -1
- package/src/components/composable/player/usePlayerLive.ts +17 -7
- package/src/components/display/filter/AdvancedSearch.vue +1 -1
- package/src/components/display/sharing/SharePlayer.vue +2 -1
- package/src/components/display/sharing/SharePlayerRadio.vue +2 -1
- package/src/components/form/ClassicDatePicker.vue +14 -1
- package/src/components/form/ClassicRadio.vue +5 -10
- package/tests/components/display/sharing/SharePlayer.spec.ts +58 -0
- package/tests/components/display/sharing/SharePlayerRadio.spec.ts +54 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 41.5.5 (16/02/2026)
|
|
4
|
+
|
|
5
|
+
**Fix**
|
|
6
|
+
|
|
7
|
+
- Correctif pour la lecture de lives/radio sur Organisation sécurisée sous
|
|
8
|
+
chrome
|
|
9
|
+
- Correction affichage critère de filtrage pour épisodes à valider
|
|
10
|
+
|
|
11
|
+
**Misc**
|
|
12
|
+
|
|
13
|
+
- Ajout de `frameborder="0"` dans les iframes miniplayer
|
|
14
|
+
- Ajustements de composants génériques
|
|
15
|
+
|
|
3
16
|
## 41.5.4 (12/02/2026)
|
|
4
17
|
|
|
5
18
|
**Misc**
|
package/package.json
CHANGED
|
@@ -28,19 +28,23 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
28
28
|
return authStore.authParam.accessToken && ("SECURED" === playerStore.playerLive?.organisation?.privacy || playerStore.playerRadio?.secured);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
function onPlay(): void {
|
|
32
32
|
playerStore.playerChangeStatus(PlayerStatus.PAUSED ===playerStore.playerStatus);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function playRadio() {
|
|
36
|
-
if (!playerStore.playerRadio)
|
|
36
|
+
if (!playerStore.playerRadio) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
37
39
|
handleSessionIdRadio();
|
|
38
40
|
playerStore.playerUpdatePlayerHlsUrl(playerStore.playerRadio.url+"?origin=octopus&sessionId="+playerStore.playerRadio.sessionId);
|
|
39
41
|
playHls();
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
function handleSessionIdRadio(){
|
|
43
|
-
if(!playerStore.playerRadio)
|
|
45
|
+
if(!playerStore.playerRadio) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
44
48
|
if(playerStore.playerRadio.sessionId && dayjs().diff(dayjs(playerStore.playerRadio.dateSessionId), 'm')<maxMinutesSessionId){
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
@@ -48,7 +52,9 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
function playLive() {
|
|
51
|
-
if (!playerStore.playerHlsIdentifier)
|
|
55
|
+
if (!playerStore.playerHlsIdentifier) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
52
58
|
playerStore.playerUpdatePlayerHlsUrl(`${apiStore.hlsUrl}live/${playerStore.playerHlsIdentifier}/index.m3u8`);
|
|
53
59
|
playHls();
|
|
54
60
|
}
|
|
@@ -74,11 +80,15 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
74
80
|
!isChrome &&
|
|
75
81
|
!isAndroid
|
|
76
82
|
) {
|
|
83
|
+
let url = playerStore.playerHlsUrl;
|
|
77
84
|
if(needToAddToken.value) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
if (url.includes('?')) {
|
|
86
|
+
url += "&access_token="+authStore.authParam.accessToken;
|
|
87
|
+
} else {
|
|
88
|
+
url += "?access_token="+authStore.authParam.accessToken;
|
|
89
|
+
}
|
|
81
90
|
}
|
|
91
|
+
audioElement.value.src = url;
|
|
82
92
|
await initLiveDownloadId();
|
|
83
93
|
hlsReady.value = true;
|
|
84
94
|
await audioElement.value.play();
|
|
@@ -233,7 +233,7 @@ const isSelectValidity = computed(() => {
|
|
|
233
233
|
undefined !== organisation.value &&
|
|
234
234
|
organisationRight.value &&
|
|
235
235
|
authStore.isRoleContribution &&
|
|
236
|
-
!isPodcastmaker &&
|
|
236
|
+
!isPodcastmaker.value &&
|
|
237
237
|
!props.isEmission &&
|
|
238
238
|
props.includeHidden
|
|
239
239
|
);
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
allowfullscreen="true"
|
|
21
21
|
allow="clipboard-read; clipboard-write; autoplay"
|
|
22
22
|
referrerpolicy="no-referrer-when-downgrade"
|
|
23
|
+
frameborder="0"
|
|
23
24
|
:src="iFrameSrc"
|
|
24
25
|
width="100%"
|
|
25
26
|
:height="iFrameHeight"
|
|
@@ -273,7 +274,7 @@ const iFrame = computed(() => {
|
|
|
273
274
|
const specialDigiteka = props.podcast?.video?.videoId
|
|
274
275
|
? 'allowfullscreen="true" referrerpolicy="no-referrer-when-downgrade"'
|
|
275
276
|
: "";
|
|
276
|
-
return `<iframe src="${iFrameSrc.value}" width="100%" height="${iFrameHeight.value}" scrolling="no" ${specialDigiteka} allow="clipboard-read; clipboard-write; autoplay"></iframe>`;
|
|
277
|
+
return `<iframe src="${iFrameSrc.value}" width="100%" height="${iFrameHeight.value}" frameborder="0" scrolling="no" ${specialDigiteka} allow="clipboard-read; clipboard-write; autoplay"></iframe>`;
|
|
277
278
|
});
|
|
278
279
|
const dataTitle = computed(() => {
|
|
279
280
|
if (props.podcast) return props.podcast.podcastId;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
id="miniplayerIframeRadio"
|
|
9
9
|
title="Miniplayer"
|
|
10
10
|
:src="iFrameSrc"
|
|
11
|
+
frameborder="0"
|
|
11
12
|
width="100%"
|
|
12
13
|
height="140px"
|
|
13
14
|
style="overflow: hidden"
|
|
@@ -90,7 +91,7 @@ const iFrameSrc = computed(() => {
|
|
|
90
91
|
return url;
|
|
91
92
|
});
|
|
92
93
|
const iFrame = computed(() => {
|
|
93
|
-
return `<iframe src="${iFrameSrc.value}" width="100%" height="140px" scrolling="no" allow="clipboard-read; clipboard-write; autoplay"></iframe>`;
|
|
94
|
+
return `<iframe src="${iFrameSrc.value}" width="100%" height="140px" frameborder="0" scrolling="no" allow="clipboard-read; clipboard-write; autoplay"></iframe>`;
|
|
94
95
|
});
|
|
95
96
|
|
|
96
97
|
|
|
@@ -82,7 +82,19 @@ const props = defineProps({
|
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
//Emits
|
|
85
|
-
const emit = defineEmits
|
|
85
|
+
const emit = defineEmits<{
|
|
86
|
+
/**
|
|
87
|
+
* Update the date
|
|
88
|
+
* @param value The new date
|
|
89
|
+
* @deprecated
|
|
90
|
+
*/
|
|
91
|
+
(e: "updateDate", value: Date): void;
|
|
92
|
+
/**
|
|
93
|
+
* Update the date
|
|
94
|
+
* @param value The new date
|
|
95
|
+
*/
|
|
96
|
+
(e: "update:date", value: Date): void;
|
|
97
|
+
}>();
|
|
86
98
|
|
|
87
99
|
//Data
|
|
88
100
|
const divContainerRef = useTemplateRef('divContainer');
|
|
@@ -147,6 +159,7 @@ function updateValue(date: Date) {
|
|
|
147
159
|
(divContainerRef?.value as HTMLElement)?.focus();
|
|
148
160
|
}
|
|
149
161
|
emit("updateDate", date);
|
|
162
|
+
emit("update:date", date);
|
|
150
163
|
}
|
|
151
164
|
|
|
152
165
|
function formatDate(value: Date): string {
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
Available slots:
|
|
5
5
|
`label-{option.value}`: Slot to replace the label of the current option.
|
|
6
6
|
Binding: `option`: the current option
|
|
7
|
+
`selected` : true if the option is selected
|
|
7
8
|
`after-{option.value}`: Slot after the radio button
|
|
8
9
|
Binding: `option`: the current option
|
|
10
|
+
`selected` : true if the option is selected
|
|
9
11
|
-->
|
|
10
12
|
<template>
|
|
11
13
|
<div role="radiogroup" class="d-flex" :class="isColumn ? 'flex-column' : ''">
|
|
@@ -33,20 +35,14 @@
|
|
|
33
35
|
</div>
|
|
34
36
|
</template>
|
|
35
37
|
|
|
36
|
-
<script setup lang="ts">
|
|
37
|
-
|
|
38
|
-
interface Option {
|
|
39
|
-
title: string;
|
|
40
|
-
value: string | undefined
|
|
41
|
-
};
|
|
42
|
-
|
|
38
|
+
<script setup generic="T extends { title: string; value: string|undefined; }" lang="ts">
|
|
43
39
|
//Props
|
|
44
40
|
const { textInit } = defineProps({
|
|
45
41
|
idRadio: { default: "", type: String },
|
|
46
42
|
isDisabled: { default: false, type: Boolean },
|
|
47
43
|
options: {
|
|
48
44
|
default: () => [],
|
|
49
|
-
type: Array as () => Array<
|
|
45
|
+
type: Array as () => Array<T>,
|
|
50
46
|
},
|
|
51
47
|
textInit: { default: undefined, type: String },
|
|
52
48
|
isColumn: { default: true, type: Boolean },
|
|
@@ -60,11 +56,10 @@ function onChange(value:string){
|
|
|
60
56
|
emit('update:textInit', value)
|
|
61
57
|
}
|
|
62
58
|
|
|
63
|
-
function slotBindings(option:
|
|
59
|
+
function slotBindings(option: T): { option: T; selected: boolean } {
|
|
64
60
|
return {
|
|
65
61
|
option,
|
|
66
62
|
selected: textInit === option.value
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
|
-
|
|
70
65
|
</script>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import '@tests/mocks/useRouter';
|
|
2
|
+
import '@tests/mocks/i18n';
|
|
3
|
+
|
|
4
|
+
import SharePlayer from '@/components/display/sharing/SharePlayer.vue';
|
|
5
|
+
import { mount as testMount } from '@tests/utils';
|
|
6
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
7
|
+
import { useApiStore } from '@/stores/ApiStore';
|
|
8
|
+
import { useSaveFetchStore } from '@/stores/SaveFetchStore';
|
|
9
|
+
|
|
10
|
+
describe('SharePlayer', () => {
|
|
11
|
+
it('renders iframe with frameborder="0"', async () => {
|
|
12
|
+
const wrapper = await testMount(SharePlayer, {
|
|
13
|
+
props: {
|
|
14
|
+
podcast: {
|
|
15
|
+
podcastId: 123,
|
|
16
|
+
organisation: { id: 'org1' },
|
|
17
|
+
availability: { visibility: true }
|
|
18
|
+
},
|
|
19
|
+
organisationId: 'org1',
|
|
20
|
+
notExclusive: true
|
|
21
|
+
},
|
|
22
|
+
beforeMount: async () => {
|
|
23
|
+
const apiStore = useApiStore();
|
|
24
|
+
apiStore.miniplayerUrl = 'https://test.com/';
|
|
25
|
+
|
|
26
|
+
const saveFetchStore = useSaveFetchStore();
|
|
27
|
+
vi.spyOn(saveFetchStore, 'getOrgaAttributes').mockResolvedValue({});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const iframe = wrapper.find('#miniplayerIframe');
|
|
32
|
+
expect(iframe.attributes('frameborder')).toBe('0');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('includes frameborder="0" in generated iframe code', async () => {
|
|
36
|
+
const wrapper = await testMount(SharePlayer, {
|
|
37
|
+
props: {
|
|
38
|
+
podcast: {
|
|
39
|
+
podcastId: 123,
|
|
40
|
+
organisation: { id: 'org1' },
|
|
41
|
+
availability: { visibility: true }
|
|
42
|
+
},
|
|
43
|
+
organisationId: 'org1',
|
|
44
|
+
notExclusive: true
|
|
45
|
+
},
|
|
46
|
+
beforeMount: async () => {
|
|
47
|
+
const apiStore = useApiStore();
|
|
48
|
+
apiStore.miniplayerUrl = 'https://test.com/';
|
|
49
|
+
|
|
50
|
+
const saveFetchStore = useSaveFetchStore();
|
|
51
|
+
vi.spyOn(saveFetchStore, 'getOrgaAttributes').mockResolvedValue({});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const iFrameCode = (wrapper.vm as any).iFrame;
|
|
56
|
+
expect(iFrameCode).toContain('frameborder="0"');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import '@tests/mocks/useRouter';
|
|
2
|
+
import '@tests/mocks/i18n';
|
|
3
|
+
|
|
4
|
+
import SharePlayerRadio from '@/components/display/sharing/SharePlayerRadio.vue';
|
|
5
|
+
import { mount as testMount } from '@tests/utils';
|
|
6
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
7
|
+
import { useApiStore } from '@/stores/ApiStore';
|
|
8
|
+
import { useSaveFetchStore } from '@/stores/SaveFetchStore';
|
|
9
|
+
|
|
10
|
+
describe('SharePlayerRadio', () => {
|
|
11
|
+
it('renders iframe with frameborder="0"', async () => {
|
|
12
|
+
const wrapper = await testMount(SharePlayerRadio, {
|
|
13
|
+
props: {
|
|
14
|
+
canal: {
|
|
15
|
+
id: 'radio1',
|
|
16
|
+
organisationId: 'org1'
|
|
17
|
+
},
|
|
18
|
+
organisationId: 'org1'
|
|
19
|
+
},
|
|
20
|
+
beforeMount: async () => {
|
|
21
|
+
const apiStore = useApiStore();
|
|
22
|
+
apiStore.miniplayerUrl = 'https://test.com/';
|
|
23
|
+
|
|
24
|
+
const saveFetchStore = useSaveFetchStore();
|
|
25
|
+
vi.spyOn(saveFetchStore, 'getOrgaAttributes').mockResolvedValue({});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const iframe = wrapper.find('#miniplayerIframeRadio');
|
|
30
|
+
expect(iframe.attributes('frameborder')).toBe('0');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('includes frameborder="0" in generated iframe code', async () => {
|
|
34
|
+
const wrapper = await testMount(SharePlayerRadio, {
|
|
35
|
+
props: {
|
|
36
|
+
canal: {
|
|
37
|
+
id: 'radio1',
|
|
38
|
+
organisationId: 'org1'
|
|
39
|
+
},
|
|
40
|
+
organisationId: 'org1'
|
|
41
|
+
},
|
|
42
|
+
beforeMount: async () => {
|
|
43
|
+
const apiStore = useApiStore();
|
|
44
|
+
apiStore.miniplayerUrl = 'https://test.com/';
|
|
45
|
+
|
|
46
|
+
const saveFetchStore = useSaveFetchStore();
|
|
47
|
+
vi.spyOn(saveFetchStore, 'getOrgaAttributes').mockResolvedValue({});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const iFrameCode = (wrapper.vm as any).iFrame;
|
|
52
|
+
expect(iFrameCode).toContain('frameborder="0"');
|
|
53
|
+
});
|
|
54
|
+
});
|