@saooti/octopus-sdk 40.1.21 → 40.2.0

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 (43) hide show
  1. package/index.ts +8 -1
  2. package/package.json +1 -1
  3. package/plateform.conf +1 -1
  4. package/src/components/composable/player/usePlayerLive.ts +1 -1
  5. package/src/components/display/accessibility/AccessibilityModal.vue +7 -7
  6. package/src/components/display/comments/CommentSection.vue +1 -1
  7. package/src/components/display/emission/EmissionPlayerItem.vue +1 -1
  8. package/src/components/display/list/SwiperList.vue +1 -1
  9. package/src/components/display/live/LiveList.vue +1 -1
  10. package/src/components/display/live/RadioList.vue +1 -1
  11. package/src/components/display/podcasts/PodcastImage.vue +17 -9
  12. package/src/components/display/podcasts/PodcastItemInfo.vue +1 -1
  13. package/src/components/display/podcasts/PodcastModuleBox.vue +121 -118
  14. package/src/components/display/podcasts/PodcastRawTranscript.vue +5 -18
  15. package/src/components/display/sharing/PlayerAnonymousModal.vue +54 -0
  16. package/src/components/display/sharing/QrCode.vue +36 -35
  17. package/src/components/display/sharing/ShareAnonymous.vue +290 -0
  18. package/src/components/display/sharing/ShareDistribution.vue +8 -27
  19. package/src/components/display/sharing/ShareNewsletter.vue +205 -0
  20. package/src/components/display/sharing/ShareSocialsButtons.vue +110 -0
  21. package/src/components/display/sharing/SubscribeButtons.vue +2 -0
  22. package/src/components/form/ClassicCopyButton.vue +65 -0
  23. package/src/components/misc/ClassicNav.vue +9 -4
  24. package/src/components/misc/ClassicPopover.vue +1 -1
  25. package/src/components/misc/modal/ClipboardModal.vue +9 -11
  26. package/src/components/misc/modal/NewsletterModal.vue +14 -192
  27. package/src/components/misc/modal/QrCodeModal.vue +2 -1
  28. package/src/components/pages/EmissionPage.vue +47 -61
  29. package/src/components/pages/ParticipantPage.vue +17 -7
  30. package/src/components/pages/PlaylistPage.vue +13 -9
  31. package/src/components/pages/PodcastPage.vue +15 -38
  32. package/src/components/pages/RadioPage.vue +12 -7
  33. package/src/components/pages/VideoPage.vue +0 -3
  34. package/src/locale/de.ts +5 -2
  35. package/src/locale/en.ts +5 -2
  36. package/src/locale/es.ts +5 -2
  37. package/src/locale/fr.ts +9 -6
  38. package/src/locale/it.ts +5 -2
  39. package/src/locale/sl.ts +5 -2
  40. package/src/router/router.ts +3 -8
  41. package/src/stores/class/config/commentsConfig.ts +2 -2
  42. package/src/style/bootstrap.scss +6 -14
  43. package/src/components/display/sharing/ShareButtons.vue +0 -351
@@ -0,0 +1,205 @@
1
+ <template>
2
+ <div class="d-flex flex-column align-items-center">
3
+ <div class="d-flex flex-grow-1">
4
+ <div class="d-flex flex-column flex-shrink-0 me-3">
5
+ <h2 class="mb-3">
6
+ {{ $t("Configure your Newsletter tile") }}
7
+ </h2>
8
+ <div
9
+ v-for="colors in arrayColors"
10
+ :key="colors.mainText"
11
+ class="d-flex align-items-center mb-3"
12
+ >
13
+ <VSwatches
14
+ v-model="colors.color"
15
+ class="c-hand me-2"
16
+ show-fallback
17
+ fallback-input-type="color"
18
+ colors="text-advanced"
19
+ popover-to="right"
20
+ :data-color="colors.color"
21
+ />
22
+ <div class="d-flex flex-column">
23
+ <div class="fw-bold">{{ colors.mainText }}</div>
24
+ <div v-if="colors.secondText" class="description-text">
25
+ {{ colors.secondText }}
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <!-- eslint-disable vue/no-v-html -->
31
+ <div class="border p-3" v-html="newsletterHtml" />
32
+ <!-- eslint-enable -->
33
+ </div>
34
+ <ClassicCopyButton
35
+ :text="$t('Copy code')"
36
+ :text-after-copy="$t('Code copied!')"
37
+ :data-to-copy="newsletterHtml"
38
+ />
39
+ <div>{{ $t("And paste it in your newsletter") }}</div>
40
+ </div>
41
+ </template>
42
+
43
+ <script lang="ts">
44
+ import ClassicCopyButton from "../../form/ClassicCopyButton.vue";
45
+ import { VSwatches } from "vue3-swatches";
46
+ import "vue3-swatches/dist/style.css";
47
+ import { Podcast } from "@/stores/class/general/podcast";
48
+ import { defineComponent } from "vue";
49
+ import { useSaveFetchStore } from "../../../stores/SaveFetchStore";
50
+ import { useAuthStore } from "../../../stores/AuthStore";
51
+ import { mapState, mapActions } from "pinia";
52
+ import { Emission } from "@/stores/class/general/emission";
53
+ import { Playlist } from "@/stores/class/general/playlist";
54
+ export default defineComponent({
55
+ name: "SahreNewsletter",
56
+
57
+ components: {
58
+ ClassicCopyButton,
59
+ VSwatches,
60
+ },
61
+
62
+ props: {
63
+ podcast: { default: undefined, type: Object as () => Podcast },
64
+ emission: { default: undefined, type: Object as () => Emission },
65
+ playlist: { default: undefined, type: Object as () => Playlist },
66
+ },
67
+
68
+ emits: ["close"],
69
+
70
+ data() {
71
+ return {
72
+ arrayColors: [
73
+ {
74
+ color: "#40a372",
75
+ mainText: this.$t("Choose main color"),
76
+ secondText: this.$t("Newsletter elements"),
77
+ },
78
+ { color: "#000000", mainText: this.$t("Choose text color") },
79
+ { color: "#FFFFFF", mainText: this.$t("Choose background color") },
80
+ ],
81
+ shareUrl: window.location.href,
82
+ };
83
+ },
84
+ computed: {
85
+ ...mapState(useAuthStore, ["authOrgaId"]),
86
+ newsletterInfo() {
87
+ if (this.podcast) {
88
+ return {
89
+ imageUrl: `${this.podcast.imageUrl}" alt="${this.$t(
90
+ "Episode name image",
91
+ { name: this.podcast.title },
92
+ )}`,
93
+ title: this.podcast.title,
94
+ description: this.podcast.description ?? "",
95
+ shareText: this.$t("Listen this episode"),
96
+ emissionHtml: `<tr><td style="padding:5px 0;">
97
+ <div style="display:flex; margin-top:5px;">
98
+ <div style="font-size:16px; color:${
99
+ this.arrayColors[1].color
100
+ }; margin-right:5px;text-wrap: nowrap;">${this.$t("Emission")} :</div>
101
+ <a href="${this.shareUrl}" style="font-size: 16px;color: ${
102
+ this.arrayColors[0].color
103
+ };overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">${
104
+ this.podcast.emission.name
105
+ }</a>
106
+ </div></td></tr>`,
107
+ articleHtml:
108
+ !this.podcast?.article || 0 === this.podcast.article?.length
109
+ ? ``
110
+ : `<tr><td style="padding:5px 0;">
111
+ <div style="display:flex;">
112
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M7 17h7v-2H7zm0-4h10v-2H7zm0-4h10V7H7zM5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h14q.825 0 1.413.588T21 5v14q0 .825-.587 1.413T19 21zm0-2h14V5H5zM5 5v14z"/></svg>
113
+ <a href="${this.podcast.article}" style="color: ${
114
+ this.arrayColors[1].color
115
+ };margin-top:2px">${this.$t("See associated article")}</a>
116
+ </div></td></tr>
117
+ `,
118
+ colorTitle: `color:${this.arrayColors[1].color};`,
119
+ };
120
+ }
121
+ if (this.emission) {
122
+ return {
123
+ imageUrl: `${this.emission.imageUrl}" alt="${this.$t(
124
+ "Emission image",
125
+ )}`,
126
+ title: this.emission.name,
127
+ description: this.emission.description ?? "",
128
+ shareText: this.$t("Listen to all episodes"),
129
+ emissionHtml: ``,
130
+ articleHtml: ``,
131
+ colorTitle: `color:${this.arrayColors[0].color};`,
132
+ };
133
+ }
134
+ return {
135
+ imageUrl: `${this.playlist?.imageUrl}" alt="${this.$t(
136
+ "Playlist image",
137
+ )}`,
138
+ title: this.playlist?.title,
139
+ description: this.playlist?.description ?? "",
140
+ shareText: this.$t("Listen to all episodes"),
141
+ emissionHtml: ``,
142
+ articleHtml: ``,
143
+ colorTitle: `color:${this.arrayColors[0].color};`,
144
+ };
145
+ },
146
+ newsletterHtml(): string {
147
+ return `<table style="background:${this.arrayColors[2].color};color:${
148
+ this.arrayColors[1].color
149
+ };table-layout: fixed;width:100%;font-size: 14px;">
150
+ <tr>
151
+ <td valign="top" width="30%" rowspan="7" style="padding-right:5px;"><img width="100%" src="${
152
+ this.newsletterInfo.imageUrl
153
+ }" style="border-radius: 4px;"></td>
154
+ <td valign="top" width="70%" style="padding:5px 0;"><div style="margin-top:5px;font-size: 20px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;font-weight:bold;${
155
+ this.newsletterInfo.colorTitle
156
+ }">${this.newsletterInfo.title}</div></td>
157
+ </tr>${this.newsletterInfo.emissionHtml}
158
+ <tr><td style="padding:5px 0;"><div style="overflow: hidden;display: -webkit-box;-webkit-line-clamp: 6;-webkit-box-orient: vertical;word-break: break-word;">${
159
+ this.newsletterInfo.description
160
+ }</div></td></tr>
161
+ <tr><td valign="top" style="padding:5px 0;"><a href="${
162
+ this.shareUrl
163
+ }" style="color: ${this.arrayColors[0].color};">${this.$t(
164
+ "See more",
165
+ )}</a></td></tr>
166
+ <tr>${this.newsletterInfo.articleHtml}
167
+ <td width="1" style="padding:5px 0;"><a href="${
168
+ this.shareUrl
169
+ }" style="font-size: 18px;color: ${
170
+ this.arrayColors[0].color
171
+ };text-decoration: none; display:flex;"><svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 24 24"><path fill="currentColor" d="m9.5 16.5l7-4.5l-7-4.5zM12 22q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22"/></svg><div style="margin-top: 15px; color:${
172
+ this.arrayColors[1].color
173
+ };">${this.newsletterInfo.shareText}</div></a></td>
174
+ </tr>
175
+ </table>
176
+ `;
177
+ },
178
+ },
179
+ created() {
180
+ this.initData();
181
+ },
182
+ methods: {
183
+ ...mapActions(useSaveFetchStore, ["getOrgaAttributes"]),
184
+ async initData(): Promise<void> {
185
+ const orgaId = this.authOrgaId;
186
+ if (!orgaId?.length) {
187
+ return;
188
+ }
189
+ const attributes = await this.getOrgaAttributes(orgaId ?? "");
190
+ if (
191
+ Object.hasOwn(attributes, "podcastmakerUrl") &&
192
+ (attributes.podcastmakerUrl as string | undefined | null)?.length
193
+ ) {
194
+ this.shareUrl =
195
+ attributes.podcastmakerUrl +
196
+ window.location.pathname +
197
+ window.location.search;
198
+ }
199
+ if (Object.hasOwn(attributes, "COLOR")) {
200
+ this.arrayColors[0].color = attributes.COLOR as string;
201
+ }
202
+ },
203
+ },
204
+ });
205
+ </script>
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <section v-if="!isLoading && !isGarRole && (authOrgaId || !noSharing)" id="share-buttons-podcast-section" class="module-box">
3
+ <h3 class="mb-2">
4
+ {{ $t("Share in one click") }}
5
+ </h3>
6
+ <div class="d-flex align-items-center">
7
+ <template v-for="button in arrayShareButtons" :key="button.title">
8
+ <a
9
+ v-if="button.condition"
10
+ rel="noreferrer noopener"
11
+ target="_blank"
12
+ :href="button.url"
13
+ class="btn share-btn mb-2 text-dark me-2"
14
+ :title="$t('New window', {text: button.title})"
15
+ >
16
+ <component :is="button.icon" :size="34" />
17
+ </a>
18
+ </template>
19
+ <slot name="additional-buttons"/>
20
+ </div>
21
+ </section>
22
+ </template>
23
+
24
+ <script lang="ts">
25
+ import XIcon from "../../icons/XIcon.vue";
26
+ import BlueSkyIcon from "../../icons/BlueSkyIcon.vue";
27
+ import WhatsappIcon from "vue-material-design-icons/Whatsapp.vue";
28
+ import LinkedinIcon from "vue-material-design-icons/Linkedin.vue";
29
+ import FacebookIcon from "vue-material-design-icons/Facebook.vue";
30
+ import { useSaveFetchStore } from "../../../stores/SaveFetchStore";
31
+ import { mapActions, mapState } from "pinia";
32
+ import { useAuthStore } from "../../../stores/AuthStore";
33
+ import { defineComponent } from "vue";
34
+
35
+ export default defineComponent({
36
+ components: {
37
+ FacebookIcon,
38
+ LinkedinIcon,
39
+ WhatsappIcon,
40
+ XIcon,
41
+ BlueSkyIcon
42
+ },
43
+ props: {
44
+ organisationId: { default: undefined, type: String },
45
+ },
46
+ data() {
47
+ return {
48
+ noSharing: true as boolean,
49
+ isLoading: true as boolean,
50
+ };
51
+ },
52
+ computed: {
53
+ ...mapState(useAuthStore, [
54
+ "isGarRole",
55
+ "authOrgaId"
56
+ ]),
57
+ arrayShareButtons() {
58
+ return [
59
+ {
60
+ title: "Facebook",
61
+ icon: "FacebookIcon",
62
+ url: `https://www.facebook.com/sharer/sharer.php?u=${this.urlPage}`,
63
+ condition: true,
64
+ },
65
+ {
66
+ title: "X",
67
+ icon: "XIcon",
68
+ url: `https://twitter.com/intent/tweet?text=${this.urlPage}`,
69
+ condition: true,
70
+ },
71
+ {
72
+ title: "Linkedin",
73
+ icon: "LinkedinIcon",
74
+ url: `https://www.linkedin.com/sharing/share-offsite/?url=${this.urlPage}`,
75
+ condition: true,
76
+ },
77
+ {
78
+ title: "Bluesky",
79
+ icon: "BlueSkyIcon",
80
+ url: `https://bsky.app/intent/compose?text=${this.urlPage}`,
81
+ condition: true,
82
+ },
83
+ {
84
+ title: "Whatsapp",
85
+ icon: "WhatsappIcon",
86
+ url: `whatsapp://send?text=${this.urlPage}`,
87
+ condition: window.matchMedia("(hover: none)").matches,
88
+ },
89
+ ];
90
+ },
91
+ urlPage(): string {
92
+ return window.location.href;
93
+ },
94
+ },
95
+ created() {
96
+ this.initShareButtons();
97
+ },
98
+ methods: {
99
+ ...mapActions(useSaveFetchStore, ["getOrgaAttributes"]),
100
+ async initShareButtons() {
101
+ if (!this.organisationId) {
102
+ return;
103
+ }
104
+ const attributes = await this.getOrgaAttributes(this.organisationId);
105
+ this.noSharing = "true" === attributes.noSharing;
106
+ this.isLoading = false;
107
+ },
108
+ },
109
+ });
110
+ </script>
@@ -116,6 +116,8 @@ export default defineComponent({
116
116
  return {
117
117
  hiddenLinks: [] as Array<Link>,
118
118
  lastWindowWidth: 420 as number,
119
+ exclusive: false as boolean,
120
+ notExclusive: false as boolean,
119
121
  };
120
122
  },
121
123
  computed: {
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <div>
3
+ <button
4
+ :class="classBtn"
5
+ @click="onCopyCode(afterCopy)"
6
+ >
7
+ {{ textDisplayed }}
8
+ </button>
9
+ <SnackBar
10
+ v-if="lazyLoadingSnackbar"
11
+ ref="snackbar"
12
+ position="bottom-left"
13
+ />
14
+ </div>
15
+ </template>
16
+
17
+ <script lang="ts">
18
+ import SnackBar from "../misc/SnackBar.vue";
19
+ import displayHelper from "../../helper/displayHelper";
20
+ import { defineComponent } from "vue";
21
+ export default defineComponent({
22
+ name: "ClassicCopyButton",
23
+
24
+ components: {
25
+ SnackBar,
26
+ },
27
+
28
+ props: {
29
+ text: { default: undefined, type: String },
30
+ textAfterCopy: { default: undefined, type: String },
31
+ dataToCopy: { default: undefined, type: String },
32
+ snackbarText: { default: undefined, type: String },
33
+ classBtn: { default: "btn btn-primary w-fit-content my-3", type: String },
34
+ },
35
+ data() {
36
+ return {
37
+ hasBeenCopied: false as boolean,
38
+ lazyLoadingSnackbar: false as boolean,
39
+ };
40
+ },
41
+ computed:{
42
+ textDisplayed(){
43
+ return this.hasBeenCopied ? this.textAfterCopy : this.text;
44
+ }
45
+ },
46
+ methods: {
47
+ onCopyCode(callback: () => void){
48
+ displayHelper.onCopyCode(this.dataToCopy??"", callback);
49
+ },
50
+ afterCopy(): void {
51
+ this.hasBeenCopied = true;
52
+ if (!this.lazyLoadingSnackbar) {
53
+ this.lazyLoadingSnackbar = true;
54
+ setTimeout(() => {
55
+ this.afterCopy();
56
+ }, 500);
57
+ } else {
58
+ (this.$refs.snackbar as InstanceType<typeof SnackBar>).open(
59
+ this.snackbarText ?? this.$t("Data in clipboard"),
60
+ );
61
+ }
62
+ },
63
+ },
64
+ });
65
+ </script>
@@ -89,11 +89,13 @@ export default defineComponent({
89
89
  border-bottom: solid 1px var(--octopus-border-default);
90
90
  background-color: var(--octopus-background);
91
91
  }
92
+ .octopus-nav.light .octopus-tab-content{
93
+ border-top: solid 1px var(--octopus-border-default);
94
+ }
92
95
 
93
96
 
94
97
  .octopus-nav.light .octopus-nav-item {
95
98
  border: 0;
96
- flex-grow: 0;
97
99
  }
98
100
 
99
101
  .octopus-nav-link {
@@ -122,10 +124,13 @@ export default defineComponent({
122
124
  }
123
125
 
124
126
  .octopus-nav.light .octopus-nav-link {
125
- border-top: 0 !important;
126
- border-right: 0 !important;
127
- border-left: 0 !important;
128
127
  font-weight: bold;
128
+ background:var(--octopus-border-default);
129
+ &.active{
130
+ border-bottom-color: var(--octopus-primary);
131
+ background: transparent;
132
+ color: var(--octopus-primary);
133
+ }
129
134
  }
130
135
 
131
136
 
@@ -245,7 +245,7 @@ export default defineComponent({
245
245
  return;
246
246
  }
247
247
  //Exception timepicker in popover
248
- var result = Array.from(e?.target?.classList ?? []).findIndex((val) => { return val.startsWith("dp__");});
248
+ const result = Array.from(e?.target?.classList ?? []).findIndex((val) => { return val.startsWith("dp__");});
249
249
  if (-1!==result) {
250
250
  return;
251
251
  }
@@ -8,9 +8,12 @@
8
8
  <p class="d-flex justify-content-between align-items-center">
9
9
  {{ $t("Rss feed:") }}
10
10
  <span id="LINK">{{ link }}</span>
11
- <button class="btn btn-primary" @click="onCopyCode(link, afterCopy)">
12
- {{ $t("Copy") }}
13
- </button>
11
+ <ClassicCopyButton
12
+ :text="$t('Copy')"
13
+ :text-after-copy="$t('Copied!')"
14
+ :data-to-copy="link"
15
+ :snackbar-text="$t('Link in clipboard')"
16
+ />
14
17
  </p>
15
18
  <RssSection
16
19
  v-if="emission && undefined !== authOrgaId"
@@ -21,9 +24,9 @@
21
24
  </template>
22
25
 
23
26
  <script lang="ts">
27
+ import ClassicCopyButton from "../../form/ClassicCopyButton.vue";
24
28
  import ClassicModal from "../modal/ClassicModal.vue";
25
29
  import { Emission } from "@/stores/class/general/emission";
26
- import displayHelper from "../../../helper/displayHelper";
27
30
  import { defineComponent, defineAsyncComponent } from "vue";
28
31
  import { useAuthStore } from "../../../stores/AuthStore";
29
32
  import { mapState } from "pinia";
@@ -35,25 +38,20 @@ export default defineComponent({
35
38
  components: {
36
39
  RssSection,
37
40
  ClassicModal,
41
+ ClassicCopyButton
38
42
  },
39
43
  props: {
40
44
  link: { default: "", type: String },
41
45
  emission: { default: undefined, type: Object as () => Emission },
42
46
  },
43
- emits: ["close", "copy"],
47
+ emits: ["close"],
44
48
  computed: {
45
49
  ...mapState(useAuthStore, ["authOrgaId"]),
46
50
  },
47
51
  methods: {
48
- onCopyCode(link: string, callback: () => void){
49
- displayHelper.onCopyCode(link, callback);
50
- },
51
52
  closePopup(): void {
52
53
  this.$emit("close");
53
54
  },
54
- afterCopy(): void {
55
- this.$emit("copy");
56
- },
57
55
  },
58
56
  });
59
57
  </script>