@saooti/octopus-sdk 31.0.8 → 31.0.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.
Files changed (31) hide show
  1. package/README.md +6 -4
  2. package/package.json +3 -2
  3. package/src/App.vue +7 -12
  4. package/src/assets/general.scss +1 -0
  5. package/src/components/display/emission/EmissionItem.vue +3 -3
  6. package/src/components/display/emission/EmissionPlayerItem.vue +4 -4
  7. package/src/components/display/organisation/OrganisationChooser.vue +2 -2
  8. package/src/components/display/participant/ParticipantItem.vue +3 -3
  9. package/src/components/display/participant/ParticipantList.vue +1 -1
  10. package/src/components/display/playlist/PlaylistItem.vue +3 -6
  11. package/src/components/display/playlist/PlaylistList.vue +1 -1
  12. package/src/components/display/playlist/PodcastList.vue +1 -1
  13. package/src/components/display/podcasts/AnimatorsItem.vue +1 -2
  14. package/src/components/display/podcasts/PodcastImage.vue +4 -1
  15. package/src/components/display/podcasts/PodcastItem.vue +15 -173
  16. package/src/components/display/podcasts/PodcastItemInfo.vue +170 -0
  17. package/src/components/display/podcasts/PodcastList.vue +35 -34
  18. package/src/components/display/podcasts/PodcastPlayBar.vue +6 -6
  19. package/src/components/display/sharing/SharePlayerTypes.vue +1 -1
  20. package/src/components/misc/PlayerButtons.vue +1 -1
  21. package/src/components/mixins/handle403.ts +1 -1
  22. package/src/components/mixins/organisationFilter.ts +21 -14
  23. package/src/components/pages/Emission.vue +1 -1
  24. package/src/components/pages/Participant.vue +3 -5
  25. package/src/components/pages/Playlist.vue +1 -1
  26. package/src/locale/de.ts +5 -5
  27. package/src/locale/en.ts +17 -17
  28. package/src/locale/es.ts +1 -1
  29. package/src/locale/sl.ts +1 -1
  30. package/src/main.ts +2 -0
  31. package/src/store/paramStore.ts +7 -7
package/README.md CHANGED
@@ -569,6 +569,9 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
569
569
  * 30.0.70 Améliorations 30
570
570
  * 30.0.71 Parlement européen
571
571
  * 30.0.72 Ajout des traductions
572
+ * 30.0.73 Ajout classe css
573
+ * 30.0.74 Error locales en allemand (je sens que ça va être fun cette histoire)
574
+ * 30.0.75 Parlement
572
575
 
573
576
 
574
577
  * 31.0.0 Passage en 31
@@ -580,7 +583,6 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
580
583
  * 31.0.6 Erreur de Merge 30
581
584
  * 31.0.7 Sécurisation
582
585
  * 31.0.8 Dropdown Lang + classicSelect
583
-
584
-
585
-
586
-
586
+ * 31.0.9 LazyLoad image
587
+ * 31.0.10 Sécurisation
588
+ * 31.0.11 Sécurisation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "31.0.8",
3
+ "version": "31.0.11",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -15,7 +15,7 @@
15
15
  "main": "./dist/octopus.common.js",
16
16
  "dependencies": {
17
17
  "@popperjs/core": "^2.11.0",
18
- "@saooti/octopus-api": "^0.31.1",
18
+ "@saooti/octopus-api": "^0.31.2",
19
19
  "@vue/cli": "^5.0.0-rc.1",
20
20
  "@vue/compat": "^3.2.26",
21
21
  "axios": "^0.24.0",
@@ -37,6 +37,7 @@
37
37
  "vue-multiselect": "^3.0.0-alpha.2",
38
38
  "vue-recaptcha-v3": "^2.0.1",
39
39
  "vue-router": "^4.0.12",
40
+ "vue3-lazyload": "^0.2.5-beta",
40
41
  "vue3-swatches": "^1.0.5",
41
42
  "vuex": "^4.0.2",
42
43
  "webpack": "^5.66.0"
package/src/App.vue CHANGED
@@ -1,5 +1,6 @@
1
1
  <template>
2
- <div
2
+ <div
3
+ v-if="isInit"
3
4
  id="app"
4
5
  :key="reload"
5
6
  class="octopus-app"
@@ -45,27 +46,21 @@ export default defineComponent({
45
46
  data() {
46
47
  return {
47
48
  displayMenu: false as boolean,
48
- initQueryRouter: false,
49
49
  reload: false as boolean,
50
+ isInit: false as boolean,
50
51
  };
51
52
  },
52
53
 
53
54
  watch: {
54
- '$route': {
55
- deep: true,
56
- handler(){
57
- if(!this.initQueryRouter){
58
- this.initQueryRouter = true;
59
- this.initApp();
60
- }
61
- }
62
- },
63
55
  '$i18n.locale'(){
64
56
  this.$forceUpdate();
65
57
  this.reload = !this.reload;
66
58
  }
67
59
  },
68
-
60
+ async created(){
61
+ await this.initApp();
62
+ this.isInit =true;
63
+ },
69
64
  methods:{
70
65
  async initApp(){
71
66
  await this.initSdk();
@@ -213,6 +213,7 @@ body{
213
213
  background-size: cover;
214
214
  box-shadow: 0px 8px 26px 6px rgba(64, 163, 114, 0.3);
215
215
  margin: auto;
216
+ display: flex;
216
217
  }
217
218
 
218
219
  .comma {
@@ -11,10 +11,10 @@
11
11
  :title="$t('Emission')"
12
12
  class="d-flex text-dark"
13
13
  >
14
- <div
14
+ <img
15
+ v-lazy="emission.imageUrl"
15
16
  class="img-box"
16
- :style="{ 'background-image': 'url(\'' + emission.imageUrl + '\')' }"
17
- />
17
+ >
18
18
  <div class="emission-item-text">
19
19
  <div
20
20
  class="emission-name"
@@ -18,11 +18,11 @@
18
18
  </div>
19
19
  <div
20
20
  class="img-box rounded-0"
21
- :style="{
22
- 'background-image':
23
- 'url(\'' + emission.imageUrl + '?dummy=' + dummyParam + '\')',
24
- }"
25
21
  >
22
+ <img
23
+ v-lazy="emission.imageUrl"
24
+ class="img-box rounded-0"
25
+ >
26
26
  <div
27
27
  v-if="titleInImage"
28
28
  class="titleInImage"
@@ -44,8 +44,8 @@
44
44
  <div class="multiselect-octopus-proposition">
45
45
  <img
46
46
  v-if="!light"
47
+ v-lazy="option.imageUrl"
47
48
  class="option__image"
48
- :src="option.imageUrl"
49
49
  :alt="option.name"
50
50
  >
51
51
  <span
@@ -64,8 +64,8 @@
64
64
  >
65
65
  <img
66
66
  v-if="!light"
67
+ v-lazy="option.imageUrl"
67
68
  class="option__image"
68
- :src="option.imageUrl"
69
69
  :alt="option.name"
70
70
  >
71
71
  <span
@@ -12,10 +12,10 @@
12
12
  class="mt-3 text-dark"
13
13
  :title="$t('Participant')"
14
14
  >
15
- <div
15
+ <img
16
+ v-lazy="participant.imageUrl"
16
17
  class="img-box-circle"
17
- :style="{ 'background-image': 'url(\'' + participant.imageUrl + '\')' }"
18
- />
18
+ >
19
19
  <div class="participant-name">
20
20
  <img
21
21
  v-if="!activeParticipant && !isPodcastmaker && editRight"
@@ -9,7 +9,7 @@
9
9
  class="text-secondary mb-2"
10
10
  >
11
11
  {{
12
- $t('Number participants', { nb: displayCount }) + $t('sort by score')
12
+ $t('Number participants', { nb: displayCount }) +" "+ $t('sort by score')
13
13
  }}
14
14
  </div>
15
15
  <ul
@@ -12,13 +12,10 @@
12
12
  :title="$t('Playlist')"
13
13
  class="text-dark"
14
14
  >
15
- <div
15
+ <img
16
+ v-lazy="playlist.imageUrl"
16
17
  class="img-box"
17
- :style="{
18
- 'background-image':
19
- 'url(\'' + playlist.imageUrl + '?dummy=' + dummyParam + '\')',
20
- }"
21
- />
18
+ >
22
19
  </router-link>
23
20
  <div class="emission-item-text">
24
21
  <router-link
@@ -7,7 +7,7 @@
7
7
  v-if="loaded && playlists.length > 1"
8
8
  class="text-secondary mb-2"
9
9
  >
10
- {{ $t('Number playlists', { nb: displayCount }) + $t('sort by score') }}
10
+ {{ $t('Number playlists', { nb: displayCount }) +" "+ $t('sort by score') }}
11
11
  </div>
12
12
  <ul class="emission-list two-emissions">
13
13
  <PlaylistItem
@@ -18,7 +18,7 @@
18
18
  v-if="loaded && podcasts.length > 1"
19
19
  class="text-secondary mb-4"
20
20
  >
21
- {{ $t('Number podcasts', { nb: podcasts.length }) + $t('sort by score') }}
21
+ {{ $t('Number podcasts', { nb: podcasts.length }) +" "+ $t('sort by score') }}
22
22
  </div>
23
23
  <ClassicSearch
24
24
  v-if="notEmptyPlaylist"
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  v-if="animators && 0 !== animators.length"
4
- class="d-flex align-items-center justify-content-start"
4
+ class="d-flex align-items-center justify-content-start animators-item"
5
5
  >
6
6
  <router-link
7
7
  v-for="(animator, index) in animators"
@@ -36,7 +36,6 @@ export default defineComponent({
36
36
  visibleIndex: 0 as number,
37
37
  };
38
38
  },
39
-
40
39
  methods: {
41
40
  getAnimatorName(animator: Participant): string {
42
41
  const first = animator.firstName || '';
@@ -2,8 +2,11 @@
2
2
  <div
3
3
  v-if="podcast"
4
4
  class="img-box d-flex flex-column justify-content-start align-items-start position-relative justify rounded-lg flex-shrink-0 float-start"
5
- :style="{ 'background-image': 'url(\'' + podcast.imageUrl + '\')' }"
6
5
  >
6
+ <img
7
+ v-lazy="podcast.imageUrl"
8
+ class="img-box"
9
+ >
7
10
  <template v-if="isPodcastmaker">
8
11
  <div
9
12
  :class="mainRubrique? 'mainRubrique' : 'notMainRubrique'"
@@ -31,78 +31,34 @@
31
31
  />
32
32
  <!-- eslint-enable -->
33
33
  </div>
34
- <div
35
- class="d-contents"
34
+ <PodcastItemInfo
35
+ :podcast-id="podcast.podcastId"
36
+ :title="podcast.title"
37
+ :pub-date="podcast.pubDate"
38
+ :podcast-organisation-id="podcast.organisation.id"
39
+ :podcast-organisation-name="podcast.organisation.name"
40
+ :podcast-order="podcast.order"
41
+ :duration="podcast.duration"
42
+ :animators="podcast.animators"
36
43
  @mouseenter="showDescription"
37
44
  @mouseleave="hideDescription"
38
- >
39
- <div class="d-flex justify-content-between flex-wrap text-secondary mb-3">
40
- <div class="me-3 small-text">
41
- {{ date }}
42
- </div>
43
- <div
44
- v-if="0 !== duration.length"
45
- class="small-text"
46
- >
47
- {{ duration }}
48
- </div>
49
- </div>
50
- <AnimatorsItem :animators="podcast.animators" />
51
- <router-link
52
- :to="{
53
- name: 'podcast',
54
- params: { podcastId: podcast.podcastId },
55
- query: { productor: $store.state.filter.organisationId },
56
- }"
57
- class="text-dark d-flex flex-column flex-grow-1"
58
- >
59
- <div class="title-podcast-item">
60
- {{ title }}
61
- </div>
62
- </router-link>
63
- <PodcastPlayBar
64
- :podcast="podcast"
65
- class="mx-2"
66
- />
67
- <div class="d-flex justify-content-between">
68
- <router-link
69
- v-if="!isPodcastmaker"
70
- :to="{
71
- name: 'productor',
72
- params: { productorId: podcast.organisation.id },
73
- query: { productor: $store.state.filter.organisationId },
74
- }"
75
- class="text-dark producer-podcast-item"
76
- >
77
- <div>{{ '© ' + podcast.organisation.name }}</div>
78
- </router-link>
79
- <span
80
- v-if="editRight && podcast.order && podcast.order > 1"
81
- class="saooti-star-bounty text-danger pe-2"
82
- />
83
- </div>
84
- </div>
45
+ />
85
46
  </li>
86
47
  </template>
87
48
 
88
49
  <script lang="ts">
89
- import AnimatorsItem from './AnimatorsItem.vue';
50
+ import PodcastItemInfo from './PodcastItemInfo.vue';
90
51
  import PodcastImage from './PodcastImage.vue';
91
52
  import { state } from '../../../store/paramStore';
92
53
  import moment from 'moment';
93
- // @ts-ignore
94
- import humanizeDuration from 'humanize-duration';
95
- import PodcastPlayBar from '../podcasts/PodcastPlayBar.vue';
96
54
  import { Podcast } from '@/store/class/general/podcast';
97
- import { Category } from '@/store/class/general/category';
98
55
  import { defineComponent } from 'vue'
99
56
  export default defineComponent({
100
57
  name: 'PodcastItem',
101
58
 
102
59
  components: {
103
- AnimatorsItem,
60
+ PodcastItemInfo,
104
61
  PodcastImage,
105
- PodcastPlayBar
106
62
  },
107
63
 
108
64
  props: {
@@ -116,113 +72,24 @@ export default defineComponent({
116
72
  isDescriptionBig: false as boolean,
117
73
  };
118
74
  },
119
-
75
+
120
76
  computed: {
121
- isPodcastmaker(): boolean {
122
- return (state.generalParameters.podcastmaker as boolean);
123
- },
124
77
  podcastShadow(): boolean {
125
78
  return (state.podcastsPage.podcastShadow as boolean);
126
79
  },
127
80
  podcastBorderBottom(): boolean {
128
81
  return (state.podcastsPage.podcastBorderBottom as boolean);
129
82
  },
130
- date(): string {
131
- return moment(this.podcast.pubDate).format('D MMMM YYYY, HH[h]mm');
132
- },
133
83
  displayDate(): string {
134
84
  return moment(this.podcast.pubDate).format('X');
135
85
  },
136
- category(): string {
137
- const catIds = this.podcast.emission.iabIds;
138
- return this.$store.state.categories
139
- .filter((c: Category) => {
140
- return catIds && catIds.includes(c.id);
141
- })
142
- .map((c: Category) => {
143
- return c.name;
144
- })
145
- .join(', ');
146
- },
147
86
  description(): string {
148
87
  if (!this.podcast.description) return '';
149
88
  return this.podcast.description;
150
89
  },
151
- title(): string {
152
- return this.podcast.title;
153
- },
154
- organisationId(): string|undefined {
155
- return state.generalParameters.organisationId;
156
- },
157
- authenticated(): boolean {
158
- return (state.generalParameters.authenticated as boolean);
159
- },
160
- editRight(): boolean {
161
- if (
162
- (this.authenticated &&
163
- this.organisationId === this.podcast.organisation.id) ||
164
- state.generalParameters.isAdmin
165
- )
166
- return true;
167
- return false;
168
- },
169
- duration(): string {
170
- if (this.podcast.duration <= 1) return '';
171
- if (this.podcast.duration > 600000) {
172
- return humanizeDuration(this.podcast.duration, {
173
- language: 'short'+this.$i18n.locale.charAt(0).toUpperCase() + this.$i18n.locale.slice(1),
174
- largest: 1,
175
- round: true,
176
- languages: {
177
- shortFr: {
178
- y: () => 'années',
179
- mo: () => 'mois',
180
- w: () => 'semaines',
181
- d: () => 'jours',
182
- h: () => 'h',
183
- m: () => 'min',
184
- s: () => 'sec',
185
- ms: () => 'ms',
186
- },
187
- shortEn: {
188
- y: () => 'years',
189
- mo: () => 'months',
190
- w: () => 'weeks',
191
- d: () => 'days',
192
- h: () => 'h',
193
- m: () => 'min',
194
- s: () => 'sec',
195
- ms: () => 'ms',
196
- },
197
- shortIt: {
198
- y: () => 'anni',
199
- mo: () => 'mesi',
200
- w: () => 'settimane',
201
- d: () => 'giorni',
202
- h: () => 'h',
203
- m: () => 'min',
204
- s: () => 'sec',
205
- ms: () => 'ms',
206
- },
207
- },
208
- });
209
- }
210
- return humanizeDuration(this.podcast.duration, {
211
- language: 'short',
212
- largest: 2,
213
- round: true,
214
- languages: {
215
- short: {
216
- m: () => 'min',
217
- s: () => 'sec',
218
- ms: () => 'ms',
219
- },
220
- },
221
- });
222
- },
223
90
  },
224
91
 
225
- mounted() {
92
+ created() {
226
93
  const podcastDesc = document.getElementById(
227
94
  'description-podcast-' + this.podcast.podcastId
228
95
  );
@@ -262,26 +129,7 @@ export default defineComponent({
262
129
  text-align: left;
263
130
  background: #fff;
264
131
  flex-shrink: 0;
265
- .text-secondary {
266
- margin: 0.5rem !important;
267
- }
268
- .saooti-star-bounty {
269
- font-size: 22px;
270
- }
271
-
272
- .title-podcast-item {
273
- font-weight: 700;
274
- margin: 0.25rem 0.5rem 0.5rem;
275
- overflow: hidden;
276
- display: -webkit-box;
277
- flex-grow: 1;
278
- font-size: 0.7rem;
279
- -webkit-line-clamp: 3;
280
- -webkit-box-orient: vertical;
281
- min-height: 3rem;
282
- line-height: 1rem;
283
- word-break: break-word;
284
- }
132
+
285
133
  .description-podcast-item {
286
134
  padding: 1rem;
287
135
  color: #333;
@@ -306,12 +154,6 @@ export default defineComponent({
306
154
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 40%);
307
155
  }
308
156
  }
309
- .producer-podcast-item {
310
- margin: 0.2rem 0.5rem 0.5rem;
311
- font-size: 0.55rem;
312
- color: #666;
313
- }
314
-
315
157
  @media (max-width: 960px) {
316
158
  margin: 0.5rem !important;
317
159
  }
@@ -0,0 +1,170 @@
1
+ <template>
2
+ <div class="d-contents podcast-item-info">
3
+ <div class="d-flex justify-content-between flex-wrap text-secondary mb-3">
4
+ <div class="me-3 small-text">
5
+ {{ date }}
6
+ </div>
7
+ <div
8
+ v-if="0 !== durationString.length"
9
+ class="small-text"
10
+ >
11
+ {{ durationString }}
12
+ </div>
13
+ </div>
14
+ <AnimatorsItem :animators="animators" />
15
+ <router-link
16
+ :to="{
17
+ name: 'podcast',
18
+ params: { podcastId: podcastId },
19
+ query: { productor: $store.state.filter.organisationId },
20
+ }"
21
+ class="text-dark d-flex flex-column flex-grow-1"
22
+ >
23
+ <div class="title-podcast-item">
24
+ {{ title }}
25
+ </div>
26
+ </router-link>
27
+ <PodcastPlayBar
28
+ :podcast-id="podcastId"
29
+ :duration="duration"
30
+ class="mx-2"
31
+ />
32
+ <div class="d-flex justify-content-between">
33
+ <router-link
34
+ v-if="!isPodcastmaker"
35
+ :to="{
36
+ name: 'productor',
37
+ params: { productorId: podcastOrganisationId },
38
+ query: { productor: $store.state.filter.organisationId },
39
+ }"
40
+ class="text-dark producer-podcast-item"
41
+ >
42
+ <div>{{ '© ' + podcastOrganisationName }}</div>
43
+ </router-link>
44
+ <span
45
+ v-if="editRight && podcastOrder && podcastOrder > 1"
46
+ class="saooti-star-bounty text-danger pe-2"
47
+ />
48
+ </div>
49
+ </div>
50
+ </template>
51
+
52
+ <script lang="ts">
53
+ import AnimatorsItem from './AnimatorsItem.vue';
54
+ import { state } from '../../../store/paramStore';
55
+ import moment from 'moment';
56
+ // @ts-ignore
57
+ import humanizeDuration from 'humanize-duration';
58
+ import PodcastPlayBar from './PodcastPlayBar.vue';
59
+ import { defineComponent } from 'vue'
60
+ import { Participant } from '@/store/class/general/participant';
61
+ export default defineComponent({
62
+ name: 'PodcastItemInfo',
63
+
64
+ components: {
65
+ AnimatorsItem,
66
+ PodcastPlayBar
67
+ },
68
+
69
+ props: {
70
+ podcastId: { default: undefined, type: Number},
71
+ title: { default: "", type: String},
72
+ pubDate: { default: "", type: String},
73
+ podcastOrganisationId: { default: "", type: String},
74
+ podcastOrganisationName: { default: "", type: String},
75
+ podcastOrder: { default: undefined, type: Number},
76
+ duration: { default: 0, type: Number},
77
+ animators: { default: undefined, type: Object as ()=> Array<Participant>},
78
+ },
79
+
80
+ computed: {
81
+ isPodcastmaker(): boolean {
82
+ return (state.generalParameters.podcastmaker as boolean);
83
+ },
84
+ date(): string {
85
+ return moment(this.pubDate).format('D MMMM YYYY, HH[h]mm');
86
+ },
87
+ organisationId(): string|undefined {
88
+ return state.generalParameters.organisationId;
89
+ },
90
+ authenticated(): boolean {
91
+ return (state.generalParameters.authenticated as boolean);
92
+ },
93
+ editRight(): boolean {
94
+ if (
95
+ (this.authenticated &&
96
+ this.organisationId === this.podcastOrganisationId) ||
97
+ state.generalParameters.isAdmin
98
+ )
99
+ return true;
100
+ return false;
101
+ },
102
+ durationString(): string {
103
+ if (this.duration <= 1) return '';
104
+ if (this.duration > 600000) {
105
+ return humanizeDuration(this.duration, {
106
+ language: 'short',
107
+ largest: 1,
108
+ round: true,
109
+ languages: {
110
+ short: {
111
+ y: () => 'years',
112
+ mo: () => 'months',
113
+ w: () => 'weeks',
114
+ d: () => 'days',
115
+ h: () => 'h',
116
+ m: () => 'min',
117
+ s: () => 'sec',
118
+ ms: () => 'ms',
119
+ },
120
+ },
121
+ });
122
+ }
123
+ return humanizeDuration(this.duration, {
124
+ language: 'short',
125
+ largest: 2,
126
+ round: true,
127
+ languages: {
128
+ short: {
129
+ m: () => 'min',
130
+ s: () => 'sec',
131
+ ms: () => 'ms',
132
+ },
133
+ },
134
+ });
135
+ },
136
+ },
137
+ })
138
+ </script>
139
+
140
+ <style lang="scss">
141
+ .octopus-app{
142
+ .podcast-item-info {
143
+ .text-secondary {
144
+ margin: 0.5rem !important;
145
+ }
146
+ .saooti-star-bounty {
147
+ font-size: 22px;
148
+ }
149
+ .title-podcast-item {
150
+ font-weight: 700;
151
+ margin: 0.25rem 0.5rem 0.5rem;
152
+ overflow: hidden;
153
+ display: -webkit-box;
154
+ flex-grow: 1;
155
+ font-size: 0.7rem;
156
+ -webkit-line-clamp: 3;
157
+ -webkit-box-orient: vertical;
158
+ min-height: 3rem;
159
+ line-height: 1rem;
160
+ word-break: break-word;
161
+ }
162
+
163
+ .producer-podcast-item {
164
+ margin: 0.2rem 0.5rem 0.5rem;
165
+ font-size: 0.55rem;
166
+ color: #666;
167
+ }
168
+ }
169
+ }
170
+ </style>
@@ -4,38 +4,39 @@
4
4
  :loading-text="loading?$t('Loading podcasts ...'):undefined"
5
5
  :error-text="loaded && !podcasts.length?$t(`No podcast match your query`):undefined"
6
6
  />
7
- <div
8
- v-if="showCount && loaded && podcasts.length > 1"
9
- class="text-secondary mb-2"
10
- >
11
- {{ $t('Number podcasts', { nb: totalCount }) + sortText }}
12
- </div>
13
- <ul
14
- v-show="loaded"
15
- class="podcast-list"
16
- >
17
- <PodcastItem
18
- v-for="p in podcasts"
19
- :key="p.podcastId"
20
- :podcast="p"
21
- />
22
- </ul>
23
- <button
24
- v-show="!allFetched && loaded"
25
- class="btn"
26
- :class="buttonPlus ? 'btn-link align-self-center width-fit-content m-4' : 'btn-more'"
27
- :disabled="inFetching"
28
- :title="$t('See more')"
29
- @click="displayMore"
30
- >
31
- <template v-if="buttonPlus">
32
- {{ $t('See more') }}
33
- </template>
7
+ <template v-if="loaded">
34
8
  <div
35
- :class="buttonPlus?'ms-1':''"
36
- class="saooti-more"
37
- />
38
- </button>
9
+ v-if="showCount && podcasts.length > 1"
10
+ class="text-secondary mb-2"
11
+ >
12
+ {{ $t('Number podcasts', { nb: totalCount }) + sortText }}
13
+ </div>
14
+ <ul
15
+ class="podcast-list"
16
+ >
17
+ <PodcastItem
18
+ v-for="p in podcasts"
19
+ :key="p.podcastId"
20
+ :podcast="p"
21
+ />
22
+ </ul>
23
+ <button
24
+ v-show="!allFetched"
25
+ class="btn"
26
+ :class="buttonPlus ? 'btn-link align-self-center width-fit-content m-4' : 'btn-more'"
27
+ :disabled="inFetching"
28
+ :title="$t('See more')"
29
+ @click="displayMore"
30
+ >
31
+ <template v-if="buttonPlus">
32
+ {{ $t('See more') }}
33
+ </template>
34
+ <div
35
+ :class="buttonPlus?'ms-1':''"
36
+ class="saooti-more"
37
+ />
38
+ </button>
39
+ </template>
39
40
  </div>
40
41
  </template>
41
42
 
@@ -93,7 +94,7 @@ export default defineComponent({
93
94
  inFetching: false as boolean,
94
95
  };
95
96
  },
96
-
97
+
97
98
  computed: {
98
99
  allFetched(): boolean {
99
100
  return this.dfirst >= this.totalCount;
@@ -144,8 +145,8 @@ export default defineComponent({
144
145
  },
145
146
  },
146
147
 
147
- created() {
148
- this.fetchContent(true);
148
+ async created() {
149
+ await this.fetchContent(true);
149
150
  },
150
151
  methods: {
151
152
  async fetchContent(reset: boolean): Promise<void> {
@@ -32,7 +32,6 @@
32
32
  </template>
33
33
 
34
34
  <script lang="ts">
35
- import { Podcast } from '@/store/class/general/podcast';
36
35
  import DurationHelper from '../../../helper/duration';
37
36
  import { displayMethods } from '../../mixins/functions';
38
37
  import { state } from '../../../store/paramStore';
@@ -41,21 +40,22 @@ export default defineComponent({
41
40
  name: 'PodcastPlayBar',
42
41
  mixins: [displayMethods],
43
42
  props: {
44
- podcast: { default: ()=>({}), type: Object as ()=>Podcast },
43
+ podcastId: { default: undefined, type: Number},
44
+ duration: { default: 0, type: Number},
45
45
  },
46
46
  computed: {
47
47
  isProgressBar(): boolean{
48
48
  return (state.emissionsPage.progressBar as boolean);
49
49
  },
50
50
  percentProgress(): number{
51
- if(!this.$store.state.player.podcast || this.podcast.podcastId !== this.$store.state.player.podcast.podcastId){
51
+ if(!this.$store.state.player.podcast || this.podcastId !== this.$store.state.player.podcast.podcastId){
52
52
  return 0;
53
53
  }
54
54
  if(!this.$store.state.player.elapsed){return 0;}
55
55
  return this.$store.state.player.elapsed * 100;
56
56
  },
57
57
  playedTime(): string{
58
- if(this.$store.state.player.podcast && this.podcast.podcastId === this.$store.state.player.podcast.podcastId){
58
+ if(this.$store.state.player.podcast && this.podcastId === this.$store.state.player.podcast.podcastId){
59
59
  if (this.$store.state.player.elapsed && this.$store.state.player.elapsed > 0 && this.$store.state.player.total && this.$store.state.player.total > 0) {
60
60
  return DurationHelper.formatDuration(
61
61
  Math.round(this.$store.state.player.elapsed * this.$store.state.player.total)
@@ -65,12 +65,12 @@ export default defineComponent({
65
65
  return '00:00';
66
66
  },
67
67
  totalTime(): string {
68
- return DurationHelper.formatDuration(Math.round(this.podcast.duration/1000));
68
+ return DurationHelper.formatDuration(Math.round(this.duration/1000));
69
69
  },
70
70
  },
71
71
  methods: {
72
72
  seekTo(event: MouseEvent): void {
73
- if(!this.$store.state.player.podcast || this.podcast.podcastId !== this.$store.state.player.podcast.podcastId){return;}
73
+ if(!this.$store.state.player.podcast || this.podcastId !== this.$store.state.player.podcast.podcastId){return;}
74
74
  const rect = (event.currentTarget as Element).getBoundingClientRect();
75
75
  const barWidth = (event.currentTarget as Element).clientWidth;
76
76
  const x = event.clientX - rect.left;
@@ -99,7 +99,7 @@ export default defineComponent({
99
99
  }
100
100
  this.customPlayers = this.customPlayers.concat(playersContent);
101
101
  if(trySelect && this.customPlayers[0] && this.customPlayers[0].selected){
102
- this.$emit('update:iFrameModel',this.customPlayers[0].customId);
102
+ this.$emit('update:iFrameModel',this.customPlayers[0].customId.toString());
103
103
  return false;
104
104
  }
105
105
  return true;
@@ -4,7 +4,7 @@
4
4
  :to="podcastShareUrl"
5
5
  >
6
6
  <img
7
- :src="podcastImage"
7
+ v-lazy="podcastImage"
8
8
  :alt="$t('Podcast image')"
9
9
  class="player-image"
10
10
  >
@@ -5,7 +5,7 @@ export const handle403 = defineComponent({
5
5
  handle403(error: AxiosError): void {
6
6
  if (403 === error.response?.status) {
7
7
  if(!this.$store.state.authentication.isAuthenticated){
8
- this.$router.push("/sso/login");
8
+ window.location.href = window.location.origin + "/sso/login";
9
9
  }else{
10
10
  this.$router.push({
11
11
  path: '/main/pub/error'
@@ -1,24 +1,31 @@
1
1
 
2
+ import { handle403 } from '../mixins/handle403';
2
3
  import { Rubriquage } from "@/store/class/rubrique/rubriquage";
3
4
  import octopusApi from '@saooti/octopus-api';
4
5
  import { defineComponent } from 'vue'
6
+ import { AxiosError } from 'axios';
5
7
  export const orgaFilter = defineComponent({
8
+ mixins: [handle403],
6
9
  methods: {
7
10
  async selectOrganisation(organisationId: string): Promise<void> {
8
- const response = await octopusApi.fetchOrganisation(organisationId);
9
- const data = await octopusApi.fetchTopics(organisationId, {
10
- sort:'HOMEPAGEORDER',
11
- homePageOrder: true
12
- });
13
- const isLive = await octopusApi.liveEnabledOrganisation(organisationId);
14
- this.$store.commit('filterOrga', {
15
- orgaId: organisationId,
16
- imgUrl: response.imageUrl,
17
- rubriquageArray: data.filter((element: Rubriquage)=>{
18
- return element.rubriques.length;
19
- }),
20
- isLive: isLive
21
- });
11
+ try {
12
+ const response = await octopusApi.fetchOrganisation(organisationId);
13
+ const data = await octopusApi.fetchTopics(organisationId, {
14
+ sort:'HOMEPAGEORDER',
15
+ homePageOrder: true
16
+ });
17
+ const isLive = await octopusApi.liveEnabledOrganisation(organisationId);
18
+ this.$store.commit('filterOrga', {
19
+ orgaId: organisationId,
20
+ imgUrl: response.imageUrl,
21
+ rubriquageArray: data.filter((element: Rubriquage)=>{
22
+ return element.rubriques.length;
23
+ }),
24
+ isLive: isLive
25
+ });
26
+ } catch (error) {
27
+ this.handle403((error as AxiosError));
28
+ }
22
29
  },
23
30
  },
24
31
  });
@@ -26,7 +26,7 @@
26
26
  <div class="mb-5 mt-3 descriptionText">
27
27
  <img
28
28
  v-if="!isOuestFrance"
29
- :src="imageUrl"
29
+ v-lazy="imageUrl"
30
30
  :alt="$t('Emission name image', { name: name })"
31
31
  class="img-box shadow-element float-start me-3 mb-3"
32
32
  >
@@ -14,12 +14,10 @@
14
14
  <div
15
15
  class="d-flex flex-column align-items-center mb-3"
16
16
  >
17
- <div
17
+ <img
18
+ v-lazy="participant.imageUrl"
18
19
  class="img-box-circle mb-3"
19
- :style="{
20
- 'background-image': 'url(\'' + participant.imageUrl + '\')',
21
- }"
22
- />
20
+ >
23
21
  <h2 class="text-capitalize">
24
22
  {{ name }}
25
23
  </h2>
@@ -15,7 +15,7 @@
15
15
  <h2>{{ name }}</h2>
16
16
  <div class="mb-5 mt-3 descriptionText">
17
17
  <img
18
- :src="imageUrl"
18
+ v-lazy="imageUrl"
19
19
  :alt="$t('Playlist name image', { name: name })"
20
20
  class="img-box shadow-element float-start me-3 mb-3"
21
21
  >
package/src/locale/de.ts CHANGED
@@ -41,7 +41,7 @@ export default{
41
41
  Cancel: "Abbrechen",
42
42
  'Most popular': "Beliebteste",
43
43
  'Last added': "Neueste",
44
- 'All podcast button': 'Alle Podcasts von "{Name}"',
44
+ 'All podcast button': 'Alle Podcasts von "{name}"',
45
45
  'Podcast search': "Podcasts durchsuchen",
46
46
  'No podcast match your query':
47
47
  "Kein Podcast entspricht Ihrer Suchanfrage.",
@@ -70,7 +70,7 @@ export default{
70
70
  'Episode name image': "Bild zur Folge {name}",
71
71
  'More episodes of this emission': "Mehr Folgen aus dieser Reihe",
72
72
  'More episodes of this category : {name}': "Mehr Folgen aus dieser Kategorie: {name}",
73
- 'All podcast serie button': "Alle Folgen dieser Reihe",
73
+ 'All podcast emission button': "Alle Folgen dieser Reihe",
74
74
  Duration: "Dauer: {duration}",
75
75
  Animator: "Autor",
76
76
  'No category filter': "Keine Kategorie",
@@ -240,9 +240,9 @@ export default{
240
240
  'All live emission button': "Alle Live-Übertragungen der Reihe",
241
241
  'player parameters': "Player-Einstellungen",
242
242
  'Start at': "Beginnt um",
243
- 'sort by score': "Nach Relevanz",
244
- 'sort by alphabetical': "In alphabetischer Reihenfolge",
245
- 'sort by date': "Nach Datum",
243
+ 'sort by score': "nach Relevanz",
244
+ 'sort by alphabetical': "in alphabetischer Reihenfolge",
245
+ 'sort by date': "nach Datum",
246
246
  'Be the first to react': "Ersten Kommentar hinterlassen",
247
247
  "Podcast's comments": "Kommentare zum Podcast",
248
248
  '()': '({nb})',
package/src/locale/en.ts CHANGED
@@ -41,7 +41,7 @@ export default{
41
41
  Cancel: 'Cancel',
42
42
  'Most popular': 'Most popular',
43
43
  'Last added': 'Last added',
44
- 'All podcast button': 'All the podcasts of "{name}"',
44
+ 'All podcast button': 'All the podcasts from "{name}"',
45
45
  'Podcast search': 'Search in the podcasts',
46
46
  'No podcast match your query':
47
47
  'No podcast matches your query',
@@ -51,26 +51,26 @@ export default{
51
51
  'All productors': 'All producers',
52
52
  'All emissions': 'All series',
53
53
  'Filter by keyword : ': 'Filter by keyword : ',
54
- 'Look for participant name': 'Search for speaker by name',
55
- 'Look for productor name': 'Search for Producer by title',
56
- 'Look for emission name': 'Search for serie by title',
57
- 'Look for podcast name': 'Search for podcast by title',
54
+ 'Look for participant name': 'Search for a speaker by name',
55
+ 'Look for productor name': 'Search for a producer by title',
56
+ 'Look for emission name': 'Search for a series by title',
57
+ 'Look for podcast name': 'Search for a podcast by title',
58
58
  'Type string to filter by organisation': 'Filter by organization',
59
- 'Type string to filter by emission': 'Filter by serie',
59
+ 'Type string to filter by emission': 'Filter by series',
60
60
  'Type string to filter by podcast': 'Filter by podcast',
61
61
  'No organisation filter': 'No organization filter',
62
- 'No emission filter': 'No serie filter',
62
+ 'No emission filter': 'No series filter',
63
63
  'No podcast filter': 'No podcast filter',
64
64
  'Loading participants ...': 'Loading speakers...',
65
65
  'Loading productors ...': 'Loading Producers...',
66
66
  'Loading emissions ...': 'Loading series...',
67
- 'Emission name image': "Image for the serie {name}",
67
+ 'Emission name image': "Image for the series {name}",
68
68
  'Loading content ...': 'Loading content...',
69
69
  Episode: 'Episode',
70
70
  'Episode name image': "Episode {name} image",
71
- 'More episodes of this emission': "More episodes of this serie",
72
- 'More episodes of this category : {name}': "More episodes of this category : {name}",
73
- 'All podcast serie button': "All podcast serie button",
71
+ 'More episodes of this emission': "More episodes from this series",
72
+ 'More episodes of this category : {name}': "More episodes from this category : {name}",
73
+ 'All podcast emission button': "All podcast from this series",
74
74
  Duration: 'Duration : {duration}',
75
75
  Animator: 'Host',
76
76
  'No category filter': 'No category filter',
@@ -113,15 +113,15 @@ export default{
113
113
  'Search results': 'Search results for "{query}"',
114
114
  'Search - no results': 'Search - no results for "{query}"',
115
115
  Downloading: 'Downloading',
116
- 'Subscribe to this emission': "Subscribe to this serie",
116
+ 'Subscribe to this emission': "Subscribe to this series",
117
117
  'Subscribe to this participant': "Subscribe to this speakers",
118
- 'Emission have not podcasts': "This serie does not have any podcasts",
118
+ 'Emission have not podcasts': "This series does not have any podcasts",
119
119
  'Participant have not podcasts':
120
120
  'Speaker is not associated to any podcasts',
121
121
  'Default version': 'Default version',
122
122
  'Large version': 'Large version',
123
123
  'Emission version': 'Serie version',
124
- 'Large emission version': 'Large serie version',
124
+ 'Large emission version': 'Large series version',
125
125
  'Large suggestion version': 'Large suggestion version',
126
126
  'Embed link': 'Embed miniplayer',
127
127
  'Embedly link': 'Player link',
@@ -184,7 +184,7 @@ export default{
184
184
  "Share this page without edit and share blocks",
185
185
  'Podcast in cancelled status': 'Podcast has a cancelled status',
186
186
  'Show every episode': 'Show every episode',
187
- 'Subscribe emission': "Subscribe to the serie",
187
+ 'Subscribe emission': "Subscribe to the series",
188
188
  'Rss feed parameters': 'RSS Feed settings',
189
189
  'Not share episodes before':
190
190
  'Do not share episodes before',
@@ -206,7 +206,7 @@ export default{
206
206
  Configuration: 'Configuration',
207
207
  'HTML Code': 'HTML Code',
208
208
  'Listen this episode': 'Listen to this episode',
209
- 'Display emission name': "Display the serie title",
209
+ 'Display emission name': "Display the series title",
210
210
  'Display participants list': 'Display the speakers list',
211
211
  'Choose main color': 'Choose the main color',
212
212
  'Octopus is ACPM Podcast accredited': 'Octopus is ACPM accredited',
@@ -237,7 +237,7 @@ export default{
237
237
  'Podcasts in the playlist': 'All the Podcasts in the playlist',
238
238
  'No podcasts in the playlist': "No podcasts in the playlist",
239
239
  'Start in a while': 'Starts any minute',
240
- 'All live emission button': "All lives in the serie",
240
+ 'All live emission button': "All lives in the series",
241
241
  'player parameters': 'Setting of player',
242
242
  'Start at': 'Start at',
243
243
  'sort by score': 'by relevancy score',
package/src/locale/es.ts CHANGED
@@ -70,7 +70,7 @@ export default{
70
70
  'Episode name image': "Imagen del episodio {name}",
71
71
  'More episodes of this emission': "Más episodios de este programa",
72
72
  'More episodes of this category : {name}': "Más episodios de esta categoría: {name}",
73
- 'All podcast serie button': "Todos los episodios del programa",
73
+ 'All podcast emission button': "Todos los episodios del programa",
74
74
  Duration: 'Duración: {duration}',
75
75
  Animator: 'Presentador/a',
76
76
  'No category filter': 'Sin filtro de categoría',
package/src/locale/sl.ts CHANGED
@@ -70,7 +70,7 @@ export default{
70
70
  'Episode name image': "Slika epizode {name}",
71
71
  'More episodes of this emission': "Več oddaj iz tega niza",
72
72
  'More episodes of this category : ': 'Več oddaj iz te kategorije", {name}',
73
- 'All podcast emission buttonn': "Vsi podkasti iz tega sklopa",
73
+ 'All podcast emission button': "Vsi podkasti iz tega sklopa",
74
74
  Duration: 'Trajanje: {duration}',
75
75
  Animator: 'Napovedovalec',
76
76
  'No category filter': 'Brez filtra za kategorijo',
package/src/main.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createApp } from 'vue';
2
2
  import { VueReCaptcha } from 'vue-recaptcha-v3';
3
+ import VueLazyLoad from 'vue3-lazyload';
3
4
  import App from './App.vue';
4
5
  import { createI18n, VueMessageType } from 'vue-i18n';
5
6
  import I18nResources from './locale/messages';
@@ -66,5 +67,6 @@ createApp(App)
66
67
  .use(i18n)
67
68
  .use(store)
68
69
  .use(router)
70
+ .use(VueLazyLoad)
69
71
  .use(VueReCaptcha, { siteKey: '6LfyP_4ZAAAAAPODj8nov2LvosIwcX0GYeBSungh' })
70
72
  .mount('#app');
@@ -12,7 +12,7 @@ const state:paramStore = {
12
12
  isPlaylist: false,
13
13
  isProduction: true,
14
14
  isContribution: true,
15
- ApiUri: 'https://api.staging.saooti.org/',
15
+ ApiUri: 'https://api.dev2.saooti.org/',
16
16
  podcastmaker: false,
17
17
  buttonPlus: true,
18
18
  allCategories: [],
@@ -26,10 +26,10 @@ const state:paramStore = {
26
26
  SharePlayer: true,
27
27
  ShareButtons: true,
28
28
  ShareDistribution: true,
29
- MiniplayerUri: 'https://playerbeta.staging.saooti.org/',
29
+ MiniplayerUri: 'https://playerbeta.dev2.saooti.org/',
30
30
  ouestFranceStyle: false,
31
31
  downloadButton: false,
32
- hlsUri: 'https://hls.staging.saooti.org/',
32
+ hlsUri: 'https://hls.dev2.saooti.org/',
33
33
  mainRubrique: 0,
34
34
  resourceUrl: undefined
35
35
  },
@@ -85,10 +85,10 @@ const state:paramStore = {
85
85
  userName: '',
86
86
  },
87
87
  octopusApi: {
88
- url: 'http://api.staging.saooti.org/',
89
- commentsUrl: 'http://comments.staging.saooti.org/',
90
- studioUrl: 'http://studio.staging.saooti.org/',
91
- playerUrl: 'https://playerbeta.staging.saooti.org/',
88
+ url: 'http://api.dev2.saooti.org/',
89
+ commentsUrl: 'http://comments.dev2.saooti.org/',
90
+ studioUrl: 'http://studio.dev2.saooti.org/',
91
+ playerUrl: 'https://playerbeta.dev2.saooti.org/',
92
92
  organisationId: undefined,
93
93
  rubriqueIdFilter: undefined,
94
94
  },