@saooti/octopus-sdk 40.2.9 → 40.2.11

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": "40.2.9",
3
+ "version": "40.2.11",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
package/src/App.vue CHANGED
@@ -40,7 +40,7 @@ export default defineComponent({
40
40
  CategoryFilter,
41
41
  FooterOctopus,
42
42
  PlayerComponent,
43
- ClassicLazy,
43
+ ClassicLazy
44
44
  },
45
45
 
46
46
  setup(){
@@ -16,17 +16,25 @@ export const useRubriquesFilterParam = ()=>{
16
16
  .map((value) => value.rubriquageId + ":" + value.rubriqueId)
17
17
  .join();
18
18
  }
19
-
20
- function modifyRubriquesFilter(modifyFunction: (a: Array<RubriquageFilter>)=> Array<RubriquageFilter>){
19
+ function returnValToUpdate(modifyFunction: (a: Array<RubriquageFilter>)=> Array<RubriquageFilter>){
21
20
  const newFilter = modifyFunction( Array.from(filterStore.filterRubrique));
22
21
  const queryString = stringifyRubriquesFilter(newFilter);
23
- const valToUpdate = "" !== queryString ? queryString : undefined;
22
+ return "" !== queryString ? queryString : undefined;
23
+ }
24
+ function modifyRubriquesFilter(modifyFunction: (a: Array<RubriquageFilter>)=> Array<RubriquageFilter>){
25
+ const valToUpdate = returnValToUpdate(modifyFunction);
24
26
  updateFiltersParam({ rubriquesId: valToUpdate }, {r: valToUpdate});
25
27
  }
26
28
 
29
+ function returnRubriquesFilter(modifyFunction: (a: Array<RubriquageFilter>)=> Array<RubriquageFilter>){
30
+ const valToUpdate = returnValToUpdate(modifyFunction);
31
+ return { rubriquesId: valToUpdate, r: valToUpdate };
32
+ }
33
+
27
34
  return {
28
35
  stringifyRubriquesFilter,
29
36
  modifyRubriquesFilter,
30
- updateRouteParamAdvanced
37
+ updateRouteParamAdvanced,
38
+ returnRubriquesFilter
31
39
  }
32
40
  }
@@ -7,6 +7,7 @@
7
7
  <div>{{ $t("Advanced filters") }}</div>
8
8
  <ChevronDownIcon :class="{ 'arrow-transform': showFilters }" />
9
9
  </button>
10
+ <Transition name="advanced-search">
10
11
  <div
11
12
  v-if="firstLoaded"
12
13
  v-show="showFilters"
@@ -76,6 +77,7 @@
76
77
  @update:sort="updateSort"
77
78
  />
78
79
  </div>
80
+ </Transition>
79
81
  </div>
80
82
  </template>
81
83
 
@@ -282,12 +284,28 @@ export default defineComponent({
282
284
  background: var(--octopus-background);
283
285
  display: flex;
284
286
  width: 100%;
285
- margin-bottom: 1rem;
287
+ padding-bottom: 1rem;
286
288
  justify-content: space-around;
287
289
 
288
290
  @media (width <= 720px) {
289
291
  flex-wrap: wrap;
290
292
  }
291
293
  }
294
+
295
+ .advanced-search-enter-active,
296
+ .advanced-search-leave-active {
297
+ transition: 0.3s all;
298
+ opacity: 1;
299
+ max-height: 900px;
300
+ height: auto;
301
+ overflow: hidden;
302
+ }
303
+
304
+ .advanced-search-enter-from,
305
+ .advanced-search-leave-to {
306
+ opacity: 0;
307
+ max-height: 0;
308
+ overflow: hidden;
309
+ }
292
310
  }
293
311
  </style>
@@ -91,16 +91,16 @@ export default defineComponent({
91
91
  },
92
92
  emits: ["sortChrono", "sortPopular", "displayPrevious", "displayNext"],
93
93
  setup(){
94
- const { modifyRubriquesFilter } = useRubriquesFilterParam();
94
+ const { returnRubriquesFilter } = useRubriquesFilterParam();
95
95
  const { rubriqueQueryParam } = useRubriquesFilterComputed();
96
- return { modifyRubriquesFilter, rubriqueQueryParam }
96
+ return { returnRubriquesFilter, rubriqueQueryParam }
97
97
  },
98
98
  data() {
99
99
  return {};
100
100
  },
101
101
 
102
102
  computed: {
103
- ...mapState(useFilterStore, ["filterIab", "filterRubriquage"]),
103
+ ...mapState(useFilterStore, ["filterIab", "filterRubriquage", "filterOrgaId"]),
104
104
  refTo(): string | RouteLocationRaw {
105
105
  if (this.href) return this.href;
106
106
  if (this.iabId) {
@@ -114,6 +114,7 @@ export default defineComponent({
114
114
  query: {
115
115
  iabId: this.filterIab?.id,
116
116
  rubriquesId: this.rubriqueQueryParam,
117
+ productor: this.filterOrgaId
117
118
  },
118
119
  };
119
120
  },
@@ -142,12 +143,7 @@ export default defineComponent({
142
143
  }
143
144
  event.preventDefault();
144
145
  const rubriqueChosenId = this.rubriqueId.at(-1);
145
- let filterToAdd: RubriquageFilter = {
146
- rubriquageId: 0,
147
- rubriqueId: rubriqueChosenId,
148
- nameRubriquage: "",
149
- nameRubrique: "",
150
- };
146
+ let filterToAdd: RubriquageFilter|undefined;
151
147
  if (this.filterRubriquage.length) {
152
148
  for (let i = 0, len = this.filterRubriquage.length; i < len; i++) {
153
149
  const rubriqueChosen = this.filterRubriquage[i].rubriques.find(
@@ -164,9 +160,19 @@ export default defineComponent({
164
160
  }
165
161
  }
166
162
  }
167
- this.modifyRubriquesFilter((a) => {
168
- a.push(filterToAdd);
163
+ if(!filterToAdd){return;}
164
+ const queries = this.returnRubriquesFilter((a) => {
165
+ let indexRubriquage = a.findIndex(filter => filter.rubriquageId === filterToAdd.rubriquageId);
166
+ if (indexRubriquage === -1) {
167
+ a.push(filterToAdd);
168
+ } else {
169
+ a[indexRubriquage] = filterToAdd;
170
+ }
169
171
  return a;
172
+ })
173
+ this.$router.push({
174
+ name: "podcasts",
175
+ query: {...this.$route.query, ...queries}
170
176
  });
171
177
  },
172
178
  },
@@ -40,7 +40,7 @@
40
40
  <div v-if="isLiveReady" class="text-danger">
41
41
  {{ $t("Episode record in live") }}
42
42
  </div>
43
- <div class="d-flex flex-column align-items-end flex-grow-1">
43
+ <div class="d-flex flex-column align-items-end">
44
44
  <time :datetime="durationIso">
45
45
  {{ duration }}
46
46
  </time>
@@ -1,13 +1,13 @@
1
1
  <template>
2
2
  <div
3
- v-if="undefined !== tagList && 0 !== tagList.length"
3
+ v-if="undefined !== tagListFiltered && 0 !== tagListFiltered.length"
4
4
  class="tag-list-component d-flex align-items-center flex-wrap mb-3 small-text"
5
5
  >
6
6
  <div class="fw-bold me-3">
7
7
  {{ $t("Podcast tags") + " : " }}
8
8
  </div>
9
9
  <router-link
10
- v-for="(tag, index) in tagList"
10
+ v-for="(tag, index) in tagListFiltered"
11
11
  :key="tag"
12
12
  class="d-flex align-items-center border p-1 m-1 text-dark"
13
13
  :to="{
@@ -72,6 +72,11 @@ export default defineComponent({
72
72
  },
73
73
  computed: {
74
74
  ...mapState(useFilterStore, ["filterOrgaId"]),
75
+ tagListFiltered(): Array<string>{
76
+ return this.tagList.filter((tag: string) => {
77
+ return !tag.match(/^\[\[.*\]\]$/);
78
+ });
79
+ },
75
80
  organisationQuery(){
76
81
  if(this.filterOrgaId){
77
82
  return undefined;
@@ -133,10 +133,7 @@ export default defineComponent({
133
133
  methods: {
134
134
  ...mapActions(useFilterStore, ["filterUpdateRubriqueDisplay"]),
135
135
  initRubriques(): void {
136
- if (!this.rubriquage) {
137
- return;
138
- }
139
- this.filterUpdateRubriqueDisplay(this.rubriquage.rubriques);
136
+ this.filterUpdateRubriqueDisplay(this.rubriquage?.rubriques ?? []);
140
137
  window.addEventListener("resize", this.resizeWindow);
141
138
  this.$nextTick(() => {
142
139
  this.resizeWindow();
@@ -25,7 +25,7 @@
25
25
  :margin="2"
26
26
  />
27
27
  <div class="d-flex align-items-center my-3">
28
- <FormatSwitch class="me-3" v-model:isSvg="isSvg"/>
28
+ <FormatSwitch v-model:is-svg="isSvg" class="me-3"/>
29
29
  <button class="btn btn-primary" @click="download">
30
30
  {{ $t("Download") }}
31
31
  </button>
@@ -4,7 +4,7 @@
4
4
  class="d-flex align-items-center justify-content-center"
5
5
  >
6
6
  <ClassicSpinner class="me-3" />
7
- <div class="h3 mt-2">
7
+ <div class="h3">
8
8
  {{ loadingText }}
9
9
  </div>
10
10
  </div>
@@ -1,5 +1,7 @@
1
1
  <template>
2
- <div class="octopus-spinner" :class="small ? 'small' : ''" />
2
+ <div class="octopus-spinner" :style="small ? '--size-spinner:1rem;' : ''" >
3
+ <div v-for="index of 12" :key="index"></div>
4
+ </div>
3
5
  </template>
4
6
 
5
7
  <script lang="ts">
@@ -13,7 +15,89 @@ export default defineComponent({
13
15
  </script>
14
16
  <style lang="scss">
15
17
  .octopus-app .octopus-spinner {
18
+
19
+ --size-spinner: 3rem;
20
+ --size-spinner-section: calc(var(--size-spinner) / 20);
21
+ --half-size-spinner: calc(var(--size-spinner) / 2);
22
+
23
+ color: #000000;
16
24
  display: inline-block;
25
+ position: relative;
26
+ width: var(--size-spinner);
27
+ height: var(--size-spinner);
28
+
29
+ div {
30
+ transform-origin: var(--half-size-spinner) var(--half-size-spinner);
31
+ animation: octopus-spinner 1.2s linear infinite;
32
+ }
33
+ div:after {
34
+ content: " ";
35
+ display: block;
36
+ position: absolute;
37
+ top: 3px;
38
+ left: calc(var(--half-size-spinner) - calc(var(--size-spinner-section) / 2));
39
+ width: var(--size-spinner-section);
40
+ height: calc(var(--half-size-spinner) / 3);
41
+ border-radius: 20%;
42
+ background: currentColor;
43
+ }
44
+ div:nth-child(1) {
45
+ transform: rotate(0deg);
46
+ animation-delay: -1.1s;
47
+ }
48
+ div:nth-child(2) {
49
+ transform: rotate(30deg);
50
+ animation-delay: -1s;
51
+ }
52
+ div:nth-child(3) {
53
+ transform: rotate(60deg);
54
+ animation-delay: -0.9s;
55
+ }
56
+ div:nth-child(4) {
57
+ transform: rotate(90deg);
58
+ animation-delay: -0.8s;
59
+ }
60
+ div:nth-child(5) {
61
+ transform: rotate(120deg);
62
+ animation-delay: -0.7s;
63
+ }
64
+ div:nth-child(6) {
65
+ transform: rotate(150deg);
66
+ animation-delay: -0.6s;
67
+ }
68
+ div:nth-child(7) {
69
+ transform: rotate(180deg);
70
+ animation-delay: -0.5s;
71
+ }
72
+ div:nth-child(8) {
73
+ transform: rotate(210deg);
74
+ animation-delay: -0.4s;
75
+ }
76
+ div:nth-child(9) {
77
+ transform: rotate(240deg);
78
+ animation-delay: -0.3s;
79
+ }
80
+ div:nth-child(10) {
81
+ transform: rotate(270deg);
82
+ animation-delay: -0.2s;
83
+ }
84
+ div:nth-child(11) {
85
+ transform: rotate(300deg);
86
+ animation-delay: -0.1s;
87
+ }
88
+ div:nth-child(12) {
89
+ transform: rotate(330deg);
90
+ animation-delay: 0s;
91
+ }
92
+ @keyframes octopus-spinner {
93
+ 0% {
94
+ opacity: 1;
95
+ }
96
+ 100% {
97
+ opacity: 0;
98
+ }
99
+ }
100
+ /* display: inline-block;
17
101
  width: 2rem;
18
102
  height: 2rem;
19
103
  border-radius: 50%;
@@ -31,6 +115,6 @@ export default defineComponent({
31
115
  to {
32
116
  transform: rotate(360deg);
33
117
  }
34
- }
118
+ } */
35
119
  }
36
120
  </style>
@@ -4,10 +4,7 @@
4
4
  class="top-bar-logo d-flex align-items-center"
5
5
  :to="{
6
6
  name: 'home',
7
- query: {
8
- iabId: filterIab?.id,
9
- rubriquesId: rubriqueQueryParam,
10
- },
7
+ query: getQueriesRouter('home'),
11
8
  }"
12
9
  :title="$t('Home')"
13
10
  >
@@ -274,7 +271,7 @@ export default defineComponent({
274
271
  },
275
272
  methods: {
276
273
  getQueriesRouter(routeName: string) {
277
- if ("podcasts" !== routeName && "emissions" !== routeName) {
274
+ if ("podcasts" !== routeName && "emissions" !== routeName && "home" !== routeName) {
278
275
  return { productor: this.filterOrgaId };
279
276
  }
280
277
  return {
@@ -308,12 +305,15 @@ export default defineComponent({
308
305
  color: white;
309
306
  font-weight: bold;
310
307
  font-size: 0.93rem;
308
+ text-decoration: underline;
309
+ text-decoration-color: transparent;
310
+ transition: text-decoration-color 250ms;
311
+ text-underline-offset: 8px;
311
312
 
312
313
  &.link-hover:hover,
313
314
  &.link-hover.router-link-exact-active.router-link-active {
314
315
  color: white;
315
- text-decoration: underline;
316
- text-underline-offset: 8px;
316
+ text-decoration-color: white;
317
317
  }
318
318
  }
319
319
 
@@ -5,13 +5,15 @@
5
5
  <WindowCloseIcon />
6
6
  </button>
7
7
  <div class="video-wrapper">
8
- <PlayerVideoDigiteka v-if="!playerLive" :video-id="videoId" />
8
+ <PlayerYoutubeEmbed v-if="youtubeId" :youtube-id="youtubeId" />
9
+ <PlayerVideoDigiteka v-else-if="!playerLive" :video-id="playerPodcast?.video?.videoId" />
9
10
  <PlayerVideoHls v-else :hls-url="hlsVideoUrl" />
10
11
  </div>
11
12
  </template>
12
13
  </teleport>
13
14
  </template>
14
15
  <script lang="ts">
16
+ import youtubeVideoHelper from "../../../../helper/youtubeVideoHelper";
15
17
  import WindowCloseIcon from "vue-material-design-icons/WindowClose.vue";
16
18
  import { usePlayerStore } from "../../../../stores/PlayerStore";
17
19
  import { useApiStore } from "../../../../stores/ApiStore";
@@ -23,16 +25,22 @@ const PlayerVideoDigiteka = defineAsyncComponent(
23
25
  const PlayerVideoHls = defineAsyncComponent(
24
26
  () => import("../video/PlayerVideoHls.vue"),
25
27
  );
28
+ const PlayerYoutubeEmbed = defineAsyncComponent(
29
+ () => import("../video/PlayerYoutubeEmbed.vue"),
30
+ );
26
31
  export default defineComponent({
27
32
  name: "PlayerVideo",
28
33
 
29
34
  components: {
30
35
  PlayerVideoDigiteka,
31
36
  PlayerVideoHls,
37
+ PlayerYoutubeEmbed,
32
38
  WindowCloseIcon,
33
39
  },
34
40
  data() {
35
- return {};
41
+ return {
42
+ youtubeId: undefined as string|undefined,
43
+ };
36
44
  },
37
45
  computed: {
38
46
  ...mapState(useApiStore, ["hlsUrl"]),
@@ -43,9 +51,9 @@ export default defineComponent({
43
51
  }
44
52
  return `${this.hlsUrl}live/video_dev.${this.playerLive.conferenceId}/index.m3u8`;
45
53
  },
46
- videoId(): string | undefined {
47
- return this.playerPodcast?.video?.videoId;
48
- },
54
+ },
55
+ created(){
56
+ this.youtubeId = youtubeVideoHelper.getYoutubeId((this.playerPodcast ?? this.playerLive )?.tags ?? []);
49
57
  },
50
58
 
51
59
  methods: {
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <iframe
3
+ width="500"
4
+ height="281"
5
+ :title="$t('Video')"
6
+ class="youtube-iframe"
7
+ :src="'https://www.youtube.com/embed/'+youtubeId"
8
+ frameborder="0"
9
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
10
+ referrerpolicy="strict-origin-when-cross-origin"
11
+ allowfullscreen>
12
+ </iframe>
13
+ </template>
14
+
15
+ <script lang="ts">
16
+ import { defineComponent } from "vue";
17
+ export default defineComponent({
18
+ name: "PlayerYoutubeEmbed",
19
+ components: {
20
+ },
21
+ props: {
22
+ youtubeId: { default: undefined, type: String },
23
+ },
24
+
25
+ });
26
+ </script>
27
+ <style lang="scss">
28
+ @use "../../../../style/videoPlayer";
29
+ </style>
@@ -44,6 +44,7 @@
44
44
  query: {
45
45
  iabId: filterIab?.id,
46
46
  rubriquesId: rubriqueQueryParam,
47
+ productor: filterOrgaId
47
48
  },
48
49
  }"
49
50
  class="btn btn-primary align-self-center w-fit-content mt-5 m-auto"
@@ -13,6 +13,7 @@
13
13
  query: {
14
14
  iabId: filterStore.filterIab?.id,
15
15
  rubriquesId: rubriqueQueryParam,
16
+ productor: filterStore.filterOrgaId
16
17
  },
17
18
  }"
18
19
  >
@@ -21,7 +21,7 @@
21
21
  :organisation-id="podcast.organisation.id"
22
22
  />
23
23
  <SharePlayer
24
- v-if="!isPodcastmaker && editRight"
24
+ v-if="!isPodcastmaker && editRight && !youtubeId"
25
25
  :podcast="podcast"
26
26
  :emission="podcast?.emission"
27
27
  :organisation-id="authOrgaId"
@@ -68,6 +68,7 @@
68
68
  </template>
69
69
 
70
70
  <script lang="ts">
71
+ import youtubeVideoHelper from "../../helper/youtubeVideoHelper";
71
72
  import {useOrgaComputed} from "../composable/useOrgaComputed";
72
73
  import PodcastInlineList from "../display/podcasts/PodcastInlineList.vue";
73
74
  import PodcastModuleBox from "../display/podcasts/PodcastModuleBox.vue";
@@ -135,6 +136,7 @@ export default defineComponent({
135
136
  error: false as boolean,
136
137
  fetchConference: undefined as Conference | undefined,
137
138
  infoReload: undefined as ReturnType<typeof setTimeout> | undefined,
139
+ youtubeId: undefined as string|undefined,
138
140
  };
139
141
  },
140
142
 
@@ -312,6 +314,9 @@ export default defineComponent({
312
314
  this.podcastInProcessing();
313
315
  this.updatePathParams(this.podcast.title);
314
316
  await this.getCommentsConfig(this.podcast);
317
+ if((this.fetchConference?.videoProfile?.includes("video_") && "READY_TO_RECORD" === this.podcast.processingStatus) || undefined !== this.podcast.video?.videoId){
318
+ this.youtubeId = youtubeVideoHelper.getYoutubeId(this.podcast?.tags ?? []);
319
+ }
315
320
  this.loaded = true;
316
321
  } catch (error) {
317
322
  this.handle403(error as AxiosError);
@@ -0,0 +1,13 @@
1
+ export default {
2
+ getYoutubeId(tags: Array<string>){
3
+ let youtubeId = undefined;
4
+ for(const tag of tags){
5
+ const regexExec = /^\[\[https:\/\/(?:www.)?youtube.com\/(?:watch\?v=|live\/)(?<id>\S+)\]\]$/.exec(tag);
6
+ if(regexExec?.groups?.id){
7
+ youtubeId = regexExec.groups.id;
8
+ break;
9
+ }
10
+ }
11
+ return youtubeId;
12
+ }
13
+ }
@@ -97,7 +97,7 @@ const routes: Array<RouteRecordRaw> = [
97
97
  routeValidity:route.query.vl ?? "",
98
98
  routeOnlyVideo:route.query.v ?? "",
99
99
  routeOrga:route.query.o,
100
- routeRubriques :route.query.r,
100
+ routeRubriques :route.query.r ?? route.query.rubriquesId,
101
101
  }),
102
102
  meta:{
103
103
  title: "Podcasts",
@@ -118,7 +118,7 @@ const routes: Array<RouteRecordRaw> = [
118
118
  routeFrom: route.query.from,
119
119
  routeTo: route.query.to,
120
120
  routeOrga:route.query.o,
121
- routeRubriques :route.query.r,
121
+ routeRubriques :route.query.r ?? route.query.rubriquesId,
122
122
  }),
123
123
  meta:{
124
124
  title: "Emissions",
@@ -47,8 +47,8 @@
47
47
  }
48
48
 
49
49
  .img-box-podcast{
50
- height: calc(var(--octopus-podcast-size) - 4px);
51
- width: calc(var(--octopus-podcast-size) - 4px);
50
+ height: calc(var(--octopus-podcast-size) - 2px);
51
+ width: calc(var(--octopus-podcast-size) - 2px);
52
52
  }
53
53
 
54
54
  .img-box,.img-box.img-box-podcast{